diff --git a/.gitignore b/.gitignore index 52b635e92ad15fd50b706c63232d10df9e005dab..1c5289f640ee61bb56cdcd74eec4be819a4bae5b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ /teqp /dev/docker/valgrind/output /dev/docker/gcov/output +/**/.ipynb_checkpoints +/doc/build \ No newline at end of file diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d0c3cbf1020d5c292abdedf27627c6abe25e2293 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..336540f390c1b92359ee637380a838e7c779977a --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,10 @@ + +*************************** +Converted IPython notebooks +*************************** + +.. note:: These static pages were auto-generated from the IPython notebooks residing `here on github <https://github.com/ibell/pdsim/tree/master/doc/notebooks>`_ They can be also be `viewed with nbviewer <http://nbviewer.ipython.org/github/ibell/pdsim/tree/master/doc/notebooks/>`_ + +.. toctree:: + + MultiFluidTutorial diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 0000000000000000000000000000000000000000..dc1312ab09ca6fb0267dee6b28a38e69c253631a --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/source/algorithms/VLE.ipynb b/doc/source/algorithms/VLE.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..7c9400a18cdfcd32106e1e79c2fff357f2e9b973 --- /dev/null +++ b/doc/source/algorithms/VLE.ipynb @@ -0,0 +1,38 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "8218498b", + "metadata": {}, + "source": [ + "# Vapor-liquid equilibria\n", + "\n", + "Two basic approaches are implemented in teqp:\n", + "\n", + "* Iterative calculations given guess values\n", + "* Tracing along curves" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/source/algorithms/index.rst b/doc/source/algorithms/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..57169ed566c6e16605cea6f9d6dea353106dde89 --- /dev/null +++ b/doc/source/algorithms/index.rst @@ -0,0 +1,8 @@ +Algorithms +========== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + VLE \ No newline at end of file diff --git a/doc/source/conf.py b/doc/source/conf.py new file mode 100644 index 0000000000000000000000000000000000000000..5449eb132bd300c674dc79b743197507053894f2 --- /dev/null +++ b/doc/source/conf.py @@ -0,0 +1,56 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'teqp' +copyright = '2022, Ian Bell' +author = 'Ian Bell' + +# The full version, including alpha/beta/rc tags +import teqp +release = teqp.__version__ + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ +'nbsphinx' +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'insipid' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] \ No newline at end of file diff --git a/doc/source/derivs/derivs.ipynb b/doc/source/derivs/derivs.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..7af50d86aa1f0ffc4e236a1302625a49d34749bb --- /dev/null +++ b/doc/source/derivs/derivs.ipynb @@ -0,0 +1,79 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1afc4517", + "metadata": {}, + "source": [ + "# Thermodynamic Derivatives" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "ca35cc29", + "metadata": {}, + "outputs": [], + "source": [ + "import teqp\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8d254c40", + "metadata": {}, + "outputs": [], + "source": [ + "Tc_K = [300]\n", + "pc_Pa = [4e6]\n", + "acentric = [0.01]\n", + "model = teqp.canonical_PR(Tc_K, pc_Pa, acentric)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "49ee3453", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-0.06836660379313926" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "z = np.array([1.0])\n", + "model.get_Ar01(300,300,z)" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/source/derivs/index.rst b/doc/source/derivs/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..8dccdb9bef2cb5289f2817e4eb7020b1b9d4fa0d --- /dev/null +++ b/doc/source/derivs/index.rst @@ -0,0 +1,8 @@ +Derivatives +=========== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + derivs \ No newline at end of file diff --git a/doc/source/index.rst b/doc/source/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..d321eadc912705e22ba4ce5dee5673f3c10c71e5 --- /dev/null +++ b/doc/source/index.rst @@ -0,0 +1,17 @@ +Welcome to teqp's documentation! +================================ + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + derivs/index + models/index + algorithms/index + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/source/models/cubics.ipynb b/doc/source/models/cubics.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..2a597f271e2528c8ae0722657d3172c60345f268 --- /dev/null +++ b/doc/source/models/cubics.ipynb @@ -0,0 +1,43 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "df447d16", + "metadata": {}, + "source": [ + "# Cubic EOS\n", + "\n", + "Something about cubic EOS" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a884dab", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/source/models/index.rst b/doc/source/models/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..355677785073736c8116c9d9e04c2942ef887de9 --- /dev/null +++ b/doc/source/models/index.rst @@ -0,0 +1,9 @@ +Models +====== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + cubics + multifluid diff --git a/doc/source/models/multifluid.ipynb b/doc/source/models/multifluid.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..82d80bca097c09fe06d8ad6f52e7ee59b7db5428 --- /dev/null +++ b/doc/source/models/multifluid.ipynb @@ -0,0 +1,274 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Multi-fluid EOS\n", + "\n", + "Peering into the innards of teqp" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'0.8.1'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import timeit, json\n", + "import pandas\n", + "import numpy as np\n", + "import teqp\n", + "teqp.__version__" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pure fluid loading" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "13.4 ms ± 158 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + ] + } + ], + "source": [ + "# By default teqp looks for fluids relative to the set of fluids in ROOT/dev/fluids\n", + "# The name (case-sensitive) should match the .json file, without the json extension.\n", + "%timeit model = teqp.build_multifluid_model([\"Methane\", \"Ethane\"], teqp.get_datapath())" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "121 ms ± 3.07 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "# And if you provide valid aliases, alias lookup will be used to resolve the name\n", + "# But beware, this is rather a lot slower than the above because all fluid files need to be read\n", + "# in to build the alias map\n", + "%timeit model = teqp.build_multifluid_model([\"n-C1H4\", \"n-C3H8\"], teqp.get_datapath())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So, how to make it faster? Only do it once and cache" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "105 ms ± 968 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" + ] + } + ], + "source": [ + "# Here is the set of possible aliases to absolute paths of files\n", + "# Building this map takes a little while (somewhat faster in C++) due to all the file reads\n", + "# If you know your files will not change, good idea to build this alias map yourself.\n", + "%timeit aliasmap = teqp.build_alias_map(teqp.get_datapath())\n", + "aliasmap = teqp.build_alias_map(teqp.get_datapath())" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "14.1 ms ± 1.12 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + ] + } + ], + "source": [ + "# Then load the absolute paths from the alias map, \n", + "# which will guarantee that you hit exactly what you were looking for,\n", + "# resolving aliases as needed\n", + "identifiers = [aliasmap[n] for n in [\"Neon\", \"Hydrogen\"]]\n", + "%timeit model = teqp.build_multifluid_model(identifiers, teqp.get_datapath())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At some point soon teqp will support in-memory loading of JSON data for the pure components, without requiring reads from the operating system" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# And you can also load the JSON that teqp is loading for the pure fluids\n", + "pureJSON = teqp.collect_component_json(['NEON','HYDROGEN'], teqp.get_datapath())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Mixture model loading" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# Load the default JSON for the binary interaction parameters\n", + "BIP = json.load(open(teqp.get_datapath()+'/dev/mixtures/mixture_binary_pairs.json'))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'BibTeX': 'Kunz-JCED-2012',\n", + " 'CAS1': '74-82-8',\n", + " 'CAS2': '74-84-0',\n", + " 'F': 1.0,\n", + " 'Name1': 'Methane',\n", + " 'Name2': 'Ethane',\n", + " 'betaT': 0.996336508,\n", + " 'betaV': 0.997547866,\n", + " 'function': 'Methane-Ethane',\n", + " 'gammaT': 1.049707697,\n", + " 'gammaV': 1.006617867}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# You can obtain interaction parameters either by pairs of names, where name is the name that teqp uses, the [\"INFO\"][\"NAME\"] field\n", + "params, swap_needed = teqp.get_BIPdep(BIP, ['Methane','Ethane'])\n", + "params" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'BibTeX': 'Kunz-JCED-2012',\n", + " 'CAS1': '74-82-8',\n", + " 'CAS2': '74-84-0',\n", + " 'F': 1.0,\n", + " 'Name1': 'Methane',\n", + " 'Name2': 'Ethane',\n", + " 'betaT': 0.996336508,\n", + " 'betaV': 0.997547866,\n", + " 'function': 'Methane-Ethane',\n", + " 'gammaT': 1.049707697,\n", + " 'gammaV': 1.006617867}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Or also by CAS#\n", + "params, swap_needed = teqp.get_BIPdep(BIP, ['74-82-8','74-84-0'])\n", + "params" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "Can't match the binary pair for: 74-82-8/Ethane", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", + "Input \u001b[1;32mIn [10]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;66;03m# But mixing is not allowed\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m params, swap_needed \u001b[38;5;241m=\u001b[39m \u001b[43mteqp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_BIPdep\u001b[49m\u001b[43m(\u001b[49m\u001b[43mBIP\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m74-82-8\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mEthane\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 3\u001b[0m params\n", + "\u001b[1;31mValueError\u001b[0m: Can't match the binary pair for: 74-82-8/Ethane" + ] + } + ], + "source": [ + "# But mixing is not allowed\n", + "params, swap_needed = teqp.get_BIPdep(BIP, ['74-82-8','Ethane'])\n", + "params" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}