diff --git a/src/specmicp/reaction_path.cpp b/src/specmicp/reaction_path.cpp index 7f669cb..00c8a03 100644 --- a/src/specmicp/reaction_path.cpp +++ b/src/specmicp/reaction_path.cpp @@ -1,83 +1,82 @@ /*------------------------------------------------------- - Module : specmicp - File : reaction_path.cpp - Author : Fabien Georget Copyright (c) 2014, Fabien Georget, Princeton University ---------------------------------------------------------*/ #include "reaction_path.hpp" #include "thermodata.hpp" #include "micpsolver/micpsolver.hpp" #include "utils/log.hpp" #include <iostream> namespace specmicp { void ReactionPathDriver::read_database() { m_database.parse_database(m_model->database_path); m_database.make_canonical(); m_data = m_database.get_database(); } int ReactionPathDriver::label_to_id(const std::string& label, const std::vector<std::string>& list_labels) { auto it = std::find(list_labels.begin(), list_labels.end(), label); if (it == list_labels.end()) { throw std::invalid_argument("Unknow species : " + label); } return it - list_labels.begin(); } void ReactionPathDriver::dissolve_to_components() { m_tot_conc = Eigen::VectorXd(m_data->nb_component); m_tot_conc_increase = Eigen::VectorXd(m_data->nb_component); // everything is dissolved ... for (auto it=m_model->amount_components.begin(); it!=m_model->amount_components.end(); ++it) { const int id = label_to_id(it->first, m_data->labels_basis); m_tot_conc(id) = it->second.first; m_tot_conc_increase(id) = it->second.second; } std::vector<int> to_remove; to_remove.reserve(10); int new_i = 0; for (int i=0; i<m_data->nb_component; ++i) { if (m_tot_conc(i) == 0 and m_tot_conc_increase(i) == 0) { to_remove.push_back(0); continue; } m_tot_conc(new_i) = m_tot_conc(i); m_tot_conc_increase(new_i) = m_tot_conc_increase(i); ++new_i; } m_tot_conc.conservativeResize(new_i); m_tot_conc_increase.conservativeResize(new_i); - std::cout << m_tot_conc << std::endl; - std::cout << m_tot_conc_increase << std::endl; m_database.remove_components(to_remove); } micpsolver::MiCPPerformance ReactionPathDriver::one_step(Eigen::VectorXd& x) { - m_current_solver = ReducedSystemSolver (m_data, m_tot_conc, m_options); + m_current_solver = ReducedSystemSolver(m_data, m_tot_conc); + m_current_solver.get_options().solver_options = m_solver_options; micpsolver::MiCPPerformance perf = m_current_solver.solve(x); if (perf.return_code != micpsolver::MiCPSolverReturnCode::ResidualMinimized) { ERROR << "Failed to solve the system !"; } m_tot_conc += m_tot_conc_increase; return perf; } } // end namespace specmicp diff --git a/src/specmicp/reaction_path.hpp b/src/specmicp/reaction_path.hpp index a5cdfec..c78df8c 100644 --- a/src/specmicp/reaction_path.hpp +++ b/src/specmicp/reaction_path.hpp @@ -1,106 +1,106 @@ /*------------------------------------------------------- - Module : specmicp - File : reaction_path.hpp - Author : Fabien Georget Copyright (c) 2014, Fabien Georget, Princeton University ---------------------------------------------------------*/ #ifndef SPECMICP_SPECMICP_REACTIONPATH_HPP #define SPECMICP_SPECMICP_REACTIONPATH_HPP //! \file reaction_path.hpp reaction path driver #include <memory> #include <map> #include "database/database.hpp" #include "micpsolver/micpsolver_structs.hpp" #include "reduced_system_solver.hpp" namespace specmicp { //! \brief typedef to a reaction path amount //! //! The first element is the inital amount, //! The second element is the increase to add at every step using reaction_amount_t = std::pair<double, double>; //! \brief A reaction path model //! //! Contains every data we need to run a reaction path model struct ReactionPathModel { //! The amount of components std::map<std::string, reaction_amount_t> amount_components; //! The amount of aqueous species std::map<std::string, reaction_amount_t> amount_aqueous; //! The amount of minerals std::map<std::string, reaction_amount_t> amount_minerals; //! the number of step int nb_step; //! the path to the database - optional std::string database_path; }; //! \brief Driver to solve a reaction path model class ReactionPathDriver { public: //! \brief Initialise from a model //! //! Build a database from the attribute database_path of the model ReactionPathDriver(std::shared_ptr<ReactionPathModel> model): m_model(model) { read_database(); } //! \brief Initialise the driver from a model and a raw database ReactionPathDriver(std::shared_ptr<ReactionPathModel> model, std::shared_ptr<database::DataContainer> data): m_model(model), m_database(data), m_data(data) {} //! Initialize the database void read_database(); //! Dissolve everything into components void dissolve_to_components(); //! \brief Return the id of a species in 'list_labels' from its id int label_to_id(const std::string& label, const std::vector<std::string>& list_labels); //! \brief Perform one step micpsolver::MiCPPerformance one_step(Eigen::VectorXd& x); //! Set total aqueous concentrations void total_aqueous_concentration(const Eigen::VectorXd& x, Eigen::VectorXd& totaq) { m_current_solver.total_aqueous_concentration(x, totaq); } private: std::shared_ptr<ReactionPathModel> m_model; specmicp::database::Database m_database; std::shared_ptr<specmicp::database::DataContainer> m_data; Eigen::VectorXd m_tot_conc; Eigen::VectorXd m_tot_conc_increase; - micpsolver::MiCPSolverOptions m_options; + micpsolver::MiCPSolverOptions m_solver_options; ReducedSystemSolver m_current_solver; //std::shared_ptr<ThermoData> m_thermo; }; } // end namespace specmicp #endif // SPECMICP_SPECMICP_REACTIONPATH_HPP diff --git a/src/specmicp/reduced_system_solver.cpp b/src/specmicp/reduced_system_solver.cpp index dc2d03d..70e6828 100644 --- a/src/specmicp/reduced_system_solver.cpp +++ b/src/specmicp/reduced_system_solver.cpp @@ -1,122 +1,130 @@ /*------------------------------------------------------- - Module : specmicp - File : reduced_system_solver - Author : Fabien Georget Copyright (c) 2014, Fabien Georget, Princeton University ---------------------------------------------------------*/ #include "reduced_system_solver.hpp" #include "micpsolver/micpsolver.hpp" #include <iostream> namespace specmicp { -ReducedSystemSolver::ReducedSystemSolver( - std::shared_ptr<database::DataContainer> data, - Eigen::VectorXd& totconc, - micpsolver::MiCPSolverOptions options): +ReducedSystemSolver::ReducedSystemSolver(std::shared_ptr<database::DataContainer> data, + Eigen::VectorXd& totconc): m_data(data), m_system(std::make_shared<ReducedSystem>(std::make_shared<ThermoData>(data), totconc)), m_var(Eigen::VectorXd::Zero(data->nb_component+data->nb_mineral)), - m_options(options) + m_options() {} micpsolver::MiCPPerformance ReducedSystemSolver::solve(Eigen::VectorXd &x) { set_true_variable_vector(x); micpsolver::MiCPPerformance perf = solve(); set_return_vector(x); return perf; } void ReducedSystemSolver::set_true_variable_vector(const Eigen::VectorXd &x) { const std::vector<int>& non_active_component = m_system->get_non_active_component(); if (non_active_component.size() == 0) { m_var = x; for (int i=0; i<m_var.rows(); ++i) { if (m_var(i) == -HUGE_VAL) { m_var(i) = -6; } } } else { unsigned int new_i = 0; for (int i=0; i<m_data->nb_component; ++i) { auto it = std::find(non_active_component.begin(), non_active_component.end(),i); if (it != non_active_component.end()) continue; m_var(new_i) = x(i); ++new_i; } assert(new_i == m_data->nb_component - non_active_component.size()); for (int m=0; m<m_data->nb_mineral; ++m) { for (auto it=non_active_component.begin(); it!=non_active_component.end(); ++it) { if (m_data->nu_mineral(m, *it) != 0) continue; m_var(new_i) = x(m_data->nb_component+m); ++new_i; } } m_var.conservativeResize(new_i); } } micpsolver::MiCPPerformance ReducedSystemSolver::solve() { - micpsolver::MiCPSolver<ReducedSystem> solver(m_system); - solver.set_options(m_options); - solver.solve(m_var); - return solver.get_performance(); + if (get_options().ncp_function == micpsolver::NCPfunction::penalizedFB) + { + micpsolver::MiCPSolver<ReducedSystem,micpsolver::NCPfunction::penalizedFB> solver(m_system); + solver.set_options(get_options().solver_options); + solver.solve(m_var); + return solver.get_performance(); + } + else + { + micpsolver::MiCPSolver<ReducedSystem,micpsolver::NCPfunction::min> solver(m_system); + solver.set_options(get_options().solver_options); + solver.solve(m_var); + return solver.get_performance(); + } } void ReducedSystemSolver::set_return_vector(Eigen::VectorXd &x) { const std::vector<int>& non_active_component = m_system->get_non_active_component(); if (non_active_component.size() == 0) { x = m_var; } else { unsigned int new_i = 0; for (int i=0; i<m_data->nb_component; ++i) { auto it = std::find(non_active_component.begin(), non_active_component.end(),i); if (it != non_active_component.end()) { x(i) = -HUGE_VAL; // FIXME continue; } x(i) = m_var(new_i) ; ++new_i; } assert(new_i == m_data->nb_component - non_active_component.size()); for (int m=0; m<m_data->nb_mineral; ++m) { for (auto it=non_active_component.begin(); it!=non_active_component.end(); ++it) { if (m_data->nu_mineral(m, *it) != 0) { x(m_data->nb_component+m) = 0; continue; } x(m_data->nb_component+m) =m_var(new_i); ++new_i; } } } } } // end namespace specmicp diff --git a/src/specmicp/reduced_system_solver.hpp b/src/specmicp/reduced_system_solver.hpp index 7f49f25..593af28 100644 --- a/src/specmicp/reduced_system_solver.hpp +++ b/src/specmicp/reduced_system_solver.hpp @@ -1,76 +1,88 @@ /*------------------------------------------------------- - Module : specmicp - File : reduced_system_solver.hpp - Author : Fabien Georget Copyright (c) 2014, Fabien Georget, Princeton University ---------------------------------------------------------*/ #ifndef SPECMICP_SPECMICP_REDUCEDSYSTEMSOLVER_HPP #define SPECMICP_SPECMICP_REDUCEDSYSTEMSOLVER_HPP #include "database/data_container.hpp" #include "reduced_system.hpp" #include "micpsolver/micpsolver_structs.hpp" //! \file reduced_system_solver.hpp Solve a reduced system namespace specmicp { +struct ReducedSystemSolverOptions +{ + micpsolver::NCPfunction ncp_function; + micpsolver::MiCPSolverOptions solver_options; + + ReducedSystemSolverOptions(): + ncp_function(micpsolver::NCPfunction::penalizedFB), + solver_options() + {} +}; //! \brief Solver a reduced system //! //! Take care of possibly non-existing component in the system class ReducedSystemSolver { public: //! Default constructor - you need to use another method to initialize it correctly ReducedSystemSolver() {} ReducedSystemSolver(std::shared_ptr<database::DataContainer> data, - Eigen::VectorXd& totconc, - micpsolver::MiCPSolverOptions options=micpsolver::MiCPSolverOptions()); + Eigen::VectorXd& totconc); //! \brief solve the problem using initial guess x //! //! @param[in,out] x, in -> initial guess, out -> solution micpsolver::MiCPPerformance solve(Eigen::VectorXd& x); //! Return the system used for the computation std::shared_ptr<ReducedSystem> get_system() {return m_system;} //! Set total aqueous concentrations void total_aqueous_concentration(const Eigen::VectorXd& x, Eigen::VectorXd& totaq) { m_system->aqueous_tot_conc(x, totaq); } + const ReducedSystemSolverOptions& get_options() const {return m_options;} + ReducedSystemSolverOptions& get_options() {return m_options;} + private: //! \brief set up the true variable vector void set_true_variable_vector(const Eigen::VectorXd& x); //! \brief set up the true solution vector //! //! add zero components void set_return_vector(Eigen::VectorXd& x); //! \brief solve the problem micpsolver::MiCPPerformance solve(); + ReducedSystemSolverOptions m_options; std::shared_ptr<database::DataContainer> m_data; std::shared_ptr<ReducedSystem> m_system; Eigen::VectorXd m_var; - micpsolver::MiCPSolverOptions m_options; }; inline micpsolver::MiCPPerformance solve_reduced_system(std::shared_ptr<database::DataContainer> data, Eigen::VectorXd& totconc, Eigen::VectorXd& x) { return ReducedSystemSolver(data, totconc).solve(x); } } // end namespace specmicp #endif // SPECMICP_SPECMICP_REDUCEDSYSTEMSOLVER_HPP diff --git a/tests/specmicp/thermocarbo.cpp b/tests/specmicp/thermocarbo.cpp index 5a95507..2d7f446 100644 --- a/tests/specmicp/thermocarbo.cpp +++ b/tests/specmicp/thermocarbo.cpp @@ -1,469 +1,533 @@ #include <iostream> #include "specmicp/extended_system.hpp" #include "specmicp/reduced_system.hpp" #include "micpsolver/micpsolver.hpp" #include "specmicp/reduced_system_solver.hpp" #include "database/database.hpp" #include "specmicp/reaction_path.hpp" std::shared_ptr<specmicp::ThermoData> set_thermodata_from_database() { specmicp::database::Database database("data/cemdata_specmicp.js"); std::shared_ptr<specmicp::database::DataContainer> data = database.get_database(); //std::cout << data->nu_aqueous << std::endl; //std::cout << data->nu_mineral << std::endl; database.change_basis(std::vector<int>({0, 5, 2, 3, 8})); //std::cout << data->nu_aqueous << std::endl; //std::cout << data->nu_mineral << std::endl; std::cout << "Basis : " << std::endl; for (auto it = data->labels_basis.begin(); it!=data->labels_basis.end(); ++it) { std::cout << *it << "\t" << data->param_aq.row(it - data->labels_basis.begin()) << std::endl; } std::cout << std::endl; std::cout << "Aqueous : \n"; for (auto it = data->labels_aqueous.begin(); it!=data->labels_aqueous.end(); ++it) { const int j = it - data->labels_aqueous.begin(); std::cout << *it << "\t\t" << data->nu_aqueous.row(j) << "\t" << data->logk_aqueous(j) << "\t" << data->param_aq.row(j+data->nb_component) << std::endl; } std::cout << "Minerals : \n"; for (auto it = data->labels_minerals.begin(); it!=data->labels_minerals.end(); ++it) { const int j = it - data->labels_minerals.begin(); std::cout << *it << "\t\t" << data->nu_mineral.row(j) << "\t" << data->logk_mineral(j) << std::endl; } std::cout << std::endl; std::shared_ptr<specmicp::ThermoData> ptr = std::make_shared<specmicp::ThermoData>(data); return ptr; } //std::shared_ptr<specmicp::ThermoData> set_thermodata() //{ // int nmin = 5; // Eigen::MatrixXd nu(10+nmin, 5); // nu << 1, 0, -1, 0, 0, // 1, 0, -1, 1, 0, // -1, 0, 1, 1, 0, // 0, 1, 1, 0, 0, // -1, 0, 1, 0, 1, // 0, 0, -1, 0, 1, // -1, 1, 1, 0, 1, // 0, 1, 0, 0, 1, // 0, 1, 0, 1, 0, // -1, 1, 1, 1, 0, // // minerals // 0, 1, 2, 0, 0, // -1, 0, -1, 1, 0, // -0.5567, 1.6667, 2.3333, 1, 0, // -0.5, 0.8333, 0.6667, 1, 0, // -1, 1, 1, 0, 1 // ; // Eigen::VectorXd logkr(10+nmin); // logkr << 13.9995, 4.8595, 0.1005, -1.2195, // -3.6706, 7.6476, -6.8947, -1.1057, // -1.2, -4.4995, // // minerals // -5.1995, // 1.476, // -13.17, // -8.0, // -12.1505; // Eigen::MatrixXd param_aqueous(Eigen::MatrixXd::Zero(5+10,3)); // param_aqueous << 0, 0.0 , 0.0 , // H2O // 2, 4.86, 0.15, // Ca+2 // -1, 10.65, 0.0 , // HO- // -1, 4.0 , 0.0 , // SiO(HO)3- // -1, 5.40, 0.0 , // HCO3- // 1, 9.0 , 0.0 , // H+ // 0, 0.0 , 0.1 , // Si(OH)4 // -2, 4.0 , 0.0 , // SiO2(OH)-2 // 1, 4.0 , 0.0 , // CaOH+ // -2, 5.40, 0.0 , // CO3-2 // 0, 0.0 , 0.1 , // CO2(aq) // 0, 0.0 , 0.1 , // CaCO3(aq) // 1, 4.0 , 0.0 , // CaHCO3+ // 1, 4.0 , 0.0 , // CaSiO(HO)3+ // 0, 0.0 , 0.1 // CaSiO2(HO)2(aq) // ; // std::shared_ptr<specmicp::ThermoData> ptr = std::make_shared<specmicp::ThermoData>(10, nmin, nu, logkr, param_aqueous); // return ptr; //} //std::shared_ptr<specmicp::ThermoData> set_thermodata_aluminum() //{ // Eigen::MatrixXd nu(5, 3); // nu << 1, 1, -1, // 2, 1, -2, // 3, 1, -3, // 4, 1, -4, // 1, 0, -1 // ; // Eigen::VectorXd logkr(5); // logkr << 5.0, 10.1, 16.9, 22.7, 14.0; // Eigen::MatrixXd paramaq(Eigen::MatrixXd::Zero(5+3,3)); // ideal case // std::shared_ptr<specmicp::ThermoData> ptr = std::make_shared<specmicp::ThermoData>(5, 0, nu, logkr, paramaq); // return ptr; //} //void solve_aluminium() //{ // std::shared_ptr<specmicp::ThermoData> thermoptr = set_thermodata_aluminum(); // Eigen::VectorXd totconc(3); // totconc << 1.0/specmicp::molar_mass_water, 1e-6, -3e-6; // //totconc << 1e-6, -3e-6; // std::shared_ptr<specmicp::SpecProg> prog = std::make_shared<specmicp::SpecProg>(thermoptr, totconc, true); // specmicp::micpsolver::MiCPSolver<specmicp::SpecProg> solver(prog); // //solver.get_options().fvectol = 1e-6; // solver.get_options().maxstep = 20.0; // solver.get_options().maxiter_maxstep = 100; // //solver.get_options().factor_descent_condition = -1e-6; // Eigen::VectorXd x(prog->total_variables()); // //x.setConstant(-1); // x(0) = 1.0; // x(1) = -9; // x(2) = -13; // prog->init_secondary_conc(x); // std::cout << x << std::endl; //// Eigen::VectorXd residual(20); //// prog->get_residuals(x, residual); //// std::cout << "Residual \n ------ \n" << residual << std::endl; //// Eigen::MatrixXd jacob(20, 20); //// prog->get_jacobian(x, jacob); //// std::cout << "Jacobian \n ------ \n" << jacob << std::endl; // std::cout << "Return Code : " << (int) solver.solve(x) << std::endl; // std::cout << "Solution \n -------- \n" << x << std::endl; //} specmicp::micpsolver::MiCPPerformance solve_one( std::shared_ptr<specmicp::ThermoData> thermoptr, const Eigen::VectorXd& totconc, Eigen::VectorXd& x, Eigen::VectorXd& totaq) { x(15) = std::max(0.0, x(15)-1.0); x(16) = std::max(0.0, x(16)-1.0); x(17) = std::max(0.0, x(17)-1.0); x(18) = std::max(0.0, x(18)-1.0); x(19) = std::max(0.0, x(19)-1.0); std::shared_ptr<specmicp::SpecProg> prog = std::make_shared<specmicp::SpecProg>(thermoptr, totconc); prog->init_secondary_conc(x); - specmicp::micpsolver::MiCPSolver<specmicp::SpecProg> solver(prog); + specmicp::micpsolver::MiCPSolver<specmicp::SpecProg, specmicp::micpsolver::NCPfunction::penalizedFB> solver(prog); //solver.get_options().fvectol = 1e-6; solver.get_options().maxstep = 200.0; solver.get_options().maxiter_maxstep = 100; solver.get_options().use_crashing = false; solver.get_options().use_scaling = false; solver.get_options().projection_min_variable = 1e-6; solver.solve(x); prog->aqueous_tot_conc(x, totaq); return solver.get_performance(); } void solve_lot() { specmicp::stdlog::ReportLevel() = specmicp::logger::Warning; Eigen::VectorXd x(20); x(0) = 10.0; x(1) = -2.0; x(2) = -2.0; x(3) = -2.0; x(4) = -2.0; x(15) = 0.0; x(16) = 0.0; x(17) = 0.0; x(18) = 0.0; x(19) = 0.0; //x.setConstant(-1); //prog->init_secondary_conc(x); Eigen::VectorXd totaq(5); double m_c3s = 0.70; double m_c2s = 0.3; double m_h2co3 = 0.0; double totiter = 0; double totfact = 0; std::shared_ptr<specmicp::ThermoData> thermoptr = set_thermodata_from_database(); std::cout << "Reaction_path return_code nb_iter pH H2O HO C Ca Si " << " Portlandite SiO2(am) Jennite Tobermorite Calcite" << std::endl; for (int i=0; i<40; ++i) { m_h2co3 = 0.1*(1+i); Eigen::VectorXd totconc(5); totconc << 1/specmicp::molar_mass_water - 4*m_c3s - 3*m_c2s + m_h2co3, 5*m_c3s + 3*m_c2s-m_h2co3, m_h2co3, 3*m_c3s +2*m_c2s, m_c3s + m_c2s; specmicp::micpsolver::MiCPPerformance perf = solve_one(thermoptr, totconc, x, totaq); std::cout << m_h2co3 << " " << (int) perf.return_code << " " << perf.nb_iterations << " " << 14+x(1) << " " << x(0) << " " << totaq.block(1,0,4,1).transpose() << " " << x.block(15, 0, 5, 1).transpose() << std::endl; totiter += perf.nb_iterations; totfact += perf.nb_factorization; } std::cout << "Average iterations : " << totiter/40 << std::endl; std::cout << "Average factorization : " << totfact/40 << std::endl; } specmicp::micpsolver::MiCPPerformance solve_one_reduced( std::shared_ptr<specmicp::database::DataContainer> data, Eigen::VectorXd& totconc, Eigen::VectorXd& x, Eigen::VectorXd& totaq) { x(5) = std::max(0.0, x(5)-1.0); x(6) = std::max(0.0, x(6)-1.0); x(7) = std::max(0.0, x(7)-1.0); x(8) = std::max(0.0, x(8)-1.0); x(9) = std::max(0.0, x(9)-1.0); specmicp::micpsolver::MiCPSolverOptions options; options.maxstep = 100.0; options.maxiter_maxstep = 100; options.use_crashing = false; options.use_scaling = true; options.projection_min_variable = 1e-6; - specmicp::ReducedSystemSolver solver(data, totconc, options); + specmicp::ReducedSystemSolver solver(data, totconc); + solver.get_options().solver_options = options; specmicp::micpsolver::MiCPPerformance perf = solver.solve(x); solver.total_aqueous_concentration(x, totaq); return perf; } void solve_lot_reduced() { specmicp::stdlog::ReportLevel() = specmicp::logger::Warning; Eigen::VectorXd x(10); x(0) = 1.0; x(1) = -2.0; x(2) = -2.0; x(3) = -2.0; x(4) = -2.0; x(5) = 0.0; x(6) = 0.0; x(7) = 0.0; x(8) = 0.0; x(9) = 0.0; //x.setConstant(-1); //prog->init_secondary_conc(x); Eigen::VectorXd totaq(5); double m_c3s = 0.70; double m_c2s = 0.3; double m_h2co3 = 0.0; double totiter = 0; double totfact = 0; std::shared_ptr<specmicp::ThermoData> thermoptr = set_thermodata_from_database(); Eigen::VectorXd totconc(5); totconc << 1/specmicp::molar_mass_water - 4*m_c3s - 3*m_c2s + m_h2co3, 5*m_c3s + 3*m_c2s-m_h2co3, m_h2co3, 3*m_c3s +2*m_c2s, m_c3s + m_c2s; std::cout << "Reaction_path return_code nb_iter pH H2O HO C Ca Si " << " Portlandite SiO2(am) Jennite Tobermorite Calcite" << std::endl; for (int i=0; i<41; ++i) { m_h2co3 = 0.1*(i); totconc << 1/specmicp::molar_mass_water - 4*m_c3s - 3*m_c2s + m_h2co3, 5*m_c3s + 3*m_c2s-m_h2co3, m_h2co3, 3*m_c3s +2*m_c2s, m_c3s + m_c2s; specmicp::micpsolver::MiCPPerformance perf = solve_one_reduced(thermoptr->get_raw_database(), totconc, x, totaq); //std::cout << x << std::endl; std::cout << m_h2co3 << " " << (int) perf.return_code << " " << perf.nb_iterations << " " << 14+x(1) << " " << x(0) << " " << totaq.block(1,0,4,1).transpose() << " " << x.block(5, 0, 5, 1).transpose() << std::endl; totiter += perf.nb_iterations; totfact += perf.nb_factorization; } std::cout << "Average iterations : " << totiter/41 << std::endl; std::cout << "Average factorization : " << totfact/41 << std::endl; } void solve_lot_reaction_path() { specmicp::stdlog::ReportLevel() = specmicp::logger::Warning; Eigen::VectorXd x(10); x(0) = 1.0; x(1) = -2.0; x(2) = -2.0; x(3) = -2.0; x(4) = -2.0; x(5) = 0.0; x(6) = 0.0; x(7) = 0.0; x(8) = 0.0; x(9) = 0.0; specmicp::database::Database database("data/cemdata_specmicp.js"); std::shared_ptr<specmicp::database::DataContainer> data = database.get_database(); database.change_basis(std::vector<int>({0, 5, 2, 3, 8})); std::shared_ptr<specmicp::ReactionPathModel> model = std::make_shared<specmicp::ReactionPathModel>(); double m_c3s = 0.70; double m_c2s = 0.3; double delta_h2co3 = 0.1; model->amount_components = { {"H2O", specmicp::reaction_amount_t(1/specmicp::molar_mass_water- 4*m_c3s - 3*m_c2s, delta_h2co3)}, {"HCO3[-]", specmicp::reaction_amount_t(0, delta_h2co3)}, {"Ca[2+]", specmicp::reaction_amount_t(3*m_c3s +2*m_c2s, 0)}, {"HO[-]", specmicp::reaction_amount_t(5*m_c3s + 3*m_c2s, -delta_h2co3)}, {"SiO(OH)3[-]", specmicp::reaction_amount_t(m_c3s + m_c2s, 0)} }; model->database_path = "data/cemdata_specmicp.js"; Eigen::VectorXd totaq(5); double totiter = 0; double totfact = 0; specmicp::ReactionPathDriver driver(model, data); driver.dissolve_to_components(); std::cout << "Reaction_path return_code nb_iter pH H2O HO C Ca Si " << " Portlandite SiO2(am) Jennite Tobermorite Calcite" << std::endl; for (int i=0; i<41; ++i) { + x(0) = 1.0; + x(1) = -2.0; + x(2) = -2.0; + x(3) = -2.0; + x(4) = -2.0; + x(5) = 0.0; + x(6) = 0.0; + x(7) = 0.0; + x(8) = 0.0; + x(9) = 0.0; specmicp::micpsolver::MiCPPerformance perf = driver.one_step(x); driver.total_aqueous_concentration(x, totaq); std::cout << i*(0.1) << " " << (int) perf.return_code << " " << perf.nb_iterations << " " << 14+x(1) << " " << x(0) << " " << totaq.block(1,0,4,1).transpose() << " " << x.block(5, 0, 5, 1).transpose() << std::endl; totiter += perf.nb_iterations; totfact += perf.nb_factorization; } std::cout << "Average iterations : " << totiter/41 << std::endl; std::cout << "Average factorization : " << totfact/41 << std::endl; } void solve() { specmicp::stdlog::ReportLevel() = specmicp::logger::Debug; std::shared_ptr<specmicp::ThermoData> thermoptr = set_thermodata_from_database(); Eigen::VectorXd totconc(5); double m_c3s = 0.70; double m_c2s = 0.3; double m_h2co3 = 1.9; totconc << 1/specmicp::molar_mass_water - 4*m_c3s - 3*m_c2s + m_h2co3, 5*m_c3s + 3*m_c2s-m_h2co3, m_h2co3, 3*m_c3s +2*m_c2s, m_c3s + m_c2s; std::shared_ptr<specmicp::SpecProg> prog = std::make_shared<specmicp::SpecProg>(thermoptr, totconc); - specmicp::micpsolver::MiCPSolver<specmicp::SpecProg> solver(prog); + specmicp::micpsolver::MiCPSolver<specmicp::SpecProg, specmicp::micpsolver::NCPfunction::penalizedFB> solver(prog); //solver.get_options().fvectol = 1e-6; solver.get_options().max_iter = 100; solver.get_options().maxstep = 200.0; solver.get_options().maxiter_maxstep = 100; solver.get_options().factor_descent_condition = 1e-4; solver.get_options().use_crashing = 0; Eigen::VectorXd x(prog->total_variables()); //x.setConstant(-1); x(0) = 1.0; x(1) = -2.0; x(2) = -2.0; x(3) = -2.0; x(4) = -2.0; x(15) = 0.0; x(16) = 0.0; x(17) = 0.0; x(18) = 0.0; x(19) = 0.0; prog->init_secondary_conc(x); std::cout << x << std::endl; // Eigen::VectorXd residual(20); // prog->get_residuals(x, residual); // std::cout << "Residual \n ------ \n" << residual << std::endl; // Eigen::MatrixXd jacob(20, 20); // prog->get_jacobian(x, jacob); // std::cout << "Jacobian \n ------ \n" << jacob << std::endl; std::cout << "Return Code : " << (int) solver.solve(x) << std::endl; std::cout << "Solution \n -------- \n" << x << std::endl; } void solve_reduced() { specmicp::stdlog::ReportLevel() = specmicp::logger::Debug; std::shared_ptr<specmicp::ThermoData> thermoptr = set_thermodata_from_database(); Eigen::VectorXd totconc(5); double m_c3s = 0.70; double m_c2s = 0.3; double m_h2co3 = 2.8; totconc << 1/specmicp::molar_mass_water - 4*m_c3s - 3*m_c2s + m_h2co3, 5*m_c3s + 3*m_c2s-m_h2co3, m_h2co3, 3*m_c3s +2*m_c2s, m_c3s + m_c2s; std::shared_ptr<specmicp::ReducedSystem> prog = std::make_shared<specmicp::ReducedSystem>(thermoptr, totconc); - specmicp::micpsolver::MiCPSolver<specmicp::ReducedSystem> solver(prog); + specmicp::micpsolver::MiCPSolver<specmicp::ReducedSystem, specmicp::micpsolver::NCPfunction::penalizedFB> solver(prog); //solver.get_options().fvectol = 1e-6; solver.get_options().max_iter = 100; solver.get_options().maxstep = 200; solver.get_options().maxiter_maxstep = 100; solver.get_options().factor_descent_condition = 1e-4; solver.get_options().use_crashing = false; solver.get_options().use_scaling = true; Eigen::VectorXd x(prog->total_variables()); //x.setConstant(-1); x(0) = 1.0485; x(1) = -5.01517; x(2) = -3.52536; x(3) = -3.50741; x(4) = -3.5383; x(5) = 0.0; x(6) = 0.997242; x(7) = 0.0; x(8) = 0.0; x(9) = 2.69967; std::cout << x << std::endl; // Eigen::VectorXd residual(20); // prog->get_residuals(x, residual); // std::cout << "Residual \n ------ \n" << residual << std::endl; // Eigen::MatrixXd jacob(20, 20); // prog->get_jacobian(x, jacob); // std::cout << "Jacobian \n ------ \n" << jacob << std::endl; std::cout << "Return Code : " << (int) solver.solve(x) << std::endl; std::cout << "Solution \n -------- \n" << x << std::endl; } + +void solve_reduced_min() +{ + + specmicp::stdlog::ReportLevel() = specmicp::logger::Debug; + std::shared_ptr<specmicp::ThermoData> thermoptr = set_thermodata_from_database(); + Eigen::VectorXd totconc(5); + double m_c3s = 0.70; + double m_c2s = 0.3; + double m_h2co3 = 2.8; + totconc << 1/specmicp::molar_mass_water - 4*m_c3s - 3*m_c2s + m_h2co3, + 5*m_c3s + 3*m_c2s-m_h2co3, + m_h2co3, + 3*m_c3s +2*m_c2s, + m_c3s + m_c2s; + std::shared_ptr<specmicp::ReducedSystem> prog = std::make_shared<specmicp::ReducedSystem>(thermoptr, totconc); + specmicp::micpsolver::MiCPSolver<specmicp::ReducedSystem, specmicp::micpsolver::NCPfunction::min> solver(prog); + //solver.get_options().fvectol = 1e-6; + solver.get_options().max_iter = 100; + solver.get_options().maxstep = 200; + solver.get_options().maxiter_maxstep = 100; + solver.get_options().factor_descent_condition = 1e-4; + solver.get_options().use_crashing = false; + solver.get_options().use_scaling = true; + Eigen::VectorXd x(prog->total_variables()); + //x.setConstant(-1); + x(0) = 1.0; + x(1) = -2; + x(2) = -2; + x(3) = -2; + x(4) = -2; + x(5) = 0.0; + x(6) = 0.0; + x(7) = 0.0; + x(8) = 0.0; + x(9) = 0.0; + + std::cout << x << std::endl; + +// Eigen::VectorXd residual(20); +// prog->get_residuals(x, residual); +// std::cout << "Residual \n ------ \n" << residual << std::endl; +// Eigen::MatrixXd jacob(20, 20); +// prog->get_jacobian(x, jacob); +// std::cout << "Jacobian \n ------ \n" << jacob << std::endl; + + std::cout << "Return Code : " << (int) solver.solve(x) << std::endl; + + + std::cout << "Solution \n -------- \n" << x << std::endl; +} + int main() { specmicp::logger::ErrFile::stream() = &std::cerr; //set_thermodata_from_database(); //solve(); //solve_lot(); //solve_reduced(); + //solve_reduced_min(); //solve_lot_reduced(); //solve_aluminium(); solve_lot_reaction_path(); }