Skip to content

Commit 6134ed9

Browse files
authored
Merge pull request #72 from KingsburyLab/speed
Performance Improvements
2 parents 0af0c7e + bb12261 commit 6134ed9

9 files changed

+125
-108
lines changed

AUTHORS.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ developed and maintained by the Kingsbury Lab at Princeton University.
55

66
Other contributors, listed alphabetically, are:
77

8-
* Hernan Grecco <[email protected]>
8+
* @DhruvDuseja
9+
* Hernan Grecco (@hgrecco)
910

1011
(If you think that your name belongs here, please let the maintainer know)

CHANGELOG.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [Unreleased]
8+
## [0.9.1] - 2023-11-04
99

1010
### Added
1111

12-
- `format_solutes_dict()` method added into the utils module to help format solutes dictionaries with a unit.
12+
- `format_solutes_dict()` method added into the utils module to help format solutes dictionaries with a unit. (@DhruvDuseja)
13+
14+
### Changed
15+
16+
- Native property database is now instantiated on `pyEQL.__init__` to speed subsequent access by `Solution`
17+
- Numerous performance optimization increased the speed of many `Solution` property and method calls by 3x-10x
1318

1419
## [0.9.0] - 2023-10-17
1520

setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ install_requires =
5555
pymatgen>=2023.10.11
5656
iapws
5757
monty
58-
maggma
58+
maggma>=0.57.5
5959
phreeqpython
6060

6161
[options.packages.find]

src/pyEQL/__init__.py

+10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from importlib.metadata import PackageNotFoundError, version # pragma: no cover
1212

1313
from pint import UnitRegistry
14+
from pathlib import Path
15+
from maggma.stores import JSONStore
1416
from pkg_resources import resource_filename
1517

1618
try:
@@ -39,6 +41,14 @@
3941
# set the default string formatting for pint quantities
4042
ureg.default_format = "P~"
4143

44+
# create a Store for the default database
45+
database_dir = resource_filename("pyEQL", "database")
46+
json = Path(database_dir) / "pyeql_db.json"
47+
IonDB = JSONStore(str(json), key="formula")
48+
# By calling connect on init, we get the expensive JSON reading operation out
49+
# of the way. Subsequent calls to connect will bypass this and access the already-
50+
# instantiated Store in memory, which should speed up instantiation of Solution objects.
51+
IonDB.connect()
4252

4353
from pyEQL.functions import * # noqa: E402, F403
4454
from pyEQL.solution import Solution # noqa: E402

src/pyEQL/engines.py

+11-11
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ def get_osmotic_coefficient(self, solution):
429429
# solution.get_amount(Salt.anion,'mol/kg')/Salt.nu_anion)/2
430430

431431
# get the effective molality of the salt
432-
concentration = d["mol"] * ureg.Quantity("mol") / solution.solvent_mass
432+
concentration = ureg.Quantity(d["mol"], "mol") / solution.solvent_mass
433433

434434
molality_sum += concentration
435435

@@ -463,7 +463,7 @@ def get_osmotic_coefficient(self, solution):
463463
"Cannot calculate osmotic coefficient because Pitzer parameters for salt %s are not specified. Returning unit osmotic coefficient"
464464
% item.formula
465465
)
466-
effective_osmotic_sum += concentration * ureg.Quantity("1 dimensionless")
466+
effective_osmotic_sum += concentration * osmotic_coefficient
467467

468468
try:
469469
return effective_osmotic_sum / molality_sum
@@ -545,7 +545,7 @@ def get_solute_volume(self, solution):
545545

546546
part_vol = solution.get_property(solute, "size.molar_volume")
547547
if part_vol is not None:
548-
solute_vol += part_vol * mol * ureg.Quantity("1 mol")
548+
solute_vol += part_vol * ureg.Quantity(mol, "mol")
549549
logger.info("Updated solution volume using direct partial molar volume for solute %s" % solute)
550550

551551
else:
@@ -593,6 +593,9 @@ def __init__(
593593
)
594594
self.database = phreeqc_db
595595

596+
# create the PhreeqcPython instance
597+
self.pp = PhreeqPython(database=self.database, database_directory=self.db_path)
598+
596599
def _setup_ppsol(self, solution):
597600
"""
598601
Helper method to set up a PhreeqPython solution for subsequent analysis
@@ -637,12 +640,9 @@ def _setup_ppsol(self, solution):
637640
key += " charge"
638641
d[key] = mol / solv_mass
639642

640-
# create the PhreeqcPython instance
641-
pp = PhreeqPython(database=self.database, database_directory=self.db_path)
642-
643643
# create the PHREEQC solution object
644644
try:
645-
ppsol = pp.add_solution(d)
645+
ppsol = self.pp.add_solution(d)
646646
except Exception as e:
647647
print(d)
648648
# catch problems with the input to phreeqc
@@ -672,20 +672,20 @@ def get_activity_coefficient(self, solution, solute):
672672

673673
# translate the species into keys that phreeqc will understand
674674
k = standardize_formula(solute)
675-
el = k.split("[")[0]
676-
chg = k.split("[")[1].split("]")[0]
675+
spl = k.split("[")
676+
el = spl[0]
677+
chg = spl[1].split("]")[0]
677678
if chg[-1] == "1":
678679
chg = chg[0] # just pass + or -, not +1 / -1
679680
k = el + chg
680681

681682
# calculate the molal scale activity coefficient
682-
print(k)
683683
act = ppsol.activity(k, "mol") / ppsol.molality(k, "mol")
684684

685685
# remove the PPSol from the phreeqcpython instance
686686
self._destroy_ppsol(ppsol)
687687

688-
return act * ureg.Quantity("1 dimensionless")
688+
return ureg.Quantity(act, "dimensionless")
689689

690690
def get_osmotic_coefficient(self, solution):
691691
"""

src/pyEQL/equilibrium.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ def adjust_temp_pitzer(c1, c2, c3, c4, c5, temp, temp_ref=ureg.Quantity("298.15
162162
)
163163

164164

165-
def adjust_temp_vanthoff(equilibrium_constant, enthalpy, temperature, reference_temperature=25 * ureg.Quantity("degC")):
165+
def adjust_temp_vanthoff(equilibrium_constant, enthalpy, temperature, reference_temperature=ureg.Quantity(25, "degC")):
166166
r"""(float,float,number, optional number) -> float.
167167
168168
Adjust a reaction equilibrium constant from one temperature to another.
@@ -227,7 +227,7 @@ def adjust_temp_arrhenius(
227227
rate_constant,
228228
activation_energy,
229229
temperature,
230-
reference_temperature=25 * ureg.Quantity("degC"),
230+
reference_temperature=ureg.Quantity(25, "degC"),
231231
):
232232
r"""(float,float,number, optional number) -> float.
233233
@@ -363,7 +363,7 @@ def alpha(n, pH, pKa_list):
363363
k_term = 1
364364

365365
# the 'item' index counts from 0 to the number of protons, inclusive
366-
for item in range(0, num_protons + 1):
366+
for item in range(num_protons + 1):
367367
# multiply the preceding k values together
368368
for i in range(len(pKa_list[:item])):
369369
k_term *= 10 ** -pKa_list[i]

0 commit comments

Comments
 (0)