diff --git a/ChemistryLib/ChemicalSolverInterface.h b/ChemistryLib/ChemicalSolverInterface.h index a1a6eb1f66ee705e067fb229b03f64b24ad586d2..79443449e6540fafb40ef956058c3a44cc1c47a4 100644 --- a/ChemistryLib/ChemicalSolverInterface.h +++ b/ChemistryLib/ChemicalSolverInterface.h @@ -30,10 +30,16 @@ public: virtual void initialize() {} virtual void initializeChemicalSystemConcrete( + std::vector<double> const& /*concentrations*/, GlobalIndexType const& /*chemical_system_id*/, MaterialPropertyLib::Medium const* /*medium*/, - ParameterLib::SpatialPosition const& /*pos*/, - double const /*t*/) + ParameterLib::SpatialPosition const& /*pos*/, double const /*t*/) + { + } + + virtual void setChemicalSystemConcrete( + std::vector<double> const& /*concentrations*/, + GlobalIndexType const& /*chemical_system_id*/) { } diff --git a/ChemistryLib/PhreeqcIO.cpp b/ChemistryLib/PhreeqcIO.cpp index 1d77d3e1edd4e4539a866a40a27e4cf93709eef2..3ec32c7ee4f2f3006a6d7f372fca6996567b6f7b 100644 --- a/ChemistryLib/PhreeqcIO.cpp +++ b/ChemistryLib/PhreeqcIO.cpp @@ -50,6 +50,23 @@ std::ostream& operator<<(std::ostream& os, return os; } +void setAqueousSolution(std::vector<double> const& concentrations, + GlobalIndexType const& chemical_system_id, + AqueousSolution& aqueous_solution) +{ + // components + auto& components = aqueous_solution.components; + for (unsigned component_id = 0; component_id < components.size(); + ++component_id) + { + components[component_id].amount->set(chemical_system_id, + concentrations[component_id]); + } + + // pH + aqueous_solution.pH->set(chemical_system_id, concentrations.back()); +} + template <typename Reactant> void setReactantMolality(Reactant& reactant, GlobalIndexType const& chemical_system_id, @@ -145,10 +162,15 @@ void PhreeqcIO::initialize() } void PhreeqcIO::initializeChemicalSystemConcrete( + std::vector<double> const& concentrations, GlobalIndexType const& chemical_system_id, MaterialPropertyLib::Medium const* medium, - ParameterLib::SpatialPosition const& pos, double const t) + ParameterLib::SpatialPosition const& pos, + double const t) { + setAqueousSolution(concentrations, chemical_system_id, + *_chemical_system->aqueous_solution); + auto const& solid_phase = medium->phase("Solid"); for (auto& kinetic_reactant : _chemical_system->kinetic_reactants) { @@ -163,7 +185,13 @@ void PhreeqcIO::initializeChemicalSystemConcrete( } } +void PhreeqcIO::setChemicalSystemConcrete( + std::vector<double> const& concentrations, + GlobalIndexType const& chemical_system_id) { + setAqueousSolution(concentrations, chemical_system_id, + *_chemical_system->aqueous_solution); +} void PhreeqcIO::executeInitialCalculation() { diff --git a/ChemistryLib/PhreeqcIO.h b/ChemistryLib/PhreeqcIO.h index 44e6814f27d47fcd025ba87c70f5e53d9e724303..1e9d189ba94e0804376381c11f395e62eb6bbf2f 100644 --- a/ChemistryLib/PhreeqcIO.h +++ b/ChemistryLib/PhreeqcIO.h @@ -47,11 +47,15 @@ public: void initialize() override; void initializeChemicalSystemConcrete( + std::vector<double> const& concentrations, GlobalIndexType const& chemical_system_id, MaterialPropertyLib::Medium const* medium, ParameterLib::SpatialPosition const& pos, double const t) override; + void setChemicalSystemConcrete( + std::vector<double> const& concentrations, + GlobalIndexType const& chemical_system_id) override; void executeInitialCalculation() override; diff --git a/ProcessLib/ComponentTransport/ComponentTransportFEM.h b/ProcessLib/ComponentTransport/ComponentTransportFEM.h index 86ffe60394d8679000cfe9ddd0fb999652b32b0f..b117cab62802e0289a9e896a488d30b738b3f4f5 100644 --- a/ProcessLib/ComponentTransport/ComponentTransportFEM.h +++ b/ProcessLib/ComponentTransport/ComponentTransportFEM.h @@ -97,6 +97,29 @@ public: initializeChemicalSystemConcrete(local_x, t); } + void setChemicalSystem( + std::size_t const mesh_item_id, + std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables, + std::vector<GlobalVector*> const& x, double const t, double const dt) + { + std::vector<double> local_x_vec; + + auto const n_processes = x.size(); + for (std::size_t process_id = 0; process_id < n_processes; ++process_id) + { + auto const indices = + NumLib::getIndices(mesh_item_id, *dof_tables[process_id]); + assert(!indices.empty()); + auto const local_solution = x[process_id]->get(indices); + local_x_vec.insert(std::end(local_x_vec), + std::begin(local_solution), + std::end(local_solution)); + } + auto const local_x = MathLib::toVector(local_x_vec); + + setChemicalSystemConcrete(local_x, t, dt); + } + virtual std::vector<double> const& getIntPtDarcyVelocity( const double t, std::vector<GlobalVector*> const& x, @@ -113,6 +136,10 @@ private: virtual void initializeChemicalSystemConcrete( Eigen::VectorXd const& /*local_x*/, double const /*t*/) = 0; + virtual void setChemicalSystemConcrete(Eigen::VectorXd const& /*local_x*/, + double const /*t*/, + double const /*dt*/) = 0; + protected: CoupledSolutionsForStaggeredScheme* _coupled_solutions{nullptr}; }; @@ -217,7 +244,7 @@ public: } } - void initializeChemicalSystemConcrete(Eigen::VectorXd const& /*local_x*/, + void initializeChemicalSystemConcrete(Eigen::VectorXd const& local_x, double const t) override { assert(_process_data.chemical_solver_interface); @@ -233,11 +260,62 @@ public: for (unsigned ip = 0; ip < n_integration_points; ip++) { auto& ip_data = _ip_data[ip]; + auto const& N = ip_data.N; auto const& chemical_system_id = ip_data.chemical_system_id; + auto const n_component = _transport_process_variables.size(); + std::vector<double> C_int_pt(n_component); + for (unsigned component_id = 0; component_id < n_component; + ++component_id) + { + auto const concentration_index = + first_concentration_index + + component_id * concentration_size; + auto const local_C = + local_x.template segment<concentration_size>( + concentration_index); + + NumLib::shapeFunctionInterpolate(local_C, N, + C_int_pt[component_id]); + } + _process_data.chemical_solver_interface - ->initializeChemicalSystemConcrete(chemical_system_id, medium, - pos, t); + ->initializeChemicalSystemConcrete(C_int_pt, chemical_system_id, + medium, pos, t); + } + } + + void setChemicalSystemConcrete(Eigen::VectorXd const& local_x, + double const /*t*/, double /*dt*/) override + { + assert(_process_data.chemical_solver_interface); + + unsigned const n_integration_points = + _integration_method.getNumberOfPoints(); + for (unsigned ip = 0; ip < n_integration_points; ip++) + { + auto& ip_data = _ip_data[ip]; + auto const& N = ip_data.N; + auto const& chemical_system_id = ip_data.chemical_system_id; + + auto const n_component = _transport_process_variables.size(); + std::vector<double> C_int_pt(n_component); + for (unsigned component_id = 0; component_id < n_component; + ++component_id) + { + auto const concentration_index = + first_concentration_index + + component_id * concentration_size; + auto const local_C = + local_x.template segment<concentration_size>( + concentration_index); + + NumLib::shapeFunctionInterpolate(local_C, N, + C_int_pt[component_id]); + } + + _process_data.chemical_solver_interface->setChemicalSystemConcrete( + C_int_pt, chemical_system_id); } } diff --git a/ProcessLib/ComponentTransport/ComponentTransportProcess.cpp b/ProcessLib/ComponentTransport/ComponentTransportProcess.cpp index 5037f7a70b065d92115ae29441adde5100680370..8b59ddfecddb3de5a8ed42e23caecf9c68dcfa77 100644 --- a/ProcessLib/ComponentTransport/ComponentTransportProcess.cpp +++ b/ProcessLib/ComponentTransport/ComponentTransportProcess.cpp @@ -224,6 +224,18 @@ void ComponentTransportProcess::solveReactionEquation( // process. // TODO: move into a global loop to consider both mass balance over // space and localized chemical equilibrium between solutes. + const int process_id = 0; + ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0]; + + std::vector<NumLib::LocalToGlobalIndexMap const*> dof_tables; + dof_tables.reserve(x.size()); + std::generate_n(std::back_inserter(dof_tables), x.size(), + [&]() { return _local_to_global_index_map.get(); }); + + GlobalExecutor::executeSelectedMemberOnDereferenced( + &ComponentTransportLocalAssemblerInterface::setChemicalSystem, + _local_assemblers, pv.getActiveElementIDs(), dof_tables, x, t, dt); + BaseLib::RunTime time_phreeqc; time_phreeqc.start();