pyEQL 0.12.2__py2.py3-none-any.whl → 0.14.0__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/engines.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  pyEQL engines for computing aqueous equilibria (e.g., speciation, redox, etc.).
3
3
 
4
- :copyright: 2013-2023 by Ryan S. Kingsbury
4
+ :copyright: 2013-2024 by Ryan S. Kingsbury
5
5
  :license: LGPL, see LICENSE for more details.
6
6
 
7
7
  """
@@ -52,8 +52,7 @@ class EOS(ABC):
52
52
  Quantity: dimensionless quantity object
53
53
 
54
54
  Raises:
55
- ValueError if the calculation cannot be completed, e.g. due to insufficient number of
56
- parameters.
55
+ ValueError if the calculation cannot be completed, e.g. due to insufficient number of parameters.
57
56
  """
58
57
 
59
58
  @abstractmethod
@@ -68,8 +67,7 @@ class EOS(ABC):
68
67
  Quantity: dimensionless molal scale osmotic coefficient
69
68
 
70
69
  Raises:
71
- ValueError if the calculation cannot be completed, e.g. due to insufficient number of
72
- parameters.
70
+ ValueError if the calculation cannot be completed, e.g. due to insufficient number of parameters.
73
71
  """
74
72
 
75
73
  @abstractmethod
@@ -84,8 +82,7 @@ class EOS(ABC):
84
82
  Quantity: solute volume in L
85
83
 
86
84
  Raises:
87
- ValueError if the calculation cannot be completed, e.g. due to insufficient number of
88
- parameters.
85
+ ValueError if the calculation cannot be completed, e.g. due to insufficient number of parameters.
89
86
  """
90
87
 
91
88
  @abstractmethod
@@ -102,8 +99,7 @@ class EOS(ABC):
102
99
  Nothing. The speciation of the Solution is modified in-place.
103
100
 
104
101
  Raises:
