From 07d6a0ac3c65757475045cb93806b4a496619c12 Mon Sep 17 00:00:00 2001
From: titusquah <46580668+titusquah@users.noreply.github.com>
Date: Fri, 5 Jun 2020 14:22:19 -0600
Subject: [PATCH] added docs
---
.../1_getting_started-checkpoint.ipynb | 6 +
docs/Examples/1_getting_started.ipynb | 533 ++++++++++++++++++
2 files changed, 539 insertions(+)
create mode 100644 docs/Examples/.ipynb_checkpoints/1_getting_started-checkpoint.ipynb
create mode 100644 docs/Examples/1_getting_started.ipynb
diff --git a/docs/Examples/.ipynb_checkpoints/1_getting_started-checkpoint.ipynb b/docs/Examples/.ipynb_checkpoints/1_getting_started-checkpoint.ipynb
new file mode 100644
index 0000000..7fec515
--- /dev/null
+++ b/docs/Examples/.ipynb_checkpoints/1_getting_started-checkpoint.ipynb
@@ -0,0 +1,6 @@
+{
+ "cells": [],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/docs/Examples/1_getting_started.ipynb b/docs/Examples/1_getting_started.ipynb
new file mode 100644
index 0000000..6f93a81
--- /dev/null
+++ b/docs/Examples/1_getting_started.ipynb
@@ -0,0 +1,533 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# REEPS Tutorial - Getting started\n",
+ "## Introduction\n",
+ "In this notebook, you will learn how to use REEPS to fit thermodynamic parameters to experimental data and explore how well the parameters fit.\n",
+ "## Installation\n",
+ "In your terminal run
\n",
+ "```$ git clone https://xgitlab.cels.anl.gov/summer-2020/parameter-estimation.git```
\n",
+ "Navigate into the folder with
\n",
+ "```$ cd parameter-estimation```
\n",
+ "And run
\n",
+ "```pip install -e.```
\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Import and instantiate REEPS"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "First, you will need to import the package and instantiate REEPS with a few parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import sys # Navigating to reeps.py since not a package yet\n",
+ "sys.path.append('../../')\n",
+ "from reeps import REEPS\n",
+ "searcher_parameters = {'exp_csv_filename': '../../data/csvs/exp_data.csv',\n",
+ " 'phases_xml_filename': '../../data/xmls/twophase.xml',\n",
+ " 'opt_dict': {'Nd(H(A)2)3(org)': {'h0': -4662344.64}},\n",
+ " 'phase_names': ['HCl_electrolyte', 'PC88A_liquid'],\n",
+ " 'aq_solvent_name': 'H2O(L)',\n",
+ " 'extractant_name': '(HA)2(org)',\n",
+ " 'diluant_name': 'dodecane',\n",
+ " 'complex_name': 'Nd(H(A)2)3(org)',\n",
+ " 'rare_earth_ion_name': 'Nd+++',\n",
+ " 'aq_solvent_rho': 1000.0,\n",
+ " 'extractant_rho': 960.0,\n",
+ " 'diluant_rho': 750.0}\n",
+ "searcher = REEPS(**searcher_parameters)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Parameters explanation "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### exp_csv_filename"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "exp_csv_filename is the file name for the csv containing experimental data.
\n",
+ "Let us explore the format of this file with pandas"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " HI(m) | \n",
+ " REeq(m) | \n",
+ " D(m) | \n",
+ " ZI(m) | \n",
+ " Zeq | \n",
+ " Heq | \n",
+ " REI | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 0.01 | \n",
+ " 0.0239 | \n",
+ " 1.0921 | \n",
+ " 1 | \n",
+ " 0.921696 | \n",
+ " 0.088304 | \n",
+ " 0.050001 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 0.01 | \n",
+ " 0.0683 | \n",
+ " 0.4641 | \n",
+ " 1 | \n",
+ " 0.904906 | \n",
+ " 0.105094 | \n",
+ " 0.099998 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 0.01 | \n",
+ " 0.1170 | \n",
+ " 0.2821 | \n",
+ " 1 | \n",
+ " 0.900983 | \n",
+ " 0.109017 | \n",
+ " 0.150006 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 0.01 | \n",
+ " 0.1680 | \n",
+ " 0.1905 | \n",
+ " 1 | \n",
+ " 0.903988 | \n",
+ " 0.106012 | \n",
+ " 0.200004 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 0.01 | \n",
+ " 0.2637 | \n",
+ " 0.1377 | \n",
+ " 1 | \n",
+ " 0.891066 | \n",
+ " 0.118934 | \n",
+ " 0.300011 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " HI(m) REeq(m) D(m) ZI(m) Zeq Heq REI\n",
+ "0 0.01 0.0239 1.0921 1 0.921696 0.088304 0.050001\n",
+ "1 0.01 0.0683 0.4641 1 0.904906 0.105094 0.099998\n",
+ "2 0.01 0.1170 0.2821 1 0.900983 0.109017 0.150006\n",
+ "3 0.01 0.1680 0.1905 1 0.903988 0.106012 0.200004\n",
+ "4 0.01 0.2637 0.1377 1 0.891066 0.118934 0.300011"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import pandas as pd\n",
+ "exp_df = pd.read_csv(searcher_parameters['exp_csv_filename'])\n",
+ "exp_df"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The rows are for experiments, and the columns are for the measured quantaties.
\n",
+ "REEPS is looking for the ordering of these columns so it is important your experimental file has this ordering. Column names do not matter.
\n",
+ "Below is a table explaining the meaning of the column headers"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "| Column | Meaning |\n",
+ "|---------|-----------------------------------------------------------------------------------------|\n",
+ "| HI(m) | Initial Concentration of H+ ions (mol/L) |\n",
+ "| REeq(m) | Equilibrium concentration of Rare Earth ions (mol/L) |\n",
+ "| D(m) | Equilibrium Ratio between amount of rare earth elements in organic to amount in aqueous |\n",
+ "| ZI(m) | Initial concentration of extractant (mol/L) |\n",
+ "| Zeq | Equilibrium concentration of extractant (mol/L) |\n",
+ "| Heq | Equilibrium concentration of H+ ions (mol/L) |\n",
+ "| REI | Initial concentration of rare earth ions (mol/L) |"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### phases_xml_filename"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This is the xml file containing information to be loaded into Cantera, the thermodynamic modeling package.
\n",
+ "Please see parameter-estimation/data/xmls for file examples.
\n",
+ "We can explore what has been loaded."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[, ]\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(searcher.get_phases())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "It is a list of two Cantera solutions so we will dig in a little further and see what species these solutions contain."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "HCl_electrolyte\n",
+ "['H2O(L)', 'H+', 'OH-', 'Cl-', 'Nd+++']\n",
+ "PC88A_liquid\n",
+ "['(HA)2(org)', 'dodecane', 'Nd(H(A)2)3(org)']\n"
+ ]
+ }
+ ],
+ "source": [
+ "for phase in searcher.get_phases():\n",
+ " print(phase.name)\n",
+ " print(phase.species_names)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "You can explore Cantera solutions further by visiting https://cantera.org/ and seeing Cantera's documentation."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### opt_dict"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This is a dictionary that contains the information about what species and what thermodynamic properties are to be modified.
\n",
+ "The number after the thermodynamic property is the initial guess for the optimizer.
\n",
+ "In this example, we chose to optimize the standard enthalpy (h0) of the neodymium-PC88A complex ('Nd(H(A)2)3(org)') and give it an initial guess of -4662344.64. Thus,
\n",
+ "```python \n",
+ "opt_dict={'Nd(H(A)2)3(org)': {'h0': -4662344.64}}```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Say we wanted to also modify the extractant ('(HA)2(org)'), but this time change both the standard enthalpy (h0) and the molar volume (molarVolume), then the dictionary would be\n",
+ "```python \n",
+ "opt_dict={'Nd(H(A)2)3(org)': {'h0': -4662344.64, 'molarVolume':1.01},\n",
+ " '(HA)2(org)': {'h0': -4662344.64, 'molarVolume':1.01}}```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### phase_names"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This a list of the phase names in the xml file and can be found in the field phase id."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Names and rhos"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "| Parameter | Meaning | Example value |\n",
+ "|---------------------|----------------------------------------------|-------------------|\n",
+ "| aq_solvent_name | Name of solvent in aqueous phase | 'H2O(L)' |\n",
+ "| extractant_name | Name of extractant in organic phase | '(HA)2(org)' |\n",
+ "| diluant_name | Name of diluant in organic phase | 'dodecane' |\n",
+ "| complex_name | Name of rare earth complex in organic phase | 'Nd(H(A)2)3(org)' |\n",
+ "| rare_earth_ion_name | Name of rare earth ion name in aqueous phase | 'Nd+++' |\n",
+ "| rhos | Density of species (g/L) | 1000 for 'H2O(L)' |"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "For the variables containing \"rho\", these parameters can be left \"None\", and molecular weight and molar volume will be used to calculate density.
However, molar volume values may be wrong and mess up calculations so it is recommended to find density values and replace the default values."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Fitting thermodynamic properties to data"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now that the thermodynamic properties have been set, we now need to set up the optimizer.
The default optimizer is from scipy.optimize.minimize with the arguments below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "minimizer_kwargs = {\"method\": 'SLSQP',\n",
+ " \"bounds\": [(1e-1, 1e1)],\n",
+ " \"constraints\": (),\n",
+ " \"options\": {'disp': True, \n",
+ " 'maxiter': 1000, \n",
+ " 'ftol': 1e-6}}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "With the minimizer arguments defined, we can perform our fit.
\n",
+ "This minimizes the log mean squared error between the predicted and experimental Distribution ratio (D)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Optimization terminated successfully. (Exit mode 0)\n",
+ " Current function value: 0.025193550841886146\n",
+ " Iterations: 5\n",
+ " Function evaluations: 19\n",
+ " Gradient evaluations: 5\n",
+ "{'Nd(H(A)2)3(org)': {'h0': -4704703.645715787}}\n"
+ ]
+ }
+ ],
+ "source": [
+ "est_enthalpy = searcher.fit()\n",
+ "print(est_enthalpy)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can see that the fit function returns an identical structure to opt_dict"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Updating the xml"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now we have our new values, let us write them to our original xml to replace the old values"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "searcher.update_xml(est_enthalpy)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Visualization and analysis"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can also see how well this new xml data fits to the experimental data with a parity plot."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "searcher.parity_plot()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can also find what the r-squared value is. The closer to 1, the better the prediction model."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0.997071413389365\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(searcher.r_squared())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Yay! Good job! That is an amazing fit."
+ ]
+ }
+ ],
+ "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.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}