OGS
ChemistryLib::PhreeqcIOData Namespace Reference

Namespaces

namespace  anonymous_namespace{PhreeqcIO.cpp}

Classes

struct  AqueousSolution
class  BasicOutputSetups
 Controls which built-in PHREEQC columns appear in the output file. More...
struct  ChemicalSystem
 Complete description of one local reactive system passed to PHREEQC. More...
struct  Component
struct  DensityBasedSurfaceSite
struct  Dump
struct  EquilibriumReactant
struct  ExchangeSite
struct  KineticReactant
struct  Knobs
struct  MoleBasedSurfaceSite
struct  Output
 Specification of which PHREEQC output columns are imported into OpenGeoSys. More...
struct  OutputItem
 One PHREEQC output column that OpenGeoSys will keep. More...
class  PhreeqcIO
 Drives the chemistry step in the operator-split reactive transport loop. More...
struct  ReactionRate
struct  SecondaryVariable
struct  UserPunch

Enumerations

enum class  ItemType {
  pH , pe , Component , EquilibriumReactant ,
  KineticReactant , SecondaryVariable
}
 Category used to interpret a PHREEQC output column. More...

Functions

std::string specifyFileName (std::string const &project_file_name, std::string const &file_extension)
std::ostream & operator<< (std::ostream &os, PhreeqcIO const &phreeqc_io)
std::istream & operator>> (std::istream &in, PhreeqcIO &phreeqc_io)
std::unique_ptr< AqueousSolutioncreateAqueousSolution (BaseLib::ConfigTree const &config, MeshLib::Mesh &mesh)
std::unique_ptr< ChemicalSystemcreateChemicalSystem (BaseLib::ConfigTree const &config, MeshLib::Mesh &mesh)
std::vector< EquilibriumReactantcreateEquilibriumReactants (std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh &mesh)
std::vector< ExchangeSitecreateExchange (std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh &mesh)
std::vector< KineticReactantcreateKineticReactants (std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh &mesh)
Knobs createKnobs (BaseLib::ConfigTree const &config)
std::unique_ptr< OutputcreateOutput (ChemicalSystem const &chemical_system, std::unique_ptr< UserPunch > const &user_punch, bool const use_high_precision, std::string const &project_file_name)
std::vector< ComponentcreateSolutionComponents (BaseLib::ConfigTree const &config)
std::vector< std::variant< DensityBasedSurfaceSite, MoleBasedSurfaceSite > > createSurface (std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh &mesh)
std::unique_ptr< UserPunchcreateUserPunch (std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh const &mesh)
std::ostream & operator<< (std::ostream &os, Knobs const &knobs)
std::ostream & operator<< (std::ostream &os, BasicOutputSetups const &basic_output_setups)
std::ostream & operator<< (std::ostream &os, Output const &output)
std::ostream & operator<< (std::ostream &os, ReactionRate const &reaction_rate)
std::ostream & operator<< (std::ostream &os, UserPunch const &user_punch)

Enumeration Type Documentation

◆ ItemType

Category used to interpret a PHREEQC output column.

Distinguishes pH / pe, total component amounts, equilibrium-phase amounts, kinetic-phase amounts, and user-defined secondary variables.

Enumerator
pH 
pe 
Component 
EquilibriumReactant 
KineticReactant 
SecondaryVariable 

Definition at line 71 of file ChemistryLib/PhreeqcIOData/Output.h.

Function Documentation

◆ createAqueousSolution()

std::unique_ptr< AqueousSolution > ChemistryLib::PhreeqcIOData::createAqueousSolution ( BaseLib::ConfigTree const & config,
MeshLib::Mesh & mesh )
Input File Parameter
prj__chemical_system__solution__fixing_pe
Input File Parameter
prj__chemical_system__solution__temperature
Input File Parameter
prj__chemical_system__solution__pressure
Input File Parameter
prj__chemical_system__solution__pe

Definition at line 17 of file PhreeqcIOData/CreateAqueousSolution.cpp.

19{
21 auto const fixing_pe = config.getConfigAttribute<bool>("fixing_pe", false);
22
24 auto const temperature = config.getConfigParameter<double>("temperature");
25
27 auto const pressure = config.getConfigParameter<double>("pressure");
28
30 auto const pe0 = config.getConfigParameter<double>("pe");
31
34
35 auto components = createSolutionComponents(config);
36
37 auto charge_balance = createChargeBalance(config);
38
39 return std::make_unique<AqueousSolution>(fixing_pe, temperature, pressure,
40 pe, pe0, std::move(components),
41 charge_balance);
42}
std::vector< Component > createSolutionComponents(BaseLib::ConfigTree const &config)
ChargeBalance createChargeBalance(BaseLib::ConfigTree const &config)
PropertyVector< T > * getOrCreateMeshProperty(Mesh &mesh, std::string const &property_name, MeshItemType const item_type, int const number_of_components)

References ChemistryLib::createChargeBalance(), createSolutionComponents(), BaseLib::ConfigTree::getConfigAttribute(), BaseLib::ConfigTree::getConfigParameter(), MeshLib::getOrCreateMeshProperty(), MeshLib::IntegrationPoint, and pe.