105
- ValueError if the calculation cannot be completed, e.g. due to insufficient number of
106
- parameters or lack of convergence.
102
+ ValueError if the calculation cannot be completed, e.g. due to insufficient number of parameters or lack of convergence.
107
103
  """
108
104
 
109
105
 
@@ -163,7 +159,15 @@ class NativeEOS(EOS):
163
159
  Path(os.path.dirname(__file__)) / "database" if self.phreeqc_db in ["llnl.dat", "geothermal.dat"] else None
164
160
  )
165
161
  # create the PhreeqcPython instance
166
- self.pp = PhreeqPython(database=self.phreeqc_db, database_directory=self.db_path)
162
+ # try/except added to catch unsupported architectures, such as Apple Silicon
163
+ try:
164
+ self.pp = PhreeqPython(database=self.phreeqc_db, database_directory=self.db_path)
165
+ except OSError:
166
+ logger.error(
167
+ "OSError encountered when trying to instantiate phreeqpython. Most likely this means you"
168
+ " are running on an architecture that is not supported by PHREEQC, such as Apple M1/M2 chips."
169
+ " pyEQL will work, but equilibrate() will have no effect."
170
+ )
167
171
  # attributes to hold the PhreeqPython solution.
168
172
  self.ppsol = None
169
173
  # store the solution composition to see whether we need to re-instantiate the solution
@@ -238,7 +242,7 @@ class NativeEOS(EOS):
238
242
  self.ppsol = None
239
243
 
240
244
  def get_activity_coefficient(self, solution, solute):
241
- """
245
+ r"""
242
246
  Whenever the appropriate parameters are available, the Pitzer model [may]_ is used.
243
247
  If no Pitzer parameters are available, then the appropriate equations are selected
244
248
  according to the following logic: [stumm]_.
@@ -250,17 +254,17 @@ class NativeEOS(EOS):
250
254
 
251
255
  The ionic strength, activity coefficients, and activities are all
252
256
  calculated based on the molal (mol/kg) concentration scale. If a different
253
- scale is given as input, then the molal-scale activity coefficient :math:`\\gamma_\\pm` is
257
+ scale is given as input, then the molal-scale activity coefficient :math:`\gamma_\pm` is
254
258
  converted according to [rbs]_
255
259
 
256
- .. math:: f_\\pm = \\gamma_\\pm * (1 + M_w \\sum_i \\nu_i \\m_i)
260
+ .. math:: f_\pm = \gamma_\pm * (1 + M_w \sum_i \nu_i m_i)
257
261
 
258
- .. math:: y_\\pm = m \\rho_w / C \\gamma_\\pm
262
+ .. math:: y_\pm = \frac{m \rho_w}{C \gamma_\pm}
259
263
 
260
- where :math:`f_\\pm` is the rational activity coefficient, :math:`M_w` is
264
+ where :math:`f_\pm` is the rational activity coefficient, :math:`M_w` is
261
265
  the molecular weight of water, the summation represents the total molality of
262
- all solute species, :math:`y_\\pm` is the molar activity coefficient,
263
- :math:`\\rho_w` is the density of pure water, :math:`m` and :math:`C` are
266
+ all solute species, :math:`y_\pm` is the molar activity coefficient,
267
+ :math:`\rho_w` is the density of pure water, :math:`m` and :math:`C` are
264
268
  the molal and molar concentrations of the chosen salt (not individual solute), respectively.
265
269
 
266
270
  Args:
@@ -280,11 +284,11 @@ class NativeEOS(EOS):
280
284
  molality," which is the molality that would result in a single-salt
281
285
  mixture with the same total ionic strength as the multicomponent solution.
282
286
 
283
- .. math:: m_effective = 2 I \\over (\\nu_{+} z_{+}^2 + \\nu{_}- z_{-} ^2)
287
+ .. math:: m_{effective} = \frac{2 I}{(\nu_{+} z_{+}^2 + \nu_{-}- z_{-}^2)}
284
288
 
285
289
  References:
286
- .. [may] May, P. M., Rowland, D., Hefter, G., & Königsberger, E. (2011).
287
- A Generic and Updatable Pitzer Characterization of Aqueous Binary Electrolyte Solutions at 1 bar and 25 °C.
290
+ .. [may] May, P. M., Rowland, D., Hefter, G., & Königsberger, E. (2011).
291
+ A Generic and Updatable Pitzer Characterization of Aqueous Binary Electrolyte Solutions at 1 bar and 25 °C.
288
292
  *Journal of Chemical & Engineering Data*, 56(12), 5066-5077. doi:10.1021/je2009329
289
293
 
290
294
  .. [stumm] Stumm, Werner and Morgan, James J. *Aquatic Chemistry*, 3rd ed,
@@ -297,12 +301,11 @@ class NativeEOS(EOS):
297
301
  desalination calculations for mixed electrolyte solutions with comparison to seawater. Desalination 2013, 318, 34-47.
298
302
 
299
303
  See Also:
300
- get_ionic_strength
301
- get_salt
302
- activity_correction.get_activity_coefficient_debyehuckel
303
- activity_correction.get_activity_coefficient_guntelberg
304
- activity_correction.get_activity_coefficient_davies
305
- activity_correction.get_activity_coefficient_pitzer
304
+ :attr:`pyEQL.solution.Solution.ionic_strength`
305
+ :func:`pyEQL.activity_correction.get_activity_coefficient_debyehuckel`
306
+ :func:`pyEQL.activity_correction.get_activity_coefficient_guntelberg`
307
+ :func:`pyEQL.activity_correction.get_activity_coefficient_davies`
308
+ :func:`pyEQL.activity_correction.get_activity_coefficient_pitzer`
306
309
  """
307
310
  # identify the predominant salt that this ion is a member of
308
311
  salt = None
@@ -418,7 +421,7 @@ class NativeEOS(EOS):
418
421
  return molal
419
422
 
420
423
  def get_osmotic_coefficient(self, solution):
421
- """
424
+ r"""
422
425
  Return the *molal scale* osmotic coefficient of solute, given a Solution
423
426
  object.
424
427
 
@@ -427,28 +430,27 @@ class NativeEOS(EOS):
427
430
  coefficient of 1.
428
431
 
429
432
  If the 'rational' scale is given as input, then the molal-scale osmotic
