diff --git a/examples/reactmicp/saturated_react/carbonation.cpp b/examples/reactmicp/saturated_react/carbonation.cpp
index 57de2f4..af2a98c 100644
--- a/examples/reactmicp/saturated_react/carbonation.cpp
+++ b/examples/reactmicp/saturated_react/carbonation.cpp
@@ -1,599 +1,678 @@
 #include <Eigen/Core>
 #include <Eigen/QR>
 
 #include "specmicp/adimensional/adimensional_system_solver.hpp"
 #include "specmicp/problem_solver/formulation.hpp"
 #include "specmicp/problem_solver/dissolver.hpp"
 #include "specmicp/adimensional/adimensional_system_solution_extractor.hpp"
 
 #include "reactmicp/systems/saturated_react/variables.hpp"
 #include "reactmicp/systems/saturated_react/equilibrium_stagger.hpp"
 #include "reactmicp/systems/saturated_react/transport_stagger.hpp"
 #include "reactmicp/systems/saturated_react/init_variables.hpp"
 
 #include "reactmicp/solver/reactive_transport_solver.hpp"
 #include "reactmicp/solver/reactive_transport_solver_structs.hpp"
 #include "reactmicp/solver/staggers_base/upscaling_stagger_base.hpp"
 #include "reactmicp/solver/staggers_base/stagger_structs.hpp"
 #include "reactmicp/solver/timestepper.hpp"
 
 
 #include "physics/laws.hpp"
 
 #include "dfpm/mesh.hpp"
 
 #include "utils/log.hpp"
 #include "utils/timer.hpp"
 
 #include "utils/io/reactive_transport.hpp"
 
 #include <iostream>
 #include <fstream>
 
 using namespace specmicp;
 using namespace reactmicp;
 using namespace reactmicp::systems;
 
 using namespace specmicp::reactmicp::systems::satdiff;
 using namespace reactmicp::solver;
 
 AdimensionalSystemSolution get_cement_initial_compo(
         RawDatabasePtr the_database,
         const AdimensionalSystemConstraints& constraints,
         const AdimensionalSystemSolverOptions& options
         );
 
 AdimensionalSystemConstraints get_cement_initial_constraints(
         RawDatabasePtr the_database,
         const units::UnitsSet& units_set);
 
 AdimensionalSystemSolution get_bc_initial_compo(
         RawDatabasePtr the_database,
         const AdimensionalSystemConstraints& constraints,
         const AdimensionalSystemSolverOptions& options
         );
 
 
 AdimensionalSystemConstraints get_bc_initial_constraints(
         RawDatabasePtr the_database,
         const units::UnitsSet& units_set);
 
 RawDatabasePtr get_database(const std::string& path_to_database);
 
 Vector initial_compo(const Vector& publi);
 
 AdimensionalSystemSolverOptions get_specmicp_options();
 
 mesh::Mesh1DPtr get_mesh(scalar_t dx);