Referenced by createChemicalSystem().

◆ createChemicalSystem()

std::unique_ptr< ChemicalSystem > ChemistryLib::PhreeqcIOData::createChemicalSystem ( BaseLib::ConfigTree const & config,
MeshLib::Mesh & mesh )
Input File Parameter
prj__chemical_system__solution
Input File Parameter
prj__chemical_system__kinetic_reactants
Input File Parameter
prj__chemical_system__equilibrium_reactants
Input File Parameter
prj__chemical_system__exchangers
Input File Parameter
prj__chemical_system__surface

Definition at line 22 of file CreateChemicalSystem.cpp.

24{
25 // solution
26 auto aqueous_solution = createAqueousSolution(
28 config.getConfigSubtree("solution"), mesh);
29
30 // kinetic reactants
31 auto kinetic_reactants = createKineticReactants(
33 config.getConfigSubtreeOptional("kinetic_reactants"), mesh);
34
35 // equilibrium reactants
36 auto equilibrium_reactants = createEquilibriumReactants(
38 config.getConfigSubtreeOptional("equilibrium_reactants"), mesh);
39
40 // exchangers
41 auto exchangers = createExchange(
43 config.getConfigSubtreeOptional("exchangers"), mesh);
44
45 // surface
46 auto surface = createSurface(
48 config.getConfigSubtreeOptional("surface"), mesh);
49
50 return std::make_unique<ChemicalSystem>(std::move(aqueous_solution),
51 std::move(kinetic_reactants),
52 std::move(equilibrium_reactants),
53 std::move(exchangers),
54 std::move(surface));
55}
std::vector< std::variant< DensityBasedSurfaceSite, MoleBasedSurfaceSite > > createSurface(std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh &mesh)
std::unique_ptr< AqueousSolution > createAqueousSolution(BaseLib::ConfigTree const &config, MeshLib::Mesh &mesh)
std::vector< ExchangeSite > createExchange(std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh &mesh)
std::vector< EquilibriumReactant > createEquilibriumReactants(std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh &mesh)
std::vector< KineticReactant > createKineticReactants(std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh &mesh)

References createAqueousSolution(), createEquilibriumReactants(), createExchange(), createKineticReactants(), createSurface(), BaseLib::ConfigTree::getConfigSubtree(), and BaseLib::ConfigTree::getConfigSubtreeOptional().

◆ createEquilibriumReactants()

std::vector< EquilibriumReactant > ChemistryLib::PhreeqcIOData::createEquilibriumReactants ( std::optional< BaseLib::ConfigTree > const & config,
MeshLib::Mesh & mesh )
Input File Parameter
prj__chemical_system__equilibrium_reactants__phase_component
Input File Parameter
prj__chemical_system__equilibrium_reactants__phase_component__name
Input File Parameter
prj__chemical_system__equilibrium_reactants__phase_component__saturation_index
Input File Parameter
prj__chemical_system__equilibrium_reactants__phase_component__reaction_irreversibility

Definition at line 17 of file PhreeqcIOData/CreateEquilibriumReactants.cpp.

19{
20 if (!config)
21 {
22 return {};
23 }
24
25 std::vector<EquilibriumReactant> equilibrium_reactants;
26 for (
27 auto const& equilibrium_reactant_config :
29 config->getConfigSubtreeList("phase_component"))
30 {
31 auto name =
33 equilibrium_reactant_config.getConfigParameter<std::string>("name");
34
35 double const saturation_index =
37 equilibrium_reactant_config.getConfigParameter<double>(
38 "saturation_index");
39
40 auto reaction_irreversibility =
42 equilibrium_reactant_config.getConfigParameter<std::string>(
43 "reaction_irreversibility", "");
44
45 if (!reaction_irreversibility.empty() &&
46 (reaction_irreversibility != "dissolve_only" &&
47 reaction_irreversibility != "precipitate_only"))
48 {
50 "{:s}: reaction direction only allows `dissolve_only` or "
51 "`precipitate_only`",
52 name);
53 }
54
57
59 mesh, name + "_prev", MeshLib::MeshItemType::IntegrationPoint, 1);
60
62 mesh, "phi_" + name, MeshLib::MeshItemType::IntegrationPoint, 1);
63
64 auto volume_fraction_prev = MeshLib::getOrCreateMeshProperty<double>(
65 mesh,
66 "phi_" + name + "_prev",
68 1);
69
70 auto mesh_prop_molality = MeshLib::getOrCreateMeshProperty<double>(
71 mesh, name + "_avg", MeshLib::MeshItemType::Cell, 1);
72 mesh_prop_molality->resize(mesh.getNumberOfElements());
73
74 equilibrium_reactants.emplace_back(std::move(name),
75 molality,
76 molality_prev,
77 volume_fraction,
78 volume_fraction_prev,
79 mesh_prop_molality,
80 saturation_index,
81 std::move(reaction_irreversibility));
82 }
83
84 return equilibrium_reactants;
85}
#define OGS_FATAL(...)
Definition Error.h:19
std::size_t getNumberOfElements() const
Get the number of elements.
Definition Mesh.h:89

