724 lines
32 KiB
Plaintext
724 lines
32 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Comparaison des Réfrigérants pour Applications Courantes\n",
|
|
"\n",
|
|
"Ce notebook compare les propriétés thermodynamiques de différents réfrigérants pour des applications typiques:\n",
|
|
"\n",
|
|
"- **Climatisation** : Température d'évaporation ~7°C, Condensation ~45°C\n",
|
|
"- **Réfrigération commerciale** : Tévap ~-10°C, Tcond ~40°C\n",
|
|
"- **Froid négatif** : Tévap ~-35°C, Tcond ~35°C"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import entropyk\n",
|
|
"import pandas as pd\n",
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"# Pour les graphiques (optionnel)\n",
|
|
"try:\n",
|
|
" import matplotlib.pyplot as plt\n",
|
|
" HAS_MATPLOTLIB = True\n",
|
|
"except ImportError:\n",
|
|
" HAS_MATPLOTLIB = False\n",
|
|
" print(\"matplotlib non disponible - graphiques désactivés\")\n",
|
|
"\n",
|
|
"print(\"Entropyk chargé avec succès!\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 1. Paramètres des Applications"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Définir les conditions opératoires pour chaque application\n",
|
|
"applications = {\n",
|
|
" \"Climatisation\": {\n",
|
|
" \"T_evap_C\": 7.0,\n",
|
|
" \"T_cond_C\": 45.0,\n",
|
|
" \"surchauffe_K\": 5.0,\n",
|
|
" \"sous-refroidissement_K\": 3.0,\n",
|
|
" },\n",
|
|
" \"Réfrigération commerciale\": {\n",
|
|
" \"T_evap_C\": -10.0,\n",
|
|
" \"T_cond_C\": 40.0,\n",
|
|
" \"surchauffe_K\": 5.0,\n",
|
|
" \"sous-refroidissement_K\": 3.0,\n",
|
|
" },\n",
|
|
" \"Froid négatif\": {\n",
|
|
" \"T_evap_C\": -35.0,\n",
|
|
" \"T_cond_C\": 35.0,\n",
|
|
" \"surchauffe_K\": 5.0,\n",
|
|
" \"sous-refroidissement_K\": 3.0,\n",
|
|
" },\n",
|
|
" \"Pompe à chaleur\": {\n",
|
|
" \"T_evap_C\": -5.0,\n",
|
|
" \"T_cond_C\": 55.0,\n",
|
|
" \"surchauffe_K\": 5.0,\n",
|
|
" \"sous-refroidissement_K\": 5.0,\n",
|
|
" },\n",
|
|
"}\n",
|
|
"\n",
|
|
"for app_name, params in applications.items():\n",
|
|
" print(f\"{app_name}:\")\n",
|
|
" print(f\" Évaporation: {params['T_evap_C']}°C\")\n",
|
|
" print(f\" Condensation: {params['T_cond_C']}°C\")\n",
|
|
" print(f\" Delta T: {params['T_cond_C'] - params['T_evap_C']}K\")\n",
|
|
" print()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 2. Fluides à Comparer"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Liste des fluides avec leurs propriétés GWP et sécurité\n",
|
|
"fluides = {\n",
|
|
" \"R134a\": {\"GWP\": 1430, \"Classe\": \"A1\", \"Type\": \"HFC\"},\n",
|
|
" \"R410A\": {\"GWP\": 2088, \"Classe\": \"A1\", \"Type\": \"HFC\"},\n",
|
|
" \"R32\": {\"GWP\": 675, \"Classe\": \"A2L\", \"Type\": \"HFC\"},\n",
|
|
" \"R290\": {\"GWP\": 3, \"Classe\": \"A3\", \"Type\": \"Naturel\"},\n",
|
|
" \"R600a\": {\"GWP\": 3, \"Classe\": \"A3\", \"Type\": \"Naturel\"},\n",
|
|
" \"R744\": {\"GWP\": 1, \"Classe\": \"A1\", \"Type\": \"Naturel\"},\n",
|
|
" \"R1234yf\": {\"GWP\": 4, \"Classe\": \"A2L\", \"Type\": \"HFO\"},\n",
|
|
" \"R1234ze(E)\": {\"GWP\": 7, \"Classe\": \"A2L\", \"Type\": \"HFO\"},\n",
|
|
" \"R454B\": {\"GWP\": 146, \"Classe\": \"A2L\", \"Type\": \"Mélange\"},\n",
|
|
" \"R513A\": {\"GWP\": 631, \"Classe\": \"A1\", \"Type\": \"Mélange\"},\n",
|
|
"}\n",
|
|
"\n",
|
|
"df_fluides = pd.DataFrame.from_dict(fluides, orient='index')\n",
|
|
"df_fluides.index.name = \"Fluide\"\n",
|
|
"df_fluides"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 3. Comparaison des Pressions de Travail"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Afficher les pressions de saturation pour chaque application\n",
|
|
"print(\"=== Pressions de Saturation (bar) ===\\n\")\n",
|
|
"\n",
|
|
"for app_name, params in applications.items():\n",
|
|
" print(f\"--- {app_name} ---\")\n",
|
|
" print(f\"{'Fluide':12s} {'P_evap':>10s} {'P_cond':>10s} {'Ratio':>8s}\")\n",
|
|
" print(\"-\" * 45)\n",
|
|
" \n",
|
|
" for fluide in fluides:\n",
|
|
" # Note: Les valeurs réelles nécessitent CoolProp\n",
|
|
" # Ici on utilise des valeurs approximatives pour démonstration\n",
|
|
" if fluide == \"R744\":\n",
|
|
" # CO2 a des pressions très élevées\n",
|
|
" p_evap_approx = {\"Climatisation\": 45, \"Réfrigération commerciale\": 26, \"Froid négatif\": 12, \"Pompe à chaleur\": 30}\n",
|
|
" p_cond_approx = {\"Climatisation\": 90, \"Réfrigération commerciale\": 75, \"Froid négatif\": 65, \"Pompe à chaleur\": 120}\n",
|
|
" elif fluide == \"R410A\":\n",
|
|
" p_evap_approx = {\"Climatisation\": 6.2, \"Réfrigération commerciale\": 3.5, \"Froid négatif\": 1.5, \"Pompe à chaleur\": 4.8}\n",
|
|
" p_cond_approx = {\"Climatisation\": 26.5, \"Réfrigération commerciale\": 24, \"Froid négatif\": 21, \"Pompe à chaleur\": 34}\n",
|
|
" elif fluide == \"R134a\":\n",
|
|
" p_evap_approx = {\"Climatisation\": 3.8, \"Réfrigération commerciale\": 2.0, \"Froid négatif\": 0.8, \"Pompe à chaleur\": 2.8}\n",
|
|
" p_cond_approx = {\"Climatisation\": 11.6, \"Réfrigération commerciale\": 10.2, \"Froid négatif\": 8.9, \"Pompe à chaleur\": 15}\n",
|
|
" elif fluide == \"R32\":\n",
|
|
" p_evap_approx = {\"Climatisation\": 5.8, \"Réfrigération commerciale\": 3.2, \"Froid négatif\": 1.3, \"Pompe à chaleur\": 4.4}\n",
|
|
" p_cond_approx = {\"Climatisation\": 24, \"Réfrigération commerciale\": 21.5, \"Froid négatif\": 19, \"Pompe à chaleur\": 30}\n",
|
|
" elif fluide == \"R290\":\n",
|
|
" p_evap_approx = {\"Climatisation\": 5.5, \"Réfrigération commerciale\": 2.8, \"Froid négatif\": 1.0, \"Pompe à chaleur\": 4.0}\n",
|
|
" p_cond_approx = {\"Climatisation\": 15.5, \"Réfrigération commerciale\": 13.5, \"Froid négatif\": 11.5, \"Pompe à chaleur\": 20}\n",
|
|
" else:\n",
|
|
" # Valeurs génériques\n",
|
|
" p_evap_approx = {k: 3.0 for k in applications}\n",
|
|
" p_cond_approx = {k: 10.0 for k in applications}\n",
|
|
" \n",
|
|
" p_evap = p_evap_approx[app_name]\n",
|
|
" p_cond = p_cond_approx[app_name]\n",
|
|
" ratio = p_cond / p_evap\n",
|
|
" \n",
|
|
" print(f\"{fluide:12s} {p_evap:10.1f} {p_cond:10.1f} {ratio:8.2f}\")\n",
|
|
" print()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 4. Performance Théorique (COP) par Application"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# COP théorique de Carnot et valeurs typiques\n",
|
|
"print(\"=== COP par Application ===\\n\")\n",
|
|
"\n",
|
|
"cop_data = []\n",
|
|
"for app_name, params in applications.items():\n",
|
|
" T_evap_K = params['T_evap_C'] + 273.15\n",
|
|
" T_cond_K = params['T_cond_C'] + 273.15\n",
|
|
" \n",
|
|
" # COP de Carnot\n",
|
|
" cop_carnot = T_evap_K / (T_cond_K - T_evap_K)\n",
|
|
" \n",
|
|
" # COP réels typiques (60-70% de Carnot)\n",
|
|
" cop_real = cop_carnot * 0.65\n",
|
|
" \n",
|
|
" cop_data.append({\n",
|
|
" \"Application\": app_name,\n",
|
|
" \"T_evap (°C)\": params['T_evap_C'],\n",
|
|
" \"T_cond (°C)\": params['T_cond_C'],\n",
|
|
" \"COP Carnot\": round(cop_carnot, 2),\n",
|
|
" \"COP Réel (~)\": round(cop_real, 2),\n",
|
|
" })\n",
|
|
"\n",
|
|
"df_cop = pd.DataFrame(cop_data)\n",
|
|
"df_cop"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 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,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"recommandations = {\n",
|
|
" \"Climatisation\": {\n",
|
|
" \"Principal\": \"R32\",\n",
|
|
" \"Alternatives\": [\"R290\", \"R454B\"],\n",
|
|
" \"Raisons\": \"R32: bon COP, GWP modéré, compatible R410A. R290: meilleur COP, faible charge.\",\n",
|
|
" },\n",
|
|
" \"Réfrigération commerciale\": {\n",
|
|
" \"Principal\": \"R744 (CO2)\",\n",
|
|
" \"Alternatives\": [\"R290\", \"R404A (existant)\"],\n",
|
|
" \"Raisons\": \"CO2: GWP=1, toutes températures. R290: haute efficacité, charge limitée.\",\n",
|
|
" },\n",
|
|
" \"Froid négatif\": {\n",
|
|
" \"Principal\": \"R744 (CO2) cascade\",\n",
|
|
" \"Alternatives\": [\"R290/R600a cascade\"],\n",
|
|
" \"Raisons\": \"CO2 cascade ou R290/R600a pour GWP minimal.\",\n",
|
|
" },\n",
|
|
" \"Pompe à chaleur\": {\n",
|
|
" \"Principal\": \"R290\",\n",
|
|
" \"Alternatives\": [\"R32\", \"R744\"],\n",
|
|
" \"Raisons\": \"R290: excellent COP haute température. R744: transcritique pour eau chaude.\",\n",
|
|
" },\n",
|
|
"}\n",
|
|
"\n",
|
|
"for app, rec in recommandations.items():\n",
|
|
" print(f\"\\n{'='*60}\")\n",
|
|
" print(f\"{app}\")\n",
|
|
" print(f\"{'='*60}\")\n",
|
|
" print(f\" Principal: {rec['Principal']}\")\n",
|
|
" print(f\" Alternatives: {', '.join(rec['Alternatives'])}\")\n",
|
|
" print(f\" Raisons: {rec['Raisons']}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 6. Matrice de Sélection Rapide"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Matrice de compatibilité\n",
|
|
"compatibilite = {\n",
|
|
" \"R134a\": {\"Climatisation\": \"★★★\", \"Réfrigération\": \"★★★\", \"Froid négatif\": \"★★\", \"Pompe chaleur\": \"★★\", \"GWP\": 1430},\n",
|
|
" \"R410A\": {\"Climatisation\": \"★★★★\", \"Réfrigération\": \"★★\", \"Froid négatif\": \"★\", \"Pompe chaleur\": \"★★★\", \"GWP\": 2088},\n",
|
|
" \"R32\": {\"Climatisation\": \"★★★★★\", \"Réfrigération\": \"★★★\", \"Froid négatif\": \"★\", \"Pompe chaleur\": \"★★★★\", \"GWP\": 675},\n",
|
|
" \"R290\": {\"Climatisation\": \"★★★★★\", \"Réfrigération\": \"★★★★\", \"Froid négatif\": \"★★★\", \"Pompe chaleur\": \"★★★★★\", \"GWP\": 3},\n",
|
|
" \"R600a\": {\"Climatisation\": \"★★\", \"Réfrigération\": \"★★★\", \"Froid négatif\": \"★★★★\", \"Pompe chaleur\": \"★★\", \"GWP\": 3},\n",
|
|
" \"R744\": {\"Climatisation\": \"★★★\", \"Réfrigération\": \"★★★★★\", \"Froid négatif\": \"★★★★★\", \"Pompe chaleur\": \"★★★★\", \"GWP\": 1},\n",
|
|
" \"R1234yf\": {\"Climatisation\": \"★★★★\", \"Réfrigération\": \"★★★\", \"Froid négatif\": \"★\", \"Pompe chaleur\": \"★★\", \"GWP\": 4},\n",
|
|
" \"R454B\": {\"Climatisation\": \"★★★★\", \"Réfrigération\": \"★★★\", \"Froid négatif\": \"★\", \"Pompe chaleur\": \"★★★\", \"GWP\": 146},\n",
|
|
" \"R513A\": {\"Climatisation\": \"★★★\", \"Réfrigération\": \"★★★\", \"Froid négatif\": \"★★\", \"Pompe chaleur\": \"★★\", \"GWP\": 631},\n",
|
|
"}\n",
|
|
"\n",
|
|
"print(\"\\n=== Matrice de Sélection ===\")\n",
|
|
"print(\"★★★★★ = Excellent, ★★★★ = Très bon, ★★★ = Bon, ★★ = Acceptable, ★ = Déconseillé\\n\")\n",
|
|
"\n",
|
|
"for fluide, scores in compatibilite.items():\n",
|
|
" print(f\"{fluide:12s} | GWP:{scores['GWP']:5d} | Clim:{scores['Climatisation']} | Réfrig:{scores['Réfrigération']} | Nég:{scores['Froid négatif']} | PAC:{scores['Pompe chaleur']}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 7. Exemple de Code: Cycle Multi-Fluides"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"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",
|
|
" \n",
|
|
" # Ajuster les composants selon le fluide\n",
|
|
" if fluid == \"R744\":\n",
|
|
" # CO2: haute pression, échangeur gaz cooler\n",
|
|
" ua_cond = 8000.0 # Plus élevé pour CO2\n",
|
|
" ua_evap = 5000.0\n",
|
|
" elif fluid == \"R290\" or fluid == \"R600a\":\n",
|
|
" # Hydrocarbures: excellents transferts thermiques\n",
|
|
" ua_cond = 4000.0\n",
|
|
" ua_evap = 3500.0\n",
|
|
" else:\n",
|
|
" # HFC/HFO standards\n",
|
|
" ua_cond = 5000.0\n",
|
|
" ua_evap = 3000.0\n",
|
|
" \n",
|
|
" system = entropyk.System()\n",
|
|
" \n",
|
|
" comp = entropyk.Compressor(\n",
|
|
" speed_rpm=2900.0,\n",
|
|
" displacement=0.0001,\n",
|
|
" efficiency=0.85,\n",
|
|
" fluid=fluid\n",
|
|
" )\n",
|
|
" cond = entropyk.Condenser(ua=ua_cond)\n",
|
|
" exv = entropyk.ExpansionValve(fluid=fluid, opening=0.8)\n",
|
|
" evap = entropyk.Evaporator(ua=ua_evap)\n",
|
|
" \n",
|
|
" comp_idx = system.add_component(comp)\n",
|
|
" cond_idx = system.add_component(cond)\n",
|
|
" exv_idx = system.add_component(exv)\n",
|
|
" evap_idx = system.add_component(evap)\n",
|
|
" \n",
|
|
" system.add_edge(comp_idx, cond_idx)\n",
|
|
" system.add_edge(cond_idx, exv_idx)\n",
|
|
" system.add_edge(exv_idx, evap_idx)\n",
|
|
" system.add_edge(evap_idx, comp_idx)\n",
|
|
" \n",
|
|
" system.finalize()\n",
|
|
" return system\n",
|
|
"\n",
|
|
"# Test\n",
|
|
"for fluid in [\"R134a\", \"R32\", \"R290\", \"R744\"]:\n",
|
|
" system = create_cycle_for_fluid(fluid, \"Climatisation\")\n",
|
|
" 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": {},
|
|
"source": [
|
|
"## 8. Résumé Exécutif"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"print(\"\"\"\n",
|
|
"╔══════════════════════════════════════════════════════════════════════════╗\n",
|
|
"║ RÉSUMÉ - SÉLECTION DES RÉFRIGÉRANTS ║\n",
|
|
"╠══════════════════════════════════════════════════════════════════════════╣\n",
|
|
"║ CLIMATISATION ║\n",
|
|
"║ → R32 (standard), R290 (performant, charge limitée), R454B (retrofit) ║\n",
|
|
"║ ║\n",
|
|
"║ RÉFRIGÉRATION COMMERCIALE ║\n",
|
|
"║ → R744/CO2 (futur), R290 (nouveau), R404A (existant) ║\n",
|
|
"║ ║\n",
|
|
"║ FROID NÉGATIF ║\n",
|
|
"║ → R744 cascade, R290/R600a cascade ║\n",
|
|
"║ ║\n",
|
|
"║ POMPE À CHALEUR ║\n",
|
|
"║ → R290 (haute température), R32 (standard), R744 (transcritique) ║\n",
|
|
"╠══════════════════════════════════════════════════════════════════════════╣\n",
|
|
"║ TENDANCE RÉGLEMENTAIRE: GWP < 750 d'ici 2025-2030 ║\n",
|
|
"║ → Privilégier: R290, R600a, R744, R1234yf, R32 ║\n",
|
|
"╚══════════════════════════════════════════════════════════════════════════╝\n",
|
|
"\"\"\")"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "entropyk",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.13.11"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|