pyEQL 0.5.2__py3-none-any.whl → 1.1.0__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.
Files changed (62) hide show
  1. pyEQL/__init__.py +50 -43
  2. pyEQL/activity_correction.py +481 -707
  3. pyEQL/database/geothermal.dat +5693 -0
  4. pyEQL/database/llnl.dat +19305 -0
  5. pyEQL/database/phreeqc_license.txt +54 -0
  6. pyEQL/database/pyeql_db.json +35902 -0
  7. pyEQL/engines.py +793 -0
  8. pyEQL/equilibrium.py +148 -228
  9. pyEQL/functions.py +121 -416
  10. pyEQL/pint_custom_units.txt +2 -2
  11. pyEQL/presets/Ringers lactate.yaml +20 -0
  12. pyEQL/presets/normal saline.yaml +17 -0
  13. pyEQL/presets/rainwater.yaml +17 -0
  14. pyEQL/presets/seawater.yaml +29 -0
  15. pyEQL/presets/urine.yaml +26 -0
  16. pyEQL/presets/wastewater.yaml +21 -0
  17. pyEQL/salt_ion_match.py +53 -284
  18. pyEQL/solute.py +126 -191
  19. pyEQL/solution.py +2163 -2090
  20. pyEQL/utils.py +165 -0
  21. pyEQL-1.1.0.dist-info/AUTHORS.md +13 -0
  22. {pyEQL-0.5.2.dist-info → pyEQL-1.1.0.dist-info}/COPYING +1 -1
  23. pyEQL-0.5.2.dist-info/LICENSE → pyEQL-1.1.0.dist-info/LICENSE.txt +3 -7
  24. pyEQL-1.1.0.dist-info/METADATA +129 -0
  25. pyEQL-1.1.0.dist-info/RECORD +27 -0
  26. {pyEQL-0.5.2.dist-info → pyEQL-1.1.0.dist-info}/WHEEL +2 -1
  27. pyEQL/chemical_formula.py +0 -1006
  28. pyEQL/database/Erying_viscosity.tsv +0 -18
  29. pyEQL/database/Jones_Dole_B.tsv +0 -32
  30. pyEQL/database/Jones_Dole_B_inorganic_Jenkins.tsv +0 -75
  31. pyEQL/database/LICENSE +0 -4
  32. pyEQL/database/dielectric_parameter.tsv +0 -30
  33. pyEQL/database/diffusion_coefficient.tsv +0 -116
  34. pyEQL/database/hydrated_radius.tsv +0 -35
  35. pyEQL/database/ionic_radius.tsv +0 -35
  36. pyEQL/database/partial_molar_volume.tsv +0 -22
  37. pyEQL/database/pitzer_activity.tsv +0 -169
  38. pyEQL/database/pitzer_volume.tsv +0 -132
  39. pyEQL/database/template.tsv +0 -14
  40. pyEQL/database.py +0 -300
  41. pyEQL/elements.py +0 -4552
  42. pyEQL/logging_system.py +0 -53
  43. pyEQL/parameter.py +0 -435
  44. pyEQL/tests/__init__.py +0 -32
  45. pyEQL/tests/test_activity.py +0 -578
  46. pyEQL/tests/test_bulk_properties.py +0 -86
  47. pyEQL/tests/test_chemical_formula.py +0 -279
  48. pyEQL/tests/test_debye_length.py +0 -79
  49. pyEQL/tests/test_density.py +0 -106
  50. pyEQL/tests/test_dielectric.py +0 -153
  51. pyEQL/tests/test_effective_pitzer.py +0 -276
  52. pyEQL/tests/test_mixed_electrolyte_activity.py +0 -154
  53. pyEQL/tests/test_osmotic_coeff.py +0 -99
  54. pyEQL/tests/test_pyeql_volume_concentration.py +0 -428
  55. pyEQL/tests/test_salt_matching.py +0 -337
  56. pyEQL/tests/test_solute_properties.py +0 -251
  57. pyEQL/water_properties.py +0 -352
  58. pyEQL-0.5.2.dist-info/AUTHORS +0 -7
  59. pyEQL-0.5.2.dist-info/METADATA +0 -72
  60. pyEQL-0.5.2.dist-info/RECORD +0 -47
  61. pyEQL-0.5.2.dist-info/entry_points.txt +0 -3
  62. {pyEQL-0.5.2.dist-info → pyEQL-1.1.0.dist-info}/top_level.txt +0 -0
