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 
32 
35 {
37  // MultiAppUserObjectTransfer does not need source variable since it query values from user
38  // objects
39  params.suppressParameter<std::vector<VariableName>>("source_variable");
40  params.addRequiredParam<UserObjectName>(
41  "user_object",
42  "The UserObject you want to transfer values from. Note: This might be a "
43  "UserObject from your MultiApp's input file!");
44  params.addParam<bool>("all_master_nodes_contained_in_sub_app",
45  false,
46  "Set to true if every master node is mapped to a distinct point on one of "
47  "the subApps during a transfer from sub App to Master App. If master node "
48  "cannot be found within bounding boxes of any of the subApps, an error is "
49  "generated.");
50  params.addParam<bool>(
51  "skip_bounding_box_check",
52  false,
53  "Skip the check if the to_elem is within the bounding box of the from_app.");
54 
55  params.addClassDescription(
56  "Samples a variable's value in the Master domain at the point where the MultiApp is and "
57  "copies that value into a post-processor in the MultiApp");
58 
59  return params;
60 }
61 
63  : MultiAppConservativeTransfer(parameters),
64  _user_object_name(getParam<UserObjectName>("user_object")),
65  _all_master_nodes_contained_in_sub_app(getParam<bool>("all_master_nodes_contained_in_sub_app")),
66  _skip_bbox_check(getParam<bool>("skip_bounding_box_check"))
67 {
68  // This transfer does not work with DistributedMesh
69  _fe_problem.mesh().errorIfDistributedMesh("MultiAppUserObjectTransfer");
70 
71  if (_to_var_names.size() != 1)
72  paramError("variable", " Support single to-variable only ");
73 
74  if (_from_var_names.size() > 0)
75  paramError("source_variable",
76  " You should not provide any source variables since the transfer takes values from "
77  "user objects ");
78 }
79 
80 void
82 {
83  _console << "Beginning MultiAppUserObjectTransfer " << name() << std::endl;
84 
85  switch (_current_direction)
86  {
87  case TO_MULTIAPP:
88  {
89  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
90  {
91  if (_multi_app->hasLocalApp(i))
92  {
93  Moose::ScopedCommSwapper swapper(_multi_app->comm());
94 
95  // Loop over the master nodes and set the value of the variable
96  System * to_sys = find_sys(_multi_app->appProblemBase(i).es(), _to_var_name);
97 
98  unsigned int sys_num = to_sys->number();
99  unsigned int var_num = to_sys->variable_number(_to_var_name);
100 
101  NumericVector<Real> & solution = _multi_app->appTransferVector(i, _to_var_name);
102 
103  MeshBase * mesh = NULL;
104 
105  if (_displaced_target_mesh && _multi_app->appProblemBase(i).getDisplacedProblem())
106  {
107  mesh = &_multi_app->appProblemBase(i).getDisplacedProblem()->mesh().getMesh();
108  }
109  else
110  mesh = &_multi_app->appProblemBase(i).mesh().getMesh();
111 
112  auto & fe_type = to_sys->variable_type(var_num);
113  bool is_constant = fe_type.order == CONSTANT;
114  bool is_nodal = fe_type.family == LAGRANGE;
115 
116  if (fe_type.order > FIRST && !is_nodal)
117  mooseError("We don't currently support second order or higher elemental variable ");
118 
119  const UserObject & user_object =
120  _multi_app->problemBase().getUserObjectBase(_user_object_name);
121 
122  if (is_nodal)
123  {
124  for (auto & node : mesh->local_node_ptr_range())
125  {
126  if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
127  {
128  // The zero only works for LAGRANGE!
129  dof_id_type dof = node->dof_number(sys_num, var_num, 0);
130 
131  swapper.forceSwap();
132  Real from_value = user_object.spatialValue(*node + _multi_app->position(i));
133  swapper.forceSwap();
134 
135  solution.set(dof, from_value);
136  }
137  }
138  }
139  else // Elemental
140  {
141  std::vector<Point> points;
142  for (auto & elem : as_range(mesh->local_elements_begin(), mesh->local_elements_end()))
143  {
144  // Skip this element if the variable has no dofs at it.
145  if (elem->n_dofs(sys_num, var_num) < 1)
146  continue;
147 
148  points.clear();
149  // grap sample points
150  // for constant shape function, we take the element centroid
151  if (is_constant)
152  points.push_back(elem->centroid());
153  // for higher order method, we take all nodes of element
154  // this works for the first order L2 Lagrange.
155  else
156  for (auto & node : elem->node_ref_range())
157  points.push_back(node);
158 
159  auto n_points = points.size();
160  unsigned int n_comp = elem->n_comp(sys_num, var_num);
161  // We assume each point corresponds to one component of elemental variable
162  if (n_points != n_comp)
163  mooseError(" Number of points ",
164  n_points,
165  " does not equal to number of variable components ",
166  n_comp);
167 
168  unsigned int offset = 0;
169  for (auto & point : points) // If this variable has dofs at this elem
170  {
171  // The zero only works for LAGRANGE!
172  dof_id_type dof = elem->dof_number(sys_num, var_num, offset++);
173 
174  swapper.forceSwap();
175  Real from_value = user_object.spatialValue(point + _multi_app->position(i));
176  swapper.forceSwap();
177 
178  solution.set(dof, from_value);
179  }
180  }
181  }
182 
183  solution.close();
184  to_sys->update();
185  }
186  }
187 
188  break;
189  }
190  case FROM_MULTIAPP:
191  {
192  FEProblemBase & to_problem = _multi_app->problemBase();
193  MooseVariableFEBase & to_var = to_problem.getVariable(
195  SystemBase & to_system_base = to_var.sys();
196 
197  System & to_sys = to_system_base.system();
198 
199  unsigned int to_sys_num = to_sys.number();
200 
201  // Only works with a serialized mesh to transfer to!
202  mooseAssert(to_sys.get_mesh().is_serial(),
203  "MultiAppUserObjectTransfer only works with ReplicatedMesh!");
204 
205  unsigned int to_var_num = to_sys.variable_number(to_var.name());
206 
207  _console << "Transferring to: " << to_var.name() << std::endl;
208 
209  // EquationSystems & to_es = to_sys.get_equation_systems();
210 
211  // Create a serialized version of the solution vector
212  NumericVector<Number> * to_solution = to_sys.solution.get();
213 
214  MeshBase * to_mesh = NULL;
215 
216  if (_displaced_target_mesh && to_problem.getDisplacedProblem())
217  to_mesh = &to_problem.getDisplacedProblem()->mesh().getMesh();
218  else
219  to_mesh = &to_problem.mesh().getMesh();
220 
221  auto & fe_type = to_sys.variable_type(to_var_num);
222  bool is_constant = fe_type.order == CONSTANT;
223  bool is_nodal = fe_type.family == LAGRANGE;
224 
225  if (fe_type.order > FIRST && !is_nodal)
226  mooseError("We don't currently support second order or higher elemental variable ");
227 
229  {
230  // check to see if master nodes or elements lies within any of the sub application bounding
231  // boxes
232  if (is_nodal)
233  {
234  for (auto & node : to_mesh->node_ptr_range())
235  {
236  if (node->n_dofs(to_sys_num, to_var_num) > 0)
237  {
238  unsigned int node_found_in_sub_app = 0;
239  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
240  {
241  if (!_multi_app->hasLocalApp(i))
242  continue;
243 
244  BoundingBox app_box = _multi_app->getBoundingBox(i, _displaced_source_mesh);
245 
246  if (app_box.contains_point(*node))
247  ++node_found_in_sub_app;
248  }
249 
250  if (node_found_in_sub_app == 0)
251  {
252  Point n = *node;
253  mooseError("MultiAppUserObjectTransfer: Master node ",
254  n,
255  " not found within the bounding box of any of the sub applications.");
256  }
257  else if (node_found_in_sub_app > 1)
258  {
259  Point n = *node;
260  mooseError("MultiAppUserObjectTransfer: Master node ",
261  n,
262  " found within the bounding box of two or more sub applications.");
263  }
264  }
265  }
266  }
267  else // elemental
268  {
269  std::vector<Point> points;
270  for (auto & elem : as_range(to_mesh->elements_begin(), to_mesh->elements_end()))
271  {
272  // Skip this element if the variable has no dofs at it.
273  if (elem->n_dofs(to_sys_num, to_var_num) < 1)
274  continue;
275 
276  points.clear();
277  // grap sample points
278  // for constant shape function, we take the element centroid
279  if (is_constant)
280  points.push_back(elem->centroid());
281  // for higher order method, we take all nodes of element
282  // this works for the first order L2 Lagrange.
283  else
284  for (auto & node : elem->node_ref_range())
285  points.push_back(node);
286 
287  auto n_points = points.size();
288  unsigned int n_comp = elem->n_comp(to_sys_num, to_var_num);
289  // We assume each point corresponds to one component of elemental variable
290  if (n_points != n_comp)
291  mooseError(" Number of points ",
292  n_points,
293  " does not equal to number of variable components ",
294  n_comp);
295 
296  for (auto & point : points)
297  {
298  unsigned int elem_found_in_sub_app = 0;
299 
300  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
301  {
302  if (!_multi_app->hasLocalApp(i))
303  continue;
304 
305  BoundingBox app_box = _multi_app->getBoundingBox(i, _displaced_source_mesh);
306 
307  if (app_box.contains_point(point))
308  ++elem_found_in_sub_app;
309  }
310 
311  if (elem_found_in_sub_app == 0)
312  mooseError("MultiAppUserObjectTransfer: Master element with ",
313  n_points > 1 ? "node" : "centroid",
314  " at ",
315  point,
316  " not found within the bounding box of any of the sub applications.");
317 
318  else if (elem_found_in_sub_app > 1)
319  mooseError("MultiAppUserObjectTransfer: Master element with ",
320  n_points > 1 ? "node" : "centroid",
321  " at ",
322  point,
323  " found within the bounding box of two or more sub applications.");
324  }
325  }
326  }
327  }
328 
329  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
330  {
331  if (!_multi_app->hasLocalApp(i))
332  continue;
333 
334  Point app_position = _multi_app->position(i);
335  BoundingBox app_box = _multi_app->getBoundingBox(i, _displaced_source_mesh);
336  const UserObject & user_object = _multi_app->appUserObjectBase(i, _user_object_name);
337 
338  if (is_nodal)
339  {
340  for (auto & node : to_mesh->node_ptr_range())
341  {
342  if (node->n_dofs(to_sys_num, to_var_num) > 0) // If this variable has dofs at this node
343  {
344  // See if this node falls in this bounding box
345  if (_skip_bbox_check || app_box.contains_point(*node))
346  {
347  dof_id_type dof = node->dof_number(to_sys_num, to_var_num, 0);
348 
349  Real from_value = 0;
350  {
351  Moose::ScopedCommSwapper swapper(_multi_app->comm());
352  from_value = user_object.spatialValue(*node - app_position);
353  }
354 
355  if (from_value == std::numeric_limits<Real>::infinity())
356  {
357  Point n = *node;
358  mooseError("MultiAppUserObjectTransfer: Point corresponding to master node at (",
359  n,
360  ") not found in the sub application.");
361  }
362  to_solution->set(dof, from_value);
363  }
364  }
365  }
366  }
367  else // Elemental
368  {
369  std::vector<Point> points;
370  for (auto & elem : as_range(to_mesh->elements_begin(), to_mesh->elements_end()))
371  {
372  // Skip this element if the variable has no dofs at it.
373  if (elem->n_dofs(to_sys_num, to_var_num) < 1)
374  continue;
375 
376  points.clear();
377  // grap sample points
378  // for constant shape function, we take the element centroid
379  if (is_constant)
380  points.push_back(elem->centroid());
381  // for higher order method, we take all nodes of element
382  // this works for the first order L2 Lagrange.
383  else
384  for (auto & node : elem->node_ref_range())
385  points.push_back(node);
386 
387  auto n_points = points.size();
388  unsigned int n_comp = elem->n_comp(to_sys_num, to_var_num);
389  // We assume each point corresponds to one component of elemental variable
390  if (n_points != n_comp)
391  mooseError(" Number of points ",
392  n_points,
393  " does not equal to number of variable components ",
394  n_comp);
395 
396  unsigned int offset = 0;
397  for (auto & point : points) // If this variable has dofs at this elem
398  {
399  // See if this elem falls in this bounding box
400  if (_skip_bbox_check || app_box.contains_point(point))
401  {
402  dof_id_type dof = elem->dof_number(to_sys_num, to_var_num, offset++);
403 
404  Real from_value = 0;
405  {
406  Moose::ScopedCommSwapper swapper(_multi_app->comm());
407  from_value = user_object.spatialValue(point - app_position);
408  }
409 
410  if (from_value == std::numeric_limits<Real>::infinity())
411  mooseError(
412  "MultiAppUserObjectTransfer: Point corresponding to element's centroid (",
413  point,
414  ") not found in sub application.");
415 
416  to_solution->set(dof, from_value);
417  }
418  }
419  }
420  }
421  }
422 
423  to_solution->close();
424  to_sys.update();
425 
426  break;
427  }
428  }
429 
430  _console << "Finished MultiAppUserObjectTransfer " << name() << std::endl;
431 
432  postExecute();
433 }
MultiAppConservativeTransfer::_from_var_names
const std::vector< VariableName > _from_var_names
Name of variables transfering from.
Definition: MultiAppConservativeTransfer.h:44
MooseVariableFEBase
Definition: MooseVariableFEBase.h:27
Transfer::FROM_MULTIAPP
Definition: Transfer.h:72
Moose::ScopedCommSwapper
Definition: Moose.h:216
MultiAppConservativeTransfer
Transfers variables on possibly differne meshes while conserving a user defined property of each vari...
Definition: MultiAppConservativeTransfer.h:24
MooseMesh.h
FEProblem.h
MultiAppTransfer::_multi_app
std::shared_ptr< MultiApp > _multi_app
The MultiApp this Transfer is transferring data to or from.
Definition: MultiAppTransfer.h:55
MooseObject::mooseError
void mooseError(Args &&... args) const
Definition: MooseObject.h:141
MultiAppUserObjectTransfer
Samples a variable's value in the Master domain at the point where the MultiApp is.
Definition: MultiAppUserObjectTransfer.h:26
UserObject::spatialValue
virtual Real spatialValue(const Point &) const
Optional interface function for "evaluating" a UserObject at a spatial position.
Definition: UserObject.h:87
defineLegacyParams
defineLegacyParams(MultiAppUserObjectTransfer)
SystemBase::system
virtual System & system()=0
Get the reference to the libMesh system.
InputParameters::addParam
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.
Definition: InputParameters.h:1198
MultiAppUserObjectTransfer::_skip_bbox_check
const bool _skip_bbox_check
whether to check the bounding box check or not
Definition: MultiAppUserObjectTransfer.h:45
MultiAppUserObjectTransfer.h
FEProblemBase::getDisplacedProblem
virtual std::shared_ptr< DisplacedProblem > getDisplacedProblem()
Definition: FEProblemBase.h:1262
MultiAppTransfer::_displaced_source_mesh
bool _displaced_source_mesh
True if displaced mesh is used for the source mesh, otherwise false.
Definition: MultiAppTransfer.h:73
Transfer::find_sys
static System * find_sys(EquationSystems &es, const std::string &var_name)
Small helper function for finding the system containing the variable.
Definition: Transfer.C:86
Transfer::_current_direction
MooseEnum _current_direction
Definition: Transfer.h:106
MooseObject::paramError
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition: MooseObject.h:215
ConsoleStreamInterface::_console
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
Definition: ConsoleStreamInterface.h:31
InputParameters
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
Definition: InputParameters.h:53
registerMooseObject
registerMooseObject("MooseApp", MultiAppUserObjectTransfer)
MultiAppConservativeTransfer::_to_var_names
const std::vector< AuxVariableName > _to_var_names
Name of variables transfering to.
Definition: MultiAppConservativeTransfer.h:46
Moose::VAR_ANY
Definition: MooseTypes.h:610
MultiAppUserObjectTransfer::MultiAppUserObjectTransfer
MultiAppUserObjectTransfer(const InputParameters &parameters)
Definition: MultiAppUserObjectTransfer.C:62
UserObject
Base class for user-specific data.
Definition: UserObject.h:38
MultiAppConservativeTransfer::_to_var_name
AuxVariableName _to_var_name
Definition: MultiAppConservativeTransfer.h:50
MultiAppConservativeTransfer::validParams
static InputParameters validParams()
Definition: MultiAppConservativeTransfer.C:23
MooseMesh::getMesh
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2599
MultiAppTransfer::_displaced_target_mesh
bool _displaced_target_mesh
True if displaced mesh is used for the target mesh, otherwise false.
Definition: MultiAppTransfer.h:75
Transfer::_fe_problem
FEProblemBase & _fe_problem
Definition: Transfer.h:97
InputParameters::addClassDescription
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
Definition: InputParameters.C:70
MultiAppUserObjectTransfer::_user_object_name
std::string _user_object_name
Definition: MultiAppUserObjectTransfer.h:36
MooseVariableFE.h
MultiApp.h
InputParameters::suppressParameter
void suppressParameter(const std::string &name)
This method suppresses an inherited parameter so that it isn't required or valid in the derived class...
Definition: InputParameters.h:1367
MultiAppUserObjectTransfer::_all_master_nodes_contained_in_sub_app
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...
Definition: MultiAppUserObjectTransfer.h:42
DisplacedProblem.h
Transfer::TO_MULTIAPP
Definition: Transfer.h:71
FEProblemBase::getVariable
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...
Definition: FEProblemBase.C:4207
MooseVariableBase::sys
SystemBase & sys()
Get the system this variable is part of.
Definition: MooseVariableBase.h:58
SystemBase
Base class for a system (of equations)
Definition: SystemBase.h:95
UserObject.h
MultiAppConservativeTransfer::postExecute
virtual void postExecute()
Add some extra work if necessary after execute().
Definition: MultiAppConservativeTransfer.C:148
MooseTypes.h
FEProblemBase
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
Definition: FEProblemBase.h:139
MultiAppUserObjectTransfer::execute
virtual void execute() override
Execute the transfer.
Definition: MultiAppUserObjectTransfer.C:81
InputParameters::addRequiredParam
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...
Definition: InputParameters.h:1176
FEProblemBase::mesh
virtual MooseMesh & mesh() override
Definition: FEProblemBase.h:148
Moose::VAR_FIELD_STANDARD
Definition: MooseTypes.h:615
MooseObject::name
virtual const std::string & name() const
Get the name of the object.
Definition: MooseObject.h:70
MooseMesh::errorIfDistributedMesh
void errorIfDistributedMesh(std::string name) const
Generate a unified error message if the underlying libMesh mesh is a DistributedMesh.
Definition: MooseMesh.C:2717
MultiAppUserObjectTransfer::validParams
static InputParameters validParams()
Definition: MultiAppUserObjectTransfer.C:34
MooseVariableBase::name
const std::string & name() const override
Get the variable name.
Definition: MooseVariableBase.h:63
n
PetscInt n
Definition: PetscDMMoose.C:1504