Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #include "MooseError.h"
11 : #include "MultiAppReporterTransfer.h"
12 : #include "MultiApp.h"
13 :
14 : registerMooseObject("MooseApp", MultiAppReporterTransfer);
15 :
16 : InputParameters
17 3703 : MultiAppReporterTransfer::validParams()
18 : {
19 3703 : InputParameters params = MultiAppTransfer::validParams();
20 3703 : params += ReporterTransferInterface::validParams();
21 7406 : params.addClassDescription("Transfers reporter data between two applications.");
22 14812 : params.addRequiredParam<std::vector<ReporterName>>(
23 : "from_reporters",
24 : "List of the reporter names (object_name/value_name) to transfer the value from.");
25 14812 : params.addRequiredParam<std::vector<ReporterName>>(
26 : "to_reporters",
27 : "List of the reporter names (object_name/value_name) to transfer the value to.");
28 11109 : params.addParam<unsigned int>(
29 : "subapp_index",
30 7406 : std::numeric_limits<unsigned int>::max(),
31 : "The MultiApp object sub-application index to use when transferring to/from the "
32 : "sub-application. If unset and transferring to the sub-applications then all "
33 : "sub-applications will receive data. The value must be set when transferring from a "
34 : "sub-application.");
35 7406 : params.addParam<bool>(
36 : "distribute_reporter_vector",
37 7406 : false,
38 : "Transfer to/from a vector reporter from/to reporters on child applications. N "
39 : "to 1 or 1 to N type of transfer. The number of child applications must "
40 : "match the size of the vector reporter");
41 3703 : return params;
42 0 : }
43 :
44 300 : MultiAppReporterTransfer::MultiAppReporterTransfer(const InputParameters & parameters)
45 : : MultiAppTransfer(parameters),
46 : ReporterTransferInterface(this),
47 300 : _from_reporter_names(getParam<std::vector<ReporterName>>("from_reporters")),
48 600 : _to_reporter_names(getParam<std::vector<ReporterName>>("to_reporters")),
49 600 : _subapp_index(getParam<unsigned int>("subapp_index")),
50 900 : _distribute_reporter_vector(getParam<bool>("distribute_reporter_vector"))
51 : {
52 300 : if (_from_reporter_names.size() != _to_reporter_names.size())
53 0 : paramError("to_reporters", "from_reporters and to_reporters must be the same size.");
54 :
55 300 : if (_directions.size() > 1)
56 0 : paramError("direction", "This transfer only supports a single direction.");
57 :
58 1260 : if (isParamValid("to_multi_app") && isParamValid("from_multi_app") &&
59 24 : _subapp_index != std::numeric_limits<unsigned int>::max())
60 0 : paramError("subapp_index",
61 : "The subapp_index parameter is not supported for transfers between two multiapps");
62 :
63 300 : if (hasFromMultiApp())
64 : {
65 156 : const auto multi_app = getFromMultiApp();
66 : // Errors for sub app index.
67 246 : if (_subapp_index != std::numeric_limits<unsigned int>::max() &&
68 90 : _subapp_index >= multi_app->numGlobalApps())
69 6 : paramError(
70 : "subapp_index",
71 : "The supplied sub-application index is greater than the number of sub-applications.");
72 282 : else if (_directions.isValueSet(FROM_MULTIAPP) &&
73 171 : _subapp_index == std::numeric_limits<unsigned int>::max() &&
74 324 : multi_app->numGlobalApps() > 1 && !_distribute_reporter_vector)
75 6 : paramError("from_multi_app",
76 : "subapp_index must be provided when more than one subapp is present.");
77 150 : }
78 144 : else if (hasToMultiApp())
79 : {
80 : // Errors for sub app index.
81 219 : if (_subapp_index != std::numeric_limits<unsigned int>::max() &&
82 219 : _subapp_index >= getToMultiApp()->numGlobalApps())
83 6 : paramError(
84 : "subapp_index",
85 : "The supplied sub-application index is greater than the number of sub-applications.");
86 : }
87 291 : }
88 :
89 : void
90 258 : MultiAppReporterTransfer::initialSetup()
91 : {
92 258 : MultiAppTransfer::initialSetup();
93 :
94 : // We need to get a reference to the data now so we can tell ReporterData
95 : // that we consume a replicated version.
96 : // Find proper FEProblem
97 258 : FEProblemBase * problem_ptr = nullptr;
98 258 : if (_directions.isValueSet(TO_MULTIAPP))
99 123 : problem_ptr = &getToMultiApp()->problemBase();
100 198 : else if (_subapp_index == std::numeric_limits<unsigned int>::max() &&
101 198 : getFromMultiApp()->hasLocalApp(0))
102 48 : problem_ptr = &getFromMultiApp()->appProblemBase(0);
103 87 : else if (getFromMultiApp()->hasLocalApp(_subapp_index))
104 54 : problem_ptr = &getFromMultiApp()->appProblemBase(_subapp_index);
105 :
106 : // Tell ReporterData to consume with replicated
107 258 : if (problem_ptr && !_distribute_reporter_vector)
108 384 : for (const auto & fn : _from_reporter_names)
109 228 : addReporterTransferMode(fn, REPORTER_MODE_REPLICATED, *problem_ptr);
110 :
111 : // Check that we have the correct reporter modes setup.
112 258 : if (_distribute_reporter_vector)
113 : {
114 78 : if (hasFromMultiApp())
115 39 : setVectorReporterTransferModes(getFromMultiApp(), _to_reporter_names, _from_reporter_names);
116 39 : else if (hasToMultiApp())
117 39 : setVectorReporterTransferModes(getToMultiApp(), _from_reporter_names, _to_reporter_names);
118 : }
119 258 : }
120 :
121 : void
122 156 : MultiAppReporterTransfer::executeToMultiapp()
123 : {
124 156 : if (!hasToMultiApp())
125 0 : return;
126 :
127 156 : std::vector<unsigned int> indices;
128 156 : if (_subapp_index == std::numeric_limits<unsigned int>::max())
129 : {
130 101 : indices.resize(getToMultiApp()->numGlobalApps());
131 101 : std::iota(indices.begin(), indices.end(), 0);
132 : }
133 : else
134 55 : indices = {_subapp_index};
135 :
136 479 : for (const auto & ind : indices)
137 882 : if (getToMultiApp()->hasLocalApp(ind) &&
138 559 : (!hasFromMultiApp() || getFromMultiApp()->hasLocalApp(ind)))
139 676 : for (unsigned int n = 0; n < _from_reporter_names.size(); ++n)
140 : {
141 440 : if (_distribute_reporter_vector)
142 384 : transferFromVectorReporter(_from_reporter_names[n],
143 192 : _to_reporter_names[n],
144 384 : getToMultiApp()->problemBase(),
145 192 : getToMultiApp()->appProblemBase(ind),
146 192 : ind);
147 : else
148 744 : transferReporter(_from_reporter_names[n],
149 248 : _to_reporter_names[n],
150 520 : hasFromMultiApp() ? getFromMultiApp()->appProblemBase(ind)
151 360 : : getToMultiApp()->problemBase(),
152 496 : getToMultiApp()->appProblemBase(ind));
153 : }
154 156 : }
155 :
156 : void
157 99 : MultiAppReporterTransfer::executeFromMultiapp()
158 : {
159 99 : if (!hasFromMultiApp())
160 0 : return;
161 :
162 : // subapp indices to perform transfers on
163 99 : std::vector<unsigned int> indices;
164 99 : if (_distribute_reporter_vector)
165 : {
166 : // If distributing, resize the indices vector to the number of global apps
167 33 : indices.resize(getFromMultiApp()->numGlobalApps());
168 33 : std::iota(indices.begin(), indices.end(), 0);
169 : }
170 66 : else if (_subapp_index == std::numeric_limits<unsigned int>::max())
171 : {
172 : // if _subapp_index not set indices is set to 0
173 0 : indices = {0};
174 : }
175 : else
176 : // set indices to specific _subapp_index
177 66 : indices = {_subapp_index};
178 :
179 99 : if (_distribute_reporter_vector)
180 99 : for (const auto n : index_range(_to_reporter_names))
181 : {
182 : // Clear all vector reporters and resize to the number of subapps.
183 : // The summing process later will make sure the reporter values are
184 : // consistent across the processors.
185 66 : auto size = getFromMultiApp()->numGlobalApps();
186 66 : clearVectorReporter(_to_reporter_names[n], getFromMultiApp()->problemBase());
187 66 : resizeReporter(_to_reporter_names[n], getFromMultiApp()->problemBase(), size);
188 : }
189 :
190 297 : for (const auto ind : indices)
191 540 : if (getFromMultiApp()->hasLocalApp(ind) &&
192 342 : (!hasToMultiApp() || getToMultiApp()->hasLocalApp(ind)))
193 400 : for (const auto n : index_range(_from_reporter_names))
194 : {
195 256 : if (_distribute_reporter_vector)
196 : {
197 192 : if (getFromMultiApp()->appProblemBase(ind).processor_id() == 0) // Subapp Root Rank only
198 384 : transferToVectorReporter(_from_reporter_names[n],
199 192 : _to_reporter_names[n],
200 384 : getFromMultiApp()->appProblemBase(ind),
201 384 : getFromMultiApp()->problemBase(),
202 : ind);
203 : }
204 : else
205 128 : transferReporter(_from_reporter_names[n],
206 64 : _to_reporter_names[n],
207 128 : getFromMultiApp()->appProblemBase(ind),
208 128 : hasToMultiApp() ? getToMultiApp()->appProblemBase(ind) // !
209 128 : : getFromMultiApp()->problemBase());
210 : }
211 :
212 99 : if (_distribute_reporter_vector)
213 99 : for (const auto n : index_range(_to_reporter_names))
214 : {
215 : // Perform summing operation that makes sure all procs have the correct
216 : // Reporter values.
217 66 : sumVectorReporter(_to_reporter_names[n], getFromMultiApp()->problemBase());
218 : }
219 99 : }
220 :
221 : void
222 255 : MultiAppReporterTransfer::execute()
223 : {
224 1275 : TIME_SECTION("MultiAppReporterTransfer::execute()", 5, "Transferring reporters");
225 :
226 255 : if (_current_direction == FROM_MULTIAPP)
227 99 : executeFromMultiapp();
228 : else
229 156 : executeToMultiapp();
230 255 : }
231 :
232 : void
233 24 : MultiAppReporterTransfer::checkSiblingsTransferSupported() const
234 : {
235 :
236 24 : if (_distribute_reporter_vector)
237 0 : paramError("distribute_reporter_vector",
238 : "Distributing reporter vectors is not implemented with sibling transfers.");
239 :
240 : // Check that we are in the supported configuration: same number of source and target apps
241 : // The allocation of the child apps on the processors must be the same
242 24 : if (getFromMultiApp()->numGlobalApps() == getToMultiApp()->numGlobalApps())
243 : {
244 72 : for (const auto i : make_range(getToMultiApp()->numGlobalApps()))
245 48 : if (getFromMultiApp()->hasLocalApp(i) + getToMultiApp()->hasLocalApp(i) == 1)
246 0 : mooseError("Child application allocation on parallel processes must be the same to support "
247 : "siblings reporter transfer");
248 : }
249 : else
250 0 : mooseError("Number of source and target child apps must match for siblings transfer");
251 24 : }
252 :
253 : // Helper function to check reporter modes
254 : void
255 78 : MultiAppReporterTransfer::setVectorReporterTransferModes(
256 : const std::shared_ptr<MultiApp> & main_app,
257 : const std::vector<ReporterName> & main_app_rep_names,
258 : const std::vector<ReporterName> & sub_app_rep_names)
259 : {
260 : // Set reporter transfer modes for the main app.
261 228 : for (const auto & rn : main_app_rep_names)
262 150 : addReporterTransferMode(rn, REPORTER_MODE_REPLICATED, main_app->problemBase());
263 :
264 78 : std::vector<unsigned int> indices(main_app->numGlobalApps());
265 78 : std::iota(indices.begin(), indices.end(), 0);
266 :
267 : // Set reporter transfer modes for sub app.
268 : // Setting to ROOT means this works for ROOT and REPLICATED reports with no
269 : // change to users.
270 372 : for (const auto & ind : indices)
271 294 : if (main_app->hasLocalApp(ind))
272 660 : for (const auto & rn : sub_app_rep_names)
273 438 : addReporterTransferMode(rn, REPORTER_MODE_ROOT, main_app->appProblemBase(ind));
274 78 : }
|