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 : // StochasticTools includes
11 : #include "SamplerTransientMultiApp.h"
12 : #include "Sampler.h"
13 : #include "StochasticToolsTransfer.h"
14 : #include "SamplerFullSolveMultiApp.h"
15 :
16 : registerMooseObject("StochasticToolsApp", SamplerTransientMultiApp);
17 :
18 : InputParameters
19 1304 : SamplerTransientMultiApp::validParams()
20 : {
21 1304 : InputParameters params = TransientMultiApp::validParams();
22 1304 : params += SamplerInterface::validParams();
23 1304 : params.addClassDescription("Creates a sub-application for each row of each Sampler matrix.");
24 2608 : params.addRequiredParam<SamplerName>("sampler",
25 : "The Sampler object to utilize for creating MultiApps.");
26 1304 : params.suppressParameter<std::vector<Point>>("positions");
27 1304 : params.suppressParameter<bool>("output_in_position");
28 1304 : params.suppressParameter<std::vector<FileName>>("positions_file");
29 1304 : params.suppressParameter<Real>("move_time");
30 1304 : params.suppressParameter<std::vector<Point>>("move_positions");
31 1304 : params.suppressParameter<std::vector<unsigned int>>("move_apps");
32 1304 : params.set<bool>("use_positions") = false;
33 :
34 : // use "batch-restore=2" to be consistent with SamplerFullSolveMultiApp and use the
35 : // allow_out_of_range flag to allow the StochasticToolsTransfer object to inspect the MultiApp
36 : // object parameters without triggering an assert.
37 2608 : MooseEnum modes("normal=0 batch-reset=1 batch-restore=2", "normal");
38 2608 : params.addParam<MooseEnum>(
39 : "mode",
40 : modes,
41 : "The operation mode, 'normal' creates one sub-application for each row in the Sampler and "
42 : "'batch-reset' and 'batch-restore' creates N sub-applications, where N is the minimum of "
43 : "'num_rows' in the Sampler and floor(number of processes / min_procs_per_app). To run "
44 : "the rows in the Sampler, 'batch-reset' will destroy and re-create sub-apps as needed, "
45 : "whereas the 'batch-restore' will backup and restore sub-apps to the initial state prior "
46 : "to execution, without destruction.");
47 :
48 1304 : return params;
49 1304 : }
50 :
51 654 : SamplerTransientMultiApp::SamplerTransientMultiApp(const InputParameters & parameters)
52 : : TransientMultiApp(parameters),
53 : SamplerInterface(this),
54 654 : _sampler(getSampler("sampler")),
55 1308 : _mode(getParam<MooseEnum>("mode").getEnum<StochasticTools::MultiAppMode>()),
56 654 : _local_batch_app_index(0),
57 1308 : _number_of_sampler_rows(_sampler.getNumberOfRows())
58 : {
59 654 : if (_mode == StochasticTools::MultiAppMode::BATCH_RESET)
60 8 : paramError("mode",
61 : "The supplied mode, '",
62 : getParam<MooseEnum>("mode"),
63 : "', currently is not implemented for the SamplerTransientMultiApp, the available "
64 : "options are 'normal' or 'batch-restore'.");
65 :
66 1300 : if (getParam<unsigned int>("min_procs_per_app") !=
67 1950 : _sampler.getParam<unsigned int>("min_procs_per_row") ||
68 1300 : getParam<unsigned int>("max_procs_per_app") !=
69 1950 : _sampler.getParam<unsigned int>("max_procs_per_row"))
70 0 : paramError("sampler",
71 : "Sampler and multiapp communicator configuration inconsistent. Please ensure that "
72 : "'MultiApps/",
73 : name(),
74 : "/min(max)_procs_per_app' and 'Samplers/",
75 0 : _sampler.name(),
76 : "/min(max)_procs_per_row' are the same.");
77 :
78 650 : init(_sampler.getNumberOfRows(),
79 650 : _sampler.getRankConfig(_mode == StochasticTools::MultiAppMode::BATCH_RESET ||
80 : _mode == StochasticTools::MultiAppMode::BATCH_RESTORE));
81 650 : }
82 :
83 : void
84 642 : SamplerTransientMultiApp::initialSetup()
85 : {
86 1284 : TIME_SECTION("initialSetup", 2, "Setting Up SamplerTransientMultiApp");
87 :
88 642 : TransientMultiApp::initialSetup();
89 :
90 : // Perform initial backup for the batch sub-applications
91 642 : if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
92 : {
93 180 : dof_id_type n = _rank_config.num_local_sims;
94 180 : _batch_backup.resize(n);
95 680 : for (MooseIndex(n) i = 0; i < n; ++i)
96 1000 : for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
97 500 : _batch_backup[i].emplace_back(_apps[j]->backup());
98 : }
99 642 : }
100 :
101 : bool
102 1978 : SamplerTransientMultiApp::solveStep(Real dt, Real target_time, bool auto_advance)
103 : {
104 3956 : TIME_SECTION("solveStep", 3, "Solving SamplerTransientMultiApp");
105 :
106 1978 : if (_sampler.getNumberOfRows() != _number_of_sampler_rows)
107 4 : mooseError("The size of the sampler has changed; SamplerTransientMultiApp object do not "
108 : "support dynamic Sampler output.");
109 :
110 : bool last_solve_converged = true;
111 1974 : if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
112 588 : last_solve_converged = solveStepBatch(dt, target_time, auto_advance);
113 : else
114 1386 : last_solve_converged = TransientMultiApp::solveStep(dt, target_time, auto_advance);
115 1966 : return last_solve_converged;
116 : }
117 :
118 : bool
119 588 : SamplerTransientMultiApp::solveStepBatch(Real dt, Real target_time, bool auto_advance)
120 : {
121 : // Value to return
122 : bool last_solve_converged = true;
123 :
124 : // List of active relevant Transfer objects
125 : std::vector<std::shared_ptr<StochasticToolsTransfer>> to_transfers =
126 588 : getActiveStochasticToolsTransfers(MultiAppTransfer::TO_MULTIAPP);
127 : std::vector<std::shared_ptr<StochasticToolsTransfer>> from_transfers =
128 588 : getActiveStochasticToolsTransfers(MultiAppTransfer::FROM_MULTIAPP);
129 :
130 : // Initialize to/from transfers
131 1176 : for (auto transfer : to_transfers)
132 : {
133 588 : transfer->setGlobalMultiAppIndex(_rank_config.first_local_app_index);
134 588 : transfer->initializeToMultiapp();
135 : }
136 1176 : for (auto transfer : from_transfers)
137 : {
138 588 : transfer->setGlobalMultiAppIndex(_rank_config.first_local_app_index);
139 588 : transfer->initializeFromMultiapp();
140 : }
141 :
142 : // Perform batch MultiApp solves
143 588 : _local_batch_app_index = 0;
144 588 : for (dof_id_type i = _rank_config.first_local_sim_index;
145 2288 : i < _rank_config.first_local_sim_index + _rank_config.num_local_sims;
146 : ++i)
147 : {
148 1700 : updateRowData(_local_batch_app_index);
149 :
150 1700 : if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
151 3400 : for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
152 : {
153 1700 : _apps[j]->restore(std::move(_batch_backup[_local_batch_app_index][j]), false);
154 1700 : _apps[j]->finalizeRestore();
155 : }
156 :
157 1700 : SamplerFullSolveMultiApp::execBatchTransfers(to_transfers,
158 : i,
159 1700 : _row_data,
160 : MultiAppTransfer::TO_MULTIAPP,
161 1700 : _fe_problem.verboseMultiApps(),
162 1700 : _console);
163 :
164 : // Set the file base based on the current row
165 3400 : for (unsigned int ai = 0; ai < _my_num_apps; ++ai)
166 : {
167 1700 : const std::string mname = getMultiAppName(name(), i, _number_of_sampler_rows);
168 5100 : _apps[ai]->setOutputFileBase(_app.getOutputFileBase() + "_" + mname);
169 : }
170 :
171 : const bool curr_last_solve_converged =
172 1700 : TransientMultiApp::solveStep(dt, target_time, auto_advance);
173 1700 : last_solve_converged = last_solve_converged && curr_last_solve_converged;
174 :
175 1700 : SamplerFullSolveMultiApp::execBatchTransfers(from_transfers,
176 : i,
177 : _row_data,
178 : MultiAppTransfer::FROM_MULTIAPP,
179 1700 : _fe_problem.verboseMultiApps(),
180 : _console);
181 :
182 1700 : incrementTStep(target_time);
183 :
184 1700 : if (_mode == StochasticTools::MultiAppMode::BATCH_RESTORE)
185 3400 : for (MooseIndex(_my_num_apps) j = 0; j < _my_num_apps; j++)
186 1700 : _batch_backup[_local_batch_app_index][j] = _apps[j]->backup();
187 :
188 1700 : _local_batch_app_index++;
189 : }
190 588 : _local_batch_app_index = 0;
191 :
192 : // Finalize to/from transfers
193 1176 : for (auto transfer : to_transfers)
194 588 : transfer->finalizeToMultiapp();
195 1176 : for (auto transfer : from_transfers)
196 588 : transfer->finalizeFromMultiapp();
197 :
198 588 : return last_solve_converged;
199 588 : }
200 :
201 : std::vector<std::shared_ptr<StochasticToolsTransfer>>
202 1176 : SamplerTransientMultiApp::getActiveStochasticToolsTransfers(Transfer::DIRECTION direction)
203 : {
204 : std::vector<std::shared_ptr<StochasticToolsTransfer>> output;
205 : const ExecuteMooseObjectWarehouse<Transfer> & warehouse =
206 1176 : _fe_problem.getMultiAppTransferWarehouse(direction);
207 2416 : for (std::shared_ptr<Transfer> transfer : warehouse.getActiveObjects())
208 : {
209 : std::shared_ptr<StochasticToolsTransfer> ptr =
210 1240 : std::dynamic_pointer_cast<StochasticToolsTransfer>(transfer);
211 2416 : if (ptr && ptr->getMultiApp().get() == this)
212 1176 : output.push_back(ptr);
213 : }
214 1176 : return output;
215 0 : }
216 :
217 : std::vector<std::string>
218 456 : SamplerTransientMultiApp::getCommandLineArgs(const unsigned int local_app)
219 : {
220 : std::vector<std::string> args;
221 :
222 : // With multiple processors per app, there are no local rows for non-root processors
223 456 : if (isRootProcessor())
224 : {
225 : // Since we only store param_names in cli_args, we need to find the values for each param from
226 : // sampler data and combine them to get full command line option strings.
227 396 : updateRowData(_mode == StochasticTools::MultiAppMode::NORMAL ? local_app
228 : : _local_batch_app_index);
229 396 : args = SamplerFullSolveMultiApp::sampledCommandLineArgs(
230 792 : _row_data, TransientMultiApp::getCommandLineArgs(local_app));
231 : }
232 :
233 456 : _my_communicator.broadcast(args);
234 456 : return args;
235 0 : }
236 :
237 : void
238 2096 : SamplerTransientMultiApp::updateRowData(dof_id_type local_index)
239 : {
240 2096 : if (!isRootProcessor())
241 : return;
242 :
243 : mooseAssert(local_index < _sampler.getNumberOfLocalRows(),
244 : "Local index must be less than number of local rows.");
245 :
246 1916 : if (_row_data.empty() ||
247 1632 : (_local_row_index == _sampler.getNumberOfLocalRows() - 1 && local_index == 0))
248 : {
249 : mooseAssert(local_index == 0,
250 : "The first time calling updateRowData must have a local index of 0.");
251 632 : _local_row_index = 0;
252 1264 : _row_data = _sampler.getNextLocalRow();
253 : }
254 1284 : else if (local_index - _local_row_index == 1)
255 : {
256 1268 : _local_row_index++;
257 2536 : _row_data = _sampler.getNextLocalRow();
258 : }
259 :
260 : mooseAssert(local_index == _local_row_index,
261 : "Local index must be equal or one greater than the index previously called.");
262 : }
|