+mesh::Mesh1DPtr get_mesh();
+
+void output_mesh(mesh::Mesh1DPtr the_mesh);
 
 void set_transport_options(dfpmsolver::ParabolicDriverOptions& transport_options);
 
 void set_reactive_solver_options(reactmicp::solver::ReactiveTransportOptions& reactive_options);
 
 void print_minerals_profile(
         RawDatabasePtr the_database,
         SaturatedVariablesPtr variables,
         mesh::Mesh1DPtr the_mesh,
         const std::string& filepath
         );
 
 class CarboUspcaling: public solver::UpscalingStaggerBase
 {
 public:
 
     static constexpr scalar_t de_0 = 1e-11;
     static constexpr scalar_t factor = 1e4;
     static constexpr scalar_t porosity_r = 0.02;
 
     CarboUspcaling(RawDatabasePtr the_database,
                       units::UnitsSet the_units):
         m_data(the_database),
         m_units_set(the_units),
         m_dt(HUGE_VAL)
     {
 
     }
 
     //! \brief Initialize the stagger at the beginning of the computation
     void initialize(VariablesBasePtr var)
     {
         SaturatedVariablesPtr true_var = cast_var_from_base(var);
         true_var->upscaling_variables().setZero();
         for (index_t node=0; node<true_var->nb_nodes(); ++node)
         {
             upscaling_one_node(node, true_var);
         }
 
 
     }
 
     //! \brief Initialize the stagger at the beginning of an iteration
     void initialize_timestep(scalar_t dt, VariablesBasePtr var)
     {
         SaturatedVariablesPtr true_var = cast_var_from_base(var);
         m_dt = dt;
 
         for (index_t node=1; node<true_var->nb_nodes(); ++node)
         {
             upscaling_one_node(node, true_var);
             true_var->vel_porosity(node) = 0.0;
         }
     }
 
     //! \brief Solve the equation for the timestep
     StaggerReturnCode restart_timestep(VariablesBasePtr var)
     {
         SaturatedVariablesPtr true_var = cast_var_from_base(var);
         for (index_t node=1; node<true_var->nb_nodes(); ++node)
         {
             upscaling_one_node(node, true_var);
         }
         return StaggerReturnCode::ResidualMinimized;
     }
 
     scalar_t coeff_diffusion_law(scalar_t porosity)
     {
-        return factor*de_0*((porosity - porosity_r)/(0.4 - porosity_r));
+        if (porosity > 0.7)
+            return factor*4.0*1e-10;
+        else
+        {
+            const scalar_t ratio = ((porosity - porosity_r)/(0.4 - porosity_r));
+            return factor*de_0*std::pow(ratio, 3.32);
+        }
     }
 
     void upscaling_one_node(index_t node, SaturatedVariablesPtr true_var)
     {
         AdimensionalSystemSolutionExtractor extractor(true_var->equilibrium_solution(node),
                                                       m_data, m_units_set);
 
         scalar_t porosity = extractor.porosity();
         true_var->vel_porosity(node) += (porosity - true_var->porosity(node))/m_dt;
         true_var->porosity(node) = porosity;
 
         true_var->diffusion_coefficient(node) = coeff_diffusion_law(porosity);
     }
 
 private:
     RawDatabasePtr m_data;
     units::UnitsSet m_units_set;
     index_t m_id_cshj;
     scalar_t m_initial_sat_cshj;
     scalar_t m_dt;
 };
 
 int main()
 {
 
     specmicp::logger::ErrFile::stream() = &std::cerr;
     specmicp::stdlog::ReportLevel() = specmicp::logger::Warning;
 
     RawDatabasePtr the_database = get_database("../data/cemdata_specmicp.js");
 
     for (auto label: the_database->labels_basis)
         std::cout << label << std::endl;
 
     AdimensionalSystemSolverOptions specmicp_options = get_specmicp_options();
     units::UnitsSet units_set =  specmicp_options.units_set;
 
     AdimensionalSystemConstraints cement_constraints = get_cement_initial_constraints(the_database, units_set);
 
     for (auto label: the_database->labels_minerals)
         std::cout << label << std::endl;
 
     AdimensionalSystemSolution cement_solution = get_cement_initial_compo(
                 the_database,
                 cement_constraints,
                 specmicp_options);
 
     AdimensionalSystemSolutionExtractor extractor(cement_solution, the_database, units_set);
 
     std::cout << "Porosity : " << extractor.porosity() << std::endl;
     std::cout << "Water volume fraction " << extractor.volume_fraction_water() << std::endl;
 
     AdimensionalSystemConstraints bc_constraints = get_bc_initial_constraints(
                 the_database,
                 specmicp_options.units_set
                 );
 
     AdimensionalSystemSolution bc_solution = get_bc_initial_compo(
                 the_database,
                 bc_constraints,
                 specmicp_options
                 );
 
     AdimensionalSystemSolutionExtractor extractor2(bc_solution, the_database, units_set);
 
     std::cout << "pH : " << extractor2.pH() << std::endl;
 
-    mesh::Mesh1DPtr the_mesh = get_mesh(0.0075);
+    mesh::Mesh1DPtr the_mesh = get_mesh(0.0025);
+    //mesh::Mesh1DPtr the_mesh = get_mesh(); //(0.0005);
     index_t nb_nodes = the_mesh->nb_nodes();
     std::vector<specmicp::AdimensionalSystemConstraints> list_constraints = {cement_constraints,
                                                                              bc_constraints};
     std::vector<specmicp::AdimensionalSystemSolution> list_initial_composition = {cement_solution, bc_solution};
     std::vector<int> index_initial_state(nb_nodes, 0);
     std::vector<int> index_constraints(nb_nodes, 0);
     index_initial_state[0] = 1;
     index_constraints[0] = 1 ;
 
     std::vector<index_t> list_fixed_nodes = {0};
 
 
     satdiff::SaturatedVariablesPtr variables =
             satdiff::init_variables(the_mesh, the_database, units_set,
                                                         list_fixed_nodes,
                                                         list_initial_composition,
                                                         index_initial_state);
 
     std::shared_ptr<EquilibriumStagger> equilibrium_stagger =
             std::make_shared<satdiff::EquilibriumStagger>(list_constraints, index_constraints, specmicp_options);
 
     std::shared_ptr<SaturatedTransportStagger> transport_stagger =
             std::make_shared<satdiff::SaturatedTransportStagger>(variables, list_fixed_nodes);
     set_transport_options(transport_stagger->options_solver());
 
     UpscalingStaggerPtr upscaling_stagger =
             std::make_shared<CarboUspcaling>(the_database, units_set);
 
     ReactiveTransportSolver solver(transport_stagger, equilibrium_stagger, upscaling_stagger);
     transport_stagger->initialize(variables);
     equilibrium_stagger->initialize(variables);
     upscaling_stagger->initialize(variables);
 
     std::cout << variables->upscaling_variables() << std::endl;
 
     set_reactive_solver_options(solver.get_options());
 
-    scalar_t dt = 1.0;
+    output_mesh(the_mesh);
+
+    scalar_t dt = 0.1;
     index_t cnt = 0;
 
     Timestepper timestepper(1e-2, 10.0, 30*24*3600, 2);
 
     database::Database dbhandler(the_database);
-    index_t id_oh = dbhandler.component_label_to_id("HO[-]");
+    //index_t id_oh = dbhandler.component_label_to_id("HO[-]");
     index_t id_hco3 = dbhandler.component_label_to_id("HCO3[-]");
     index_t id_ca = dbhandler.component_label_to_id("Ca[2+]");
 
+    index_t id_calcite = dbhandler.mineral_label_to_id("Calcite");
+
     std::string prefix = "out_carbo_";
     std::string suffix = ".dat";
 
     std::ofstream out_c_oh(prefix+"ph"+suffix);
     std::ofstream out_c_hco3(prefix+"c_hco3"+suffix);
     std::ofstream out_s_ca(prefix+"s_ca"+suffix);
-    std::ofstream out_s_co2(prefix+"s_co2"+suffix);
     std::ofstream out_iter(prefix+"iter"+suffix);
+    std::ofstream out_calcite(prefix+"calcite"+suffix);
 
     io::print_reactmicp_performance_long_header(&out_iter);
 
 //    std::vector<std::ofstream> out_minerals(the_database->nb_mineral);
 //    for (index_t mineral: the_database->range_mineral())
 //    {
 //        const std::string path = prefix+"min_"+the_database->labels_minerals[mineral]+suffix;
 //        out_minerals[mineral].open(path);
 //    }
 
     while (timestepper.get_total() < timestepper.get_total_target())
     {
         Timer step_timer;
         step_timer.start();
         reactmicp::solver::ReactiveTransportReturnCode retcode = solver.solve_timestep(dt, variables);
         step_timer.stop();
 
         io::print_reactmicp_performance_long(&out_iter, cnt, timestepper.get_total()+dt, solver.get_perfs());
 
         dt = timestepper.next_timestep(dt, retcode, solver.get_perfs().nb_iterations);
         if (retcode <= reactmicp::solver::ReactiveTransportReturnCode::NotConvergedYet)
         {
             dt = 0.01;
             variables->reset_main_variables();
             retcode = solver.solve_timestep(dt, variables);
             dt = timestepper.next_timestep(dt, retcode, solver.get_perfs().nb_iterations);
             io::print_reactmicp_performance_long(&out_iter, cnt, timestepper.get_total(), solver.get_perfs());
         }
 
 
 
-        if (cnt % 50 == 0)
+        if (cnt % 360 == 0)
         {
 
 
         out_c_oh << timestepper.get_total();
         out_c_hco3 << timestepper.get_total();
         out_s_ca << timestepper.get_total();
-        out_s_co2 << timestepper.get_total();
+        out_calcite << timestepper.get_total();
 
         //for (index_t mineral: the_database->range_mineral())
         //    out_minerals[mineral] << timestepper.get_total();
 
         for (index_t node: the_mesh->range_nodes())
         {
             AdimensionalSystemSolutionExtractor extractor(variables->equilibrium_solution(node), the_database, units_set);
             out_c_oh << "\t" << extractor.pH();
             out_c_hco3 << "\t" << variables->aqueous_concentration(node, id_hco3, variables->displacement());
             out_s_ca << "\t" << variables->solid_concentration(node, id_ca, variables->displacement());
-            out_s_co2 << "\t" << variables->solid_concentration(node, id_hco3, variables->displacement());
+            out_calcite << "\t" << extractor.volume_fraction_mineral(id_calcite);
 
             //for (index_t mineral: the_database->range_mineral())
             //    out_minerals[mineral] << "\t" << extractor.volume_fraction_mineral(mineral);
         }
         out_c_hco3 << std::endl;
         out_c_oh << std::endl;
         out_s_ca << std::endl;
-        out_s_co2 << std::endl;
+        out_calcite << std::endl;
         //for (index_t mineral: the_database->range_mineral())
          //   out_minerals[mineral] <<  std::endl;
 
         }
 
         ++cnt;
     }
 
     print_minerals_profile(the_database, variables, the_mesh, prefix+"profiles_end"+suffix);
 
     io::print_reactmicp_timer(&out_iter, solver.get_timer());
 }
 
 AdimensionalSystemSolverOptions get_specmicp_options()
 {
     AdimensionalSystemSolverOptions options;
 
     options.solver_options.steptol = 1e-10;
     options.solver_options.maxiter_maxstep = 100;
     options.solver_options.maxstep = 10.0;
     options.solver_options.fvectol = 1e-10;
     options.solver_options.steptol = 1e-16;
     options.solver_options.condition_limit = -1;
     options.solver_options.factor_descent_condition = -1;
     options.solver_options.threshold_cycling_linesearch = 1e-6;
     options.solver_options.non_monotone_linesearch = true;
     options.solver_options.use_scaling = true;
 
     options.system_options.non_ideality_tolerance = 1e-14;
 
     options.units_set.length = units::LengthUnit::centimeter;
 
     return options;
 }
 
 void set_transport_options(dfpmsolver::ParabolicDriverOptions& transport_options)
 {
     transport_options.maximum_iterations = 450;
     transport_options.quasi_newton = 3;
     transport_options.residuals_tolerance = 1e-6;
     transport_options.step_tolerance = 1e-16;
     transport_options.absolute_tolerance = 1e-18;
 
     transport_options.alpha = 1.0;
     //transport_options.linesearch = dfpmsolver::ParabolicLinesearch::Strang;
     transport_options.sparse_solver = SparseSolver::SparseLU;
     //transport_options.sparse_solver = SparseSolver::GMRES;
     transport_options.threshold_stationary_point = 1e-4;
 }
 
 void set_reactive_solver_options(reactmicp::solver::ReactiveTransportOptions& reactive_options)
 {
     reactive_options.maximum_iterations = 50; //500;
     reactive_options.residuals_tolerance = 1e-4;
     reactive_options.good_enough_tolerance = 1.0;
 
     reactive_options.absolute_residuals_tolerance = 1e-6;
     reactive_options.implicit_upscaling = false;
 }
 
 RawDatabasePtr get_database(const std::string& path_to_database) {
     database::Database the_database(path_to_database);
     std::map<std::string, std::string> swapping({
                                                     {"H[+]","HO[-]"},
                                                     {"Si(OH)4", "SiO(OH)3[-]"},
                                                     {"Al[3+]","Al(OH)4[-]"}
                                                 });
     the_database.swap_components(swapping);
 
     return the_database.get_database();
 
 }
 
 void print_minerals_profile(
         RawDatabasePtr the_database,
         SaturatedVariablesPtr variables,
         mesh::Mesh1DPtr the_mesh,
         const std::string& filepath
         )
 {
     std::ofstream ofile(filepath);
 
     ofile << "Radius";
     for (index_t mineral: the_database->range_mineral())
     {
         ofile << "\t" << the_database->labels_minerals[mineral];
     }
     ofile << "\t" << "Porosity";
     ofile << "\t" << "pH";
     ofile << std::endl;
 
     for (index_t node: the_mesh->range_nodes())
     {
         ofile << the_mesh->get_position(node);
         AdimensionalSystemSolutionExtractor extractor(variables->equilibrium_solution(node), the_database, units::UnitsSet());
 
         for (index_t mineral: the_database->range_mineral())
         {
             ofile << "\t" << extractor.volume_fraction_mineral(mineral);
         }
         ofile << "\t" << variables->porosity(node);
         ofile << "\t" << extractor.pH();
         ofile << std::endl;
 
     }
 
     ofile.close();
 }
 
 AdimensionalSystemConstraints get_cement_initial_constraints(
         RawDatabasePtr the_database,
         const units::UnitsSet& units_set)
 {
     Vector init_min_publi(5);
     init_min_publi << 12.9, 1.62, 0.605, 0.131, 0.001;
     Vector init_min;
     init_min = initial_compo(init_min_publi);
     std::cout << "Init min \n ---- \n" << init_min << "\n ---- \n" << std::endl;
 
     scalar_t mult = 1e-6;
     //scalar_t mult = 6.73153e-4;
     //scalar_t mult = 0.001296315;
     init_min *= 6.71146e-4;
 
     Formulation formulation;
     formulation.mass_solution = 1.0;
     formulation.amount_minerals = {
         {"Portlandite", init_min(0)},
         {"CSH,jennite", init_min(1)},
         {"Monosulfoaluminate", init_min(2)},
         {"Ettringite", init_min(3)},
         {"Calcite", init_min(4)}
     };
     formulation.concentration_aqueous =
     {
         {"Na[+]", mult*1.0298},
         {"K[+]",  mult*0.0801},
         {"Cl[-]", mult*0.0001},
         {"HO[-]", mult*1.8298}
     },
     formulation.minerals_to_keep = {
         "Portlandite",
         "CSH,jennite",
         "CSH,tobermorite",
         "SiO2,am",
         "Calcite",
         "Al(OH)3,am",
         "Monosulfoaluminate",
         "Tricarboaluminate",
         "Monocarboaluminate",
         "Hemicarboaluminate",
         "Straetlingite",
         "Gypsum",
-        "Ettringite",
-        "Thaumasite"
+        "Ettringite"
     };
     Dissolver dissolver(the_database);
     dissolver.set_units(units_set);
 
     AdimensionalSystemConstraints constraints;
     //constraints.set_charge_keeper(1);
 
     constraints.total_concentrations =  dissolver.dissolve(formulation);
 
     std::cout << constraints.total_concentrations << std::endl;
 
     constraints.set_saturated_system();
 
     return constraints;
 }
 
 AdimensionalSystemConstraints get_bc_initial_constraints(
         RawDatabasePtr the_database,
         const units::UnitsSet& units_set)
 {
     const scalar_t rho_w = laws::density_water(units::celsius(25.0), units_set.length, units_set.mass);
     const scalar_t nacl = 0.3*rho_w;
     const scalar_t kcl = 0.28*rho_w;
 
     database::Database dbhandler(the_database);
 
     Vector total_concentrations(the_database->nb_component);
     total_concentrations.setZero();
     total_concentrations(dbhandler.component_label_to_id("K[+]")) = kcl;
     total_concentrations(dbhandler.component_label_to_id("Cl[-]")) = nacl + kcl;
     total_concentrations(dbhandler.component_label_to_id("Na[+]")) = nacl;
 
     AdimensionalSystemConstraints constraints;
     constraints.add_fixed_activity_component(dbhandler.component_label_to_id("HO[-]"), -10.3);
     constraints.set_charge_keeper(dbhandler.component_label_to_id("HCO3[-]"));
     constraints.total_concentrations =  total_concentrations;
 
     constraints.set_saturated_system();
 
     return constraints;
 }
 
 AdimensionalSystemSolution get_bc_initial_compo(
         RawDatabasePtr the_database,
         const AdimensionalSystemConstraints& constraints,
         const AdimensionalSystemSolverOptions& options
         )
 {
     Vector variables;
     AdimensionalSystemSolver solver(the_database,
                                     constraints,
                                     options);
 
     micpsolver::MiCPPerformance perf = solver.solve(variables, true);
 
     if (perf.return_code <= micpsolver::MiCPSolverReturnCode::NotConvergedYet)
         throw std::runtime_error("Failed to solve initial composition");
 
     std::cout << variables << std::endl;
 
     return solver.get_raw_solution(variables);
 }
 
 AdimensionalSystemSolution get_cement_initial_compo(
         RawDatabasePtr the_database,
         const AdimensionalSystemConstraints& constraints,
         const AdimensionalSystemSolverOptions& options
         )
 {
     AdimensionalSystemSolver solver(the_database,
                                     constraints,
                                     options);
 
     Vector variables;
     solver.initialise_variables(
                 variables,
                 0.4,
                 {
                     {"HO[-]", -1.2},
                     {"Al(OH)4[-]", -4},
                     {"HCO3[-]", -5},
                     {"Ca[2+]", -1.6}
                 });
     micpsolver::MiCPPerformance perf = solver.solve(variables);
 
     if (perf.return_code <= micpsolver::MiCPSolverReturnCode::NotConvergedYet)
         throw std::runtime_error("Failed to solve initial composition");
 
     std::cout << variables << std::endl;
 
     return solver.get_raw_solution(variables);
 }
 
 
 Vector initial_compo(const Vector& publi)
 {
     Matrix publi_stochio(5,5);
     publi_stochio << 1, 0, 0, 0, 0,
                      9, 6, 0, 0, 0,
                      3, 0, 1, 1, 0,
                      3, 0, 1, 3, 0,
                      0, 0, 0, 0, 1;
 
     Matrix cemdata_stochio(5, 5);
     cemdata_stochio << 1, 0, 0, 0, 0,
                        1.0/0.6, 1.0, 0, 0, 0,
                        3, 0, 1, 1, 0,
                        3, 0, 1, 3, 0,
                        0, 0, 0, 0, 1;
 
     Vector oxyde;
     Eigen::ColPivHouseholderQR<Matrix> solver(publi_stochio);
     oxyde = solver.solve(publi);
 
     Vector for_cemdata =  cemdata_stochio*oxyde;
     return for_cemdata;
 }
 
 
 mesh::Mesh1DPtr get_mesh(scalar_t dx)
 {
-    const scalar_t total_length = 7.5/2.0; //cm
+    const scalar_t total_length = 0.75/2.0 + dx; //cm
     const scalar_t height = 20;
 
-    index_t nb_nodes = total_length/dx + 1;
+    index_t nb_nodes = 151; //total_length/dx + 1;
 
     return mesh::uniform_axisymmetric_mesh1d(nb_nodes, total_length, dx, height);
 }
