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