www.mooseframework.org
MultiAppUserObjectTransfer.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 
11 
12 #include <limits>
13 
14 // MOOSE includes
15 #include "DisplacedProblem.h"
16 #include "FEProblem.h"
17 #include "MooseMesh.h"
18 #include "MooseTypes.h"
19 #include "MooseVariableFE.h"
20 #include "MultiApp.h"
21 #include "UserObject.h"
22 
23 // libMesh
24 #include "libmesh/meshfree_interpolation.h"
25 #include "libmesh/system.h"
26 #include "libmesh/mesh_function.h"
27 #include "libmesh/mesh_tools.h"
28 
30 
31 template <>
34 {
36  params.addRequiredParam<AuxVariableName>(
37  "variable", "The auxiliary variable to store the transferred values in.");
38  params.addRequiredParam<UserObjectName>(
39  "user_object",
40  "The UserObject you want to transfer values from. Note: This might be a "
41  "UserObject from your MultiApp's input file!");
42  params.addParam<bool>("all_master_nodes_contained_in_sub_app",
43  false,
44  "Set to true if every master node is mapped to a distinct point on one of "
45  "the subApps during a transfer from sub App to Master App. If master node "
46  "cannot be found within bounding boxes of any of the subApps, an error is "
47  "generated.");
48  return params;
49 }
50 
52  : MultiAppTransfer(parameters),
53  _to_var_name(getParam<AuxVariableName>("variable")),
54  _user_object_name(getParam<UserObjectName>("user_object")),
55  _all_master_nodes_contained_in_sub_app(getParam<bool>("all_master_nodes_contained_in_sub_app"))
56 {
57  // This transfer does not work with DistributedMesh
58  _fe_problem.mesh().errorIfDistributedMesh("MultiAppUserObjectTransfer");
59 }
60 
61 void
63 {
64  if (_direction == TO_MULTIAPP)
66 }
67 
68 void
70 {
71  _console << "Beginning MultiAppUserObjectTransfer " << name() << std::endl;
72 
73  switch (_direction)
74  {
75  case TO_MULTIAPP:
76  {
77  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
78  {
79  if (_multi_app->hasLocalApp(i))
80  {
81  Moose::ScopedCommSwapper swapper(_multi_app->comm());
82 
83  // Loop over the master nodes and set the value of the variable
84  System * to_sys = find_sys(_multi_app->appProblemBase(i).es(), _to_var_name);
85 
86  unsigned int sys_num = to_sys->number();
87  unsigned int var_num = to_sys->variable_number(_to_var_name);
88 
89  NumericVector<Real> & solution = _multi_app->appTransferVector(i, _to_var_name);
90 
91  MeshBase * mesh = NULL;
92 
93  if (_displaced_target_mesh && _multi_app->appProblemBase(i).getDisplacedProblem())
94  {
95  mesh = &_multi_app->appProblemBase(i).getDisplacedProblem()->mesh().getMesh();
96  }
97  else
98  mesh = &_multi_app->appProblemBase(i).mesh().getMesh();
99 
100  bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE;
101 
102  const UserObject & user_object =
103  _multi_app->problemBase().getUserObjectBase(_user_object_name);
104 
105  if (is_nodal)
106  {
107  for (auto & node : mesh->local_node_ptr_range())
108  {
109  if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
110  {
111  // The zero only works for LAGRANGE!
112  dof_id_type dof = node->dof_number(sys_num, var_num, 0);
113 
114  swapper.forceSwap();
115  Real from_value = user_object.spatialValue(*node + _multi_app->position(i));
116  swapper.forceSwap();
117 
118  solution.set(dof, from_value);
119  }
120  }
121  }
122  else // Elemental
123  {
124  for (auto & elem : as_range(mesh->local_elements_begin(), mesh->local_elements_end()))
125  {
126  Point centroid = elem->centroid();
127 
128  if (elem->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this elem
129  {
130  // The zero only works for LAGRANGE!
131  dof_id_type dof = elem->dof_number(sys_num, var_num, 0);
132 
133  swapper.forceSwap();
134  Real from_value = user_object.spatialValue(centroid + _multi_app->position(i));
135  swapper.forceSwap();
136 
137  solution.set(dof, from_value);
138  }
139  }
140  }
141 
142  solution.close();
143  to_sys->update();
144  }
145  }
146 
147  break;
148  }
149  case FROM_MULTIAPP:
150  {
151  FEProblemBase & to_problem = _multi_app->problemBase();
152  MooseVariableFEBase & to_var = to_problem.getVariable(
154  SystemBase & to_system_base = to_var.sys();
155 
156  System & to_sys = to_system_base.system();
157 
158  unsigned int to_sys_num = to_sys.number();
159 
160  // Only works with a serialized mesh to transfer to!
161  mooseAssert(to_sys.get_mesh().is_serial(),
162  "MultiAppUserObjectTransfer only works with ReplicatedMesh!");
163 
164  unsigned int to_var_num = to_sys.variable_number(to_var.name());
165 
166  _console << "Transferring to: " << to_var.name() << std::endl;
167 
168  // EquationSystems & to_es = to_sys.get_equation_systems();
169 
170  // Create a serialized version of the solution vector
171  NumericVector<Number> * to_solution = to_sys.solution.get();
172 
173  MeshBase * to_mesh = NULL;
174 
175  if (_displaced_target_mesh && to_problem.getDisplacedProblem())
176  to_mesh = &to_problem.getDisplacedProblem()->mesh().getMesh();
177  else
178  to_mesh = &to_problem.mesh().getMesh();
179 
180  bool is_nodal = to_sys.variable_type(to_var_num).family == LAGRANGE;
181 
183  {
184  // check to see if master nodes or elements lies within any of the sub application bounding
185  // boxes
186  if (is_nodal)
187  {
188  for (auto & node : to_mesh->node_ptr_range())
189  {
190  if (node->n_dofs(to_sys_num, to_var_num) > 0)
191  {
192  unsigned int node_found_in_sub_app = 0;
193  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
194  {
195  if (!_multi_app->hasLocalApp(i))
196  continue;
197 
198  BoundingBox app_box = _multi_app->getBoundingBox(i, _displaced_source_mesh);
199 
200  if (app_box.contains_point(*node))
201  ++node_found_in_sub_app;
202  }
203 
204  if (node_found_in_sub_app == 0)
205  {
206  Point n = *node;
207  mooseError("MultiAppUserObjectTransfer: Master node ",
208  n,
209  " not found within the bounding box of any of the sub applications.");
210  }
211  else if (node_found_in_sub_app > 1)
212  {
213  Point n = *node;
214  mooseError("MultiAppUserObjectTransfer: Master node ",
215  n,
216  " found within the bounding box of two or more sub applications.");
217  }
218  }
219  }
220  }
221  else // elemental
222  {
223  for (auto & elem : as_range(to_mesh->elements_begin(), to_mesh->elements_end()))
224  {
225  if (elem->n_dofs(to_sys_num, to_var_num) > 0) // If this variable has dofs at this elem
226  {
227  unsigned int elem_found_in_sub_app = 0;
228  Point centroid = elem->centroid();
229 
230  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
231  {
232  if (!_multi_app->hasLocalApp(i))
233  continue;
234 
235  BoundingBox app_box = _multi_app->getBoundingBox(i, _displaced_source_mesh);
236 
237  if (app_box.contains_point(centroid))
238  ++elem_found_in_sub_app;
239  }
240 
241  if (elem_found_in_sub_app == 0)
242  mooseError("MultiAppUserObjectTransfer: Master element with centroid at ",
243  centroid,
244  " not found within the bounding box of any of the sub applications.");
245  else if (elem_found_in_sub_app > 1)
246  mooseError("MultiAppUserObjectTransfer: Master element with centroid at ",
247  centroid,
248  " found within the bounding box of two or more sub applications.");
249  }
250  }
251  }
252  }
253 
254  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
255  {
256  if (!_multi_app->hasLocalApp(i))
257  continue;
258 
259  Point app_position = _multi_app->position(i);
260  BoundingBox app_box = _multi_app->getBoundingBox(i, _displaced_source_mesh);
261  const UserObject & user_object = _multi_app->appUserObjectBase(i, _user_object_name);
262 
263  if (is_nodal)
264  {
265  for (auto & node : to_mesh->node_ptr_range())
266  {
267  if (node->n_dofs(to_sys_num, to_var_num) > 0) // If this variable has dofs at this node
268  {
269  // See if this node falls in this bounding box
270  if (app_box.contains_point(*node))
271  {
272  dof_id_type dof = node->dof_number(to_sys_num, to_var_num, 0);
273 
274  Real from_value = 0;
275  {
276  Moose::ScopedCommSwapper swapper(_multi_app->comm());
277  from_value = user_object.spatialValue(*node - app_position);
278  }
279 
280  if (from_value == std::numeric_limits<Real>::infinity())
281  {
282  Point n = *node;
283  mooseError("MultiAppUserObjectTransfer: Point corresponding to master node at (",
284  n,
285  ") not found in the sub application.");
286  }
287  to_solution->set(dof, from_value);
288  }
289  }
290  }
291  }
292  else // Elemental
293  {
294  for (auto & elem : as_range(to_mesh->elements_begin(), to_mesh->elements_end()))
295  {
296  if (elem->n_dofs(to_sys_num, to_var_num) > 0) // If this variable has dofs at this elem
297  {
298  Point centroid = elem->centroid();
299 
300  // See if this elem falls in this bounding box
301  if (app_box.contains_point(centroid))
302  {
303  dof_id_type dof = elem->dof_number(to_sys_num, to_var_num, 0);
304 
305  Real from_value = 0;
306  {
307  Moose::ScopedCommSwapper swapper(_multi_app->comm());
308  from_value = user_object.spatialValue(centroid - app_position);
309  }
310 
311  if (from_value == std::numeric_limits<Real>::infinity())
312  mooseError(
313  "MultiAppUserObjectTransfer: Point corresponding to element's centroid (",
314  centroid,
315  ") not found in sub application.");
316 
317  to_solution->set(dof, from_value);
318  }
319  }
320  }
321  }
322  }
323 
324  to_solution->close();
325  to_sys.update();
326 
327  break;
328  }
329  }
330 
331  _console << "Finished MultiAppUserObjectTransfer " << name() << std::endl;
332 }
virtual MooseVariableFEBase & getVariable(THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) override
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
virtual void execute() override
Execute the transfer.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
FEProblemBase & _fe_problem
Definition: Transfer.h:69
void mooseError(Args &&... args) const
Definition: MooseObject.h:147
Base class for a system (of equations)
Definition: SystemBase.h:92
std::shared_ptr< MultiApp > _multi_app
The MultiApp this Transfer is transferring data to or from.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
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...
bool _displaced_target_mesh
True if displaced mesh is used for the target mesh, otherwise false.
void errorIfDistributedMesh(std::string name) const
Generate a unified error message if the underlying libMesh mesh is a DistributedMesh.
Definition: MooseMesh.C:2685
const bool _all_master_nodes_contained_in_sub_app
Boolean variable to generate error if every master node cannot be mapped to a subApp during from_mult...
void variableIntegrityCheck(const AuxVariableName &var_name) const
Utility to verify that the vEariable in the destination system exists.
virtual std::shared_ptr< DisplacedProblem > getDisplacedProblem()
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2567
virtual System & system()=0
Get the reference to the libMesh system.
InputParameters validParams< MultiAppUserObjectTransfer >()
Samples a variable&#39;s value in the Master domain at the point where the MultiApp is.
virtual Real spatialValue(const Point &) const
Optional interface function for "evaluating" a UserObject at a spatial position.
Definition: UserObject.h:83
InputParameters validParams< MultiAppTransfer >()
PetscInt n
Base class for all MultiAppTransfer objects.
const std::string & name() const
Get the variable name.
virtual MooseMesh & mesh() override
bool _displaced_source_mesh
True if displaced mesh is used for the source mesh, otherwise false.
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...
registerMooseObject("MooseApp", MultiAppUserObjectTransfer)
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
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
const MooseEnum _direction
Whether we&#39;re transferring to or from the MultiApp.
MultiAppUserObjectTransfer(const InputParameters &parameters)
SystemBase & sys()
Get the system this variable is part of.
virtual void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup...
Base class for user-specific data.
Definition: UserObject.h:37