OGS
PhreeqcIO.cpp
Go to the documentation of this file.
1 
11 #include "PhreeqcIO.h"
12 
13 #include <IPhreeqc.h>
14 
15 #include <boost/algorithm/string.hpp>
16 #include <cmath>
17 #include <fstream>
18 #include <iomanip>
19 #include <numeric>
20 
21 #include "BaseLib/Algorithm.h"
22 #include "BaseLib/ConfigTreeUtil.h"
23 #include "MaterialLib/MPL/Medium.h"
25 #include "MathLib/LinAlg/LinAlg.h"
26 #include "MeshLib/Mesh.h"
29 #include "PhreeqcIOData/Dump.h"
31 #include "PhreeqcIOData/Exchange.h"
33 #include "PhreeqcIOData/Knobs.h"
34 #include "PhreeqcIOData/Output.h"
36 #include "PhreeqcIOData/Surface.h"
38 
39 namespace ChemistryLib
40 {
41 namespace PhreeqcIOData
42 {
43 namespace
44 {
45 template <typename DataBlock>
46 std::ostream& operator<<(std::ostream& os,
47  std::vector<DataBlock> const& data_blocks)
48 {
49  std::copy(data_blocks.begin(), data_blocks.end(),
50  std::ostream_iterator<DataBlock>(os));
51  return os;
52 }
53 
54 void setAqueousSolution(std::vector<double> const& concentrations,
55  GlobalIndexType const& chemical_system_id,
56  AqueousSolution& aqueous_solution)
57 {
58  // components
59  auto& components = aqueous_solution.components;
60  for (unsigned component_id = 0; component_id < components.size();
61  ++component_id)
62  {
63  components[component_id].amount->set(chemical_system_id,
64  concentrations[component_id]);
65  }
66 
67  // pH
68  aqueous_solution.pH->set(chemical_system_id, concentrations.back());
69 }
70 
71 template <typename Reactant>
72 void initializeReactantMolality(Reactant& reactant,
73  GlobalIndexType const& chemical_system_id,
74  MaterialPropertyLib::Phase const& solid_phase,
75  MaterialPropertyLib::Phase const& liquid_phase,
76  MaterialPropertyLib::Medium const& medium,
78  double const t)
79 {
80  auto const& solid_constituent = solid_phase.component(reactant.name);
81 
82  if (solid_constituent.hasProperty(
84  {
85  auto const molality =
87  .template initialValue<double>(pos, t);
88 
89  (*reactant.molality)[chemical_system_id] = molality;
90  (*reactant.molality_prev)[chemical_system_id] = molality;
91  }
92  else
93  {
94  auto const volume_fraction =
95  solid_constituent
97  .template initialValue<double>(pos, t);
98 
99  (*reactant.volume_fraction)[chemical_system_id] = volume_fraction;
100 
101  (*reactant.volume_fraction_prev)[chemical_system_id] = volume_fraction;
102 
103  auto const fluid_density =
105  .template initialValue<double>(pos, t);
106 
107  auto const porosity =
109  .template initialValue<double>(pos, t);
110 
111  auto const molar_volume =
113  .template initialValue<double>(pos, t);
114 
115  (*reactant.molality)[chemical_system_id] =
117 
118  (*reactant.molality_prev)[chemical_system_id] =
119  (*reactant.molality)[chemical_system_id];
120  }
121 }
122 
123 template <typename Reactant>
124 void setReactantMolality(Reactant& reactant,
125  GlobalIndexType const& chemical_system_id,
126  MaterialPropertyLib::Phase const& solid_phase,
127  MaterialPropertyLib::Phase const& liquid_phase,
130  double const t, double const dt)
131 {
132  auto const& solid_constituent = solid_phase.component(reactant.name);
133 
134  if (solid_constituent.hasProperty(
136  {
137  (*reactant.molality_prev)[chemical_system_id] =
138  (*reactant.molality)[chemical_system_id];
139 
140  return;
141  }
142 
143  auto const volume_fraction =
144  (*reactant.volume_fraction)[chemical_system_id];
145 
146  (*reactant.volume_fraction_prev)[chemical_system_id] =
147  (*reactant.volume_fraction)[chemical_system_id];
148 
149  auto const fluid_density =
151  .template value<double>(vars, pos, t, dt);
152 
153  auto const porosity = std::get<double>(
154  vars[static_cast<int>(MaterialPropertyLib::Variable::porosity)]);
155 
156  auto const molar_volume =
158  .template value<double>(vars, pos, t, dt);
159 
160  (*reactant.molality)[chemical_system_id] =
162 
163  (*reactant.molality_prev)[chemical_system_id] =
164  (*reactant.molality)[chemical_system_id];
165 }
166 
167 template <typename Exchanger>
168 void initializeExchangerMolality(Exchanger& exchanger,
169  GlobalIndexType const& chemical_system_id,
170  MaterialPropertyLib::Phase const& solid_phase,
172  double const t)
173 {
174  auto const& solid_constituent = solid_phase.component(exchanger.name);
175 
176  auto const molality =
178  .template initialValue<double>(pos, t);
179 
180  (*exchanger.molality)[chemical_system_id] = molality;
181 }
182 
183 template <typename Reactant>
184 void updateReactantVolumeFraction(Reactant& reactant,
185  GlobalIndexType const& chemical_system_id,
186  MaterialPropertyLib::Medium const& medium,
188  double const porosity, double const t,
189  double const dt)
190 {
191  auto const& solid_phase = medium.phase("Solid");
192  auto const& liquid_phase = medium.phase("AqueousLiquid");
193 
195 
196  auto const liquid_density =
198  .template value<double>(vars, pos, t, dt);
199 
200  auto const& solid_constituent = solid_phase.component(reactant.name);
201 
202  if (solid_constituent.hasProperty(
204  {
205  return;
206  }
207 
208  auto const molar_volume =
210  .template value<double>(vars, pos, t, dt);
211 
212  (*reactant.volume_fraction)[chemical_system_id] +=
213  ((*reactant.molality)[chemical_system_id] -
214  (*reactant.molality_prev)[chemical_system_id]) *
215  liquid_density * porosity * molar_volume;
216 }
217 
218 template <typename Reactant>
219 void setPorosityPostReaction(Reactant& reactant,
220  GlobalIndexType const& chemical_system_id,
221  MaterialPropertyLib::Medium const& medium,
222  double& porosity)
223 {
224  auto const& solid_phase = medium.phase("Solid");
225 
226  auto const& solid_constituent = solid_phase.component(reactant.name);
227 
228  if (solid_constituent.hasProperty(
230  {
231  return;
232  }
233 
234  porosity -= ((*reactant.volume_fraction)[chemical_system_id] -
235  (*reactant.volume_fraction_prev)[chemical_system_id]);
236 }
237 
238 template <typename Reactant>
240  Reactant const& reactant,
241  std::vector<GlobalIndexType> const& chemical_system_indices)
242 {
243  double const sum = std::accumulate(
244  chemical_system_indices.begin(), chemical_system_indices.end(), 0.0,
245  [&](double const s, GlobalIndexType const id)
246  { return s + (*reactant.molality)[id]; });
247  return sum / chemical_system_indices.size();
248 }
249 } // namespace
250 
252  std::string const& project_file_name,
253  std::string&& database,
254  std::unique_ptr<ChemicalSystem>&& chemical_system,
255  std::vector<ReactionRate>&& reaction_rates,
256  std::vector<SurfaceSite>&& surface,
257  std::unique_ptr<UserPunch>&& user_punch,
258  std::unique_ptr<Output>&& output,
259  std::unique_ptr<Dump>&& dump,
260  Knobs&& knobs)
261  : ChemicalSolverInterface(linear_solver),
262  _phreeqc_input_file(project_file_name + "_phreeqc.inp"),
263  _database(std::move(database)),
264  _chemical_system(std::move(chemical_system)),
265  _reaction_rates(std::move(reaction_rates)),
266  _surface(std::move(surface)),
267  _user_punch(std::move(user_punch)),
268  _output(std::move(output)),
269  _dump(std::move(dump)),
270  _knobs(std::move(knobs))
271 {
272  // initialize phreeqc instance
273  if (CreateIPhreeqc() != phreeqc_instance_id)
274  {
275  OGS_FATAL(
276  "Failed to initialize phreeqc instance, due to lack of memory.");
277  }
278 
279  // load specified thermodynamic database
280  if (LoadDatabase(phreeqc_instance_id, _database.c_str()) != IPQ_OK)
281  {
282  OGS_FATAL(
283  "Failed in loading the specified thermodynamic database file: "
284  "{:s}.",
285  _database);
286  }
287 
288  if (SetSelectedOutputFileOn(phreeqc_instance_id, 1) != IPQ_OK)
289  {
290  OGS_FATAL(
291  "Failed to fly the flag for the specified file {:s} where phreeqc "
292  "will write output.",
293  _output->basic_output_setups.output_file);
294  }
295 
296  if (_dump)
297  {
298  // Chemical composition of the aqueous solution of last time step will
299  // be written into .dmp file once the second function argument is set to
300  // one.
301  SetDumpFileOn(phreeqc_instance_id, 1);
302  }
303 }
304 
306 {
308 
310 
311  if (_user_punch)
312  {
313  _user_punch->initialize(_num_chemical_systems);
314  }
315 }
316 
318  std::vector<double> const& concentrations,
319  GlobalIndexType const& chemical_system_id,
320  MaterialPropertyLib::Medium const& medium,
322  double const t)
323 {
324  setAqueousSolution(concentrations, chemical_system_id,
325  *_chemical_system->aqueous_solution);
326 
327  auto const& solid_phase = medium.phase("Solid");
328  auto const& liquid_phase = medium.phase("AqueousLiquid");
329 
330  for (auto& kinetic_reactant : _chemical_system->kinetic_reactants)
331  {
332  initializeReactantMolality(kinetic_reactant, chemical_system_id,
333  solid_phase, liquid_phase, medium, pos, t);
334  }
335 
336  for (auto& equilibrium_reactant : _chemical_system->equilibrium_reactants)
337  {
338  initializeReactantMolality(equilibrium_reactant, chemical_system_id,
339  solid_phase, liquid_phase, medium, pos, t);
340  }
341 
342  for (auto& exchanger : _chemical_system->exchangers)
343  {
344  initializeExchangerMolality(exchanger, chemical_system_id, solid_phase,
345  pos, t);
346  }
347 }
348 
350  std::vector<double> const& concentrations,
351  GlobalIndexType const& chemical_system_id,
352  MaterialPropertyLib::Medium const* medium,
354  ParameterLib::SpatialPosition const& pos, double const t, double const dt)
355 {
356  setAqueousSolution(concentrations, chemical_system_id,
357  *_chemical_system->aqueous_solution);
358 
359  auto const& solid_phase = medium->phase("Solid");
360  auto const& liquid_phase = medium->phase("AqueousLiquid");
361 
362  for (auto& kinetic_reactant : _chemical_system->kinetic_reactants)
363  {
364  setReactantMolality(kinetic_reactant, chemical_system_id, solid_phase,
365  liquid_phase, vars, pos, t, dt);
366  }
367 
368  for (auto& equilibrium_reactant : _chemical_system->equilibrium_reactants)
369  {
370  setReactantMolality(equilibrium_reactant, chemical_system_id,
371  solid_phase, liquid_phase, vars, pos, t, dt);
372  }
373 }
374 
376 {
377  writeInputsToFile(dt);
378 
379  callPhreeqc();
380 
382 }
383 
384 std::vector<GlobalVector*> PhreeqcIO::getIntPtProcessSolutions() const
385 {
386  auto const& aqueous_solution = _chemical_system->aqueous_solution;
387  std::vector<GlobalVector*> int_pt_process_solutions;
388  int_pt_process_solutions.reserve(aqueous_solution->components.size() + 1);
389 
390  std::transform(aqueous_solution->components.begin(),
391  aqueous_solution->components.end(),
392  std::back_inserter(int_pt_process_solutions),
393  [](auto const& c) { return c.amount.get(); });
394 
395  int_pt_process_solutions.push_back(aqueous_solution->pH.get());
396 
397  return int_pt_process_solutions;
398 }
399 
401  int const component_id, GlobalIndexType const chemical_system_id) const
402 {
403  auto const& aqueous_solution = *_chemical_system->aqueous_solution;
404  auto& components = aqueous_solution.components;
405  auto const& pH = *aqueous_solution.pH;
406 
407  return component_id < static_cast<int>(components.size())
408  ? components[component_id].amount->get(chemical_system_id)
409  : pH.get(chemical_system_id);
410 }
411 
413 {
414  if (!_dump)
415  {
416  return;
417  }
418 
419  auto const& dump_file = _dump->dump_file;
420  std::ifstream in(dump_file);
421  if (!in)
422  {
423  OGS_FATAL("Could not open phreeqc dump file '{:s}'.", dump_file);
424  }
425 
426  _dump->readDumpFile(in, _num_chemical_systems);
427 
428  if (!in)
429  {
430  OGS_FATAL("Error when reading phreeqc dump file '{:s}'", dump_file);
431  }
432 
433  in.close();
434 }
435 
436 void PhreeqcIO::writeInputsToFile(double const dt)
437 {
438  DBUG("Writing phreeqc inputs into file '{:s}'.", _phreeqc_input_file);
439  std::ofstream out(_phreeqc_input_file, std::ofstream::out);
440 
441  if (!out)
442  {
443  OGS_FATAL("Could not open file '{:s}' for writing phreeqc inputs.",
445  }
446 
447  out << std::scientific
448  << std::setprecision(std::numeric_limits<double>::digits10);
449  out << (*this << dt);
450 
451  if (!out)
452  {
453  OGS_FATAL("Failed in generating phreeqc input file '{:s}'.",
455  }
456 
457  out.close();
458 }
459 
460 std::ostream& operator<<(std::ostream& os, PhreeqcIO const& phreeqc_io)
461 {
462  os << phreeqc_io._knobs << "\n";
463 
464  os << *phreeqc_io._output << "\n";
465 
466  auto const& user_punch = phreeqc_io._user_punch;
467  if (user_punch)
468  {
469  os << *user_punch << "\n";
470  }
471 
472  auto const& reaction_rates = phreeqc_io._reaction_rates;
473  if (!reaction_rates.empty())
474  {
475  os << "RATES"
476  << "\n";
477  os << reaction_rates << "\n";
478  }
479 
480  for (std::size_t chemical_system_id = 0;
481  chemical_system_id < phreeqc_io._num_chemical_systems;
482  ++chemical_system_id)
483  {
484  os << "SOLUTION " << chemical_system_id + 1 << "\n";
485  phreeqc_io._chemical_system->aqueous_solution->print(
486  os, chemical_system_id);
487 
488  auto const& dump = phreeqc_io._dump;
489  if (dump)
490  {
491  auto const& aqueous_solutions_prev = dump->aqueous_solutions_prev;
492  if (!aqueous_solutions_prev.empty())
493  {
494  os << aqueous_solutions_prev[chemical_system_id] << "\n\n";
495  }
496  }
497 
498  os << "USE solution none"
499  << "\n";
500  os << "END"
501  << "\n\n";
502 
503  os << "USE solution " << chemical_system_id + 1 << "\n\n";
504 
505  auto const& equilibrium_reactants =
506  phreeqc_io._chemical_system->equilibrium_reactants;
507  if (!equilibrium_reactants.empty())
508  {
509  os << "EQUILIBRIUM_PHASES " << chemical_system_id + 1 << "\n";
510  for (auto const& equilibrium_reactant : equilibrium_reactants)
511  {
512  equilibrium_reactant.print(os, chemical_system_id);
513  }
514  os << "\n";
515  }
516 
517  auto const& kinetic_reactants =
518  phreeqc_io._chemical_system->kinetic_reactants;
519  if (!kinetic_reactants.empty())
520  {
521  os << "KINETICS " << chemical_system_id + 1 << "\n";
522  for (auto const& kinetic_reactant : kinetic_reactants)
523  {
524  kinetic_reactant.print(os, chemical_system_id);
525  }
526  os << "-steps " << phreeqc_io._dt << "\n"
527  << "\n";
528  }
529 
530  auto const& surface = phreeqc_io._surface;
531  if (!surface.empty())
532  {
533  os << "SURFACE " << chemical_system_id + 1 << "\n";
534  std::size_t aqueous_solution_id =
535  dump->aqueous_solutions_prev.empty()
536  ? chemical_system_id + 1
537  : phreeqc_io._num_chemical_systems + chemical_system_id + 1;
538  os << "-equilibrate with solution " << aqueous_solution_id << "\n";
539  os << "-sites_units DENSITY"
540  << "\n";
541  os << surface << "\n";
542  os << "SAVE solution " << chemical_system_id + 1 << "\n";
543  }
544 
545  auto const& exchangers = phreeqc_io._chemical_system->exchangers;
546  if (!exchangers.empty())
547  {
548  os << "EXCHANGE " << chemical_system_id + 1 << "\n";
549  std::size_t const aqueous_solution_id =
550  dump->aqueous_solutions_prev.empty()
551  ? chemical_system_id + 1
552  : phreeqc_io._num_chemical_systems + chemical_system_id + 1;
553  os << "-equilibrate with solution " << aqueous_solution_id << "\n";
554  for (auto const& exchanger : exchangers)
555  {
556  exchanger.print(os, chemical_system_id);
557  }
558  os << "SAVE solution " << chemical_system_id + 1 << "\n";
559  }
560 
561  os << "END"
562  << "\n\n";
563  }
564 
565  auto const& dump = phreeqc_io._dump;
566  if (dump)
567  {
568  dump->print(os, phreeqc_io._num_chemical_systems);
569  }
570 
571  return os;
572 }
573 
575 {
576  INFO("Phreeqc: Executing chemical calculation.");
577  if (RunFile(phreeqc_instance_id, _phreeqc_input_file.c_str()) != IPQ_OK)
578  {
579  OutputErrorString(phreeqc_instance_id);
580  OGS_FATAL(
581  "Failed in performing speciation calculation with the generated "
582  "phreeqc input file '{:s}'.",
584  }
585 }
586 
588 {
589  auto const& basic_output_setups = _output->basic_output_setups;
590  auto const& phreeqc_result_file = basic_output_setups.output_file;
591  DBUG("Reading phreeqc results from file '{:s}'.", phreeqc_result_file);
592  std::ifstream in(phreeqc_result_file);
593 
594  if (!in)
595  {
596  OGS_FATAL("Could not open phreeqc result file '{:s}'.",
597  phreeqc_result_file);
598  }
599 
600  in >> *this;
601 
602  if (!in)
603  {
604  OGS_FATAL("Error when reading phreeqc result file '{:s}'",
605  phreeqc_result_file);
606  }
607 
608  in.close();
609 }
610 
611 std::istream& operator>>(std::istream& in, PhreeqcIO& phreeqc_io)
612 {
613  // Skip the headline
614  in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
615 
616  std::string line;
617  auto const& output = *phreeqc_io._output;
618  auto const& dropped_item_ids = output.dropped_item_ids;
619 
620  auto const& surface = phreeqc_io._surface;
621  auto const& exchangers = phreeqc_io._chemical_system->exchangers;
622 
623  if (!surface.empty() && !exchangers.empty())
624  {
625  OGS_FATAL(
626  "Using surface and exchange reactions simultaneously is not "
627  "supported at the moment");
628  }
629 
630  int const num_skipped_lines = surface.empty() && exchangers.empty() ? 1 : 2;
631 
632  auto& equilibrium_reactants =
633  phreeqc_io._chemical_system->equilibrium_reactants;
634  auto& kinetic_reactants = phreeqc_io._chemical_system->kinetic_reactants;
635 
636  for (std::size_t chemical_system_id = 0;
637  chemical_system_id < phreeqc_io._num_chemical_systems;
638  ++chemical_system_id)
639  {
640  // Skip equilibrium calculation result of initial solution
641  for (int i = 0; i < num_skipped_lines; ++i)
642  {
643  in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
644  }
645 
646  // Get calculation result of the solution after the reaction
647  if (!std::getline(in, line))
648  {
649  OGS_FATAL(
650  "Error when reading calculation result of Solution {:d} "
651  "after the reaction.",
652  chemical_system_id);
653  }
654 
655  std::vector<double> accepted_items;
656  std::vector<std::string> items;
657  boost::trim_if(line, boost::is_any_of("\t "));
658  boost::algorithm::split(items, line, boost::is_any_of("\t "),
659  boost::token_compress_on);
660  for (int item_id = 0; item_id < static_cast<int>(items.size());
661  ++item_id)
662  {
663  if (std::find(dropped_item_ids.begin(), dropped_item_ids.end(),
664  item_id) == dropped_item_ids.end())
665  {
666  double value;
667  try
668  {
669  value = std::stod(items[item_id]);
670  }
671  catch (const std::invalid_argument& e)
672  {
673  OGS_FATAL(
674  "Invalid argument. Could not convert string '{:s}' to "
675  "double for chemical system {:d}, column {:d}. "
676  "Exception '{:s}' was thrown.",
677  items[item_id], chemical_system_id + 1, item_id,
678  e.what());
679  }
680  catch (const std::out_of_range& e)
681  {
682  OGS_FATAL(
683  "Out of range error. Could not convert string "
684  "'{:s}' to double for chemical system {:d}, column "
685  "{:d}. Exception '{:s}' was thrown.",
686  items[item_id], chemical_system_id + 1, item_id,
687  e.what());
688  }
689  accepted_items.push_back(value);
690  }
691  }
692  assert(accepted_items.size() == output.accepted_items.size());
693 
694  auto& aqueous_solution = phreeqc_io._chemical_system->aqueous_solution;
695  auto& components = aqueous_solution->components;
696  auto& user_punch = phreeqc_io._user_punch;
697  for (int item_id = 0; item_id < static_cast<int>(accepted_items.size());
698  ++item_id)
699  {
700  auto const& accepted_item = output.accepted_items[item_id];
701  auto const& item_name = accepted_item.name;
702 
703  auto compare_by_name = [&item_name](auto const& item)
704  { return item.name == item_name; };
705 
706  switch (accepted_item.item_type)
707  {
708  case ItemType::pH:
709  {
710  // Update pH value
711  aqueous_solution->pH->set(
712  chemical_system_id,
713  std::pow(10, -accepted_items[item_id]));
714  break;
715  }
716  case ItemType::pe:
717  {
718  // Update pe value
719  (*aqueous_solution->pe)[chemical_system_id] =
720  accepted_items[item_id];
721  break;
722  }
723  case ItemType::Component:
724  {
725  // Update component concentrations
726  auto& component = BaseLib::findElementOrError(
727  components.begin(), components.end(), compare_by_name,
728  "Could not find component '" + item_name + "'.");
729  component.amount->set(chemical_system_id,
730  accepted_items[item_id]);
731  break;
732  }
734  {
735  // Update amounts of equilibrium reactant
736  auto& equilibrium_reactant = BaseLib::findElementOrError(
737  equilibrium_reactants.begin(),
738  equilibrium_reactants.end(), compare_by_name,
739  "Could not find equilibrium reactant '" + item_name +
740  "'.");
741  (*equilibrium_reactant.molality)[chemical_system_id] =
742  accepted_items[item_id];
743  break;
744  }
746  {
747  // Update amounts of kinetic reactants
748  auto& kinetic_reactant = BaseLib::findElementOrError(
749  kinetic_reactants.begin(), kinetic_reactants.end(),
750  compare_by_name,
751  "Could not find kinetic reactant '" + item_name + "'.");
752  (*kinetic_reactant.molality)[chemical_system_id] =
753  accepted_items[item_id];
754  break;
755  }
757  {
758  assert(user_punch);
759  auto& secondary_variables = user_punch->secondary_variables;
760  // Update values of secondary variables
761  auto& secondary_variable = BaseLib::findElementOrError(
762  secondary_variables.begin(), secondary_variables.end(),
763  compare_by_name,
764  "Could not find secondary variable '" + item_name +
765  "'.");
766  (*secondary_variable.value)[chemical_system_id] =
767  accepted_items[item_id];
768  break;
769  }
770  }
771  }
772  }
773 
774  return in;
775 }
776 
777 std::vector<std::string> const PhreeqcIO::getComponentList() const
778 {
779  std::vector<std::string> component_names;
780  auto const& components = _chemical_system->aqueous_solution->components;
781  std::transform(components.begin(), components.end(),
782  std::back_inserter(component_names),
783  [](auto const& c) { return c.name; });
784 
785  component_names.push_back("H");
786 
787  return component_names;
788 }
789 
791  GlobalIndexType const& chemical_system_id,
792  MaterialPropertyLib::Medium const& medium,
793  ParameterLib::SpatialPosition const& pos, double const porosity,
794  double const t, double const dt)
795 {
796  for (auto& kinetic_reactant : _chemical_system->kinetic_reactants)
797  {
798  updateReactantVolumeFraction(kinetic_reactant, chemical_system_id,
799  medium, pos, porosity, t, dt);
800  }
801 
802  for (auto& equilibrium_reactant : _chemical_system->equilibrium_reactants)
803  {
804  updateReactantVolumeFraction(equilibrium_reactant, chemical_system_id,
805  medium, pos, porosity, t, dt);
806  }
807 }
808 
810  GlobalIndexType const& chemical_system_id,
811  MaterialPropertyLib::Medium const& medium,
812  double& porosity)
813 {
814  for (auto& kinetic_reactant : _chemical_system->kinetic_reactants)
815  {
816  setPorosityPostReaction(kinetic_reactant, chemical_system_id, medium,
817  porosity);
818  }
819 
820  for (auto& equilibrium_reactant : _chemical_system->equilibrium_reactants)
821  {
822  setPorosityPostReaction(equilibrium_reactant, chemical_system_id,
823  medium, porosity);
824  }
825 }
826 
828  std::size_t const ele_id,
829  std::vector<GlobalIndexType> const& chemical_system_indices)
830 {
831  for (auto& kinetic_reactant : _chemical_system->kinetic_reactants)
832  {
833  (*kinetic_reactant.mesh_prop_molality)[ele_id] =
834  averageReactantMolality(kinetic_reactant, chemical_system_indices);
835  }
836 
837  for (auto& equilibrium_reactant : _chemical_system->equilibrium_reactants)
838  {
839  (*equilibrium_reactant.mesh_prop_molality)[ele_id] =
840  averageReactantMolality(equilibrium_reactant,
841  chemical_system_indices);
842  }
843 }
844 } // namespace PhreeqcIOData
845 } // namespace ChemistryLib
#define OGS_FATAL(...)
Definition: Error.h:26
GlobalMatrix::IndexType GlobalIndexType
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::vector< GlobalIndexType > chemical_system_index_map
std::vector< SurfaceSite > const _surface
Definition: PhreeqcIO.h:114
std::string const _phreeqc_input_file
Definition: PhreeqcIO.h:96
PhreeqcIO(GlobalLinearSolver &linear_solver, std::string const &project_file_name, std::string &&database, std::unique_ptr< ChemicalSystem > &&chemical_system, std::vector< ReactionRate > &&reaction_rates, std::vector< SurfaceSite > &&surface, std::unique_ptr< UserPunch > &&user_punch, std::unique_ptr< Output > &&output, std::unique_ptr< Dump > &&dump, Knobs &&knobs)
Definition: PhreeqcIO.cpp:251
double getConcentration(int const component_id, GlobalIndexType const chemical_system_id) const override
Definition: PhreeqcIO.cpp:400
void setAqueousSolutionsPrevFromDumpFile() override
Definition: PhreeqcIO.cpp:412
std::unique_ptr< ChemicalSystem > _chemical_system
Definition: PhreeqcIO.h:112
std::vector< ReactionRate > const _reaction_rates
Definition: PhreeqcIO.h:113
std::unique_ptr< UserPunch > _user_punch
Definition: PhreeqcIO.h:115
void writeInputsToFile(double const dt)
Definition: PhreeqcIO.cpp:436
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
Definition: PhreeqcIO.cpp:349
std::unique_ptr< Dump > const _dump
Definition: PhreeqcIO.h:117
std::unique_ptr< Output > const _output
Definition: PhreeqcIO.h:116
std::vector< GlobalVector * > getIntPtProcessSolutions() const override
Definition: PhreeqcIO.cpp:384
void computeSecondaryVariable(std::size_t const ele_id, std::vector< GlobalIndexType > const &chemical_system_indices) override
Definition: PhreeqcIO.cpp:827
void initializeChemicalSystemConcrete(std::vector< double > const &concentrations, GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Medium const &medium, ParameterLib::SpatialPosition const &pos, double const t) override
Definition: PhreeqcIO.cpp:317
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
Definition: PhreeqcIO.cpp:790
void executeSpeciationCalculation(double const dt) override
Definition: PhreeqcIO.cpp:375
std::vector< std::string > const getComponentList() const override
Definition: PhreeqcIO.cpp:777
void updatePorosityPostReaction(GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Medium const &medium, double &porosity) override
Definition: PhreeqcIO.cpp:809
Phase const & phase(std::size_t index) const
Definition: Medium.cpp:30
Component const & component(std::size_t const &index) const
Definition: Phase.cpp:32
std::iterator_traits< InputIt >::reference findElementOrError(InputIt begin, InputIt end, Predicate predicate, std::string const &error="")
Definition: Algorithm.h:69
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)
Definition: PhreeqcIO.cpp:72
void initializeExchangerMolality(Exchanger &exchanger, GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Phase const &solid_phase, ParameterLib::SpatialPosition const &pos, double const t)
Definition: PhreeqcIO.cpp:168
void setPorosityPostReaction(Reactant &reactant, GlobalIndexType const &chemical_system_id, MaterialPropertyLib::Medium const &medium, double &porosity)
Definition: PhreeqcIO.cpp:219
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)
Definition: PhreeqcIO.cpp:124
void setAqueousSolution(std::vector< double > const &concentrations, GlobalIndexType const &chemical_system_id, AqueousSolution &aqueous_solution)
Definition: PhreeqcIO.cpp:54
static double averageReactantMolality(Reactant const &reactant, std::vector< GlobalIndexType > const &chemical_system_indices)
Definition: PhreeqcIO.cpp:239
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)
Definition: PhreeqcIO.cpp:184
std::istream & operator>>(std::istream &in, PhreeqcIO &phreeqc_io)
Definition: PhreeqcIO.cpp:611
std::ostream & operator<<(std::ostream &os, PhreeqcIO const &phreeqc_io)
Definition: PhreeqcIO.cpp:460
std::array< VariableType, static_cast< int >(Variable::number_of_variables)> VariableArray
Definition: VariableType.h:108
void copy(PETScVector const &x, PETScVector &y)
Definition: LinAlg.cpp:37
double fluid_density(const double p, const double T, const double x)
std::unique_ptr< GlobalVector > pH