+
+mesh::Mesh1DPtr get_mesh()
+{
+    Vector radius(40);
+
+    const scalar_t height = 20;
+
+    radius <<
+              3.751,
+            3.750,
+            3.749,
+            3.748,
+            3.747,
+            3.745,
+            3.740,
+            3.735,
+            3.730,
+            3.720,
+            3.710,
+            3.700,
+            3.675,
+            3.650,
+            3.625,
+            3.600,
+            3.575,
+            3.550,
+            3.525,
+            3.500,
+            3.475,
+            3.450,
+            3.425,
+            3.400,
+            3.375,
+            3.350,
+            3.325,
+            3.300,
+            3.250,
+            3.200,
+            3.150,
+            3.100,
+            3.050,
+            3.000,
+            2.950,
+            2.900,
+            2.850,
+            2.800,
+            2.750,
+            2.700;
+
+
+    return mesh::axisymmetric_mesh1d(radius, height);
+}
+
+void output_mesh(mesh::Mesh1DPtr the_mesh)
+{
+    std::ofstream output_mesh;
+    output_mesh.open("out_carbo_mesh.dat");
+
+    output_mesh << "Node\tPosition" << std::endl;
+    for (index_t node: the_mesh->range_nodes())
+    {
+        output_mesh << node << "\t" << the_mesh->get_position(node) << std::endl;
+    }
+    output_mesh.close();
+
+}