pyEQL 0.15.1__py2.py3-none-any.whl → 1.0.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pyEQL/__init__.py CHANGED
@@ -5,6 +5,8 @@ and performing chemical thermodynamics computations.
5
5
  :copyright: 2013-2024 by Ryan S. Kingsbury
6
6
  :license: LGPL, see LICENSE for more details.
7
7
  """
8
+
9
+ import logging
8
10
  from importlib.metadata import PackageNotFoundError, version # pragma: no cover
9
11
  from importlib.resources import files
10
12
 
@@ -20,6 +22,12 @@ except PackageNotFoundError: # pragma: no cover
20
22
  finally:
21
23
  del version, PackageNotFoundError
22
24
 
25
+ # logging
26
+ logger = logging.getLogger("pyEQL")
27
+ logger.setLevel(logging.WARNING)
28
+ logger.addHandler(logging.NullHandler())
29
+
30
+
23
31
  # Units handling
24
32
  # per the pint documentation, it's important that pint and its associated Unit
25
33
  # Registry are only instantiated once.
@@ -39,7 +47,7 @@ ureg.default_format = "P~"
39
47
 
40
48
  # create a Store for the default database
41
49
  json_db_file = files("pyEQL") / "database" / "pyeql_db.json"
42
- IonDB = JSONStore(str(json_db_file), key="formula")
50
+ IonDB = JSONStore(str(json_db_file), key="formula", encoding="utf8")
43
51
  # By calling connect on init, we get the expensive JSON reading operation out
44
52
  # of the way. Subsequent calls to connect will bypass this and access the already-
45
53
  # instantiated Store in memory, which should speed up instantiation of Solution objects.
@@ -12,14 +12,17 @@ are called from within the get_activity_coefficient method of the Solution class
12
12
  :license: LGPL, see LICENSE for more details.
13
13
 
14
14
  """
15
- import math
16
15
 
16
+ import logging
17
+
18
+ import numpy as np
17
19
  from pint import Quantity
18
20
 
19
21
  from pyEQL import ureg
20
- from pyEQL.logging_system import logger
21
22
  from pyEQL.utils import create_water_substance
22
23
 
24
+ logger = logging.getLogger(f"pyEQL.{__name__}")
25
+
23
26
 
24
27
  def _debye_parameter_B(temperature: str = "25 degC") -> Quantity:
25
28
  r"""
@@ -111,11 +114,11 @@ def _debye_parameter_activity(temperature: str = "25 degC") -> "Quantity":
111
114
 
112
115
  debyeparam = (
113
116
  ureg.elementary_charge**3
114
- * (2 * math.pi * ureg.N_A * ureg.Quantity(water_substance.rho, "g/L")) ** 0.5
115
- / (4 * math.pi * ureg.epsilon_0 * water_substance.epsilon * ureg.boltzmann_constant * T) ** 1.5
117
+ * (2 * np.pi * ureg.N_A * ureg.Quantity(water_substance.rho, "g/L")) ** 0.5
118
+ / (4 * np.pi * ureg.epsilon_0 * water_substance.epsilon * ureg.boltzmann_constant * T) ** 1.5
116
119
  )
117
120
 
118
- logger.info(rf"Computed Debye-Huckel Limiting Law Constant A^{{\gamma}} = {debyeparam} at {temperature}")
121
+ logger.debug(rf"Computed Debye-Huckel Limiting Law Constant A^{{\gamma}} = {debyeparam} at {temperature}")
119
122
  return debyeparam.to("kg ** 0.5 / mol ** 0.5")
120
123
 
121
124
 
@@ -149,7 +152,7 @@ def _debye_parameter_osmotic(temperature="25 degC"):
149
152
 
150
153
  """
151
154
  output = 1 / 3 * _debye_parameter_activity(temperature)
152
- logger.info(f"Computed Debye-Huckel Limiting slope for osmotic coefficient A^phi = {output} at {temperature}")
155
+ logger.debug(f"Computed Debye-Huckel Limiting slope for osmotic coefficient A^phi = {output} at {temperature}")
153
156
  return output.to("kg ** 0.5 /mol ** 0.5")
154
157
 
155
158
 
