{ "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 }