www.mooseframework.org
MultiAppTransfer.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 // MOOSE includes
11 #include "MultiAppTransfer.h"
12 #include "Transfer.h"
13 #include "MooseTypes.h"
14 #include "FEProblem.h"
15 #include "DisplacedProblem.h"
16 #include "MultiApp.h"
17 #include "MooseMesh.h"
18 
19 #include "libmesh/parallel_algebra.h"
20 #include "libmesh/mesh_tools.h"
21 
22 template <>
25 {
27  params.addRequiredParam<MultiAppName>("multi_app", "The name of the MultiApp to use.");
28 
29  params.addRequiredParam<MooseEnum>("direction",
31  "Whether this Transfer will be 'to' or 'from' a MultiApp.");
32 
33  // MultiAppTransfers by default will execute with their associated MultiApp. These flags will be
34  // added by FEProblemBase when the transfer is added.
35  ExecFlagEnum & exec_enum = params.set<ExecFlagEnum>("execute_on", true);
37  exec_enum = EXEC_SAME_AS_MULTIAPP;
38  params.setDocString("execute_on", exec_enum.getDocString());
39 
40  params.addParam<bool>(
41  "check_multiapp_execute_on",
42  true,
43  "When false the check between the multiapp and transfer execute on flags is not preformed.");
44  params.addParam<bool>("displaced_source_mesh",
45  false,
46  "Whether or not to use the displaced mesh for the source mesh.");
47  params.addParam<bool>("displaced_target_mesh",
48  false,
49  "Whether or not to use the displaced mesh for the target mesh.");
50  return params;
51 }
52 
54  : Transfer(parameters),
55  _multi_app(_fe_problem.getMultiApp(getParam<MultiAppName>("multi_app"))),
56  _direction(getParam<MooseEnum>("direction")),
57  _displaced_source_mesh(getParam<bool>("displaced_source_mesh")),
58  _displaced_target_mesh(getParam<bool>("displaced_target_mesh"))
59 {
60  if (getParam<bool>("check_multiapp_execute_on"))
62 }
63 
64 void
66 {
67  if (getExecuteOnEnum() != _multi_app->getExecuteOnEnum())
68  mooseDoOnce(mooseWarning("MultiAppTransfer execute_on flags do not match associated Multiapp "
69  "execute_on flags"));
70 }
71 
72 void
73 MultiAppTransfer::variableIntegrityCheck(const AuxVariableName & var_name) const
74 {
75  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
76  if (_multi_app->hasLocalApp(i) && !find_sys(_multi_app->appProblemBase(i).es(), var_name))
77  mooseError("Cannot find variable ", var_name, " for ", name(), " Transfer");
78 }
79 
80 const std::vector<ExecFlagType> &
82 {
83  mooseDeprecated("The execFlags() methos is being removed because MOOSE has been updated to use a "
84  "ExecFlagEnum for execute flags. The current flags should be retrieved from "
85  "the \"exeucte_on\" parameters of your object or by using the \"_execute_enum\" "
86  "reference to the parameter or the getExecuteOnEnum() method.");
87  return _exec_flags;
88 }
89 
90 void
92 {
93  // I would like to do all of this in initialSetup, but it will fail with
94  // multiapps that reset. A reset deletes and rebuilds the FEProblems so all
95  // of the pointers will be broken.
96 
97  // Clear the vectors since we've probably built them up from a previous call
98  _from_problems.clear();
99  _to_problems.clear();
100  _from_es.clear();
101  _to_es.clear();
102  _from_meshes.clear();
103  _to_meshes.clear();
104  _to_positions.clear();
105  _from_positions.clear();
106 
107  // Build the vectors for to problems, from problems, and subapps positions.
108  switch (_direction)
109  {
110  case TO_MULTIAPP:
111  _from_problems.push_back(&_multi_app->problemBase());
112  _from_positions.push_back(Point(0., 0., 0.));
113  for (unsigned int i_app = 0; i_app < _multi_app->numGlobalApps(); i_app++)
114  {
115  if (!_multi_app->hasLocalApp(i_app))
116  continue;
117  _local2global_map.push_back(i_app);
118  _to_problems.push_back(&_multi_app->appProblemBase(i_app));
119  _to_positions.push_back(_multi_app->position(i_app));
120  }
121  break;
122 
123  case FROM_MULTIAPP:
124  _to_problems.push_back(&_multi_app->problemBase());
125  _to_positions.push_back(Point(0., 0., 0.));
126  for (unsigned int i_app = 0; i_app < _multi_app->numGlobalApps(); i_app++)
127  {
128  if (!_multi_app->hasLocalApp(i_app))
129  continue;
130  _local2global_map.push_back(i_app);
131  _from_problems.push_back(&_multi_app->appProblemBase(i_app));
132  _from_positions.push_back(_multi_app->position(i_app));
133  }
134  break;
135  }
136 
137  // Build the from and to equation systems and mesh vectors.
138  for (unsigned int i = 0; i < _to_problems.size(); i++)
139  {
140  // TODO: Do I actually want es or displaced es?
141  _to_es.push_back(&_to_problems[i]->es());
142  if (_displaced_target_mesh && _to_problems[i]->getDisplacedProblem())
143  _to_meshes.push_back(&_to_problems[i]->getDisplacedProblem()->mesh());
144  else
145  _to_meshes.push_back(&_to_problems[i]->mesh());
146  }
147  for (unsigned int i = 0; i < _from_problems.size(); i++)
148  {
149  _from_es.push_back(&_from_problems[i]->es());
150  if (_displaced_source_mesh && _from_problems[i]->getDisplacedProblem())
151  _from_meshes.push_back(&_from_problems[i]->getDisplacedProblem()->mesh());
152  else
153  _from_meshes.push_back(&_from_problems[i]->mesh());
154  }
155 }
156 
157 std::vector<BoundingBox>
159 {
160  std::vector<std::pair<Point, Point>> bb_points(_from_meshes.size());
161  for (unsigned int i = 0; i < _from_meshes.size(); i++)
162  {
163  // Get a bounding box around the mesh elements that are local to the current
164  // processor.
165  BoundingBox bbox = MeshTools::create_local_bounding_box(*_from_meshes[i]);
166 
167  // Translate the bounding box to the from domain's position.
168  bbox.first += _from_positions[i];
169  bbox.second += _from_positions[i];
170 
171  // Cast the bounding box into a pair of points (so it can be put through
172  // MPI communication).
173  bb_points[i] = static_cast<std::pair<Point, Point>>(bbox);
174  }
175 
176  // Serialize the bounding box points.
177  _communicator.allgather(bb_points);
178 
179  // Recast the points back into bounding boxes and return.
180  std::vector<BoundingBox> bboxes(bb_points.size());
181  for (unsigned int i = 0; i < bb_points.size(); i++)
182  bboxes[i] = static_cast<BoundingBox>(bb_points[i]);
183 
184  return bboxes;
185 }
186 
187 std::vector<BoundingBox>
189 {
190  std::vector<std::pair<Point, Point>> bb_points(_from_meshes.size());
191  const Real min_r = std::numeric_limits<Real>::lowest();
192  const Real max_r = std::numeric_limits<Real>::max();
193 
194  for (unsigned int i = 0; i < _from_meshes.size(); i++)
195  {
196 
197  Point min(max_r, max_r, max_r);
198  Point max(min_r, min_r, min_r);
199  bool at_least_one = false;
200 
201  // TODO: Factor this into mesh_tools after adding new boundary bounding box routine.
202  const ConstBndNodeRange & bnd_nodes = *_from_meshes[i]->getBoundaryNodeRange();
203  for (const auto & bnode : bnd_nodes)
204  {
205  if (bnode->_bnd_id == boundary_id && bnode->_node->processor_id() == processor_id())
206  {
207  const auto & node = *bnode->_node;
208  for (unsigned int i = 0; i < LIBMESH_DIM; ++i)
209  {
210  min = std::min(min(i), node(i));
211  max = std::max(max(i), node(i));
212  at_least_one = true;
213  }
214  }
215  }
216 
217  BoundingBox bbox(min, max);
218  if (!at_least_one)
219  bbox.min() = max; // If we didn't hit any nodes, this will be _the_ minimum bbox
220  else
221  {
222  // Translate the bounding box to the from domain's position.
223  bbox.first += _from_positions[i];
224  bbox.second += _from_positions[i];
225  }
226 
227  // Cast the bounding box into a pair of points (so it can be put through
228  // MPI communication).
229  bb_points[i] = static_cast<std::pair<Point, Point>>(bbox);
230  }
231 
232  // Serialize the bounding box points.
233  _communicator.allgather(bb_points);
234 
235  // Recast the points back into bounding boxes and return.
236  std::vector<BoundingBox> bboxes(bb_points.size());
237  for (unsigned int i = 0; i < bb_points.size(); i++)
238  bboxes[i] = static_cast<BoundingBox>(bb_points[i]);
239 
240  return bboxes;
241 }
242 
243 std::vector<unsigned int>
245 {
246  std::vector<unsigned int> froms_per_proc;
247  switch (_direction)
248  {
249  case TO_MULTIAPP:
250  froms_per_proc.resize(n_processors(), 1);
251  break;
252  case FROM_MULTIAPP:
253  froms_per_proc.resize(n_processors());
254  _communicator.allgather(_multi_app->numLocalApps(), froms_per_proc);
255  break;
256  }
257  return froms_per_proc;
258 }
259 
260 NumericVector<Real> &
261 MultiAppTransfer::getTransferVector(unsigned int i_local, std::string var_name)
262 {
263  mooseAssert(_direction == TO_MULTIAPP, "getTransferVector only works for transfers to multiapps");
264 
265  return _multi_app->appTransferVector(_local2global_map[i_local], var_name);
266 }
NumericVector< Real > & getTransferVector(unsigned int i_local, std::string var_name)
If we are transferring to a multiapp, return the appropriate solution vector.
A MultiMooseEnum object to hold "execute_on" flags.
Definition: ExecFlagEnum.h:24
void mooseWarning(Args &&... args) const
Definition: MooseObject.h:155
void setDocString(const std::string &name, const std::string &doc)
Set the doc string of a parameter.
std::vector< EquationSystems * > _to_es
void checkMultiAppExecuteOn()
Helper method for checking the &#39;check_multiapp_execute_on&#39; flag.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
MultiAppTransfer(const InputParameters &parameters)
std::vector< BoundingBox > getFromBoundingBoxes()
Return the bounding boxes of all the "from" domains, including all the domains not local to this proc...
std::vector< FEProblemBase * > _to_problems
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
void addAvailableFlags(const ExecFlagType &flag, Args... flags)
Add additional execute_on flags to the list of possible flags.
Definition: ExecFlagEnum.h:84
std::vector< Point > _from_positions
void mooseError(Args &&... args) const
Definition: MooseObject.h:147
std::shared_ptr< MultiApp > _multi_app
The MultiApp this Transfer is transferring data to or from.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
InputParameters validParams< Transfer >()
Definition: Transfer.C:26
bool _displaced_target_mesh
True if displaced mesh is used for the target mesh, otherwise false.
std::vector< MooseMesh * > _from_meshes
void variableIntegrityCheck(const AuxVariableName &var_name) const
Utility to verify that the vEariable in the destination system exists.
static MooseEnum directions()
Used to construct InputParameters.
boundary_id_type BoundaryID
const ExecFlagEnum & getExecuteOnEnum() const
Return the execute on MultiMooseEnum for this object.
std::vector< unsigned int > getFromsPerProc()
Return the number of "from" domains that each processor owns.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:31
std::vector< unsigned int > _local2global_map
std::vector< Point > _to_positions
std::vector< EquationSystems * > _from_es
void mooseDeprecated(Args &&... args) const
Definition: MooseObject.h:161
InputParameters validParams< MultiAppTransfer >()
bool _displaced_source_mesh
True if displaced mesh is used for the source mesh, otherwise false.
const ExecFlagType EXEC_SAME_AS_MULTIAPP
const std::string & name() const
Get the name of the object.
Definition: MooseObject.h:59
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object...
static System * find_sys(EquationSystems &es, const std::string &var_name)
Small helper function for finding the system containing the variable.
Definition: Transfer.C:65
StoredRange< MooseMesh::const_bnd_node_iterator, const BndNode * > ConstBndNodeRange
Some useful StoredRange typedefs.
Definition: MooseMesh.h:1258
const MooseEnum _direction
Whether we&#39;re transferring to or from the MultiApp.
const std::vector< ExecFlagType > _exec_flags
(DEPRECATED) execution flag (when is the object executed/evaluated) TODO: ExecFlagType ...
virtual const std::vector< ExecFlagType > & execFlags() const
Return the execution flags, handling "same_as_multiapp".
void getAppInfo()
This method will fill information into the convenience member variables (_to_problems, _from_meshes, etc.)
std::vector< FEProblemBase * > _from_problems
std::vector< MooseMesh * > _to_meshes
Base class for all Transfer objects.
Definition: Transfer.h:40