Solving equilibria
There are two 'layers' of solver in Pytzer: stoichiometric and thermodynamic.
The stoichiometric solver determines the molality of each solute given a set of total molalities and fixed stoichiometric equilibrium constants. It uses a NewtonRaphson iterative method that is fully compatible with JAX.
The thermodynamic solver wraps the stoichiometric solver and adjusts the stoichiometric equilibrium constants to agree with thermodynamic constraints. Because it uses scipy.optimize.root
, it cannot be yet^{1} differentiated or compiled with JAX.
You can solve equilibria using the following functions. Lowerlevel approaches with more fine control are possible, but not yet documented.
Solve a single solution
You can solve a single solution for equilibrium using pz.solve
:
solutes, pks_constants = pz.solve(
totals,
exclude_equilibria=None,
ks_constants=None,
ks_only=None,
library=Seawater,
pressure=10.10325,
temperature=298.15,
verbose=False,
)
Arguments
totals
is anOrderedDict
of the total molality of each group of components in the solution. Nonequilibrating components are included too. Equilibrating components are grouped as follows:totals["CO2"]
= sum of all carbonate species.totals["PO4"]
= sum of all phosphate species.totals["F"]
= sum of all fluoride species.totals["SO4"]
= sum of all sulfate species.totals["BOH3"]
= sum of all borate species.totals["NH3"]
= sum of all ammonia species.totals["H2S"]
= sum of all sulfide species.totals["NO2"]
= sum of all nitrite species.totals["H4SiO4"]
= sum of all silicate species.totals["Mg"]
= sum of all magnesium species.totals["Ca"]
= sum of all calcium species.totals["Sr"]
= sum of all strontium species.
exclude_equilibria
allows you to list equilibria that will not be included in the model.ks_constants
allows you to provide your own initialguess values of the stoichiometric equilibrium constants, as adict
.ks_only
allows you to list equilibria for which the thermodyamic constants are not used (i.e. the initial stoichiometric constants are kept constant).library
is theParameterLibrary
that you want to use.pressure
is the pressure in dbar.temperature
is the temperature in K.verbose
controls how much information is sent to stdout.
Results
solutes
is anOrderedDict
of the molality of each component at thermodynamic equilibrium.ks_constants
is adict
of the stoichiometric equilibrium constants at thermodynamic equilibrium.
Solve a pandas DataFrame
You can put the totals
described above into columns of a pandas DataFrame (df
), add columns for "temperature"
(in K) and "pressure"
(in dbar) if needed, and then solve all the rows in the DataFrame with pz.solve_df
:
pz.solve_df(
df,
exclude_equilibria=None,
inplace=True,
ks_only=None,
library=Seawater,
verbose=False,
)

We are planning to merge the two solvers together, making the entire program gradable and jitable by JAX, in a future release. ↩