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.
- pyEQL/__init__.py +50 -43
- pyEQL/activity_correction.py +481 -707
- pyEQL/database/geothermal.dat +5693 -0
- pyEQL/database/llnl.dat +19305 -0
- pyEQL/database/phreeqc_license.txt +54 -0
- pyEQL/database/pyeql_db.json +35902 -0
- pyEQL/engines.py +793 -0
- pyEQL/equilibrium.py +148 -228
- pyEQL/functions.py +121 -416
- pyEQL/pint_custom_units.txt +2 -2
- pyEQL/presets/Ringers lactate.yaml +20 -0
- pyEQL/presets/normal saline.yaml +17 -0
- pyEQL/presets/rainwater.yaml +17 -0
- pyEQL/presets/seawater.yaml +29 -0
- pyEQL/presets/urine.yaml +26 -0
- pyEQL/presets/wastewater.yaml +21 -0
- pyEQL/salt_ion_match.py +53 -284
- pyEQL/solute.py +126 -191
- pyEQL/solution.py +2163 -2090
- pyEQL/utils.py +165 -0
- pyEQL-1.1.0.dist-info/AUTHORS.md +13 -0
- {pyEQL-0.5.2.dist-info → pyEQL-1.1.0.dist-info}/COPYING +1 -1
- pyEQL-0.5.2.dist-info/LICENSE → pyEQL-1.1.0.dist-info/LICENSE.txt +3 -7
- pyEQL-1.1.0.dist-info/METADATA +129 -0
- pyEQL-1.1.0.dist-info/RECORD +27 -0
- {pyEQL-0.5.2.dist-info → pyEQL-1.1.0.dist-info}/WHEEL +2 -1
- pyEQL/chemical_formula.py +0 -1006
- pyEQL/database/Erying_viscosity.tsv +0 -18
- pyEQL/database/Jones_Dole_B.tsv +0 -32
- pyEQL/database/Jones_Dole_B_inorganic_Jenkins.tsv +0 -75
- pyEQL/database/LICENSE +0 -4
- pyEQL/database/dielectric_parameter.tsv +0 -30
- pyEQL/database/diffusion_coefficient.tsv +0 -116
- pyEQL/database/hydrated_radius.tsv +0 -35
- pyEQL/database/ionic_radius.tsv +0 -35
- pyEQL/database/partial_molar_volume.tsv +0 -22
- pyEQL/database/pitzer_activity.tsv +0 -169
- pyEQL/database/pitzer_volume.tsv +0 -132
- pyEQL/database/template.tsv +0 -14
- pyEQL/database.py +0 -300
- pyEQL/elements.py +0 -4552
- pyEQL/logging_system.py +0 -53
- pyEQL/parameter.py +0 -435
- pyEQL/tests/__init__.py +0 -32
- pyEQL/tests/test_activity.py +0 -578
- pyEQL/tests/test_bulk_properties.py +0 -86
- pyEQL/tests/test_chemical_formula.py +0 -279
- pyEQL/tests/test_debye_length.py +0 -79
- pyEQL/tests/test_density.py +0 -106
- pyEQL/tests/test_dielectric.py +0 -153
- pyEQL/tests/test_effective_pitzer.py +0 -276
- pyEQL/tests/test_mixed_electrolyte_activity.py +0 -154
- pyEQL/tests/test_osmotic_coeff.py +0 -99
- pyEQL/tests/test_pyeql_volume_concentration.py +0 -428
- pyEQL/tests/test_salt_matching.py +0 -337
- pyEQL/tests/test_solute_properties.py +0 -251
- pyEQL/water_properties.py +0 -352
- pyEQL-0.5.2.dist-info/AUTHORS +0 -7
- pyEQL-0.5.2.dist-info/METADATA +0 -72
- pyEQL-0.5.2.dist-info/RECORD +0 -47
- pyEQL-0.5.2.dist-info/entry_points.txt +0 -3
- {pyEQL-0.5.2.dist-info → pyEQL-1.1.0.dist-info}/top_level.txt +0 -0
pyEQL/tests/test_activity.py
DELETED
|
@@ -1,578 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
pyEQL activity correction methods test suite
|
|
3
|
-
============================================
|
|
4
|
-
|
|
5
|
-
This file contains tests for some of the activity correction methods
|
|
6
|
-
employed by pyEQL.
|
|
7
|
-
|
|
8
|
-
NOTE: generally, these tests check the module output against experimental
|
|
9
|
-
data rather than the theoretical result of the respective functions. In some
|
|
10
|
-
cases, the output is also tested against a well-established model published
|
|
11
|
-
by USGS(PHREEQC)
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
import pyEQL
|
|
15
|
-
import unittest
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class Test_activity_pitzer_nacl(unittest.TestCase, pyEQL.CustomAssertions):
|
|
19
|
-
"""
|
|
20
|
-
test Pitzer model for activity of NaCl
|
|
21
|
-
------------------------------------------------
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
def setUp(self):
|
|
25
|
-
self.s1 = pyEQL.Solution([["Na+", "0.1 mol/L"], ["Cl-", "0.1 mol/L"]])
|
|
26
|
-
|
|
27
|
-
# relative error tolerance for assertWithinExperimentalError
|
|
28
|
-
self.tol = 0.05
|
|
29
|
-
|
|
30
|
-
def test_activity_pitzer_coeff_units(self):
|
|
31
|
-
# the activity coefficient should be dimensionless
|
|
32
|
-
result = self.s1.get_activity_coefficient("Na+").dimensionality
|
|
33
|
-
self.assertEqual(result, "")
|
|
34
|
-
|
|
35
|
-
def test_activity_pitzer_units(self):
|
|
36
|
-
# the activity should be dimensionless
|
|
37
|
-
result = self.s1.get_activity("Na+").dimensionality
|
|
38
|
-
self.assertEqual(result, "")
|
|
39
|
-
|
|
40
|
-
def test_activity_pitzer_equality(self):
|
|
41
|
-
# the activity coefficient of both the Na+ and Cl- should be the same
|
|
42
|
-
a1 = self.s1.get_activity_coefficient("Na+")
|
|
43
|
-
a2 = self.s1.get_activity_coefficient("Cl-")
|
|
44
|
-
self.assertEqual(a1, a2)
|
|
45
|
-
|
|
46
|
-
def test_activity_crc_HCl(self):
|
|
47
|
-
"""
|
|
48
|
-
calculate the activity coefficient of HCl at each concentration and compare
|
|
49
|
-
to experimental data
|
|
50
|
-
|
|
51
|
-
Experimental activity coefficient values at 25 degC are found in
|
|
52
|
-
*CRC Handbook of Chemistry and Physics*, Mean Activity Coefficients of Electrolytes as a Function of
|
|
53
|
-
Concentration, in: W.M. Haynes (Ed.), 92nd ed., 2011.
|
|
54
|
-
|
|
55
|
-
"""
|
|
56
|
-
cation = "H+"
|
|
57
|
-
nu_cation = 1
|
|
58
|
-
anion = "Cl-"
|
|
59
|
-
nu_anion = 1
|
|
60
|
-
|
|
61
|
-
# list of concentrations to test, mol/kg
|
|
62
|
-
conc_list = [0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5]
|
|
63
|
-
|
|
64
|
-
# list of published experimental activity coefficients
|
|
65
|
-
pub_activity_coeff = [
|
|
66
|
-
0.965,
|
|
67
|
-
0.952,
|
|
68
|
-
0.929,
|
|
69
|
-
0.905,
|
|
70
|
-
0.876,
|
|
71
|
-
0.832,
|
|
72
|
-
0.797,
|
|
73
|
-
0.768,
|
|
74
|
-
0.759,
|
|
75
|
-
0.811,
|
|
76
|
-
1.009,
|
|
77
|
-
2.380,
|
|
78
|
-
]
|
|
79
|
-
|
|
80
|
-
for i in range(len(conc_list)):
|
|
81
|
-
with self.subTest(conc=conc_list[i]):
|
|
82
|
-
conc_c = str(conc_list[i] * nu_cation) + "mol/kg"
|
|
83
|
-
conc_a = str(conc_list[i] * nu_anion) + "mol/kg"
|
|
84
|
-
sol = pyEQL.Solution()
|
|
85
|
-
sol.add_solute(cation, conc_c)
|
|
86
|
-
sol.add_solute(anion, conc_a)
|
|
87
|
-
act_cat = sol.get_activity_coefficient(cation)
|
|
88
|
-
act_an = sol.get_activity_coefficient(anion)
|
|
89
|
-
result = (act_cat ** nu_cation * act_an ** nu_anion) ** (
|
|
90
|
-
1 / (nu_cation + nu_anion)
|
|
91
|
-
)
|
|
92
|
-
expected = pub_activity_coeff[i]
|
|
93
|
-
|
|
94
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
95
|
-
|
|
96
|
-
def test_activity_crc_CsI(self):
|
|
97
|
-
"""
|
|
98
|
-
calculate the activity coefficient of CsI at each concentration and compare
|
|
99
|
-
to experimental data
|
|
100
|
-
|
|
101
|
-
Experimental activity coefficient values at 25 degC are found in
|
|
102
|
-
*CRC Handbook of Chemistry and Physics*, Mean Activity Coefficients of Electrolytes as a Function of
|
|
103
|
-
Concentration, in: W.M. Haynes (Ed.), 92nd ed., 2011.
|
|
104
|
-
|
|
105
|
-
"""
|
|
106
|
-
cation = "Cs+"
|
|
107
|
-
nu_cation = 1
|
|
108
|
-
anion = "I-"
|
|
109
|
-
nu_anion = 1
|
|
110
|
-
|
|
111
|
-
# list of concentrations to test, mol/kg
|
|
112
|
-
conc_list = [0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2]
|
|
113
|
-
|
|
114
|
-
# list of published experimental activity coefficients
|
|
115
|
-
pub_activity_coeff = [
|
|
116
|
-
0.965,
|
|
117
|
-
0.951,
|
|
118
|
-
0.925,
|
|
119
|
-
0.898,
|
|
120
|
-
0.863,
|
|
121
|
-
0.804,
|
|
122
|
-
0.749,
|
|
123
|
-
0.688,
|
|
124
|
-
0.601,
|
|
125
|
-
0.534,
|
|
126
|
-
0.470,
|
|
127
|
-
]
|
|
128
|
-
|
|
129
|
-
for i in range(len(conc_list)):
|
|
130
|
-
with self.subTest(conc=conc_list[i]):
|
|
131
|
-
conc_c = str(conc_list[i] * nu_cation) + "mol/kg"
|
|
132
|
-
conc_a = str(conc_list[i] * nu_anion) + "mol/kg"
|
|
133
|
-
sol = pyEQL.Solution()
|
|
134
|
-
sol.add_solute(cation, conc_c)
|
|
135
|
-
sol.add_solute(anion, conc_a)
|
|
136
|
-
act_cat = sol.get_activity_coefficient(cation)
|
|
137
|
-
act_an = sol.get_activity_coefficient(anion)
|
|
138
|
-
result = (act_cat ** nu_cation * act_an ** nu_anion) ** (
|
|
139
|
-
1 / (nu_cation + nu_anion)
|
|
140
|
-
)
|
|
141
|
-
expected = pub_activity_coeff[i]
|
|
142
|
-
|
|
143
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
144
|
-
|
|
145
|
-
def test_activity_crc_bacl2(self):
|
|
146
|
-
"""
|
|
147
|
-
calculate the activity coefficient of BaCl2 at each concentration and compare
|
|
148
|
-
to experimental data
|
|
149
|
-
|
|
150
|
-
Experimental activity coefficient values at 25 degC are found in
|
|
151
|
-
*CRC Handbook of Chemistry and Physics*, Mean Activity Coefficients of Electrolytes as a Function of
|
|
152
|
-
Concentration, in: W.M. Haynes (Ed.), 92nd ed., 2011.
|
|
153
|
-
|
|
154
|
-
"""
|
|
155
|
-
# list of concentrations to test, mol/kg
|
|
156
|
-
conc_list = [0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1]
|
|
157
|
-
|
|
158
|
-
# list of published experimental activity coefficients
|
|
159
|
-
pub_activity_coeff = [
|
|
160
|
-
0.887,
|
|
161
|
-
0.849,
|
|
162
|
-
0.782,
|
|
163
|
-
0.721,
|
|
164
|
-
0.653,
|
|
165
|
-
0.559,
|
|
166
|
-
0.492,
|
|
167
|
-
0.436,
|
|
168
|
-
0.391,
|
|
169
|
-
0.393,
|
|
170
|
-
]
|
|
171
|
-
|
|
172
|
-
for i in range(len(conc_list)):
|
|
173
|
-
with self.subTest(conc=conc_list[i]):
|
|
174
|
-
conc_c = str(conc_list[i]) + "mol/kg"
|
|
175
|
-
conc_a = str(conc_list[i] * 2) + "mol/kg"
|
|
176
|
-
sol = pyEQL.Solution()
|
|
177
|
-
sol.add_solute("Ba+2", conc_c)
|
|
178
|
-
sol.add_solute("Cl-", conc_a)
|
|
179
|
-
act_cat = sol.get_activity_coefficient("Ba+2")
|
|
180
|
-
act_an = sol.get_activity_coefficient("Cl-")
|
|
181
|
-
result = (act_cat ** 1 * act_an ** 2) ** (1 / 3)
|
|
182
|
-
expected = pub_activity_coeff[i]
|
|
183
|
-
|
|
184
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
185
|
-
|
|
186
|
-
def test_activity_crc_licl(self):
|
|
187
|
-
"""
|
|
188
|
-
calculate the activity coefficient of LiCl at each concentration and compare
|
|
189
|
-
to experimental data
|
|
190
|
-
|
|
191
|
-
Experimental activity coefficient values at 25 degC are found in
|
|
192
|
-
*CRC Handbook of Chemistry and Physics*, Mean Activity Coefficients of Electrolytes as a Function of
|
|
193
|
-
Concentration, in: W.M. Haynes (Ed.), 92nd ed., 2011.
|
|
194
|
-
|
|
195
|
-
"""
|
|
196
|
-
# list of concentrations to test, mol/kg
|
|
197
|
-
conc_list = [0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5]
|
|
198
|
-
|
|
199
|
-
# list of published experimental activity coefficients
|
|
200
|
-
pub_activity_coeff = [
|
|
201
|
-
0.965,
|
|
202
|
-
0.952,
|
|
203
|
-
0.928,
|
|
204
|
-
0.904,
|
|
205
|
-
0.874,
|
|
206
|
-
0.827,
|
|
207
|
-
0.789,
|
|
208
|
-
0.756,
|
|
209
|
-
0.739,
|
|
210
|
-
0.775,
|
|
211
|
-
0.924,
|
|
212
|
-
2.0,
|
|
213
|
-
]
|
|
214
|
-
|
|
215
|
-
for i in range(len(conc_list)):
|
|
216
|
-
with self.subTest(conc=conc_list[i]):
|
|
217
|
-
conc_c = str(conc_list[i]) + "mol/kg"
|
|
218
|
-
conc_a = str(conc_list[i]) + "mol/kg"
|
|
219
|
-
sol = pyEQL.Solution()
|
|
220
|
-
sol.add_solute("Li+", conc_c)
|
|
221
|
-
sol.add_solute("Cl-", conc_a)
|
|
222
|
-
act_cat = sol.get_activity_coefficient("Li+")
|
|
223
|
-
act_an = sol.get_activity_coefficient("Cl-")
|
|
224
|
-
result = (act_cat ** 1 * act_an ** 1) ** (1 / 2)
|
|
225
|
-
expected = pub_activity_coeff[i]
|
|
226
|
-
|
|
227
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
228
|
-
|
|
229
|
-
def test_activity_crc_rbcl(self):
|
|
230
|
-
"""
|
|
231
|
-
calculate the activity coefficient of RbCl at each concentration and compare
|
|
232
|
-
to experimental data
|
|
233
|
-
|
|
234
|
-
Experimental activity coefficient values at 25 degC are found in
|
|
235
|
-
*CRC Handbook of Chemistry and Physics*, Mean Activity Coefficients of Electrolytes as a Function of
|
|
236
|
-
Concentration, in: W.M. Haynes (Ed.), 92nd ed., 2011.
|
|
237
|
-
|
|
238
|
-
"""
|
|
239
|
-
# list of concentrations to test, mol/kg
|
|
240
|
-
conc_list = [0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5]
|
|
241
|
-
|
|
242
|
-
# list of published experimental activity coefficients
|
|
243
|
-
pub_activity_coeff = [
|
|
244
|
-
0.965,
|
|
245
|
-
0.951,
|
|
246
|
-
0.926,
|
|
247
|
-
0.900,
|
|
248
|
-
0.867,
|
|
249
|
-
0.811,
|
|
250
|
-
0.761,
|
|
251
|
-
0.707,
|
|
252
|
-
0.633,
|
|
253
|
-
0.583,
|
|
254
|
-
0.546,
|
|
255
|
-
0.544,
|
|
256
|
-
]
|
|
257
|
-
|
|
258
|
-
for i in range(len(conc_list)):
|
|
259
|
-
with self.subTest(conc=conc_list[i]):
|
|
260
|
-
conc_c = str(conc_list[i]) + "mol/kg"
|
|
261
|
-
conc_a = str(conc_list[i]) + "mol/kg"
|
|
262
|
-
sol = pyEQL.Solution()
|
|
263
|
-
sol.add_solute("Rb+", conc_c)
|
|
264
|
-
sol.add_solute("Cl-", conc_a)
|
|
265
|
-
result = sol.get_activity_coefficient("Rb+")
|
|
266
|
-
expected = pub_activity_coeff[i]
|
|
267
|
-
|
|
268
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
269
|
-
|
|
270
|
-
def test_activity_crc_MgCl2(self):
|
|
271
|
-
"""
|
|
272
|
-
calculate the activity coefficient of MgCl2 at each concentration and compare
|
|
273
|
-
to experimental data
|
|
274
|
-
|
|
275
|
-
Experimental activity coefficient values at 25 degC are found in
|
|
276
|
-
*CRC Handbook of Chemistry and Physics*, Mean Activity Coefficients of Electrolytes as a Function of
|
|
277
|
-
Concentration, in: W.M. Haynes (Ed.), 92nd ed., 2011.
|
|
278
|
-
|
|
279
|
-
"""
|
|
280
|
-
cation = "Mg+2"
|
|
281
|
-
nu_cation = 1
|
|
282
|
-
anion = "Cl-"
|
|
283
|
-
nu_anion = 2
|
|
284
|
-
|
|
285
|
-
# list of concentrations to test, mol/kg
|
|
286
|
-
conc_list = [0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5]
|
|
287
|
-
|
|
288
|
-
# list of published experimental activity coefficients
|
|
289
|
-
pub_activity_coeff = [
|
|
290
|
-
0.889,
|
|
291
|
-
0.852,
|
|
292
|
-
0.790,
|
|
293
|
-
0.734,
|
|
294
|
-
0.672,
|
|
295
|
-
0.590,
|
|
296
|
-
0.535,
|
|
297
|
-
0.493,
|
|
298
|
-
0.485,
|
|
299
|
-
0.577,
|
|
300
|
-
1.065,
|
|
301
|
-
14.40,
|
|
302
|
-
]
|
|
303
|
-
|
|
304
|
-
for i in range(len(conc_list)):
|
|
305
|
-
with self.subTest(conc=conc_list[i]):
|
|
306
|
-
conc_c = str(conc_list[i] * nu_cation) + "mol/kg"
|
|
307
|
-
conc_a = str(conc_list[i] * nu_anion) + "mol/kg"
|
|
308
|
-
sol = pyEQL.Solution()
|
|
309
|
-
sol.add_solute(cation, conc_c)
|
|
310
|
-
sol.add_solute(anion, conc_a)
|
|
311
|
-
act_cat = sol.get_activity_coefficient(cation)
|
|
312
|
-
act_an = sol.get_activity_coefficient(anion)
|
|
313
|
-
result = (act_cat ** nu_cation * act_an ** nu_anion) ** (
|
|
314
|
-
1 / (nu_cation + nu_anion)
|
|
315
|
-
)
|
|
316
|
-
expected = pub_activity_coeff[i]
|
|
317
|
-
|
|
318
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
319
|
-
|
|
320
|
-
def test_activity_crc_KBr(self):
|
|
321
|
-
"""
|
|
322
|
-
calculate the activity coefficient of KBr at each concentration and compare
|
|
323
|
-
to experimental data
|
|
324
|
-
|
|
325
|
-
Experimental activity coefficient values at 25 degC are found in
|
|
326
|
-
*CRC Handbook of Chemistry and Physics*, Mean Activity Coefficients of Electrolytes as a Function of
|
|
327
|
-
Concentration, in: W.M. Haynes (Ed.), 92nd ed., 2011.
|
|
328
|
-
|
|
329
|
-
"""
|
|
330
|
-
cation = "K+"
|
|
331
|
-
nu_cation = 1
|
|
332
|
-
anion = "Br-"
|
|
333
|
-
nu_anion = 1
|
|
334
|
-
|
|
335
|
-
# list of concentrations to test, mol/kg
|
|
336
|
-
conc_list = [0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5]
|
|
337
|
-
|
|
338
|
-
# list of published experimental activity coefficients
|
|
339
|
-
pub_activity_coeff = [
|
|
340
|
-
0.965,
|
|
341
|
-
0.952,
|
|
342
|
-
0.927,
|
|
343
|
-
0.902,
|
|
344
|
-
0.870,
|
|
345
|
-
0.817,
|
|
346
|
-
0.771,
|
|
347
|
-
0.722,
|
|
348
|
-
0.658,
|
|
349
|
-
0.617,
|
|
350
|
-
0.593,
|
|
351
|
-
0.626,
|
|
352
|
-
]
|
|
353
|
-
|
|
354
|
-
for i in range(len(conc_list)):
|
|
355
|
-
with self.subTest(conc=conc_list[i]):
|
|
356
|
-
conc_c = str(conc_list[i] * nu_cation) + "mol/kg"
|
|
357
|
-
conc_a = str(conc_list[i] * nu_anion) + "mol/kg"
|
|
358
|
-
sol = pyEQL.Solution()
|
|
359
|
-
sol.add_solute(cation, conc_c)
|
|
360
|
-
sol.add_solute(anion, conc_a)
|
|
361
|
-
act_cat = sol.get_activity_coefficient(cation)
|
|
362
|
-
act_an = sol.get_activity_coefficient(anion)
|
|
363
|
-
result = (act_cat ** nu_cation * act_an ** nu_anion) ** (
|
|
364
|
-
1 / (nu_cation + nu_anion)
|
|
365
|
-
)
|
|
366
|
-
expected = pub_activity_coeff[i]
|
|
367
|
-
|
|
368
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
369
|
-
|
|
370
|
-
def test_activity_crc_k2so4(self):
|
|
371
|
-
"""
|
|
372
|
-
calculate the activity coefficient of K2SO4 at each concentration and compare
|
|
373
|
-
to experimental data
|
|
374
|
-
|
|
375
|
-
Experimental activity coefficient values at 25 degC are found in
|
|
376
|
-
*CRC Handbook of Chemistry and Physics*, Mean Activity Coefficients of Electrolytes as a Function of
|
|
377
|
-
Concentration, in: W.M. Haynes (Ed.), 92nd ed., 2011.
|
|
378
|
-
|
|
379
|
-
"""
|
|
380
|
-
# list of concentrations to test, mol/kg
|
|
381
|
-
conc_list = [0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5]
|
|
382
|
-
|
|
383
|
-
# list of published experimental activity coefficients
|
|
384
|
-
pub_activity_coeff = [
|
|
385
|
-
0.885,
|
|
386
|
-
0.844,
|
|
387
|
-
0.772,
|
|
388
|
-
0.704,
|
|
389
|
-
0.625,
|
|
390
|
-
0.511,
|
|
391
|
-
0.424,
|
|
392
|
-
0.343,
|
|
393
|
-
0.251,
|
|
394
|
-
]
|
|
395
|
-
|
|
396
|
-
for i in range(len(conc_list)):
|
|
397
|
-
with self.subTest(conc=conc_list[i]):
|
|
398
|
-
conc_c = str(conc_list[i] * 2) + "mol/kg"
|
|
399
|
-
conc_a = str(conc_list[i]) + "mol/kg"
|
|
400
|
-
sol = pyEQL.Solution()
|
|
401
|
-
sol.add_solute("K+", conc_c)
|
|
402
|
-
sol.add_solute("SO4-2", conc_a)
|
|
403
|
-
act_cat = sol.get_activity_coefficient("K+")
|
|
404
|
-
act_an = sol.get_activity_coefficient("SO4-2")
|
|
405
|
-
result = (act_cat ** 2 * act_an ** 1) ** (1 / 3)
|
|
406
|
-
expected = pub_activity_coeff[i]
|
|
407
|
-
|
|
408
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
409
|
-
|
|
410
|
-
def test_activity_pitzer_nacl_1(self):
|
|
411
|
-
"""
|
|
412
|
-
calculate the activity coefficient at each concentration and compare
|
|
413
|
-
to experimental data
|
|
414
|
-
|
|
415
|
-
Experimental activity coefficient values at 25 degC are found in
|
|
416
|
-
*J. Phys. Chem. Reference Data* Vol 13 (1), 1984, p.53.
|
|
417
|
-
|
|
418
|
-
"""
|
|
419
|
-
# list of concentrations to test, mol/kg
|
|
420
|
-
conc_list = [0.1, 0.25, 0.5, 0.75, 1, 2, 3, 4, 5, 6]
|
|
421
|
-
|
|
422
|
-
# list of published experimental activity coefficients
|
|
423
|
-
pub_activity_coeff = [
|
|
424
|
-
0.778,
|
|
425
|
-
0.72,
|
|
426
|
-
0.681,
|
|
427
|
-
0.665,
|
|
428
|
-
0.657,
|
|
429
|
-
0.669,
|
|
430
|
-
0.714,
|
|
431
|
-
0.782,
|
|
432
|
-
0.873,
|
|
433
|
-
0.987,
|
|
434
|
-
]
|
|
435
|
-
|
|
436
|
-
for i in range(len(conc_list)):
|
|
437
|
-
with self.subTest(conc=conc_list[i]):
|
|
438
|
-
conc = str(conc_list[i]) + "mol/kg"
|
|
439
|
-
sol = pyEQL.Solution()
|
|
440
|
-
sol.add_solute("Na+", conc)
|
|
441
|
-
sol.add_solute("Cl-", conc)
|
|
442
|
-
result = sol.get_activity_coefficient("Na+")
|
|
443
|
-
expected = pub_activity_coeff[i]
|
|
444
|
-
|
|
445
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
446
|
-
|
|
447
|
-
# The pitzer model diverges a bit from experimental data at high concentration
|
|
448
|
-
@unittest.expectedFailure
|
|
449
|
-
def test_water_activity_pitzer_nacl_1(self):
|
|
450
|
-
"""
|
|
451
|
-
calculate the water activity at each concentration and compare
|
|
452
|
-
to experimental data
|
|
453
|
-
|
|
454
|
-
Experimental osmotic coefficients for NaCl are found in:
|
|
455
|
-
Pitzer and Pelper, 1984. "Thermodyamic Properties of Aqueous Sodium Chloride Solutions"
|
|
456
|
-
*J. Phys. Chem. Ref. Data* 13(1).
|
|
457
|
-
|
|
458
|
-
Osmotic coefficients were converted into water activity according to the equation
|
|
459
|
-
found in
|
|
460
|
-
Blandamer, Mike J., Engberts, Jan B. F. N., Gleeson, Peter T., Reis,
|
|
461
|
-
Joao Carlos R., 2005. "Activity of water in aqueous systems: A frequently
|
|
462
|
-
neglected property." *Chemical Society Review* 34, 440-458.
|
|
463
|
-
|
|
464
|
-
.. math:: ln a_w = - \\Phi M_w \\sum_i m_i
|
|
465
|
-
|
|
466
|
-
Where :math:`M_w` is the molar mass of water (0.018015 kg/mol) and :math:`m_i` is the molal concentration
|
|
467
|
-
of each species.
|
|
468
|
-
|
|
469
|
-
"""
|
|
470
|
-
# list of concentrations to test, mol/kg
|
|
471
|
-
conc_list = [0.1, 0.25, 0.5, 0.75, 1, 2, 3, 4, 5, 6]
|
|
472
|
-
|
|
473
|
-
# list of published experimental water activity
|
|
474
|
-
pub_water_activity = [
|
|
475
|
-
0.9964,
|
|
476
|
-
0.9910,
|
|
477
|
-
0.9821,
|
|
478
|
-
0.9733,
|
|
479
|
-
0.9646,
|
|
480
|
-
0.9304,
|
|
481
|
-
0.8975,
|
|
482
|
-
0.8657,
|
|
483
|
-
0.8351,
|
|
484
|
-
0.8055,
|
|
485
|
-
]
|
|
486
|
-
|
|
487
|
-
for i in range(len(conc_list)):
|
|
488
|
-
with self.subTest(conc=conc_list[i]):
|
|
489
|
-
conc = str(conc_list[i]) + "mol/kg"
|
|
490
|
-
sol = pyEQL.Solution()
|
|
491
|
-
sol.add_solute("Na+", conc)
|
|
492
|
-
sol.add_solute("Cl-", conc)
|
|
493
|
-
result = sol.get_water_activity()
|
|
494
|
-
expected = pub_water_activity[i]
|
|
495
|
-
|
|
496
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
497
|
-
|
|
498
|
-
def test_activity_pitzer_phreeqc_nacl_2(self):
|
|
499
|
-
"""
|
|
500
|
-
calculate the activity coefficient at each concentration and compare
|
|
501
|
-
to the output of the PHREEQC model
|
|
502
|
-
|
|
503
|
-
PHREEQC version 3.1.4 was used to calculate density, conductivity, water
|
|
504
|
-
activity, and NaCl activity coefficient for NaCl solutions up to 6m.
|
|
505
|
-
The Pitzer model (pitzer.dat) database was used.
|
|
506
|
-
<http://wwwbrr.cr.usgs.gov/projects/GWC_coupled/phreeqc/>
|
|
507
|
-
|
|
508
|
-
"""
|
|
509
|
-
# list of concentrations to test, mol/kg
|
|
510
|
-
conc_list = [0.1, 0.25, 0.5, 0.75, 1, 2, 3, 4, 5, 6]
|
|
511
|
-
|
|
512
|
-
# list of modeled activity coefficients
|
|
513
|
-
phreeqc_pitzer_activity_coeff = [
|
|
514
|
-
0.7771,
|
|
515
|
-
0.7186,
|
|
516
|
-
0.6799,
|
|
517
|
-
0.6629,
|
|
518
|
-
0.6561,
|
|
519
|
-
0.6675,
|
|
520
|
-
0.7128,
|
|
521
|
-
0.7825,
|
|
522
|
-
0.8729,
|
|
523
|
-
0.9874,
|
|
524
|
-
]
|
|
525
|
-
|
|
526
|
-
for i in range(len(conc_list)):
|
|
527
|
-
with self.subTest(conc=conc_list[i]):
|
|
528
|
-
conc = str(conc_list[i]) + "mol/kg"
|
|
529
|
-
sol = pyEQL.Solution()
|
|
530
|
-
sol.add_solute("Na+", conc)
|
|
531
|
-
sol.add_solute("Cl-", conc)
|
|
532
|
-
result = sol.get_activity_coefficient("Na+")
|
|
533
|
-
expected = phreeqc_pitzer_activity_coeff[i]
|
|
534
|
-
|
|
535
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
536
|
-
|
|
537
|
-
def test_water_activity_phreeqc_pitzer_nacl_2(self):
|
|
538
|
-
"""
|
|
539
|
-
calculate the water activity at each concentration and compare
|
|
540
|
-
to the output of the PHREEQC model
|
|
541
|
-
|
|
542
|
-
PHREEQC version 3.1.4 was used to calculate density, conductivity, water
|
|
543
|
-
activity, and NaCl activity coefficient for NaCl solutions up to 6m.
|
|
544
|
-
The Pitzer model (pitzer.dat) database was used.
|
|
545
|
-
<http://wwwbrr.cr.usgs.gov/projects/GWC_coupled/phreeqc/>
|
|
546
|
-
|
|
547
|
-
"""
|
|
548
|
-
# list of concentrations to test, mol/kg
|
|
549
|
-
conc_list = [0.1, 0.25, 0.5, 0.75, 1, 2, 3, 4, 5, 6]
|
|
550
|
-
|
|
551
|
-
# list of modeled water activities
|
|
552
|
-
phreeqc_pitzer_water_activity = [
|
|
553
|
-
0.997,
|
|
554
|
-
0.992,
|
|
555
|
-
0.984,
|
|
556
|
-
0.975,
|
|
557
|
-
0.967,
|
|
558
|
-
0.932,
|
|
559
|
-
0.893,
|
|
560
|
-
0.851,
|
|
561
|
-
0.807,
|
|
562
|
-
0.759,
|
|
563
|
-
]
|
|
564
|
-
|
|
565
|
-
for i in range(len(conc_list)):
|
|
566
|
-
with self.subTest(conc=conc_list[i]):
|
|
567
|
-
conc = str(conc_list[i]) + "mol/kg"
|
|
568
|
-
sol = pyEQL.Solution()
|
|
569
|
-
sol.add_solute("Na+", conc)
|
|
570
|
-
sol.add_solute("Cl-", conc)
|
|
571
|
-
result = sol.get_water_activity()
|
|
572
|
-
expected = phreeqc_pitzer_water_activity[i]
|
|
573
|
-
|
|
574
|
-
self.assertWithinExperimentalError(result, expected, self.tol)
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
if __name__ == "__main__":
|
|
578
|
-
unittest.main()
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
pyEQL test suite for bulk property calculations
|
|
3
|
-
===============================================
|
|
4
|
-
|
|
5
|
-
This file contains tests for the bulk properties calculated by
|
|
6
|
-
Solution class methods. Currently included methods are:
|
|
7
|
-
|
|
8
|
-
- get_hardness()
|
|
9
|
-
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
import pyEQL
|
|
13
|
-
import unittest
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class test_hardness(unittest.TestCase, pyEQL.CustomAssertions):
|
|
17
|
-
"""
|
|
18
|
-
test the get_hardness() method
|
|
19
|
-
------------------------------
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
# an empty solution should have zero hardness
|
|
23
|
-
def test_empty_solution(self):
|
|
24
|
-
s1 = pyEQL.Solution()
|
|
25
|
-
result = s1.get_hardness().magnitude
|
|
26
|
-
expected = 0
|
|
27
|
-
|
|
28
|
-
self.assertEqual(result, expected)
|
|
29
|
-
|
|
30
|
-
# a solution with only monovalent ions should have zero hardness
|
|
31
|
-
def test_hardness_1(self):
|
|
32
|
-
s1 = pyEQL.Solution([["Na+", "0.2 mol/L"], ["Cl-", "0.2 mol/L"]])
|
|
33
|
-
result = s1.get_hardness().magnitude
|
|
34
|
-
expected = 0
|
|
35
|
-
|
|
36
|
-
self.assertEqual(result, expected)
|
|
37
|
-
|
|
38
|
-
# a solution with only multivalent anions should have zero hardness
|
|
39
|
-
def test_hardness_2(self):
|
|
40
|
-
s1 = pyEQL.Solution([["Na+", "0.4 mol/L"], ["SO4-2", "0.2 mol/L"]])
|
|
41
|
-
result = s1.get_hardness().magnitude
|
|
42
|
-
expected = 0
|
|
43
|
-
|
|
44
|
-
self.assertEqual(result, expected)
|
|
45
|
-
|
|
46
|
-
# the hardness should return the equivalent concentration, not just the
|
|
47
|
-
# molar concentration (e.g. multiply by the charge)
|
|
48
|
-
def test_hardness_3(self):
|
|
49
|
-
s1 = pyEQL.Solution([["Fe+3", "0.1 mol/L"], ["Cl-", "0.3 mol/L"]])
|
|
50
|
-
result = s1.get_hardness().magnitude
|
|
51
|
-
expected = 15013.5
|
|
52
|
-
|
|
53
|
-
self.assertAlmostEqual(result, expected)
|
|
54
|
-
|
|
55
|
-
# the hardness should account for multiple cations but count only those
|
|
56
|
-
# that are multivalent
|
|
57
|
-
def test_hardness_4(self):
|
|
58
|
-
s1 = pyEQL.Solution(
|
|
59
|
-
[
|
|
60
|
-
["Na+", "0.1 mol/L"],
|
|
61
|
-
["K+", "0.1 mol/L"],
|
|
62
|
-
["Mg+2", "0.1 mol/L"],
|
|
63
|
-
["Ca+2", "0.1 mol/L"],
|
|
64
|
-
["Fe+3", "0.1 mol/L"],
|
|
65
|
-
["Cl-", "0.1 mol/L"],
|
|
66
|
-
["F-", "0.1 mol/L"],
|
|
67
|
-
["SO4-2", "0.2 mol/L"],
|
|
68
|
-
["PO4-3", "0.1 mol/L"],
|
|
69
|
-
]
|
|
70
|
-
)
|
|
71
|
-
result = s1.get_hardness().magnitude
|
|
72
|
-
expected = 35031.5
|
|
73
|
-
|
|
74
|
-
self.assertAlmostEqual(result, expected)
|
|
75
|
-
|
|
76
|
-
# the hardness should return g/L units
|
|
77
|
-
def test_hardness_5(self):
|
|
78
|
-
s1 = pyEQL.Solution([["Fe+3", "0.1 mol/L"], ["Cl-", "0.3 mol/L"]])
|
|
79
|
-
result = str(s1.get_hardness().dimensionality)
|
|
80
|
-
expected = "[mass] / [length] ** 3"
|
|
81
|
-
|
|
82
|
-
self.assertEqual(result, expected)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if __name__ == "__main__":
|
|
86
|
-
unittest.main()
|