diff --git a/tests/specmicp/adim/adimensional_system.cpp b/tests/specmicp/adim/adimensional_system.cpp index 82d4eaf..d8d30fb 100644 --- a/tests/specmicp/adim/adimensional_system.cpp +++ b/tests/specmicp/adim/adimensional_system.cpp @@ -1,256 +1,258 @@ #include "catch.hpp" #include "specmicp/adimensional/adimensional_system.hpp" #include "database/database.hpp" #include specmicp::RawDatabasePtr get_test_database() { specmicp::database::Database thedatabase("../data/cemdata_specmicp.js"); std::map swapping ({ {"H[+]","HO[-]"}, }); thedatabase.swap_components(swapping); std::vector to_keep = {"HO[-]", "Ca[2+]"}; thedatabase.keep_only_components(to_keep); return thedatabase.get_database(); } specmicp::RawDatabasePtr get_test_oxydoreduc_database() { specmicp::database::Database thedatabase("../data/cemdata.js"); std::map swapping ({ {"H[+]","HO[-]"}, }); thedatabase.swap_components(swapping); std::vector to_keep = {"HO[-]", "Ca[2+]"}; thedatabase.keep_only_components(to_keep); return thedatabase.get_database(); } using namespace specmicp; TEST_CASE("Adimensional system", "[specmicp][MiCP program][adimensional]") { RawDatabasePtr thedatabase = get_test_database(); auto id_h2o = database::DataContainer::water_index(); auto id_oh = thedatabase->get_id_component("HO[-]"); auto id_ca = thedatabase->get_id_component("Ca[2+]"); auto id_ch = thedatabase->get_id_mineral("Portlandite"); SECTION("initialization") { Vector total_concentration = Vector::Zero(thedatabase->nb_component()); total_concentration(id_h2o) = 55.5; total_concentration(id_oh) = 2e-3; total_concentration(id_ca) = 1e-3; AdimensionalSystemConstraints constraints(total_concentration); AdimensionalSystem system(thedatabase, constraints); REQUIRE(system.ideq_w() != no_equation); REQUIRE(system.ideq_paq(id_oh) != no_equation); REQUIRE(system.ideq_paq(id_ca) != no_equation); REQUIRE(system.ideq_min(id_ch) != no_equation); Vector x = Vector::Zero(system.total_dofs()); x(id_h2o) = 1.0; x(id_oh) = std::log10(2e-3); x(id_ca) = -3; system.set_secondary_concentration(x); scalar_t molality_h = system.secondary_molality(0); REQUIRE(std::isfinite(molality_h)); REQUIRE(molality_h == Approx(5e-12)); system.compute_log_gamma(x); molality_h = system.secondary_molality(0); REQUIRE(std::isfinite(molality_h)); system.hook_start_iteration(x, 1.0); molality_h = system.secondary_molality(0); REQUIRE(std::isfinite(molality_h)); system.hook_start_iteration(x, 1.0); REQUIRE(molality_h == Approx(system.secondary_molality(0))); } SECTION("Residuals") { Vector total_concentration = Vector::Zero(thedatabase->nb_component()); total_concentration(id_h2o) = 55.5; total_concentration(id_oh) = 2e-3; total_concentration(id_ca) = 1e-3; specmicp::AdimensionalSystemConstraints constraints(total_concentration); specmicp::AdimensionalSystem system(thedatabase, constraints); Vector x = Vector::Zero(system.total_dofs()); x(system.ideq_w()) = 1.0; x(system.ideq_paq(id_oh)) = std::log10(2e-3); x(system.ideq_paq(id_ca)) = -3; specmicp::scalar_t res = system.residual_water(x); REQUIRE(std::isfinite(res)); REQUIRE(res == Approx((55.5 - system.density_water()/thedatabase->molar_mass_basis_si(id_h2o))/55.5)); } SECTION("Equation numbering") { Vector total_concentration = Vector::Zero(thedatabase->nb_component()); total_concentration(id_h2o) = 55.5; total_concentration(id_oh) = 2e-3; total_concentration(id_ca) = 1e-3; specmicp::AdimensionalSystemConstraints constraints(total_concentration); constraints.disable_conservation_water(); constraints.enable_surface_model(1.23456); constraints.total_concentrations(2) = 0; specmicp::AdimensionalSystem system(thedatabase, constraints); CHECK(system.water_equation_type() == specmicp::WaterEquationType::NoEquation); CHECK(system.surface_model() == specmicp::SurfaceEquationType::Equilibrium); CHECK(system.surface_total_concentration() == 1.23456); CHECK((int) system.aqueous_component_equation_type(2) == (int) specmicp::AqueousComponentEquationType::NoEquation); constraints = specmicp::AdimensionalSystemConstraints(total_concentration); constraints.enable_conservation_water(); constraints.disable_surface_model(); constraints.add_fixed_activity_component(2, -2.0); system = specmicp::AdimensionalSystem(thedatabase, constraints); CHECK(system.water_equation_type() == specmicp::WaterEquationType::MassConservation); CHECK(system.surface_model() == specmicp::SurfaceEquationType::NoEquation); CHECK(system.aqueous_component_equation_type(2) == specmicp::AqueousComponentEquationType::FixedActivity); CHECK(system.fixed_activity_bc(2) == -2.0); } SECTION("Jacobian") { // add a sorbed species, just to see if it works thedatabase->sorbed.resize(1); specmicp::database::SorbedValues values; values.label = "SorbedSpecies"; values.logk = -1; values.sorption_site_occupied = 1; thedatabase->sorbed.set_values(0, std::move(values)); specmicp::Matrix numatrix(1, thedatabase->nb_component()); numatrix << 0, 0, 2, 1; thedatabase->sorbed.set_nu_matrix(numatrix); + thedatabase->sorbed.set_valid(); Vector total_concentration = Vector::Zero(thedatabase->nb_component()); total_concentration(id_h2o) = 55.5; total_concentration(id_oh) = 2e-3; total_concentration(id_ca) = 1e-3; specmicp::AdimensionalSystemConstraints constraints(total_concentration); constraints.enable_conservation_water(); constraints.enable_surface_model(1.23456); specmicp::AdimensionalSystem system (thedatabase, constraints); Vector x = Vector::Zero(system.total_variables()); x(system.ideq_w()) = 1.0; x(system.ideq_paq(id_oh)) = std::log10(2e-3); x(system.ideq_paq(id_ca)) = -3; specmicp::Vector residual; system.get_residuals(x, residual); std::cout << residual << std::endl; specmicp::Matrix analytical_jacobian; system.analytical_jacobian(x, analytical_jacobian); specmicp::Matrix fd_jacobian; system.finite_difference_jacobian(x, fd_jacobian); std::cout << analytical_jacobian - fd_jacobian << std::endl; REQUIRE((analytical_jacobian - fd_jacobian).isMuchSmallerThan(1.0, 1e-3)); } } TEST_CASE("Adimensional system - oxydoreduc", "[specmicp][MiCP program][adimensional]") { RawDatabasePtr thedatabase = get_test_oxydoreduc_database(); auto id_h2o = database::DataContainer::water_index(); auto id_oh = thedatabase->get_id_component("HO[-]"); auto id_ca = thedatabase->get_id_component("Ca[2+]"); auto id_ch = thedatabase->get_id_mineral("Portlandite"); SECTION("Jacobian - oxydoreduc") { // add a sorbed species, just to see if it works thedatabase->sorbed.resize(1); specmicp::database::SorbedValues values; values.label = "SorbedSpecies"; values.logk = -1; values.sorption_site_occupied = 1; thedatabase->sorbed.set_values(0, std::move(values)); specmicp::Matrix numatrix(1, thedatabase->nb_component()); numatrix << 0, 0, 2, 1; thedatabase->sorbed.set_nu_matrix(numatrix); + thedatabase->sorbed.set_valid(); Vector total_concentration = Vector::Zero(thedatabase->nb_component()); total_concentration(id_h2o) = 55.5; total_concentration(id_oh) = 2e-3; total_concentration(id_ca) = 1e-3; specmicp::AdimensionalSystemConstraints constraints(total_concentration); constraints.enable_conservation_water(); constraints.enable_surface_model(1.23456); specmicp::AdimensionalSystem system (thedatabase, constraints); Vector x = Vector::Zero(system.total_variables()); x(system.ideq_w()) = 1.0; x(system.ideq_paq(id_oh)) = std::log10(2e-3); x(system.ideq_paq(id_ca)) = -3.0; x(system.ideq_electron()) = -2.0; for (index_t j: thedatabase->range_aqueous()){ std::cout << "\t" << thedatabase->get_label_aqueous(j); } std::cout << "\n"; std::cout << thedatabase->aqueous.get_nu_matrix() << std::endl; specmicp::Vector residual; system.get_residuals(x, residual); std::cout << residual << std::endl; specmicp::Matrix analytical_jacobian; system.analytical_jacobian(x, analytical_jacobian); specmicp::Matrix fd_jacobian; system.finite_difference_jacobian(x, fd_jacobian); std::cout << analytical_jacobian - fd_jacobian << std::endl; REQUIRE((analytical_jacobian - fd_jacobian).isMuchSmallerThan(1.0, 1e-3)); } }