pyEQL/equilibrium.py CHANGED
@@ -1,137 +1,107 @@
1
1
  """
2
2
  pyEQL methods for chemical equilibrium calculations (e.g. acid/base, reactions,
3
- redox, complexation, etc.)
3
+ 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-2020 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
  """
11
11
 
12
- # Dependencies
13
12
  # import libraries for scientific functions
14
- import math
15
-
16
- # the pint unit registry
17
- from pyEQL import unit
18
-
19
- # logging system
20
13
  import logging
21
14
 
22
- # add a filter to emit only unique log messages to the handler
23
- from pyEQL.logging_system import Unique
24
-
25
- logger = logging.getLogger(__name__)
26
- unique = Unique()
27
- logger.addFilter(unique)
28
-
29
- # add a handler for console output, since pyEQL is meant to be used interactively
30
- ch = logging.StreamHandler()
15
+ import numpy as np
31
16
 
32
- # create formatter for the log
33
- formatter = logging.Formatter("(%(name)s) - %(levelname)s - %(message)s")
34
-
35
- # add formatter to the handler
36
- ch.setFormatter(formatter)
37
- logger.addHandler(ch)
17
+ from pyEQL import ureg
38
18
 
19
+ logger = logging.getLogger(__name__)
39
20
 
40
- def adjust_temp_pitzer(c1, c2, c3, c4, c5, temp, temp_ref=unit("298.15 K")):
21
+ # TODO - not used. Remove?
22
+ SPECIES_ALIAISES = {
23
+ "Sodium": "Na+",
24
+ "Potassium": "K+",
25
+ "Calcium": "Ca+2",
26
+ "Barium": "Ba+2",
27
+ "Strontium": "Sr+2",
28
+ "Magnesium": "Mg+2",
29
+ "Chloride": "Cl-",
30
+ "Fluoride": "F-",
31
+ "Nitrate": "NO3-",
32
+ "Ammonium": "NH4+",
33
+ "Sulfate": "SO4-2",
34
+ "Phosphate": "PO4-3",
35
+ "Carbonate": "CO3-2",
36
+ "Bicarbonate": "HCO3-",
37
+ }
38
+
39
+
40
+ def adjust_temp_pitzer(c1, c2, c3, c4, c5, temp, temp_ref=ureg.Quantity("298.15 K")):
41
41
  """
42
- Calculate a parameter for th e Pitzer model based on temperature-dependent
43
- coefficients c1,c2,c3,c4,and c5.
44
-
45
- Parameters
46
- ----------
47
- c1, c2, c3, c4, c5: float
48
- Temperature-dependent coefficients for the pitzer parameter of
49
- interest.
50
- temp: Quantity
51
- The temperature at which the Pitzer parameter is to be calculated
52
- temp_ref: Quantity, optional
53
- The reference temperature on which the parameters are based.
54
- 298.15 K if omitted.
55
-
56
- As described in the PHREEQC documentation
42
+ Calculate a parameter for the Pitzer model based on temperature-dependent coefficients c1,c2,c3,c4,and c5.
57
43
 
44
+ Args:
45
+ c1, c2, c3, c4, c5 (float): Temperature-dependent coefficients for the pitzer parameter of interest.
46
+ temp (Quantity): The temperature at which the Pitzer parameter is to be calculated.
47
+ temp_ref (Quantity, optional): The reference temperature on which the parameters are based. Defaults to 298.15 K if omitted.
58
48
 
49
+ Note:
50
+ As described in the PHREEQC documentation.
59
51
  """
