chore: remove deprecated flow_boundary and update docs to match new architecture

This commit is contained in:
Sepehr
2026-03-01 20:00:09 +01:00
parent 20700afce8
commit d88914a44f
105 changed files with 11222 additions and 2994 deletions

View File

@@ -5,7 +5,7 @@
use std::os::raw::{c_double, c_uint};
use entropyk_components::{
Component, ComponentError, ConnectedPort, JacobianBuilder, ResidualVector, SystemState,
Component, ComponentError, ConnectedPort, JacobianBuilder, ResidualVector,
};
/// Opaque handle to a component.
@@ -34,7 +34,7 @@ impl SimpleAdapter {
impl Component for SimpleAdapter {
fn compute_residuals(
&self,
_state: &SystemState,
_state: &[f64],
residuals: &mut ResidualVector,
) -> Result<(), ComponentError> {
for r in residuals.iter_mut() {
@@ -45,7 +45,7 @@ impl Component for SimpleAdapter {
fn jacobian_entries(
&self,
_state: &SystemState,
_state: &[f64],
_jacobian: &mut JacobianBuilder,
) -> Result<(), ComponentError> {
Ok(())

View File

@@ -25,7 +25,7 @@
"outputs": [],
"source": [
"import entropyk\n",
"import numpy as np"
"import numpy as np\n"
]
},
{
@@ -175,11 +175,25 @@
"except entropyk.SolverError as e:\n",
" print(\"Solver error:\", e)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "entropyk",
"language": "python",
"name": "python3"
},

View File

@@ -17,7 +17,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
@@ -39,9 +39,20 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Pression:\n",
" 1200000.00 Pa → 12.00 bar, 1200.0 kPa, 174.0 psi\n",
" 350000.00 Pa → 3.50 bar\n",
" 1034213.59 Pa → 10.34 bar\n"
]
}
],
"source": [
"# Pression - plusieurs unités supportées\n",
"p1 = entropyk.Pressure(bar=12.0)\n",
@@ -56,9 +67,20 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Température:\n",
" 318.15 K → 45.00°C, 113.00°F\n",
" 273.15 K → 0.00°C (point de congélation)\n",
" 310.93 K → 37.78°C, 310.93 K\n"
]
}
],
"source": [
"# Température\n",
"t1 = entropyk.Temperature(celsius=45.0)\n",
@@ -73,9 +95,19 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 4,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Enthalpie:\n",
" 420000.00 J/kg → 420.0 kJ/kg\n",
" 250000.00 J/kg → 250.0 kJ/kg\n"
]
}
],
"source": [
"# Enthalpie\n",
"h1 = entropyk.Enthalpy(kj_per_kg=420.0)\n",
@@ -88,9 +120,19 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Débit massique:\n",
" 0.050000 kg/s → 50.0 g/s\n",
" 0.050000 kg/s → 0.0500 kg/s\n"
]
}
],
"source": [
"# Débit massique\n",
"m1 = entropyk.MassFlow(kg_per_s=0.05)\n",
@@ -112,7 +154,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
@@ -149,9 +191,22 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 7,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cycles HFC classiques:\n",
"--------------------------------------------------\n",
" R134a → 8 variables d'état\n",
" R410A → 8 variables d'état\n",
" R407C → 8 variables d'état\n",
" R32 → 8 variables d'état\n"
]
}
],
"source": [
"# Test avec différents fluides HFC classiques\n",
"hfc_fluids = [\"R134a\", \"R410A\", \"R407C\", \"R32\"]\n",
@@ -174,9 +229,114 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 8,
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Fluide</th>\n",
" <th>Type</th>\n",
" <th>GWP</th>\n",
" <th>Usage</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>R1234yf</td>\n",
" <td>HFO</td>\n",
" <td>&lt;1</td>\n",
" <td>Remplacement R134a (automobile)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>R1234ze(E)</td>\n",
" <td>HFO</td>\n",
" <td>&lt;1</td>\n",
" <td>Remplacement R134a (stationnaire)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>R1233zd(E)</td>\n",
" <td>HCFO</td>\n",
" <td>1</td>\n",
" <td>Remplacement R123 (basse pression)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>R1243zf</td>\n",
" <td>HFO</td>\n",
" <td>&lt;1</td>\n",
" <td>Nouveau fluide recherche</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>R1336mzz(E)</td>\n",
" <td>HFO</td>\n",
" <td>&lt;1</td>\n",
" <td>ORC, haute température</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>R513A</td>\n",
" <td>Mélange</td>\n",
" <td>631</td>\n",
" <td>R134a + R1234yf (56/44)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>R454B</td>\n",
" <td>Mélange</td>\n",
" <td>146</td>\n",
" <td>R32 + R1234yf (50/50) - Opteon XL41</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>R452B</td>\n",
" <td>Mélange</td>\n",
" <td>676</td>\n",
" <td>R32 + R125 + R1234yf - Opteon XL55</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Fluide Type GWP Usage\n",
"0 R1234yf HFO <1 Remplacement R134a (automobile)\n",
"1 R1234ze(E) HFO <1 Remplacement R134a (stationnaire)\n",
"2 R1233zd(E) HCFO 1 Remplacement R123 (basse pression)\n",
"3 R1243zf HFO <1 Nouveau fluide recherche\n",
"4 R1336mzz(E) HFO <1 ORC, haute température\n",
"5 R513A Mélange 631 R134a + R1234yf (56/44)\n",
"6 R454B Mélange 146 R32 + R1234yf (50/50) - Opteon XL41\n",
"7 R452B Mélange 676 R32 + R125 + R1234yf - Opteon XL55"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# HFO et alternatives Low-GWP\n",
"low_gwp_fluids = [\n",
@@ -196,9 +356,26 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 9,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cycles HFO / Low-GWP:\n",
"--------------------------------------------------\n",
" R1234yf → ✅ Supporté (8 vars)\n",
" R1234ze(E) → ✅ Supporté (8 vars)\n",
" R1233zd(E) → ✅ Supporté (8 vars)\n",
" R1243zf → ✅ Supporté (8 vars)\n",
" R1336mzz(E) → ✅ Supporté (8 vars)\n",
" R513A → ✅ Supporté (8 vars)\n",
" R454B → ✅ Supporté (8 vars)\n",
" R452B → ✅ Supporté (8 vars)\n"
]
}
],
"source": [
"# Test cycles HFO\n",
"print(\"Cycles HFO / Low-GWP:\")\n",
@@ -222,9 +399,98 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 10,
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Code ASHRAE</th>\n",
" <th>Nom</th>\n",
" <th>GWP</th>\n",
" <th>Application</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>R744</td>\n",
" <td>CO2</td>\n",
" <td>1</td>\n",
" <td>Transcritique, commercial</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>R290</td>\n",
" <td>Propane</td>\n",
" <td>3</td>\n",
" <td>Climatisation, commercial</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>R600a</td>\n",
" <td>Isobutane</td>\n",
" <td>3</td>\n",
" <td>Domestique, commerc. faible charge</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>R600</td>\n",
" <td>Butane</td>\n",
" <td>3</td>\n",
" <td>Réfrigération basse température</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>R1270</td>\n",
" <td>Propylène</td>\n",
" <td>3</td>\n",
" <td>Climatisation industrielle</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>R717</td>\n",
" <td>Ammonia</td>\n",
" <td>0</td>\n",
" <td>Industriel, forte puissance</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Code ASHRAE Nom GWP Application\n",
"0 R744 CO2 1 Transcritique, commercial\n",
"1 R290 Propane 3 Climatisation, commercial\n",
"2 R600a Isobutane 3 Domestique, commerc. faible charge\n",
"3 R600 Butane 3 Réfrigération basse température\n",
"4 R1270 Propylène 3 Climatisation industrielle\n",
"5 R717 Ammonia 0 Industriel, forte puissance"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Fluides naturels\n",
"natural_fluids = [\n",
@@ -242,9 +508,24 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 11,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cycles fluides naturels:\n",
"--------------------------------------------------\n",
" R744 (CO2 ) → ✅ Supporté\n",
" R290 (Propane ) → ✅ Supporté\n",
" R600a (Isobutane ) → ✅ Supporté\n",
" R600 (Butane ) → ✅ Supporté\n",
" R1270 (Propylène ) → ✅ Supporté\n",
" R717 (Ammonia ) → ✅ Supporté\n"
]
}
],
"source": [
"# Test cycles fluides naturels\n",
"print(\"Cycles fluides naturels:\")\n",
@@ -266,9 +547,17 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 12,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Total réfrigérants classiques: 26\n"
]
}
],
"source": [
"# Autres réfrigérants disponibles\n",
"other_refrigerants = [\n",
@@ -295,9 +584,168 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 13,
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Nom CoolProp</th>\n",
" <th>Formule</th>\n",
" <th>Usage</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Water</td>\n",
" <td>H2O</td>\n",
" <td>Fluide de travail, calibration</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Air</td>\n",
" <td>N2+O2</td>\n",
" <td>Climatisation, psychrométrie</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Nitrogen</td>\n",
" <td>N2</td>\n",
" <td>Cryogénie, inertage</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Oxygen</td>\n",
" <td>O2</td>\n",
" <td>Applications spéciales</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Argon</td>\n",
" <td>Ar</td>\n",
" <td>Cryogénie</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>Helium</td>\n",
" <td>He</td>\n",
" <td>Cryogénie très basse T</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Hydrogen</td>\n",
" <td>H2</td>\n",
" <td>Énergie, cryogénie</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>Methane</td>\n",
" <td>CH4</td>\n",
" <td>GNL, pétrole</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>Ethane</td>\n",
" <td>C2H6</td>\n",
" <td>Pétrochimie</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>Ethylene</td>\n",
" <td>C2H4</td>\n",
" <td>Pétrochimie</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>Propane</td>\n",
" <td>C3H8</td>\n",
" <td>= R290</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>Butane</td>\n",
" <td>C4H10</td>\n",
" <td>= R600</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>Ethanol</td>\n",
" <td>C2H5OH</td>\n",
" <td>Solvant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>Methanol</td>\n",
" <td>CH3OH</td>\n",
" <td>Solvant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>Acetone</td>\n",
" <td>C3H6O</td>\n",
" <td>Solvant</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>Benzene</td>\n",
" <td>C6H6</td>\n",
" <td>Chimie</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>Toluene</td>\n",
" <td>C7H8</td>\n",
" <td>ORC</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Nom CoolProp Formule Usage\n",
"0 Water H2O Fluide de travail, calibration\n",
"1 Air N2+O2 Climatisation, psychrométrie\n",
"2 Nitrogen N2 Cryogénie, inertage\n",
"3 Oxygen O2 Applications spéciales\n",
"4 Argon Ar Cryogénie\n",
"5 Helium He Cryogénie très basse T\n",
"6 Hydrogen H2 Énergie, cryogénie\n",
"7 Methane CH4 GNL, pétrole\n",
"8 Ethane C2H6 Pétrochimie\n",
"9 Ethylene C2H4 Pétrochimie\n",
"10 Propane C3H8 = R290\n",
"11 Butane C4H10 = R600\n",
"12 Ethanol C2H5OH Solvant\n",
"13 Methanol CH3OH Solvant\n",
"14 Acetone C3H6O Solvant\n",
"15 Benzene C6H6 Chimie\n",
"16 Toluene C7H8 ORC"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Fluides non-réfrigérants disponibles\n",
"other_fluids = [\n",
@@ -333,9 +781,108 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 14,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"=== RÉSUMÉ DES FLUIDES DISPONIBLES ===\n",
"Total: 61+ fluides\n",
"\n"
]
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Catégorie</th>\n",
" <th>Exemples</th>\n",
" <th>Nombre</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>HFC Classiques</td>\n",
" <td>R134a, R410A, R407C, R32, R125</td>\n",
" <td>5</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>HFO / Low-GWP</td>\n",
" <td>R1234yf, R1234ze(E), R1233zd(E)</td>\n",
" <td>6</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Alternatives (Mélanges)</td>\n",
" <td>R513A, R454B, R452B, R507A</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Fluides Naturels</td>\n",
" <td>R744 (CO2), R290, R600a, R717</td>\n",
" <td>6</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>CFC/HCFC (Obsolètes)</td>\n",
" <td>R11, R12, R22, R123, R141b</td>\n",
" <td>8</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>Autres HFC</td>\n",
" <td>R143a, R152A, R227EA, R245fa</td>\n",
" <td>15</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Non-Réfrigérants</td>\n",
" <td>Water, Air, Nitrogen, Helium</td>\n",
" <td>17</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Catégorie Exemples Nombre\n",
"0 HFC Classiques R134a, R410A, R407C, R32, R125 5\n",
"1 HFO / Low-GWP R1234yf, R1234ze(E), R1233zd(E) 6\n",
"2 Alternatives (Mélanges) R513A, R454B, R452B, R507A 4\n",
"3 Fluides Naturels R744 (CO2), R290, R600a, R717 6\n",
"4 CFC/HCFC (Obsolètes) R11, R12, R22, R123, R141b 8\n",
"5 Autres HFC R143a, R152A, R227EA, R245fa 15\n",
"6 Non-Réfrigérants Water, Air, Nitrogen, Helium 17"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Catégorisation complète\n",
"fluid_summary = {\n",
@@ -377,9 +924,24 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 15,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"=== Cycle CO2 Transcritique (R744) ===\n",
"\n",
"Propriétés du CO2:\n",
" Point critique: 31.0°C, 73.8 bar\n",
" GWP: 1\n",
" Applications: Supermarchés, transports, chaleur industrielle\n",
"\n",
"Système créé: 8 variables d'état\n"
]
}
],
"source": [
"# Cycle CO2 transcritique\n",
"print(\"=== Cycle CO2 Transcritique (R744) ===\")\n",
@@ -401,9 +963,25 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 16,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"=== Cycle Ammoniac (R717) ===\n",
"\n",
"Propriétés de l'Ammoniac:\n",
" Point critique: 132.4°C, 113.3 bar\n",
" GWP: 0 (naturel)\n",
" haute efficacité, toxique mais détectable\n",
" Applications: Industrie agroalimentaire, patinoires, entrepôts\n",
"\n",
"Système créé: 8 variables d'état\n"
]
}
],
"source": [
"# Cycle Ammoniac\n",
"print(\"=== Cycle Ammoniac (R717) ===\")\n",
@@ -426,9 +1004,26 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 17,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"=== Cycle Propane (R290) ===\n",
"\n",
"Propriétés du Propane:\n",
" Point critique: 96.7°C, 42.5 bar\n",
" GWP: 3 (très bas)\n",
" Excellentes propriétés thermodynamiques\n",
" Inflammable (A3)\n",
" Applications: Climatisation, pompes à chaleur, commercial\n",
"\n",
"Système créé: 8 variables d'état\n"
]
}
],
"source": [
"# Cycle Propane\n",
"print(\"=== Cycle Propane (R290) ===\")\n",
@@ -452,9 +1047,17 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 18,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Solver configuré: FallbackConfig(newton=NewtonConfig(max_iter=200, tol=1.0e-6, line_search=true), picard=PicardConfig(max_iter=500, tol=1.0e-4, relax=0.50))\n"
]
}
],
"source": [
"# Exemple de configuration du solveur pour résolution\n",
"system = build_simple_cycle(\"R134a\")\n",
@@ -502,7 +1105,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "entropyk",
"language": "python",
"name": "python3"
},
@@ -516,7 +1119,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.0"
"version": "3.13.11"
}
},
"nbformat": 4,