References MeshLib::Cell, MeshLib::Mesh::getNumberOfElements(), MeshLib::getOrCreateMeshProperty(), MeshLib::IntegrationPoint, and OGS_FATAL.

Referenced by createChemicalSystem().

◆ createExchange()

std::vector< ExchangeSite > ChemistryLib::PhreeqcIOData::createExchange ( std::optional< BaseLib::ConfigTree > const & config,
MeshLib::Mesh & mesh )
Input File Parameter
prj__chemical_system__exchangers__exchange_site
Input File Parameter
prj__chemical_system__exchangers__exchange_site__ion_exchanging_species

Definition at line 15 of file CreateExchange.cpp.

17{
18 if (!config)
19 {
20 return {};
21 }
22
23 std::vector<ExchangeSite> exchangers;
24 for (auto const& site_config :
26 config->getConfigSubtreeList("exchange_site"))
27 {
29 auto name = site_config.getConfigParameter<std::string>(
30 "ion_exchanging_species");
31
32 auto const molality = MeshLib::getOrCreateMeshProperty<double>(
34
35 exchangers.emplace_back(std::move(name), molality);
36 }
37
38 return exchangers;
39}

References MeshLib::getOrCreateMeshProperty(), and MeshLib::IntegrationPoint.

Referenced by createChemicalSystem().

◆ createKineticReactants()

std::vector< KineticReactant > ChemistryLib::PhreeqcIOData::createKineticReactants ( std::optional< BaseLib::ConfigTree > const & config,
MeshLib::Mesh & mesh )
Input File Parameter
prj__chemical_system__kinetic_reactants__kinetic_reactant
Input File Parameter
prj__chemical_system__kinetic_reactants__kinetic_reactant__name
Input File Parameter
prj__chemical_system__kinetic_reactants__kinetic_reactant__chemical_formula
Input File Parameter
prj__chemical_system__kinetic_reactants__kinetic_reactant__parameters
Input File Parameter
prj__chemical_system__kinetic_reactants__kinetic_reactant__fix_amount

Definition at line 17 of file PhreeqcIOData/CreateKineticReactant.cpp.

19{
20 if (!config)
21 {
22 return {};
23 }
24
25 std::vector<KineticReactant> kinetic_reactants;
26 for (
27 auto const& reactant_config :
29 config->getConfigSubtreeList("kinetic_reactant"))
30 {
32 auto name = reactant_config.getConfigParameter<std::string>("name");
33
34 auto chemical_formula =
36 reactant_config.getConfigParameter<std::string>("chemical_formula",
37 "");
38
39 auto parameters =
41 reactant_config.getConfigParameter<std::vector<double>>(
42 "parameters", {});
43
44 bool const fix_amount =
46 reactant_config.getConfigParameter<bool>("fix_amount", false);
47
50
52 mesh, name + "_prev", MeshLib::MeshItemType::IntegrationPoint, 1);
53
55 mesh, "phi_" + name, MeshLib::MeshItemType::IntegrationPoint, 1);
56
57 auto volume_fraction_prev = MeshLib::getOrCreateMeshProperty<double>(
58 mesh,
59 "phi_" + name + "_prev",
61 1);
62
63 auto mesh_prop_molality = MeshLib::getOrCreateMeshProperty<double>(
64 mesh, name + "_avg", MeshLib::MeshItemType::Cell, 1);
65 assert(mesh_prop_molality->size() == mesh.getNumberOfElements());
66
67 kinetic_reactants.emplace_back(std::move(name),
68 std::move(chemical_formula),
69 molality,
70 molality_prev,
71 volume_fraction,
72 volume_fraction_prev,
73 mesh_prop_molality,
74 std::move(parameters),
75 fix_amount);
76 }
77
78 return kinetic_reactants;
79}

References MeshLib::Cell, MeshLib::Mesh::getNumberOfElements(), MeshLib::getOrCreateMeshProperty(), and MeshLib::IntegrationPoint.

Referenced by createChemicalSystem().

◆ createKnobs()

Knobs ChemistryLib::PhreeqcIOData::createKnobs ( BaseLib::ConfigTree const & config)
Input File Parameter
prj__chemical_system__knobs__max_iter
Input File Parameter
prj__chemical_system__knobs__relative_convergence_tolerance
Input File Parameter
prj__chemical_system__knobs__tolerance
Input File Parameter
prj__chemical_system__knobs__step_size
Input File Parameter
prj__chemical_system__knobs__scaling

Definition at line 13 of file CreateKnobs.cpp.

14{
15 auto const max_iterations =
17 config.getConfigParameter<int>("max_iter");
18
19 auto const relative_convergence_tolerance =
21 config.getConfigParameter<double>("relative_convergence_tolerance");
22
23 auto const tolerance =
25 config.getConfigParameter<double>("tolerance");
26
27 auto const step_size =
29 config.getConfigParameter<int>("step_size");
30
31 auto const scaling =
33 config.getConfigParameter<bool>("scaling");
34
35 return {max_iterations, relative_convergence_tolerance, tolerance,
36 step_size, scaling};
37}