430
- coefficient :math:`\\phi` is converted according to [rbs]_
433
+ coefficient :math:`\phi` is converted according to [rbs]_
431
434
 
432
- .. math:: g = - \\phi * M_{w} \\sum_{i} \\nu_{i} \\m_{i}) / \\ln x_{w}
435
+ .. math:: g = - \phi M_{w} \frac{\sum_{i} \nu_{i} m_{i}}{\ln x_{w}}
433
436
 
434
437
  where :math:`g` is the rational osmotic coefficient, :math:`M_{w}` is
435
438
  the molecular weight of water, the summation represents the total molality of
436
439
  all solute species, and :math:`x_{w}` is the mole fraction of water.
437
440
 
438
441
  Args:
439
- scale:
440
- The concentration scale for the returned osmotic coefficient. Valid options are "molal",
441
- "rational" (i.e., mole fraction), and "fugacity". By default, the molal scale osmotic
442
- coefficient is returned.
442
+ scale: The concentration scale for the returned osmotic coefficient. Valid options are "molal",
443
+ "rational" (i.e., mole fraction), and "fugacity". By default, the molal scale osmotic
444
+ coefficient is returned.
443
445
 
444
- Returns
446
+ Returns:
445
447
  Quantity:
446
448
  The osmotic coefficient
447
449
 
448
450
  See Also:
449
- get_water_activity
450
- get_ionic_strength
451
- get_salt
451
+ :meth:`pyEQL.solution.Solution.get_water_activity`
452
+ :meth:`pyEQL.solution.Solution.get_salt`
453
+ :attr:`pyEQL.solution.Solution.ionic_strength`
452
454
 
453
455
  Notes:
454
456
  For multicomponent mixtures, pyEQL adopts the "effective Pitzer model"
@@ -469,8 +471,7 @@ class NativeEOS(EOS):
469
471
  the author confirmed that the weight factor should be the true molality, and that is what is implemented
470
472
  in pyEQL.)
471
473
 
472
- References
473
-
474
+ References:
474
475
  .. [may] May, P. M., Rowland, D., Hefter, G., & Königsberger, E. (2011).
475
476
  A Generic and Updatable Pitzer Characterization of Aqueous Binary Electrolyte Solutions at 1 bar and
476
477
  25 °C. Journal of Chemical & Engineering Data, 56(12), 5066-5077. doi:10.1021/je2009329
@@ -482,7 +483,6 @@ class NativeEOS(EOS):
482
483
  behavior on desalination calculations for mixed electrolyte solutions with comparison to seawater. Desalination 2013, 318, 34-47.
483
484
 
484
485
  Examples:
485
-
486
486
  >>> s1 = pyEQL.Solution([['Na+','0.2 mol/kg'],['Cl-','0.2 mol/kg']])
487
487
  >>> s1.get_osmotic_coefficient()
488
488
  <Quantity(0.923715281, 'dimensionless')>
pyEQL/equilibrium.py CHANGED
@@ -4,7 +4,7 @@ redox, complexation, etc.).
4
4
 
5
5
  NOTE: these methods are not currently used but are here for the future.
6
6
 
7
- :copyright: 2013-2023 by Ryan S. Kingsbury
7
+ :copyright: 2013-2024 by Ryan S. Kingsbury
8
8
  :license: LGPL, see LICENSE for more details.
9
9
 
10
10
  """
@@ -36,23 +36,15 @@ SPECIES_ALIAISES = {
36
36
 
37
37
  def adjust_temp_pitzer(c1, c2, c3, c4, c5, temp, temp_ref=ureg.Quantity("298.15 K")):
38
38
  """
39
- Calculate a parameter for the Pitzer model based on temperature-dependent
40
- coefficients c1,c2,c3,c4,and c5.
41
-
42
- Parameters
43
- ----------
44
- c1, c2, c3, c4, c5: float
45
- Temperature-dependent coefficients for the pitzer parameter of
46
- interest.
47
- temp: Quantity
48
- The temperature at which the Pitzer parameter is to be calculated
49
- temp_ref: Quantity, optional
50
- The reference temperature on which the parameters are based.
51
- 298.15 K if omitted.
52
-
53
- As described in the PHREEQC documentation
39
+ Calculate a parameter for the Pitzer model based on temperature-dependent coefficients c1,c2,c3,c4,and c5.
54
40
 
