20 #include "libmesh/meshfree_interpolation.h" 21 #include "libmesh/system.h" 22 #include "libmesh/mesh_function.h" 23 #include "libmesh/mesh_tools.h" 24 #include "libmesh/parallel_algebra.h" 34 MultiAppMeshFunctionTransfer,
43 "Transfers field data at the MultiApp position using solution the finite element function " 44 "from the main/parent application, via a 'libMesh::MeshFunction' object.");
49 "Whether or not to error in the case that a target point is not found in the source domain.");
58 "MultiAppGeneralFieldShapeEvaluationTransfer instead and adapt the parameters");
63 paramError(
"variable",
"The number of variables to transfer to and from should be equal");
69 TIME_SECTION(
"MultiAppShapeEvaluationTransfer::execute()",
71 "Transferring variables via finite element interpolation");
74 for (
unsigned int i = 0; i <
_var_size; ++i)
83 mooseAssert(i <
_var_size,
"The variable of index " << i <<
" does not exist");
101 std::map<processor_id_type, std::vector<Point>> outgoing_points;
103 std::map<processor_id_type, std::map<std::pair<unsigned int, dof_id_type>,
dof_id_type>>
106 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); ++i_to)
109 unsigned int sys_num = to_sys->
number();
114 bool is_nodal = fe_type.family ==
LAGRANGE;
118 if (fe_type.order >
FIRST && !is_nodal)
119 mooseError(
"We don't currently support second order or higher elemental variable.");
123 for (
const auto & node : to_mesh->local_node_ptr_range())
126 if (node->n_dofs(sys_num, var_num) < 1)
132 unsigned int from0 = 0;
134 from0 += froms_per_proc[i_proc], ++i_proc)
136 bool point_found =
false;
137 for (
unsigned int i_from = from0; i_from < from0 + froms_per_proc[i_proc] && !point_found;
140 auto transformed_node = to_transform(*node);
141 if (bboxes[i_from].contains_point(transformed_node))
144 std::pair<unsigned int, dof_id_type> key(i_to, node->id());
147 point_index_map[i_proc][key] = outgoing_points[i_proc].size();
149 outgoing_points[i_proc].push_back(std::move(transformed_node));
158 std::vector<Point> points;
159 std::vector<dof_id_type> point_ids;
160 for (
auto & elem :
as_range(to_mesh->local_elements_begin(), to_mesh->local_elements_end()))
163 if (elem->n_dofs(sys_num, var_num) < 1)
172 points.push_back(elem->vertex_average());
173 point_ids.push_back(elem->id());
179 for (
auto & node : elem->node_ref_range())
181 points.push_back(node);
182 point_ids.push_back(node.id());
185 unsigned int offset = 0;
186 for (
auto & point : points)
191 unsigned int from0 = 0;
193 from0 += froms_per_proc[i_proc], ++i_proc)
195 bool point_found =
false;
196 for (
unsigned int i_from = from0;
197 i_from < from0 + froms_per_proc[i_proc] && !point_found;
200 auto transformed_point = to_transform(point);
201 if (bboxes[i_from].contains_point(transformed_point))
203 std::pair<unsigned int, dof_id_type> key(i_to, point_ids[offset]);
204 if (point_index_map[i_proc].find(key) != point_index_map[i_proc].end())
207 point_index_map[i_proc][key] = outgoing_points[i_proc].size();
208 outgoing_points[i_proc].push_back(std::move(transformed_point));
223 std::vector<BoundingBox> local_bboxes(froms_per_proc[
processor_id()]);
226 unsigned int local_start = 0;
230 local_start += froms_per_proc[i_proc];
234 for (
unsigned int i_from = 0; i_from < froms_per_proc[
processor_id()]; ++i_from)
236 local_bboxes[i_from] = bboxes[local_start + i_from];
241 std::vector<MeshFunction> local_meshfuns;
243 for (
unsigned int i_from = 0; i_from <
_from_problems.size(); ++i_from)
258 local_meshfuns.back().init();
271 auto gather_functor =
272 [
this, &local_meshfuns, &local_bboxes](
274 const std::vector<Point> & incoming_points,
275 std::vector<std::pair<Real, unsigned int>> & vals_ids_for_incoming_points)
277 vals_ids_for_incoming_points.resize(incoming_points.size(), std::make_pair(
OutOfMeshValue, 0));
278 for (MooseIndex(incoming_points.size()) i_pt = 0; i_pt < incoming_points.size(); ++i_pt)
280 Point pt = incoming_points[i_pt];
289 if (local_bboxes[i_from].contains_point(pt))
291 const auto from_global_num =
294 vals_ids_for_incoming_points[i_pt].first =
314 std::map<processor_id_type, std::vector<std::pair<Real, unsigned int>>> incoming_vals_ids;
316 auto action_functor =
317 [&incoming_vals_ids](
319 const std::vector<Point> & ,
320 const std::vector<std::pair<Real, unsigned int>> & vals_ids_for_outgoing_points)
323 incoming_vals_ids[pid].reserve(vals_ids_for_outgoing_points.size());
325 std::copy(vals_ids_for_outgoing_points.begin(),
326 vals_ids_for_outgoing_points.end(),
327 std::back_inserter(incoming_vals_ids[pid]));
332 const std::pair<Real, unsigned int> * ex =
nullptr;
333 libMesh::Parallel::pull_parallel_vector_data(
334 comm(), outgoing_points, gather_functor, action_functor, ex);
336 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); ++i_to)
341 unsigned int sys_num = to_sys->
number();
360 bool is_nodal = fe_type.family ==
LAGRANGE;
364 for (
const auto & node : to_mesh->local_node_ptr_range())
367 if (node->n_dofs(sys_num, var_num) < 1)
372 bool point_found =
false;
373 for (
auto & group : incoming_vals_ids)
376 std::pair<unsigned int, dof_id_type> key(i_to, node->id());
378 mooseAssert(point_index_map.find(group.first) != point_index_map.end(),
379 "Point index map does not have data for processor group.first");
380 if (point_index_map[group.first].find(key) == point_index_map[group.first].end())
383 auto i_pt = point_index_map[group.first][key];
389 if (group.second[i_pt].second >= lowest_app_rank)
397 best_val = group.second[i_pt].first;
402 mooseError(
"Point not found in the reference space! ",
405 dof_id_type dof = node->dof_number(sys_num, var_num, 0);
406 solution->
set(dof, best_val);
411 std::vector<Point> points;
412 std::vector<dof_id_type> point_ids;
413 for (
auto & elem :
as_range(to_mesh->local_elements_begin(), to_mesh->local_elements_end()))
416 if (elem->n_dofs(sys_num, var_num) < 1)
425 points.push_back(elem->vertex_average());
426 point_ids.push_back(elem->id());
433 for (
auto & node : elem->node_ref_range())
435 points.push_back(node);
436 point_ids.push_back(node.id());
440 auto n_points = points.size();
441 unsigned int n_comp = elem->n_comp(sys_num, var_num);
443 if (n_points != n_comp)
446 " does not equal to number of variable components ",
448 for (
unsigned int offset = 0; offset < n_points; offset++)
452 bool point_found =
false;
453 for (
auto & group : incoming_vals_ids)
456 std::pair<unsigned int, dof_id_type> key(i_to, point_ids[offset]);
457 if (point_index_map[group.first].find(key) == point_index_map[group.first].end())
460 unsigned int i_pt = point_index_map[group.first][key];
466 if (group.second[i_pt].second >= lowest_app_rank)
474 best_val = group.second[i_pt].first;
479 mooseError(
"Point not found in the reference space! ",
483 dof_id_type dof = elem->dof_number(sys_num, var_num, offset);
484 solution->
set(dof, best_val);
libMesh::NumericVector< Real > & getTransferVector(unsigned int i_local, std::string var_name)
If we are transferring to a multiapp, return the appropriate solution vector.
std::vector< std::unique_ptr< MultiAppCoordTransform > > _to_transforms
std::vector< libMesh::EquationSystems * > _to_es
virtual void execute() override
Execute the transfer.
const unsigned int invalid_uint
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
MooseEnum _current_direction
MultiAppShapeEvaluationTransfer(const InputParameters ¶meters)
registerMooseObjectDeprecated("MooseApp", MultiAppShapeEvaluationTransfer, "12/31/2024 24:00")
std::vector< libMesh::BoundingBox > getFromBoundingBoxes()
Return the bounding boxes of all the "from" domains, including all the domains not local to this proc...
virtual libMesh::System & system()=0
Get the reference to the libMesh system.
const std::vector< VariableName > _from_var_names
Name of variables transferring from.
std::vector< FEProblemBase * > _to_problems
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...
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
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.
unsigned int variable_number(std::string_view var) const
uint8_t processor_id_type
processor_id_type n_processors() const
unsigned int number() const
const std::string & name() const
Get the name of the class.
libMesh::EquationSystems & getEquationSystem(FEProblemBase &problem, bool use_displaced) const
Returns the Problem's equation system, displaced or not Be careful! If you transfer TO a displaced sy...
bool _error_on_miss
Whether to error if the target point is not found in the source domain.
void mooseDeprecated(Args &&... args) const
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
const std::vector< AuxVariableName > _to_var_names
Name of variables transferring to.
static libMesh::System * find_sys(libMesh::EquationSystems &es, const std::string &var_name)
Small helper function for finding the system containing the variable.
std::unique_ptr< NumericVector< Number > > solution
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...
static const libMesh::Number OutOfMeshValue
static InputParameters validParams()
Transfers a vector of variables.
const FEType & variable_type(const unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void transferVariable(unsigned int i)
Performs the transfer for the variable of index i.
unsigned int _var_size
The number of variables to transfer.
registerMooseObjectRenamed("MooseApp", MultiAppMeshFunctionTransfer, "12/31/2023 24:00", MultiAppShapeEvaluationTransfer)
std::vector< std::unique_ptr< MultiAppCoordTransform > > _from_transforms
bool _displaced_source_mesh
True if displaced mesh is used for the source mesh, otherwise false.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
std::vector< unsigned int > _from_local2global_map
Given local app index, returns global app index.
static InputParameters validParams()
std::unique_ptr< NumericVector< Number > > current_local_solution
static void addBBoxFactorParam(InputParameters ¶ms)
Add the bounding box factor parameter to the supplied input parameters.
virtual void set(const numeric_index_type i, const T value)=0
processor_id_type processor_id() const
SystemBase & sys()
Get the system this variable is part of.
const DofMap & get_dof_map() const
std::vector< FEProblemBase * > _from_problems
std::vector< MooseMesh * > _to_meshes