Page MenuHomec4science

benchmark_rasouli.cpp
No OneTemporary

File Metadata

Created
Wed, Jul 17, 14:09

benchmark_rasouli.cpp

/* =============================================================================
Copyright (c) 2014-2017 F. Georget <fabieng@princeton.edu> Princeton University
Copyright (c) 2017 F. Georget <fabien.georget@epfl.ch> EPFL
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
============================================================================= */
// Benchmarks as described in :
// Rasouli, Pejman, Steefel, Carl I., Mayer, K. Ulrich, Rolle, Massimo
// Benchmarks for multicomponent diffusion and electrochemical migration
// Computational Geosciences 19(3), 523–533, Jun 2015
#include "reactmicp/systems/chloride/variables.hpp"
#include "reactmicp/systems/chloride/variables_interface.hpp"
#include "reactmicp/systems/chloride/transport_stagger.hpp"
#include "reactmicp/systems/chloride/boundary_conditions.hpp"
#include "specmicp_common/log.hpp"
#include "specmicp_database/io/configuration.hpp"
#include "specmicp/adimensional/adimensional_system_solver.hpp"
#include "specmicp/problem_solver/smart_solver.hpp"
#include "specmicp/problem_solver/reactant_box.hpp"
#include "specmicp/adimensional/adimensional_system_solver_structs.hpp"
#include "reactmicp/systems/chloride/transport_program_struct.hpp"
#include "reactmicp/solver/staggers_base/stagger_structs.hpp"
#include "dfpm/solver/parabolic_structs.hpp"
#include "specmicp_common/log.hpp"
#include <vector>
#include <iostream>
#include <sstream>
using namespace specmicp;
using namespace specmicp::reactmicp::systems::chloride;
// ===========================
//
// Benchmark 1
//
// ===========================
const auto db_b1 = R"dbb1(
Metadata:
name: CEMDATA14
version: 2018-02-16 15:15:01 +0100
path: N/A
Elements:
- element: "O"
component: H2O
- element: "E"
component: E[-]
- element: "H"
component: H[+]
- element: "Cl"
component: Cl[-]
- element: "Na"
component: Na[+]
- element: "N"
component: NO3[-]
Basis:
- label: H2O
molar_mass: 0.018015
- label: E[-]
molar_mass: 0
- label: H[+]
molar_mass: 0.001008
activity:
a: 9
b: 0
- label: Cl[-]
molar_mass: 0.035453
activity:
a: 3.71
b: 0.01
- label: Na[+]
molar_mass: 0.02299
activity:
a: 4.32
b: 0.06
- label: NO3[-]
molar_mass: 0.062004
activity:
a: 3
b: 0
Aqueous:
- label: "HO[-]"
composition: "H2O, - H[+]"
log_k: 13.9995
activity:
a: 10.65
b: 0
Minerals:
[]
Gas:
[]
Sorbed:
[]
Compounds:
- label: "NaCl"
composition: "Cl[-], Na[+]"
- label: "NaOH"
composition: "H2O, - H[+], Na[+]"
- label: "NaNO3"
composition: "Na[+], NO3[-]"
- label: "HCl"
composition: "H[+], Cl[-]"
- label: "HNO3"
composition: "H[+], NO3[-]"
)dbb1";
database::RawDatabasePtr b1_database() {
static database::RawDatabasePtr raw_data {nullptr};
if (raw_data == nullptr)
{
std::istringstream input_db(db_b1);
database::Database thedatabase;
thedatabase.parse_database(input_db);
raw_data = thedatabase.get_database();
raw_data->freeze_db();
//thedatabase.save("db_b1.yaml");
}
return raw_data;
}
AdimensionalSystemSolution b1_initial_condition(
database::RawDatabasePtr b1_data,
const specmicp::units::UnitsSet& tunits) {
ReactantBox box(b1_data, tunits);
box.set_solution(1.0, "L/L");
box.set_saturated_system();
box.set_inert_volume_fraction(0.0);
box.add_aqueous_species("NaCl", 0.1e-3, "mol/L");
box.add_aqueous_species("HNO3", 0.1e-3, "mol/L");
box.set_charge_keeper("Cl[-]");
box.add_fixed_activity_component("H[+]", std::pow(10, -4.007));
SmartAdimSolver solver(b1_data, box, false);
if (! solver.solve()) {
throw std::runtime_error("Cannot solve benchmark 1 initial conditions");
}
return solver.get_solution();
}
AdimensionalSystemSolution b1_boundary_condition(
database::RawDatabasePtr b1_data,
const specmicp::units::UnitsSet& tunits) {
ReactantBox box(b1_data, tunits);
box.set_solution(1.0, "L/L");
box.set_saturated_system();
box.set_inert_volume_fraction(0.0);
box.add_aqueous_species("NaCl", 0.1e-3, "mol/L");
box.add_aqueous_species("HNO3", 0.001e-3, "mol/L");
box.add_fixed_activity_component("H[+]", std::pow(10, -6.001));
box.set_charge_keeper("Cl[-]");
SmartAdimSolver solver(b1_data, box, false);
if (! solver.solve()) {
throw std::runtime_error("Cannot solve benchmark 1 boundary conditions");
}
return solver.get_solution();
}
mesh::Mesh1DPtr b1_mesh() {
mesh::Uniform1DMeshGeometry amesh;
amesh.dx = 0.01;
amesh.section = 1.0;
amesh.nb_nodes = 101;
return mesh::uniform_mesh1d(amesh);
}
void b1()
{
std::cerr.flush();
specmicp::logger::ErrFile::stream() = &std::cout;
specmicp::stdlog::ReportLevel() = specmicp::logger::Warning;
mesh::Mesh1DPtr amesh = b1_mesh();
auto tunits = units::SI_units;
tunits.length = units::LengthUnit::centimeter;
auto data = b1_database();
index_t i_na = data->get_id_component("Na[+]");
index_t i_cl = data->get_id_component("Cl[-]");
index_t i_h = data->get_id_component("H[+]");
index_t i_no = data->get_id_component("NO3[-]");
ChlorideVariablesInterface interface(data, amesh, tunits);
std::vector<AdimensionalSystemSolution> sols = {b1_initial_condition(data, tunits), b1_boundary_condition(data, tunits)};
std::vector<index_t> indices(101, 0);
indices[0] = 1;
interface.set_adim_solutions(indices, sols);
interface.set_diffusion_coefficient_component("H[+]", 9.31e-5);
interface.set_diffusion_coefficient_component("Na[+]", 1.33e-5);
interface.set_diffusion_coefficient_component("Cl[-]", 2.03e-5);
interface.set_diffusion_coefficient_component("NO3[-]", 1.90e-5);
interface.set_diffusion_coefficient_aqueous( "HO[-]", 5.27e-5);
//interface.set_diffusion_coefficient_aqueous( "NaOH", 1e-13);
interface.set_default_diffusion_resistance_factor(1.0);
interface.set_potential(0, 0.0);
auto variables = interface.get_variables();
std::shared_ptr<BoundaryConditions> bcs = BoundaryConditions::make(amesh, data);
bcs->fix_concentrations_node(0);
bcs->fix_potential_node(0);
ChlorideTransportStagger stagger(variables, bcs);
Vector scaling(5);
scaling << 1e-7, 1e-7, 1e-7, 1e-7, 1.0;
stagger.set_scaling(scaling);
stagger.initialize(variables.get());
stagger.set_approximation_method(AdimSolutionPerturbationMethod::component);
auto& opts = stagger.get_options();
opts.absolute_tolerance = 1e-12;
opts.residuals_tolerance = 1e-6;
opts.step_tolerance = 1e-14;
opts.quasi_newton = 1;
opts.maximum_step_length = 1e3;
opts.maximum_iterations = 500;
opts.alpha = 1;
index_t nb_iter = 1000;
scalar_t dt = 0.001*3600;
std::cout << "======\n" << variables->main_variables() << "\n=========\n" << std::endl;
for (int i=0; i<nb_iter; ++i) {
std::cout << "timestep : " << i << " - return code : ";
stagger.initialize_timestep(dt, variables.get());
auto retcode = stagger.restart_timestep(variables.get());
std::cout << static_cast<int>(retcode) << "\n";
if (retcode < reactmicp::solver::StaggerReturnCode::NotConvergedYet) {
throw std::runtime_error("Failed to solve iteration "+ std::to_string(i) +". Retcode : "+std::to_string(static_cast<int>(retcode)));
}
}
//std::cout << "-----\n" << variables->main_variables() << "\n-----\n" << std::endl;
//std::cout << variables->current() << std::endl;
std::cout << "# Na[+] (mol/L)\t" << "Cl[-] (mol/L)\t" << "H[+] (mol/L)\t" << "NO3[-] (mol/L)\t" << "HO[-] (mol/L)\t" << "Charge balance (mol/L)\t" << "Potential (V)\n";
for (index_t node: range(amesh->nb_nodes()))
{
AdimensionalSystemSolutionExtractor extr(variables->adim_solution(node), data, tunits);
auto rho_w = extr.density_water()*1000.;
auto cl = extr.molality_component(i_cl)*rho_w;
auto na = extr.molality_component(i_na)*rho_w;
auto h = extr.molality_component(i_h)*rho_w;
auto no = extr.molality_component(i_no)*rho_w;
auto ho = extr.molality_aqueous(data->get_id_aqueous("HO[-]"))*rho_w;
std::cout << amesh->get_position(node) << "\t"
<< na << "\t"
<< cl << "\t"
<< h << "\t"
<< no << "\t"
<< ho << "\t"
<< extr.charge_balance()*rho_w << "\t"
<< variables->main_variables()(variables->dof_potential(node)) << "\n";
}
std::cout << std::endl;
}
// ===========================
//
// Benchmark 2
//
// ===========================
const auto db_b2 = R"dbb2(
Metadata:
name: CEMDATA14
version: 2018-02-19 14:22:42 +0100
path: N/A
Elements:
- element: "O"
component: H2O
- element: "E"
component: E[-]
- element: "H"
component: H[+]
- element: "Cl"
component: Cl[-]
- element: "Na"
component: Na[+]
- element: "K"
component: K[+]
Basis:
- label: H2O
molar_mass: 0.018015
- label: E[-]
molar_mass: 0
- label: H[+]
molar_mass: 0.001008
activity:
a: 9
b: 0
- label: Cl[-]
molar_mass: 0.035453
activity:
a: 3.71
b: 0.01
- label: Na[+]
molar_mass: 0.02299
activity:
a: 4.32
b: 0.06
- label: K[+]
molar_mass: 0.039098
activity:
a: 3.71
b: 0
Aqueous:
- label: "HO[-]"
composition: "H2O, - H[+]"
log_k: 13.9995
activity:
a: 10.65
b: 0
Minerals:
[]
Gas:
[]
Sorbed:
[]
Compounds:
- label: "NaCl"
composition: "Cl[-], Na[+]"
- label: "NaOH"
composition: "H2O, - H[+], Na[+]"
- label: "KCl"
composition: "Cl[-], K[+]"
- label: "KOH"
composition: "H2O, - H[+], K[+]"
- label: "HCl"
composition: "H[+], Cl[-]"
)dbb2";
database::RawDatabasePtr b2_database() {
static database::RawDatabasePtr raw_data {nullptr};
if (raw_data == nullptr)
{
std::istringstream input_db(db_b2);
database::Database thedatabase;
thedatabase.parse_database(input_db);
raw_data = thedatabase.get_database();
raw_data->freeze_db();
}
return raw_data;
}
AdimensionalSystemSolution b2_left_boundary_condition(
database::RawDatabasePtr b2_data,
const specmicp::units::UnitsSet& tunits) {
ReactantBox box(b2_data, tunits);
box.set_solution(1.0, "L/L");
box.set_saturated_system();
box.set_inert_volume_fraction(0.0);
box.add_aqueous_species("NaCl", 0.5, "mmol/L");
box.add_aqueous_species("KCl", 1e-6, "mmol/L");
box.set_charge_keeper("Na[+]");
box.add_fixed_activity_component("H[+]", 1e-7);
SmartAdimSolver solver(b2_data, box, false);
if (! solver.solve()) {
throw std::runtime_error("Cannot solve benchmark 2 left boundary conditions");
}
return solver.get_solution();
}
AdimensionalSystemSolution b2_right_boundary_condition(
database::RawDatabasePtr b2_data,
const specmicp::units::UnitsSet& tunits) {
ReactantBox box(b2_data, tunits);
box.set_solution(1.0, "L/L");
box.set_saturated_system();
box.set_inert_volume_fraction(0.0);
box.add_aqueous_species("NaCl", 0.1, "mmol/L");
box.add_aqueous_species("KCl", 1e-6, "mmol/L");
box.set_charge_keeper("Na[+]");
box.add_fixed_activity_component("H[+]", 1e-7);
SmartAdimSolver solver(b2_data, box, false);
if (! solver.solve()) {
throw std::runtime_error("Cannot solve benchmark 2 right boundary conditions");
}
return solver.get_solution();
}
mesh::Mesh1DPtr b2_mesh() {
mesh::Uniform1DMeshGeometry amesh;
amesh.dx = 0.01;
amesh.section = 1.0;
amesh.nb_nodes = 101;
return mesh::uniform_mesh1d(amesh);
}
void b2()
{
std::cerr.flush();
specmicp::logger::ErrFile::stream() = &std::cout;
specmicp::stdlog::ReportLevel() = specmicp::logger::Warning;
mesh::Mesh1DPtr amesh = b2_mesh();
auto tunits = units::SI_units;
tunits.length = units::LengthUnit::centimeter;
tunits.quantity = units::QuantityUnit::millimoles;
auto data = b2_database();
index_t i_na = data->get_id_component("Na[+]");
index_t i_cl = data->get_id_component("Cl[-]");
index_t i_h = data->get_id_component("H[+]");
index_t i_k = data->get_id_component("K[+]"); // K[+] is used for ^22Na[+]
index_t i_ho = data->get_id_aqueous("HO[-]");
ChlorideVariablesInterface interface(data, amesh, tunits);
std::vector<AdimensionalSystemSolution> sols = {b2_left_boundary_condition(data, tunits), b2_right_boundary_condition(data, tunits)};
std::vector<index_t> indices(101, 0);
for (auto i=50; i<101; ++i) {
indices[i] =1;
}
interface.set_adim_solutions(indices, sols);
interface.set_diffusion_coefficient_component("H[+]", 9.31e-5);
interface.set_diffusion_coefficient_component("Na[+]", 1.33e-5);
interface.set_diffusion_coefficient_component("Cl[-]", 2.03e-5);
interface.set_diffusion_coefficient_component("K[+]", 1.33e-5);
interface.set_diffusion_coefficient_aqueous( "HO[-]", 5.27e-5);
//interface.set_diffusion_coefficient_aqueous( "NaOH", 1e-13);
interface.set_default_diffusion_resistance_factor(1.0);
interface.set_potential(0, 0.0);
auto variables = interface.get_variables();
std::shared_ptr<BoundaryConditions> bcs = BoundaryConditions::make(amesh, data);
bcs->fix_concentrations_node(0);
bcs->fix_potential_node(0);
bcs->fix_concentrations_node(100);
ChlorideTransportStagger stagger(variables, bcs);
Vector scaling(5);
scaling << 1e-7, 1e-7, 1e-7, 1e-7, 1.0;
stagger.set_scaling(scaling);
stagger.initialize(variables.get());
stagger.set_approximation_method(AdimSolutionPerturbationMethod::component);
auto& opts = stagger.get_options();
opts.absolute_tolerance = 1e-12;
opts.residuals_tolerance = 1e-6;
opts.step_tolerance = 1e-14;
opts.quasi_newton = 3;
opts.maximum_step_length = 1e3;
opts.maximum_iterations = 500;
opts.alpha = 1;
opts.sparse_solver = sparse_solvers::SparseSolver::SparseLU;
index_t nb_iter = 1500*24;
scalar_t dt = 3600.0;
std::cout << "======\n" << variables->main_variables() << "\n=========\n" << std::endl;
for (int i=0; i<nb_iter; ++i) {
std::cout << "timestep : " << i << " - return code : " ;
stagger.initialize_timestep(dt, variables.get());
auto retcode = stagger.restart_timestep(variables.get());
std::cout << static_cast<int>(retcode) << "\n";
if (retcode < reactmicp::solver::StaggerReturnCode::NotConvergedYet) {
throw std::runtime_error("Failed to solve iteration "+ std::to_string(i) +". Retcode : "+std::to_string(static_cast<int>(retcode)));
}
}
std::cout << "# Na[+] (mol/L)\t" << "Cl[-] (mol/L)\t" << "H[+] (mol/L)\t" << "22Na[+] (mol/L)\t" << "HO[-] (mol/L)\t" << "Charge balance (mol/L)\t" << "Potential (V)\n";
for (index_t node: range(amesh->nb_nodes()))
{
AdimensionalSystemSolutionExtractor extr(variables->adim_solution(node), data, tunits);
auto rho_w = extr.density_water();
auto cl = extr.molality_component(i_cl)*rho_w;
auto na = extr.molality_component(i_na)*rho_w;
auto h = extr.molality_component(i_h)*rho_w;
auto k = extr.molality_component(i_k)*rho_w;
auto ho = extr.molality_aqueous(i_ho)*rho_w;
std::cout << amesh->get_position(node) << "\t"
<< na << "\t"
<< cl << "\t"
<< h << "\t"
<< k << "\t"
<< ho << "\t"
<< extr.charge_balance() << "\t"
<< variables->main_variables()(variables->dof_potential(node)) << "\n";
}
std::cout << std::endl;
}
// ########################################################
const auto db_b3 = R"dbb3(
Metadata:
name: CEMDATA14
version: 2018-02-19 11:37:31 +0100
path: N/A
Elements:
- element: "O"
component: H2O
- element: "E"
component: E[-]
- element: "Cl"
component: Cl[-]
- element: "K"
component: K[+]
- element: "Mg"
component: Mg[2+]
Basis:
- label: H2O
molar_mass: 0.018015
- label: E[-]
molar_mass: 0
- label: Cl[-]
molar_mass: 0.035453
activity:
a: 3.71
b: 0.01
- label: K[+]
molar_mass: 0.039098
activity:
a: 3.71
b: 0
- label: Mg[2+]
molar_mass: 0.024305
activity:
a: 5.46
b: 0.22
Aqueous:
[]
Minerals:
[]
Gas:
[]
Sorbed:
[]
Compounds:
- label: "KCl"
composition: "Cl[-], K[+]"
- label: "MgCl2"
composition: "2 Cl[-], Mg[2+]"
)dbb3";
database::RawDatabasePtr b3_database() {
static database::RawDatabasePtr raw_data {nullptr};
if (raw_data == nullptr)
{
std::istringstream input_db(db_b3);
database::Database thedatabase;
thedatabase.parse_database(input_db);
raw_data = thedatabase.get_database();
raw_data->freeze_db();
}
return raw_data;
}
AdimensionalSystemSolution b3_initial_condition(
database::RawDatabasePtr b3_data,
const specmicp::units::UnitsSet& tunits) {
ReactantBox box(b3_data, tunits);
box.set_solution(1.0, "L/L");
box.set_saturated_system();
box.set_inert_volume_fraction(0.0);
box.add_aqueous_species("MgCl2", 1e-5, "mmol/L");
box.add_aqueous_species("KCl", 1e-5, "mmol/L");
box.set_charge_keeper("Cl[-]");
SmartAdimSolver solver(b3_data, box, false);
if (! solver.solve()) {
throw std::runtime_error("Cannot solve benchmark 3 initial condition");
}
return solver.get_solution();
}
AdimensionalSystemSolution b3_boundary_condition(
database::RawDatabasePtr b3_data,
const specmicp::units::UnitsSet& tunits) {
ReactantBox box(b3_data, tunits);
box.set_solution(1.0, "L/L");
box.set_saturated_system();
box.set_inert_volume_fraction(0.0);
box.add_aqueous_species("MgCl2", 0.29, "mmol/L");
box.add_aqueous_species("KCl", 0.29, "mmol/L");
box.set_charge_keeper("Cl[-]");
SmartAdimSolver solver(b3_data, box, false);
if (! solver.solve()) {
throw std::runtime_error("Cannot solve benchmark 3 boundary conditions");
}
return solver.get_solution();
}
AdimensionalSystemSolution b3_boundary_condition_bis(
database::RawDatabasePtr b3_data,
const specmicp::units::UnitsSet& tunits) {
ReactantBox box(b3_data, tunits);
box.set_solution(1.0, "L/L");
box.set_saturated_system();
box.set_inert_volume_fraction(0.0);
box.add_aqueous_species("MgCl2", 0.29/2, "mmol/L");
box.add_aqueous_species("KCl", 0.29/2, "mmol/L");
box.set_charge_keeper("Cl[-]");
SmartAdimSolver solver(b3_data, box, false);
if (! solver.solve()) {
throw std::runtime_error("Cannot solve benchmark 3 boundary conditions");
}
return solver.get_solution();
}
mesh::Mesh1DPtr b3_mesh() {
mesh::Uniform1DMeshGeometry amesh;
amesh.dx = 0.25;
amesh.section = 1.0;
amesh.nb_nodes = 49;
return mesh::uniform_mesh1d(amesh);
}
void b3()
{
std::cerr.flush();
specmicp::logger::ErrFile::stream() = &std::cout;
specmicp::stdlog::ReportLevel() = specmicp::logger::Warning;
mesh::Mesh1DPtr amesh = b3_mesh();
auto tunits = units::SI_units;
tunits.length = units::LengthUnit::centimeter;
tunits.quantity = units::QuantityUnit::moles;
auto data = b3_database();
index_t i_cl = data->get_id_component("Cl[-]");
index_t i_mg = data->get_id_component("Mg[2+]");
index_t i_k = data->get_id_component("K[+]");
ChlorideVariablesInterface interface(data, amesh, tunits);
std::vector<AdimensionalSystemSolution> sols = {b3_initial_condition(data, tunits), b3_boundary_condition(data, tunits), b3_boundary_condition_bis(data, tunits)};
std::vector<index_t> indices(49, 0);
indices[22] = 2;
indices[23] = 1;
indices[24] = 1;
indices[25] = 1;
indices[26] = 2;
interface.set_adim_solutions(indices, sols);
interface.set_diffusion_coefficient_component("K[+]", 2.405e-5);
interface.set_diffusion_coefficient_component("Mg[2+]", 1.745e-5);
interface.set_diffusion_coefficient_component("Cl[-]", 2.425e-5);
interface.set_default_diffusion_resistance_factor(1.0);
interface.set_potential(0, 0.0);
auto variables = interface.get_variables();
std::cout << variables->porosity(0) << " - " << variables->porosity(24) << std::endl;
std::shared_ptr<BoundaryConditions> bcs = BoundaryConditions::make(amesh, data);
bcs->fix_potential_node(24);
AdimensionalSystemSolutionExtractor extr(variables->adim_solution(24), data, tunits);
auto cl_0 = extr.molality_component(i_cl);
auto mg_0 = extr.molality_component(i_mg);
auto k_0 = extr.molality_component(i_k);
ChlorideTransportStagger stagger(variables, bcs);
Vector scaling(4);
scaling << 1e-7, 1e-7, 1e-7, 1.0;
stagger.set_scaling(scaling);
stagger.initialize(variables.get());
stagger.set_approximation_method(AdimSolutionPerturbationMethod::component);
auto& opts = stagger.get_options();
opts.absolute_tolerance = 1e-12;
opts.residuals_tolerance = 1e-6;
opts.step_tolerance = 1e-10;
opts.quasi_newton = 1;
opts.maximum_step_length = 1e3;
opts.maximum_iterations = 500;
opts.alpha = 1;
opts.sparse_solver = sparse_solvers::SparseSolver::SparseLU;
scalar_t dt = 0.001*3600;
index_t nb_iter = 16000;
std::cout << "======\n" << variables->main_variables() << "\n=========\n" << std::endl;
for (int i=0; i<nb_iter; ++i) {
std::cout << "timestep : " << i << " - return code : ";
stagger.initialize_timestep(dt, variables.get());
auto retcode = stagger.restart_timestep(variables.get());
std::cout << static_cast<int>(retcode) << "\n";
if (retcode < reactmicp::solver::StaggerReturnCode::NotConvergedYet) {
throw std::runtime_error("Failed to solve iteration "+ std::to_string(i) +". Retcode : "+std::to_string(static_cast<int>(retcode)));
}
}
//std::cout << "-----\n" << variables->main_variables() << "\n-----\n" << std::endl;
//std::cout << variables->current() << std::endl;
std::cout << "# Cl[-] (C/C_0)\t" << "Mg[2+] (C/C_0)\t" << "K[+] (C/C_0)\t" << "Charge balance (mol/L)\t" << "Potential (V)\n";
for (index_t node: range(amesh->nb_nodes()))
{
AdimensionalSystemSolutionExtractor extr(variables->adim_solution(node), data, tunits);
auto cl = extr.molality_component(i_cl);
auto mg = extr.molality_component(i_mg);
auto k = extr.molality_component(i_k);
std::cout << amesh->get_position(node) << "\t"
<< cl/cl_0 << "\t"
<< mg/mg_0 << "\t"
<< k/k_0 << "\t"
<< extr.charge_balance()*extr.density_water()*1000 << "\t"
<< variables->main_variables()(variables->dof_potential(node)) << "\n";
}
std::cout << std::endl;
}
// ########################################################
int main(int argc, char* argv[]) {
if (argc == 1) {
std::cout << "Usage: " << argv[0] << " <x>\n\n \t x: benchmark number (1,2,3)" << std::endl;
return EXIT_SUCCESS;
} else {
int case_number = std::stoi(argv[1]);
switch (case_number) {
case 1:
b1();
break;
case 2:
b2();
break;
case 3:
b3();
break;
default:
throw std::runtime_error(std::string("Unrecognized benchmark number ") + argv[1]);
}
}
return EXIT_SUCCESS;
}

Event Timeline