From 7834dae6682ab9dcfa83584bf9bdaaaa97122237 Mon Sep 17 00:00:00 2001 From: Ryan Kingsbury Date: Tue, 25 Jul 2023 16:43:09 -0400 Subject: [PATCH] Solution: add pE and pH properties --- CHANGELOG.md | 1 + src/pyEQL/solution.py | 19 ++++++++++++++++--- tests/test_pyeql_volume_concentration.py | 4 ++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d86265c4..d5fd0145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 0.6.0 (in progress) +- `Solution`: add `pE` and `pH` properties - `Solution`: add support for passing solutes as a `dict` - Implement extensible system for connecting `Solution` to various activity and speciation models. Models can be integrated into pyEQL by implementing an `EOS` class. The desired activity model is selected on init. diff --git a/src/pyEQL/solution.py b/src/pyEQL/solution.py index d6dd9cbd..5bc6b448 100644 --- a/src/pyEQL/solution.py +++ b/src/pyEQL/solution.py @@ -15,7 +15,7 @@ from iapws import IAPWS95 from monty.dev import deprecated -from pint import DimensionalityError +from pint import DimensionalityError, Quantity # internal pyEQL imports import pyEQL.solute as sol @@ -58,6 +58,7 @@ def __init__( temperature: str = "298.15 K", pressure: str = "1 atm", pH: float = 7, + pE: float = 8.5, engine: Literal["native", "ideal"] = "native", **kwargs, ): @@ -89,6 +90,10 @@ def __init__( Negative log of H+ activity. If omitted, the solution will be initialized to pH 7 (neutral) with appropriate quantities of H+ and OH- ions + pe: the pE value (redox potential) of the solution. Lower values = more reducing, + higher values = more oxidizing. At pH 7, water is stable between approximately + -7 to +14. The default value corresponds to a pE value typical of natural + waters in equilibrium with the atmosphere. Examples: >>> s1 = pyEQL.Solution([['Na+','1 mol/L'],['Cl-','1 mol/L']],temperature='20 degC',volume='500 mL') @@ -111,6 +116,7 @@ def __init__( self.volume = unit("1 L") self._temperature = unit(temperature) self._pressure = unit(pressure) + self.pE = pE # instantiate a water substance for property retrieval self.water_substance = IAPWS95( @@ -265,7 +271,7 @@ def get_solvent(self): return self.components[self.solvent_name] @property - def temperature(self): + def temperature(self) -> Quantity: """ Return the temperature of the solution in Kelvin. """ @@ -318,7 +324,14 @@ def set_temperature(self, temperature): self._update_volume() @property - def pressure(self): + def pH(self) -> Quantity: + """ + Return the pH of the solution. + """ + return self.p('H+', activity=True) + + @property + def pressure(self) -> Quantity: """ Return the hydrostatic pressure of the solution in atm. """ diff --git a/tests/test_pyeql_volume_concentration.py b/tests/test_pyeql_volume_concentration.py index 53b9a71b..af82dd6e 100644 --- a/tests/test_pyeql_volume_concentration.py +++ b/tests/test_pyeql_volume_concentration.py @@ -56,6 +56,8 @@ def test_empty_solution_3(self): assert s1.pressure.to("atm").magnitude == 1 # the pH should be 7.0 assert np.isclose(s1.get_activity("H+"), 1e-7, atol=1e-9) + assert np.isclose(s1.pH, 7.0, atol=0.01) + assert np.isclose(s1.pE, 8.5) # it should contain H2O, H+, and OH- species assert set(s1.list_solutes()) == set(["H2O", "OH-", "H+"]) @@ -213,6 +215,8 @@ def test_add_amount_5(self, s3): s3.add_amount("Na+", "1 mol/kg") s3.add_amount("Cl-", "1 mol/kg") assert np.allclose(s3.get_solvent_mass().to("kg").magnitude, original) + assert np.isclose(s3.pH, 7.0, atol=0.01) + assert np.isclose(s3.pE, 8.5) def test_add_amount_12(self, s3): # If the concentration of a solute is directly increased with a substance / mass