From a56402df4eb7444676fc6163bc02e047bfef8bc8 Mon Sep 17 00:00:00 2001 From: Ian Bell <ian.bell@nist.gov> Date: Fri, 4 Nov 2022 18:03:48 -0400 Subject: [PATCH] Add I&ECR examples to docs --- doc/source/examples/IECR examples.ipynb | 198 ++++++++++++++++++++++++ doc/source/examples/index.rst | 8 + doc/source/index.rst | 1 + 3 files changed, 207 insertions(+) create mode 100644 doc/source/examples/IECR examples.ipynb create mode 100644 doc/source/examples/index.rst diff --git a/doc/source/examples/IECR examples.ipynb b/doc/source/examples/IECR examples.ipynb new file mode 100644 index 0000000..65a6de2 --- /dev/null +++ b/doc/source/examples/IECR examples.ipynb @@ -0,0 +1,198 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1e108f86", + "metadata": {}, + "source": [ + "# The teqp paper in I&ECR \n", + "\n", + "A few minor changes have been made:\n", + " \n", + "* The ``get_splus`` method requires the molar concentrations to be a numpy array (to avoid copies) (as of version 0.14.0\n", + "* The top-level methods ``teqp.xxx`` have been deprecated, and the methods attached to the instance are preferred" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9539423f", + "metadata": {}, + "outputs": [], + "source": [ + "import timeit, numpy as np\n", + "import matplotlib.pyplot as plt\n", + "plt.style.use('classic')\n", + "import teqp\n", + "\n", + "def build_models():\n", + " Tc_K, pc_Pa, acentric = 647.096, 22064000.0, 0.3442920843\n", + "\n", + " water = {\n", + " \"a0i / Pa m^6/mol^2\": 0.12277 , \"bi / m^3/mol\": 0.000014515, \"c1\": 0.67359, \n", + " \"Tc / K\": 647.096, \"epsABi / J/mol\": 16655.0, \"betaABi\": 0.0692, \"class\": \"4C\"\n", + " }\n", + " j = {\"cubic\": \"SRK\", \"pures\": [water], \"R_gas / J/mol/K\": 8.3144598}\n", + "\n", + " datapath = teqp.get_datapath()\n", + " def get_PCSAFT():\n", + " c = teqp.SAFTCoeffs()\n", + " # Values from https://doi.org/10.1016/j.fluid.2017.11.015, \n", + " # but association contribution is ignored\n", + " c.name = 'Water'\n", + " c.m = 2.5472\n", + " c.sigma_Angstrom = 2.1054\n", + " c.epsilon_over_k = 138.63\n", + " return teqp.PCSAFTEOS(coeffs=[c])\n", + " \n", + " return [\n", + " ('vdW', teqp.vdWEOS([Tc_K], [pc_Pa])),\n", + " ('PR', teqp.canonical_PR([Tc_K], [pc_Pa], [acentric])),\n", + " ('SRK', teqp.canonical_SRK([Tc_K], [pc_Pa], [acentric])),\n", + " ('PCSAFT', get_PCSAFT()),\n", + " ('CPA', teqp.CPAfactory(j)),\n", + " ('IAPWS', teqp.build_multifluid_model([\"Water\"], datapath))\n", + " ]\n", + "\n", + "fig, ax = plt.subplots(1,1,figsize=(7,6))\n", + "T = 700 # K\n", + "rhovec = np.geomspace(0.1, 30e3, 10000) # mol/m^3; critical density is 17873.8... mol/m^3\n", + "tic = timeit.default_timer()\n", + "for abbrv, model in build_models():\n", + " splus = np.array([model.get_splus(T, np.array([rho])) for rho in rhovec])\n", + " plt.plot(rhovec, splus, label=abbrv, lw = 1.5 if abbrv=='IAPWS' else 1)\n", + "elap = timeit.default_timer()-tic\n", + "plt.axvline(17873.8, dashes=[2,2])\n", + "plt.legend(loc='best')\n", + "plt.gca().set(xlabel=r'$\\rho$ / mol/m$^3$', ylabel=r'$s^+\\equiv (s^{\\rm ig}(T,\\rho)-s(T,\\rho))/R$')\n", + "plt.tight_layout(pad=0.2)\n", + "plt.gcf().text(0,0,f'time: {elap:0.1f} s', ha='left', va='bottom', fontsize=7)\n", + "plt.gcf().text(1,0,f'teqp: {teqp.__version__}', ha='right', va='bottom', fontsize=7)\n", + "plt.savefig('splus_water_700K.pdf')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb28d259", + "metadata": {}, + "outputs": [], + "source": [ + "import json, timeit\n", + "import pandas, numpy as np, matplotlib.pyplot as plt\n", + "plt.style.use('classic')\n", + "import teqp\n", + "\n", + "Tc_K = [190.564, 154.581]\n", + "pc_Pa = [4599200, 5042800]\n", + "acentric = [0.011, 0.022]\n", + "model = teqp.canonical_PR(Tc_K, pc_Pa, acentric)\n", + "fig, ax = plt.subplots(1,1,figsize=(7, 6), subplot_kw=dict(projection='3d'))\n", + "tic = timeit.default_timer()\n", + "for ifluid in [0,1]:\n", + " model0 = teqp.canonical_PR([Tc_K[ifluid]], [pc_Pa[ifluid]], [acentric[ifluid]])\n", + " for T in np.linspace(190, 120, 50):\n", + " if T > Tc_K[ifluid]: continue\n", + " [rhoL, rhoV] = model0.superanc_rhoLV(T)\n", + " rhovecL = np.array([0.0, 0.0]); rhovecL[ifluid] = rhoL\n", + " rhovecV = np.array([0.0, 0.0]); rhovecV[ifluid] = rhoV\n", + " opt = teqp.TVLEOptions(); opt.calc_criticality = True\n", + " df = pandas.DataFrame(model.trace_VLE_isotherm_binary(T, rhovecL, rhovecV, opt))\n", + " df['too_critical'] = df.apply(\n", + " lambda row: (abs(row['crit. conditions L'][0]) < 5e-8), axis=1)\n", + " first_too_critical = np.argmax(df['too_critical'])\n", + " df = df.iloc[0:(first_too_critical if first_too_critical else len(df))]\n", + " line, = ax.plot(xs=df['T / K'], ys=df['xL_0 / mole frac.'], zs=df['pL / Pa']/1e6, \n", + " lw=0.2, color='k')\n", + " ax.plot(xs=df['T / K'], ys=df['xV_0 / mole frac.'], zs=df['pL / Pa']/1e6, \n", + " dashes=[2,2], color=line.get_color(), lw=0.2)\n", + "elap = timeit.default_timer()-tic\n", + "ax.view_init(elev=10., azim=130)\n", + "ax.set(xlabel='$T$ / K', ylabel='$x_1$ / mole frac.', zlabel='$p$ / MPa')\n", + "fig.text(0,0,f'time: {elap:0.1f} s', ha='left', va='bottom', fontsize=7)\n", + "fig.text(1,0,f'teqp: {teqp.__version__}', ha='right', va='bottom', fontsize=7)\n", + "plt.tight_layout(pad=0.2)\n", + "plt.savefig('PR_VLE_trace.pdf')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cbe191dd", + "metadata": {}, + "outputs": [], + "source": [ + "import timeit\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt \n", + "plt.style.use('classic')\n", + "import pandas\n", + "import teqp\n", + "\n", + "def get_critical_curve(ipure):\n", + " \"\"\" Return curve as pandas DataFrame \"\"\"\n", + " names = ['Nitrogen', 'Ethane']\n", + " model = teqp.build_multifluid_model(names, teqp.get_datapath())\n", + " T0 = model.get_Tcvec()[ipure]\n", + " rho0 = np.array([1.0/model.get_vcvec()[ipure]]*2)\n", + " rho0[1-ipure] = 0\n", + " o = teqp.TCABOptions() \n", + " o.init_dt = 1.0 # step in the parameter\n", + " o.rel_err = 1e-8\n", + " o.abs_err = 1e-5\n", + " o.integration_order = 5\n", + " o.calc_stability = True\n", + " o.polish = True\n", + " curveJSON = model.trace_critical_arclength_binary(T0, rho0, '', o)\n", + " df = pandas.DataFrame(curveJSON)\n", + " rhotot = df['rho0 / mol/m^3']+df['rho1 / mol/m^3']\n", + " df['z0 / mole frac.'] = df['rho0 / mol/m^3']/rhotot\n", + " return df\n", + "\n", + "if __name__ == '__main__':\n", + " fig, ax = plt.subplots(1,1,figsize=(7, 6))\n", + " tic = timeit.default_timer()\n", + " for ipure in [1,0]:\n", + " df = get_critical_curve(ipure)\n", + " first_unstable = np.argmax(~df['locally stable'])\n", + " df = df.iloc[0:(first_unstable if first_unstable else len(df))]\n", + " line, = plt.plot(df['T / K'], df['p / Pa']/1e6, '-')\n", + " plt.plot(df['T / K'].iloc[0], df['p / Pa'].iloc[0]/1e6, 'd', \n", + " color=line.get_color())\n", + "\n", + " elap = timeit.default_timer()-tic\n", + " plt.gca().set(xlabel='$T$ / K', ylabel='$p$ / MPa',\n", + " xlim=(100, 350), ylim=(1, 1e3))\n", + " plt.yscale('log')\n", + " plt.tight_layout(pad=0.2)\n", + " plt.gcf().text(0,0,f'time: {elap:0.1f} s', ha='left', va='bottom', fontsize=7)\n", + " plt.gcf().text(1,0,f'teqp: {teqp.__version__}', ha='right', va='bottom', fontsize=7)\n", + " plt.savefig('N2_ethane_critical.pdf')\n", + " plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/source/examples/index.rst b/doc/source/examples/index.rst new file mode 100644 index 0000000..0be3570 --- /dev/null +++ b/doc/source/examples/index.rst @@ -0,0 +1,8 @@ +Examples +========== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + IECR_examples \ No newline at end of file diff --git a/doc/source/index.rst b/doc/source/index.rst index c537fab..24647d1 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -10,6 +10,7 @@ Welcome to teqp's documentation! derivs/index algorithms/index api/modules + examples/index Indices and tables ================== -- GitLab