60
- pitzer_param = (
52
+ return (
61
53
  c1
62
54
  + c2 * (1 / temp + 1 / temp_ref)
63
- + c2 * math.log(temp / temp_ref)
55
+ + c2 * np.log(temp / temp_ref)
64
56
  + c3 * (temp - temp_ref)
65
- + c4 * (temp ** 2 - temp_ref ** 2)
66
- + c5 * (temp ** -2 - temp_ref ** -2)
57
+ + c4 * (temp**2 - temp_ref**2)
58
+ + c5 * (temp**-2 - temp_ref**-2)
67
59
  )
68
60
 
69
- return pitzer_param
70
-
71
-
72
- def adjust_temp_vanthoff(
73
- equilibrium_constant, enthalpy, temperature, reference_temperature=25 * unit("degC")
74
- ):
75
- """(float,float,number, optional number) -> float
76
61
 
62
+ def adjust_temp_vanthoff(equilibrium_constant, enthalpy, temperature, reference_temperature=ureg.Quantity(25, "degC")):
63
+ r"""
77
64
  Adjust a reaction equilibrium constant from one temperature to another.
78
65
 
79
- Parameters
80
- ----------
81
- equilibrium_constant : float
82
- The reaction equilibrium constant for the reaction
83
- enthalpy : Quantity
84
- The enthalpy change (delta H) for the reaction in kJ/mol. Assumed
85
- independent of temperature (see Notes).
86
- temperature : Quantity
87
- the desired reaction temperature in degrees Celsius
88
- reference_temperature : Quantity, optional
89
- the temperature at which equilibrium_constant is valid. (25 degrees C if omitted).
90
-
91
- Returns
92
- -------
93
- float
94
- adjusted reaction equilibrium constant
66
+ Args:
67
+ equilibrium_constant (float): The reaction equilibrium constant for the reaction.
68
+ enthalpy (Quantity): The enthalpy change (delta H) for the reaction in kJ/mol. Assumed independent of temperature (see Notes).
69
+ temperature (Quantity): The desired reaction temperature in degrees Celsius.
70
+ reference_temperature (Quantity, optional): The temperature at which equilibrium_constant is valid. Defaults to 25 degrees C if omitted.
95
71
 
96
- Notes
97
- -----
98
- This function implements the Van't Hoff equation to adjust measured
99
- equilibrium constants to other temperatures.
72
+ Returns:
73
+ float: The adjusted reaction equilibrium constant.
100
74
 
101
- .. math::
75
+ Note:
76
+ This function implements the Van't Hoff equation to adjust measured equilibrium constants to other temperatures.
102
77
 
103
- ln(K2 / K1) = {\\delta H \\over R} ( {1 \\over T_1} - {1 \\over T_2} )
78
+ .. math::
79
+ ln(K2 / K1) = {\delta H \over R} ( {1 \over T_1} - {1 \over T_2} )
104
80
 
105
- This implementation assumes that the enthalpy is independent of temperature
106
- over the range of interest.[1]
81
+ This implementation assumes that the enthalpy is independent of temperature over the range of interest.
107
82
 
108
- .. [1] Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 53.
109
- Wiley Interscience, 1996.
83
+ References:
84
+ Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 53. Wiley Interscience, 1996.
110
85
 
111
- Examples
112
- --------
113
- >>> adjust_temp_vanthoff(0.15,-197.6*unit('kJ/mol'),42*unit('degC'),25*unit('degC')) #doctest: +ELLIPSIS
114
- 0.00203566...
86
+ Examples:
87
+ >>> adjust_temp_vanthoff(0.15,ureg.Quantity('-197.6 kJ/mol'),ureg.Quantity('42 degC'),ureg.Quantity(' 25degC')) #doctest: +ELLIPSIS
88
+ 0.00203566...
115
89
 
116
- If the 'ref_temperature' parameter is omitted, a default of 25 C is used.
117
-
118
- >>> adjust_temp_vanthoff(0.15,-197.6*unit('kJ/mol'),42*unit('degC')) #doctest: +ELLIPSIS
119
- 0.00203566...
90
+ If the 'ref_temperature' parameter is omitted, a default of 25 C is used.
120
91
 
92
+ >>> adjust_temp_vanthoff(0.15,ureg.Quantity('-197.6 kJ/mol'),ureg.Quantity('42 degC')) #doctest: +ELLIPSIS
93
+ 0.00203566...
121
94
  """
122
- output = equilibrium_constant * math.exp(
123
- enthalpy
124
- / unit.R
125
- * (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
95
+ output = equilibrium_constant * np.exp(
96
+ enthalpy / ureg.R * (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
126
97
  )
127
98
 
128
- logger.info(
129
- "Adjusted equilibrium constant K=%s from %s to %s degrees Celsius with Delta H = %s. "
130
- "Adjusted K = %s % equilibrium_constant,reference_temperature,temperature,enthalpy,output"
99
+ logger.debug(
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"
131
101
  )
132
102
 
133
- logger.warning(
134
- "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"
135
105
  )
136
106
  return output
137
107
 
@@ -140,168 +110,118 @@ def adjust_temp_arrhenius(
140
110
  rate_constant,
141
111
  activation_energy,
142
112
  temperature,
143
- reference_temperature=25 * unit("degC"),
113
+ reference_temperature=ureg.Quantity(25, "degC"),
144
114
  ):
145
- """(float,float,number, optional number) -> float
146
-
115
+ r"""
147
116
  Adjust a reaction equilibrium constant from one temperature to another.
148
117
 
149
- Parameters
150
- ----------
151
- rate_constant : Quantity
152
- The parameter value (usually a rate constant) being adjusted
153
- activation_energy : Quantity
154
- The activation energy of the process, in kJ/mol
155
- temperature : Quantity
156
- the desired reaction temperature.
157
- reference_temperature : Quantity, optional
158
- the temperature at which equilibrium_constant is valid
159
- Defaults to 25 degrees C if omitted.
160
-
161
- Returns
162
- -------
163
- Quantity
164
- The adjusted reaction equilibrium constant
165
-
166
- See Also
167
- --------
168
- kelvin
169
-
170
- Notes
171
- -----
172
- This function implements the Arrhenius equation to adjust measured rate
173
- constants to other temperatures. [1]
174
-
175
- .. math::
176
-
177
- ln(K2 / K1) = {E_a \\over R} ( {1 \\over T_1} - {1 \\over T_2} )
178
-
179
- .. [1] http://chemwiki.ucdavis.edu/Physical_Chemistry/Kinetics/Reaction_Rates/\
180
- Temperature_Dependence_of_Reaction_Rates/Arrhenius_Equation
181
- TODO - add better reference
182
-
183
- Examples
184
- --------
185
- >>> adjust_temp_arrhenius(7,900*unit('kJ/mol'),37*unit('degC'),97*unit('degC')) #doctest: +ELLIPSIS
186
- 1.8867225...e-24
118
+ Args:
119
+ rate_constant (Quantity): The parameter value (usually a rate constant) being adjusted.
120
+ activation_energy (Quantity): The activation energy of the process, in kJ/mol.
121
+ temperature (Quantity): The desired reaction temperature.
122
+ reference_temperature (Quantity, optional): The temperature at which equilibrium_constant is valid. Defaults to 25 degrees C if omitted.
123
+
124
+ Returns:
125
+ Quantity: The adjusted reaction equilibrium constant.
126
+
127
+ Notes:
128
+ This function implements the Arrhenius equation to adjust measured rate constants to other temperatures.
129
+ TODO - add better reference
187
130
 
131
+ .. math::
132
+ ln(\frac{K2}{K1}) = \frac{E_a}{R} ( \frac{1}{T_{1}} - {\frac{1}{T_2}} )
133
+
134
+ References:
135
+ http://chemwiki.ucdavis.edu/Physical_Chemistry/Kinetics/Reaction_Rates/Temperature_Dependence_of_Reaction_Rates/Arrhenius_Equation
136
+
137
+ Examples:
138
+ >>> adjust_temp_arrhenius(7,900*ureg.Quantity('kJ/mol'),37*ureg.Quantity('degC'),97*ureg.Quantity('degC')) #doctest: +ELLIPSIS
139
+ 1.8867225...e-24
188
140
  """
189
- output = rate_constant * math.exp(
190
- activation_energy
191
- / unit.R
192
- * (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
141
+ output = rate_constant * np.exp(
142
+ activation_energy / ureg.R * (1 / reference_temperature.to("K") - 1 / temperature.to("K"))
193
143
  )
194
144
 
195
- logger.info(
196
- "Adjusted parameter %s from %s to %s degrees Celsius with Activation Energy = %s kJ/mol. "
197
- "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}"
198
148
  )
199
149
 
200
150
  return output
201
151
 
202
152
 
203
153
  def alpha(n, pH, pKa_list):
204
- """(int,number,list of numbers)
205
- Returns the acid-base distribution coefficient (alpha) of an acid in the
206
- n-deprotonated form at a given pH.
207
-
208
- Parameters
209
- ----------
210
- n : int
211
- The number of protons that have been lost by the desired form of the
212
- acid. Also the subscript on the alpha value. E.g. for bicarbonate
213
- (HCO3-), n=1 because 1 proton has been lost from the fully-protonated
214
- carbonic acid (H2CO3) form.
215
- pH : float or int
216
- The pH of the solution.
217
- pKa_list : list of floats or ints
218
- The pKa values (negative log of equilibrium constants) for the acid
219
- of interest. There must be a minimum of n pKa values in the list.
220
-
221
- Returns
222
- -------
223
- float
224
- The fraction of total acid present in the specified form.
225
-
226
- Notes
227
- -----
228
- The acid-base distribution coefficient is calculated as follows:[1]
229
-
230
- .. math::
231
-
232
- \\alpha_n = {term_n \\over [H+]^n + k_{a1}[H+]^n-1 + k_{a1}k_{a2}[H+]^n-2 ... k_{a1}k_{a2}...k_{an} }
233
-
234
- Where :math: '\\term_n' refers to the nth term in the denominator, starting from 0
235
-
236
- .. [1] Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed,
237
- pp 127-130. Wiley Interscience, 1996.
238
-
239
- Examples
240
- --------
241
- >>> alpha(1,8,[4.7]) #doctest: +ELLIPSIS
242
- 0.999...
243
-
244
- The sum of all alpha values should equal 1
245
-
246
- >>> alpha(0,8,[6.35,10.33]) #doctest: +ELLIPSIS
247
- 0.021...
248
- >>> alpha(1,8,[6.35,10.33]) #doctest: +ELLIPSIS
249
- 0.979...
250
- >>> alpha(2,8,[6.35,10.33]) #doctest: +ELLIPSIS
251
- 2.043...e-09
252
-
253
- If pH is equal to one of the pKa values the function should return 0.5.
254
-
255
- >>> alpha(1,6.35,[6.35,10.33])
256
- 0.5
257
-
258
- # The function will return an error if the number ofpKa's is less than n.
259
- #
260
- # >>> alpha(2,8,[])
261
- # ERROR: insufficient number of pKa values given
262
- # 0.5
154
+ r"""
155
+ Returns the acid-base distribution coefficient (alpha) of an acid in the n-deprotonated form at a given pH.
156
+
157
+ Args:
158
+ n (int): The number of protons that have been lost by the desired form of the acid. Also the subscript on the
159
+ alpha value. E.g. for bicarbonate (HCO3-), n=1 because 1 proton has been lost from the fully-protonated
160
+ carbonic acid (H2CO3) form.
161
+ pH (float or int): The pH of the solution.
162
+ pKa_list (list of floats or ints): The pKa values (negative log of equilibrium constants) for the acid of
163
+ interest. There must be a minimum of n pKa values in the list.
164
+
165
+ Returns:
166
+ float: The fraction of total acid present in the specified form.
167
+
168
+ Notes:
169
+ The acid-base coefficient is calculated as follows: [stm]_
170
+
171
+ .. math::
172
+
173
+ \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} }
174
+
175
+ Where :math: '\term_n' refers to the nth term in the denominator, starting from 0
263
176
 
177
+ References:
178
+ Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 127-130. Wiley Interscience, 1996.
179
+
180
+ Examples:
181
+ >>> alpha(1,8,[4.7]) #doctest: +ELLIPSIS
182
+ 0.999...
183
+
184
+ The sum of all alpha values should equal 1
185
+
186
+ >>> alpha(0,8,[6.35,10.33]) #doctest: +ELLIPSIS
187
+ 0.021...
188
+ >>> alpha(1,8,[6.35,10.33]) #doctest: +ELLIPSIS
189
+ 0.979...
190
+ >>> alpha(2,8,[6.35,10.33]) #doctest: +ELLIPSIS
191
+ 2.043...e-09
192
+
193
+ If pH is equal to one of the pKa values the function should return 0.5.
194
+
195
+ >>> alpha(1,6.35,[6.35,10.33])
196
+ 0.5
264
197
  """
265
198
  # generate an error if no pKa values are specified
266
199
  if len(pKa_list) == 0:
267
- logger.error("No pKa values given. Cannot calculate distribution coeffiicent.")
268
- return None
200
+ raise ValueError("No pKa values given. Cannot calculate distribution coefficient.")
269
201
 
270
202
  # generate an error if n > number of pKa values
271
203
  if len(pKa_list) < n:
272
- logger.error(
273
- "Insufficient number of pKa values given. Cannot calculate distribution coeffiicent."
274
- )
275
- return None
204
+ raise ValueError("Insufficient number of pKa values given. Cannot calculate distribution coefficient.")
276
205
 
277
- # convert pH to hydrogen ion concentration
278
- Hplus = 10 ** -pH
206
+ # sort the pKa list
207
+ pKa_list = sorted(pKa_list)
279
208
 
280
209
  # determine how many protons the acid has
281
210
  num_protons = len(pKa_list)
282
211
 
283
212
  # build a list of terms where the term subscript corresponds to the list index
284
- terms_list = []
285
- k_term = 1
286
-
287
- # the 'item' index counts from 0 to the number of protons, inclusive
288
- for item in range(0, num_protons + 1):
289
- # multiply the preceding k values together
290
- for i in range(len(pKa_list[:item])):
291
- k_term *= 10 ** -pKa_list[i]
292
-
293
- # add the term to the list
294
- terms_list.append(k_term * Hplus ** (num_protons - item))
295
-
296
- # build the expression
297
- numerator = terms_list[n]
298
- denominator = 0
299
- for item in terms_list:
300
- denominator += item
213
+ terms_list = [10 ** (-pH * num_protons)]
214
+ for i in range(len(pKa_list)):
215
+ # multiply together all K values with
216
+ k_term = 1
217
+ for pK in pKa_list[0 : i + 1]:
218
+ k_term *= 10**-pK
219
+ terms_list.append(k_term * 10 ** (-pH * (num_protons - (i + 1))))
220
+ print(terms_list)
301
221
 
302
222
  # return the desired distribution factor
303
- alpha = numerator / denominator
304
- logger.info(
223
+ alpha = terms_list[n] / sum(terms_list)
224
+ logger.debug(
305
225
  "Calculated %s-deprotonated acid distribution coefficient of %s for pKa=%s at pH %s % n,alpha,pKa_list,pH"
306
226
  )
307
227
  return alpha