8#include <boost/algorithm/string.hpp>
42 using Ts::operator()...;
63 if (
const auto newline_pos =
text_.find(
'\n',
pos_);
64 newline_pos == std::string_view::npos)
72 pos_ = newline_pos + 1;
76 if (!line.empty() && line.back() ==
'\r')
78 line.remove_suffix(1);
86 for (
int i = 0; i < num_lines &&
pos_ <
text_.size(); ++i)
88 const auto newline_pos =
text_.find(
'\n',
pos_);
89 pos_ = (newline_pos == std::string_view::npos) ?
text_.size()
101 std::vector<std::string> items;
102 std::string line_str(line);
103 boost::trim_if(line_str, boost::is_any_of(
"\t "));
104 boost::algorithm::split(items, line_str, boost::is_any_of(
"\t "),
105 boost::token_compress_on);
110 std::string
const& line,
111 std::vector<int>
const& dropped_item_ids,
112 std::size_t chemical_system_id)
114 std::vector<double> accepted_items;
116 for (
int item_id = 0; item_id < static_cast<int>(items.size()); ++item_id)
118 if (std::find(dropped_item_ids.begin(), dropped_item_ids.end(),
119 item_id) != dropped_item_ids.end())
126 value = std::stod(items[item_id]);
128 catch (
const std::invalid_argument& e)
131 "Invalid argument. Could not convert string '{:s}' to "
132 "double for chemical system {:d}, column {:d}. "
133 "Exception '{:s}' was thrown.",
134 items[item_id], chemical_system_id + 1, item_id, e.what());
136 catch (
const std::out_of_range& e)
139 "Out of range error. Could not convert string "
140 "'{:s}' to double for chemical system {:d}, column "
141 "{:d}. Exception '{:s}' was thrown.",
142 items[item_id], chemical_system_id + 1, item_id, e.what());
144 accepted_items.push_back(value);
146 return accepted_items;
149template <
typename DataBlock>
151 std::vector<DataBlock>
const& data_blocks)
153 std::copy(data_blocks.begin(), data_blocks.end(),
154 std::ostream_iterator<DataBlock>(os));
166 auto& components = aqueous_solution.
components;
167 for (
unsigned component_id = 0; component_id < components.size();
171 *components[component_id].amount);
172 components[component_id].amount->set(global_index,
173 concentrations[component_id]);
178 aqueous_solution.
pH->set(global_index, concentrations.back());
181template <
typename Reactant>
190 auto const& solid_constituent = solid_phase.
component(reactant.name);
192 if (solid_constituent.hasProperty(
195 auto const molality =
197 .template initialValue<double>(pos, t);
199 (*reactant.molality)[chemical_system_id] = molality;
200 (*reactant.molality_prev)[chemical_system_id] = molality;
204 auto const volume_fraction =
207 .template initialValue<double>(pos, t);
209 (*reactant.volume_fraction)[chemical_system_id] = volume_fraction;
211 (*reactant.volume_fraction_prev)[chemical_system_id] = volume_fraction;
213 auto const fluid_density =
215 .template initialValue<double>(pos, t);
217 auto const porosity =
219 .template initialValue<double>(pos, t);
221 auto const molar_volume =
223 .template initialValue<double>(pos, t);
225 (*reactant.molality)[chemical_system_id] =
226 volume_fraction / fluid_density / porosity / molar_volume;
228 (*reactant.molality_prev)[chemical_system_id] =
229 (*reactant.molality)[chemical_system_id];
233template <
typename Reactant>
240 double const t,
double const dt)
242 auto const& solid_constituent = solid_phase.
component(reactant.name);
244 if (solid_constituent.hasProperty(
247 (*reactant.molality_prev)[chemical_system_id] =
248 (*reactant.molality)[chemical_system_id];
253 auto const volume_fraction =
254 (*reactant.volume_fraction)[chemical_system_id];
256 (*reactant.volume_fraction_prev)[chemical_system_id] =
257 (*reactant.volume_fraction)[chemical_system_id];
259 auto const fluid_density =
261 .template value<double>(vars, pos, t, dt);
263 auto const molar_volume =
265 .template value<double>(vars, pos, t, dt);
267 (*reactant.molality)[chemical_system_id] =
268 volume_fraction / fluid_density / vars.
porosity / molar_volume;
270 (*reactant.molality_prev)[chemical_system_id] =
271 (*reactant.molality)[chemical_system_id];
274template <
typename Site>
281 auto const& solid_constituent = solid_phase.
component(site.name);
283 auto const molality =
285 .template initialValue<double>(pos, t);
287 (*site.molality)[chemical_system_id] = molality;
290template <
typename Reactant>
295 double const porosity,
double const t,
298 auto const& solid_phase =
300 auto const& liquid_phase =
305 auto const liquid_density =
307 .template value<double>(vars, pos, t, dt);
309 auto const& solid_constituent = solid_phase.component(reactant.name);
311 if (solid_constituent.hasProperty(
317 auto const molar_volume =
319 .template value<double>(vars, pos, t, dt);
321 (*reactant.volume_fraction)[chemical_system_id] +=
322 ((*reactant.molality)[chemical_system_id] -
323 (*reactant.molality_prev)[chemical_system_id]) *
324 liquid_density * porosity * molar_volume;
327template <
typename Reactant>
333 auto const& solid_phase =
336 auto const& solid_constituent = solid_phase.
component(reactant.name);
338 if (solid_constituent.hasProperty(
344 porosity -= ((*reactant.volume_fraction)[chemical_system_id] -
345 (*reactant.volume_fraction_prev)[chemical_system_id]);
348template <
typename Reactant>
350 Reactant
const& reactant,
351 std::vector<GlobalIndexType>
const& chemical_system_indices)
353 double const sum = std::accumulate(
354 chemical_system_indices.begin(), chemical_system_indices.end(), 0.0,
356 { return s + (*reactant.molality)[id]; });
357 return sum / chemical_system_indices.size();
361extern std::string
specifyFileName(std::string
const& project_file_name,
362 std::string
const& file_extension);
366 std::string
const& project_file_name,
367 std::string&& database,
368 std::unique_ptr<ChemicalSystem>&& chemical_system,
369 std::vector<ReactionRate>&& reaction_rates,
370 std::unique_ptr<UserPunch>&& user_punch,
371 std::unique_ptr<Output>&& output,
372 std::unique_ptr<Dump>&& dump,
374 bool use_stream_mode)
382 _dump(std::move(dump)),
390 "Failed to initialize phreeqc instance, due to lack of memory.");
397 "Failed in loading the specified thermodynamic database file: "
410 "Failed to disable file output for selected output in stream "
418 "Failed to enable string buffering for selected output in "
423 "PhreeqcIO stream mode: selected output file disabled, using "
424 "internal memory buffer.");
432 "Failed to fly the flag for the specified file {:s} where "
433 "phreeqc will write output.",
434 _output->basic_output_setups.output_file);
445 "PhreeqcIO is configured for stream-based data exchange: dump "
446 "file output disabled.");
453 "Failed to enable string buffering for dump output in "
469 "PhreeqcIO is configured for stream-based data exchange: input "
470 "and output will be exchanged via in-memory strings.");
492 std::vector<double>
const& concentrations,
498 setAqueousSolution(concentrations, chemical_system_id,
501 auto const& solid_phase =
503 auto const& liquid_phase =
508 initializeReactantMolality(kinetic_reactant, chemical_system_id,
509 solid_phase, liquid_phase, medium, pos, t);
514 initializeReactantMolality(equilibrium_reactant, chemical_system_id,
515 solid_phase, liquid_phase, medium, pos, t);
520 initializeSiteMolality(exchanger, chemical_system_id, solid_phase, pos,
526 if (
auto const surface_site_ptr =
527 std::get_if<MoleBasedSurfaceSite>(&surface_site))
529 initializeSiteMolality(*surface_site_ptr, chemical_system_id,
530 solid_phase, pos, t);
536 std::vector<double>
const& concentrations,
542 setAqueousSolution(concentrations, chemical_system_id,
545 auto const& solid_phase =
547 auto const& liquid_phase =
552 setReactantMolality(kinetic_reactant, chemical_system_id, solid_phase,
553 liquid_phase, vars, pos, t, dt);
558 setReactantMolality(equilibrium_reactant, chemical_system_id,
559 solid_phase, liquid_phase, vars, pos, t, dt);
568 DBUG(
"Executing speciation with stream-based data exchange.");
590 DBUG(
"Executing speciation with file-based data exchange.");
601 int const component_id,
GlobalIndexType const chemical_system_id)
const
604 auto& components = aqueous_solution.components;
605 auto const&
pH = *aqueous_solution.pH;
607 if (component_id <
static_cast<int>(components.size()))
610 *components[component_id].amount);
612 return components[component_id].amount->get(chemical_system_id);
618 return pH.get(chemical_system_id);
628 auto const& dump_file =
_dump->dump_file;
629 std::ifstream in(dump_file);
641 OGS_FATAL(
"Error when reading phreeqc dump file '{:s}'", dump_file);
648 std::string_view dump_content)
655 if (dump_content.empty())
660 "Dump content is empty, skipping aqueous solutions initialization "
670 DBUG(
"Serializing phreeqc inputs to string stream.");
671 std::stringstream ss;
673 ss << std::scientific
674 << std::setprecision(std::numeric_limits<double>::max_digits10);
680 OGS_FATAL(
"Failed in serializing phreeqc inputs to string.");
693 OGS_FATAL(
"Could not open file '{:s}' for writing phreeqc inputs.",
697 out << std::scientific
698 << std::setprecision(std::numeric_limits<double>::max_digits10);
704 OGS_FATAL(
"Failed in generating phreeqc input file '{:s}'.",
713 bool const fixing_pe =
723 os << phreeqc_io.
_knobs <<
"\n";
725 os << *phreeqc_io.
_output <<
"\n";
730 os << *user_punch <<
"\n";
734 if (!reaction_rates.empty())
737 os << reaction_rates <<
"\n";
740 for (std::size_t chemical_system_id = 0;
742 ++chemical_system_id)
744 os <<
"SOLUTION " << chemical_system_id + 1 <<
"\n";
746 os, chemical_system_id);
748 auto const& dump = phreeqc_io.
_dump;
751 auto const& aqueous_solutions_prev = dump->aqueous_solutions_prev;
753 if (!aqueous_solutions_prev.empty())
755 os << aqueous_solutions_prev[chemical_system_id] <<
"\n\n";
759 os <<
"USE solution none\n";
762 os <<
"USE solution " << chemical_system_id + 1 <<
"\n\n";
764 auto const& equilibrium_reactants =
766 if (!equilibrium_reactants.empty() || fixing_pe)
768 os <<
"EQUILIBRIUM_PHASES " << chemical_system_id + 1 <<
"\n";
769 for (
auto const& equilibrium_reactant : equilibrium_reactants)
771 equilibrium_reactant.print(os, chemical_system_id);
780 auto const& kinetic_reactants =
782 if (!kinetic_reactants.empty())
784 os <<
"KINETICS " << chemical_system_id + 1 <<
"\n";
785 for (
auto const& kinetic_reactant : kinetic_reactants)
787 kinetic_reactant.print(os, chemical_system_id);
789 os <<
"-steps " << phreeqc_io.
_dt <<
"\n\n";
793 if (!surface.empty())
803 os <<
"SURFACE " << chemical_system_id + 1 <<
"\n";
804 std::size_t aqueous_solution_id =
805 dump->aqueous_solutions_prev.empty()
806 ? chemical_system_id + 1
808 os <<
"-equilibrate with solution " << aqueous_solution_id <<
"\n";
811 if (std::holds_alternative<DensityBasedSurfaceSite>(
814 os <<
"-sites_units density\n";
818 os <<
"-sites_units absolute\n";
821 for (
auto const& surface_site : surface)
826 os << s.name <<
" " << s.site_density <<
" "
827 << s.specific_surface_area <<
" "
830 [&os, chemical_system_id](
833 << (*s.molality)[chemical_system_id]
840 if (std::holds_alternative<MoleBasedSurfaceSite>(surface.front()))
848 os <<
"SAVE solution " << chemical_system_id + 1 <<
"\n";
852 if (!exchangers.empty())
854 os <<
"EXCHANGE " << chemical_system_id + 1 <<
"\n";
855 std::size_t
const aqueous_solution_id =
856 dump->aqueous_solutions_prev.empty()
857 ? chemical_system_id + 1
859 os <<
"-equilibrate with solution " << aqueous_solution_id <<
"\n";
860 for (
auto const& exchanger : exchangers)
862 exchanger.print(os, chemical_system_id);
864 os <<
"SAVE solution " << chemical_system_id + 1 <<
"\n";
870 auto const& dump = phreeqc_io.
_dump;
881 INFO(
"Phreeqc: Executing chemical calculation.");
886 "Failed in performing speciation calculation with the generated "
887 "phreeqc input file '{:s}'.",
894 INFO(
"Phreeqc: Executing chemical calculation from string stream.");
900 "Failed in performing speciation calculation with string input.");
906 DBUG(
"Retrieving phreeqc results from internal memory buffer.");
911 DBUG(
"Selected output string is empty or unavailable.");
912 return std::string_view();
915 return std::string_view(output_ptr);
920 DBUG(
"Retrieving phreeqc dump data from internal buffer.");
926 DBUG(
"Dump string is empty or unavailable.");
927 return std::string_view();
930 return std::string_view(dump_ptr);
935 auto const& basic_output_setups =
_output->basic_output_setups;
936 auto const& phreeqc_result_file = basic_output_setups.output_file;
937 DBUG(
"Reading phreeqc results from file '{:s}'.", phreeqc_result_file);
938 std::ifstream in(phreeqc_result_file);
942 OGS_FATAL(
"Could not open phreeqc result file '{:s}'.",
943 phreeqc_result_file);
950 OGS_FATAL(
"Error when reading phreeqc result file '{:s}'",
951 phreeqc_result_file);
959 DBUG(
"Reading phreeqc results from string buffer.");
961 if (output_content.empty())
966 StringViewLineIterator line_iter(output_content);
967 std::string_view line;
970 line_iter.getline(line);
975 "No output configuration available when reading PhreeqC results "
980 auto const& dropped_item_ids = output.dropped_item_ids;
985 int const num_skipped_lines =
986 1 + (!surface.empty() ? 1 : 0) + (!exchangers.empty() ? 1 : 0);
991 for (std::size_t chemical_system_id = 0;
993 ++chemical_system_id)
996 line_iter.skip(num_skipped_lines);
999 if (!line_iter.getline(line))
1002 "Error when reading calculation result of Solution {:d} "
1003 "after the reaction.",
1004 chemical_system_id);
1007 auto accepted_items = parseAndFilterChemicalData(
1008 std::string(line), dropped_item_ids, chemical_system_id);
1009 assert(accepted_items.size() == output.accepted_items.size());
1012 auto& components = aqueous_solution->components;
1018 for (
int item_id = 0; item_id < static_cast<int>(accepted_items.size());
1021 auto const& accepted_item = output.accepted_items[item_id];
1022 auto const& item_name = accepted_item.name;
1024 auto compare_by_name = [&item_name](
auto const& item)
1025 {
return item.name == item_name; };
1027 switch (accepted_item.item_type)
1033 *aqueous_solution->pH);
1034 aqueous_solution->pH->set(
1035 global_index, std::pow(10, -accepted_items[item_id]));
1041 (*aqueous_solution->pe)[chemical_system_id] =
1042 accepted_items[item_id];
1049 components, compare_by_name,
1051 OGS_FATAL(
"Could not find component '{:s}'.",
1056 component.amount->set(global_index,
1057 accepted_items[item_id]);
1063 auto const& equilibrium_reactant =
1065 equilibrium_reactants, compare_by_name,
1069 "Could not find equilibrium reactant "
1073 (*equilibrium_reactant.molality)[chemical_system_id] =
1074 accepted_items[item_id];
1081 kinetic_reactants, compare_by_name,
1083 OGS_FATAL(
"Could not find kinetic reactant '{:s}'.",
1086 (*kinetic_reactant.molality)[chemical_system_id] =
1087 accepted_items[item_id];
1093 auto const& secondary_variables =
1094 user_punch->secondary_variables;
1096 auto const& secondary_variable =
1098 secondary_variables, compare_by_name,
1101 "Could not find secondary variable '{:s}'.",
1104 (*secondary_variable.value)[chemical_system_id] =
1105 accepted_items[item_id];
1116 in.ignore(std::numeric_limits<std::streamsize>::max(),
'\n');
1119 auto const& output = *phreeqc_io.
_output;
1120 auto const& dropped_item_ids = output.dropped_item_ids;
1125 int const num_skipped_lines =
1126 1 + (!surface.empty() ? 1 : 0) + (!exchangers.empty() ? 1 : 0);
1128 auto& equilibrium_reactants =
1132 for (std::size_t chemical_system_id = 0;
1134 ++chemical_system_id)
1137 for (
int i = 0; i < num_skipped_lines; ++i)
1139 in.ignore(std::numeric_limits<std::streamsize>::max(),
'\n');
1143 if (!std::getline(in, line))
1146 "Error when reading calculation result of Solution {:d} "
1147 "after the reaction.",
1148 chemical_system_id);
1151 auto accepted_items = parseAndFilterChemicalData(line, dropped_item_ids,
1152 chemical_system_id);
1153 assert(accepted_items.size() == output.accepted_items.size());
1156 auto& components = aqueous_solution->components;
1162 for (
int item_id = 0; item_id < static_cast<int>(accepted_items.size());
1165 auto const& accepted_item = output.accepted_items[item_id];
1166 auto const& item_name = accepted_item.name;
1168 auto compare_by_name = [&item_name](
auto const& item)
1169 {
return item.name == item_name; };
1171 switch (accepted_item.item_type)
1177 *aqueous_solution->pH);
1178 aqueous_solution->pH->set(
1179 global_index, std::pow(10, -accepted_items[item_id]));
1185 (*aqueous_solution->pe)[chemical_system_id] =
1186 accepted_items[item_id];
1193 components, compare_by_name,
1195 OGS_FATAL(
"Could not find component '{:s}'.",
1200 component.amount->set(global_index,
1201 accepted_items[item_id]);
1207 auto const& equilibrium_reactant =
1209 equilibrium_reactants, compare_by_name,
1213 "Could not find equilibrium reactant "
1217 (*equilibrium_reactant.molality)[chemical_system_id] =
1218 accepted_items[item_id];
1225 kinetic_reactants, compare_by_name,
1227 OGS_FATAL(
"Could not find kinetic reactant '{:s}'.",
1230 (*kinetic_reactant.molality)[chemical_system_id] =
1231 accepted_items[item_id];
1237 auto const& secondary_variables =
1238 user_punch->secondary_variables;
1240 auto const& secondary_variable =
1242 secondary_variables, compare_by_name,
1245 "Could not find secondary variable '{:s}'.",
1248 (*secondary_variable.value)[chemical_system_id] =
1249 accepted_items[item_id];
1261 std::vector<std::string> component_names;
1263 std::transform(components.begin(), components.end(),
1264 std::back_inserter(component_names),
1265 [](
auto const& c) { return c.name; });
1267 component_names.push_back(
"H");
1269 return component_names;
1276 double const t,
double const dt)
1280 updateReactantVolumeFraction(kinetic_reactant, chemical_system_id,
1281 medium, pos, porosity, t, dt);
1286 updateReactantVolumeFraction(equilibrium_reactant, chemical_system_id,
1287 medium, pos, porosity, t, dt);
1298 setPorosityPostReaction(kinetic_reactant, chemical_system_id, medium,
1304 setPorosityPostReaction(equilibrium_reactant, chemical_system_id,
1310 std::size_t
const ele_id,
1311 std::vector<GlobalIndexType>
const& chemical_system_indices)
1315 (*kinetic_reactant.mesh_prop_molality)[ele_id] =
1316 averageReactantMolality(kinetic_reactant, chemical_system_indices);
1319 for (
auto const& equilibrium_reactant :
1322 (*equilibrium_reactant.mesh_prop_molality)[ele_id] =
1323 averageReactantMolality(equilibrium_reactant,
1324 chemical_system_indices);
Definition of one reactive chemical system for PHREEQC coupling.
MathLib::EigenLisLinearSolver GlobalLinearSolver
GlobalMatrix::IndexType GlobalIndexType
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Per-system aqueous state exchanged with PHREEQC.
PHREEQC-backed ChemicalSolverInterface implementation.
std::vector< GlobalIndexType > chemical_system_index_map
GlobalLinearSolver & linear_solver
ChemicalSolverInterface(MeshLib::Mesh const &mesh, GlobalLinearSolver &linear_solver_)
std::string const _phreeqc_input_file
double getConcentration(int const component_id, GlobalIndexType const chemical_system_id) const override
void setAqueousSolutionsPrevFromDumpFile() override
PhreeqcIO(MeshLib::Mesh const &mesh, GlobalLinearSolver &linear_solver, std::string const &project_file_name, std::string &&database, std::unique_ptr< ChemicalSystem > &&chemical_system, std::vector< ReactionRate > &&reaction_rates, std::unique_ptr< UserPunch > &&user_punch, std::unique_ptr< Output > &&output, std::unique_ptr< Dump > &&dump, Knobs &&knobs, bool use_stream_mode)
std::unique_ptr< ChemicalSystem > _chemical_system
std::vector< ReactionRate > const _reaction_rates
std::unique_ptr< UserPunch > _user_punch
const int phreeqc_instance_id
void writeInputsToFile(double const dt)
void setChemicalSystemConcrete(std::vector< double > const &concentrations, GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Medium const *medium, MaterialPropertyLib::VariableArray const &vars, ParameterLib::SpatialPosition const &pos, double const t, double const dt) override
std::unique_ptr< Dump > const _dump
void initialize() override
std::unique_ptr< Output > const _output
void readOutputsFromFile()
void readOutputsFromStringView(std::string_view output_content)
void callPhreeqcWithString(std::string const &input_content) const
std::string_view retrieveDumpString() const
std::size_t _num_chemical_systems
void computeSecondaryVariable(std::size_t const ele_id, std::vector< GlobalIndexType > const &chemical_system_indices) 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 updateVolumeFractionPostReaction(GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Medium const &medium, ParameterLib::SpatialPosition const &pos, double const porosity, double const t, double const dt) override
std::string_view retrieveSelectedOutputString() const
void executeSpeciationCalculation(double const dt) override
void setAqueousSolutionsPrevFromDumpString(std::string_view dump_content)
std::string const _database
std::vector< std::string > const getComponentList() const override
std::stringstream writeInputsToStringStream(double const dt)
void updatePorosityPostReaction(GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Medium const &medium, double &porosity) override
StringViewLineIterator(std::string_view text, std::size_t pos=0)
bool getline(std::string_view &line)
Phase const & phase(std::size_t index) const
Component const & component(std::size_t const &index) const
ranges::range_reference_t< Range > findElementOrError(Range &range, std::predicate< ranges::range_reference_t< Range > > auto &&predicate, std::invocable auto error_callback)
std::vector< double > parseAndFilterChemicalData(std::string const &line, std::vector< int > const &dropped_item_ids, std::size_t chemical_system_id)
void initializeSiteMolality(Site &site, GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Phase const &solid_phase, ParameterLib::SpatialPosition const &pos, double const t)
void initializeReactantMolality(Reactant &reactant, GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Phase const &solid_phase, MaterialPropertyLib::Phase const &liquid_phase, MaterialPropertyLib::Medium const &medium, ParameterLib::SpatialPosition const &pos, double const t)
std::vector< std::string > extractItemsFromLine(std::string const &line)
void setPorosityPostReaction(Reactant &reactant, GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Medium const &medium, double &porosity)
void setReactantMolality(Reactant &reactant, GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Phase const &solid_phase, MaterialPropertyLib::Phase const &liquid_phase, MaterialPropertyLib::VariableArray const &vars, ParameterLib::SpatialPosition const &pos, double const t, double const dt)
void setAqueousSolution(std::vector< double > const &concentrations, GlobalIndexType const &chemical_system_id, AqueousSolution &aqueous_solution)
static double averageReactantMolality(Reactant const &reactant, std::vector< GlobalIndexType > const &chemical_system_indices)
void updateReactantVolumeFraction(Reactant &reactant, GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Medium const &medium, ParameterLib::SpatialPosition const &pos, double const porosity, double const t, double const dt)
std::ostream & operator<<(std::ostream &os, PhreeqcIO const &phreeqc_io)
std::string specifyFileName(std::string const &project_file_name, std::string const &file_extension)
std::istream & operator>>(std::istream &in, PhreeqcIO &phreeqc_io)
void setLocalAccessibleVector(PETScVector const &x)
std::vector< Component > components
std::unique_ptr< GlobalVector > pH