41
+ Args:
42
+ c1, c2, c3, c4, c5 (float): Temperature-dependent coefficients for the pitzer parameter of interest.
43
+ temp (Quantity): The temperature at which the Pitzer parameter is to be calculated.
44
+ temp_ref (Quantity, optional): The reference temperature on which the parameters are based. Defaults to 298.15 K if omitted.
55
45
 
46
+ Note:
47
+ As described in the PHREEQC documentation.
56
48
  """
57
49
  return (
58
50
  c1
@@ -65,53 +57,37 @@ def adjust_temp_pitzer(c1, c2, c3, c4, c5, temp, temp_ref=ureg.Quantity("298.15
65
57
 
66
58
 
67
59
  def adjust_temp_vanthoff(equilibrium_constant, enthalpy, temperature, reference_temperature=ureg.Quantity(25, "degC")):
68
- r"""(float,float,number, optional number) -> float.
69
-
60
+ r"""
70
61
  Adjust a reaction equilibrium constant from one temperature to another.
71
62
 
72
- Parameters
73
- ----------
74
- equilibrium_constant : float
75
- The reaction equilibrium constant for the reaction
76
- enthalpy : Quantity
77
- The enthalpy change (delta H) for the reaction in kJ/mol. Assumed
78
- independent of temperature (see Notes).
79
- temperature : Quantity
80
- the desired reaction temperature in degrees Celsius
81
- reference_temperature : Quantity, optional
82
- the temperature at which equilibrium_constant is valid. (25 degrees C if omitted).
83
-
84
- Returns
85
- -------
86
- float
87
- adjusted reaction equilibrium constant
88
-
89
- Notes
90
- -----
91
- This function implements the Van't Hoff equation to adjust measured
92
- equilibrium constants to other temperatures.
93
-
94
- .. math::
95
- ln(K2 / K1) = {\delta H \over R} ( {1 \over T_1} - {1 \over T_2} )
96
-
97
- This implementation assumes that the enthalpy is independent of temperature
98
- over the range of interest.
99
-
100
- References
101
- ----------
102
- Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 53.
103
- Wiley Interscience, 1996.
63
+ Args:
64
+ equilibrium_constant (float): The reaction equilibrium constant for the reaction.
65
+ enthalpy (Quantity): The enthalpy change (delta H) for the reaction in kJ/mol. Assumed independent of temperature (see Notes).
66
+ temperature (Quantity): The desired reaction temperature in degrees Celsius.
67
+ reference_temperature (Quantity, optional): The temperature at which equilibrium_constant is valid. Defaults to 25 degrees C if omitted.
104
68
 
105
- Examples:
106
- --------
107
- >>> adjust_temp_vanthoff(0.15,ureg.Quantity('-197.6 kJ/mol'),ureg.Quantity('42 degC'),ureg.Quantity(' 25degC')) #doctest: +ELLIPSIS
108
- 0.00203566...
69
+ Returns:
70
+ float: The adjusted reaction equilibrium constant.
71
+
72
+ Note:
73
+ This function implements the Van't Hoff equation to adjust measured equilibrium constants to other temperatures.
74
+
75
+ .. math::
76
+ ln(K2 / K1) = {\delta H \over R} ( {1 \over T_1} - {1 \over T_2} )
77
+
78
+ This implementation assumes that the enthalpy is independent of temperature over the range of interest.
79
+
80
+ References:
81
+ Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 53. Wiley Interscience, 1996.
109
82
 
110
- If the 'ref_temperature' parameter is omitted, a default of 25 C is used.
83
+ Examples:
84
+ >>> adjust_temp_vanthoff(0.15,ureg.Quantity('-197.6 kJ/mol'),ureg.Quantity('42 degC'),ureg.Quantity(' 25degC')) #doctest: +ELLIPSIS
85
+ 0.00203566...
111
86
 
112
- >>> adjust_temp_vanthoff(0.15,ureg.Quantity('-197.6 kJ/mol'),ureg.Quantity('42 degC')) #doctest: +ELLIPSIS
113
- 0.00203566...
87
+ If the 'ref_temperature' parameter is omitted, a default of 25 C is used.
114
88
 
89
+ >>> adjust_temp_vanthoff(0.15,ureg.Quantity('-197.6 kJ/mol'),ureg.Quantity('42 degC')) #doctest: +ELLIPSIS
90
+ 0.00203566...
115
91
  """
