Page MenuHomec4science

adimensional_system.cpp
No OneTemporary

File Metadata

Created
Tue, May 28, 07:40

adimensional_system.cpp

#include "catch.hpp"
#include "specmicp/adimensional/adimensional_system.hpp"
#include "database/database.hpp"
#include <iostream>
specmicp::RawDatabasePtr get_test_database()
{
specmicp::database::Database thedatabase("../data/cemdata_specmicp.js");
std::map<std::string, std::string> swapping ({
{"H[+]","HO[-]"},
});
thedatabase.swap_components(swapping);
std::vector<std::string> 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<std::string, std::string> swapping ({
{"H[+]","HO[-]"},
});
thedatabase.swap_components(swapping);
std::vector<std::string> 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(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));
}
}

Event Timeline