@@ -206,7 +209,7 @@ def _debye_parameter_volume(temperature="25 degC"):
206
209
  if T.to("degC").magnitude != 25:
207
210
  logger.warning("Debye-Huckel limiting slope for volume is approximate when T is not equal to 25 degC")
208
211
 
209
- logger.info(f"Computed Debye-Huckel Limiting Slope for volume A^V = {result} at {temperature}")
212
+ logger.debug(f"Computed Debye-Huckel Limiting Slope for volume A^V = {result} at {temperature}")
210
213
 
211
214
  return result.to("cm ** 3 * kg ** 0.5 / mol ** 1.5")
212
215
 
@@ -245,7 +248,7 @@ def get_activity_coefficient_debyehuckel(ionic_strength, z=1, temperature="25 de
245
248
 
246
249
  log_f = -_debye_parameter_activity(temperature) * z**2 * ionic_strength**0.5
247
250
 
248
- return math.exp(log_f) * ureg.Quantity(1, "dimensionless")
251
+ return np.exp(log_f) * ureg.Quantity(1, "dimensionless")
249
252
 
250
253
 
251
254
  def get_activity_coefficient_guntelberg(ionic_strength, z=1, temperature="25 degC"):
@@ -280,11 +283,9 @@ def get_activity_coefficient_guntelberg(ionic_strength, z=1, temperature="25 deg
280
283
  if not ionic_strength.magnitude <= 0.1:
281
284
  logger.warning("Ionic strength exceeds valid range of the Guntelberg approximation")
282
285
 
283
- log_f = (
284
- -_debye_parameter_activity(temperature) * z**2 * ionic_strength**0.5 / (1 + ionic_strength.magnitude**0.5)
285
- )
286
+ log_f = -_debye_parameter_activity(temperature) * z**2 * ionic_strength**0.5 / (1 + ionic_strength.magnitude**0.5)
286
287
 
287
- return math.exp(log_f) * ureg.Quantity(1, "dimensionless")
288
+ return np.exp(log_f) * ureg.Quantity(1, "dimensionless")
288
289
 
289
290
 
290
291
  def get_activity_coefficient_davies(ionic_strength, z=1, temperature="25 degC"):
@@ -326,7 +327,7 @@ def get_activity_coefficient_davies(ionic_strength, z=1, temperature="25 degC"):
326
327
  * (ionic_strength.magnitude**0.5 / (1 + ionic_strength.magnitude**0.5) - 0.2 * ionic_strength.magnitude)
327
328
  )
328
329
 
329
- return math.exp(log_f) * ureg.Quantity(1, "dimensionless")
330
+ return np.exp(log_f) * ureg.Quantity(1, "dimensionless")
330
331
 
331
332
 
332
333
  def get_activity_coefficient_pitzer(
@@ -436,7 +437,7 @@ def get_activity_coefficient_pitzer(
436
437
  b,
437
438
  )
438
439
 
439
- return math.exp(loggamma) * ureg.Quantity(1, "dimensionless")
440
+ return np.exp(loggamma) * ureg.Quantity(1, "dimensionless")
440
441
 
441
442
 
442
443
  def get_apparent_volume_pitzer(
@@ -532,7 +533,7 @@ def get_apparent_volume_pitzer(
532
533
  (nu_cation + nu_anion)
533
534
  * abs(z_cation * z_anion)
534
535
  * (_debye_parameter_volume(temperature) / 2 / b)
535
- * math.log(1 + b * ionic_strength**0.5)
536
+ * np.log(1 + b * ionic_strength**0.5)
536
537
  )
537
538
 
538
539
  third_term = (
@@ -565,7 +566,7 @@ def _pitzer_f1(x):
565
566
  # return 0 if the input is 0
566
567
  if x == 0:
567
568
  return 0
568
- return 2 * (1 - (1 + x) * math.exp(-x)) / x**2
569
+ return 2 * (1 - (1 + x) * np.exp(-x)) / x**2
569
570
 
570
571
 
571
572
  def _pitzer_f2(x):
@@ -585,7 +586,7 @@ def _pitzer_f2(x):
585
586
  # return 0 if the input is 0
586
587
  if x == 0:
587
588
  return 0
588
- return -2 * (1 - (1 + x + x**2 / 2) * math.exp(-x)) / x**2
589
+ return -2 * (1 - (1 + x + x**2 / 2) * np.exp(-x)) / x**2
589
590
 
590
591
 
591
592
  def _pitzer_B_MX(ionic_strength, alpha1, alpha2, beta0, beta1, beta2):
@@ -615,9 +616,7 @@ def _pitzer_B_MX(ionic_strength, alpha1, alpha2, beta0, beta1, beta2):
615
616
  :func:`_pitzer_f1`
616
617
 
617
618
  """
618
- coeff = (
619
- beta0 + beta1 * _pitzer_f1(alpha1 * ionic_strength**0.5) + beta2 * _pitzer_f1(alpha2 * ionic_strength**0.5)
620
- )
619
+ coeff = beta0 + beta1 * _pitzer_f1(alpha1 * ionic_strength**0.5) + beta2 * _pitzer_f1(alpha2 * ionic_strength**0.5)
621
620
  return coeff.magnitude
622
621
 
623
622
 
@@ -693,6 +692,10 @@ def _pitzer_B_phi(ionic_strength, alpha1, alpha2, beta0, beta1, beta2):
693
692
  and Representation with an Ion Interaction (Pitzer) Model.
694
693
  Journal of Chemical & Engineering Data, 55(2), 830-838. doi:10.1021/je900487a
695
694
  """
695
+ import math
696
+
697
+ # TODO - for some reason this specific method requires the use of math.exp rather than np.exp. Using np.exp raises
698
+ # a dimensionalityerror.
696
699
  return beta0 + beta1 * math.exp(-alpha1 * ionic_strength**0.5) + beta2 * math.exp(-alpha2 * ionic_strength**0.5)
697
700
 
698
701
 
@@ -773,7 +776,7 @@ def _pitzer_log_gamma(
773
776
  -1
774
777
  * abs(z_cation * z_anion)
775
778
  * _debye_parameter_osmotic(temperature)
776
- * (ionic_strength**0.5 / (1 + b * ionic_strength**0.5) + 2 / b * math.log(1 + b * ionic_strength**0.5))
779
+ * (ionic_strength**0.5 / (1 + b * ionic_strength**0.5) + 2 / b * np.log(1 + b * ionic_strength**0.5))
777
780
  )
778
781
  second_term = 2 * molality * nu_cation * nu_anion / (nu_cation + nu_anion) * (B_MX + B_phi)
779
782
  third_term = 3 * molality**2 * (nu_cation * nu_anion) ** 1.5 / (nu_cation + nu_anion) * C_phi
pyEQL/engines.py CHANGED
@@ -6,6 +6,7 @@ pyEQL engines for computing aqueous equilibria (e.g., speciation, redox, etc.).
6
6
 
7
7
  """
8
8
 
9
+ import logging
9
10
  import os
10
11
  import warnings
11
12
  from abc import ABC, abstractmethod
@@ -14,13 +15,8 @@ from typing import Literal
14
15
 
15
16
  from phreeqpython import PhreeqPython
16
17
 
17
- # internal pyEQL imports
18
18
  import pyEQL.activity_correction as ac
19
-
20
- # import the parameters database
21
- # the pint unit registry
22
19
  from pyEQL import ureg
23
- from pyEQL.logging_system import logger
24
20
  from pyEQL.salt_ion_match import Salt
25
21
  from pyEQL.utils import standardize_formula
26
22
 
@@ -28,6 +24,8 @@ from pyEQL.utils import standardize_formula
28
24
  # PHREEQC will ignore others (e.g., 'Na(1)')
29
25
  SPECIAL_ELEMENTS = ["S", "C", "N", "Cu", "Fe", "Mn"]
30
26
 
27
+ logger = logging.getLogger(__name__)
28
+
31
29
 
32
30
  class EOS(ABC):
33
31
  """
@@ -49,7 +47,7 @@ class EOS(ABC):
49
47
  solution: pyEQL Solution object
50
48
  solute: str identifying the solute of interest
51
49
 
52
- Returns
50
+ Returns:
53
51
  Quantity: dimensionless quantity object
54
52
 
55
53
  Raises:
@@ -64,7 +62,7 @@ class EOS(ABC):
64
62
  Args:
65
63
  solution: pyEQL Solution object
66
64
 
67
- Returns
65
+ Returns:
68
66
  Quantity: dimensionless molal scale osmotic coefficient
69
67
 
70
68
  Raises:
@@ -79,7 +77,7 @@ class EOS(ABC):
79
77
  Args:
80
78
  solution: pyEQL Solution object
81
79
 
82
- Returns
80
+ Returns:
83
81
  Quantity: solute volume in L
84
82
 
85
83
  Raises:
@@ -96,7 +94,7 @@ class EOS(ABC):
96
94
  Args:
97
95
  solution: pyEQL Solution object
98
96
 
99
- Returns
97
+ Returns:
100
98
  Nothing. The speciation of the Solution is modified in-place.
101
99
 
102
100
  Raises:
@@ -175,9 +173,7 @@ class NativeEOS(EOS):
175
173
  self._stored_comp = None
176
174
 
177
175
  def _setup_ppsol(self, solution):
178
- """
179
- Helper method to set up a PhreeqPython solution for subsequent analysis.
180
- """
176
+ """Helper method to set up a PhreeqPython solution for subsequent analysis."""
181
177
  self._stored_comp = solution.components.copy()
182
178
  solv_mass = solution.solvent_mass.to("kg").magnitude
183
179
  # inherit bulk solution properties
@@ -199,6 +195,16 @@ class NativeEOS(EOS):
199
195
  # add the composition to the dict
200
196
  # also, skip H and O
201
197
  for el, mol in solution.get_el_amt_dict().items():
198
+ # CAUTION - care must be taken to avoid unintended behavior here. get_el_amt_dict() will return
199
+ # all distinct oxi states of each element present. If there are elements present whose oxi states
200
+ # are NOT recognized by PHREEQC (via SPECIAL_ELEMENTS) then the amount of only 1 oxi state will be
201
+ # entered into the composition dict. This can especially cause problems after equilibrate() has already
202
+ # been called once. For example, equilibrating a simple NaCl solution generates Cl species that are assigned
203
+ # various oxidations states, -1 mostly, but also 1, 2, and 3. Since the concentrations of everything
204
+ # except the -1 oxi state are tiny, this can result in Cl "disappearing" from the solution if
205
+ # equlibrate is called again. It also causes non-determinism, because the amount is taken from whatever
206
+ # oxi state happens to be iterated through last.
207
+
202
208
  # strip off the oxi state
203
209
  bare_el = el.split("(")[0]
204
210
  if bare_el in SPECIAL_ELEMENTS:
@@ -210,7 +216,12 @@ class NativeEOS(EOS):
210
216
  else:
211
217
  key = bare_el
212
218
 
213
- d[key] = str(mol / solv_mass)
219
+ if key in d:
220
+ # when multiple oxi states for the same (non-SPECIAL) element are present, make sure to
221
+ # add all their amounts together
222
+ d[key] += str(mol / solv_mass)
223
+ else:
224
+ d[key] = str(mol / solv_mass)
214
225
 
215
226
  # tell PHREEQC which species to use for charge balance
216
227
  if (
@@ -318,7 +329,7 @@ class NativeEOS(EOS):
318
329
 
319
330
  # show an error if no salt can be found that contains the solute
320
331
  if salt is None:
321
- logger.warning("No salts found that contain solute %s. Returning unit activity coefficient." % solute)
332
+ logger.error("No salts found that contain solute %s. Returning unit activity coefficient." % solute)
322
333
  return ureg.Quantity(1, "dimensionless")
323
334
 
324
335
  # use the Pitzer model for higher ionic strength, if the parameters are available
@@ -367,15 +378,16 @@ class NativeEOS(EOS):
367
378
  str(solution.temperature),
368
379
  )
369
380
 
370
- logger.info(
371
- f"Calculated activity coefficient of species {solute} as {activity_coefficient} based on salt {salt} using Pitzer model"
381
+ logger.debug(
382
+ f"Calculated activity coefficient of species {solute} as {activity_coefficient} based on salt"
383
+ f" {salt} using Pitzer model"
372
384
  )
373
385
  molal = activity_coefficient
374
386
 
375
387
  # for very low ionic strength, use the Debye-Huckel limiting law
376
388
  elif solution.ionic_strength.magnitude <= 0.005:
377
- logger.info(
378
- "Ionic strength = %s. Using Debye-Huckel to calculate activity coefficient." % solution.ionic_strength
389
+ logger.debug(
390
+ f"Ionic strength = {solution.ionic_strength}. Using Debye-Huckel to calculate activity coefficient."
379
391
  )
380
392
  molal = ac.get_activity_coefficient_debyehuckel(
381
393
  solution.ionic_strength,
@@ -385,8 +397,8 @@ class NativeEOS(EOS):
385
397
 
386
398
  # use the Guntelberg approximation for 0.005 < I < 0.1
387
399
  elif solution.ionic_strength.magnitude <= 0.1:
388
- logger.info(
389
- "Ionic strength = %s. Using Guntelberg to calculate activity coefficient." % solution.ionic_strength
400
+ logger.debug(
401
+ f"Ionic strength = {solution.ionic_strength}. Using Guntelberg to calculate activity coefficient."
390
402
  )
391
403
  molal = ac.get_activity_coefficient_guntelberg(
392
404
  solution.ionic_strength,
@@ -396,9 +408,8 @@ class NativeEOS(EOS):
396
408
 
397
409
  # use the Davies equation for 0.1 < I < 0.5
398
410
  elif solution.ionic_strength.magnitude <= 0.5:
399
- logger.info(
400
- "Ionic strength = %s. Using Davies equation to calculate activity coefficient."
401
- % solution.ionic_strength
411
+ logger.debug(
412
+ f"Ionic strength = {solution.ionic_strength}. Using Davies equation to calculate activity coefficient."
402
413
  )
403
414
  molal = ac.get_activity_coefficient_davies(
404
415
  solution.ionic_strength,
@@ -407,9 +418,9 @@ class NativeEOS(EOS):
407
418
  )
408
419
 
409
420
  else:
410
- logger.warning(
411
- "Ionic strength too high to estimate activity for species %s. Specify parameters for Pitzer model. Returning unit activity coefficient"
412
- % solute
421
+ logger.error(
422
+ f"Ionic strength too high to estimate activity for species {solute}. Specify parameters for Pitzer "
423
+ "model. Returning unit activity coefficient"
413
424
  )
414
425
 
415
426
  molal = ureg.Quantity(1, "dimensionless")
@@ -479,11 +490,11 @@ class NativeEOS(EOS):
479
490
  behavior on desalination calculations for mixed electrolyte solutions with comparison to seawater. Desalination 2013, 318, 34-47.
480
491
 
481
492
  Examples:
482
- >>> s1 = pyEQL.Solution([['Na+','0.2 mol/kg'],['Cl-','0.2 mol/kg']])
493
+ >>> s1 = pyEQL.Solution({'Na+': '0.2 mol/kg', 'Cl-': '0.2 mol/kg'})
483
494
  >>> s1.get_osmotic_coefficient()
484
495
  <Quantity(0.923715281, 'dimensionless')>
485
496
 
486
- >>> s1 = pyEQL.Solution([['Mg+2','0.3 mol/kg'],['Cl-','0.6 mol/kg']],temperature='30 degC')
497
+ >>> s1 = pyEQL.Solution({'Mg+2': '0.3 mol/kg', 'Cl-': '0.6 mol/kg'},temperature='30 degC')
487
498
  >>> s1.get_osmotic_coefficient()
488
499
  <Quantity(0.891409618, 'dimensionless')>
489
500
 
@@ -494,7 +505,7 @@ class NativeEOS(EOS):
494
505
  molality_sum = 0
495
506
 
496
507
  # loop through all the salts in the solution, calculate the osmotic
497
- # coefficint for reach, and average them into an effective osmotic
508
+ # coefficint for each, and average them into an effective osmotic
498
509
  # coefficient
499
510
  for d in solution.get_salt_dict().values():
500
511
  item = Salt(d["cation"], d["anion"])
@@ -544,17 +555,18 @@ class NativeEOS(EOS):
544
555
  str(solution.temperature),
545
556
  )
546
557
 
547
- logger.info(
548
- f"Calculated osmotic coefficient of water as {osmotic_coefficient} based on salt {item.formula} using Pitzer model"
558
+ logger.debug(
559
+ f"Calculated osmotic coefficient of water as {osmotic_coefficient} based on salt "
560
+ f"{item.formula} using Pitzer model"
549
561
  )
550
562
  effective_osmotic_sum += concentration * osmotic_coefficient
551
563
 
552
564
  else:
553
- logger.warning(
554
- "Cannot calculate osmotic coefficient because Pitzer parameters for salt %s are not specified. Returning unit osmotic coefficient"
555
- % item.formula
565
+ logger.debug(
566
+ f"Returning unit osmotic coefficient for salt {item.formula} because Pitzer parameters are not"
567
+ "available in database."
556
568
  )
557
- effective_osmotic_sum += concentration * osmotic_coefficient
569
+ effective_osmotic_sum += concentration * 1
558
570
 
559
571
  try:
560
572
  return effective_osmotic_sum / molality_sum
@@ -621,7 +633,7 @@ class NativeEOS(EOS):
621
633
 
622
634
  pitzer_calc = True
623
635
 
624
- logger.info("Updated solution volume using Pitzer model for solute %s" % salt.formula)
636
+ logger.debug("Updated solution volume using Pitzer model for solute %s" % salt.formula)
625
637
 
626
638
  # add the partial molar volume of any other solutes, except for water
627
639
  # or the parent salt, which is already accounted for by the Pitzer parameters
@@ -637,12 +649,11 @@ class NativeEOS(EOS):
637
649
  part_vol = solution.get_property(solute, "size.molar_volume")
638
650
  if part_vol is not None:
639
651
  solute_vol += part_vol * ureg.Quantity(mol, "mol")
640
- logger.info("Updated solution volume using direct partial molar volume for solute %s" % solute)
652
+ logger.debug("Updated solution volume using direct partial molar volume for solute %s" % solute)
641
653
 
642
654
  else:
643
655
  logger.warning(
644
- "Partial molar volume data not available for solute %s. Solution volume will not be corrected."
645
- % solute
656
+ f"Volume of solute {solute} will be ignored because partial molar volume data are not available."
646
657
  )
647
658
 
648
659
  return solute_vol.to("L")
@@ -662,7 +673,6 @@ class NativeEOS(EOS):
662
673
  solution.components[s] = mol
663
674
 
664
675
  # make sure all species are accounted for
665
- charge_adjust = 0
666
676
  assert set(self._stored_comp.keys()) - set(solution.components.keys()) == set()
667
677
 
668
678
  # log a message if any components were not touched by PHREEQC
@@ -673,6 +683,11 @@ class NativeEOS(EOS):
673
683
  f"After equilibration, the amounts of species {missing_species} were not modified "
674
684
  "by PHREEQC. These species are likely absent from its database."
675
685
  )
686
+
687
+ # re-adjust charge balance for any missing species
688
+ # note that if balance_charge is set, it will have been passed to PHREEQC, so we only need to adjust
689
+ # for any missing species here.
690
+ charge_adjust = 0
676
691
  for s in missing_species:
677
692
  charge_adjust += -1 * solution.get_amount(s, "eq").magnitude
678
693
  if charge_adjust != 0:
@@ -681,11 +696,10 @@ class NativeEOS(EOS):
681
696
  f" {charge_adjust} eq of charge were added via {solution.balance_charge}"
682
697
  )
683
698
 
684
- # re-adjust charge balance
685
699
  if solution.balance_charge is None:
686
700
  pass
687
701
  elif solution.balance_charge == "pH":
688
- solution.components["H+"] += charge_adjust
702
+ solution.components["H+"] += charge_adjust.magnitude
689
703
  elif solution.balance_charge == "pE":
690
704
  raise NotImplementedError
691
705
  else:
pyEQL/equilibrium.py CHANGED
@@ -8,12 +8,15 @@ NOTE: these methods are not currently used but are here for the future.
8
8
  :license: LGPL, see LICENSE for more details.
9
9
 
10
10
  """
11
+
11
12
  # import libraries for scientific functions
12
- import math
13
+ import logging
14
+
15
+ import numpy as np
13
16
 
14
- # the pint unit registry
15
17
  from pyEQL import ureg
16
- from pyEQL.logging_system import logger
18
+
19
+ logger = logging.getLogger(__name__)
17
20
 
18
21
  # TODO - not used. Remove?
19
22
  SPECIES_ALIAISES = {
@@ -49,7 +52,7 @@ def adjust_temp_pitzer(c1, c2, c3, c4, c5, temp, temp_ref=ureg.Quantity("298.15
49
52
  return (
50
53
  c1
51
54
  + c2 * (1 / temp + 1 / temp_ref)
52
- + c2 * math.log(temp / temp_ref)
55
+ + c2 * np.log(temp / temp_ref)
53
56
  + c3 * (temp - temp_ref)
54
57
  + c4 * (temp**2 - temp_ref**2)
55
58
  + c5 * (temp**-2 - temp_ref**-2)
@@ -89,15 +92,17 @@ def adjust_temp_vanthoff(equilibrium_constant, enthalpy, temperature, reference_
89
92
  >>> adjust_temp_vanthoff(0.15,ureg.Quantity('-197.6 kJ/mol'),ureg.Quantity('42 degC')) #doctest: +ELLIPSIS
90
93
  0.00203566...
91
94
  """
92
- output = equilibrium_constant * math.exp(
95
+ output = equilibrium_constant * np.exp(
93
96
  enthalpy / ureg.R * (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
94
97
  )
95
98
 
96
- logger.info(
99
+ logger.debug(
97
100
  "Adjusted equilibrium constant K=%s from %s to %s degrees Celsius with Delta H = %s. Adjusted K = %s % equilibrium_constant,reference_temperature,temperature,enthalpy,output"
98
101
  )
99
102
 
100
- logger.warning("Van't Hoff equation assumes enthalpy is independent of temperature over the range of interest")
103
+ logger.info(
104
+ "Note that the Van't Hoff equation assumes enthalpy is independent of temperature over the range of interest"
105
+ )
101
106
  return output
102
107
 
103
108
 
@@ -124,7 +129,7 @@ def adjust_temp_arrhenius(
124
129
  TODO - add better reference
125
130
 
126
131
  .. math::
127
- ln(\frac{K2}{K1} = \frac{E_a}{R} ( \frac{1}{T_{1}} - {\frac{1}{T_2}} )
132
+ ln(\frac{K2}{K1}) = \frac{E_a}{R} ( \frac{1}{T_{1}} - {\frac{1}{T_2}} )
128
133
 
129
134
  References:
130
135
  http://chemwiki.ucdavis.edu/Physical_Chemistry/Kinetics/Reaction_Rates/Temperature_Dependence_of_Reaction_Rates/Arrhenius_Equation
@@ -133,12 +138,13 @@ def adjust_temp_arrhenius(
133
138
  >>> adjust_temp_arrhenius(7,900*ureg.Quantity('kJ/mol'),37*ureg.Quantity('degC'),97*ureg.Quantity('degC')) #doctest: +ELLIPSIS
134
139
  1.8867225...e-24
135
140
  """
136
- output = rate_constant * math.exp(
141
+ output = rate_constant * np.exp(
137
142
  activation_energy / ureg.R * (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
138
143
  )
139
144
 
140
- logger.info(
141
- "Adjusted parameter %s from %s to %s degrees Celsius with Activation Energy = %s kJ/mol. Adjusted value = %s % rate_constant,reference_temperature,temperature,activation_energy,output"
145
+ logger.debug(
146
+ f"Adjusted parameter {rate_constant} from {reference_temperature} to {temperature} degrees Celsius with"
147
+ f"Activation Energy = {activation_energy}s kJ/mol. Adjusted value = {output}"
142
148
  )
143
149
 
144
150
  return output
@@ -215,7 +221,7 @@ def alpha(n, pH, pKa_list):
215
221
 
216
222
  # return the desired distribution factor
217
223
  alpha = terms_list[n] / sum(terms_list)
218
- logger.info(
224
+ logger.debug(
219
225
  "Calculated %s-deprotonated acid distribution coefficient of %s for pKa=%s at pH %s % n,alpha,pKa_list,pH"
220
226
  )
221
227
  return alpha