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 14953 : MultiAppReporterTransfer::validParams()
18 : {
19 14953 : InputParameters params = MultiAppTransfer::validParams();
20 14953 : params += ReporterTransferInterface::validParams();
21 14953 : params.addClassDescription("Transfers reporter data between two applications.");
22 14953 : params.addRequiredParam<std::vector<ReporterName>>(
23 : "from_reporters",
24 : "List of the reporter names (object_name/value_name) to transfer the value from.");
25 14953 : params.addRequiredParam<std::vector<ReporterName>>(
26 : "to_reporters",
27 : "List of the reporter names (object_name/value_name) to transfer the value to.");
28 44859 : params.addParam<unsigned int>(
29 : "subapp_index",
30 29906 : 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 44859 : params.addParam<bool>(
36 : "distribute_reporter_vector",
37 29906 : 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 14953 : return params;
42 0 : }
43 :
44 316 : MultiAppReporterTransfer::MultiAppReporterTransfer(const InputParameters & parameters)
45 : : MultiAppTransfer(parameters),
46 : ReporterTransferInterface(this),
47 316 : _from_reporter_names(getParam<std::vector<ReporterName>>("from_reporters")),
48 316 : _to_reporter_names(getParam<std::vector<ReporterName>>("to_reporters")),
49 316 : _subapp_index(getParam<unsigned int>("subapp_index")),
50 632 : _distribute_reporter_vector(getParam<bool>("distribute_reporter_vector"))
51 : {
52 316 : 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 316 : if (_directions.size() > 1)
56 0 : paramError("direction", "This transfer only supports a single direction.");
57 :
58 340 : 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 316 : if (hasFromMultiApp())
64 : {
65 164 : const auto multi_app = getFromMultiApp();
66 : // Errors for sub app index.
67 260 : if (_subapp_index != std::numeric_limits<unsigned int>::max() &&
68 96 : _subapp_index >= multi_app->numGlobalApps())
69 4 : paramError(
70 : "subapp_index",
71 : "The supplied sub-application index is greater than the number of sub-applications.");
72 296 : else if (_directions.isValueSet(FROM_MULTIAPP) &&
73 180 : _subapp_index == std::numeric_limits<unsigned int>::max() &&
74 340 : multi_app->numGlobalApps() > 1 && !_distribute_reporter_vector)
75 4 : paramError("from_multi_app",
76 : "subapp_index must be provided when more than one subapp is present.");
77 156 : }
78 152 : else if (hasToMultiApp())
79 : {
80 : // Errors for sub app index.
81 232 : if (_subapp_index != std::numeric_limits<unsigned int>::max() &&
82 232 : _subapp_index >= getToMultiApp()->numGlobalApps())
83 4 : paramError(
84 : "subapp_index",
85 : "The supplied sub-application index is greater than the number of sub-applications.");
86 : }
87 304 : }
88 :
89 : void
90 260 : MultiAppReporterTransfer::initialSetup()
91 : {
92 260 : 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 260 : FEProblemBase * problem_ptr = nullptr;
98 260 : if (_directions.isValueSet(TO_MULTIAPP))
99 124 : problem_ptr = &getToMultiApp()->problemBase();
100 200 : else if (_subapp_index == std::numeric_limits<unsigned int>::max() &&
101 200 : getFromMultiApp()->hasLocalApp(0))
102 49 : 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 260 : 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 260 : if (_distribute_reporter_vector)
113 : {
114 80 : if (hasFromMultiApp())
115 40 : setVectorReporterTransferModes(getFromMultiApp(), _to_reporter_names, _from_reporter_names);
116 40 : else if (hasToMultiApp())
117 40 : setVectorReporterTransferModes(getToMultiApp(), _from_reporter_names, _to_reporter_names);
118 : }
119 260 : }
120 :
121 : void
122 1010 : MultiAppReporterTransfer::executeToMultiapp()
123 : {
124 1010 : if (!hasToMultiApp())
125 0 : return;
126 :
127 1010 : std::vector<unsigned int> indices;
128 1010 : if (_subapp_index == std::numeric_limits<unsigned int>::max())
129 : {
130 955 : indices.resize(getToMultiApp()->numGlobalApps());
131 955 : std::iota(indices.begin(), indices.end(), 0);
132 : }
133 : else
134 55 : indices = {_subapp_index};
135 :
136 3041 : for (const auto & ind : indices)
137 5502 : if (getToMultiApp()->hasLocalApp(ind) &&
138 3471 : (!hasFromMultiApp() || getFromMultiApp()->hasLocalApp(ind)))
139 4288 : for (unsigned int n = 0; n < _from_reporter_names.size(); ++n)
140 : {
141 2848 : 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 7968 : transferReporter(_from_reporter_names[n],
149 2656 : _to_reporter_names[n],
150 7744 : hasFromMultiApp() ? getFromMultiApp()->appProblemBase(ind)
151 2768 : : getToMultiApp()->problemBase(),
152 5312 : getToMultiApp()->appProblemBase(ind));
153 : }
154 1010 : }
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 1109 : MultiAppReporterTransfer::execute()
223 : {
224 1109 : TIME_SECTION("MultiAppReporterTransfer::execute()", 5, "Transferring reporters");
225 :
226 1109 : if (_current_direction == FROM_MULTIAPP)
227 99 : executeFromMultiapp();
228 : else
229 1010 : executeToMultiapp();
230 1109 : }
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 80 : 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 232 : for (const auto & rn : main_app_rep_names)
262 152 : addReporterTransferMode(rn, REPORTER_MODE_REPLICATED, main_app->problemBase());
263 :
264 80 : std::vector<unsigned int> indices(main_app->numGlobalApps());
265 80 : 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 376 : for (const auto & ind : indices)
271 296 : if (main_app->hasLocalApp(ind))
272 664 : for (const auto & rn : sub_app_rep_names)
273 440 : addReporterTransferMode(rn, REPORTER_MODE_ROOT, main_app->appProblemBase(ind));
274 80 : }
|