OGS
CreateProcessData.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include <range/v3/algorithm/contains.hpp>
5
6#include "BaseLib/Algorithm.h"
9#ifdef USE_PETSC
11#endif // USE_PETSC
12#include "CreateProcessData.h"
14
15namespace ProcessLib
16{
17static std::unique_ptr<ProcessData> makeProcessData(
18 std::unique_ptr<NumLib::TimeStepAlgorithm>&& timestepper,
19 NumLib::NonlinearSolverBase& nonlinear_solver, int const process_id,
20 std::string process_name, Process& process,
21 std::unique_ptr<NumLib::TimeDiscretization>&& time_disc,
22 std::unique_ptr<NumLib::ConvergenceCriterion>&& conv_crit,
23 bool const compensate_non_equilibrium_initial_residuum)
24{
26
27 if (auto* nonlinear_solver_picard =
29 &nonlinear_solver))
30 {
31 nonlinear_solver_picard->compensateNonEquilibriumInitialResiduum(
32 compensate_non_equilibrium_initial_residuum);
33 return std::make_unique<ProcessData>(
34 std::move(timestepper), Tag::Picard, *nonlinear_solver_picard,
35 std::move(conv_crit), std::move(time_disc), process_id,
36 std::move(process_name), process);
37 }
38 if (auto* nonlinear_solver_newton =
40 &nonlinear_solver))
41 {
42 nonlinear_solver_newton->compensateNonEquilibriumInitialResiduum(
43 compensate_non_equilibrium_initial_residuum);
44 return std::make_unique<ProcessData>(
45 std::move(timestepper), Tag::Newton, *nonlinear_solver_newton,
46 std::move(conv_crit), std::move(time_disc), process_id,
47 std::move(process_name), process);
48 }
49#ifdef USE_PETSC
50 if (auto* nonlinear_solver_petsc =
51 dynamic_cast<NumLib::PETScNonlinearSolver*>(&nonlinear_solver))
52 {
53 for (auto const& pv : process.getProcessVariables(process_id))
54 {
55 if (pv.get().compensateNonEquilibriumInitialResiduum())
56 {
58 "The PETSc SNES nonlinear solver does not support "
59 "'compensate_non_equilibrium_initial_residuum', but it "
60 "is set for process variable '{}'. Please use the "
61 "Picard or Newton-Raphson solver instead.",
62 pv.get().getName());
63 }
64 }
65 return std::make_unique<ProcessData>(
66 std::move(timestepper), Tag::Newton, *nonlinear_solver_petsc,
67 std::move(conv_crit), std::move(time_disc), process_id,
68 std::move(process_name), process);
69 }
70#endif // USE_PETSC
71
72 OGS_FATAL("Encountered unknown nonlinear solver type. Aborting");
73}
74
75std::vector<std::unique_ptr<ProcessData>> createPerProcessData(
76 BaseLib::ConfigTree const& config,
77 std::vector<std::unique_ptr<Process>> const& processes,
78 std::map<std::string, std::unique_ptr<NumLib::NonlinearSolverBase>> const&
79 nonlinear_solvers,
80 bool const compensate_non_equilibrium_initial_residuum,
81 std::vector<double> const& fixed_times_for_output)
82{
83 std::vector<std::unique_ptr<ProcessData>> per_process_data;
84 std::vector<std::string> process_names;
85 int process_id = 0;
86
88 for (auto pcs_config : config.getConfigSubtreeList("process"))
89 {
91 auto const pcs_name = pcs_config.getConfigAttribute<std::string>("ref");
92 auto& pcs = *BaseLib::getIfOrError(
93 processes,
94 [&pcs_name](std::unique_ptr<Process> const& p)
95 { return p->name == pcs_name; },
96 "A process with the given name has not been defined.");
97
98 auto const process_name =
100 pcs_config.getConfigParameter<std::string>("process_name", "");
101 if (process_name != "")
102 {
103 if (ranges::contains(process_names, process_name))
104 {
105 OGS_FATAL(
106 "The given process name is not unique! Please check the "
107 "element "
108 "'time_loop/process/name' in the project file. Found "
109 "duplicate "
110 "process name '{:s}'.",
111 process_name);
112 }
113 process_names.emplace_back(process_name);
114 }
115
116 auto const nl_slv_name =
118 pcs_config.getConfigParameter<std::string>("nonlinear_solver");
119 auto& nl_slv = *BaseLib::getOrError(
120 nonlinear_solvers, nl_slv_name,
121 "A nonlinear solver with the given name has not been defined.");
122
123 auto time_disc = NumLib::createTimeDiscretization(
125 pcs_config.getConfigSubtree("time_discretization"));
126
127 auto timestepper = NumLib::createTimeStepper(
129 pcs_config.getConfigSubtree("time_stepping"),
130 fixed_times_for_output);
131
132 auto conv_crit = NumLib::createConvergenceCriterion(
134 pcs_config.getConfigSubtree("convergence_criterion"));
135
137 auto output = pcs_config.getConfigSubtreeOptional("output");
138 if (output)
139 {
140 OGS_FATAL(
141 "In order to make the specification of output in the project "
142 "file consistent, the variables output tags were moved from "
143 "xpath "
144 "'//OpenGeoSysProject/time_loop/processes/process/output' to "
145 "the global output section, i.e., to the xpath "
146 "'//OpenGeoSysProject/time_loop/output'. This has to be done "
147 "in the current project file!");
148 }
149
150 per_process_data.emplace_back(makeProcessData(
151 std::move(timestepper), nl_slv, process_id, std::move(process_name),
152 pcs, std::move(time_disc), std::move(conv_crit),
153 compensate_non_equilibrium_initial_residuum));
154 ++process_id;
155 }
156
157 if (per_process_data.size() != processes.size())
158 {
159 if (processes.size() > 1)
160 {
161 OGS_FATAL(
162 "Some processes have not been configured to be solved by this "
163 "time loop.");
164 }
165 else
166 {
167 INFO(
168 "The equations of the coupled processes will be solved by the "
169 "staggered scheme.");
170 }
171 }
172
173 return per_process_data;
174}
175} // namespace ProcessLib
#define OGS_FATAL(...)
Definition Error.h:19
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
Range< SubtreeIterator > getConfigSubtreeList(std::string const &root) const
std::vector< std::vector< std::reference_wrapper< ProcessVariable > > > const & getProcessVariables() const
Definition Process.h:149
NonlinearSolverTag
Tag used to specify which nonlinear solver will be used.
Definition Types.h:13
OGS_NO_DANGLING Container::value_type const & getIfOrError(Container const &container, Predicate &&predicate, std::string const &error_message)
Definition Algorithm.h:156
OGS_NO_DANGLING Map::mapped_type & getOrError(Map &map, Key const &key, std::string const &error_message)
Definition Algorithm.h:111
std::unique_ptr< TimeDiscretization > createTimeDiscretization(BaseLib::ConfigTree const &config)
std::unique_ptr< TimeStepAlgorithm > createTimeStepper(BaseLib::ConfigTree const &config, std::vector< double > const &fixed_times_for_output)
std::unique_ptr< ConvergenceCriterion > createConvergenceCriterion(const BaseLib::ConfigTree &config)
Creates a convergence criterion from the given configuration.
std::vector< std::unique_ptr< ProcessData > > createPerProcessData(BaseLib::ConfigTree const &config, std::vector< std::unique_ptr< Process > > const &processes, std::map< std::string, std::unique_ptr< NumLib::NonlinearSolverBase > > const &nonlinear_solvers, bool const compensate_non_equilibrium_initial_residuum, std::vector< double > const &fixed_times_for_output)
static std::unique_ptr< ProcessData > makeProcessData(std::unique_ptr< NumLib::TimeStepAlgorithm > &&timestepper, NumLib::NonlinearSolverBase &nonlinear_solver, int const process_id, std::string process_name, Process &process, std::unique_ptr< NumLib::TimeDiscretization > &&time_disc, std::unique_ptr< NumLib::ConvergenceCriterion > &&conv_crit, bool const compensate_non_equilibrium_initial_residuum)