116
92
  output = equilibrium_constant * math.exp(
117
93
  enthalpy / ureg.R * (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
@@ -131,51 +107,31 @@ def adjust_temp_arrhenius(
131
107
  temperature,
132
108
  reference_temperature=ureg.Quantity(25, "degC"),
133
109
  ):
134
- r"""(float,float,number, optional number) -> float.
135
-
110
+ r"""
136
111
  Adjust a reaction equilibrium constant from one temperature to another.
137
112
 
138
- Parameters
139
- ----------
140
- rate_constant : Quantity
141
- The parameter value (usually a rate constant) being adjusted
142
- activation_energy : Quantity
143
- The activation energy of the process, in kJ/mol
144
- temperature : Quantity
145
- the desired reaction temperature.
146
- reference_temperature : Quantity, optional
147
- the temperature at which equilibrium_constant is valid
148
- Defaults to 25 degrees C if omitted.
149
-
150
- Returns
151
- -------
152
- Quantity
153
- The adjusted reaction equilibrium constant
113
+ Args:
114
+ rate_constant (Quantity): The parameter value (usually a rate constant) being adjusted.
115
+ activation_energy (Quantity): The activation energy of the process, in kJ/mol.
116
+ temperature (Quantity): The desired reaction temperature.
117
+ reference_temperature (Quantity, optional): The temperature at which equilibrium_constant is valid. Defaults to 25 degrees C if omitted.
154
118
 
155
- See Also:
156
- --------
157
- kelvin
119
+ Returns:
120
+ Quantity: The adjusted reaction equilibrium constant.
158
121
 
159
- Notes
160
- -----
161
- This function implements the Arrhenius equation to adjust measured rate
162
- constants to other temperatures.
163
- TODO - add better reference
122
+ Notes:
123
+ This function implements the Arrhenius equation to adjust measured rate constants to other temperatures.
124
+ TODO - add better reference
164
125
 
165
- .. math::
166
- ln(\\frac{K2}{K1} = \\frac{E_a}{R} ( \\frac{1}{T_{1}} - {\\frac{1}{T_2}} )
167
-
168
- References
169
- ----------
170
-
171
- http://chemwiki.ucdavis.edu/Physical_Chemistry/Kinetics/Reaction_Rates/Temperature_Dependence_of_Reaction_Rates/Arrhenius_Equation
126
+ .. math::
127
+ ln(\frac{K2}{K1} = \frac{E_a}{R} ( \frac{1}{T_{1}} - {\frac{1}{T_2}} )
172
128
 
129
+ References:
130
+ http://chemwiki.ucdavis.edu/Physical_Chemistry/Kinetics/Reaction_Rates/Temperature_Dependence_of_Reaction_Rates/Arrhenius_Equation
173
131
 
174
132
  Examples:
175
- --------
176
- >>> adjust_temp_arrhenius(7,900*ureg.Quantity('kJ/mol'),37*ureg.Quantity('degC'),97*ureg.Quantity('degC')) #doctest: +ELLIPSIS
177
- 1.8867225...e-24
178
-
133
+ >>> adjust_temp_arrhenius(7,900*ureg.Quantity('kJ/mol'),37*ureg.Quantity('degC'),97*ureg.Quantity('degC')) #doctest: +ELLIPSIS
134
+ 1.8867225...e-24
179
135
  """
180
136
  output = rate_constant * math.exp(
181
137
  activation_energy / ureg.R * (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
@@ -189,98 +145,76 @@ def adjust_temp_arrhenius(
189
145
 
190
146
 
191
147
  def alpha(n, pH, pKa_list):
192
- """Returns the acid-base distribution coefficient (alpha) of an acid in the
193
- n-deprotonated form at a given pH.
194
-
195
- Parameters
196
- ----------
197
- n : int
198
- The number of protons that have been lost by the desired form of the
199
- acid. Also the subscript on the alpha value. E.g. for bicarbonate
200
- (HCO3-), n=1 because 1 proton has been lost from the fully-protonated
201
- carbonic acid (H2CO3) form.
202
- pH : float or int
203
- The pH of the solution.
204
- pKa_list : list of floats or ints
205
- The pKa values (negative log of equilibrium constants) for the acid
206
- of interest. There must be a minimum of n pKa values in the list.
207
-
208
- Returns
209
- -------
210
- float
211
- The fraction of total acid present in the specified form.
212
-
213
- Notes
214
- -----
215
- The acid-base cient is calculated as follows: [stm]_
148
+ r"""
149
+ Returns the acid-base distribution coefficient (alpha) of an acid in the n-deprotonated form at a given pH.
150
+
151
+ Args:
152
+ n (int): The number of protons that have been lost by the desired form of the acid. Also the subscript on the
153
+ alpha value. E.g. for bicarbonate (HCO3-), n=1 because 1 proton has been lost from the fully-protonated
154
+ carbonic acid (H2CO3) form.
155
+ pH (float or int): The pH of the solution.
156
+ pKa_list (list of floats or ints): The pKa values (negative log of equilibrium constants) for the acid of
157
+ interest. There must be a minimum of n pKa values in the list.
158
+
159
+ Returns:
160
+ float: The fraction of total acid present in the specified form.
161
+
162
+ Notes:
163
+ The acid-base coefficient is calculated as follows: [stm]_
216
164
 
217
165
  .. math::
218
166
 
219
- \\alpha_n = \\frac{term_n}{[H+]^n + k_{a1}[H+]^{n-1} + k_{a1}k_{a2}[H+]^{n-2} ... k_{a1}k_{a2}...k_{an} }
167
+ \alpha_n = \frac{term_n}{[H+]^n + k_{a1}[H+]^{n-1} + k_{a1}k_{a2}[H+]^{n-2} ... k_{a1}k_{a2}...k_{an} }
220
168
 
221
169
  Where :math: '\term_n' refers to the nth term in the denominator, starting from 0
222
170
 
223
- References
224
- ----------
225
- .. [stm] Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 127-130. Wiley Interscience, 1996.
171
+ References:
172
+ Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 127-130. Wiley Interscience, 1996.
226
173
 
227
174
  Examples:
228
- --------
229
- >>> alpha(1,8,[4.7]) #doctest: +ELLIPSIS
230
- 0.999...
231
-
232
- The sum of all alpha values should equal 1
175
+ >>> alpha(1,8,[4.7]) #doctest: +ELLIPSIS
176
+ 0.999...
233
177
 
234
- >>> alpha(0,8,[6.35,10.33]) #doctest: +ELLIPSIS
235
- 0.021...
236
- >>> alpha(1,8,[6.35,10.33]) #doctest: +ELLIPSIS
237
- 0.979...
238
- >>> alpha(2,8,[6.35,10.33]) #doctest: +ELLIPSIS
239
- 2.043...e-09
178
+ The sum of all alpha values should equal 1
240
179
 
241
- If pH is equal to one of the pKa values the function should return 0.5.
180
+ >>> alpha(0,8,[6.35,10.33]) #doctest: +ELLIPSIS
181
+ 0.021...
182
+ >>> alpha(1,8,[6.35,10.33]) #doctest: +ELLIPSIS
183
+ 0.979...
184
+ >>> alpha(2,8,[6.35,10.33]) #doctest: +ELLIPSIS
185
+ 2.043...e-09
242
186
 
243
- >>> alpha(1,6.35,[6.35,10.33])
244
- 0.5
187
+ If pH is equal to one of the pKa values the function should return 0.5.
245
188
 
189
+ >>> alpha(1,6.35,[6.35,10.33])
190
+ 0.5
246
191
  """
247
192
  # generate an error if no pKa values are specified
248
193
  if len(pKa_list) == 0:
249
- logger.error("No pKa values given. Cannot calculate distribution coeffiicent.")
250
- return None
194
+ raise ValueError("No pKa values given. Cannot calculate distribution coefficient.")
251
195
 
252
196
  # generate an error if n > number of pKa values
253
197
  if len(pKa_list) < n:
254
- logger.error("Insufficient number of pKa values given. Cannot calculate distribution coeffiicent.")
255
- return None
198
+ raise ValueError("Insufficient number of pKa values given. Cannot calculate distribution coefficient.")
256
199
 
257
- # convert pH to hydrogen ion concentration
258
- Hplus = 10**-pH
200
+ # sort the pKa list
201
+ pKa_list = sorted(pKa_list)
259
202
 
260
203
  # determine how many protons the acid has
261
204
  num_protons = len(pKa_list)
262
205
 
263
206
  # build a list of terms where the term subscript corresponds to the list index
264
- terms_list = []
265
- k_term = 1
266
-
267
- # the 'item' index counts from 0 to the number of protons, inclusive
268
- for item in range(num_protons + 1):
269
- # multiply the preceding k values together
270
- for i in range(len(pKa_list[:item])):
271
- k_term *= 10 ** -pKa_list[i]
272
-
273
- # add the term to the list
274
- terms_list.append(k_term * Hplus ** (num_protons - item))
275
-
276
- # build the expression
277
- numerator = terms_list[n]
278
- denominator = 0
279
- for item in terms_list:
280
- denominator += item
207
+ terms_list = [10 ** (-pH * num_protons)]
208
+ for i in range(len(pKa_list)):
209
+ # multiply together all K values with
210
+ k_term = 1
211
+ for pK in pKa_list[0 : i + 1]:
212
+ k_term *= 10**-pK
213
+ terms_list.append(k_term * 10 ** (-pH * (num_protons - (i + 1))))
214
+ print(terms_list)
281
215
 
282
216
  # return the desired distribution factor
283
- alpha = numerator / denominator
217
+ alpha = terms_list[n] / sum(terms_list)
284
218
  logger.info(
285
219
  "Calculated %s-deprotonated acid distribution coefficient of %s for pKa=%s at pH %s % n,alpha,pKa_list,pH"
286
220
  )
pyEQL/functions.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  pyEQL functions that take Solution objects as inputs or return Solution objects.
3
3
 
4
- :copyright: 2013-2023 by Ryan S. Kingsbury
4
+ :copyright: 2013-2024 by Ryan S. Kingsbury
5
5
  :license: LGPL, see LICENSE for more details.
6
6
 
7
7
  """
@@ -19,7 +19,8 @@ def gibbs_mix(solution1: Solution, solution2: Solution):
19
19
  Return the Gibbs energy change associated with mixing two solutions.
20
20
 
21
21
  Args:
22
- solution1, solution2: The two solutions to be mixed.
22
+ solution1: a solution to be mixed.
23
+ solution2: a solution to be mixed.
23
24
 
24
25
  Returns:
25
26
  The change in Gibbs energy associated with complete mixing of the
@@ -30,7 +31,7 @@ def gibbs_mix(solution1: Solution, solution2: Solution):
30
31
 
31
32
  .. math::
32
33
 
33
- \\Delta_{mix} G = \\sum_i (n_c + n_d) R T \\ln a_b - \\sum_i n_c R T \\ln a_c - \\sum_i n_d R T \\ln a_d
34
+ \Delta_{mix} G = \sum_i {(n_c + n_d) R T \ln a_b} - \sum_i {n_c R T \ln a_c} - \sum_i {n_d R T \ln a_d}
34
35
 
35
36
  Where :math:`n` is the number of moles of substance, :math:`T` is the temperature in kelvin,
36
37
  and subscripts :math:`b`, :math:`c`, and :math:`d` refer to the concentrated, dilute, and blended
@@ -41,8 +42,8 @@ def gibbs_mix(solution1: Solution, solution2: Solution):
41
42
  anion, and water).
42
43
 
43
44
  References:
44
- Koga, Yoshikata, 2007. *Solution Thermodynamics and its Application to Aqueous Solutions:
45
- A differential approach.* Elsevier, 2007, pp. 23-37.
45
+ Koga, Yoshikata, 2007. Solution Thermodynamics and its Application to Aqueous Solutions:
46
+ A differential approach. Elsevier, 2007, pp. 23-37.
46
47
 
47
48
  """
48
49
  concentrate = solution1
@@ -77,7 +78,7 @@ def entropy_mix(solution1: Solution, solution2: Solution):
77
78
 
78
79
  .. math::
79
80
 
80
- \\Delta_{mix} S = \\sum_i (n_c + n_d) R T \\ln x_b - \\sum_i n_c R T \\ln x_c - \\sum_i n_d R T \\ln x_d
81
+ \Delta_{mix} S = \sum_i {(n_c + n_d) R T \ln x_b} - \sum_i {n_c R T \ln x_c} - \sum_i {n_d R T \ln x_d}
81
82
 
82
83
  Where :math:`n` is the number of moles of substance, :math:`T` is the temperature in kelvin,
83
84
  and subscripts :math:`b`, :math:`c`, and :math:`d` refer to the concentrated, dilute, and blended
@@ -111,10 +112,10 @@ def entropy_mix(solution1: Solution, solution2: Solution):
111
112
 
112
113
 
113
114
  def donnan_eql(solution: Solution, fixed_charge: str):
114
- """
115
+ r"""
115
116
  Return a solution object in equilibrium with fixed_charge.
116
117
 
117
- Parameters:
118
+ Args:
118
119
  solution : Solution object
119
120
  The external solution to be brought into equilibrium with the fixed
120
121
  charges
@@ -133,19 +134,20 @@ def donnan_eql(solution: Solution, fixed_charge: str):
133
134
 
134
135
  .. math::
135
136
 
136
- \\frac{a_{-}}{\\bar a_{-}}^{\\frac{1}{z_{-}} \\frac{\\bar a_{+}}{a_{+}}^{\\frac{1}{z_{+}} \
137
- = exp(\\frac{\\Delta \\pi \\bar V}{{RT z_{+} \\nu_{+}}})
137
+ \big(\frac{a_{-}}{\bar a_{-}} \big)^(\frac{1}{z_{-})
138
+ \big(\frac{\bar a_{+}}{a_{+}}\big)^(\frac{1}{z_{+})
139
+ \exp(\frac{\Delta \pi \bar V}{RT z_{+} \nu_{+}})
138
140
 
139
141
  Where subscripts :math:`+` and :math:`-` indicate the cation and anion, respectively,
140
142
  the overbar indicates the membrane phase,
141
- :math:`a` represents activity, :math:`z` represents charge, :math:`\\nu` represents the stoichiometric
143
+ :math:`a` represents activity, :math:`z` represents charge, :math:`\nu` represents the stoichiometric
142
144
  coefficient, :math:`V` represents the partial molar volume of the salt, and
143
- :math:`\\Delta \\pi` is the difference in osmotic pressure between the membrane and the
145
+ :math:`\Delta \pi` is the difference in osmotic pressure between the membrane and the
144
146
  solution phase.
145
147
 
146
148
  In addition, electroneutrality must prevail within the membrane phase:
147
149
 
148
- .. math:: \\bar C_{+} z_{+} + \\bar X + \\bar C_{-} z_{-} = 0
150
+ .. math:: \bar C_{+} z_{+} + \bar X + \bar C_{-} z_{-} = 0
149
151
 
150
152
  Where :math:`C` represents concentration and :math:`X` is the fixed charge concentration
151
153
  in the membrane or ion exchange phase.
pyEQL/logging_system.py CHANGED
@@ -15,7 +15,7 @@ WARNING - assumptions or limitations of module output
15
15
  ERROR - Module could not complete a task due to invalid input or other problem
16
16
  CRITICAL - not used
17
17
 
18
- :copyright: 2013-2023 by Ryan S. Kingsbury
18
+ :copyright: 2013-2024 by Ryan S. Kingsbury
19
19
  :license: LGPL, see LICENSE for more details.
20
20
 
21
21
  """