mirror of https://github.com/ANL-CEEESA/LLEPE
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
534 lines
36 KiB
534 lines
36 KiB
{
|
|
"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<br/>\n",
|
|
"```$ git clone https://xgitlab.cels.anl.gov/summer-2020/parameter-estimation.git```<br/>\n",
|
|
"Navigate into the folder with <br/>\n",
|
|
"```$ cd parameter-estimation```<br/>\n",
|
|
"And run <br/>\n",
|
|
"```pip install -e.```<br/>\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. <br/>\n",
|
|
"Let us explore the format of this file with pandas"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<div>\n",
|
|
"<style scoped>\n",
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|
" vertical-align: middle;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe tbody tr th {\n",
|
|
" vertical-align: top;\n",
|
|
" }\n",
|
|
"\n",
|
|
" .dataframe thead th {\n",
|
|
" text-align: right;\n",
|
|
" }\n",
|
|
"</style>\n",
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|
" <thead>\n",
|
|
" <tr style=\"text-align: right;\">\n",
|
|
" <th></th>\n",
|
|
" <th>HI(m)</th>\n",
|
|
" <th>REeq(m)</th>\n",
|
|
" <th>D(m)</th>\n",
|
|
" <th>ZI(m)</th>\n",
|
|
" <th>Zeq</th>\n",
|
|
" <th>Heq</th>\n",
|
|
" <th>REI</th>\n",
|
|
" </tr>\n",
|
|
" </thead>\n",
|
|
" <tbody>\n",
|
|
" <tr>\n",
|
|
" <th>0</th>\n",
|
|
" <td>0.01</td>\n",
|
|
" <td>0.0239</td>\n",
|
|
" <td>1.0921</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.921696</td>\n",
|
|
" <td>0.088304</td>\n",
|
|
" <td>0.050001</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>1</th>\n",
|
|
" <td>0.01</td>\n",
|
|
" <td>0.0683</td>\n",
|
|
" <td>0.4641</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.904906</td>\n",
|
|
" <td>0.105094</td>\n",
|
|
" <td>0.099998</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>2</th>\n",
|
|
" <td>0.01</td>\n",
|
|
" <td>0.1170</td>\n",
|
|
" <td>0.2821</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.900983</td>\n",
|
|
" <td>0.109017</td>\n",
|
|
" <td>0.150006</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>3</th>\n",
|
|
" <td>0.01</td>\n",
|
|
" <td>0.1680</td>\n",
|
|
" <td>0.1905</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.903988</td>\n",
|
|
" <td>0.106012</td>\n",
|
|
" <td>0.200004</td>\n",
|
|
" </tr>\n",
|
|
" <tr>\n",
|
|
" <th>4</th>\n",
|
|
" <td>0.01</td>\n",
|
|
" <td>0.2637</td>\n",
|
|
" <td>0.1377</td>\n",
|
|
" <td>1</td>\n",
|
|
" <td>0.891066</td>\n",
|
|
" <td>0.118934</td>\n",
|
|
" <td>0.300011</td>\n",
|
|
" </tr>\n",
|
|
" </tbody>\n",
|
|
"</table>\n",
|
|
"</div>"
|
|
],
|
|
"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. <br/>\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.<br/>\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. <br/>\n",
|
|
"Please see parameter-estimation/data/xmls for file examples. <br/>\n",
|
|
"We can explore what has been loaded."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {
|
|
"scrolled": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"[<cantera.composite.Solution object at 0x0000022879F97128>, <cantera.composite.Solution object at 0x0000022879F97358>]\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.<br/> \n",
|
|
"The number after the thermodynamic property is the initial guess for the optimizer. <br/> \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, <br/> \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.<br/> 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. <br/> 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.<br/>\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": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"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
|
|
}
|