OGS
ChemistryLib::PhreeqcIOData::PhreeqcIO Class Referencefinal

Detailed Description

Drives the chemistry step in the operator-split reactive transport loop.

Per timestep:

  1. initializeChemicalSystemConcrete(...) / setChemicalSystemConcrete(...): For each chemical_system_id, store the transported totals \(c_{T\alpha}\), the current porous-medium state (porosity, mineral fractions, reactive surface area), and the process variables (e.g. temperature \(T\), pressure \(p\), time \(t\), and timestep \(\Delta t\)) in the corresponding ChemicalSystem. Each chemical_system_id is treated as one local batch reactor.
  2. executeSpeciationCalculation(dt): Build PHREEQC input for all chemical_system_id, run PHREEQC via IPhreeqc, and obtain the reacted state after advancing chemistry over \(\Delta t\):
    • updated aqueous composition,
    • reaction/source terms \(R_{\alpha}\) for each transported component,
    • updated mineral amounts.
  3. updateVolumeFractionPostReaction(...), updatePorosityPostReaction(...): Apply precipitation / dissolution back into OpenGeoSys by updating mineral / solid volume fractions and porosity for each local system. These updates feed into flow / transport / mechanics in the next global step.
  4. computeSecondaryVariable(...): Optionally expose derived quantities (e.g. pH fields, mineral fractions, surface loading) for output.

Accessors:

  • getConcentration(component_id, chemical_system_id): Reacted total \(c_{T\alpha}\) of a transported component for that local system after the last chemistry step. Used as the starting composition for the next transport solve.
  • getComponentList(): List of transported components in the order expected by the transport process.

Internal data:

Definition at line 114 of file PhreeqcIO.h.

#include <PhreeqcIO.h>

Inheritance diagram for ChemistryLib::PhreeqcIOData::PhreeqcIO:
[legend]
Collaboration diagram for ChemistryLib::PhreeqcIOData::PhreeqcIO:
[legend]

Public Member Functions

 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, int num_chemistry_threads, double concentration_warning_threshold)
 ~PhreeqcIO ()
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, MaterialPropertyLib::Medium const *medium, MaterialPropertyLib::VariableArray const &vars, ParameterLib::SpatialPosition const &pos, double const t, double const dt) override
void setAqueousSolutionsPrevFromDumpFile () override
void executeSpeciationCalculation (double const dt) override
double getConcentration (int const component_id, GlobalIndexType const chemical_system_id) const 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
void updatePorosityPostReaction (GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Medium const &medium, double &porosity) override
void computeSecondaryVariable (std::size_t const ele_id, std::vector< GlobalIndexType > const &chemical_system_indices) override
std::vector< std::string > const getComponentList () const override
Public Member Functions inherited from ChemistryLib::ChemicalSolverInterface
 ChemicalSolverInterface (MeshLib::Mesh const &mesh, GlobalLinearSolver &linear_solver_)
std::vector< std::size_t > const & activeElementIDs () const
virtual Eigen::SparseMatrix< double > const * getStoichiometricMatrix () const
virtual double getKineticPrefactor (std::size_t reaction_id) const
virtual ~ChemicalSolverInterface ()=default

Public Attributes

std::string const _phreeqc_input_file
Public Attributes inherited from ChemistryLib::ChemicalSolverInterface
std::vector< GlobalIndexTypechemical_system_index_map
MeshLib::Mesh const & _mesh
GlobalLinearSolverlinear_solver

Private Member Functions

void writeInputsToFile (double const dt)
void writeInputHeader (std::ostream &os) const
void writeSystemBlock (std::ostream &os, std::size_t chemical_system_id, std::size_t solution_id, std::size_t prev_solution_id, double dt) const
void updateSystemFromOutputLine (std::string_view line, std::size_t chemical_system_id)
void setAqueousSolutionsPrevFromDumpString (std::string_view dump_content)
void callPhreeqc () const
void readOutputsFromFile ()
void executeSpeciationCalculationParallel (double const dt)
std::string generateInputForSystem (std::size_t chemical_system_id, double const dt) const
void parseOutputForSystem (std::string_view output_content, std::size_t chemical_system_id)
void updateChemicalSystemFromOutput (std::vector< double > const &accepted_items, std::size_t chemical_system_id)
PhreeqcIOoperator<< (double const dt)

Private Attributes

ClampingStats _clamping_totals
std::string const _database
Knobs const _knobs
std::vector< ReactionRate > const _reaction_rates
std::unique_ptr< ChemicalSystem_chemical_system
std::unique_ptr< UserPunch_user_punch
std::unique_ptr< Output > const _output
std::unique_ptr< Dump > const _dump
std::unique_ptr< PhreeqcInstancePoolinstance_pool_
double _dt = std::numeric_limits<double>::quiet_NaN()
std::size_t _num_chemical_systems = 0
double _concentration_warning_threshold
int phreeqc_instance_id = -1
int num_chemistry_threads_
bool _use_stream_mode

Friends

std::ostream & operator<< (std::ostream &os, PhreeqcIO const &phreeqc_io)
std::istream & operator>> (std::istream &in, PhreeqcIO &phreeqc_io)

Constructor & Destructor Documentation

◆ PhreeqcIO()

ChemistryLib::PhreeqcIOData::PhreeqcIO::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,
int num_chemistry_threads,
double concentration_warning_threshold )

Definition at line 347 of file PhreeqcIO.cpp.