View File

@@ -214,6 +214,60 @@
"## 5. Recommandations par Application"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import entropyk\n",
"\n",
"# Create a system\n",
"system = entropyk.System()\n",
"\n",
"# Add components\n",
"# Note: Python bindings use simplified adapters for demonstration\n",
"compressor = entropyk.Compressor(\n",
" speed_rpm=2900.0,\n",
" displacement=0.0001, # m³/rev\n",
" efficiency=0.85,\n",
" fluid=\"R134a\",\n",
")\n",
"\n",
"condenser = entropyk.Condenser(ua=5000.0) # UA in W/K\n",
"evaporator = entropyk.Evaporator(ua=3000.0)\n",
"valve = entropyk.ExpansionValve(fluid=\"R134a\", opening=0.8)\n",
"\n",
"# Add to system\n",
"comp_idx = system.add_component(compressor)\n",
"cond_idx = system.add_component(condenser)\n",
"evap_idx = system.add_component(evaporator)\n",
"valve_idx = system.add_component(valve)\n",
"\n",
"# Connect refrigerant circuit\n",
"system.add_edge(comp_idx, cond_idx) # Compressor → Condenser (hot side)\n",
"system.add_edge(cond_idx, valve_idx) # Condenser → Valve\n",
"system.add_edge(valve_idx, evap_idx) # Valve → Evaporator (cold side)\n",
"system.add_edge(evap_idx, comp_idx) # Evaporator → Compressor\n",
"\n",
"# Finalize topology\n",
"system.finalize()\n",
"\n",
"# Configure solver\n",
"solver = entropyk.NewtonConfig(\n",
" max_iterations=200,\n",
" tolerance=1e-6,\n",
" line_search=True,\n",
")\n",
"\n",
"# Solve (requires proper boundary conditions and fluid backend)\n",
"try:\n",
" result = solver.solve(system)\n",
" print(f\"Converged in {result.iterations} iterations\")\n",
"except entropyk.SolverError as e:\n",
" print(f\"Solver error: {e}\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
@@ -294,15 +348,28 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"metadata": {},
"outputs": [],
"outputs": [
{
"ename": "NameError",
"evalue": "name 'entropyk' is not defined",
"output_type": "error",
"traceback": [
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
"\u001b[31mNameError\u001b[39m Traceback (most recent call last)",
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 48\u001b[39m\n\u001b[32m 46\u001b[39m \u001b[38;5;66;03m# Test\u001b[39;00m\n\u001b[32m 47\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m fluid \u001b[38;5;129;01min\u001b[39;00m [\u001b[33m\"\u001b[39m\u001b[33mR134a\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mR32\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mR290\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mR744\u001b[39m\u001b[33m\"\u001b[39m]:\n\u001b[32m---> \u001b[39m\u001b[32m48\u001b[39m system = \u001b[43mcreate_cycle_for_fluid\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfluid\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mClimatisation\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 49\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfluid\u001b[38;5;132;01m:\u001b[39;00m\u001b[33m8s\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00msystem.state_vector_len\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m variables d\u001b[39m\u001b[33m'\u001b[39m\u001b[33métat\u001b[39m\u001b[33m\"\u001b[39m)\n",
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 21\u001b[39m, in \u001b[36mcreate_cycle_for_fluid\u001b[39m\u001b[34m(fluid, app_name)\u001b[39m\n\u001b[32m 18\u001b[39m ua_cond = \u001b[32m5000.0\u001b[39m\n\u001b[32m 19\u001b[39m ua_evap = \u001b[32m3000.0\u001b[39m\n\u001b[32m---> \u001b[39m\u001b[32m21\u001b[39m system = \u001b[43mentropyk\u001b[49m.System()\n\u001b[32m 23\u001b[39m comp = entropyk.Compressor(\n\u001b[32m 24\u001b[39m speed_rpm=\u001b[32m2900.0\u001b[39m,\n\u001b[32m 25\u001b[39m displacement=\u001b[32m0.0001\u001b[39m,\n\u001b[32m 26\u001b[39m efficiency=\u001b[32m0.85\u001b[39m,\n\u001b[32m 27\u001b[39m fluid=fluid\n\u001b[32m 28\u001b[39m )\n\u001b[32m 29\u001b[39m cond = entropyk.Condenser(ua=ua_cond)\n",
"\u001b[31mNameError\u001b[39m: name 'entropyk' is not defined"
]
}
],
"source": [
"def create_cycle_for_fluid(fluid: str, app_name: str = \"Climatisation\"):\n",
" \"\"\"\n",
" Crée un cycle optimisé pour un fluide et une application donnée.\n",
" \"\"\"\n",
" params = applications[app_name]\n",
" #params = applications[app_name]\n",
" \n",
" # Ajuster les composants selon le fluide\n",
" if fluid == \"R744\":\n",
@@ -349,6 +416,253 @@
" print(f\"{fluid:8s}: {system.state_vector_len} variables d'état\")"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Construction du système Entropyk complet...\n",
"Finalisation du graphe (Construction de la topologie)...\n",
"Propriétés du système : 18 composants, 17 connexions.\n",
"Taille du vecteur d'état mathématique : 34 variables.\n",
"\n",
"Configuration de la stratégie de résolution...\n",
"Lancement de la simulation (Newton uniquement)...\n",
"\n",
"❌ Erreur du solveur : Solver diverged: Jacobian is singular - cannot solve linear system\n",
"Note: Ce comportement peut arriver si les paramètres (taille des tuyaux, coeffs, températures)\n",
"dépassent le domaine thermodynamique du fluide ou si le graphe manque de contraintes aux limites.\n"
]
}
],
"source": [
"import entropyk\n",
"import math\n",
"\n",
"def build_complete_system():\n",
" # ── 1. Initialisation du graphe du système ──\n",
" system = entropyk.System()\n",
" print(\"Construction du système Entropyk complet...\")\n",
"\n",
" # Paramètres fluides\n",
" refrigerant = \"R410A\"\n",
" water = \"Water\"\n",
"\n",
" # =========================================================================\n",
" # BOUCLE 1 : CIRCUIT FRIGORIFIQUE (REFRIGERANT R410A)\n",
" # =========================================================================\n",
" \n",
" # 1.1 Compresseur (Modèle Polynomial AHRI 540)\n",
" compressor = system.add_component(entropyk.Compressor(\n",
" m1=0.85, m2=2.5, m3=500.0, m4=1500.0, m5=-2.5, m6=1.8, m7=600.0, m8=1600.0, m9=-3.0, m10=2.0,\n",
" speed_rpm=3600.0,\n",
" displacement=0.00008,\n",
" efficiency=0.88,\n",
" fluid=refrigerant\n",
" ))\n",
" \n",
" # 1.2 Tuyau de refoulement (vers condenseur)\n",
" pipe_hot = system.add_component(entropyk.Pipe(\n",
" length=5.0,\n",
" diameter=0.02,\n",
" fluid=refrigerant\n",
" ))\n",
" \n",
" # 1.3 Condenseur (Rejet de chaleur)\n",
" condenser = system.add_component(entropyk.Condenser(\n",
" ua=4500.0,\n",
" fluid=refrigerant,\n",
" water_temp=30.0, # Température d'entrée côté eau/air\n",
" water_flow=2.0\n",
" ))\n",
" \n",
" # 1.4 Ligne liquide\n",
" pipe_liquid = system.add_component(entropyk.Pipe(\n",
" length=10.0,\n",
" diameter=0.015,\n",
" fluid=refrigerant\n",
" ))\n",
" \n",
" # 1.5 Division du débit (FlowSplitter) vers 2 évaporateurs\n",
" splitter = system.add_component(entropyk.FlowSplitter(n_outlets=2))\n",
" \n",
" # 1.6 Branche A : Détendeur + Évaporateur 1\n",
" exv_a = system.add_component(entropyk.ExpansionValve(fluid=refrigerant, opening=0.5))\n",
" evap_a = system.add_component(entropyk.Evaporator(\n",
" ua=2000.0,\n",
" fluid=refrigerant,\n",
" water_temp=12.0,\n",
" water_flow=1.0\n",
" ))\n",
" \n",
" # 1.7 Branche B : Détendeur + Évaporateur 2\n",
" exv_b = system.add_component(entropyk.ExpansionValve(fluid=refrigerant, opening=0.5))\n",
" evap_b = system.add_component(entropyk.Evaporator(\n",
" ua=2000.0,\n",
" fluid=refrigerant,\n",
" water_temp=15.0, # Température d'eau légèrement différente\n",
" water_flow=1.0\n",
" ))\n",
" \n",
" # 1.8 Fusion du débit (FlowMerger)\n",
" merger = system.add_component(entropyk.FlowMerger(n_inlets=2))\n",
" \n",
" # 1.9 Tuyau d'aspiration (retour compresseur)\n",
" pipe_suction = system.add_component(entropyk.Pipe(\n",
" length=5.0,\n",
" diameter=0.025,\n",
" fluid=refrigerant\n",
" ))\n",
"\n",
" # --- Connexions de la boucle frigo ---\n",
" system.add_edge(compressor, pipe_hot)\n",
" system.add_edge(pipe_hot, condenser)\n",
" system.add_edge(condenser, pipe_liquid)\n",
" \n",
" # Splitter\n",
" system.add_edge(pipe_liquid, splitter)\n",
" system.add_edge(splitter, exv_a)\n",
" system.add_edge(splitter, exv_b)\n",
" \n",
" # Branches parallèles\n",
" system.add_edge(exv_a, evap_a)\n",
" system.add_edge(exv_b, evap_b)\n",
" \n",
" # Merger\n",
" system.add_edge(evap_a, merger)\n",
" system.add_edge(evap_b, merger)\n",
" \n",
" system.add_edge(merger, pipe_suction)\n",
" system.add_edge(pipe_suction, compressor)\n",
"\n",
" # =========================================================================\n",
" # BOUCLE 2 : CIRCUIT RÉSEAU HYDRAULIQUE (EAU - Côté Évaporateur Principal)\n",
" # (Juste de la tuyauterie et une pompe pour montrer les FlowSource/FlowSink)\n",
" # =========================================================================\n",
" \n",
" water_source = system.add_component(entropyk.FlowSource(\n",
" fluid=water,\n",
" pressure_pa=101325.0, # 1 atm\n",
" temperature_k=285.15 # 12 °C\n",
" ))\n",
" \n",
" water_pump = system.add_component(entropyk.Pump(\n",
" pressure_rise_pa=50000.0, # 0.5 bar\n",
" efficiency=0.6\n",
" ))\n",
" \n",
" water_pipe = system.add_component(entropyk.Pipe(\n",
" length=20.0,\n",
" diameter=0.05,\n",
" fluid=water\n",
" ))\n",
" \n",
" water_sink = system.add_component(entropyk.FlowSink())\n",
" \n",
" # --- Connexions Hydrauliques Principales ---\n",
" system.add_edge(water_source, water_pump)\n",
" system.add_edge(water_pump, water_pipe)\n",
" system.add_edge(water_pipe, water_sink)\n",
"\n",
"\n",
" # =========================================================================\n",
" # BOUCLE 3 : CIRCUIT VENTILATION (AIR - Côté Condenseur)\n",
" # =========================================================================\n",
" \n",
" air_source = system.add_component(entropyk.FlowSource(\n",
" fluid=\"Air\",\n",
" pressure_pa=101325.0,\n",
" temperature_k=308.15 # 35 °C d'air ambiant\n",
" ))\n",
" \n",
" condenser_fan = system.add_component(entropyk.Fan(\n",
" pressure_rise_pa=200.0, # 200 Pa de montée en pression par le ventilo\n",
" efficiency=0.5\n",
" ))\n",
" \n",
" air_sink = system.add_component(entropyk.FlowSink())\n",
" \n",
" # --- Connexions Ventilation ---\n",
" system.add_edge(air_source, condenser_fan)\n",
" system.add_edge(condenser_fan, air_sink)\n",
"\n",
"\n",
" # ── 4. Finalisation du système ──\n",
" print(\"Finalisation du graphe (Construction de la topologie)...\")\n",
" system.finalize()\n",
" print(f\"Propriétés du système : {system.node_count} composants, {system.edge_count} connexions.\")\n",
" print(f\"Taille du vecteur d'état mathématique : {system.state_vector_len} variables.\")\n",
" \n",
" return system\n",
"\n",
"\n",
"def solve_system(system):\n",
" # ── 5. Configuration Avancée du Solveur (Story 6-6) ──\n",
" print(\"\\nConfiguration de la stratégie de résolution...\")\n",
"\n",
" # (Optionnel) Critères de convergence fins\n",
" convergence = entropyk.ConvergenceCriteria(\n",
" pressure_tolerance_pa=5.0,\n",
" mass_balance_tolerance_kgs=1e-6,\n",
" energy_balance_tolerance_w=1e-3\n",
" )\n",
"\n",
" # (Optionnel) Jacobian Freezing pour aller plus vite\n",
" freezing = entropyk.JacobianFreezingConfig(\n",
" max_frozen_iters=4,\n",
" threshold=0.1\n",
" )\n",
"\n",
" # Configuration Newton avec tolérances avancées\n",
" newton_config = entropyk.NewtonConfig(\n",
" max_iterations=150,\n",
" tolerance=1e-5,\n",
" line_search=True,\n",
" use_numerical_jacobian=True,\n",
" jacobian_freezing=freezing,\n",
" convergence_criteria=convergence,\n",
" initial_state=[1000000.0, 450000.0] * 17\n",
" )\n",
"\n",
" # Configuration Picard robuste en cas d'échec de Newton\n",
" picard_config = entropyk.PicardConfig(\n",
" max_iterations=500,\n",
" tolerance=1e-4,\n",
" relaxation=0.4,\n",
" convergence_criteria=convergence\n",
" )\n",
"\n",
" # ── 6. Lancement du calcul ──\n",
" print(\"Lancement de la simulation (Newton uniquement)...\")\n",
" try:\n",
" result = newton_config.solve(system)\n",
" \n",
" status = result.status\n",
" print(f\"\\n✅ Simulation terminée avec succès !\")\n",
" print(f\"Statut : {status}\")\n",
" print(f\"Itérations : {result.iterations}\")\n",
" print(f\"Résidu final : {result.final_residual:.2e}\")\n",
" \n",
" # Le résultat contient le vecteur d'état complet\n",
" state_vec = result.state_vector\n",
" print(f\"Aperçu des 5 premières variables d'état : {state_vec[:5]}\")\n",
" \n",
" except entropyk.TimeoutError:\n",
" print(\"\\n❌ Le solveur a dépassé le temps imparti (Timeout).\")\n",
" except entropyk.SolverError as e:\n",
" print(f\"\\n❌ Erreur du solveur : {e}\")\n",
" print(\"Note: Ce comportement peut arriver si les paramètres (taille des tuyaux, coeffs, températures)\")\n",
" print(\"dépassent le domaine thermodynamique du fluide ou si le graphe manque de contraintes aux limites.\")\n",
"\n",
"if __name__ == \"__main__\":\n",
" system = build_complete_system()\n",
" solve_system(system)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
@@ -387,7 +701,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "entropyk",
"language": "python",
"name": "python3"
},
@@ -401,7 +715,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.0"
"version": "3.13.11"
}
},
"nbformat": 4,

View File

@@ -549,6 +549,7 @@ impl PyNewtonConfig {
initial_state: self.initial_state.clone(),
convergence_criteria: self.convergence_criteria.as_ref().map(|cc| cc.inner.clone()),
jacobian_freezing: self.jacobian_freezing.as_ref().map(|jf| jf.inner.clone()),
verbose_config: Default::default(),
};
// Catch any Rust panic to prevent it from reaching Python (Task 5.4)
@@ -739,6 +740,7 @@ impl PyFallbackConfig {
initial_state: self.newton.initial_state.clone(),
convergence_criteria: self.newton.convergence_criteria.as_ref().map(|cc| cc.inner.clone()),
jacobian_freezing: self.newton.jacobian_freezing.as_ref().map(|jf| jf.inner.clone()),
verbose_config: Default::default(),
};
let picard_config = entropyk_solver::PicardConfig {
max_iterations: self.picard.max_iterations,
@@ -982,6 +984,7 @@ impl PySolverStrategy {
initial_state: py_config.initial_state.clone(),
convergence_criteria: py_config.convergence_criteria.as_ref().map(|cc| cc.inner.clone()),
jacobian_freezing: py_config.jacobian_freezing.as_ref().map(|jf| jf.inner.clone()),
verbose_config: Default::default(),
};
Ok(PySolverStrategy {
inner: entropyk_solver::SolverStrategy::NewtonRaphson(config),

View File

@@ -273,6 +273,7 @@ impl WasmConvergedState {
#[cfg(test)]
mod tests {
use super::*;
use wasm_bindgen_test::wasm_bindgen_test;
#[wasm_bindgen_test]
fn test_pressure_creation() {