{ "cells": [ { "cell_type": "markdown", "id": "0a70636a", "metadata": {}, "source": [ "# Inverse chemical equilibrium calculations\n", "\n", "This tutorial demonstrates how to use Reaktoro to perform *inverse chemical\n", "equilibrium calculations*.\n", "\n", "In an inverse chemical equilibrium problem, not all elements have known\n", "amounts. Instead of fully specifying their amounts, we impose one or more\n", "equilibrium constraints such as fixed species amount, fixed species activity,\n", "fixed volume of a phase, fixed pH of an aqueous solution; the possibilities\n", "are many.\n", "\n", "Since the amounts of elements are not known a priori, an inverse equilibrium\n", "calculation tries to determine amounts of titrants that can control the\n", "specified equilibrium constraints. The amounts of the titrants are unknown,\n", "and its addition or removal is done over the calculation so that the\n", "equilibrium state is driven towards a state where all given equilibrium\n", "constraints are satisfied.\n", "\n", "Below we create a chemical system containing an aqueous phase, a gaseous\n", "phase, and a mineral phase." ] }, { "cell_type": "code", "execution_count": null, "id": "b459c882", "metadata": {}, "outputs": [], "source": [ "from reaktoro import *\n", "\n", "db = Database(\"supcrt98.xml\")\n", "\n", "editor = ChemicalEditor(db)\n", "editor.addAqueousPhaseWithElements(\"H O Na Cl Ca Mg C\");\n", "editor.addGaseousPhaseWithElements(\"H O C\");\n", "editor.addMineralPhase(\"Calcite\")\n", "\n", "system = ChemicalSystem(editor)" ] }, { "cell_type": "markdown", "id": "a1729b25", "metadata": {}, "source": [ "> Check previous tutorials to learn the steps above! For example,\n", "> [Basics of equilibrium calculation](eq.equilibrium-basics.ipynb),\n", "> [Equilibrium calculation of carbonate species](eq.equilibrium-carbonates.ipynb),\n", "> [Equilibrium calculations using equilibrium solver](eq.co2-brine-using-equilibrium-solver.ipynb), or\n", "> [Custom activity model for equilibrium calculations](eq.custom-activity-models.ipynb)." ] }, { "cell_type": "markdown", "id": "3d7e85ba", "metadata": {}, "source": [ "#### Equilibrium problem with fixed pH, species amount, and species activity\n", "\n", "In this problem, we fix the pH of the aqueous solution to 3, and specify that\n", "HCl is the titrant that should be added or removed so that this constraint is\n", "satisfied. Therefore, the amounts of H and Cl are not known in advance.\n", "\n", "To obtain an aqueous solution saturated with CO2, we also add a\n", "constraint that enforces 1 mol for the amount of gaseous species\n", "CO2(g) at equilibrium.\n", "\n", "Finally, we add an activity constraint for gaseous species O2(g).\n", "This is equivalent to enforcing the fugacity of the gas." ] }, { "cell_type": "code", "execution_count": null, "id": "387ebcee", "metadata": {}, "outputs": [], "source": [ "problem1 = EquilibriumInverseProblem(system)\n", "problem1.add(\"H2O\", 1, \"kg\")\n", "problem1.add(\"NaCl\", 0.1, \"mol\")\n", "problem1.add(\"CaCl2\", 2, \"mmol\")\n", "problem1.add(\"MgCl2\", 4, \"mmol\")\n", "problem1.pH(3.0, \"HCl\")\n", "problem1.fixSpeciesAmount(\"CO2(g)\", 1.0, \"mol\")\n", "problem1.fixSpeciesActivity(\"O2(g)\", 0.20)\n", "\n", "state1 = equilibrate(problem1)\n", "\n", "state1.output(\"state1.txt\")" ] }, { "cell_type": "markdown", "id": "69512531", "metadata": { "lines_to_next_cell": 2 }, "source": [ "> Check [EquilibriumInverseProblem](\n", "https://reaktoro.org/cpp/classReaktoro_1_1EquilibriumInverseProblem.html) to learn more about all possible\n", "equilibrium constraints currently supported.\n", "\n", "> Check the output file `state1.txt` and check whether the constraints were\n", "> successfully satisfied. We plan to output these files in HTML format so that it can be more conveniently inspected." ] }, { "cell_type": "markdown", "id": "39f078e1", "metadata": {}, "source": [ "#### Equilibrium problem with fixed pH controlled by CO2\n", "\n", "The second equilibrium inverse problem has similar conditions to those used\n", "for the first problem. However, in this case, we fix pH to be equal to 4.0,\n", "with CO2 being the titrant whose amount to be added into the system\n", "is unknown in advance." ] }, { "cell_type": "code", "execution_count": null, "id": "549680b1", "metadata": {}, "outputs": [], "source": [ "problem2 = EquilibriumInverseProblem(system)\n", "problem2.add(\"H2O\", 1, \"kg\")\n", "problem2.add(\"NaCl\", 0.1, \"mol\")\n", "problem2.add(\"CaCl2\", 2, \"mmol\")\n", "problem2.add(\"MgCl2\", 4, \"mmol\")\n", "problem2.pH(4.0, \"CO2\")\n", "\n", "state2 = equilibrate(problem2)\n", "\n", "state2.output(\"state2.txt\")" ] }, { "cell_type": "markdown", "id": "1fa730bc", "metadata": { "lines_to_next_cell": 2 }, "source": [ "> Check the output file `state2.txt` and make sure whether the constraints were successfully satisfied." ] }, { "cell_type": "markdown", "id": "14a06fee", "metadata": {}, "source": [ "#### Equilibrium problem with fixed pH controlled by either HCl or NaOH\n", "\n", "In this equilibrium problem, we also fix the pH of the aqueous solution, but we\n", "specify that this constraint is to be satisfied by titrating either HCl or\n", "NaOH (not both!)." ] }, { "cell_type": "code", "execution_count": null, "id": "3ee6442f", "metadata": {}, "outputs": [], "source": [ "problem3 = EquilibriumInverseProblem(system)\n", "problem3.add(\"H2O\", 1.0, \"kg\")\n", "problem3.add(\"NaCl\", 0.1, \"mol\")\n", "problem3.add(\"Calcite\", 1.0, \"mol\")\n", "problem3.pH(8.0, \"HCl\", \"NaOH\")\n", "\n", "state3 = equilibrate(problem3)\n", "\n", "state3.output(\"state3.txt\")" ] }, { "cell_type": "markdown", "id": "c7bdbbec", "metadata": {}, "source": [ "> Check the output file `state3.txt` and control whether the constraints were\n", "> successfully satisfied." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 5 }