forked from idaholab/moose
-
Notifications
You must be signed in to change notification settings - Fork 1
/
MultiApp.h
428 lines (348 loc) · 12.6 KB
/
MultiApp.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
/****************************************************************/
/* DO NOT MODIFY THIS HEADER */
/* MOOSE - Multiphysics Object Oriented Simulation Environment */
/* */
/* (c) 2010 Battelle Energy Alliance, LLC */
/* ALL RIGHTS RESERVED */
/* */
/* Prepared by Battelle Energy Alliance, LLC */
/* Under Contract No. DE-AC07-05ID14517 */
/* With the U. S. Department of Energy */
/* */
/* See COPYRIGHT for full restrictions */
/****************************************************************/
#ifndef MULTIAPP_H
#define MULTIAPP_H
#include "MooseObject.h"
#include "SetupInterface.h"
#include "Restartable.h"
class MultiApp;
class UserObject;
class FEProblemBase;
class FEProblem;
class Executioner;
class MooseApp;
class Backup;
// libMesh forward declarations
namespace libMesh
{
class BoundingBox;
namespace MeshTools
{
class BoundingBox;
}
template <typename T>
class NumericVector;
}
template <>
InputParameters validParams<MultiApp>();
/**
* Helper class for holding Sub-app backups
*/
class SubAppBackups : public std::vector<std::shared_ptr<Backup>>
{
};
/**
* A MultiApp represents one or more MOOSE applications that are running simultaneously.
* These other MOOSE apps generally represent some "sub-solve" or "embedded-solves"
* of the overall nonlinear solve. If your system support dynamic libraries unregistered
* Multiapps can be loaded on the fly by setting the exporting the appropriate library
* path using "MOOSE_LIBRARY_PATH" or by specifying a single input file library path
* in Multiapps InputParameters object.
*/
class MultiApp : public MooseObject, public SetupInterface, public Restartable
{
public:
MultiApp(const InputParameters & parameters);
virtual void preExecute() {}
virtual void postExecute();
virtual void initialSetup() override;
/**
* Method that reports whether the application has been fully solved or not.
* Most transient multiapps are never fully solved, however this method can be
* overridden in derived classes.
*/
virtual bool isSolved() const { return false; }
/**
* Gets called just before transfers are done _to_ the MultiApp
* (Which is just before the MultiApp is solved)
*/
virtual void preTransfer(Real dt, Real target_time);
/**
* Re-solve all of the Apps.
*
* Can be called multiple times to resolve the same timestep
* if auto_advance=false. Time is not actually advanced until
* advanceStep() is called.
*
* Note that auto_advance=false might not be compatible with
* the options for the MultiApp
*
* @return Whether or not all of the solves were successful (i.e. all solves made it to the
* target_time)
*/
virtual bool solveStep(Real dt, Real target_time, bool auto_advance = true) = 0;
/**
* Advances the multi-apps time step which is important for dt selection.
* (Note this does not advance the *time*. That is done in Transient::endStep,
* which is called either directly from solveStep() for loose coupling cases
* or through finishStep() for Picard coupling cases)
*/
virtual void incrementTStep() = 0;
/**
* Calls multi-apps executioners' endStep and postStep methods which creates output and advances
* time (not the time step; see incrementTStep()) among other things. This method is only called
* for Picard calculations and is called *after* the master application's executioner's endStep
* method. Consequently Picard may not work in conjunction with restart since the sub-app's time
* will not have been updated before the restartable data file is written.
*/
virtual void finishStep() = 0;
/**
* Save off the state of every Sub App
*
* This allows us to "Restore" this state later
*/
virtual void backup();
/**
* Restore the state of every Sub App
*
* This allows us to "Restore" this state later
*/
virtual void restore();
/**
* Whether or not this MultiApp should be restored at the beginning of
* each Picard iteration.
*/
virtual bool needsRestoration() { return true; }
/**
* @param app The global app number to get the Executioner for
* @return The Executioner associated with that App.
*/
virtual Executioner * getExecutioner(unsigned int app);
/**
* Get the BoundingBox for the mesh associated with app
* The bounding box will be shifted to be in the correct position
* within the master domain.
* If the MultiApp is in an RZ coordinate system the box will be
* the size it would be if the geometry were 3D (ie if you were to revolve
* the geometry around the axis to create the 3D geometry).
* @param app The global app number you want to get the bounding box for
*/
virtual BoundingBox getBoundingBox(unsigned int app);
/**
* Get the FEProblemBase this MultiApp is part of.
*/
FEProblemBase & problemBase() { return _fe_problem; }
/**
* Get the FEProblemBase for the global app is part of.
* @param app The global app number
*/
FEProblemBase & appProblemBase(unsigned int app);
/**
* Get the FEProblem for the global app is part of.
* @param app The global app number
*/
FEProblem & appProblem(unsigned int app);
/**
* Get a UserObject base for a specific global app
* @param app The global app number you want to get a UserObject from.
* @param name The name of the UserObject.
*/
const UserObject & appUserObjectBase(unsigned int app, const std::string & name);
/**
* Get a Postprocessor value for a specified global app
* @param app The global app number you want to get a Postprocessor from.
* @param name The name of the Postprocessor.
*/
Real appPostprocessorValue(unsigned int app, const std::string & name);
/**
* Get the vector to transfer to for this MultiApp.
* In general this is the Auxiliary system solution vector.
*
* @param app The global app number you want the transfer vector for.
* @param var_name The name of the variable you are going to be transferring to.
* @return The vector to fill.
*/
virtual NumericVector<Number> & appTransferVector(unsigned int app, std::string var_name);
/**
* @return Number of Global Apps in this MultiApp
*/
unsigned int numGlobalApps() { return _total_num_apps; }
/**
* @return Number of Apps on local processor.
*/
unsigned int numLocalApps() { return _apps.size(); }
/**
* @return The global number of the first app on the local processor.
*/
unsigned int firstLocalApp() { return _first_local_app; }
/**
* Whether or not this MultiApp has an app on this processor.
*/
bool hasApp() { return _has_an_app; }
/**
* Whether or not the given global app number is on this processor.
* @param global_app The global app number in question
* @return True if the global app is on this processor
*/
bool hasLocalApp(unsigned int global_app);
/**
* Get the local MooseApp object
* @param local_app The local app number
*/
MooseApp * localApp(unsigned int local_app);
/**
* The physical position of a global App number
* @param app The global app number you want the position for.
* @return the position
*/
Point position(unsigned int app) { return _positions[app]; }
/**
* "Reset" the App corresponding to the global App number
* passed in. "Reset" means that the App will be deleted
* and recreated. The time for the new App will be set
* to the current simulation time. This might be handy
* if some sub-app in your simulation needs to get replaced
* by a "new" piece of material.
*
* @param global_app The global app number to reset.
* @param time The time to set as the the time for the new app, this should really be the time the
* old app was at.
*/
virtual void resetApp(unsigned int global_app, Real time = 0.0);
/**
* Move the global_app to Point p.
*
* @param global_app The global app number in question
* @param p The new position of the App.
*/
virtual void moveApp(unsigned int global_app, Point p);
/**
* For apps outputting in position we need to change their output positions
* if their parent app moves.
*/
virtual void parentOutputPositionChanged();
/**
* Get the MPI communicator this MultiApp is operating on.
* @return The MPI comm for this MultiApp
*/
MPI_Comm & comm() { return _my_comm; }
/**
* Whether or not this processor is the "root" processor for the sub communicator.
* The "root" processor has rank 0 in the sub communicator
*/
bool isRootProcessor() { return _my_rank == 0; }
protected:
/**
* _must_ fill in _positions with the positions of the sub-aps
*/
virtual void fillPositions();
/**
* Helper function for creating an App instance.
*
* @param i The local app number to create.
* @param start_time The initial time for the App
*/
void createApp(unsigned int i, Real start_time);
/**
* Create an MPI communicator suitable for each app.
*
* Also find out which communicator we are using and what our first local app is.
*/
void buildComm();
/**
* Map a global App number to the local number.
* Note: This will error if given a global number that doesn't map to a local number.
*
* @param global_app The global app number.
* @return The local app number.
*/
unsigned int globalAppToLocal(unsigned int global_app);
/// call back executed right before app->runInputFile()
virtual void preRunInputFile();
/**
* Initialize the MultiApp by creating the provided number of apps.
*
* This is called in the constructor, by default it utilizes the 'positions' input parameters.
*/
void init(unsigned int num);
/// The FEProblemBase this MultiApp is part of
FEProblemBase & _fe_problem;
/// The type of application to build
std::string _app_type;
/// The positions of all of the apps
std::vector<Point> _positions;
/// Toggle use of "positions"
const bool _use_positions;
/// The input file for each app's simulation
std::vector<FileName> _input_files;
/// The output file basename for each multiapp
std::string _output_base;
/// The total number of apps to simulate
unsigned int _total_num_apps;
/// The number of apps this object is involved in simulating
unsigned int _my_num_apps;
/// The number of the first app on this processor
unsigned int _first_local_app;
/// The comm that was passed to us specifying our pool of processors
MPI_Comm _orig_comm;
/// The MPI communicator this object is going to use.
MPI_Comm _my_comm;
/// The number of processors in the original comm
int _orig_num_procs;
/// The mpi "rank" of this processor in the original communicator
int _orig_rank;
/// Node Name
std::string _node_name;
/// The mpi "rank" of this processor in the sub communicator
int _my_rank;
/// Pointers to each of the Apps
std::vector<std::shared_ptr<MooseApp>> _apps;
/// Relative bounding box inflation
Real _inflation;
/// Maximum number of processors to give to each app
unsigned int _max_procs_per_app;
/// Whether or not to move the output of the MultiApp into position
bool _output_in_position;
/// The time at which to reset apps
Real _reset_time;
/// The apps to be reset
std::vector<unsigned int> _reset_apps;
/// Whether or not apps have been reset
bool _reset_happened;
/// The time at which to move apps
Real _move_time;
/// The apps to be moved
std::vector<unsigned int> _move_apps;
/// The new positions for the apps to be moved
std::vector<Point> _move_positions;
/// Whether or not the move has happened
bool _move_happened;
/// Whether or not this processor as an App _at all_
bool _has_an_app;
/// Backups for each local App
SubAppBackups & _backups;
};
template <>
inline void
dataStore(std::ostream & stream, SubAppBackups & backups, void * context)
{
MultiApp * multi_app = static_cast<MultiApp *>(context);
multi_app->backup();
if (!multi_app)
mooseError("Error storing std::vector<Backup*>");
for (unsigned int i = 0; i < backups.size(); i++)
dataStore(stream, backups[i], context);
}
template <>
inline void
dataLoad(std::istream & stream, SubAppBackups & backups, void * context)
{
MultiApp * multi_app = static_cast<MultiApp *>(context);
if (!multi_app)
mooseError("Error loading std::vector<Backup*>");
for (unsigned int i = 0; i < backups.size(); i++)
dataLoad(stream, backups[i], context);
multi_app->restore();
}
#endif // MULTIAPP_H