https://mooseframework.inl.gov
Loading...
Searching...
No Matches
GeochemicalDatabaseReaderTest.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "gtest/gtest.h"
11#include <algorithm>
12
14
15TEST(GeochemicalDatabaseReaderTest, filename)
16{
17 GeochemicalDatabaseReader database("database/moose_testdb.json");
18
19 EXPECT_EQ(database.filename(), "database/moose_testdb.json");
20}
21
22TEST(GeochemicalDatabaseReaderTest, faultyDB)
23{
24 // Test that the database validator throws an error when a faulty
25 // database is read (the full range of validation errors are tested
26 // in GeochemicalDatabaseValidatorTest.C)
27 try
28 {
29 GeochemicalDatabaseReader database("database/faultydbs/missing_header.json");
30 }
31 catch (const std::exception & err)
32 {
33 const std::string msg = "The MOOSE database database/faultydbs/missing_header.json does not "
34 "have a required \"Header\" field";
35
36 std::size_t pos = std::string(err.what()).find(msg);
37 ASSERT_TRUE(pos != std::string::npos);
38 }
39}
40
41TEST(GeochemicalDatabaseReaderTest, getActivityModel)
42{
43 GeochemicalDatabaseReader database("database/moose_testdb.json");
44
45 EXPECT_EQ(database.getActivityModel(), "debye-huckel");
46}
47
48TEST(GeochemicalDatabaseReaderTest, getFugacityModel)
49{
50 GeochemicalDatabaseReader database("database/moose_testdb.json");
51
52 EXPECT_EQ(database.getFugacityModel(), "tsonopoulos");
53}
54
55TEST(GeochemicalDatabaseReaderTest, getLogKModel)
56{
57 GeochemicalDatabaseReader database("database/moose_testdb.json");
58
59 EXPECT_EQ(database.getLogKModel(), "fourth-order");
60
61 GeochemicalDatabaseReader database2("database/moose_testdb.json", true);
62
63 EXPECT_EQ(database2.getLogKModel(), "fourth-order");
64
65 GeochemicalDatabaseReader database3("database/moose_testdb.json", false, true);
66
67 EXPECT_EQ(database3.getLogKModel(), "piecewise-linear");
68}
69
70TEST(GeochemicalDatabaseReaderTest, getTemperatures)
71{
72 GeochemicalDatabaseReader database("database/moose_testdb.json");
73
74 // Get the temperature points from the database and compare with the expected
75 // valules
76 auto temperature_points = database.getTemperatures();
77
78 std::vector<Real> temperature_points_gold{0.0, 25.0, 60.0, 100.0, 150.0, 200.0, 250.0, 300.0};
79 EXPECT_EQ(temperature_points, temperature_points_gold);
80}
81
82TEST(GeochemicalDatabaseReaderTest, getPressures)
83{
84 GeochemicalDatabaseReader database("database/moose_testdb.json");
85
86 // Get the pressure points from the database and compare with the expected
87 // valules
88 auto pressure_points = database.getPressures();
89
90 std::vector<Real> pressure_points_gold{
91 1.0134, 1.0134, 1.0134, 1.0134, 4.7600, 15.5490, 39.7760, 85.9270};
92 EXPECT_EQ(pressure_points, pressure_points_gold);
93}
94
95TEST(GeochemicalDatabaseReaderTest, getDebyeHuckel)
96{
97 GeochemicalDatabaseReader database("database/moose_testdb.json");
98
99 // Get the Debye-Huckel from the database and compare with the expected
100 // valules
101 auto dh = database.getDebyeHuckel();
102
103 std::vector<Real> adh_gold{.4913, .5092, .5450, .5998, .6898, .8099, .9785, 1.2555};
104 std::vector<Real> bdh_gold{.3247, .3283, .3343, .3422, .3533, .3655, .3792, .3965};
105 std::vector<Real> bdot_gold{.0174, .0410, .0440, .0460, .0470, .0470, .0340, 0.0000};
106
107 EXPECT_EQ(dh.adh, adh_gold);
108 EXPECT_EQ(dh.bdh, bdh_gold);
109 EXPECT_EQ(dh.bdot, bdot_gold);
110}
111
112TEST(GeochemicalDatabaseReaderTest, getNeutralSpeciesActivity)
113{
114 GeochemicalDatabaseReader database("database/moose_testdb.json");
115
116 // Get the neutral species activity coefficients from the database
117 // and compare with the expected values
119
120 auto ns = nsa["co2"];
121 std::vector<Real> a_gold{.1224, .1127, .09341, .08018, .08427, .09892, .1371, .1967};
122 std::vector<Real> b_gold{-.004679, -.01049, -.0036, -.001503, -.01184, -.0104, -.007086, -.01809};
123 std::vector<Real> c_gold{
124 -0.0004114, 0.001545, 9.609e-05, 0.0005009, 0.003118, 0.001386, -0.002887, -0.002497};
125 std::vector<Real> d_gold(8);
126
127 EXPECT_EQ(ns.a, a_gold);
128 EXPECT_EQ(ns.b, b_gold);
129 EXPECT_EQ(ns.c, c_gold);
130 EXPECT_TRUE(ns.d.empty());
131
132 ns = nsa["h2o"];
133 a_gold = {1.4203, 1.45397, 1.5012, 1.5551, 1.6225, 1.6899, 1.7573, 1.8247};
134 b_gold = {0.0177, 0.022357, 0.0289, 0.036478, 0.045891, 0.0553, 0.0647, 0.0741};
135 c_gold = {0.0103, 0.0093804, 0.008, 0.0064366, 0.0045221, 0.0026, 0.0006, -0.0013};
136 d_gold = {-0.0005, -0.0005362, -0.0006, -0.0007132, -0.0008312, -0.0009, -0.0011, -0.0012};
137
138 EXPECT_EQ(ns.a, a_gold);
139 EXPECT_EQ(ns.b, b_gold);
140 EXPECT_EQ(ns.c, c_gold);
141 EXPECT_EQ(ns.d, d_gold);
142
143 // check error is thrown if database has no neutral species
144 GeochemicalDatabaseReader database_non("database/faultydbs/no_neutral_species.json");
145 try
146 {
147 auto nsa = database_non.getNeutralSpeciesActivity();
148 FAIL() << "Missing expected exception.";
149 }
150 catch (const std::exception & e)
151 {
152 std::string msg(e.what());
153 ASSERT_TRUE(msg.find("No neutral species activity coefficients in database") !=
154 std::string::npos)
155 << "Failed with unexpected error message: " << msg;
156 }
157}
158
159TEST(GeochemicalDatabaseReaderTest, getElements)
160{
161 GeochemicalDatabaseReader database("database/moose_testdb.json");
162
163 // Get the elements from the database and compare with the expected
164 // valules
165 auto els = database.getElements();
166 auto el = els["Ag"];
167
168 EXPECT_EQ(el.name, "Silver");
169 EXPECT_EQ(el.molecular_weight, 107.8680);
170
171 el = els["Al"];
172
173 EXPECT_EQ(el.name, "Aluminum");
174 EXPECT_EQ(el.molecular_weight, 26.9815);
175}
176
177TEST(GeochemicalDatabaseReaderTest, getBasisSpecies)
178{
179 GeochemicalDatabaseReader database("database/moose_testdb.json");
180
181 // Vector of primary species
182 std::vector<std::string> bs_names{"Ca++", "HCO3-", "H+"};
183
184 // Check the basis species
185 auto bs = database.getBasisSpecies(bs_names);
186
187 // Check that only the species in bs_names are returned
188 std::vector<std::string> bs_names_returned;
189 for (auto b : bs)
190 bs_names_returned.push_back(b.first);
191
192 std::sort(bs_names_returned.begin(), bs_names_returned.end());
193 std::sort(bs_names.begin(), bs_names.end());
194 EXPECT_EQ(bs_names_returned, bs_names);
195
196 // Check each species
197 auto species = bs["Ca++"];
198
199 std::map<std::string, Real> els_gold = {{"Ca", 1}};
200 EXPECT_EQ(species.radius, 6);
201 EXPECT_EQ(species.charge, 2);
202 EXPECT_EQ(species.molecular_weight, 40.08);
203 EXPECT_EQ(species.elements, els_gold);
204
205 species = bs["HCO3-"];
206
207 els_gold = {{"C", 1}, {"H", 1}, {"O", 3}};
208 EXPECT_EQ(species.radius, 4.5);
209 EXPECT_EQ(species.charge, -1);
210 EXPECT_EQ(species.molecular_weight, 61.0171);
211 EXPECT_EQ(species.elements, els_gold);
212
213 species = bs["H+"];
214
215 els_gold = {{"H", 1}};
216 EXPECT_EQ(species.radius, 9);
217 EXPECT_EQ(species.charge, 1);
218 EXPECT_EQ(species.molecular_weight, 1.0079);
219 EXPECT_EQ(species.elements, els_gold);
220
221 // check that an error is thrown if the species does not exist
222 try
223 {
224 auto bs_not = database.getBasisSpecies({"does_not_exist"});
225 FAIL() << "Missing expected exception.";
226 }
227 catch (const std::exception & e)
228 {
229 std::string msg(e.what());
230 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
231 std::string::npos)
232 << "Failed with unexpected error message: " << msg;
233 }
234}
235
236TEST(GeochemicalDatabaseReaderTest, getEquilibriumSpecies)
237{
238 GeochemicalDatabaseReader database("database/moose_testdb.json");
239
240 // Vector of secondary species
241 std::vector<std::string> ss_names{"CO2(aq)", "CO3--", "CaCO3", "CaOH+", "OH-"};
242
243 // Check the secondary species
244 auto ss = database.getEquilibriumSpecies(ss_names);
245
246 // Check that only the species in ss_names are returned
247 std::vector<std::string> ss_names_returned;
248 for (auto s : ss)
249 ss_names_returned.push_back(s.first);
250
251 std::sort(ss_names_returned.begin(), ss_names_returned.end());
252 std::sort(ss_names.begin(), ss_names.end());
253 EXPECT_EQ(ss_names_returned, ss_names);
254
255 // Check each species
256 auto sspecies = ss["CO2(aq)"];
257 std::vector<Real> logk_gold{
258 -6.5570, -6.3660, -6.3325, -6.4330, -6.7420, -7.1880, -7.7630, -8.4650};
259 std::map<std::string, Real> bs_gold = {{"H2O", -1}, {"H+", 1}, {"HCO3-", 1}};
260
261 EXPECT_EQ(sspecies.radius, 4);
262 EXPECT_EQ(sspecies.charge, 0);
263 EXPECT_EQ(sspecies.molecular_weight, 44.0098);
264 EXPECT_EQ(sspecies.basis_species, bs_gold);
265 EXPECT_EQ(sspecies.equilibrium_const, logk_gold);
266
267 sspecies = ss["CO3--"];
268 logk_gold = {10.6169, 10.3439, 10.2092, 10.2793, 10.5131, 10.8637, 11.2860, 11.6319};
269 bs_gold = {{"H+", -1}, {"HCO3-", 1}};
270
271 EXPECT_EQ(sspecies.radius, 4.5);
272 EXPECT_EQ(sspecies.charge, -2);
273 EXPECT_EQ(sspecies.molecular_weight, 60.0092);
274 EXPECT_EQ(sspecies.basis_species, bs_gold);
275 EXPECT_EQ(sspecies.equilibrium_const, logk_gold);
276
277 sspecies = ss["CaCO3"];
278 logk_gold = {7.5520, 7.1280, 6.7340, 6.4350, 6.1810, 5.9320, 5.5640, 4.7890};
279 bs_gold = {{"Ca++", 1}, {"HCO3-", 1}, {"H+", -1}};
280
281 EXPECT_EQ(sspecies.radius, 4);
282 EXPECT_EQ(sspecies.charge, 0);
283 EXPECT_EQ(sspecies.molecular_weight, 100.0892);
284 EXPECT_EQ(sspecies.basis_species, bs_gold);
285 EXPECT_EQ(sspecies.equilibrium_const, logk_gold);
286
287 sspecies = ss["CaOH+"];
288 logk_gold = {13.7095, 12.6887, 11.5069, 10.4366, 9.3958, 8.5583, 7.8155, 7.0306};
289 bs_gold = {{"Ca++", 1}, {"H2O", 1}, {"H+", -1}};
290
291 EXPECT_EQ(sspecies.radius, 4);
292 EXPECT_EQ(sspecies.charge, 1);
293 EXPECT_EQ(sspecies.molecular_weight, 57.0873);
294 EXPECT_EQ(sspecies.basis_species, bs_gold);
295 EXPECT_EQ(sspecies.equilibrium_const, logk_gold);
296
297 sspecies = ss["OH-"];
298 logk_gold = {14.9325, 13.9868, 13.0199, 12.2403, 11.5940, 11.2191, 11.0880, 1001.2844};
299 bs_gold = {{"H2O", 1}, {"H+", -1}};
300
301 EXPECT_EQ(sspecies.radius, 3.5);
302 EXPECT_EQ(sspecies.charge, -1);
303 EXPECT_EQ(sspecies.molecular_weight, 17.0073);
304 EXPECT_EQ(sspecies.basis_species, bs_gold);
305 EXPECT_EQ(sspecies.equilibrium_const, logk_gold);
306
307 // check that an error is thrown if the species does not exist
308 try
309 {
310 auto bs_not = database.getEquilibriumSpecies({"does_not_exist"});
311 FAIL() << "Missing expected exception.";
312 }
313 catch (const std::exception & e)
314 {
315 std::string msg(e.what());
316 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
317 std::string::npos)
318 << "Failed with unexpected error message: " << msg;
319 }
320}
321
322TEST(GeochemicalDatabaseReaderTest, getMineralSpecies)
323{
324 GeochemicalDatabaseReader database("database/moose_testdb.json");
325
326 // Vector of mineral species to be read
327 std::vector<std::string> ms_names{"Calcite", "Fe(OH)3(ppd)"};
328
329 // Check the mineral species
330 auto ms = database.getMineralSpecies(ms_names);
331
332 // Check that only the species in ms_names are returned
333 std::vector<std::string> ms_names_returned;
334 for (auto s : ms)
335 ms_names_returned.push_back(s.first);
336
337 std::sort(ms_names_returned.begin(), ms_names_returned.end());
338 std::sort(ms_names.begin(), ms_names.end());
339 EXPECT_EQ(ms_names_returned, ms_names);
340
341 auto mspecies = ms["Calcite"];
342 std::vector<Real> logk_gold = {2.0683, 1.7130, 1.2133, .6871, .0762, -.5349, -1.2301, -2.2107};
343 std::map<std::string, Real> bs_gold = {{"Ca++", 1}, {"H+", -1}, {"HCO3-", 1}};
344
345 EXPECT_EQ(mspecies.molecular_volume, 36.934);
346 EXPECT_EQ(mspecies.molecular_weight, 100.0892);
347 EXPECT_EQ(mspecies.basis_species, bs_gold);
348 EXPECT_EQ(mspecies.equilibrium_const, logk_gold);
349 EXPECT_EQ(mspecies.surface_area, 0.0);
350
351 mspecies = ms["Fe(OH)3(ppd)"];
352 logk_gold = {6.1946, 4.8890, 3.4608, 2.2392, 1.1150, .2446, -.5504, -1.5398};
353 bs_gold = {{"H+", -3}, {"Fe+++", 1}, {"H2O", 3}};
354
355 EXPECT_EQ(mspecies.molecular_volume, 34.32);
356 EXPECT_EQ(mspecies.molecular_weight, 106.8689);
357 EXPECT_EQ(mspecies.basis_species, bs_gold);
358 EXPECT_EQ(mspecies.equilibrium_const, logk_gold);
359 EXPECT_EQ(mspecies.surface_area, 600.0);
360 bs_gold = {{">(s)FeOH", 0.005}, {">(w)FeOH", 0.2}};
361 EXPECT_EQ(mspecies.sorption_sites, bs_gold);
362
363 // check that an error is thrown if the species does not exist
364 try
365 {
366 auto bs_not = database.getMineralSpecies({"does_not_exist"});
367 FAIL() << "Missing expected exception.";
368 }
369 catch (const std::exception & e)
370 {
371 std::string msg(e.what());
372 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
373 std::string::npos)
374 << "Failed with unexpected error message: " << msg;
375 }
376}
377
378TEST(GeochemicalDatabaseReaderTest, getGasSpecies)
379{
380 GeochemicalDatabaseReader database("database/moose_testdb.json");
381
382 // Vector of gas species to be read
383 std::vector<std::string> gs_names{"N2(g)", "CH4(g)"};
384
385 // Check the gas species
386 auto gs = database.getGasSpecies(gs_names);
387
388 // Check that only the species in gs_names are returned
389 std::vector<std::string> gs_names_returned;
390 for (auto s : gs)
391 gs_names_returned.push_back(s.first);
392
393 std::sort(gs_names_returned.begin(), gs_names_returned.end());
394 std::sort(gs_names.begin(), gs_names.end());
395 EXPECT_EQ(gs_names_returned, gs_names);
396
397 auto gspecies = gs["N2(g)"];
398 std::vector<Real> logk_gold = {
399 -2.9620, -3.1848, -3.3320, -3.2902, -3.1631, -2.9499, -2.7827, -2.3699};
400 std::map<std::string, Real> bs_gold = {{"N2(aq)", 1}};
401
402 EXPECT_EQ(gspecies.molecular_weight, 28.0134);
403 EXPECT_EQ(gspecies.basis_species, bs_gold);
404 EXPECT_EQ(gspecies.equilibrium_const, logk_gold);
405 EXPECT_TRUE(gspecies.chi.empty());
406 EXPECT_EQ(gspecies.Pcrit, 33.9);
407 EXPECT_EQ(gspecies.Tcrit, 126.2);
408 EXPECT_EQ(gspecies.omega, .039);
409
410 gspecies = gs["CH4(g)"];
411 logk_gold = {-2.6487, -2.8202, -2.9329, -2.9446, -2.9163, -2.7253, -2.4643, -2.1569};
412 bs_gold = {{"CH4(aq)", 1}};
413 std::vector<Real> chi_gold = {-537.779, 1.54946, -.000927827, 1.20861, -.00370814, 3.33804e-6};
414
415 EXPECT_EQ(gspecies.molecular_weight, 16.0426);
416 EXPECT_EQ(gspecies.basis_species, bs_gold);
417 EXPECT_EQ(gspecies.equilibrium_const, logk_gold);
418 EXPECT_EQ(gspecies.chi, chi_gold);
419 EXPECT_EQ(gspecies.Pcrit, 46.0);
420 EXPECT_EQ(gspecies.Tcrit, 190.4);
421 EXPECT_EQ(gspecies.omega, .011);
422
423 // check that an error is thrown if the species does not exist
424 try
425 {
426 auto bs_not = database.getGasSpecies({"does_not_exist"});
427 FAIL() << "Missing expected exception.";
428 }
429 catch (const std::exception & e)
430 {
431 std::string msg(e.what());
432 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
433 std::string::npos)
434 << "Failed with unexpected error message: " << msg;
435 }
436}
437
438TEST(GeochemicalDatabaseReaderTest, getRedoxSpecies)
439{
440 GeochemicalDatabaseReader database("database/moose_testdb.json");
441
442 // Vector of redox species
443 std::vector<std::string> rs_names{"Am++++"};
444
445 // Check the secondary species
446 auto rs = database.getRedoxSpecies(rs_names);
447
448 // Check that only the species in ss_names are returned
449 std::vector<std::string> rs_names_returned;
450 for (auto s : rs)
451 rs_names_returned.push_back(s.first);
452
453 std::sort(rs_names_returned.begin(), rs_names_returned.end());
454 std::sort(rs_names.begin(), rs_names.end());
455 EXPECT_EQ(rs_names_returned, rs_names);
456
457 auto rspecies = rs["Am++++"];
458 std::vector<Real> logk_gold = {
459 18.7967, 18.0815, 17.2698, 16.5278, 15.8024, 15.2312, 14.7898, 14.4250};
460 std::map<std::string, Real> bs_gold = {{"H2O", -0.5}, {"H+", 1}, {"Am+++", 1}, {"O2(aq)", 0.250}};
461
462 EXPECT_EQ(rspecies.radius, 11);
463 EXPECT_EQ(rspecies.charge, 4);
464 EXPECT_EQ(rspecies.molecular_weight, 241.0600);
465 EXPECT_EQ(rspecies.basis_species, bs_gold);
466 EXPECT_EQ(rspecies.equilibrium_const, logk_gold);
467
468 // check that an error is thrown if the species does not exist
469 try
470 {
471 auto bs_not = database.getRedoxSpecies({"does_not_exist"});
472 FAIL() << "Missing expected exception.";
473 }
474 catch (const std::exception & e)
475 {
476 std::string msg(e.what());
477 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
478 std::string::npos)
479 << "Failed with unexpected error message: " << msg;
480 }
481}
482
483TEST(GeochemicalDatabaseReaderTest, getOxideSpecies)
484{
485 GeochemicalDatabaseReader database("database/moose_testdb.json");
486
487 // Vector of gas species to be read
488 std::vector<std::string> os_names{"Cu2O"};
489
490 // Check the oxide species
491 auto os = database.getOxideSpecies(os_names);
492
493 // Check that only the species in gs_names are returned
494 std::vector<std::string> os_names_returned;
495 for (auto s : os)
496 os_names_returned.push_back(s.first);
497
498 EXPECT_EQ(os_names_returned, os_names);
499
500 auto ospecies = os["Cu2O"];
501 std::map<std::string, Real> bs_gold = {{"H+", -2}, {"Cu+", 2}, {"H2O", 1}};
502
503 EXPECT_EQ(ospecies.molecular_weight, 143.0929);
504 EXPECT_EQ(ospecies.basis_species, bs_gold);
505
506 // check that an error is thrown if the species does not exist
507 try
508 {
509 auto bs_not = database.getOxideSpecies({"does_not_exist"});
510 FAIL() << "Missing expected exception.";
511 }
512 catch (const std::exception & e)
513 {
514 std::string msg(e.what());
515 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
516 std::string::npos)
517 << "Failed with unexpected error message: " << msg;
518 }
519}
520
521TEST(GeochemicalDatabaseReaderTest, getSurfaceSpecies)
522{
523 GeochemicalDatabaseReader database("database/moose_testdb.json");
524
525 std::vector<std::string> ss_names{">(s)FeO-"};
526
527 auto ss = database.getSurfaceSpecies(ss_names);
528
529 // Check that only the species in ss_names are returned
530 std::vector<std::string> ss_names_returned;
531 for (auto s : ss)
532 ss_names_returned.push_back(s.first);
533
534 EXPECT_EQ(ss_names_returned, ss_names);
535
536 auto sspecies = ss[">(s)FeO-"];
537 std::map<std::string, Real> ss_gold = {{">(s)FeOH", 1}, {"H+", -1}};
538
539 EXPECT_EQ(sspecies.basis_species, ss_gold);
540
541 // check that an error is thrown if the species does not exist
542 try
543 {
544 auto bs_not = database.getSurfaceSpecies({"does_not_exist"});
545 FAIL() << "Missing expected exception.";
546 }
547 catch (const std::exception & e)
548 {
549 std::string msg(e.what());
550 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
551 std::string::npos)
552 << "Failed with unexpected error message: " << msg;
553 }
554}
555
556TEST(GeochemicalDatabaseReaderTest, equilibriumReactions)
557{
558 GeochemicalDatabaseReader database("database/moose_testdb.json");
559
560 // Secondary equilibrium species
561 std::vector<std::string> names{"CO2(aq)", "CO3--", "CaCO3", "CaOH+", "OH-"};
562
563 auto reactions = database.equilibriumReactions(names);
564
565 EXPECT_EQ(reactions[0], "CO2(aq) = H+ - H2O + HCO3-");
566 EXPECT_EQ(reactions[1], "CO3-- = - H+ + HCO3-");
567 EXPECT_EQ(reactions[2], "CaCO3 = Ca++ - H+ + HCO3-");
568 EXPECT_EQ(reactions[3], "CaOH+ = Ca++ - H+ + H2O");
569 EXPECT_EQ(reactions[4], "OH- = - H+ + H2O");
570
571 // check that an error is thrown if the species does not exist
572 try
573 {
574 auto reactions_not = database.equilibriumReactions({"does_not_exist"});
575 FAIL() << "Missing expected exception.";
576 }
577 catch (const std::exception & e)
578 {
579 std::string msg(e.what());
580 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
581 std::string::npos)
582 << "Failed with unexpected error message: " << msg;
583 }
584}
585
586TEST(GeochemicalDatabaseReaderTest, mineralReactions)
587{
588 GeochemicalDatabaseReader database("database/moose_testdb.json");
589
590 // Secondary mineral species
591 std::vector<std::string> names{"Calcite"};
592
593 auto reactions = database.mineralReactions(names);
594
595 EXPECT_EQ(reactions[0], "Calcite = Ca++ - H+ + HCO3-");
596
597 // check that an error is thrown if the species does not exist
598 try
599 {
600 auto reactions_not = database.mineralReactions({"does_not_exist"});
601 FAIL() << "Missing expected exception.";
602 }
603 catch (const std::exception & e)
604 {
605 std::string msg(e.what());
606 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
607 std::string::npos)
608 << "Failed with unexpected error message: " << msg;
609 }
610}
611
612TEST(GeochemicalDatabaseReaderTest, gasReactions)
613{
614 GeochemicalDatabaseReader database("database/moose_testdb.json");
615
616 // Secondary gas species
617 std::vector<std::string> names{"CH4(g)", "N2(g)"};
618
619 auto reactions = database.gasReactions(names);
620
621 EXPECT_EQ(reactions[0], "CH4(g) = CH4(aq)");
622 EXPECT_EQ(reactions[1], "N2(g) = N2(aq)");
623
624 // check that an error is thrown if the species does not exist
625 try
626 {
627 auto reactions_not = database.gasReactions({"does_not_exist"});
628 FAIL() << "Missing expected exception.";
629 }
630 catch (const std::exception & e)
631 {
632 std::string msg(e.what());
633 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
634 std::string::npos)
635 << "Failed with unexpected error message: " << msg;
636 }
637}
638
639TEST(GeochemicalDatabaseReaderTest, redoxReactions)
640{
641 GeochemicalDatabaseReader database("database/moose_testdb.json");
642
643 // Secondary redox couples
644 std::vector<std::string> names{"(O-phth)--", "Am++++"};
645
646 auto reactions = database.redoxReactions(names);
647
648 EXPECT_EQ(reactions[0], "(O-phth)-- = 6H+ -5H2O + 8HCO3- -7.5O2(aq)");
649 EXPECT_EQ(reactions[1], "Am++++ = Am+++ + H+ -0.5H2O + 0.25O2(aq)");
650
651 // check that an error is thrown if the species does not exist
652 try
653 {
654 auto reactions_not = database.redoxReactions({"does_not_exist"});
655 FAIL() << "Missing expected exception.";
656 }
657 catch (const std::exception & e)
658 {
659 std::string msg(e.what());
660 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
661 std::string::npos)
662 << "Failed with unexpected error message: " << msg;
663 }
664}
665
666TEST(GeochemicalDatabaseReaderTest, oxideReactions)
667{
668 GeochemicalDatabaseReader database("database/moose_testdb.json");
669
670 // Secondary oxide species
671 std::vector<std::string> names{"Cu2O"};
672
673 auto reactions = database.oxideReactions(names);
674
675 EXPECT_EQ(reactions[0], "Cu2O = 2Cu+ -2H+ + H2O");
676
677 // check that an error is thrown if the species does not exist
678 try
679 {
680 auto reactions_not = database.oxideReactions({"does_not_exist"});
681 FAIL() << "Missing expected exception.";
682 }
683 catch (const std::exception & e)
684 {
685 std::string msg(e.what());
686 ASSERT_TRUE(msg.find("does_not_exist does not exist in database database/moose_testdb.json") !=
687 std::string::npos)
688 << "Failed with unexpected error message: " << msg;
689 }
690}
691
692TEST(GeochemicalDatabaseReaderTest, isBasisSpecies)
693{
694 GeochemicalDatabaseReader database("database/moose_testdb.json");
695
696 EXPECT_TRUE(database.isBasisSpecies("Ca++"));
697 EXPECT_TRUE(database.isBasisSpecies("H2O"));
698 EXPECT_FALSE(database.isBasisSpecies("Ag"));
699 EXPECT_FALSE(database.isBasisSpecies("CO2(aq)"));
700 EXPECT_FALSE(database.isBasisSpecies("CO3--"));
701 EXPECT_FALSE(database.isBasisSpecies("Calcite"));
702 EXPECT_FALSE(database.isBasisSpecies("Fe(OH)3(ppd)"));
703 EXPECT_FALSE(database.isBasisSpecies("CH4(g)"));
704 EXPECT_FALSE(database.isBasisSpecies("(O-phth)--"));
705 EXPECT_FALSE(database.isBasisSpecies("Fe+++"));
706 EXPECT_FALSE(database.isBasisSpecies("Cu2O"));
707 EXPECT_FALSE(database.isBasisSpecies(">(s)FeO-"));
708 EXPECT_FALSE(database.isBasisSpecies("e-"));
709}
710
711TEST(GeochemicalDatabaseReaderTest, isSecondarySpecies)
712{
713 GeochemicalDatabaseReader database("database/moose_testdb.json");
714
715 EXPECT_FALSE(database.isSecondarySpecies("Ca++"));
716 EXPECT_FALSE(database.isSecondarySpecies("H2O"));
717 EXPECT_FALSE(database.isSecondarySpecies("Ag"));
718 EXPECT_TRUE(database.isSecondarySpecies("CO2(aq)"));
719 EXPECT_TRUE(database.isSecondarySpecies("CO3--"));
720 EXPECT_TRUE(database.isSecondarySpecies("OH-"));
721 EXPECT_FALSE(database.isSecondarySpecies("Calcite"));
722 EXPECT_FALSE(database.isSecondarySpecies("Fe(OH)3(ppd)"));
723 EXPECT_FALSE(database.isSecondarySpecies("CH4(g)"));
724 EXPECT_FALSE(database.isSecondarySpecies("(O-phth)--"));
725 EXPECT_FALSE(database.isSecondarySpecies("Fe+++"));
726 EXPECT_FALSE(database.isSecondarySpecies("Cu2O"));
727 EXPECT_FALSE(database.isSecondarySpecies(">(s)FeO-"));
728 EXPECT_TRUE(database.isSecondarySpecies("e-"));
729}
730
731TEST(GeochemicalDatabaseReaderTest, isMineralSpecies)
732{
733 GeochemicalDatabaseReader database("database/moose_testdb.json");
734
735 EXPECT_FALSE(database.isMineralSpecies("Ca++"));
736 EXPECT_FALSE(database.isMineralSpecies("H2O"));
737 EXPECT_FALSE(database.isMineralSpecies("Ag"));
738 EXPECT_FALSE(database.isMineralSpecies("CO2(aq)"));
739 EXPECT_FALSE(database.isMineralSpecies("CO3--"));
740 EXPECT_TRUE(database.isMineralSpecies("Calcite"));
741 EXPECT_TRUE(database.isMineralSpecies("Fe(OH)3(ppd)"));
742 EXPECT_FALSE(database.isMineralSpecies("CH4(g)"));
743 EXPECT_FALSE(database.isMineralSpecies("(O-phth)--"));
744 EXPECT_FALSE(database.isMineralSpecies("Fe+++"));
745 EXPECT_FALSE(database.isMineralSpecies("Cu2O"));
746 EXPECT_FALSE(database.isMineralSpecies(">(s)FeO-"));
747 EXPECT_FALSE(database.isMineralSpecies("e-"));
748}
749
750TEST(GeochemicalDatabaseReaderTest, isRedoxSpecies)
751{
752 GeochemicalDatabaseReader database("database/moose_testdb.json");
753
754 EXPECT_FALSE(database.isRedoxSpecies("Ca++"));
755 EXPECT_FALSE(database.isRedoxSpecies("H2O"));
756 EXPECT_FALSE(database.isRedoxSpecies("Ag"));
757 EXPECT_FALSE(database.isRedoxSpecies("CO2(aq)"));
758 EXPECT_FALSE(database.isRedoxSpecies("CO3--"));
759 EXPECT_FALSE(database.isRedoxSpecies("Calcite"));
760 EXPECT_FALSE(database.isRedoxSpecies("Fe(OH)3(ppd)"));
761 EXPECT_FALSE(database.isRedoxSpecies("CH4(g)"));
762 EXPECT_TRUE(database.isRedoxSpecies("(O-phth)--"));
763 EXPECT_TRUE(database.isRedoxSpecies("Fe+++"));
764 EXPECT_FALSE(database.isRedoxSpecies("Cu2O"));
765 EXPECT_FALSE(database.isRedoxSpecies(">(s)FeO-"));
766 EXPECT_FALSE(database.isRedoxSpecies("e-"));
767}
768
769TEST(GeochemicalDatabaseReaderTest, isGasSpecies)
770{
771 GeochemicalDatabaseReader database("database/moose_testdb.json");
772
773 EXPECT_FALSE(database.isGasSpecies("Ca++"));
774 EXPECT_FALSE(database.isGasSpecies("H2O"));
775 EXPECT_FALSE(database.isGasSpecies("Ag"));
776 EXPECT_FALSE(database.isGasSpecies("CO2(aq)"));
777 EXPECT_FALSE(database.isGasSpecies("CO3--"));
778 EXPECT_FALSE(database.isGasSpecies("Calcite"));
779 EXPECT_FALSE(database.isGasSpecies("Fe(OH)3(ppd)"));
780 EXPECT_TRUE(database.isGasSpecies("CH4(g)"));
781 EXPECT_FALSE(database.isGasSpecies("(O-phth)--"));
782 EXPECT_FALSE(database.isGasSpecies("Fe+++"));
783 EXPECT_FALSE(database.isGasSpecies("Cu2O"));
784 EXPECT_FALSE(database.isGasSpecies(">(s)FeO-"));
785 EXPECT_FALSE(database.isGasSpecies("e-"));
786}
787
788TEST(GeochemicalDatabaseReaderTest, isSorbingMineral)
789{
790 GeochemicalDatabaseReader database("database/moose_testdb.json");
791
792 EXPECT_FALSE(database.isSorbingMineral("Ca++"));
793 EXPECT_FALSE(database.isSorbingMineral("H2O"));
794 EXPECT_FALSE(database.isSorbingMineral("Ag"));
795 EXPECT_FALSE(database.isSorbingMineral("CO2(aq)"));
796 EXPECT_FALSE(database.isSorbingMineral("CO3--"));
797 EXPECT_FALSE(database.isSorbingMineral("Calcite"));
798 EXPECT_TRUE(database.isSorbingMineral("Fe(OH)3(ppd)"));
799 EXPECT_FALSE(database.isSorbingMineral("CH4(g)"));
800 EXPECT_FALSE(database.isSorbingMineral("(O-phth)--"));
801 EXPECT_FALSE(database.isSorbingMineral("Fe+++"));
802 EXPECT_FALSE(database.isSorbingMineral("Cu2O"));
803 EXPECT_FALSE(database.isSorbingMineral(">(s)FeO-"));
804 EXPECT_FALSE(database.isSorbingMineral("e-"));
805}
806
807TEST(GeochemicalDatabaseReaderTest, isOxideSpecies)
808{
809 GeochemicalDatabaseReader database("database/moose_testdb.json");
810
811 EXPECT_FALSE(database.isOxideSpecies("Ca++"));
812 EXPECT_FALSE(database.isOxideSpecies("H2O"));
813 EXPECT_FALSE(database.isOxideSpecies("Ag"));
814 EXPECT_FALSE(database.isOxideSpecies("CO2(aq)"));
815 EXPECT_FALSE(database.isOxideSpecies("CO3--"));
816 EXPECT_FALSE(database.isOxideSpecies("Calcite"));
817 EXPECT_FALSE(database.isOxideSpecies("Fe(OH)3(ppd)"));
818 EXPECT_FALSE(database.isOxideSpecies("CH4(g)"));
819 EXPECT_FALSE(database.isOxideSpecies("(O-phth)--"));
820 EXPECT_FALSE(database.isOxideSpecies("Fe+++"));
821 EXPECT_TRUE(database.isOxideSpecies("Cu2O"));
822 EXPECT_FALSE(database.isOxideSpecies(">(s)FeO-"));
823 EXPECT_FALSE(database.isOxideSpecies("e-"));
824}
825
826TEST(GeochemicalDatabaseReaderTest, isSurfaceSpecies)
827{
828 GeochemicalDatabaseReader database("database/moose_testdb.json");
829
830 EXPECT_FALSE(database.isSurfaceSpecies("Ca++"));
831 EXPECT_FALSE(database.isSurfaceSpecies("H2O"));
832 EXPECT_FALSE(database.isSurfaceSpecies("Ag"));
833 EXPECT_FALSE(database.isSurfaceSpecies("CO2(aq)"));
834 EXPECT_FALSE(database.isSurfaceSpecies("CO3--"));
835 EXPECT_FALSE(database.isSurfaceSpecies("Calcite"));
836 EXPECT_FALSE(database.isSurfaceSpecies("Fe(OH)3(ppd)"));
837 EXPECT_FALSE(database.isSurfaceSpecies("CH4(g)"));
838 EXPECT_FALSE(database.isSurfaceSpecies("(O-phth)--"));
839 EXPECT_FALSE(database.isSurfaceSpecies("Fe+++"));
840 EXPECT_FALSE(database.isSurfaceSpecies("Cu2O"));
841 EXPECT_TRUE(database.isSurfaceSpecies(">(s)FeO-"));
842 EXPECT_FALSE(database.isSurfaceSpecies("e-"));
843}
844
845TEST(GeochemicalDatabaseReaderTest, mineralSpeciesNames)
846{
847 GeochemicalDatabaseReader database("database/moose_testdb.json");
848
849 std::vector<std::string> names = database.mineralSpeciesNames();
850 for (const auto & n : {"Calcite",
851 "Calcite_asdf",
852 "Fe(OH)3(ppd)",
853 "Fe(OH)3(ppd)fake",
854 "Goethite",
855 "Something",
856 "problematic_sorber"})
857 EXPECT_TRUE(std::find(names.begin(), names.end(), n) != names.end());
858 EXPECT_EQ(names.size(), (std::size_t)7);
859}
860
861TEST(GeochemicalDatabaseReaderTest, secondarySpeciesNames)
862{
863 GeochemicalDatabaseReader database("database/moose_testdb.json");
864
865 std::vector<std::string> names = database.secondarySpeciesNames();
866 for (const auto & n : {"CO2(aq)", "CO3--", "CaCO3", "CaOH+", "OH-", "e-", "seq_radius_neg1"})
867 EXPECT_TRUE(std::find(names.begin(), names.end(), n) != names.end());
868 EXPECT_EQ(names.size(), (std::size_t)8);
869}
870
871TEST(GeochemicalDatabaseReaderTest, redoxCoupleNames)
872{
873 GeochemicalDatabaseReader database("database/moose_testdb.json");
874
875 std::vector<std::string> names = database.redoxCoupleNames();
876 for (const auto & n : {"(O-phth)--", "Am++++", "CH4(aq)", "Fe+++", "StoiCheckRedox"})
877 EXPECT_TRUE(std::find(names.begin(), names.end(), n) != names.end());
878 EXPECT_EQ(names.size(), (std::size_t)5);
879}
880
881TEST(GeochemicalDatabaseReaderTest, surfaceSpeciesNames)
882{
883 GeochemicalDatabaseReader database("database/moose_testdb.json");
884
885 std::vector<std::string> names = database.surfaceSpeciesNames();
886 for (const auto & n : {">(s)FeO-", ">(s)FeOCa+"})
887 EXPECT_TRUE(std::find(names.begin(), names.end(), n) != names.end());
888 EXPECT_EQ(names.size(), (std::size_t)2);
889}
890
891TEST(GeochemicalDatabaseReaderTest, getSpeciesData)
892{
893 GeochemicalDatabaseReader database("database/moose_testdb.json");
894
895 std::string data = database.getSpeciesData("Ca++");
896 std::string gold = "Ca++:\n{\n \"charge\": 2,\n \"elements\": {\n \"Ca\": 1.0\n "
897 "},\n \"molecular weight\": 40.08,\n \"radius\": 6.0\n}";
898 EXPECT_EQ(data, gold);
899
900 // check that an error is thrown if the species does not exist
901 try
902 {
903 auto reactions_not = database.getSpeciesData({"does_not_exist"});
904 FAIL() << "Missing expected exception.";
905 }
906 catch (const std::exception & e)
907 {
908 std::string msg(e.what());
909 ASSERT_TRUE(msg.find("does_not_exist is not a species in the database") != std::string::npos)
910 << "Failed with unexpected error message: " << msg;
911 }
912}
913
915TEST(GeochemicalDatabaseReaderTest, freeElectron)
916{
917 GeochemicalDatabaseReader database("database/moose_testdb.json");
918
919 auto fe = database.getEquilibriumSpecies({"e-"})["e-"];
920
921 std::vector<Real> logk_gold{
922 23.4266, 21.50045, 19.277525, 17.24705, 15.238975, 13.64975, 12.34665, 11.27355};
923 std::map<std::string, Real> bs_gold = {{"H2O", 0.5}, {"H+", -1}, {"O2(aq)", -0.25}};
924 EXPECT_EQ(fe.charge, -1.0);
925 EXPECT_EQ(fe.radius, 0.0);
926 EXPECT_EQ(fe.molecular_weight, 0.0);
927 EXPECT_EQ(fe.basis_species, bs_gold);
928 EXPECT_EQ(fe.equilibrium_const, logk_gold);
929}
930
932TEST(GeochemicalDatabaseReaderTest, freeElectronNoReexpress)
933{
934 GeochemicalDatabaseReader database("database/moose_testdb.json", false);
935
936 auto fe = database.getEquilibriumSpecies({"e-"})["e-"];
937
938 std::vector<Real> logk_gold{
939 22.76135, 20.7757, 18.513025, 16.4658, 14.473225, 12.92125, 11.68165, 10.67105};
940 std::map<std::string, Real> bs_gold = {{"H2O", 0.5}, {"H+", -1}, {"O2(g)", -0.25}};
941 EXPECT_EQ(fe.charge, -1.0);
942 EXPECT_EQ(fe.radius, 0.0);
943 EXPECT_EQ(fe.molecular_weight, 0.0);
944 EXPECT_EQ(fe.basis_species, bs_gold);
945 EXPECT_EQ(fe.equilibrium_const, logk_gold);
946}
947
949TEST(GeochemicalDatabaseReaderTest, isSecondarySpecies_noextrap)
950{
951 GeochemicalDatabaseReader database("database/moose_testdb.json", true, false, true);
952
953 EXPECT_FALSE(database.isSecondarySpecies("Ca++"));
954 EXPECT_FALSE(database.isSecondarySpecies("H2O"));
955 EXPECT_FALSE(database.isSecondarySpecies("Ag"));
956 EXPECT_TRUE(database.isSecondarySpecies("CO2(aq)"));
957 EXPECT_TRUE(database.isSecondarySpecies("CO3--"));
958 EXPECT_FALSE(database.isSecondarySpecies("OH-"));
959 EXPECT_FALSE(database.isSecondarySpecies("Calcite"));
960 EXPECT_FALSE(database.isSecondarySpecies("Fe(OH)3(ppd)"));
961 EXPECT_FALSE(database.isSecondarySpecies("CH4(g)"));
962 EXPECT_FALSE(database.isSecondarySpecies("(O-phth)--"));
963 EXPECT_FALSE(database.isSecondarySpecies("Fe+++"));
964 EXPECT_FALSE(database.isSecondarySpecies("Cu2O"));
965 EXPECT_FALSE(database.isSecondarySpecies(">(s)FeO-"));
966 EXPECT_TRUE(database.isSecondarySpecies("e-"));
967}
TEST(GeochemicalDatabaseReaderTest, filename)
const GeochemicalDatabaseReader database("database/moose_testdb.json", true, true, false)
Class for reading geochemical reactions from a MOOSE geochemical database.
bool isBasisSpecies(const std::string &name) const
Checks if species is of given type.
std::vector< std::string > oxideReactions(const std::vector< std::string > &names) const
Generates a formatted vector of strings representing all oxide reactions.
const GeochemistryDebyeHuckel & getDebyeHuckel() const
Get the Debye-Huckel activity coefficients.
bool isSurfaceSpecies(const std::string &name) const
bool isOxideSpecies(const std::string &name) const
bool isSorbingMineral(const std::string &name) const
returns True iff name is the name of a sorbing mineral
std::map< std::string, GeochemistryGasSpecies > getGasSpecies(const std::vector< std::string > &names)
Get the gas species information.
std::vector< std::string > gasReactions(const std::vector< std::string > &names) const
Generates a formatted vector of strings representing all gas reactions.
std::vector< std::string > mineralReactions(const std::vector< std::string > &names) const
Generates a formatted vector of strings representing all mineral reactions.
std::vector< std::string > secondarySpeciesNames() const
Returns a list of all the names of the "secondary species" and "free electron" in the database.
std::map< std::string, GeochemistryEquilibriumSpecies > getEquilibriumSpecies(const std::vector< std::string > &names)
Get the secondary equilibrium species information.
bool isMineralSpecies(const std::string &name) const
std::map< std::string, GeochemistryRedoxSpecies > getRedoxSpecies(const std::vector< std::string > &names)
Get the redox species (couples) information.
std::vector< std::string > equilibriumReactions(const std::vector< std::string > &names) const
Generates a formatted vector of strings representing all aqueous equilibrium reactions.
std::string getFugacityModel() const
Get the fugacity model type.
std::vector< std::string > mineralSpeciesNames() const
Returns a list of all the names of the "mineral species" in the database.
bool isSecondarySpecies(const std::string &name) const
Returns true if name is a "secondary species" or "free electron" in the database.
std::map< std::string, GeochemistryBasisSpecies > getBasisSpecies(const std::vector< std::string > &names)
Get the basis (primary) species information.
std::vector< std::string > redoxReactions(const std::vector< std::string > &names) const
Generates a formatted vector of strings representing all redox reactions.
bool isRedoxSpecies(const std::string &name) const
std::map< std::string, GeochemistryOxideSpecies > getOxideSpecies(const std::vector< std::string > &names)
Get the oxide species information.
const FileName & filename() const
Filename of database.
std::vector< std::string > surfaceSpeciesNames() const
Returns a list of all the names of the "surface species" in the database.
std::map< std::string, GeochemistryElements > getElements()
Get all the elements.
const std::vector< Real > & getTemperatures() const
Get the temperature points that the equilibrium constant is defined at.
std::string getSpeciesData(const std::string name) const
String representation of JSON species object contents.
const std::map< std::string, GeochemistryNeutralSpeciesActivity > & getNeutralSpeciesActivity() const
Get the neutral species activity coefficients.
std::vector< Real > getPressures()
Get the pressure points that the equilibrium constant is defined at.
std::string getActivityModel() const
Get the activity model type.
std::string getLogKModel() const
Get the equilibrium constant model type.
std::map< std::string, GeochemistrySurfaceSpecies > getSurfaceSpecies(const std::vector< std::string > &names)
Get the surface sorbing species information.
std::vector< std::string > redoxCoupleNames() const
Returns a list of all the names of the "redox couples" in the database.
bool isGasSpecies(const std::string &name) const
std::map< std::string, GeochemistryMineralSpecies > getMineralSpecies(const std::vector< std::string > &names)
Get the mineral species information.