{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Thermodynamic equilibrium"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is not necessary to use a Stream object to use thermodynamic equilibrium methods. In fact, thermosteam makes it just as easy to compute vapor-liquid equilibrium, bubble and dew points, and fugacities. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fugacities"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The easiest way to calculate fugacities is through LiquidFugacities and GasFugacities objects:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([43274.119, 58056.67 ])"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import thermosteam as tmo\n",
    "import numpy as np\n",
    "chemicals = tmo.Chemicals(['Water', 'Ethanol'])\n",
    "tmo.settings.set_thermo(chemicals)\n",
    "\n",
    "# Create a LiquidFugacities object\n",
    "F_l = tmo.equilibrium.LiquidFugacities(chemicals)\n",
    "\n",
    "# Compute liquid fugacities\n",
    "liquid_molar_composition = np.array([0.72, 0.28])\n",
    "f_l = F_l(x=liquid_molar_composition, T=355)\n",
    "f_l "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([43569.75, 57755.25])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create a GasFugacities object\n",
    "F_g = tmo.equilibrium.GasFugacities(chemicals)\n",
    "\n",
    "# Compute gas fugacities\n",
    "gas_molar_composition = np.array([0.43, 0.57])\n",
    "f_g = F_g(y=gas_molar_composition, T=355, P=101325)\n",
    "f_g"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Bubble and dew points"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similarly bubble and dew point can be calculated through BubblePoint and DewPoint objects:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "BubblePointValues(T=355, P=109755.45319869411, IDs=('Water', 'Ethanol'), z=[0.5 0.5], y=[0.343 0.657])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create a BubblePoint object\n",
    "BP = tmo.equilibrium.BubblePoint(chemicals)\n",
    "molar_composition = np.array([0.5, 0.5])\n",
    "\n",
    "# Solve bubble point at constant temperature\n",
    "bp = BP(z=molar_composition, T=355)\n",
    "bp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(355,\n",
       " 109755.45319869411,\n",
       " ('Water', 'Ethanol'),\n",
       " array([0.5, 0.5]),\n",
       " array([0.343, 0.657]))"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Note that the result is a BubblePointValues object which contain all results as attibutes\n",
    "(bp.T, bp.P, bp.IDs, bp.z, bp.y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "BubblePointValues(T=371.78188210405403, P=202650, IDs=('Water', 'Ethanol'), z=[0.5 0.5], y=[0.35 0.65])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Solve bubble point at constant pressure\n",
    "BP(z=molar_composition, P=2*101325)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DewPointValues(T=355, P=91970.14968399647, IDs=('Water', 'Ethanol'), z=[0.5 0.5], x=[0.851 0.149])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create a DewPoint object\n",
    "DP = tmo.equilibrium.DewPoint(chemicals)\n",
    "\n",
    "# Solve for dew point at constant temperautre\n",
    "dp = DP(z=molar_composition, T=355)\n",
    "dp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(355,\n",
       " 91970.14968399647,\n",
       " ('Water', 'Ethanol'),\n",
       " array([0.5, 0.5]),\n",
       " array([0.851, 0.149]))"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Note that the result is a DewPointValues object which contain all results as attibutes\n",
    "(dp.T, dp.P, dp.IDs, dp.z, dp.x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DewPointValues(T=376.2616600249248, P=202648, IDs=('Water', 'Ethanol'), z=[0.5 0.5], x=[0.832 0.168])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Solve for dew point at constant pressure\n",
    "DP(z=molar_composition, P=2*101324)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Vapor liquid equilibrium"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Vapor-liquid equilibrium can be calculated through a VLE object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "VLE(imol=MaterialIndexer(\n",
       "        g=[('Water', 0.5), ('Ethanol', 0.5)],\n",
       "        l=[('Water', 0.5), ('Ethanol', 0.5)]),\n",
       "    thermal_condition=ThermalCondition(T=298.15, P=101325))"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# First create a material indexer for the VLE object to manage material data\n",
    "imol = tmo.indexer.MaterialIndexer(l=[('Water', 0.5), ('Ethanol', 0.5)],\n",
    "                                   g=[('Water', 0.5), ('Ethanol', 0.5)])\n",
    "\n",
    "# Create a VLE object\n",
    "vle = tmo.equilibrium.VLE(imol)\n",
    "vle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can call the VLE object by setting 2 degrees of freedom from the following:`T` (temperature; in K), `P` (pressure; in Pa), `V` (molar vapor fraction), and `H` (enthalpy; in kJ/hr), `y` (binary molar vapor composition), `x` (binary molar liquid composition).\n",
    "\n",
    "Here we are some examples of the possibilities:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "VLE(imol=MaterialIndexer(\n",
       "        g=[('Water', 0.6417), ('Ethanol', 0.8607)],\n",
       "        l=[('Water', 0.3583), ('Ethanol', 0.1393)]),\n",
       "    thermal_condition=ThermalCondition(T=355.00, P=101325))"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vle(T=355, P=101325)\n",
    "vle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "VLE(imol=MaterialIndexer(\n",
       "        g=[('Water', 0.6161), ('Ethanol', 0.8266)],\n",
       "        l=[('Water', 0.3839), ('Ethanol', 0.1734)]),\n",
       "    thermal_condition=ThermalCondition(T=373.69, P=202650))"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mixture_enthalpy = vle.mixture.xH(imol, *vle.thermal_condition)\n",
    "vle(H=mixture_enthalpy, P=202650)\n",
    "vle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "VLE(imol=MaterialIndexer(\n",
       "        g=[('Water', 0.3861), ('Ethanol', 0.6139)],\n",
       "        l=[('Water', 0.6139), ('Ethanol', 0.3861)]),\n",
       "    thermal_condition=ThermalCondition(T=353.88, P=101325))"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vle(V=0.5, P=101325)\n",
    "vle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "VLE(imol=MaterialIndexer(\n",
       "        g=[('Water', 0.3886), ('Ethanol', 0.6114)],\n",
       "        l=[('Water', 0.6114), ('Ethanol', 0.3886)]),\n",
       "    thermal_condition=ThermalCondition(T=360.00, P=128136))"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vle(V=0.5, T=360)\n",
    "vle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "VLE(imol=MaterialIndexer(\n",
       "        g=[('Water', 0.8356), ('Ethanol', 0.9589)],\n",
       "        l=[('Water', 0.1644), ('Ethanol', 0.04109)]),\n",
       "    thermal_condition=ThermalCondition(T=356.25, P=128136))"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vle(x=np.array([0.8, 0.2]), P=101325)\n",
    "vle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "VLE(imol=MaterialIndexer(\n",
       "        g=[('Water', 0.4691), ('Ethanol', 0.7036)],\n",
       "        l=[('Water', 0.5309), ('Ethanol', 0.2964)]),\n",
       "    thermal_condition=ThermalCondition(T=356.25, P=126727))"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vle(y=np.array([0.4, 0.6]), T=360)\n",
    "vle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that some compositions are infeasible; so it is not advised to pass x or y unless you know what you're doing:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "ename": "AssertionError",
     "evalue": "desired composition is infeasible",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAssertionError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-16-3d0d3ab197da>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mvle\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0.2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.8\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mP\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m101325\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;32m~\\OneDrive\\Code\\thermosteam\\thermosteam\\equilibrium\\vle.py\u001b[0m in \u001b[0;36m__call__\u001b[1;34m(self, P, H, T, V, x, y)\u001b[0m\n\u001b[0;32m    165\u001b[0m                 \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_PH\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mP\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mH\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    166\u001b[0m             \u001b[1;32melif\u001b[0m \u001b[0mx_spec\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 167\u001b[1;33m                 \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_Px\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mP\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0masarray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    168\u001b[0m             \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;31m# y_spec\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    169\u001b[0m                 \u001b[1;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_Py\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mP\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0masarray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\OneDrive\\Code\\thermosteam\\thermosteam\\equilibrium\\vle.py\u001b[0m in \u001b[0;36mset_Px\u001b[1;34m(self, P, x)\u001b[0m\n\u001b[0;32m    343\u001b[0m         \u001b[1;32massert\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_N\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'number of species in equilibrium must be 2 to specify x'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    344\u001b[0m         \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_thermal_condition\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mT\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_bubble_point\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msolve_Ty\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mP\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 345\u001b[1;33m         \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_lever_rule\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    346\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    347\u001b[0m     \u001b[1;32mdef\u001b[0m \u001b[0mset_Ty\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mT\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m~\\OneDrive\\Code\\thermosteam\\thermosteam\\equilibrium\\vle.py\u001b[0m in \u001b[0;36m_lever_rule\u001b[1;34m(self, x, y)\u001b[0m\n\u001b[0;32m    325\u001b[0m     \u001b[1;32mdef\u001b[0m \u001b[0m_lever_rule\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    326\u001b[0m         \u001b[0msplit_frac\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_z\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m-\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m-\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 327\u001b[1;33m         \u001b[1;32massert\u001b[0m \u001b[1;33m-\u001b[0m\u001b[1;36m0.00001\u001b[0m \u001b[1;33m<\u001b[0m \u001b[0msplit_frac\u001b[0m \u001b[1;33m<\u001b[0m \u001b[1;36m1.00001\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'desired composition is infeasible'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    328\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0msplit_frac\u001b[0m \u001b[1;33m>\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    329\u001b[0m             \u001b[0msplit_frac\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mAssertionError\u001b[0m: desired composition is infeasible"
     ]
    }
   ],
   "source": [
    "vle(x=np.array([0.2, 0.8]), P=101325)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Liquid-liquid equilibrium"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Liquid-liquid equilibrium can be calculated through a LLE object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LLE(imol=MolarFlowIndexer(\n",
       "        L=[('Water', 290.6), ('Octane', 0.02062), ('Butanol', 4.3)],\n",
       "        l=[('Water', 13.35), ('Octane', 99.98), ('Butanol', 25.7)]),\n",
       "    thermal_condition=ThermalCondition(T=360.00, P=101325))"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tmo.settings.set_thermo(['Water', 'Octane', 'Butanol'])\n",
    "imol = tmo.indexer.MolarFlowIndexer(\n",
    "            l=[('Water', 304), ('Butanol', 30)],\n",
    "            L=[('Octane', 100)])\n",
    "lle = tmo.equilibrium.LLE(imol)\n",
    "lle(T=360)\n",
    "lle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pressure is not a significant factor in liquid-liquid equilibrium, so only temperature is needed."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