References BaseLib::ConfigTree::getConfigParameter().

◆ createOutput()

std::unique_ptr< Output > ChemistryLib::PhreeqcIOData::createOutput ( ChemicalSystem const & chemical_system,
std::unique_ptr< UserPunch > const & user_punch,
bool const use_high_precision,
std::string const & project_file_name )

Definition at line 18 of file ChemistryLib/PhreeqcIOData/CreateOutput.cpp.

23{
24 auto const& components = chemical_system.aqueous_solution->components;
25 auto const& equilibrium_reactants = chemical_system.equilibrium_reactants;
26 auto const& kinetic_reactants = chemical_system.kinetic_reactants;
27 // Mark which phreeqc output items will be held.
28 std::vector<OutputItem> accepted_items{{"pH", ItemType::pH},
29 {"pe", ItemType::pe}};
30
31 auto accepted_item = [](auto const& item)
32 { return OutputItem(item.name, item.item_type); };
33 std::transform(components.begin(), components.end(),
34 std::back_inserter(accepted_items), accepted_item);
35 std::transform(equilibrium_reactants.begin(), equilibrium_reactants.end(),
36 std::back_inserter(accepted_items), accepted_item);
37 for (auto const& kinetic_reactant : kinetic_reactants)
38 {
39 if (kinetic_reactant.fix_amount)
40 {
41 continue;
42 }
43 accepted_items.emplace_back(kinetic_reactant.name,
44 kinetic_reactant.item_type);
45 }
46
47 if (user_punch)
48 {
49 auto const& secondary_variables = user_punch->secondary_variables;
50 accepted_items.reserve(accepted_items.size() +
51 secondary_variables.size());
52 std::transform(secondary_variables.begin(), secondary_variables.end(),
53 std::back_inserter(accepted_items), accepted_item);
54 }
55
56 // Record ids of which phreeqc output items will be dropped.
57 BasicOutputSetups basic_output_setups(project_file_name,
58 use_high_precision);
59 auto const num_dropped_basic_items =
60 basic_output_setups.getNumberOfDroppedItems();
61 std::vector<int> dropped_item_ids(num_dropped_basic_items);
62 std::iota(dropped_item_ids.begin(), dropped_item_ids.end(), 0);
63
64 auto const num_dvalue_equilibrium_reactants = equilibrium_reactants.size();
65 auto const num_dvalue_kinetic_reactants = kinetic_reactants.size();
66 int const num_dvalue_items =
67 num_dvalue_equilibrium_reactants + num_dvalue_kinetic_reactants;
68
69 auto const num_basic_items =
70 basic_output_setups.getNumberOfItemsInDisplay();
71 auto const num_components = components.size();
72 auto dvalue_item_id = num_basic_items + num_components + 1;
73 for (int i = 0; i < num_dvalue_items; ++i)
74 {
75 dropped_item_ids.push_back(dvalue_item_id);
76 dvalue_item_id += 2;
77 }
78
79 return std::make_unique<Output>(std::move(basic_output_setups),
80 std::move(accepted_items),
81 std::move(dropped_item_ids));
82}
Controls which built-in PHREEQC columns appear in the output file.
One PHREEQC output column that OpenGeoSys will keep.

References ChemistryLib::PhreeqcIOData::ChemicalSystem::aqueous_solution, ChemistryLib::PhreeqcIOData::ChemicalSystem::equilibrium_reactants, ChemistryLib::PhreeqcIOData::BasicOutputSetups::getNumberOfDroppedItems(), ChemistryLib::PhreeqcIOData::BasicOutputSetups::getNumberOfItemsInDisplay(), ChemistryLib::PhreeqcIOData::ChemicalSystem::kinetic_reactants, pe, and pH.

◆ createSolutionComponents()

std::vector< Component > ChemistryLib::PhreeqcIOData::createSolutionComponents ( BaseLib::ConfigTree const & config)
Input File Parameter
prj__chemical_system__solution__components
Input File Parameter
prj__chemical_system__solution__components__component
Input File Parameter
prj__chemical_system__solution__components__component__chemical_formula

Definition at line 13 of file CreateSolutionComponent.cpp.

15{
16 std::vector<Component> components;
18 auto components_config = config.getConfigSubtree("components");
19
20 for (
21 auto const& component_config :
23 components_config.getConfigSubtreeList("component"))
24 {
25 auto const component_name = component_config.getValue<std::string>();
26 auto const chemical_formula =
28 component_config.getConfigAttribute<std::string>("chemical_formula",
29 "");
30 components.emplace_back(component_name, chemical_formula);
31 }
32
33 return components;
34}

References BaseLib::ConfigTree::getConfigSubtree().

Referenced by createAqueousSolution().

◆ createSurface()

