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))
292 vals_ids_for_incoming_points[i_pt].first = (local_meshfuns[i_from])(
312 std::map<processor_id_type, std::vector<std::pair<Real, unsigned int>>> incoming_vals_ids;
314 auto action_functor =
315 [&incoming_vals_ids](
317 const std::vector<Point> & ,
318 const std::vector<std::pair<Real, unsigned int>> & vals_ids_for_outgoing_points)
321 incoming_vals_ids[pid].reserve(vals_ids_for_outgoing_points.size());
323 std::copy(vals_ids_for_outgoing_points.begin(),
324 vals_ids_for_outgoing_points.end(),
325 std::back_inserter(incoming_vals_ids[pid]));
330 const std::pair<Real, unsigned int> * ex =
nullptr;
331 libMesh::Parallel::pull_parallel_vector_data(
332 comm(), outgoing_points, gather_functor, action_functor, ex);
334 for (
unsigned int i_to = 0; i_to <
_to_problems.size(); ++i_to)
339 unsigned int sys_num = to_sys->
number();
358 bool is_nodal = fe_type.family ==
LAGRANGE;
362 for (
const auto & node : to_mesh->local_node_ptr_range())
365 if (node->n_dofs(sys_num, var_num) < 1)
370 bool point_found =
false;
371 for (
auto & group : incoming_vals_ids)
374 std::pair<unsigned int, dof_id_type> key(i_to, node->id());
376 mooseAssert(point_index_map.find(group.first) != point_index_map.end(),
377 "Point index map does not have data for processor group.first");
378 if (point_index_map[group.first].find(key) == point_index_map[group.first].end())
381 auto i_pt = point_index_map[group.first][key];
387 if (group.second[i_pt].second >= lowest_app_rank)
395 best_val = group.second[i_pt].first;
400 mooseError(
"Point not found in the reference space! ",
403 dof_id_type dof = node->dof_number(sys_num, var_num, 0);
404 solution->
set(dof, best_val);
409 std::vector<Point> points;
410 std::vector<dof_id_type> point_ids;
411 for (
auto & elem :
as_range(to_mesh->local_elements_begin(), to_mesh->local_elements_end()))
414 if (elem->n_dofs(sys_num, var_num) < 1)
423 points.push_back(elem->vertex_average());
424 point_ids.push_back(elem->id());
431 for (
auto & node : elem->node_ref_range())
433 points.push_back(node);
434 point_ids.push_back(node.id());
438 auto n_points = points.size();
439 unsigned int n_comp = elem->n_comp(sys_num, var_num);
441 if (n_points != n_comp)
444 " does not equal to number of variable components ",
446 for (
unsigned int offset = 0; offset < n_points; offset++)
450 bool point_found =
false;
451 for (
auto & group : incoming_vals_ids)
454 std::pair<unsigned int, dof_id_type> key(i_to, point_ids[offset]);
455 if (point_index_map[group.first].find(key) == point_index_map[group.first].end())
458 unsigned int i_pt = point_index_map[group.first][key];
464 if (group.second[i_pt].second >= lowest_app_rank)
472 best_val = group.second[i_pt].first;
477 mooseError(
"Point not found in the reference space! ",
481 dof_id_type dof = elem->dof_number(sys_num, var_num, offset);
482 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
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
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
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.
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.
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.
void mooseDeprecated(Args &&... args) const
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)
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