www.mooseframework.org
MultiAppProjectionTransfer.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 // MOOSE includes
13 #include "AddVariableAction.h"
14 #include "FEProblem.h"
15 #include "MooseMesh.h"
16 #include "MooseVariableFE.h"
17 #include "SystemBase.h"
18 #include "MooseAppCoordTransform.h"
19 
20 #include "libmesh/dof_map.h"
21 #include "libmesh/linear_implicit_system.h"
22 #include "libmesh/mesh_function.h"
23 #include "libmesh/mesh_tools.h"
24 #include "libmesh/numeric_vector.h"
25 #include "libmesh/parallel_algebra.h"
26 #include "libmesh/quadrature_gauss.h"
27 #include "libmesh/sparse_matrix.h"
28 #include "libmesh/string_to_enum.h"
29 #include "libmesh/default_coupling.h"
30 
31 // TIMPI includes
32 #include "timpi/parallel_sync.h"
33 
34 void
35 assemble_l2(EquationSystems & es, const std::string & system_name)
36 {
37  MultiAppProjectionTransfer * transfer =
38  es.parameters.get<MultiAppProjectionTransfer *>("transfer");
39  transfer->assembleL2(es, system_name);
40 }
41 
43 
46 {
48  params.addClassDescription(
49  "Perform a projection between a master and sub-application mesh of a field variable.");
50 
51  MooseEnum proj_type("l2", "l2");
52  params.addParam<MooseEnum>("proj_type", proj_type, "The type of the projection.");
53 
54  params.addParam<bool>("fixed_meshes",
55  false,
56  "Set to true when the meshes are not changing (ie, "
57  "no movement or adaptivity). This will cache some "
58  "information to speed up the transfer.");
59 
60  // Need one layer of ghosting
61  params.addRelationshipManager("ElementSideNeighborLayers",
65  return params;
66 }
67 
69  : MultiAppConservativeTransfer(parameters),
70  _proj_type(getParam<MooseEnum>("proj_type")),
71  _compute_matrix(true),
72  _fixed_meshes(getParam<bool>("fixed_meshes")),
73  _qps_cached(false)
74 {
75  if (_to_var_names.size() != 1)
76  paramError("variable", " Support single to-variable only ");
77 
78  if (_from_var_names.size() != 1)
79  paramError("source_variable", " Support single from-variable only ");
80 }
81 
82 void
84 {
86 
87  _proj_sys.resize(_to_problems.size(), NULL);
88 
89  for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
90  {
91  FEProblemBase & to_problem = *_to_problems[i_to];
92  EquationSystems & to_es = to_problem.es();
93 
94  // Add the projection system.
95  FEType fe_type = to_problem
96  .getVariable(0,
100  .feType();
101 
102  LinearImplicitSystem & proj_sys = to_es.add_system<LinearImplicitSystem>("proj-sys-" + name());
103 
104  proj_sys.get_dof_map().add_coupling_functor(
105  proj_sys.get_dof_map().default_coupling(),
106  false); // The false keeps it from getting added to the mesh
107 
108  _proj_var_num = proj_sys.add_variable("var", fe_type);
109  proj_sys.attach_assemble_function(assemble_l2);
110  _proj_sys[i_to] = &proj_sys;
111 
112  // Prevent the projection system from being written to checkpoint
113  // files. In the event of a recover or restart, we'll read the checkpoint
114  // before this initialSetup method is called. As a result, we'll find
115  // systems in the checkpoint (the projection systems) that we don't know
116  // what to do with, and there will be a crash. We could fix this by making
117  // the systems in the constructor, except we don't know how many sub apps
118  // there are at the time of construction. So instead, we'll just nuke the
119  // projection system and rebuild it from scratch every recover/restart.
120  proj_sys.hide_output() = true;
121 
122  // Reinitialize EquationSystems since we added a system.
123  to_es.reinit();
124  }
125 }
126 
127 void
128 MultiAppProjectionTransfer::assembleL2(EquationSystems & es, const std::string & system_name)
129 {
130  // Get the system and mesh from the input arguments.
131  LinearImplicitSystem & system = es.get_system<LinearImplicitSystem>(system_name);
132  MeshBase & to_mesh = es.get_mesh();
133 
134  // Get the meshfunction evaluations and the map that was stashed in the es.
135  std::vector<Real> & final_evals = *es.parameters.get<std::vector<Real> *>("final_evals");
136  std::map<dof_id_type, unsigned int> & element_map =
137  *es.parameters.get<std::map<dof_id_type, unsigned int> *>("element_map");
138 
139  // Setup system vectors and matrices.
140  FEType fe_type = system.variable_type(0);
141  std::unique_ptr<FEBase> fe(FEBase::build(to_mesh.mesh_dimension(), fe_type));
142  QGauss qrule(to_mesh.mesh_dimension(), fe_type.default_quadrature_order());
143  fe->attach_quadrature_rule(&qrule);
144  const DofMap & dof_map = system.get_dof_map();
147  std::vector<dof_id_type> dof_indices;
148  const std::vector<Real> & JxW = fe->get_JxW();
149  const std::vector<std::vector<Real>> & phi = fe->get_phi();
150  auto & system_matrix = system.get_system_matrix();
151 
152  for (const auto & elem : to_mesh.active_local_element_ptr_range())
153  {
154  fe->reinit(elem);
155 
156  dof_map.dof_indices(elem, dof_indices);
157  Ke.resize(dof_indices.size(), dof_indices.size());
158  Fe.resize(dof_indices.size());
159 
160  for (unsigned int qp = 0; qp < qrule.n_points(); qp++)
161  {
162  Real meshfun_eval = 0.;
163  if (element_map.find(elem->id()) != element_map.end())
164  {
165  // We have evaluations for this element.
166  meshfun_eval = final_evals[element_map[elem->id()] + qp];
167  }
168 
169  // Now compute the element matrix and RHS contributions.
170  for (unsigned int i = 0; i < phi.size(); i++)
171  {
172  // RHS
173  Fe(i) += JxW[qp] * (meshfun_eval * phi[i][qp]);
174 
175  if (_compute_matrix)
176  for (unsigned int j = 0; j < phi.size(); j++)
177  {
178  // The matrix contribution
179  Ke(i, j) += JxW[qp] * (phi[i][qp] * phi[j][qp]);
180  }
181  }
182  dof_map.constrain_element_matrix_and_vector(Ke, Fe, dof_indices);
183 
184  if (_compute_matrix)
185  system_matrix.add_matrix(Ke, dof_indices);
186  system.rhs->add_vector(Fe, dof_indices);
187  }
188  }
189 }
190 
191 void
193 {
194  TIME_SECTION(
195  "MultiAppProjectionTransfer::execute()", 5, "Transferring variables through projection");
196 
198  // We are going to project the solutions by solving some linear systems. In
199  // order to assemble the systems, we need to evaluate the "from" domain
200  // solutions at quadrature points in the "to" domain. Some parallel
201  // communication is necessary because each processor doesn't necessarily have
202  // all the "from" information it needs to set its "to" values. We don't want
203  // to use a bunch of big all-to-all broadcasts, so we'll use bounding boxes to
204  // figure out which processors have the information we need and only
205  // communicate with those processors.
206  //
207  // Each processor will
208  // 1. Check its local quadrature points in the "to" domains to see which
209  // "from" domains they might be in.
210  // 2. Send quadrature points to the processors with "from" domains that might
211  // contain those points.
212  // 3. Recieve quadrature points from other processors, evaluate its mesh
213  // functions at those points, and send the values back to the proper
214  // processor
215  // 4. Recieve mesh function evaluations from all relevant processors and
216  // decide which one to use at every quadrature point (the lowest global app
217  // index always wins)
218  // 5. And use the mesh function evaluations to assemble and solve an L2
219  // projection system on its local elements.
221 
223  // For every combination of global "from" problem and local "to" problem, find
224  // which "from" bounding boxes overlap with which "to" elements. Keep track
225  // of which processors own bounding boxes that overlap with which elements.
226  // Build vectors of quadrature points to send to other processors for mesh
227  // function evaluations.
229 
230  // Get the bounding boxes for the "from" domains.
231  std::vector<BoundingBox> bboxes = getFromBoundingBoxes();
232 
233  // Figure out how many "from" domains each processor owns.
234  std::vector<unsigned int> froms_per_proc = getFromsPerProc();
235 
236  std::map<processor_id_type, std::vector<Point>> outgoing_qps;
237  std::map<processor_id_type, std::map<std::pair<unsigned int, unsigned int>, unsigned int>>
238  element_index_map;
239  // element_index_map[i_to, element_id] = index
240  // outgoing_qps[index] is the first quadrature point in element
241 
242  if (!_qps_cached)
243  {
244  for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
245  {
246  // Indexing into the coordinate transforms vector
247  const auto to_global_num =
249  MeshBase & to_mesh = _to_meshes[i_to]->getMesh();
250 
251  LinearImplicitSystem & system = *_proj_sys[i_to];
252 
253  FEType fe_type = system.variable_type(0);
254  std::unique_ptr<FEBase> fe(FEBase::build(to_mesh.mesh_dimension(), fe_type));
255  QGauss qrule(to_mesh.mesh_dimension(), fe_type.default_quadrature_order());
256  fe->attach_quadrature_rule(&qrule);
257  const std::vector<Point> & xyz = fe->get_xyz();
258 
259  unsigned int from0 = 0;
260  for (processor_id_type i_proc = 0; i_proc < n_processors();
261  from0 += froms_per_proc[i_proc], i_proc++)
262  {
263  for (const auto & elem :
264  as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
265  {
266  fe->reinit(elem);
267 
268  bool qp_hit = false;
269  for (unsigned int i_from = 0; i_from < froms_per_proc[i_proc] && !qp_hit; i_from++)
270  {
271  for (unsigned int qp = 0; qp < qrule.n_points() && !qp_hit; qp++)
272  {
273  Point qpt = xyz[qp];
274  if (bboxes[from0 + i_from].contains_point((*_to_transforms[to_global_num])(qpt)))
275  qp_hit = true;
276  }
277  }
278 
279  if (qp_hit)
280  {
281  // The selected processor's bounding box contains at least one
282  // quadrature point from this element. Send all qps from this element
283  // and remember where they are in the array using the map.
284  std::pair<unsigned int, unsigned int> key(i_to, elem->id());
285  element_index_map[i_proc][key] = outgoing_qps[i_proc].size();
286  for (unsigned int qp = 0; qp < qrule.n_points(); qp++)
287  {
288  Point qpt = xyz[qp];
289  outgoing_qps[i_proc].push_back((*_to_transforms[to_global_num])(qpt));
290  }
291  }
292  }
293  }
294  }
295 
296  if (_fixed_meshes)
297  _cached_index_map = element_index_map;
298  }
299  else
300  {
301  element_index_map = _cached_index_map;
302  }
303 
305  // Request quadrature point evaluations from other processors and handle
306  // requests sent to this processor.
308 
309  // Get the local bounding boxes.
310  std::vector<BoundingBox> local_bboxes(froms_per_proc[processor_id()]);
311  {
312  // Find the index to the first of this processor's local bounding boxes.
313  unsigned int local_start = 0;
314  for (processor_id_type i_proc = 0; i_proc < n_processors() && i_proc != processor_id();
315  i_proc++)
316  local_start += froms_per_proc[i_proc];
317 
318  // Extract the local bounding boxes.
319  for (unsigned int i_from = 0; i_from < froms_per_proc[processor_id()]; i_from++)
320  local_bboxes[i_from] = bboxes[local_start + i_from];
321  }
322 
323  // Setup the local mesh functions.
324  std::vector<MeshFunction> local_meshfuns;
325  for (unsigned int i_from = 0; i_from < _from_problems.size(); i_from++)
326  {
327  FEProblemBase & from_problem = *_from_problems[i_from];
328  MooseVariableFEBase & from_var = from_problem.getVariable(
330  System & from_sys = from_var.sys().system();
331  unsigned int from_var_num = from_sys.variable_number(from_var.name());
332 
333  local_meshfuns.emplace_back(
334  from_problem.es(), *from_sys.current_local_solution, from_sys.get_dof_map(), from_var_num);
335  local_meshfuns.back().init();
336  local_meshfuns.back().enable_out_of_mesh_mode(OutOfMeshValue);
337  }
338 
339  // Recieve quadrature points from other processors, evaluate mesh frunctions
340  // at those points, and send the values back.
341  std::map<processor_id_type, std::vector<std::pair<Real, unsigned int>>> outgoing_evals_ids;
342 
343  // If there is no cached data, we need to do communication
344  // Quadrature points I will receive from remote processors
345  std::map<processor_id_type, std::vector<Point>> incoming_qps;
346  if (!_qps_cached)
347  {
348  auto qps_action_functor = [&incoming_qps](processor_id_type pid, const std::vector<Point> & qps)
349  {
350  // Quadrature points from processor 'pid'
351  auto & incoming_qps_from_pid = incoming_qps[pid];
352  // Store data for late use
353  incoming_qps_from_pid.reserve(incoming_qps_from_pid.size() + qps.size());
354  std::copy(qps.begin(), qps.end(), std::back_inserter(incoming_qps_from_pid));
355  };
356 
357  Parallel::push_parallel_vector_data(comm(), outgoing_qps, qps_action_functor);
358  }
359 
360  // Cache data
361  if (!_qps_cached)
362  _cached_qps = incoming_qps;
363 
364  for (auto & qps : _cached_qps)
365  {
366  const processor_id_type pid = qps.first;
367 
368  outgoing_evals_ids[pid].resize(qps.second.size(),
369  std::make_pair(OutOfMeshValue, libMesh::invalid_uint));
370 
371  for (unsigned int qp = 0; qp < qps.second.size(); qp++)
372  {
373  Point qpt = qps.second[qp];
374 
375  // Loop until we've found the lowest-ranked app that actually contains
376  // the quadrature point.
377  for (unsigned int i_from = 0; i_from < _from_problems.size(); i_from++)
378  {
379  if (local_bboxes[i_from].contains_point(qpt))
380  {
381  const auto from_global_num =
383  outgoing_evals_ids[pid][qp].first =
384  (local_meshfuns[i_from])(_from_transforms[from_global_num]->mapBack(qpt));
386  outgoing_evals_ids[pid][qp].second = from_global_num;
387  }
388  }
389  }
390  }
391 
393  // Gather all of the qp evaluations and pick out the best ones for each qp.
395 
396  // Values back from remote processors for my local quadrature points
397  std::map<processor_id_type, std::vector<std::pair<Real, unsigned int>>> incoming_evals_ids;
398 
399  auto evals_action_functor =
400  [&incoming_evals_ids](processor_id_type pid,
401  const std::vector<std::pair<Real, unsigned int>> & evals)
402  {
403  // evals for processor 'pid'
404  auto & incoming_evals_ids_for_pid = incoming_evals_ids[pid];
405  // Copy evals for late use
406  incoming_evals_ids_for_pid.reserve(incoming_evals_ids_for_pid.size() + evals.size());
407  std::copy(evals.begin(), evals.end(), std::back_inserter(incoming_evals_ids_for_pid));
408  };
409 
410  Parallel::push_parallel_vector_data(comm(), outgoing_evals_ids, evals_action_functor);
411 
412  std::vector<std::vector<Real>> final_evals(_to_problems.size());
413  std::vector<std::map<dof_id_type, unsigned int>> trimmed_element_maps(_to_problems.size());
414 
415  for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
416  {
417  MeshBase & to_mesh = _to_meshes[i_to]->getMesh();
418  LinearImplicitSystem & system = *_proj_sys[i_to];
419 
420  FEType fe_type = system.variable_type(0);
421  std::unique_ptr<FEBase> fe(FEBase::build(to_mesh.mesh_dimension(), fe_type));
422  QGauss qrule(to_mesh.mesh_dimension(), fe_type.default_quadrature_order());
423  fe->attach_quadrature_rule(&qrule);
424 
425  for (const auto & elem : to_mesh.active_local_element_ptr_range())
426  {
427  fe->reinit(elem);
428 
429  bool element_is_evaled = false;
430  std::vector<Real> evals(qrule.n_points(), 0.);
431 
432  for (unsigned int qp = 0; qp < qrule.n_points(); qp++)
433  {
434  unsigned int lowest_app_rank = libMesh::invalid_uint;
435  for (auto & values_ids : incoming_evals_ids)
436  {
437  // Current processor id
438  const processor_id_type pid = values_ids.first;
439 
440  // Ignore the selected processor if the element wasn't found in it's
441  // bounding box.
442  std::map<std::pair<unsigned int, unsigned int>, unsigned int> & map =
443  element_index_map[pid];
444  std::pair<unsigned int, unsigned int> key(i_to, elem->id());
445  if (map.find(key) == map.end())
446  continue;
447  unsigned int qp0 = map[key];
448 
449  // Ignore the selected processor if it's app has a higher rank than the
450  // previously found lowest app rank.
452  if (values_ids.second[qp0 + qp].second >= lowest_app_rank)
453  continue;
454 
455  // Ignore the selected processor if the qp was actually outside the
456  // processor's subapp's mesh.
457  if (values_ids.second[qp0 + qp].first == OutOfMeshValue)
458  continue;
459 
460  // This is the best meshfunction evaluation so far, save it.
461  element_is_evaled = true;
462  evals[qp] = values_ids.second[qp0 + qp].first;
463  }
464  }
465 
466  // If we found good evaluations for any of the qps in this element, save
467  // those evaluations for later.
468  if (element_is_evaled)
469  {
470  trimmed_element_maps[i_to][elem->id()] = final_evals[i_to].size();
471  for (unsigned int qp = 0; qp < qrule.n_points(); qp++)
472  final_evals[i_to].push_back(evals[qp]);
473  }
474  }
475  }
476 
478  // We now have just one or zero mesh function values at all of our local
479  // quadrature points. Stash those values (and a map linking them to element
480  // ids) in the equation systems parameters and project the solution.
482 
483  for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
484  {
485  _to_es[i_to]->parameters.set<std::vector<Real> *>("final_evals") = &final_evals[i_to];
486  _to_es[i_to]->parameters.set<std::map<dof_id_type, unsigned int> *>("element_map") =
487  &trimmed_element_maps[i_to];
488  projectSolution(i_to);
489  _to_es[i_to]->parameters.set<std::vector<Real> *>("final_evals") = NULL;
490  _to_es[i_to]->parameters.set<std::map<dof_id_type, unsigned int> *>("element_map") = NULL;
491  }
492 
493  if (_fixed_meshes)
494  _qps_cached = true;
495 
496  postExecute();
497 }
498 
499 void
501 {
502  FEProblemBase & to_problem = *_to_problems[i_to];
503  EquationSystems & proj_es = to_problem.es();
504  LinearImplicitSystem & ls = *_proj_sys[i_to];
505  // activate the current transfer
506  proj_es.parameters.set<MultiAppProjectionTransfer *>("transfer") = this;
507 
508  // TODO: specify solver params in an input file
509  // solver tolerance
510  Real tol = proj_es.parameters.get<Real>("linear solver tolerance");
511  proj_es.parameters.set<Real>("linear solver tolerance") = 1e-10; // set our tolerance
512  // solve it
513  ls.solve();
514  proj_es.parameters.set<Real>("linear solver tolerance") = tol; // restore the original tolerance
515 
516  // copy projected solution into target es
517  MeshBase & to_mesh = proj_es.get_mesh();
518 
519  MooseVariableFEBase & to_var = to_problem.getVariable(
521  System & to_sys = to_var.sys().system();
522  NumericVector<Number> * to_solution = to_sys.solution.get();
523 
524  for (const auto & node : to_mesh.local_node_ptr_range())
525  {
526  for (unsigned int comp = 0; comp < node->n_comp(to_sys.number(), to_var.number()); comp++)
527  {
528  const dof_id_type proj_index = node->dof_number(ls.number(), _proj_var_num, comp);
529  const dof_id_type to_index = node->dof_number(to_sys.number(), to_var.number(), comp);
530  to_solution->set(to_index, (*ls.solution)(proj_index));
531  }
532  }
533  for (const auto & elem : to_mesh.active_local_element_ptr_range())
534  for (unsigned int comp = 0; comp < elem->n_comp(to_sys.number(), to_var.number()); comp++)
535  {
536  const dof_id_type proj_index = elem->dof_number(ls.number(), _proj_var_num, comp);
537  const dof_id_type to_index = elem->dof_number(to_sys.number(), to_var.number(), comp);
538  to_solution->set(to_index, (*ls.solution)(proj_index));
539  }
540 
541  to_solution->close();
542  to_sys.update();
543 }
std::vector< std::unique_ptr< MultiAppCoordTransform > > _to_transforms
void assemble_l2(EquationSystems &es, const std::string &system_name)
const unsigned int invalid_uint
MooseEnum _current_direction
Definition: Transfer.h:106
virtual void get(const std::vector< numeric_index_type > &index, Number *values) const
unsigned int number() const
Get variable number coming from libMesh.
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
std::map< processor_id_type, std::map< std::pair< unsigned int, unsigned int >, unsigned int > > _cached_index_map
std::vector< EquationSystems * > _to_es
void resize(const unsigned int n)
std::map< processor_id_type, std::vector< Point > > _cached_qps
std::vector< BoundingBox > getFromBoundingBoxes()
Return the bounding boxes of all the "from" domains, including all the domains not local to this proc...
const std::vector< VariableName > _from_var_names
Name of variables transferring from.
std::vector< FEProblemBase * > _to_problems
const std::string & name() const override
Get the variable name.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const Parallel::Communicator & comm() const
virtual void postExecute()
Add some extra work if necessary after execute().
This class provides an interface for common operations on field variables of both FE and FV types wit...
void addRelationshipManager(const std::string &name, Moose::RelationshipManagerType rm_type, Moose::RelationshipManagerInputParameterCallback input_parameter_callback=nullptr)
Tells MOOSE about a RelationshipManager that this object needs.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
void assembleL2(EquationSystems &es, const std::string &system_name)
virtual const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:56
registerMooseObject("MooseApp", MultiAppProjectionTransfer)
const FEType & feType() const
Get the type of finite element object.
virtual const MooseVariableFieldBase & getVariable(const 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) const override
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
std::vector< unsigned int > _to_local2global_map
Given local app index, returns global app index.
virtual EquationSystems & es() override
virtual void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup...
uint8_t processor_id_type
processor_id_type n_processors() const
Project values from one domain to another.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
bool _compute_matrix
True, if we need to recompute the projection matrix.
const std::vector< AuxVariableName > _to_var_names
Name of variables transferring to.
std::vector< unsigned int > getFromsPerProc()
Return the number of "from" domains that each processor owns.
Transfers variables on possibly different meshes while conserving a user defined property (Postproces...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:31
static InputParameters validParams()
virtual void execute() override
Execute the transfer.
virtual System & system()=0
Get the reference to the libMesh system.
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 ...
static const Number OutOfMeshValue
Definition: Transfer.h:113
virtual void close()=0
MultiAppProjectionTransfer(const InputParameters &parameters)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void resize(const unsigned int new_m, const unsigned int new_n)
std::vector< std::unique_ptr< MultiAppCoordTransform > > _from_transforms
std::vector< unsigned int > _from_local2global_map
Given local app index, returns global app index.
static void addBBoxFactorParam(InputParameters &params)
Add the bounding box factor parameter to the supplied input parameters.
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...
const InputParameters & parameters() const
Get the parameters of the object.
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...
void projectSolution(unsigned int to_problem)
virtual void set(const numeric_index_type i, const Number value)=0
std::vector< LinearImplicitSystem * > _proj_sys
virtual void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup...
unsigned int _proj_var_num
Having one projection variable number seems weird, but there is always one variable in every system b...
processor_id_type processor_id() const
SystemBase & sys()
Get the system this variable is part of.
friend void assemble_l2(EquationSystems &es, const std::string &system_name)
std::vector< FEProblemBase * > _from_problems
std::vector< MooseMesh * > _to_meshes
uint8_t dof_id_type
VariableName _from_var_name
This values are used if a derived class only supports one variable.