OGS
CreateStaggeredCoupling-impl.h
Go to the documentation of this file.
1
12#pragma once
13
14#include <numeric>
15
16#include "BaseLib/Error.h"
18#include "StaggeredCoupling.h"
19
20namespace NumLib
21{
22using CouplingNodeVariant = std::variant<CouplingNode, RootCouplingNode>;
23
24template <typename ProcessData>
26 std::vector<std::unique_ptr<ProcessData>> const& per_process_data,
27 std::vector<LocalCouplingParameters> const& all_local_coupling_parameters)
28{
29 // Check whether the process names in the sub-coupling definitions exist in
30 // the process data.
31 for (auto const& local_coupling_parameters : all_local_coupling_parameters)
32 {
33 for (auto const& process_name : local_coupling_parameters.process_names)
34 {
35 if (std::none_of(
36 per_process_data.begin(),
37 per_process_data.end(),
38 [&process_name](auto const& process_data)
39 { return process_data->process_name == process_name; }))
40 {
42 "The given process name '{}' for the element "
43 "'time_loop/global_process_coupling/"
44 "local_coupling_processes/process_name' is not found "
45 "in the element 'time_loop/global_process_coupling/"
46 "local_coupling_processes/process_name' in the project "
47 "file.",
48 process_name);
49 }
50 }
51 }
52}
53
55template <typename ProcessData>
56std::vector<CouplingNodeVariant> createRegularCouplingNodes(
57 std::vector<std::unique_ptr<ProcessData>> const& per_process_data,
58 std::vector<LocalCouplingParameters> const& all_local_coupling_parameters,
59 int const global_max_coupling_iterations,
60 std::vector<std::unique_ptr<NumLib::ConvergenceCriterion>>&
61 global_coupling_conv_criteria)
62{
63 std::vector<CouplingNodeVariant> coupling_nodes;
64
65 for (auto const& process_data : per_process_data)
66 {
67 auto const& process_name = process_data->process_name;
68
69 // If process_data->process_name occurs in local_coupling_parameters
70 // do nothing
71 if (std::any_of(
72 all_local_coupling_parameters.begin(),
73 all_local_coupling_parameters.end(),
74 [&process_name](auto const& local_coupling_parameters)
75 {
76 auto const& process_names =
77 local_coupling_parameters.process_names;
78 return std::find(process_names.begin(), process_names.end(),
79 process_name) != process_names.end();
80 }))
81 {
82 continue;
83 }
84
85 std::string const used_process_name =
86 process_name.empty() ? "not given" : process_name;
87 CouplingNode regular_node{
88 used_process_name,
89 std::move(global_coupling_conv_criteria[process_data->process_id]),
90 global_max_coupling_iterations,
91 process_data->process_id,
92 };
93 coupling_nodes.emplace_back(std::move(regular_node));
94 }
95
96 return coupling_nodes;
97}
98
100template <typename ProcessData>
101std::vector<CouplingNodeVariant> createRootCouplingNodes(
102 std::vector<std::unique_ptr<ProcessData>> const& per_process_data,
103 std::vector<LocalCouplingParameters> const& all_local_coupling_parameters,
104 int const global_max_coupling_iterations,
105 std::vector<std::unique_ptr<NumLib::ConvergenceCriterion>>&
106 global_coupling_conv_criteria)
107{
108 std::vector<CouplingNodeVariant> coupling_nodes;
109
110 for (auto const& local_coupling_parameters : all_local_coupling_parameters)
111 {
112 RootCouplingNode root_node = {global_max_coupling_iterations, {}};
113
114 for (auto const& local_process_name :
115 local_coupling_parameters.process_names)
116 {
117 if (auto it = std::find_if(
118 per_process_data.begin(),
119 per_process_data.end(),
120 [&local_process_name](auto const& process_data) {
121 return process_data->process_name == local_process_name;
122 });
123 it != per_process_data.end())
124 {
125 auto const& process_data = *it;
126
127 CouplingNode regular_node{
128 process_data->process_name,
129 std::move(global_coupling_conv_criteria[process_data
130 ->process_id]),
131 local_coupling_parameters.max_iterations,
132 process_data->process_id};
133
134 root_node.sub_coupling_nodes.emplace_back(
135 std::move(regular_node));
136 }
137 }
138 coupling_nodes.emplace_back(std::move(root_node));
139 }
140
141 return coupling_nodes;
142}
143
144template <typename ProcessData>
145std::vector<CouplingNodeVariant> createCouplingNodes(
146 std::vector<std::unique_ptr<ProcessData>> const& per_process_data,
147 std::vector<LocalCouplingParameters> const& all_local_coupling_parameters,
148 int const global_max_coupling_iterations,
149 std::vector<std::unique_ptr<NumLib::ConvergenceCriterion>>&
150 global_coupling_conv_criteria)
151{
152 checkLocalCouplingParameters(per_process_data,
153 all_local_coupling_parameters);
154
155 // First, get the coupling nodes that do not have local-coupling nodes.
156 std::vector<CouplingNodeVariant> coupling_nodes =
158 per_process_data, all_local_coupling_parameters,
159 global_max_coupling_iterations, global_coupling_conv_criteria);
160
161 // Second, get the coupling nodes that have local-coupling nodes.
162 std::vector<CouplingNodeVariant> root_coupling_nodes =
163 createRootCouplingNodes(per_process_data, all_local_coupling_parameters,
164 global_max_coupling_iterations,
165 global_coupling_conv_criteria);
166
167 std::size_t const num_coupling_nodes =
168 coupling_nodes.size() +
169 std::accumulate(
170 root_coupling_nodes.begin(),
171 root_coupling_nodes.end(),
172 0,
173 [](std::size_t accumulated_sizes, const auto& coupling_node)
174 {
175 return accumulated_sizes +
176 std::get<RootCouplingNode>(coupling_node)
177 .sub_coupling_nodes.size();
178 });
179
180 if (num_coupling_nodes != per_process_data.size())
181 {
182 OGS_FATAL(
183 "The number of all coupling nodes including sub-nodes is not "
184 "identical to the number of the processes! Please check the "
185 "element by tag global_process_coupling in the project file.");
186 }
187
188 if (coupling_nodes.empty())
189 {
190 coupling_nodes = std::move(root_coupling_nodes);
191 }
192 else
193 {
194 coupling_nodes.reserve(coupling_nodes.size() +
195 root_coupling_nodes.size());
196
197 std::move(std::begin(root_coupling_nodes),
198 std::end(root_coupling_nodes),
199 std::back_inserter(coupling_nodes));
200 }
201
202 return coupling_nodes;
203}
204
206template <typename ProcessData>
207std::unique_ptr<StaggeredCoupling> createStaggeredCoupling(
208 BaseLib::ConfigTree const& config,
209 std::vector<std::unique_ptr<ProcessData>> const& per_process_data)
210{
211 auto [global_coupling_conv_criteria, all_local_coupling_parameters,
212 max_coupling_iterations] = parseCoupling(config);
213
214 if (per_process_data.size() != global_coupling_conv_criteria.size())
215 {
216 OGS_FATAL(
217 "The number of convergence criteria of the global "
218 "staggered coupling loop is not identical to the number of the "
219 "processes! Please check the element by tag "
220 "global_process_coupling in the project file.");
221 }
222
223 auto coupling_nodes = createCouplingNodes(
224 per_process_data, all_local_coupling_parameters,
225 max_coupling_iterations, global_coupling_conv_criteria);
226
227 return std::make_unique<StaggeredCoupling>(max_coupling_iterations,
228 std::move(coupling_nodes));
229}
230} // namespace NumLib
#define OGS_FATAL(...)
Definition Error.h:26
void checkLocalCouplingParameters(std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< LocalCouplingParameters > const &all_local_coupling_parameters)
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.
std::variant< CouplingNode, RootCouplingNode > CouplingNodeVariant
std::vector< CouplingNodeVariant > createCouplingNodes(std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< LocalCouplingParameters > const &all_local_coupling_parameters, int const global_max_coupling_iterations, std::vector< std::unique_ptr< NumLib::ConvergenceCriterion > > &global_coupling_conv_criteria)
std::tuple< std::vector< std::unique_ptr< NumLib::ConvergenceCriterion > >, std::vector< LocalCouplingParameters >, int > parseCoupling(BaseLib::ConfigTree const &config)
std::vector< CouplingNodeVariant > createRootCouplingNodes(std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< LocalCouplingParameters > const &all_local_coupling_parameters, int const global_max_coupling_iterations, std::vector< std::unique_ptr< NumLib::ConvergenceCriterion > > &global_coupling_conv_criteria)
Create coupling nodes that have local-coupling nodes.
std::vector< CouplingNodeVariant > createRegularCouplingNodes(std::vector< std::unique_ptr< ProcessData > > const &per_process_data, std::vector< LocalCouplingParameters > const &all_local_coupling_parameters, int const global_max_coupling_iterations, std::vector< std::unique_ptr< NumLib::ConvergenceCriterion > > &global_coupling_conv_criteria)
Create coupling nodes that do not have local-coupling nodes.
Information of a coupling node.
std::vector< CouplingNodeVariant > sub_coupling_nodes