std::vector< std::variant< DensityBasedSurfaceSite, MoleBasedSurfaceSite > > ChemistryLib::PhreeqcIOData::createSurface ( std::optional< BaseLib::ConfigTree > const & config,
MeshLib::Mesh & mesh )
Input File Parameter
prj__chemical_system__surface__site_unit
Input File Parameter
prj__chemical_system__surface__site
Input File Parameter
prj__chemical_system__surface__site__name
Input File Parameter
prj__chemical_system__surface__site__site_density
Input File Parameter
prj__chemical_system__surface__site__specific_surface_area
Input File Parameter
prj__chemical_system__surface__site__mass
Input File Parameter
prj__chemical_system__surface__site
Input File Parameter
prj__chemical_system__surface__site__name

Definition at line 16 of file CreateSurface.cpp.

18{
19 if (!config)
20 {
21 return {};
22 }
23
24 std::vector<std::variant<DensityBasedSurfaceSite, MoleBasedSurfaceSite>>
25 surface;
26
27 auto const surface_site_unit =
29 config->getConfigAttribute<std::string>("site_unit", "mole");
30
31 if (surface_site_unit == "density")
32 {
33 for (auto const& site_config :
35 config->getConfigSubtreeList("site"))
36 {
38 auto name = site_config.getConfigParameter<std::string>("name");
39
40 auto const site_density =
42 site_config.getConfigParameter<double>("site_density");
43
44 auto const specific_surface_area =
46 site_config.getConfigParameter<double>("specific_surface_area");
47
48 auto const mass =
50 site_config.getConfigParameter<double>("mass");
51
52 surface.push_back(DensityBasedSurfaceSite(
53 std::move(name), site_density, specific_surface_area, mass));
54 }
55
56 return surface;
57 }
58
59 if (surface_site_unit == "mole")
60 {
61 for (auto const& site_config :
63 config->getConfigSubtreeList("site"))
64 {
66 auto name = site_config.getConfigParameter<std::string>("name");
67
70
71 surface.push_back(MoleBasedSurfaceSite(std::move(name), molality));
72 }
73
74 return surface;
75 }
76
77 OGS_FATAL("Surface site unit should be either of 'density' or 'mole'.");
78}

References MeshLib::getOrCreateMeshProperty(), MeshLib::IntegrationPoint, and OGS_FATAL.

Referenced by createChemicalSystem().

◆ createUserPunch()

std::unique_ptr< UserPunch > ChemistryLib::PhreeqcIOData::createUserPunch ( std::optional< BaseLib::ConfigTree > const & config,
MeshLib::Mesh const & mesh )
Input File Parameter
prj__chemical_system__user_punch__headline
Input File Parameter
prj__chemical_system__user_punch__statement

Definition at line 15 of file CreateUserPunch.cpp.

17{
18 if (!config)
19 {
20 return nullptr;
21 }
22
23 std::vector<SecondaryVariable> secondary_variables;
24 for (auto const& variable_name :
26 config->getConfigParameter<std::vector<std::string>>("headline"))
27 {
29 const_cast<MeshLib::Mesh&>(mesh),
30 variable_name,
32 1);
33 std::fill(std::begin(*value),
34 std::end(*value),
35 std::numeric_limits<double>::quiet_NaN());
36
37 secondary_variables.emplace_back(variable_name, value);
38 }
39
40 std::vector<std::string> statements;
41 for (auto const& statement :
43 config->getConfigParameterList<std::string>("statement"))
44 {
45 statements.emplace_back(statement);
46 }
47
48 return std::make_unique<UserPunch>(std::move(secondary_variables),
49 std::move(statements));
50}

References MeshLib::getOrCreateMeshProperty(), and MeshLib::IntegrationPoint.

◆ operator<<() [1/6]

std::ostream & ChemistryLib::PhreeqcIOData::operator<< ( std::ostream & os,
BasicOutputSetups const & basic_output_setups )

Definition at line 39 of file ChemistryLib/PhreeqcIOData/Output.cpp.

41{
42 os << "SELECTED_OUTPUT"
43 << "\n";
44 os << "-file " << basic_output_setups.output_file << "\n";
45 os << "-high_precision " << std::boolalpha
46 << basic_output_setups.use_high_precision << "\n";
47 os << "-simulation " << std::boolalpha
49 os << "-state " << std::boolalpha << BasicOutputSetups::display_state
50 << "\n";
51 os << "-distance " << std::boolalpha << BasicOutputSetups::display_distance
52 << "\n";
53 os << "-time " << std::boolalpha << BasicOutputSetups::display_current_time
54 << "\n";
55 os << "-step " << std::boolalpha << BasicOutputSetups::display_time_step
56 << "\n";
57
58 return os;
59}

◆ operator<<() [2/6]

std::ostream & ChemistryLib::PhreeqcIOData::operator<< ( std::ostream & os,
Knobs const & knobs )

Definition at line 12 of file Knobs.cpp.

13{
14 os << "KNOBS"
15 << "\n";
16 os << "-iterations " << knobs.max_iterations << "\n";
17 os << "-convergence_tolerance " << knobs.relative_convergence_tolerance
18 << "\n";
19 os << "-tolerance " << knobs.tolerance << "\n";
20 os << "-step_size " << knobs.step_size << "\n";
21 os << "-diagonal_scale " << knobs.scaling << "\n";
22
23 return os;
24}

◆ operator<<() [3/6]

std::ostream & ChemistryLib::PhreeqcIOData::operator<< ( std::ostream & os,
Output const & output )

Definition at line 61 of file ChemistryLib/PhreeqcIOData/Output.cpp.

62{
63 os << output.basic_output_setups;
64
65 auto const component_items =
66 output.getOutputItemsByItemType(ItemType::Component);
67 os << "-totals";
68 for (auto const& component_item : component_items)
69 {
70 os << " " << component_item.name;
71 }
72 os << "\n";
73
74 auto const equilibrium_phase_items =
75 output.getOutputItemsByItemType(ItemType::EquilibriumReactant);
76 if (!equilibrium_phase_items.empty())
77 {
78 os << "-equilibrium_phases";
79 for (auto const& equilibrium_phase_item : equilibrium_phase_items)
80 {
81 os << " " << equilibrium_phase_item.name;
82 }
83 os << "\n";
84 }
85
86 auto const kinetic_reactant_items =
87 output.getOutputItemsByItemType(ItemType::KineticReactant);
88 if (!kinetic_reactant_items.empty())
89 {
90 os << "-kinetic_reactants";
91 for (auto const& kinetic_reactant_item : kinetic_reactant_items)
92 {
93 os << " " << kinetic_reactant_item.name;
94 }
95 os << "\n";
96 }
97
98 return os;
99}

◆ operator<<() [4/6]

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

Definition at line 711 of file PhreeqcIO.cpp.

712{
713 bool const fixing_pe =
714 phreeqc_io._chemical_system->aqueous_solution->fixing_pe;
715 if (fixing_pe)
716 {
717 os << "PHASES\n"
718 << "Fix_pe\n"
719 << "e- = e-\n"
720 << "log_k 0.0\n\n";
721 }
722
723 os << phreeqc_io._knobs << "\n";
724
725 os << *phreeqc_io._output << "\n";
726
727 auto const& user_punch = phreeqc_io._user_punch;
728 if (user_punch)
729 {
730 os << *user_punch << "\n";
731 }
732
733 auto const& reaction_rates = phreeqc_io._reaction_rates;
734 if (!reaction_rates.empty())
735 {
736 os << "RATES\n";
737 os << reaction_rates << "\n";
738 }
739
740 for (std::size_t chemical_system_id = 0;
741 chemical_system_id < phreeqc_io._num_chemical_systems;
742 ++chemical_system_id)
743 {
744 os << "SOLUTION " << chemical_system_id + 1 << "\n";
745 phreeqc_io._chemical_system->aqueous_solution->print(
746 os, chemical_system_id);
747
748 auto const& dump = phreeqc_io._dump;
749 if (dump)
750 {
751 auto const& aqueous_solutions_prev = dump->aqueous_solutions_prev;
752 // Print previous aqueous solution if it exists.
753 if (!aqueous_solutions_prev.empty())
754 {
755 os << aqueous_solutions_prev[chemical_system_id] << "\n\n";
756 }
757 }
758
759 os << "USE solution none\n";
760 os << "END\n\n";
761
762 os << "USE solution " << chemical_system_id + 1 << "\n\n";
763
764 auto const& equilibrium_reactants =
765 phreeqc_io._chemical_system->equilibrium_reactants;
766 if (!equilibrium_reactants.empty() || fixing_pe)
767 {
768 os << "EQUILIBRIUM_PHASES " << chemical_system_id + 1 << "\n";
769 for (auto const& equilibrium_reactant : equilibrium_reactants)
770 {
771 equilibrium_reactant.print(os, chemical_system_id);
772 }
773 fixing_pe
774 ? os << "Fix_pe "
775 << -phreeqc_io._chemical_system->aqueous_solution->pe0
776 << " O2(g)\n\n"
777 : os << "\n";
778 }
779
780 auto const& kinetic_reactants =
781 phreeqc_io._chemical_system->kinetic_reactants;
782 if (!kinetic_reactants.empty())
783 {
784 os << "KINETICS " << chemical_system_id + 1 << "\n";
785 for (auto const& kinetic_reactant : kinetic_reactants)
786 {
787 kinetic_reactant.print(os, chemical_system_id);
788 }
789 os << "-steps " << phreeqc_io._dt << "\n\n";
790 }
791
792 auto const& surface = phreeqc_io._chemical_system->surface;
793 if (!surface.empty())
794 {
795 // To get the amount of surface species from the previous time step,
796 // an equilibration calculation with the previous aqueous solution
797 // is needed. The previous aqueous solution is saved using the
798 // PHREEQC keyword "DUMP" in the dump file and then stored as
799 // SOLUTION_RAW within aqueous_solutions_prev. Along with the
800 // PHREEQC keyword 'SURFACE', distinguish between the current and
801 // previous solutions, the previous solution number is added to the
802 // total number of chemical systems (_num_chemical_systems).
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
807 : phreeqc_io._num_chemical_systems + chemical_system_id + 1;
808 os << "-equilibrate with solution " << aqueous_solution_id << "\n";
809
810 // print unit
811 if (std::holds_alternative<DensityBasedSurfaceSite>(
812 surface.front()))
813 {
814 os << "-sites_units density\n";
815 }
816 else
817 {
818 os << "-sites_units absolute\n";
819 }
820
821 for (auto const& surface_site : surface)
822 {
823 std::visit(
824 overloaded{[&os](DensityBasedSurfaceSite const& s)
825 {
826 os << s.name << " " << s.site_density << " "
827 << s.specific_surface_area << " "
828 << s.mass << "\n";
829 },
830 [&os, chemical_system_id](
831 MoleBasedSurfaceSite const& s) {
832 os << s.name << " "
833 << (*s.molality)[chemical_system_id]
834 << "\n";
835 }},
836 surface_site);
837 }
838
839 // overlook the effect of the buildup of charges onto the surface
840 if (std::holds_alternative<MoleBasedSurfaceSite>(surface.front()))
841 {
842 os << "-no_edl\n";
843 }
844 // Here the PHREEQC "save" command is printed to save the solution
845 // internally in PHREEQC. The solution composition is saved after
846 // equilibration with the surface has been completed. The solution
847 // will not be saved for use in the next PHREEQC run.
848 os << "SAVE solution " << chemical_system_id + 1 << "\n";
849 }
850
851 auto const& exchangers = phreeqc_io._chemical_system->exchangers;
852 if (!exchangers.empty())
853 {
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
858 : phreeqc_io._num_chemical_systems + chemical_system_id + 1;
859 os << "-equilibrate with solution " << aqueous_solution_id << "\n";
860 for (auto const& exchanger : exchangers)
861 {
862 exchanger.print(os, chemical_system_id);
863 }
864 os << "SAVE solution " << chemical_system_id + 1 << "\n";
865 }
866
867 os << "END\n\n";
868 }
869
870 auto const& dump = phreeqc_io._dump;
871 if (dump)
872 {
873 dump->print(os, phreeqc_io._num_chemical_systems);
874 }
875
876 return os;
877}

◆ operator<<() [5/6]

std::ostream & ChemistryLib::PhreeqcIOData::operator<< ( std::ostream & os,
ReactionRate const & reaction_rate )

Definition at line 12 of file PhreeqcIOData/ReactionRate.cpp.

13{
14 os << reaction_rate.kinetic_reactant << "\n";
15 os << "-start"
16 << "\n";
17 int line_number = 1;
18 for (auto const& expression_statement : reaction_rate.expression_statements)
19 {
20 os << line_number << " " << expression_statement << "\n";
21 ++line_number;
22 }
23 os << "-end"
24 << "\n";
25
26 return os;
27}

◆ operator<<() [6/6]

std::ostream & ChemistryLib::PhreeqcIOData::operator<< ( std::ostream & os,
UserPunch const & user_punch )

Definition at line 20 of file UserPunch.cpp.

21{
22 os << "USER_PUNCH"
23 << "\n";
24 os << "-headings ";
25 auto const& secondary_variables = user_punch.secondary_variables;
26 for (auto const& secondary_variable : secondary_variables)
27 {
28 os << secondary_variable.name << " ";
29 }
30 os << "\n";
31
32 os << "-start"
33 << "\n";
34 int line_number = 1;
35 for (auto const& statement : user_punch.statements)
36 {
37 os << line_number << " " << statement << "\n";
38 ++line_number;
39 }
40 os << "-end"
41 << "\n";
42
43 return os;
44}

◆ operator>>()

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

Definition at line 1113 of file PhreeqcIO.cpp.

