OGS
CreateTimeLoop.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 "CreateTimeLoop.h"
5
6#include <algorithm>
7#include <range/v3/algorithm/all_of.hpp>
8#include <range/v3/algorithm/any_of.hpp>
9#include <range/v3/view/join.hpp>
10#include <string>
11
12#include "BaseLib/ConfigTree.h"
19#include "TimeLoop.h"
20
21namespace ProcessLib
22{
23std::unique_ptr<TimeLoop> createTimeLoop(
24 BaseLib::ConfigTree const& config, std::string const& output_directory,
25 const std::vector<std::unique_ptr<Process>>& processes,
26 const std::map<std::string, std::unique_ptr<NumLib::NonlinearSolverBase>>&
27 nonlinear_solvers,
28 std::vector<std::unique_ptr<MeshLib::Mesh>>& meshes,
29 bool const compensate_non_equilibrium_initial_residuum)
30{
32 auto output_config_tree = config.getConfigSubtreeOptional("output");
33 if (!output_config_tree)
34 {
35 INFO("No output section found.");
36 }
37 auto outputs =
38 output_config_tree
39 ? createOutput(*output_config_tree, output_directory, meshes)
41 : createOutputs(config.getConfigSubtree("outputs"),
42 output_directory, meshes);
43 auto const fixed_times_for_output =
45
46 if (auto const submesh_residuum_output_config_tree =
48 config.getConfigSubtreeOptional("submesh_residuum_output");
49 submesh_residuum_output_config_tree)
50 {
52 *submesh_residuum_output_config_tree, output_directory, meshes);
53
54 for (auto& process : processes)
55 {
56 auto const& residuum_vector_names =
57 process->initializeAssemblyOnSubmeshes(smroc.meshes);
58
59 for (auto const& name : residuum_vector_names | ranges::views::join)
60 {
61 smroc.output.doNotProjectFromBulkMeshToSubmeshes(
63 }
64 }
65
66 outputs.push_back(std::move(smroc.output));
67 }
68 else
69 {
70 // Submesh assembly must always be initialized.
71 for (auto& process : processes)
72 {
73 process->initializeAssemblyOnSubmeshes({});
74 }
75 }
76
77 auto per_process_data = createPerProcessData(
79 config.getConfigSubtree("processes"), processes, nonlinear_solvers,
80 compensate_non_equilibrium_initial_residuum, fixed_times_for_output);
81
82 const bool use_staggered_scheme = ranges::any_of(
83 processes.begin(), processes.end(), [](auto const& process)
84 { return !(process->isMonolithicSchemeUsed()); });
85
86 std::unique_ptr<NumLib::StaggeredCoupling> staggered_coupling = nullptr;
87 if (use_staggered_scheme)
88 {
90 config, per_process_data);
91 }
92 else
93 {
94 if (per_process_data.size() > 1)
95 {
97 "The monolithic scheme is used. However more than one "
98 "process data tags (by name \"process\") inside tag "
99 "\"time_loop\" are defined for the staggered scheme. If you "
100 "want to use staggered scheme, please set the element of tag "
101 "\"<coupling_scheme>\" to \"staggered\".");
102 }
103 }
104
105 auto const& first_timestep_algorithm =
106 *per_process_data.front()->timestep_algorithm;
107
108 if (!ranges::all_of(
109 per_process_data,
110 [t_initial = first_timestep_algorithm.begin()](
111 NumLib::Time const& t) { return t == t_initial; },
112 [](std::unique_ptr<ProcessData> const& process_data)
113 { return process_data->timestep_algorithm->begin(); }))
114 {
115 OGS_FATAL("All processes must have the same start time.");
116 }
117 if (!ranges::all_of(
118 per_process_data,
119 [t_end = first_timestep_algorithm.end()](NumLib::Time const& t)
120 { return t == t_end; },
121 [](std::unique_ptr<ProcessData> const& process_data)
122 { return process_data->timestep_algorithm->end(); }))
123 {
124 OGS_FATAL("All processes must have the same end time.");
125 }
126
127 const auto minmax_iter =
128 std::minmax_element(per_process_data.begin(),
129 per_process_data.end(),
130 [](std::unique_ptr<ProcessData> const& a,
131 std::unique_ptr<ProcessData> const& b)
132 {
133 return (a->timestep_algorithm->end() <
134 b->timestep_algorithm->end());
135 });
136 auto const start_time =
137 per_process_data[minmax_iter.first - per_process_data.begin()]
138 ->timestep_algorithm->begin();
139 auto const end_time =
140 per_process_data[minmax_iter.second - per_process_data.begin()]
141 ->timestep_algorithm->end();
142
143 return std::make_unique<TimeLoop>(
144 std::move(outputs), std::move(per_process_data),
145 std::move(staggered_coupling), start_time, end_time);
146}
147} // namespace ProcessLib
#define OGS_FATAL(...)
Definition Error.h:10
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
std::optional< ConfigTree > getConfigSubtreeOptional(std::string const &root) const
ConfigTree getConfigSubtree(std::string const &root) const
std::unique_ptr< StaggeredCoupling > createStaggeredCoupling(BaseLib::ConfigTree const &config, std::vector< std::unique_ptr< ProcessData > > const &per_process_data)
Create a StaggeredCoupling instance from the given configuration.
SubmeshResiduumOutputConfig createSubmeshResiduumOutputConfig(BaseLib::ConfigTree const &config, std::string const &output_directory, std::vector< std::unique_ptr< MeshLib::Mesh > > &meshes)
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)
Output createOutput(OutputConfig &&oc, std::string const &output_directory, std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
std::unique_ptr< TimeLoop > createTimeLoop(BaseLib::ConfigTree const &config, std::string const &output_directory, const std::vector< std::unique_ptr< Process > > &processes, const std::map< std::string, std::unique_ptr< NumLib::NonlinearSolverBase > > &nonlinear_solvers, std::vector< std::unique_ptr< MeshLib::Mesh > > &meshes, bool const compensate_non_equilibrium_initial_residuum)
Builds a TimeLoop from the given configuration.
std::vector< double > calculateUniqueFixedTimesForAllOutputs(std::vector< Output > const &outputs)
std::vector< Output > createOutputs(const BaseLib::ConfigTree &output_configs, std::string const &output_directory, std::vector< std::unique_ptr< MeshLib::Mesh > > &meshes)