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