361 _phreeqc_input_file(specifyFileName(project_file_name, ".inp")),
362 _database(std::move(database)),
363 _knobs(std::move(knobs)),
364 _reaction_rates(std::move(reaction_rates)),
365 _chemical_system(std::move(chemical_system)),
366 _user_punch(std::move(user_punch)),
367 _output(std::move(output)),
368 _dump(std::move(dump)),
369 _concentration_warning_threshold(concentration_warning_threshold),
370 num_chemistry_threads_(num_chemistry_threads),
371 _use_stream_mode(use_stream_mode)
372{
373 INFO("Chemistry threads per MPI rank: {}.", num_chemistry_threads_);
374
376 {
377 // Stream mode runs exclusively on the instance pool (even for a single
378 // thread) so there is one unified execution path. The standalone
379 // phreeqc_instance_id is not used here and stays -1.
381 {
382 INFO(
383 "Parallel chemistry enabled: {} threads will be used for "
384 "PHREEQC calculations.",
386 }
387 INFO(
388 "PhreeqcIO is configured for stream-based data exchange: input "
389 "and output will be exchanged via in-memory strings.");
390 instance_pool_ = std::make_unique<PhreeqcInstancePool>(
391 _database, std::max(1, num_chemistry_threads_));
392 }
393 else
394 {
395 // File mode: create and load the standalone PHREEQC instance and
396 // enable file-based selected output. PhreeqcInstancePool::
397 // createInstance() OGS_FATALs on failure, so any returned id is valid.
400 if (SetSelectedOutputFileOn(phreeqc_instance_id, 1) != IPQ_OK)
401 {
402 OGS_FATAL(
403 "Failed to fly the flag for the specified file {:s} where "
404 "phreeqc will write output.",
405 _output->basic_output_setups.output_file);
406 }
407 if (_dump)
408 {
409 SetDumpFileOn(phreeqc_instance_id, 1);
410 }
411 }
412}
#define OGS_FATAL(...)
Definition Error.h:10
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
ChemicalSolverInterface(MeshLib::Mesh const &mesh, GlobalLinearSolver &linear_solver_)
std::unique_ptr< ChemicalSystem > _chemical_system
Definition PhreeqcIO.h:246
std::vector< ReactionRate > const _reaction_rates
Definition PhreeqcIO.h:245
std::unique_ptr< UserPunch > _user_punch
Definition PhreeqcIO.h:247
std::unique_ptr< PhreeqcInstancePool > instance_pool_
Definition PhreeqcIO.h:250
std::unique_ptr< Dump > const _dump
Definition PhreeqcIO.h:249
std::unique_ptr< Output > const _output
Definition PhreeqcIO.h:248
static int createInstance(std::string const &database)
std::string specifyFileName(std::string const &project_file_name, std::string const &file_extension)

References ChemistryLib::ChemicalSolverInterface::ChemicalSolverInterface(), _chemical_system, _concentration_warning_threshold, _database, _dump, _knobs, _output, _phreeqc_input_file, _reaction_rates, _use_stream_mode, _user_punch, ChemistryLib::PhreeqcIOData::PhreeqcInstancePool::createInstance(), INFO(), instance_pool_, ChemistryLib::ChemicalSolverInterface::linear_solver, num_chemistry_threads_, OGS_FATAL, phreeqc_instance_id, and ChemistryLib::PhreeqcIOData::specifyFileName().

Referenced by operator<<(), operator<<, and operator>>.

◆ ~PhreeqcIO()

ChemistryLib::PhreeqcIOData::PhreeqcIO::~PhreeqcIO ( )

Definition at line 414 of file PhreeqcIO.cpp.

415{
416 // The standalone instance is only created in file mode; in stream mode
417 // phreeqc_instance_id stays -1 and there is nothing to destroy.
418 if (phreeqc_instance_id >= 0)
419 {
420 DestroyIPhreeqc(phreeqc_instance_id);
421 }
422}

References phreeqc_instance_id.

Member Function Documentation

◆ callPhreeqc()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::callPhreeqc ( ) const
private

Definition at line 803 of file PhreeqcIO.cpp.

804{
805 INFO("Phreeqc: Executing chemical calculation.");
806 if (RunFile(phreeqc_instance_id, _phreeqc_input_file.c_str()) != IPQ_OK)
807 {
808 OutputErrorString(phreeqc_instance_id);
809 OGS_FATAL(
810 "Failed in performing speciation calculation with the generated "
811 "phreeqc input file '{:s}'.",
813 }
814}

References _phreeqc_input_file, INFO(), OGS_FATAL, and phreeqc_instance_id.

Referenced by executeSpeciationCalculation().

◆ computeSecondaryVariable()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::computeSecondaryVariable ( std::size_t const ele_id,
std::vector< GlobalIndexType > const & chemical_system_indices )
overridevirtual

Reimplemented from ChemistryLib::ChemicalSolverInterface.

Definition at line 1016 of file PhreeqcIO.cpp.

1019{
1020 for (auto const& kinetic_reactant : _chemical_system->kinetic_reactants)
1021 {
1022 (*kinetic_reactant.mesh_prop_molality)[ele_id] =
1023 averageReactantMolality(kinetic_reactant, chemical_system_indices);
1024 }
1025
1026 for (auto const& equilibrium_reactant :
1027 _chemical_system->equilibrium_reactants)
1028 {
1029 (*equilibrium_reactant.mesh_prop_molality)[ele_id] =
1030 averageReactantMolality(equilibrium_reactant,
1031 chemical_system_indices);
1032 }
1033}
static double averageReactantMolality(Reactant const &reactant, std::vector< GlobalIndexType > const &chemical_system_indices)

References _chemical_system.

◆ executeSpeciationCalculation()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::executeSpeciationCalculation ( double const dt)
overridevirtual

Run PHREEQC for all local chemical systems for the current timestep.

Uses the state previously provided by initializeChemicalSystemConcrete() / setChemicalSystemConcrete() for each chemical_system_id. Each local system is advanced as an isolated batch reactor over \(\Delta t\): no mass is exchanged between different systems inside PHREEQC.

PHREEQC returns, for each system:

  • updated aqueous composition,
  • reaction / source terms \(R_{\alpha}\) for each transported component,
  • updated mineral amounts and saturation state.

After this call completes, these reacted values are available for porosity update and for assembling the reaction/source term in the transport equation.

Parameters
dtTimestep size \(\Delta t\) used for kinetic reactions.

Reimplemented from ChemistryLib::ChemicalSolverInterface.

Definition at line 512 of file PhreeqcIO.cpp.

513{
514 // Report the negative-concentration clamping accumulated over all chemical
515 // systems in this step as a single aggregated message, then reset the
516 // accumulator for the next step.
518 _clamping_totals = {};
519
521 {
522 // Stream mode always uses the pool (serial or parallel), giving one
523 // unified execution path. The pool was created with max(1, threads).
525 return;
526 }
527
528 // File-based data exchange.
529 DBUG("Executing speciation with file-based data exchange.");
531 callPhreeqc();
533}
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
void writeInputsToFile(double const dt)
void executeSpeciationCalculationParallel(double const dt)

References _clamping_totals, _concentration_warning_threshold, _use_stream_mode, callPhreeqc(), DBUG(), executeSpeciationCalculationParallel(), readOutputsFromFile(), and writeInputsToFile().

◆ executeSpeciationCalculationParallel()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::executeSpeciationCalculationParallel ( double const dt)
private

Definition at line 1092 of file PhreeqcIO.cpp.

1093{
1094 INFO("Phreeqc: Executing parallel chemical calculation with {} threads.",
1096
1097 // 1. Pre-generate inputs for all chemical systems (sequential)
1098 // This must be sequential because it reads from shared data structures
1099 std::vector<std::string> inputs(_num_chemical_systems);
1100 for (std::size_t i = 0; i < _num_chemical_systems; ++i)
1101 {
1102 inputs[i] = generateInputForSystem(i, dt);
1103 }
1104
1105 // 2. Storage for outputs
1106 std::vector<std::string> outputs(_num_chemical_systems);
1107 std::vector<std::string> dumps(_num_chemical_systems);
1108
1109 // 3. Parallel execution
1110 std::vector<std::size_t> failed_systems;
1111 std::mutex failed_mutex;
1112
1113#pragma omp parallel num_threads(num_chemistry_threads_)
1114 {
1115#ifdef _OPENMP
1116 int const thread_id = omp_get_thread_num();
1117#else
1118 int const thread_id = 0;
1119#endif
1120 int const phreeqc_id = instance_pool_->getInstanceForThread(thread_id);
1121
1122#pragma omp for schedule(dynamic)
1123 for (std::ptrdiff_t i = 0;
1124 i < static_cast<std::ptrdiff_t>(_num_chemical_systems);
1125 ++i)
1126 {
1127 if (RunString(phreeqc_id, inputs[i].c_str()) != IPQ_OK)
1128 {
1129 OutputErrorString(phreeqc_id);
1130 std::lock_guard<std::mutex> guard(failed_mutex);
1131 failed_systems.push_back(i);
1132 continue;
1133 }
1134
1135 // Retrieve output string
1136 const char* output_ptr = GetSelectedOutputString(phreeqc_id);
1137 if (output_ptr)
1138 {
1139 outputs[i] = output_ptr;
1140 }
1141
1142 // Retrieve dump string if needed
1143 if (_dump)
1144 {
1145 const char* dump_ptr = GetDumpString(phreeqc_id);
1146 if (dump_ptr)
1147 {
1148 dumps[i] = dump_ptr;
1149 }
1150 }
1151 }
1152 }
1153
1154 std::exception_ptr local_error;
1155 if (!failed_systems.empty())
1156 {
1157 std::sort(failed_systems.begin(), failed_systems.end());
1158 std::string ids;
1159 for (auto const id : failed_systems)
1160 {
1161 if (!ids.empty())
1162 {
1163 ids += ", ";
1164 }
1165 ids += std::to_string(id);
1166 }
1167 local_error = std::make_exception_ptr(std::runtime_error(
1168 "Failed in performing speciation calculation for "
1169 "chemical system(s) " +
1170 ids + "."));
1171 }
1173
1174 // 4. Parse results (sequential, updates shared state)
1175 for (std::size_t i = 0; i < _num_chemical_systems; ++i)
1176 {
1177 parseOutputForSystem(outputs[i], i);
1178 }
1179
1180 // 5. Handle dump data if surfaces/exchangers exist.
1181 // Each pool instance dumped solution 1; remap to the correct system ID.
1182 if (_dump && !dumps.empty())
1183 {
1184 _dump->aqueous_solutions_prev.resize(_num_chemical_systems);
1185 for (std::size_t i = 0; i < _num_chemical_systems; ++i)
1186 {
1187 if (!dumps[i].empty())
1188 {
1189 _dump->readDumpFromStringForSystem(dumps[i], i,
1191 }
1192 }
1193 }
1194}
void parseOutputForSystem(std::string_view output_content, std::size_t chemical_system_id)
std::string generateInputForSystem(std::size_t chemical_system_id, double const dt) const
void allRanksThrowOrNone(std::exception_ptr const &exception, auto &&warning_callback)
Definition MPI.h:236
constexpr ranges::views::view_closure ids
For an element of a range view return its id.
Definition Mesh.h:223

References _dump, _num_chemical_systems, BaseLib::MPI::allRanksThrowOrNone(), generateInputForSystem(), INFO(), instance_pool_, num_chemistry_threads_, and parseOutputForSystem().

Referenced by executeSpeciationCalculation().

◆ generateInputForSystem()

std::string ChemistryLib::PhreeqcIOData::PhreeqcIO::generateInputForSystem ( std::size_t chemical_system_id,
double const dt ) const
private

Definition at line 1035 of file PhreeqcIO.cpp.

1037{
1038 std::ostringstream os;
1039 os << std::scientific
1040 << std::setprecision(std::numeric_limits<double>::max_digits10);
1041
1042 writeInputHeader(os);
1043
1044 // Each pool instance processes exactly one system with solution ID 1.
1045 // The prev_solution_id follows the same remapping convention as in file
1046 // mode: num_chemical_systems + chemical_system_id + 1.
1047 std::size_t const prev_solution_id =
1048 _num_chemical_systems + chemical_system_id + 1;
1049 writeSystemBlock(os, chemical_system_id, 1, prev_solution_id, dt);
1050
1051 // Each pool instance dumps its single solution (ID 1) for the next
1052 // timestep's dump-restore cycle.
1053 if (_dump)
1054 {
1055 os << "DUMP\n";
1056 os << "-solution 1\n";
1057 os << "END\n";
1058 }
1059
1060 return os.str();
1061}
void writeSystemBlock(std::ostream &os, std::size_t chemical_system_id, std::size_t solution_id, std::size_t prev_solution_id, double dt) const
void writeInputHeader(std::ostream &os) const

References _dump, _num_chemical_systems, writeInputHeader(), and writeSystemBlock().

Referenced by executeSpeciationCalculationParallel().

◆ getComponentList()

std::vector< std::string > const ChemistryLib::PhreeqcIOData::PhreeqcIO::getComponentList ( ) const
overridevirtual

Reimplemented from ChemistryLib::ChemicalSolverInterface.

Definition at line 966 of file PhreeqcIO.cpp.

967{
968 std::vector<std::string> component_names;
969 auto const& components = _chemical_system->aqueous_solution->components;
970 std::transform(components.begin(), components.end(),
971 std::back_inserter(component_names),
972 [](auto const& c) { return c.name; });
973
974 component_names.emplace_back("H");
975
976 return component_names;
977}

References _chemical_system.

◆ getConcentration()

double ChemistryLib::PhreeqcIOData::PhreeqcIO::getConcentration ( int const component_id,
GlobalIndexType const chemical_system_id ) const
overridevirtual

Reimplemented from ChemistryLib::ChemicalSolverInterface.

Definition at line 535 of file PhreeqcIO.cpp.

537{
538 auto const& aqueous_solution = *_chemical_system->aqueous_solution;
539 auto const& components = aqueous_solution.components;
540 auto const& H_plus_activity = aqueous_solution.H_plus_activity;
541
542 if (component_id < static_cast<int>(components.size()))
543 {
544 return components[component_id].amount[chemical_system_id];
545 }
546
547 if (component_id != static_cast<int>(components.size()))
548 {
549 OGS_FATAL(
550 "Invalid component_id {:d}: must be in [0, {:d}] "
551 "(the last index represents H+ activity).",
552 component_id, components.size());
553 }
554
555 // H+ activity 10^-pH (the transport-side state vector stores this
556 // activity for the pH "component" — see setAqueousSolution).
557 return H_plus_activity[chemical_system_id];
558}

References _chemical_system, and OGS_FATAL.

◆ initialize()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::initialize ( )
overridevirtual

◆ initializeChemicalSystemConcrete()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::initializeChemicalSystemConcrete ( std::vector< double > const & concentrations,
GlobalIndexType const & chemical_system_id,
MaterialPropertyLib::Medium const & medium,
ParameterLib::SpatialPosition const & pos,
double const t )
overridevirtual

Reimplemented from ChemistryLib::ChemicalSolverInterface.

Definition at line 436 of file PhreeqcIO.cpp.

442{
443 setAqueousSolution(concentrations, chemical_system_id,
444 *_chemical_system->aqueous_solution,
446
447 auto const& solid_phase =
449 auto const& liquid_phase =
451
452 for (auto& kinetic_reactant : _chemical_system->kinetic_reactants)
453 {
454 initializeReactantMolality(kinetic_reactant, chemical_system_id,
455 solid_phase, liquid_phase, medium, pos, t);
456 }
457
458 for (auto& equilibrium_reactant : _chemical_system->equilibrium_reactants)
459 {
460 initializeReactantMolality(equilibrium_reactant, chemical_system_id,
461 solid_phase, liquid_phase, medium, pos, t);
462 }
463
464 for (auto& exchanger : _chemical_system->exchangers)
465 {
466 initializeSiteMolality(exchanger, chemical_system_id, solid_phase, pos,
467 t);
468 }
469
470 for (auto& surface_site : _chemical_system->surface)
471 {
472 if (auto const surface_site_ptr =
473 std::get_if<MoleBasedSurfaceSite>(&surface_site))
474 {
475 initializeSiteMolality(*surface_site_ptr, chemical_system_id,
476 solid_phase, pos, t);
477 }
478 }
479}
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)
ClampingStats setAqueousSolution(std::vector< double > const &concentrations, std::size_t const chemical_system_id, AqueousSolution &aqueous_solution, double const warning_threshold)

References _chemical_system, _concentration_warning_threshold, MaterialPropertyLib::AqueousLiquid, MaterialPropertyLib::Medium::phase(), ChemistryLib::PhreeqcIOData::setAqueousSolution(), and MaterialPropertyLib::Solid.

◆ operator<<()

PhreeqcIO & ChemistryLib::PhreeqcIOData::PhreeqcIO::operator<< ( double const dt)
inlineprivate

Definition at line 230 of file PhreeqcIO.h.

231 {
232 _dt = dt;
233 return *this;
234 }

References PhreeqcIO(), and _dt.

◆ parseOutputForSystem()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::parseOutputForSystem ( std::string_view output_content,
std::size_t chemical_system_id )
private

Definition at line 1063 of file PhreeqcIO.cpp.

1065{
1066 if (output_content.empty())
1067 {
1068 OGS_FATAL("Empty output for chemical system {}.", chemical_system_id);
1069 }
1070
1071 StringViewLineIterator line_iter(output_content);
1072 std::string_view line;
1073
1074 line_iter.getline(line); // skip headline
1075
1076 int const num_skipped_lines =
1077 1 + (!_chemical_system->surface.empty() ? 1 : 0) +
1078 (!_chemical_system->exchangers.empty() ? 1 : 0);
1079 line_iter.skip(num_skipped_lines);
1080
1081 if (!line_iter.getline(line))
1082 {
1083 OGS_FATAL(
1084 "Error when reading calculation result of Solution {} after the "
1085 "reaction.",
1086 chemical_system_id);
1087 }
1088
1089 updateSystemFromOutputLine(line, chemical_system_id);
1090}
void updateSystemFromOutputLine(std::string_view line, std::size_t chemical_system_id)

References _chemical_system, OGS_FATAL, and updateSystemFromOutputLine().

Referenced by executeSpeciationCalculationParallel().

◆ readOutputsFromFile()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::readOutputsFromFile ( )
private

Definition at line 816 of file PhreeqcIO.cpp.

817{
818 auto const& basic_output_setups = _output->basic_output_setups;
819 auto const& phreeqc_result_file = basic_output_setups.output_file;
820 DBUG("Reading phreeqc results from file '{:s}'.", phreeqc_result_file);
821 std::ifstream in(phreeqc_result_file);
822
823 if (!in)
824 {
825 OGS_FATAL("Could not open phreeqc result file '{:s}'.",
826 phreeqc_result_file);
827 }
828
829 in >> *this;
830
831 if (!in)
832 {
833 OGS_FATAL("Error when reading phreeqc result file '{:s}'",
834 phreeqc_result_file);
835 }
836
837 in.close();
838}

References _output, DBUG(), and OGS_FATAL.

Referenced by executeSpeciationCalculation().

◆ setAqueousSolutionsPrevFromDumpFile()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::setAqueousSolutionsPrevFromDumpFile ( )
overridevirtual

Reimplemented from ChemistryLib::ChemicalSolverInterface.

Definition at line 560 of file PhreeqcIO.cpp.

561{
562 if (!_dump)
563 {
564 return;
565 }
566
567 auto const& dump_file = _dump->dump_file;
568 std::ifstream in(dump_file);
569 if (!in)
570 {
571 // return if phreeqc dump file doesn't exist. This happens in
572 // the first time step when no dump file is provided by the user.
573 return;
574 }
575
576 _dump->readDumpFile(in, _num_chemical_systems);
577
578 if (!in)
579 {
580 OGS_FATAL("Error when reading phreeqc dump file '{:s}'", dump_file);
581 }
582
583 in.close();
584}

References _dump, _num_chemical_systems, and OGS_FATAL.

◆ setAqueousSolutionsPrevFromDumpString()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::setAqueousSolutionsPrevFromDumpString ( std::string_view dump_content)
private

Definition at line 586 of file PhreeqcIO.cpp.

588{
589 if (!_dump)
590 {
591 return;
592 }
593
594 if (dump_content.empty())
595 {
596 // return if dump content is empty. This happens in
597 // the first time step when no dump data is available.
598 DBUG(
599 "Dump content is empty, skipping aqueous solutions initialization "
600 "from dump.");
601 return;
602 }
603
604 _dump->readDumpFromString(dump_content, _num_chemical_systems);
605}

References _dump, _num_chemical_systems, and DBUG().

◆ setChemicalSystemConcrete()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::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 )
overridevirtual

Reimplemented from ChemistryLib::ChemicalSolverInterface.

Definition at line 481 of file PhreeqcIO.cpp.

487{
488 // Accumulate clamping over all chemical systems; reported in a single
489 // aggregated message before speciation (see executeSpeciationCalculation).
490 _clamping_totals += setAqueousSolution(concentrations, chemical_system_id,
491 *_chemical_system->aqueous_solution,
493
494 auto const& solid_phase =
496 auto const& liquid_phase =
498
499 for (auto& kinetic_reactant : _chemical_system->kinetic_reactants)
500 {
501 setReactantMolality(kinetic_reactant, chemical_system_id, solid_phase,
502 liquid_phase, vars, pos, t, dt);
503 }
504
505 for (auto& equilibrium_reactant : _chemical_system->equilibrium_reactants)
506 {
507 setReactantMolality(equilibrium_reactant, chemical_system_id,
508 solid_phase, liquid_phase, vars, pos, t, dt);
509 }
510}
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)

References _chemical_system, _clamping_totals, _concentration_warning_threshold, MaterialPropertyLib::AqueousLiquid, MaterialPropertyLib::Medium::phase(), ChemistryLib::PhreeqcIOData::setAqueousSolution(), and MaterialPropertyLib::Solid.

◆ updateChemicalSystemFromOutput()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::updateChemicalSystemFromOutput ( std::vector< double > const & accepted_items,
std::size_t chemical_system_id )
private

Definition at line 840 of file PhreeqcIO.cpp.

842{
843 auto const& output = *_output;
844 auto& aqueous_solution = _chemical_system->aqueous_solution;
845 auto& components = aqueous_solution->components;
846 auto& equilibrium_reactants = _chemical_system->equilibrium_reactants;
847 auto& kinetic_reactants = _chemical_system->kinetic_reactants;
848
849 for (int item_id = 0; item_id < static_cast<int>(accepted_items.size());
850 ++item_id)
851 {
852 auto const& accepted_item = output.accepted_items[item_id];
853 auto const& item_name = accepted_item.name;
854
855 auto compare_by_name = [&item_name](auto const& item)
856 { return item.name == item_name; };
857
858 switch (accepted_item.item_type)
859 {
860 case ItemType::pH:
861 {
862 aqueous_solution->H_plus_activity[chemical_system_id] =
863 std::pow(10, -accepted_items[item_id]);
864 break;
865 }
866 case ItemType::pe:
867 {
868 (*aqueous_solution->pe)[chemical_system_id] =
869 accepted_items[item_id];
870 break;
871 }
873 {
874 auto& component = BaseLib::findElementOrError(
875 components, compare_by_name,
876 [&]()
877 {
878 OGS_FATAL("Could not find component '{:s}'.",
879 item_name);
880 });
881 component.amount[chemical_system_id] = accepted_items[item_id];
882 break;
883 }
885 {
886 auto const& equilibrium_reactant = BaseLib::findElementOrError(
887 equilibrium_reactants, compare_by_name,
888 [&]()
889 {
890 OGS_FATAL("Could not find equilibrium reactant '{:s}'",
891 item_name);
892 });
893 (*equilibrium_reactant.molality)[chemical_system_id] =
894 accepted_items[item_id];
895 break;
896 }
898 {
899 auto const& kinetic_reactant = BaseLib::findElementOrError(
900 kinetic_reactants, compare_by_name,
901 [&]()
902 {
903 OGS_FATAL("Could not find kinetic reactant '{:s}'.",
904 item_name);
905 });
906 (*kinetic_reactant.molality)[chemical_system_id] =
907 accepted_items[item_id];
908 break;
909 }
911 {
912 assert(_user_punch);
913 auto const& secondary_variables =
914 _user_punch->secondary_variables;
915 auto const& secondary_variable = BaseLib::findElementOrError(
916 secondary_variables, compare_by_name,
917 [&]()
918 {
919 OGS_FATAL("Could not find secondary variable '{:s}'.",
920 item_name);
921 });
922 (*secondary_variable.value)[chemical_system_id] =
923 accepted_items[item_id];
924 break;
925 }
926 }
927 }
928}
ranges::range_reference_t< Range > findElementOrError(Range &range, std::predicate< ranges::range_reference_t< Range > > auto &&predicate, std::invocable auto error_callback)
Definition Algorithm.h:75

References _chemical_system, _output, _user_punch, ChemistryLib::PhreeqcIOData::Component, ChemistryLib::PhreeqcIOData::EquilibriumReactant, BaseLib::findElementOrError(), ChemistryLib::PhreeqcIOData::KineticReactant, OGS_FATAL, ChemistryLib::PhreeqcIOData::pe, ChemistryLib::PhreeqcIOData::pH, and ChemistryLib::PhreeqcIOData::SecondaryVariable.

Referenced by updateSystemFromOutputLine().

◆ updatePorosityPostReaction()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::updatePorosityPostReaction ( GlobalIndexType const & ,
MaterialPropertyLib::Medium const & ,
double &  )
overridevirtual

Update porosity after chemical reactions.

This applies porosity changes caused by precipitation / dissolution in the local chemical system. The updated porosity can then be used to update flow parameters (e.g. permeability) in the next timestep.

Reimplemented from ChemistryLib::ChemicalSolverInterface.

Definition at line 998 of file PhreeqcIO.cpp.

1002{
1003 for (auto& kinetic_reactant : _chemical_system->kinetic_reactants)
1004 {
1005 setPorosityPostReaction(kinetic_reactant, chemical_system_id, medium,
1006 porosity);
1007 }
1008
1009 for (auto& equilibrium_reactant : _chemical_system->equilibrium_reactants)
1010 {
1011 setPorosityPostReaction(equilibrium_reactant, chemical_system_id,
1012 medium, porosity);
1013 }
1014}
void setPorosityPostReaction(Reactant &reactant, GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Medium const &medium, double &porosity)

References _chemical_system.

◆ updateSystemFromOutputLine()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::updateSystemFromOutputLine ( std::string_view line,
std::size_t chemical_system_id )
private

Parse one line of PHREEQC selected output and update the chemical system state. Used by both output-reading code paths (file-mode operator>> and stream-mode parseOutputForSystem()).

Definition at line 770 of file PhreeqcIO.cpp.

772{
773 auto const& output = *_output;
774 auto accepted_items = parseAndFilterChemicalData(
775 line, output.dropped_item_ids, chemical_system_id);
776 assert(accepted_items.size() == output.accepted_items.size());
777 updateChemicalSystemFromOutput(accepted_items, chemical_system_id);
778}
void updateChemicalSystemFromOutput(std::vector< double > const &accepted_items, std::size_t chemical_system_id)
std::vector< double > parseAndFilterChemicalData(std::string_view const line, std::vector< int > const &dropped_item_ids, std::size_t const chemical_system_id)

References _output, and updateChemicalSystemFromOutput().

Referenced by operator>>, and parseOutputForSystem().

◆ updateVolumeFractionPostReaction()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::updateVolumeFractionPostReaction ( GlobalIndexType const & ,
MaterialPropertyLib::Medium const & ,
ParameterLib::SpatialPosition const & ,
double const ,
double const ,
double const  )
overridevirtual

Apply mineral precipitation / dissolution to the solid fraction in OGS.

Called after executeSpeciationCalculation(). For a given chemical_system_id, this function updates the solid / mineral inventory and related volume fractions based on the PHREEQC results for the last timestep.

Typical effect:

  • change in mineral volume fraction at this location,
  • updated solid composition available to mechanics / flow.

Reimplemented from ChemistryLib::ChemicalSolverInterface.

Definition at line 979 of file PhreeqcIO.cpp.

984{
985 for (auto& kinetic_reactant : _chemical_system->kinetic_reactants)
986 {
987 updateReactantVolumeFraction(kinetic_reactant, chemical_system_id,
988 medium, pos, porosity, t, dt);
989 }
990
991 for (auto& equilibrium_reactant : _chemical_system->equilibrium_reactants)
992 {
993 updateReactantVolumeFraction(equilibrium_reactant, chemical_system_id,
994 medium, pos, porosity, t, dt);
995 }
996}
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)

References _chemical_system.

◆ writeInputHeader()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::writeInputHeader ( std::ostream & os) const
private

Write the global input header (PHASES, KNOBS, SELECTED_OUTPUT, USER_PUNCH, RATES) shared by both file and stream mode.

Definition at line 632 of file PhreeqcIO.cpp.

633{
634 bool const fixing_pe = _chemical_system->aqueous_solution->fixing_pe;
635 if (fixing_pe)
636 {
637 os << "PHASES\n"
638 << "Fix_pe\n"
639 << "e- = e-\n"
640 << "log_k 0.0\n\n";
641 }
642
643 os << _knobs << "\n";
644 os << *_output << "\n";
645
646 if (_user_punch)
647 {
648 os << *_user_punch << "\n";
649 }
650
651 if (!_reaction_rates.empty())
652 {
653 os << "RATES\n";
654 os << _reaction_rates << "\n";
655 }
656}

References _chemical_system, _knobs, _output, _reaction_rates, and _user_punch.

Referenced by generateInputForSystem(), and operator<<.

◆ writeInputsToFile()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::writeInputsToFile ( double const dt)
private

Definition at line 607 of file PhreeqcIO.cpp.

608{
609 DBUG("Writing phreeqc inputs into file '{:s}'.", _phreeqc_input_file);
610 std::ofstream out(_phreeqc_input_file, std::ofstream::out);
611
612 if (!out)
613 {
614 OGS_FATAL("Could not open file '{:s}' for writing phreeqc inputs.",
616 }
617
618 out << std::scientific
619 << std::setprecision(std::numeric_limits<double>::max_digits10);
620 *this << dt;
621 out << *this;
622
623 if (!out)
624 {
625 OGS_FATAL("Failed in generating phreeqc input file '{:s}'.",
627 }
628
629 out.close();
630}

References _phreeqc_input_file, DBUG(), and OGS_FATAL.

Referenced by executeSpeciationCalculation().

◆ writeSystemBlock()

void ChemistryLib::PhreeqcIOData::PhreeqcIO::writeSystemBlock ( std::ostream & os,
std::size_t chemical_system_id,
std::size_t solution_id,
std::size_t prev_solution_id,
double dt ) const
private

Write the per-system input block (SOLUTION, EQUILIBRIUM_PHASES, KINETICS, SURFACE, EXCHANGE).

Parameters
osOutput stream to write the PHREEQC input to.
chemical_system_idZero-based index of the chemical system (mesh node/cell) being written.
solution_idPHREEQC solution number for this system (1 in stream mode, chemical_system_id+1 in file mode).
prev_solution_idSolution number of the previous-timestep aqueous solution used for SURFACE/EXCHANGE equilibration.
dtTime step size in seconds.

Definition at line 658 of file PhreeqcIO.cpp.

663{
664 bool const fixing_pe = _chemical_system->aqueous_solution->fixing_pe;
665
666 os << "SOLUTION " << solution_id << "\n";
667 _chemical_system->aqueous_solution->print(os, chemical_system_id);
668
669 if (_dump && !_dump->aqueous_solutions_prev.empty())
670 {
671 os << _dump->aqueous_solutions_prev[chemical_system_id] << "\n\n";
672 }
673
674 os << "USE solution none\n";
675 os << "END\n\n";
676
677 os << "USE solution " << solution_id << "\n\n";
678
679 auto const& equilibrium_reactants = _chemical_system->equilibrium_reactants;
680 if (!equilibrium_reactants.empty() || fixing_pe)
681 {
682 os << "EQUILIBRIUM_PHASES " << solution_id << "\n";
683 for (auto const& r : equilibrium_reactants)
684 {
685 r.print(os, chemical_system_id);
686 }
687 fixing_pe ? os << "Fix_pe " << -_chemical_system->aqueous_solution->pe0
688 << " O2(g)\n\n"
689 : os << "\n";
690 }
691
692 auto const& kinetic_reactants = _chemical_system->kinetic_reactants;
693 if (!kinetic_reactants.empty())
694 {
695 os << "KINETICS " << solution_id << "\n";
696 for (auto const& k : kinetic_reactants)
697 {
698 k.print(os, chemical_system_id);
699 }
700 os << "-steps " << dt << "\n\n";
701 }
702
703 auto const& surface = _chemical_system->surface;
704 if (!surface.empty())
705 {
706 // To get the amount of surface species from the previous time step,
707 // an equilibration calculation with the previous aqueous solution
708 // is needed. The previous aqueous solution is saved using the
709 // PHREEQC keyword "DUMP" and stored as SOLUTION_RAW within
710 // aqueous_solutions_prev. Along with the PHREEQC keyword 'SURFACE',
711 // distinguish between the current and previous solutions via
712 // prev_solution_id.
713 os << "SURFACE " << solution_id << "\n";
714 std::size_t const aq_id =
715 (_dump && !_dump->aqueous_solutions_prev.empty()) ? prev_solution_id
716 : solution_id;
717 os << "-equilibrate with solution " << aq_id << "\n";
718
719 if (std::holds_alternative<DensityBasedSurfaceSite>(surface.front()))
720 {
721 os << "-sites_units density\n";
722 }
723 else
724 {
725 os << "-sites_units absolute\n";
726 }
727
728 for (auto const& surface_site : surface)
729 {
730 std::visit(
731 overloaded{
732 [&os](DensityBasedSurfaceSite const& s)
733 {
734 os << s.name << " " << s.site_density << " "
735 << s.specific_surface_area << " " << s.mass << "\n";
736 },
737 [&os, chemical_system_id](MoleBasedSurfaceSite const& s)
738 {
739 os << s.name << " " << (*s.molality)[chemical_system_id]
740 << "\n";
741 }},
742 surface_site);
743 }
744
745 if (std::holds_alternative<MoleBasedSurfaceSite>(surface.front()))
746 {
747 os << "-no_edl\n";
748 }
749 os << "SAVE solution " << solution_id << "\n";
750 }
751
752 auto const& exchangers = _chemical_system->exchangers;
753 if (!exchangers.empty())
754 {
755 os << "EXCHANGE " << solution_id << "\n";
756 std::size_t const aq_id =
757 (_dump && !_dump->aqueous_solutions_prev.empty()) ? prev_solution_id
758 : solution_id;
759 os << "-equilibrate with solution " << aq_id << "\n";
760 for (auto const& exchanger : exchangers)
761 {
762 exchanger.print(os, chemical_system_id);
763 }
764 os << "SAVE solution " << solution_id << "\n";
765 }
766
767 os << "END\n\n";
768}

References _chemical_system, and _dump.

Referenced by generateInputForSystem(), and operator<<.

◆ operator<<

std::ostream & operator<< ( std::ostream & os,
PhreeqcIO const & phreeqc_io )
friend

Definition at line 780 of file PhreeqcIO.cpp.

781{
782 phreeqc_io.writeInputHeader(os);
783
784 for (std::size_t chemical_system_id = 0;
785 chemical_system_id < phreeqc_io._num_chemical_systems;
786 ++chemical_system_id)
787 {
788 std::size_t const solution_id = chemical_system_id + 1;
789 std::size_t const prev_solution_id =
790 phreeqc_io._num_chemical_systems + chemical_system_id + 1;
791 phreeqc_io.writeSystemBlock(os, chemical_system_id, solution_id,
792 prev_solution_id, phreeqc_io._dt);
793 }
794
795 if (phreeqc_io._dump)
796 {
797 phreeqc_io._dump->print(os, phreeqc_io._num_chemical_systems);
798 }
799
800 return os;
801}

References PhreeqcIO(), _dt, _dump, _num_chemical_systems, writeInputHeader(), and writeSystemBlock().

◆ operator>>

std::istream & operator>> ( std::istream & in,
PhreeqcIO & phreeqc_io )
friend

Definition at line 930 of file PhreeqcIO.cpp.

931{
932 // Skip the headline
933 in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
934
935 std::string line;
936
937 auto const& surface = phreeqc_io._chemical_system->surface;
938 auto const& exchangers = phreeqc_io._chemical_system->exchangers;
939
940 int const num_skipped_lines =
941 1 + (!surface.empty() ? 1 : 0) + (!exchangers.empty() ? 1 : 0);
942
943 for (std::size_t chemical_system_id = 0;
944 chemical_system_id < phreeqc_io._num_chemical_systems;
945 ++chemical_system_id)
946 {
947 for (int i = 0; i < num_skipped_lines; ++i)
948 {
949 in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
950 }
951
952 if (!std::getline(in, line))
953 {
954 OGS_FATAL(
955 "Error when reading calculation result of Solution {:d} "
956 "after the reaction.",
957 chemical_system_id);
958 }
959
960 phreeqc_io.updateSystemFromOutputLine(line, chemical_system_id);
961 }
962
963 return in;
964}

References PhreeqcIO(), _chemical_system, _num_chemical_systems, OGS_FATAL, and updateSystemFromOutputLine().

Member Data Documentation

◆ _chemical_system

◆ _clamping_totals

ClampingStats ChemistryLib::PhreeqcIOData::PhreeqcIO::_clamping_totals
private

Negative-concentration clamping accumulated over all chemical systems within one speciation step. Folded in setChemicalSystemConcrete() and flushed (reported + reset) in executeSpeciationCalculation() so that clamping is reported once per step rather than once per cell.

Definition at line 242 of file PhreeqcIO.h.

Referenced by executeSpeciationCalculation(), and setChemicalSystemConcrete().

◆ _concentration_warning_threshold

double ChemistryLib::PhreeqcIOData::PhreeqcIO::_concentration_warning_threshold
private

Negative (or zero) warning threshold for clamped concentrations. All negative concentrations are clamped to zero unconditionally (PHREEQC rejects negatives); this only sets the value below which a clamp is reported via an aggregated WARN. Concentrations in [threshold, 0) are treated as floating-point noise and clamped silently.

Definition at line 258 of file PhreeqcIO.h.

Referenced by PhreeqcIO(), executeSpeciationCalculation(), initializeChemicalSystemConcrete(), and setChemicalSystemConcrete().

◆ _database

std::string const ChemistryLib::PhreeqcIOData::PhreeqcIO::_database
private

Definition at line 243 of file PhreeqcIO.h.

Referenced by PhreeqcIO().

◆ _dt

double ChemistryLib::PhreeqcIOData::PhreeqcIO::_dt = std::numeric_limits<double>::quiet_NaN()
private

Definition at line 251 of file PhreeqcIO.h.

Referenced by operator<<(), and operator<<.

◆ _dump

std::unique_ptr<Dump> const ChemistryLib::PhreeqcIOData::PhreeqcIO::_dump
private

◆ _knobs

Knobs const ChemistryLib::PhreeqcIOData::PhreeqcIO::_knobs
private

Definition at line 244 of file PhreeqcIO.h.

Referenced by PhreeqcIO(), and writeInputHeader().

◆ _num_chemical_systems

std::size_t ChemistryLib::PhreeqcIOData::PhreeqcIO::_num_chemical_systems = 0
private

◆ _output

std::unique_ptr<Output> const ChemistryLib::PhreeqcIOData::PhreeqcIO::_output
private

◆ _phreeqc_input_file

std::string const ChemistryLib::PhreeqcIOData::PhreeqcIO::_phreeqc_input_file

Definition at line 179 of file PhreeqcIO.h.

Referenced by PhreeqcIO(), callPhreeqc(), and writeInputsToFile().

◆ _reaction_rates

std::vector<ReactionRate> const ChemistryLib::PhreeqcIOData::PhreeqcIO::_reaction_rates
private

Definition at line 245 of file PhreeqcIO.h.

Referenced by PhreeqcIO(), and writeInputHeader().

◆ _use_stream_mode

bool ChemistryLib::PhreeqcIOData::PhreeqcIO::_use_stream_mode
private

Definition at line 268 of file PhreeqcIO.h.

Referenced by PhreeqcIO(), and executeSpeciationCalculation().

◆ _user_punch

std::unique_ptr<UserPunch> ChemistryLib::PhreeqcIOData::PhreeqcIO::_user_punch
private

◆ instance_pool_

std::unique_ptr<PhreeqcInstancePool> ChemistryLib::PhreeqcIOData::PhreeqcIO::instance_pool_
private

Definition at line 250 of file PhreeqcIO.h.

Referenced by PhreeqcIO(), and executeSpeciationCalculationParallel().

◆ num_chemistry_threads_

int ChemistryLib::PhreeqcIOData::PhreeqcIO::num_chemistry_threads_
private

Definition at line 267 of file PhreeqcIO.h.

Referenced by PhreeqcIO(), and executeSpeciationCalculationParallel().

◆ phreeqc_instance_id

int ChemistryLib::PhreeqcIOData::PhreeqcIO::phreeqc_instance_id = -1
private

ID of the standalone file-mode PHREEQC instance (independent of the parallel pool). Created by PhreeqcInstancePool::createInstance() in the ctor only in file mode; in stream mode the pool is used instead and this stays -1. It must not be hard-coded to 0 because the IPhreeqc library hands out monotonically increasing IDs and another consumer (e.g. a unit test that constructed an IPhreeqc instance earlier) may have used 0 first.

Definition at line 266 of file PhreeqcIO.h.

Referenced by PhreeqcIO(), ~PhreeqcIO(), and callPhreeqc().


The documentation for this class was generated from the following files: