OGS
CreateChemicalSolverInterface.cpp
Go to the documentation of this file.
1 
12 
13 #include <phreeqcpp/cxxKinetics.h>
14 
15 #include "BaseLib/ConfigTree.h"
16 #include "BaseLib/FileTools.h"
18 #include "MeshLib/Mesh.h"
19 #include "PhreeqcIO.h"
27 #include "PhreeqcIOData/Dump.h"
28 #include "PhreeqcIOData/Knobs.h"
30 #include "PhreeqcIOData/Surface.h"
32 #include "PhreeqcKernel.h"
38 
39 namespace
40 {
41 std::string parseDatabasePath(BaseLib::ConfigTree const& config)
42 {
43  // database
45  auto const database = config.getConfigParameter<std::string>("database");
46  auto path_to_database =
48 
49  if (!BaseLib::IsFileExisting(path_to_database))
50  {
51  OGS_FATAL("Not found the specified thermodynamicdatabase: {:s}",
52  path_to_database);
53  }
54 
55  INFO("Found the specified thermodynamic database: {:s}", path_to_database);
56 
57  return path_to_database;
58 }
59 } // namespace
60 
61 namespace ChemistryLib
62 {
63 template <>
64 std::unique_ptr<ChemicalSolverInterface>
65 createChemicalSolverInterface<ChemicalSolver::Phreeqc>(
66  std::vector<std::unique_ptr<MeshLib::Mesh>> const& meshes,
67  std::map<std::string, std::unique_ptr<GlobalLinearSolver>> const&
68  linear_solvers,
69  BaseLib::ConfigTree const& config, std::string const& output_directory)
70 {
71  auto mesh_name =
73  config.getConfigParameter<std::string>("mesh");
74 
75  // Find and extract mesh from the list of meshes.
76  auto const& mesh = *BaseLib::findElementOrError(
77  std::begin(meshes), std::end(meshes),
78  [&mesh_name](auto const& mesh)
79  {
80  assert(mesh != nullptr);
81  return mesh->getName() == mesh_name;
82  },
83  "Required mesh with name '" + mesh_name + "' not found.");
84 
85  assert(mesh.getID() != 0);
86  DBUG("Found mesh '{:s}' with id {:d}.", mesh.getName(), mesh.getID());
87 
88  auto const ls_name =
90  config.getConfigParameter<std::string>("linear_solver");
91  auto& linear_solver = BaseLib::getOrError(
92  linear_solvers, ls_name,
93  "A linear solver with the given name does not exist.");
94 
95  auto path_to_database = parseDatabasePath(config);
96 
97  // chemical system
98  auto chemical_system =
99  PhreeqcIOData::createChemicalSystem(config, *meshes[0]);
100 
101  // rates
102  auto reaction_rates = createReactionRates<PhreeqcIOData::ReactionRate>(
104  config.getConfigSubtreeOptional("rates"));
105 
106  // surface
107  auto surface = PhreeqcIOData::createSurface(
109  config.getConfigSubtreeOptional("surface"));
110 
111  // exchange
112  auto const& exchangers = chemical_system->exchangers;
113 
114  // dump
115  auto const project_file_name = BaseLib::joinPaths(
116  output_directory,
118 
119  if (!surface.empty() && !exchangers.empty())
120  {
121  OGS_FATAL(
122  "Using surface and exchange reactions simultaneously is not "
123  "supported at the moment");
124  }
125 
126  auto dump = surface.empty() && exchangers.empty()
127  ? nullptr
128  : std::make_unique<PhreeqcIOData::Dump>(project_file_name);
129 
130  // knobs
131  auto knobs = PhreeqcIOData::createKnobs(
133  config.getConfigSubtree("knobs"));
134 
135  // user punch
136  auto user_punch = PhreeqcIOData::createUserPunch(
138  config.getConfigSubtreeOptional("user_punch"), *meshes[0]);
139 
140  // output
141  auto const use_high_precision =
143  config.getConfigParameter<bool>("use_high_precision", true);
144  auto output = PhreeqcIOData::createOutput(
145  *chemical_system, user_punch, use_high_precision, project_file_name);
146 
147  return std::make_unique<PhreeqcIOData::PhreeqcIO>(
148  *linear_solver, std::move(project_file_name),
149  std::move(path_to_database), std::move(chemical_system),
150  std::move(reaction_rates), std::move(surface), std::move(user_punch),
151  std::move(output), std::move(dump), std::move(knobs));
152 }
153 
154 template <>
155 std::unique_ptr<ChemicalSolverInterface>
156 createChemicalSolverInterface<ChemicalSolver::PhreeqcKernel>(
157  std::vector<std::unique_ptr<MeshLib::Mesh>> const& meshes,
158  std::map<std::string, std::unique_ptr<GlobalLinearSolver>> const&
159  linear_solvers,
160  BaseLib::ConfigTree const& config, std::string const& /*output_directory*/)
161 {
162  auto mesh = *meshes[0];
163 
164  auto const ls_name =
166  config.getConfigParameter<std::string>("linear_solver");
167  auto& linear_solver = BaseLib::getOrError(
168  linear_solvers, ls_name,
169  "A linear solver with the given name does not exist.");
170 
171  auto path_to_database = parseDatabasePath(config);
172 
173  // TODO (renchao): remove mapping process id to component name.
174  std::vector<std::pair<int, std::string>> process_id_to_component_name_map;
175  // solution
176  auto aqueous_solution = PhreeqcKernelData::createAqueousSolution(
178  config.getConfigSubtree("solution"),
179  process_id_to_component_name_map);
180 
181  // kinetic reactants
182  auto kinetic_reactants = PhreeqcKernelData::createKineticReactants(
184  config.getConfigSubtreeOptional("kinetic_reactants"), mesh);
185 
186  // rates
187  auto reaction_rates = createReactionRates<PhreeqcKernelData::ReactionRate>(
189  config.getConfigSubtreeOptional("rates"));
190 
191  // equilibrium reactants
192  auto equilibrium_reactants = PhreeqcKernelData::createEquilibriumReactants(
194  config.getConfigSubtreeOptional("equilibrium_reactants"), mesh);
195 
196  return std::make_unique<PhreeqcKernelData::PhreeqcKernel>(
197  *linear_solver, mesh.getNumberOfBaseNodes(),
198  process_id_to_component_name_map, std::move(path_to_database),
199  std::move(aqueous_solution), std::move(equilibrium_reactants),
200  std::move(kinetic_reactants), std::move(reaction_rates));
201 }
202 } // namespace ChemistryLib
#define OGS_FATAL(...)
Definition: Error.h:26
Filename manipulation routines.
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void DBUG(char const *fmt, Args const &... args)
Definition: Logging.h:27
Definition of the Mesh class.
std::optional< ConfigTree > getConfigSubtreeOptional(std::string const &root) const
Definition: ConfigTree.cpp:155
T getConfigParameter(std::string const &param) const
ConfigTree getConfigSubtree(std::string const &root) const
Definition: ConfigTree.cpp:146
std::string const & getProjectFileName() const
Used to get the project file name.
Definition: ConfigTree.h:297
Map::mapped_type & getOrError(Map &map, Key const &key, std::string const &error_message)
Definition: Algorithm.h:147
std::string const & getProjectDirectory()
Returns the directory where the prj file resides.
Definition: FileTools.cpp:217
bool IsFileExisting(const std::string &strFilename)
Returns true if given file exists.
Definition: FileTools.cpp:43
std::string extractBaseNameWithoutExtension(std::string const &pathname)
Definition: FileTools.cpp:180
std::string joinPaths(std::string const &pathA, std::string const &pathB)
Definition: FileTools.cpp:212
std::iterator_traits< InputIt >::reference findElementOrError(InputIt begin, InputIt end, Predicate predicate, std::string const &error="")
Definition: Algorithm.h:69
std::unique_ptr< UserPunch > createUserPunch(std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh const &mesh)
std::unique_ptr< Output > createOutput(ChemicalSystem const &chemical_system, std::unique_ptr< UserPunch > const &user_punch, bool const use_high_precision, std::string const &project_file_name)
std::unique_ptr< ChemicalSystem > createChemicalSystem(BaseLib::ConfigTree const &config, MeshLib::Mesh &mesh)
Knobs createKnobs(BaseLib::ConfigTree const &config)
Definition: CreateKnobs.cpp:20
std::vector< SurfaceSite > createSurface(std::optional< BaseLib::ConfigTree > const &config)
std::unique_ptr< EquilibriumReactants > createEquilibriumReactants(std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh const &mesh)
std::unique_ptr< Kinetics > createKineticReactants(std::optional< BaseLib::ConfigTree > const &config, MeshLib::Mesh const &mesh)
AqueousSolution createAqueousSolution(BaseLib::ConfigTree const &config, std::vector< std::pair< int, std::string >> const &process_id_to_component_name_map)
std::string parseDatabasePath(BaseLib::ConfigTree const &config)