10 #include "gtest/gtest.h" 18 db_ferric(
"../test/database/ferric_hydroxide_sorption.json",
true,
true);
24 const std::vector<GeochemicalSystem::ConstraintUserMeaningEnum>
cm2 = {
27 const std::vector<GeochemistryUnitConverter::GeochemistryUnit>
cu2 = {
30 const std::vector<GeochemicalSystem::ConstraintUserMeaningEnum>
cm4 = {
35 const std::vector<GeochemistryUnitConverter::GeochemistryUnit>
cu4 = {
44 TEST(GeochemicalSolverTest, exception)
79 FAIL() <<
"Missing expected exception.";
81 catch (
const std::exception & e)
83 std::string msg(e.what());
84 ASSERT_TRUE(msg.find(
"GeochemicalSolver: ramp_max_ionic_strength must be less than max_iter") !=
86 <<
"Failed with unexpected error message: " << msg;
104 FAIL() <<
"Missing expected exception.";
106 catch (
const std::exception & e)
108 std::string msg(e.what());
109 ASSERT_TRUE(msg.find(
"GeochemicalSolver: max_initial_residual must be positive") !=
111 <<
"Failed with unexpected error message: " << msg;
129 FAIL() <<
"Missing expected exception.";
131 catch (
const std::exception & e)
133 std::string msg(e.what());
134 ASSERT_TRUE(msg.find(
"GeochemicalSolver: max_ionic_strength must not be negative") !=
136 <<
"Failed with unexpected error message: " << msg;
154 FAIL() <<
"Missing expected exception.";
156 catch (
const std::exception & e)
158 std::string msg(e.what());
159 ASSERT_TRUE(msg.find(
"GeochemicalSolver: rel_tol must not be negative") != std::string::npos)
160 <<
"Failed with unexpected error message: " << msg;
178 FAIL() <<
"Missing expected exception.";
180 catch (
const std::exception & e)
182 std::string msg(e.what());
183 ASSERT_TRUE(msg.find(
"GeochemicalSolver: abs_tol must not be negative") != std::string::npos)
184 <<
"Failed with unexpected error message: " << msg;
202 FAIL() <<
"Missing expected exception.";
204 catch (
const std::exception & e)
206 std::string msg(e.what());
207 ASSERT_TRUE(msg.find(
"GeochemicalSolver: either rel_tol or abs_tol must be positive") !=
209 <<
"Failed with unexpected error message: " << msg;
228 FAIL() <<
"Missing expected exception.";
230 catch (
const std::exception & e)
232 std::string msg(e.what());
233 ASSERT_TRUE(msg.find(
"GeochemicalSolver: max_initial_residual must be positive") !=
235 <<
"Failed with unexpected error message: " << msg;
240 TEST(GeochemicalSolverTest, setgetMaxInitialResidual)
273 EXPECT_EQ(solver.getMaxInitialResidual(), 99.0);
274 solver.setMaxInitialResidual(123.0);
275 EXPECT_EQ(solver.getMaxInitialResidual(), 123.0);
279 TEST(GeochemicalSolverTest, solve1)
313 std::stringstream ss;
316 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
318 egs.getNumInBasis() + egs.getNumKinetic());
319 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
322 EXPECT_LE(tot_iter, (
unsigned)100);
323 EXPECT_LE(abs_residual, 1.0E-15);
326 EXPECT_NEAR(egs.getEquilibriumMolality(0) /
327 (egs.getBasisActivity(0) / egs.getBasisActivity(1) /
328 std::pow(10.0, egs.getLog10K(0)) / egs.getEquilibriumActivityCoefficient(0)),
333 EXPECT_EQ(egs.getSolventWaterMass(), 1.75);
334 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[1] / egs.getEquilibriumMolality(0),
339 EXPECT_NEAR(egs.getBulkMolesOld()[0],
342 EXPECT_NEAR(egs.getBulkMolesOld()[1], 0.0, 1.0E-9);
346 TEST(GeochemicalSolverTest, solve2)
351 {
"H2O",
"H+",
"Cl-",
"Na+",
"SO4--",
"Mg++",
"Ca++",
"K+",
"HCO3-",
"SiO2(aq)",
"O2(aq)"},
376 const std::vector<GeochemicalSystem::ConstraintUserMeaningEnum> cm = {
388 const std::vector<GeochemistryUnitConverter::GeochemistryUnit> cu = {
408 {
"H2O",
"CO2(g)",
"O2(g)",
"Cl-",
"Na+",
"SO4--",
"Mg++",
"Ca++",
"K+",
"HCO3-",
"SiO2(aq)"},
458 std::stringstream ss;
461 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
463 egs.getNumInBasis() + egs.getNumKinetic());
464 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
467 EXPECT_LE(tot_iter, (
unsigned)100);
468 EXPECT_LE(abs_residual, 1.0E-15);
471 EXPECT_EQ(egs.getNumInBasis(), (unsigned)11);
472 EXPECT_EQ(egs.getNumRedox(), (unsigned)1);
473 EXPECT_EQ(egs.getNumSurfacePotentials(), (unsigned)0);
475 EXPECT_EQ(egs.getNumKinetic(), (unsigned)0);
478 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
483 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
484 EXPECT_NEAR(egs.getSolventWaterMass(), 1.0, 1.0E-15);
485 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[0], 1.0, 1.0E-15);
491 EXPECT_TRUE(egs.getBasisActivityKnown()[i]);
492 EXPECT_NEAR(egs.getBasisActivity(i), 0.0003162278, 1.0E-15);
498 EXPECT_TRUE(egs.getBasisActivityKnown()[i]);
499 EXPECT_NEAR(egs.getBasisActivity(i), 0.2, 1.0E-15);
505 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
507 EXPECT_EQ(egs.getChargeBalanceBasisIndex(), i);
513 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
514 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.4850, 1.0E-15);
520 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
521 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.02924, 1.0E-15);
527 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
528 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.05501, 1.0E-15);
534 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
535 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.01063, 1.0E-15);
541 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
542 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.010576055, 1.0E-15);
548 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
549 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.002412, 1.0E-15);
555 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
556 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.00010349, 1.0E-15);
559 FAIL() <<
"Incorrect basis species";
562 EXPECT_NEAR(egs.getTotalChargeOld(), 0.0, 1E-15);
564 Real tot_charge = 0.0;
565 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
567 EXPECT_NEAR(tot_charge, 0.0, 1E-15);
570 for (
unsigned sp = 0; sp < egs.getNumSurfacePotentials(); ++sp)
577 egs.getSorbingSurfaceArea()[sp] * egs.getSurfaceCharge(sp) /
583 for (
unsigned i = 1; i < egs.getNumInBasis(); ++i)
587 EXPECT_NEAR(egs.getBasisActivity(i),
588 egs.getBasisActivityCoefficient(i) *
589 egs.getSolventMassAndFreeMolalityAndMineralMoles()[i],
593 for (
unsigned a = 0;
a < egs.getNumInAlgebraicSystem(); ++
a)
594 EXPECT_LE(std::abs(egs.getResidualComponent(
a, mole_additions)), 1E-15);
596 Real nw = egs.getSolventWaterMass();
597 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
599 Real res = -egs.getBulkMolesOld()[i];
603 res += egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
607 res += nw * egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
610 EXPECT_LE(std::abs(res), 1E-13);
619 for (
unsigned sp = 0; sp < egs.getNumSurfacePotentials(); ++sp)
624 egs.getSurfaceCharge(sp),
636 log10ap -= egs.getLog10K(
j);
640 log10ap -= std::log10(egs.getEquilibriumActivityCoefficient(
j));
641 if (log10ap < -300.0)
642 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j)), 1E-25);
644 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j) -
std::pow(10.0, log10ap)), 1E-15);
649 TEST(GeochemicalSolverTest, solve3)
654 {
"H2O",
"H+",
"Cl-",
"Na+",
"SO4--",
"Mg++",
"Ca++",
"K+",
"HCO3-",
"SiO2(aq)",
"O2(aq)"},
679 const std::vector<GeochemicalSystem::ConstraintUserMeaningEnum> cm = {
691 const std::vector<GeochemistryUnitConverter::GeochemistryUnit> cu = {
711 {
"H2O",
"MgCO3",
"O2(aq)",
"Cl-",
"Na+",
"SO4--",
"Mg++",
"Ca++",
"K+",
"HCO3-",
"SiO2(aq)"},
742 {
"Dolomite-ord",
"Dolomite-dis"},
748 std::stringstream ss;
751 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
753 egs.getNumInBasis() + egs.getNumKinetic());
754 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
757 EXPECT_LE(tot_iter, (
unsigned)100);
758 EXPECT_LE(abs_residual, 1.0E-15);
761 EXPECT_EQ(egs.getNumInBasis(), (unsigned)11);
762 EXPECT_EQ(egs.getNumRedox(), (unsigned)1);
763 EXPECT_EQ(egs.getNumSurfacePotentials(), (unsigned)0);
767 Real bulk_dolo = 0.0;
770 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
775 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
776 EXPECT_NEAR(egs.getSolventWaterMass(), 1.0, 1.0E-15);
777 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[0], 1.0, 1.0E-15);
783 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
784 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[i], 0.2151E-3, 1.0E-15);
790 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
792 EXPECT_EQ(egs.getChargeBalanceBasisIndex(), i);
798 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
799 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.4850, 1.0E-15);
805 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
806 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.02924, 1.0E-15);
812 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
813 bulk_mg = egs.getBulkMolesOld()[i];
819 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
820 bulk_ca = egs.getBulkMolesOld()[i];
826 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
827 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.010576055, 1.0E-15);
833 EXPECT_TRUE(egs.getBasisActivityKnown()[i]);
834 EXPECT_GE(egs.getSolventMassAndFreeMolalityAndMineralMoles()[i], 0.0);
836 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.00010349, 1.0);
842 EXPECT_TRUE(egs.getBasisActivityKnown()[i]);
843 EXPECT_GE(egs.getSolventMassAndFreeMolalityAndMineralMoles()[i], 0.0);
844 bulk_dolo = egs.getBulkMolesOld()[i];
850 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
851 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.002412, 1.0E-13);
854 FAIL() <<
"Incorrect basis species";
856 EXPECT_NEAR(bulk_dolo + bulk_ca, 0.01063, 1E-13);
857 EXPECT_NEAR(-bulk_dolo + bulk_mg, 0.05501, 1E-13);
858 EXPECT_NEAR(2.0 * bulk_dolo, 0.196E-3, 1E-13);
861 EXPECT_NEAR(egs.getTotalChargeOld(), 0.0, 1E-15);
863 Real tot_charge = 0.0;
864 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
866 EXPECT_NEAR(tot_charge, 0.0, 1E-15);
869 for (
unsigned sp = 0; sp < egs.getNumSurfacePotentials(); ++sp)
876 egs.getSorbingSurfaceArea()[sp] * egs.getSurfaceCharge(sp) /
882 for (
unsigned i = 1; i < egs.getNumInBasis(); ++i)
886 EXPECT_NEAR(egs.getBasisActivity(i),
887 egs.getBasisActivityCoefficient(i) *
888 egs.getSolventMassAndFreeMolalityAndMineralMoles()[i],
892 for (
unsigned a = 0;
a < egs.getNumInAlgebraicSystem(); ++
a)
893 EXPECT_LE(std::abs(egs.getResidualComponent(
a, mole_additions)), 1E-15);
895 Real nw = egs.getSolventWaterMass();
896 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
898 Real res = -egs.getBulkMolesOld()[i];
902 res += egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
906 res += nw * egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
909 EXPECT_LE(std::abs(res), 1E-13);
918 for (
unsigned sp = 0; sp < egs.getNumSurfacePotentials(); ++sp)
923 egs.getSurfaceCharge(sp),
935 log10ap -= egs.getLog10K(
j);
939 log10ap -= std::log10(egs.getEquilibriumActivityCoefficient(
j));
940 if (log10ap < -300.0)
941 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j)), 1E-25);
943 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j) -
std::pow(10.0, log10ap)), 1E-15);
957 EXPECT_LE(log10ap, egs.getLog10K(
j));
962 TEST(GeochemicalSolverTest, solve3_restore)
967 {
"H2O",
"H+",
"Cl-",
"Na+",
"SO4--",
"Mg++",
"Ca++",
"K+",
"HCO3-",
"SiO2(aq)",
"O2(aq)"},
992 const std::vector<GeochemicalSystem::ConstraintUserMeaningEnum> cm = {
1004 const std::vector<GeochemistryUnitConverter::GeochemistryUnit> cu = {
1024 {
"H2O",
"MgCO3",
"O2(aq)",
"Cl-",
"Na+",
"SO4--",
"Mg++",
"Ca++",
"K+",
"HCO3-",
"SiO2(aq)"},
1055 {
"Dolomite-ord",
"Dolomite-dis"},
1061 std::stringstream ss;
1064 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
1066 egs.getNumInBasis() + egs.getNumKinetic());
1067 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
1068 const Real old_residual = abs_residual;
1071 EXPECT_LE(tot_iter, (
unsigned)100);
1072 EXPECT_LE(abs_residual, 1.0E-15);
1078 std::vector<Real> molal = egs.getSolventMassAndFreeMolalityAndMineralMoles();
1079 for (
unsigned j = 0;
j < egs.getNumInEquilibrium(); ++
j)
1080 molal.push_back(egs.getEquilibriumMolality(
j));
1082 const std::vector<bool> com_false(egs.getNumInBasis(),
false);
1083 egs.setSolventMassAndFreeMolalityAndMineralMolesAndSurfacePotsAndKineticMoles(
1084 names, molal, com_false);
1096 {
"Dolomite-ord",
"Dolomite-dis"},
1102 solver0.
solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
1105 EXPECT_EQ(tot_iter, (
unsigned)0);
1106 EXPECT_EQ(abs_residual, old_residual);
1109 const std::vector<bool> com_true(egs.getNumInBasis(),
true);
1110 egs.setSolventMassAndFreeMolalityAndMineralMolesAndSurfacePotsAndKineticMoles(
1111 names, molal, com_true);
1113 solver0.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
1116 EXPECT_EQ(tot_iter, (
unsigned)0);
1117 EXPECT_LE(abs_residual, old_residual);
1122 {
"H2O",
"H+",
"Cl-",
"Na+",
"SO4--",
"Mg++",
"Ca++",
"K+",
"HCO3-",
"SiO2(aq)",
"O2(aq)"},
1152 {
"H2O",
"MgCO3",
"O2(aq)",
"Cl-",
"Na+",
"SO4--",
"Mg++",
"Ca++",
"K+",
"HCO3-",
"SiO2(aq)"},
1153 {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0},
1167 EXPECT_EQ(egs_dest, egs);
1171 TEST(GeochemicalSolverTest, solve4)
1200 const std::vector<GeochemicalSystem::ConstraintUserMeaningEnum> cm = {
1215 const std::vector<GeochemistryUnitConverter::GeochemistryUnit> cu = {
1290 std::stringstream ss;
1293 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
1295 egs.getNumInBasis() + egs.getNumKinetic());
1296 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
1299 EXPECT_LE(tot_iter, (
unsigned)100);
1300 EXPECT_LE(abs_residual, 1.0E-15);
1303 EXPECT_EQ(egs.getNumInBasis(), (unsigned)14);
1304 EXPECT_EQ(egs.getNumRedox(), (unsigned)2);
1305 EXPECT_EQ(egs.getNumSurfacePotentials(), (unsigned)0);
1309 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
1314 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1315 EXPECT_NEAR(egs.getSolventWaterMass(), 1.0, 1.0E-15);
1316 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[0], 1.0, 1.0E-15);
1322 EXPECT_TRUE(egs.getBasisActivityKnown()[i]);
1323 EXPECT_NEAR(egs.getBasisActivity(i), 0.8913E-6, 1.0E-15);
1329 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1330 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[i], 0.13438E-3, 1.0E-15);
1336 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1338 EXPECT_EQ(egs.getChargeBalanceBasisIndex(), i);
1344 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1345 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.0295E-3, 1.0E-15);
1351 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1352 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.005938E-3, 1.0E-15);
1358 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1359 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.01448E-3, 1.0E-15);
1365 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1366 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.0018704E-3, 1.0E-15);
1372 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1373 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.005115E-3, 1.0E-15);
1379 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1380 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.012534E-3, 1.0E-15);
1386 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1387 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.0005372E-3, 1.0E-15);
1393 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1394 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.005042E-3, 1.0E-15);
1400 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1401 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.001897E-3, 1.0E-15);
1407 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1408 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.01562E-3, 1.0E-15);
1411 FAIL() <<
"Incorrect basis species";
1414 EXPECT_NEAR(egs.getTotalChargeOld(), 0.0, 1E-15);
1416 Real tot_charge = 0.0;
1417 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
1419 EXPECT_NEAR(tot_charge, 0.0, 1E-15);
1422 for (
unsigned sp = 0; sp < egs.getNumSurfacePotentials(); ++sp)
1429 egs.getSorbingSurfaceArea()[sp] * egs.getSurfaceCharge(sp) /
1435 for (
unsigned i = 1; i < egs.getNumInBasis(); ++i)
1439 EXPECT_NEAR(egs.getBasisActivity(i),
1440 egs.getBasisActivityCoefficient(i) *
1441 egs.getSolventMassAndFreeMolalityAndMineralMoles()[i],
1445 for (
unsigned a = 0;
a < egs.getNumInAlgebraicSystem(); ++
a)
1446 EXPECT_LE(std::abs(egs.getResidualComponent(
a, mole_additions)), 1E-15);
1448 Real nw = egs.getSolventWaterMass();
1449 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
1451 Real res = -egs.getBulkMolesOld()[i];
1455 res += egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
1459 res += nw * egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
1462 EXPECT_LE(std::abs(res), 1E-14);
1471 for (
unsigned sp = 0; sp < egs.getNumSurfacePotentials(); ++sp)
1476 egs.getSurfaceCharge(sp),
1488 log10ap -= egs.getLog10K(
j);
1492 log10ap -= std::log10(egs.getEquilibriumActivityCoefficient(
j));
1493 if (log10ap < -300.0)
1494 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j)), 1E-25);
1496 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j) -
std::pow(10.0, log10ap)), 1E-15);
1508 EXPECT_LE(log10ap, egs.getLog10K(
j));
1513 TEST(GeochemicalSolverTest, solve4_restore)
1542 const std::vector<GeochemicalSystem::ConstraintUserMeaningEnum> cm = {
1557 const std::vector<GeochemistryUnitConverter::GeochemistryUnit> cu = {
1632 std::stringstream ss;
1635 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
1637 egs.getNumInBasis() + egs.getNumKinetic());
1638 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
1639 const Real old_residual = abs_residual;
1642 EXPECT_LE(tot_iter, (
unsigned)100);
1643 EXPECT_LE(abs_residual, 1.0E-15);
1649 std::vector<Real> molal = egs.getSolventMassAndFreeMolalityAndMineralMoles();
1650 for (
unsigned j = 0;
j < egs.getNumInEquilibrium(); ++
j)
1651 molal.push_back(egs.getEquilibriumMolality(
j));
1653 const std::vector<bool> com_false(egs.getNumInBasis(),
false);
1654 egs.setSolventMassAndFreeMolalityAndMineralMolesAndSurfacePotsAndKineticMoles(
1655 names, molal, com_false);
1672 solver0.
solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
1676 EXPECT_EQ(tot_iter, (
unsigned)0);
1677 EXPECT_LE(abs_residual, old_residual);
1680 const std::vector<bool> com_true(egs.getNumInBasis(),
true);
1681 egs.setSolventMassAndFreeMolalityAndMineralMolesAndSurfacePotsAndKineticMoles(
1682 names, molal, com_true);
1684 solver0.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
1687 EXPECT_EQ(tot_iter, (
unsigned)0);
1688 EXPECT_LE(abs_residual, old_residual);
1692 TEST(GeochemicalSolverTest, solve5)
1697 {
"H2O",
"H+",
"Na+",
"Cl-",
"Hg++",
"Pb++",
"SO4--",
"Fe+++",
">(s)FeOH",
">(w)FeOH"},
1709 const std::vector<GeochemicalSystem::ConstraintUserMeaningEnum> cm = {
1720 const std::vector<GeochemistryUnitConverter::GeochemistryUnit> cu = {
1739 {
"H2O",
"H+",
"Na+",
"Cl-",
"Hg++",
"Pb++",
"SO4--",
"Fe(OH)3(ppd)",
">(s)FeOH",
">(w)FeOH"},
1740 {1.0, 1.0E-4, 10E-3, 10E-3, 0.1E-3, 0.1E-3, 0.2E-3, 9.3573E-3, 4.6786E-5, 1.87145E-3},
1766 std::stringstream ss;
1769 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
1771 egs.getNumInBasis() + egs.getNumKinetic());
1772 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
1775 EXPECT_LE(tot_iter, (
unsigned)100);
1776 EXPECT_LE(abs_residual, 1.0E-15);
1779 EXPECT_EQ(egs.getNumInBasis(), (unsigned)10);
1780 EXPECT_EQ(egs.getNumRedox(), (unsigned)0);
1781 EXPECT_EQ(egs.getNumSurfacePotentials(), (unsigned)1);
1785 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
1790 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1791 EXPECT_NEAR(egs.getSolventWaterMass(), 1.0, 1.0E-15);
1792 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[0], 1.0, 1.0E-15);
1798 EXPECT_TRUE(egs.getBasisActivityKnown()[i]);
1799 EXPECT_NEAR(egs.getBasisActivity(i), 1.0E-4, 1.0E-15);
1805 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1806 EXPECT_NEAR(egs.getBulkMolesOld()[i], 10E-3, 1.0E-15);
1812 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1814 EXPECT_EQ(egs.getChargeBalanceBasisIndex(), i);
1820 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1821 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.1E-3, 1.0E-15);
1827 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1828 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.1E-3, 1.0E-15);
1834 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1835 EXPECT_NEAR(egs.getBulkMolesOld()[i], 0.2E-3, 1.0E-15);
1841 EXPECT_TRUE(egs.getBasisActivityKnown()[i]);
1842 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[i], 9.3573E-3, 1.0E-15);
1848 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1849 EXPECT_NEAR(egs.getBulkMolesOld()[i], 4.6786E-5, 1.0E-15);
1855 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
1856 EXPECT_NEAR(egs.getBulkMolesOld()[i], 1.87145E-3, 1.0E-15);
1859 FAIL() <<
"Incorrect basis species";
1862 EXPECT_NEAR(egs.getTotalChargeOld(), 0.0, 1E-15);
1864 Real tot_charge = 0.0;
1865 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
1867 EXPECT_NEAR(tot_charge, 0.0, 1E-15);
1870 for (
unsigned sp = 0; sp < egs.getNumSurfacePotentials(); ++sp)
1877 egs.getSorbingSurfaceArea()[sp] * egs.getSurfaceCharge(sp) /
1883 for (
unsigned i = 1; i < egs.getNumInBasis(); ++i)
1887 EXPECT_NEAR(egs.getBasisActivity(i),
1888 egs.getBasisActivityCoefficient(i) *
1889 egs.getSolventMassAndFreeMolalityAndMineralMoles()[i],
1893 for (
unsigned a = 0;
a < egs.getNumInAlgebraicSystem(); ++
a)
1894 EXPECT_LE(std::abs(egs.getResidualComponent(
a, mole_additions)), 1E-15);
1896 Real nw = egs.getSolventWaterMass();
1897 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
1899 Real res = -egs.getBulkMolesOld()[i];
1903 res += egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
1907 res += nw * egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
1910 EXPECT_LE(std::abs(res), 1E-14);
1919 for (
unsigned sp = 0; sp < egs.getNumSurfacePotentials(); ++sp)
1924 egs.getSurfaceCharge(sp),
1936 log10ap -= egs.getLog10K(
j);
1943 log10ap -= std::log10(egs.getEquilibriumActivityCoefficient(
j));
1944 if (log10ap < -300.0)
1945 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j)), 1E-25);
1947 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j) -
std::pow(10.0, log10ap)), 1E-15);
1959 EXPECT_LE(log10ap, egs.getLog10K(
j));
1964 TEST(GeochemicalSolverTest, solve5_restore)
1969 {
"H2O",
"H+",
"Na+",
"Cl-",
"Hg++",
"Pb++",
"SO4--",
"Fe+++",
">(s)FeOH",
">(w)FeOH"},
1981 const std::vector<GeochemicalSystem::ConstraintUserMeaningEnum> cm = {
1992 const std::vector<GeochemistryUnitConverter::GeochemistryUnit> cu = {
2011 {
"H2O",
"H+",
"Na+",
"Cl-",
"Hg++",
"Pb++",
"SO4--",
"Fe(OH)3(ppd)",
">(s)FeOH",
">(w)FeOH"},
2012 {1.0, 1.0E-4, 10E-3, 10E-3, 0.1E-3, 0.1E-3, 0.2E-3, 9.3573E-3, 4.6786E-5, 1.87145E-3},
2038 std::stringstream ss;
2041 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
2043 egs.getNumInBasis() + egs.getNumKinetic());
2044 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
2045 const Real old_residual = abs_residual;
2048 EXPECT_LE(tot_iter, (
unsigned)100);
2049 EXPECT_LE(abs_residual, 1.0E-15);
2058 names.push_back(
"Fe(OH)3(ppd)_surface_potential_expr");
2059 std::vector<Real> molal = egs.getSolventMassAndFreeMolalityAndMineralMoles();
2060 for (
unsigned j = 0;
j < egs.getNumInEquilibrium(); ++
j)
2061 molal.push_back(egs.getEquilibriumMolality(
j));
2066 const std::vector<bool> com_false(egs.getNumInBasis(),
false);
2067 egs.setSolventMassAndFreeMolalityAndMineralMolesAndSurfacePotsAndKineticMoles(
2068 names, molal, com_false);
2070 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
2071 EXPECT_EQ(tot_iter, (
unsigned)0);
2072 EXPECT_LE(abs_residual, 2.0 * old_residual);
2075 const std::vector<bool> com_true(egs.getNumInBasis(),
true);
2076 egs.setSolventMassAndFreeMolalityAndMineralMolesAndSurfacePotsAndKineticMoles(
2077 names, molal, com_true);
2079 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
2081 EXPECT_EQ(tot_iter, (
unsigned)0);
2082 EXPECT_LE(abs_residual, 2.0 * old_residual);
2089 {
"H2O",
"H+",
"Na+",
"Cl-",
"Hg++",
"Pb++",
"SO4--",
"Fe+++",
">(s)FeOH",
">(w)FeOH"},
2108 {
"H2O",
"H+",
"Na+",
"Cl-",
"Hg++",
"Pb++",
"SO4--",
"Fe(OH)3(ppd)",
">(s)FeOH",
">(w)FeOH"},
2109 {2.0, 2.0E-4, 20E-3, 20E-3, 0.2E-3, 0.2E-3, 0.4E-3, 19.3573E-3, 14.6786E-5, 2.87145E-3},
2123 EXPECT_EQ(dest_egs, egs);
2127 TEST(GeochemicalSolverTest, solve_addH)
2161 std::stringstream ss;
2164 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
2166 egs.getNumInBasis() + egs.getNumKinetic());
2167 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
2170 EXPECT_LE(tot_iter, (
unsigned)100);
2171 EXPECT_LE(abs_residual, 1.0E-12);
2174 const std::vector<Real> bulk = egs.getBulkMolesOld();
2175 EXPECT_NEAR(bulk[0],
2178 EXPECT_NEAR(bulk[1], 0.0, 1.0E-9);
2181 egs.changeConstraintToBulk(0);
2184 std::vector<Real> bulk_new = egs.getBulkMolesOld();
2185 for (
unsigned i = 0; i < 2; ++i)
2186 EXPECT_EQ(bulk_new[i], bulk[i]);
2189 mole_additions(0) = 1.0;
2190 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
2193 EXPECT_LE(tot_iter, (
unsigned)100);
2194 EXPECT_LE(abs_residual, 1.0E-12);
2197 bulk_new = egs.getBulkMolesOld();
2198 EXPECT_EQ(bulk_new[0], bulk[0] + 1.0);
2199 EXPECT_EQ(bulk_new[1], bulk[1]);
2203 mole_additions(0) = 0.0;
2204 mole_additions(1) = 1.0;
2205 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
2208 EXPECT_LE(tot_iter, (
unsigned)100);
2209 EXPECT_LE(abs_residual, 1.0E-12);
2212 bulk_new = egs.getBulkMolesOld();
2213 EXPECT_EQ(bulk_new[0], bulk[0] + 1.0);
2214 EXPECT_EQ(bulk_new[1], bulk[1]);
2218 TEST(GeochemicalSolverTest, maxSwapsException)
2223 {
"H2O",
"H+",
"Cl-",
"Na+",
"SO4--",
"Mg++",
"Ca++",
"K+",
"HCO3-",
"SiO2(aq)",
"O2(aq)"},
2248 const std::vector<GeochemicalSystem::ConstraintUserMeaningEnum> cm = {
2260 const std::vector<GeochemistryUnitConverter::GeochemistryUnit> cu = {
2280 {
"H2O",
"MgCO3",
"O2(aq)",
"Cl-",
"Na+",
"SO4--",
"Mg++",
"Ca++",
"K+",
"HCO3-",
"SiO2(aq)"},
2311 {
"Dolomite-ord",
"Dolomite-dis"},
2317 std::stringstream ss;
2322 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
2324 egs.getNumInBasis() + egs.getNumKinetic());
2325 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
2326 FAIL() <<
"Missing expected exception.";
2328 catch (
const std::exception & e)
2330 std::string msg(e.what());
2331 ASSERT_TRUE(msg.find(
"Maximum number of swaps performed during solve") != std::string::npos)
2332 <<
"Failed with unexpected error message: " << msg;
2337 TEST(GeochemicalSolverTest, setRampMaxIonicStrength)
2371 ASSERT_EQ(solver.getRampMaxIonicStrength(), (unsigned)10);
2374 solver.setRampMaxIonicStrength(101);
2375 FAIL() <<
"Missing expected exception.";
2377 catch (
const std::exception & e)
2379 std::string msg(e.what());
2380 ASSERT_TRUE(msg.find(
"GeochemicalSolver: ramp_max_ionic_strength must be less than max_iter") !=
2382 <<
"Failed with unexpected error message: " << msg;
2384 solver.setRampMaxIonicStrength(21);
2385 ASSERT_EQ(solver.getRampMaxIonicStrength(), (unsigned)21);
2389 TEST(GeochemicalSolverTest, solve_kinetic1)
2392 {
"H2O",
"H+",
"Fe+++",
"HCO3-"},
2395 {
"Something",
"Fe(OH)3(ppd)fake"},
2401 std::vector<GeochemistryUnitConverter::GeochemistryUnit> ku;
2411 {
"H2O",
"H+",
"Fe+++",
"HCO3-"},
2412 {1.75, 1E-5, 1E-5, 4E-5},
2418 {
"Something",
"Fe(OH)3(ppd)fake"},
2435 std::stringstream ss;
2438 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
2440 egs.getNumInBasis() + egs.getNumKinetic());
2441 solver.solveSystem(egs, ss, tot_iter, abs_residual, 0.0, mole_additions, dmole_additions);
2444 EXPECT_LE(tot_iter, (
unsigned)100);
2445 EXPECT_LE(abs_residual, 1.0E-15);
2448 EXPECT_EQ(egs.getNumInBasis(), (unsigned)4);
2449 EXPECT_EQ(egs.getNumRedox(), (unsigned)0);
2450 EXPECT_EQ(egs.getNumSurfacePotentials(), (unsigned)0);
2452 EXPECT_EQ(egs.getNumKinetic(), (unsigned)2);
2455 for (
unsigned k = 0;
k < egs.getNumKinetic(); ++
k)
2457 EXPECT_EQ(egs.getKineticMoles(
k), 1.0E-6);
2459 EXPECT_EQ(egs.getKineticMoles(
k), 2.0E-6);
2461 FAIL() <<
"Incorrect kinetic species";
2464 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
2469 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
2470 EXPECT_NEAR(egs.getSolventWaterMass(), 1.75, 1.0E-15);
2471 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[0], 1.75, 1.0E-15);
2477 EXPECT_TRUE(egs.getBasisActivityKnown()[i]);
2478 EXPECT_NEAR(egs.getBasisActivity(i), 1E-5, 1.0E-15);
2484 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
2485 EXPECT_NEAR(egs.getBulkMolesOld()[i], 1E-5 + 1E-6 + 2 * 2E-6, 1.0E-15);
2491 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
2493 EXPECT_EQ(egs.getChargeBalanceBasisIndex(), i);
2496 FAIL() <<
"Incorrect basis species";
2499 EXPECT_NEAR(egs.getTotalChargeOld(), 0.0, 1E-15);
2501 Real tot_charge = 0.0;
2502 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
2504 EXPECT_NEAR(tot_charge, 0.0, 1E-15);
2507 for (
unsigned i = 1; i < egs.getNumInBasis(); ++i)
2511 EXPECT_NEAR(egs.getBasisActivity(i),
2512 egs.getBasisActivityCoefficient(i) *
2513 egs.getSolventMassAndFreeMolalityAndMineralMoles()[i],
2517 for (
unsigned a = 0;
a < egs.getNumInAlgebraicSystem(); ++
a)
2518 EXPECT_LE(std::abs(egs.getResidualComponent(
a, mole_additions)), 1E-15);
2520 Real nw = egs.getSolventWaterMass();
2521 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
2523 Real res = -egs.getBulkMolesOld()[i];
2527 res += egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
2531 res += nw * egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
2536 egs.getKineticMoles(
2538 EXPECT_LE(std::abs(res), 1E-13);
2549 log10ap -= egs.getLog10K(
j);
2553 log10ap -= std::log10(egs.getEquilibriumActivityCoefficient(
j));
2554 if (log10ap < -300.0)
2555 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j)), 1E-25);
2557 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j) -
std::pow(10.0, log10ap)), 1E-15);
2562 TEST(GeochemicalSolverTest, solve_kinetic2)
2565 {
"H2O",
"H+",
"Fe+++",
"HCO3-"},
2568 {
"Something",
"Fe(OH)3(ppd)fake"},
2623 std::vector<GeochemistryUnitConverter::GeochemistryUnit> ku;
2633 {
"H2O",
"H+",
"Fe+++",
"HCO3-"},
2634 {1.75, 1E-5, 1E-5, 4E-5},
2640 {
"Something",
"Fe(OH)3(ppd)fake"},
2660 std::stringstream ss;
2663 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
2664 mole_additions(egs.getNumInBasis() + index_something) = 1.5E-6;
2666 egs.getNumInBasis() + egs.getNumKinetic());
2668 solver.solveSystem(egs, ss, tot_iter, abs_residual, 10.0, mole_additions, dmole_additions);
2671 EXPECT_LE(tot_iter, (
unsigned)100);
2672 EXPECT_LE(abs_residual, 1.0E-15);
2675 EXPECT_EQ(egs.getNumInBasis(), (unsigned)4);
2676 EXPECT_EQ(egs.getNumRedox(), (unsigned)0);
2677 EXPECT_EQ(egs.getNumSurfacePotentials(), (unsigned)0);
2679 EXPECT_EQ(egs.getNumKinetic(), (unsigned)2);
2682 EXPECT_GT(egs.log10KineticActivityProduct(index_something),
2683 egs.getKineticLog10K(index_something));
2684 EXPECT_LT(egs.log10KineticActivityProduct(index_fe), egs.getKineticLog10K(index_fe));
2687 EXPECT_EQ(mole_additions(egs.getNumInBasis() + index_something), 1.5E-6 + 1.0E-6);
2688 EXPECT_EQ(mole_additions(egs.getNumInBasis() + index_fe), -1.0E-6);
2691 for (
unsigned k = 0;
k < egs.getNumKinetic(); ++
k)
2693 EXPECT_NEAR(egs.getKineticMoles(
k), 2.0E-6 + 1.5E-6, 1.0E-12);
2695 EXPECT_EQ(egs.getKineticMoles(
k), 1.0E-6);
2697 FAIL() <<
"Incorrect kinetic species";
2700 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
2705 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
2706 EXPECT_NEAR(egs.getSolventWaterMass(), 1.75, 1.0E-15);
2707 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[0], 1.75, 1.0E-15);
2713 EXPECT_TRUE(egs.getBasisActivityKnown()[i]);
2714 EXPECT_NEAR(egs.getBasisActivity(i), 1E-5, 1.0E-15);
2720 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
2721 EXPECT_NEAR(egs.getBulkMolesOld()[i], 1E-5 + 1E-6 + 2 * 2E-6, 1.0E-15);
2727 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
2729 EXPECT_EQ(egs.getChargeBalanceBasisIndex(), i);
2732 FAIL() <<
"Incorrect basis species";
2735 EXPECT_NEAR(egs.getTotalChargeOld(), 0.0, 1E-15);
2737 Real tot_charge = 0.0;
2738 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
2740 EXPECT_NEAR(tot_charge, 0.0, 1E-15);
2743 for (
unsigned i = 1; i < egs.getNumInBasis(); ++i)
2747 EXPECT_NEAR(egs.getBasisActivity(i),
2748 egs.getBasisActivityCoefficient(i) *
2749 egs.getSolventMassAndFreeMolalityAndMineralMoles()[i],
2753 mole_additions.zero();
2754 for (
unsigned a = 0;
a < egs.getNumInAlgebraicSystem(); ++
a)
2755 EXPECT_LE(std::abs(egs.getResidualComponent(
a, mole_additions)), 1E-15);
2757 Real nw = egs.getSolventWaterMass();
2758 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
2760 Real res = -egs.getBulkMolesOld()[i];
2764 res += egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
2768 res += nw * egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
2773 EXPECT_LE(std::abs(res), 1E-13);
2784 log10ap -= egs.getLog10K(
j);
2788 log10ap -= std::log10(egs.getEquilibriumActivityCoefficient(
j));
2789 if (log10ap < -300.0)
2790 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j)), 1E-25);
2792 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j) -
std::pow(10.0, log10ap)), 1E-15);
2797 TEST(GeochemicalSolverTest, solve_kinetic3)
2800 db_solver, {
"H2O",
"H+",
"Fe+++",
"HCO3-"}, {}, {}, {
"Something"}, {}, {},
"O2(aq)",
"e-");
2830 std::vector<GeochemistryUnitConverter::GeochemistryUnit> ku;
2839 {
"H2O",
"H+",
"Fe+++",
"HCO3-"},
2840 {1.75, 1E-5, 1E-5, 4E-5},
2863 std::stringstream ss;
2866 DenseVector<Real> mole_additions(egs.getNumInBasis() + egs.getNumKinetic());
2868 egs.getNumInBasis() + egs.getNumKinetic());
2870 solver.solveSystem(egs, ss, tot_iter, abs_residual, 1.0E4, mole_additions, dmole_additions);
2873 EXPECT_LE(tot_iter, (
unsigned)100);
2874 EXPECT_LE(abs_residual, 1.0E-15);
2877 EXPECT_EQ(egs.getNumInBasis(), (unsigned)4);
2878 EXPECT_EQ(egs.getNumRedox(), (unsigned)0);
2879 EXPECT_EQ(egs.getNumSurfacePotentials(), (unsigned)0);
2881 EXPECT_EQ(egs.getNumKinetic(), (unsigned)1);
2884 const unsigned index_something = 0;
2885 EXPECT_GT(egs.log10KineticActivityProduct(index_something),
2886 egs.getKineticLog10K(index_something));
2889 EXPECT_NEAR(mole_additions(egs.getNumInBasis() + index_something) /
2890 (1.0E4 * 4.56796204026978E-06 * egs.getKineticMoles(0)),
2895 for (
unsigned k = 0;
k < egs.getNumKinetic(); ++
k)
2897 EXPECT_NEAR(egs.getKineticMoles(
k),
2898 1.0E-6 + mole_additions(egs.getNumInBasis() + index_something),
2901 FAIL() <<
"Incorrect kinetic species";
2904 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
2909 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
2910 EXPECT_NEAR(egs.getSolventWaterMass(), 1.75, 1.0E-15);
2911 EXPECT_NEAR(egs.getSolventMassAndFreeMolalityAndMineralMoles()[0], 1.75, 1.0E-15);
2917 EXPECT_TRUE(egs.getBasisActivityKnown()[i]);
2918 EXPECT_NEAR(egs.getBasisActivity(i), 1E-5, 1.0E-15);
2924 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
2925 EXPECT_NEAR(egs.getBulkMolesOld()[i], 1E-5 + 1E-6, 1E-15);
2931 EXPECT_FALSE(egs.getBasisActivityKnown()[i]);
2933 EXPECT_EQ(egs.getChargeBalanceBasisIndex(), i);
2936 FAIL() <<
"Incorrect basis species";
2939 EXPECT_NEAR(egs.getTotalChargeOld(), 0.0, 1E-15);
2941 Real tot_charge = 0.0;
2942 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
2944 EXPECT_NEAR(tot_charge, 0.0, 1E-15);
2947 for (
unsigned i = 1; i < egs.getNumInBasis(); ++i)
2951 EXPECT_NEAR(egs.getBasisActivity(i),
2952 egs.getBasisActivityCoefficient(i) *
2953 egs.getSolventMassAndFreeMolalityAndMineralMoles()[i],
2957 mole_additions.zero();
2958 for (
unsigned a = 0;
a < egs.getNumInAlgebraicSystem(); ++
a)
2959 EXPECT_LE(std::abs(egs.getResidualComponent(
a, mole_additions)), 1E-15);
2961 Real nw = egs.getSolventWaterMass();
2962 for (
unsigned i = 0; i < egs.getNumInBasis(); ++i)
2964 Real res = -egs.getBulkMolesOld()[i];
2968 res += egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
2972 res += nw * egs.getSolventMassAndFreeMolalityAndMineralMoles()[i];
2977 EXPECT_LE(std::abs(res), 1E-13);
2988 log10ap -= egs.getLog10K(
j);
2992 log10ap -= std::log10(egs.getEquilibriumActivityCoefficient(
j));
2993 if (log10ap < -300.0)
2994 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j)), 1E-25);
2996 EXPECT_LE(std::abs(egs.getEquilibriumMolality(
j) -
std::pow(10.0, log10ap)), 1E-15);
std::vector< bool > surface_sorption_related
surface_sorption_related[j] = true iff the j^th equilibrium species is involved in surface sorption ...
constexpr Real MOLES_PER_KG_WATER
constexpr Real CELSIUS_TO_KELVIN
GeochemistryIonicStrength is_solver(3.0, 3.0, false, false)
std::vector< bool > eqm_species_gas
eqm_species_gas[i] = true iff the i^th equilibrium species is a gas
constexpr Real DIELECTRIC_CONSTANT_WATER
const std::vector< GeochemicalSystem::ConstraintUserMeaningEnum > cm4
const ModelGeochemicalDatabase mgd
DenseMatrix< Real > kin_stoichiometry
kin_stoichiometry(i, j) = stoichiometric coefficient for kinetic species "i" in terms of the basis sp...
void setMaxInitialResidual(Real max_initial_residual)
Set value for max_initial_residual.
GeochemistrySpeciesSwapper swapper2(2, 1E-6)
std::unordered_map< std::string, unsigned > kin_species_index
kin_species_index[name] = index of the kinetic species, within all ModelGeochemicalDatabase internal ...
DenseMatrix< Real > eqm_stoichiometry
eqm_stoichiometry(i, j) = stoichiometric coefficient for equilibrium species "i" in terms of the basi...
Class to swap basis species with equilibrium species.
constexpr Real PERMITTIVITY_FREE_SPACE
std::vector< unsigned > surface_sorption_number
surface_sorption_number[j] = the index of the surface potential that should be used to modify the equ...
Computes activity coefficients for non-minerals and non-gases (since these species do not have activi...
const ModelGeochemicalDatabase & modelGeochemicalDatabase() const
Return a reference to the ModelGeochemicalDatabase structure.
const GeochemicalDatabaseReader db_full("../database/moose_geochemdb.json", true, true, false)
void addKineticRate(const KineticRateUserDescription &description)
Adds a rate description for kinetic_species.
const GeochemicalDatabaseReader db_ferric("../test/database/ferric_hydroxide_sorption.json", true, true)
Constructs and stores a minimal amount of information that is pertinent to the user-defined geochemic...
Calculators to compute ionic strength and stoichiometric ionic strength.
void solveSystem(GeochemicalSystem &egs, std::stringstream &ss, unsigned &tot_iter, Real &abs_residual, Real dt, DenseVector< Real > &mole_additions, DenseMatrix< Real > &dmole_additions)
Solve the system.
const PertinentGeochemicalSystem model(database, {"H2O", "H+", "HCO3-", "O2(aq)", "Ca++", ">(s)FeOH", "radius_neg1", "radius_neg1.5"}, {"Calcite"}, {}, {"Calcite_asdf"}, {"CH4(aq)"}, {">(s)FeOCa+"}, "O2(aq)", "e-")
GeochemistrySpeciesSwapper swapper_kin(4, 1E-6)
TEST(GeochemicalSolverTest, exception)
Check exception.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::vector< GeochemistryUnitConverter::GeochemistryUnit > cu2
constexpr Real DENSITY_WATER
GeochemistryActivityCoefficientsDebyeHuckel ac_solver(is_solver, db_solver)
constexpr Real GAS_CONSTANT
This class holds information about bulk composition, molalities, activities, activity coefficients...
std::vector< Real > basis_species_charge
all quantities have a charge (mineral charge = 0, gas charge = 0, oxide charge = 0) ...
Holds a user-specified description of a kinetic rate.
std::vector< bool > basis_species_gas
basis_species_gas[j] = true iff the j^th basis species is a gas
std::vector< bool > basis_species_mineral
basis_species_mineral[j] = true iff the j^th basis species is a mineral
std::vector< Real > eqm_species_charge
all quantities have a charge (mineral charge = 0, gas charge = 0, oxide charge = 0) ...
std::vector< std::string > kin_species_name
kin_species_name[j] = name of the j^th kinetic species
Data structure to hold all relevant information from the database file.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
std::vector< bool > eqm_species_mineral
eqm_species_mineral[i] = true iff the i^th equilibrium species is a mineral
const PertinentGeochemicalSystem model_simplest(db_solver, {"H2O", "H+"}, {}, {}, {}, {}, {}, "O2(aq)", "e-")
const GeochemicalDatabaseReader db_solver("database/moose_testdb.json", true, true, false)
void closeSystem()
Changes a KG_SOLVENT_WATER constraint to MOLES_BULK_WATER (if there is such a constraint) and all FRE...
const std::vector< GeochemicalSystem::ConstraintUserMeaningEnum > cm2
This class contains methods to solve the algebraic system in GeochemicalSystem.
MooseUnits pow(const MooseUnits &, int)
std::vector< std::string > eqm_species_name
eqm_species_name[i] = name of the i^th eqm species
static const std::string k
std::vector< std::string > basis_species_name
basis_species_name[j] = name of the j^th basis species
Class for reading geochemical reactions from a MOOSE geochemical database.
const std::vector< GeochemistryUnitConverter::GeochemistryUnit > cu4