1114{
1115 // Skip the headline
1116 in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
1117
1118 std::string line;
1119 auto const& output = *phreeqc_io._output;
1120 auto const& dropped_item_ids = output.dropped_item_ids;
1121
1122 auto const& surface = phreeqc_io._chemical_system->surface;
1123 auto const& exchangers = phreeqc_io._chemical_system->exchangers;
1124
1125 int const num_skipped_lines =
1126 1 + (!surface.empty() ? 1 : 0) + (!exchangers.empty() ? 1 : 0);
1127
1128 auto& equilibrium_reactants =
1129 phreeqc_io._chemical_system->equilibrium_reactants;
1130 auto& kinetic_reactants = phreeqc_io._chemical_system->kinetic_reactants;
1131
1132 for (std::size_t chemical_system_id = 0;
1133 chemical_system_id < phreeqc_io._num_chemical_systems;
1134 ++chemical_system_id)
1135 {
1136 // Skip equilibrium calculation result of initial solution
1137 for (int i = 0; i < num_skipped_lines; ++i)
1138 {
1139 in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
1140 }
1141
1142 // Get calculation result of the solution after the reaction
1143 if (!std::getline(in, line))
1144 {
1145 OGS_FATAL(
1146 "Error when reading calculation result of Solution {:d} "
1147 "after the reaction.",
1148 chemical_system_id);
1149 }
1150
1151 auto accepted_items = parseAndFilterChemicalData(line, dropped_item_ids,
1152 chemical_system_id);
1153 assert(accepted_items.size() == output.accepted_items.size());
1154
1155 auto& aqueous_solution = phreeqc_io._chemical_system->aqueous_solution;
1156 auto& components = aqueous_solution->components;
1157 auto& user_punch = phreeqc_io._user_punch;
1158
1159 GlobalIndexType const offset = aqueous_solution->pH->getRangeBegin();
1160 GlobalIndexType const global_index = offset + chemical_system_id;
1161
1162 for (int item_id = 0; item_id < static_cast<int>(accepted_items.size());
1163 ++item_id)
1164 {
1165 auto const& accepted_item = output.accepted_items[item_id];
1166 auto const& item_name = accepted_item.name;
1167
1168 auto compare_by_name = [&item_name](auto const& item)
1169 { return item.name == item_name; };
1170
1171 switch (accepted_item.item_type)
1172 {
1173 case ItemType::pH:
1174 {
1175 // Update pH value
1177 *aqueous_solution->pH);
1178 aqueous_solution->pH->set(
1179 global_index, std::pow(10, -accepted_items[item_id]));
1180 break;
1181 }
1182 case ItemType::pe:
1183 {
1184 // Update pe value
1185 (*aqueous_solution->pe)[chemical_system_id] =
1186 accepted_items[item_id];
1187 break;
1188 }
1190 {
1191 // Update component concentrations
1192 auto const& component = BaseLib::findElementOrError(
1193 components, compare_by_name,
1194 [&]() {
1195 OGS_FATAL("Could not find component '{:s}'.",
1196 item_name);
1197 });
1199 *component.amount);
1200 component.amount->set(global_index,
1201 accepted_items[item_id]);
1202 break;
1203 }
1205 {
1206 // Update amounts of equilibrium reactant
1207 auto const& equilibrium_reactant =
1209 equilibrium_reactants, compare_by_name,
1210 [&]()
1211 {
1212 OGS_FATAL(
1213 "Could not find equilibrium reactant "
1214 "'{:s}'",
1215 item_name);
1216 });
1217 (*equilibrium_reactant.molality)[chemical_system_id] =
1218 accepted_items[item_id];
1219 break;
1220 }
1222 {
1223 // Update amounts of kinetic reactants
1224 auto const& kinetic_reactant = BaseLib::findElementOrError(
1225 kinetic_reactants, compare_by_name,
1226 [&]() {
1227 OGS_FATAL("Could not find kinetic reactant '{:s}'.",
1228 item_name);
1229 });
1230 (*kinetic_reactant.molality)[chemical_system_id] =
1231 accepted_items[item_id];
1232 break;
1233 }
1235 {
1236 assert(user_punch);
1237 auto const& secondary_variables =
1238 user_punch->secondary_variables;
1239 // Update values of secondary variables
1240 auto const& secondary_variable =
1242 secondary_variables, compare_by_name,
1243 [&]() {
1244 OGS_FATAL(
1245 "Could not find secondary variable '{:s}'.",
1246 item_name);
1247 });
1248 (*secondary_variable.value)[chemical_system_id] =
1249 accepted_items[item_id];
1250 break;
1251 }
1252 }
1253 }
1254 }
1255
1256 return in;
1257}
GlobalMatrix::IndexType GlobalIndexType
std::unique_ptr< ChemicalSystem > _chemical_system
Definition PhreeqcIO.h:201
std::unique_ptr< UserPunch > _user_punch
Definition PhreeqcIO.h:203
std::unique_ptr< Output > const _output
Definition PhreeqcIO.h:204
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:74
void setLocalAccessibleVector(PETScVector const &x)
Definition LinAlg.cpp:20

◆ specifyFileName()

std::string ChemistryLib::PhreeqcIOData::specifyFileName ( std::string const & project_file_name,
std::string const & file_extension )
extern

Definition at line 18 of file ChemistryLib/PhreeqcIOData/Output.cpp.

20{
21#ifdef USE_PETSC
22 int mpi_rank;
23
24 MPI_Comm_rank(BaseLib::MPI::OGS_COMM_WORLD, &mpi_rank);
25 return project_file_name + "_phreeqc_pid_" + std::to_string(mpi_rank) +
26 file_extension;
27#endif
28
29 return project_file_name + "_phreeqc" + file_extension;
30}
MPI_Comm OGS_COMM_WORLD
Definition MPI.cpp:9

References BaseLib::MPI::OGS_COMM_WORLD.

Referenced by ChemistryLib::PhreeqcIOData::BasicOutputSetups::BasicOutputSetups(), ChemistryLib::PhreeqcIOData::Dump::Dump(), and ChemistryLib::PhreeqcIOData::PhreeqcIO::PhreeqcIO().