24 #include "libmesh/point_locator_base.h" 25 #include "libmesh/enum_point_locator_type.h" 48 "Factor to inflate or deflate the source app bounding boxes");
50 "fixed_bounding_box_size",
51 "fixed_bounding_box_size >= 0",
52 "Override source app bounding box size(s) for searches. App bounding boxes will still be " 53 "centered on the same coordinates. Only non-zero components passed will override.");
55 "extrapolation_constant",
57 "Constant to use when no source app can provide a valid value for a target location.");
60 params.
addParam<std::vector<SubdomainName>>(
62 "Subdomain restriction to transfer from (defaults to all the origin app domain)");
63 params.
addParam<std::vector<SubdomainName>>(
64 "to_blocks",
"Subdomain restriction to transfer to, (defaults to all the target app domain)");
67 params.
addParam<std::vector<BoundaryName>>(
69 "The boundary we are transferring from (if not specified, whole domain is used).");
70 params.
addParam<std::vector<BoundaryName>>(
72 "The boundary we are transferring to (if not specified, whole domain is used).");
73 MooseEnum nodes_or_sides(
"nodes sides",
"sides");
76 "Whether elemental variable boundary restriction is considered by " 77 "element side or element nodes");
80 params.
addParam<MeshDivisionName>(
"from_mesh_division",
81 "Mesh division object on the origin application");
82 params.
addParam<MeshDivisionName>(
"to_mesh_division",
83 "Mesh division object on the target application");
84 MooseEnum mesh_division_uses(
"spatial_restriction matching_division matching_subapp_index none",
88 "How to use the source mesh division in the transfer. See object " 89 "documentation for description of each option");
92 "How to use the target mesh division in the transfer. See object " 93 "documentation for description of each option");
96 params.
addParam<std::vector<unsigned int>>(
"source_variable_components",
97 std::vector<unsigned int>(),
98 "The source array or vector variable component(s).");
99 params.
addParam<std::vector<unsigned int>>(
"target_variable_components",
100 std::vector<unsigned int>(),
101 "The target array or vector variable component(s).");
107 "Whether or not to send a point to all the domains. If true, all the processors will be " 108 "checked for a given point." 109 "The code will be slow if this flag is on but it will give a better solution.");
113 "Whether or not to error in the case that a target point is not found in the source domain.");
114 params.
addParam<
bool>(
"use_bounding_boxes",
116 "When set to false, bounding boxes will not be used to restrict the source " 117 "of the transfer. Either source applications must be set using the " 118 "from_mesh_division parameter, or a greedy search must be used.");
122 "When True, transfers from a child application will work by finding the nearest (using " 123 "the `position` + mesh centroid) sub-app and query that app for the value to transfer.");
125 "use_nearest_position",
126 "Name of the the Positions object (in main app) such that transfers to/from a child " 127 "application will work by finding the nearest position to a target and query only the " 128 "app / points closer to this position than to any other position for the value to transfer.");
130 "from_app_must_contain_point",
132 "Wether on not the origin mesh must contain the point to evaluate data at. If false, this " 133 "allows for interpolation between origin app meshes. Origin app bounding boxes are still " 134 "considered so you may want to increase them with 'fixed_bounding_box_size'");
135 params.
addParam<
bool>(
"search_value_conflicts",
137 "Whether to look for potential conflicts between two valid and different " 138 "source values for any target point");
140 "value_conflicts_output",
142 "Maximum number of conflicts to output if value-conflicts, from equidistant sources to a " 143 "given transfer target location, search is turned on");
146 "to_blocks from_blocks to_boundaries from_boundaries elemental_boundary_restriction " 147 "from_mesh_division from_mesh_division_usage to_mesh_division to_mesh_division_usage",
148 "Transfer spatial restriction");
150 "greedy_search use_bounding_boxes use_nearest_app use_nearest_position " 151 "search_value_conflicts",
154 "Extrapolation behavior");
161 _from_var_components(getParam<
std::vector<unsigned
int>>(
"source_variable_components")),
162 _to_var_components(getParam<
std::vector<unsigned
int>>(
"target_variable_components")),
163 _use_bounding_boxes(getParam<bool>(
"use_bounding_boxes")),
164 _use_nearest_app(getParam<bool>(
"use_nearest_app")),
165 _nearest_positions_obj(
166 isParamValid(
"use_nearest_position")
167 ? &_fe_problem.getPositionsObject(getParam<PositionsName>(
"use_nearest_position"))
169 _source_app_must_contain_point(getParam<bool>(
"from_app_must_contain_point")),
170 _from_mesh_division_behavior(getParam<
MooseEnum>(
"from_mesh_division_usage")),
171 _to_mesh_division_behavior(getParam<
MooseEnum>(
"to_mesh_division_usage")),
172 _elemental_boundary_restriction_on_sides(
173 getParam<
MooseEnum>(
"elemental_boundary_restriction") ==
"sides"),
174 _greedy_search(getParam<bool>(
"greedy_search")),
175 _search_value_conflicts(getParam<bool>(
"search_value_conflicts")),
176 _already_output_search_value_conflicts(false),
177 _search_value_conflicts_max_log(getParam<unsigned
int>(
"value_conflicts_output")),
178 _error_on_miss(getParam<bool>(
"error_on_miss")),
179 _default_extrapolation_value(getParam<
Real>(
"extrapolation_constant")),
180 _bbox_factor(getParam<
Real>(
"bbox_factor")),
181 _fixed_bbox_size(isParamValid(
"fixed_bounding_box_size")
182 ? getParam<
std::vector<
Real>>(
"fixed_bounding_box_size")
187 paramError(
"variable",
"The number of variables to transfer to and from should be equal");
192 "This parameter must be equal to the number of source variables");
195 "This parameter must be equal to the number of target variables");
201 paramError(
"use_nearest_app",
"Cannot use nearest-app and nearest-position together");
204 "Should have a 'from_multiapp' when using the nearest-app informed search");
205 auto pos_params =
_app.
getFactory().getValidParams(
"MultiAppPositions");
206 pos_params.set<std::vector<MultiAppName>>(
"multiapps") = {
getFromMultiApp()->name()};
216 "Extrapolation (nearest-source options, outside-app source) parameters have " 217 "been passed, but no subapp bounding box expansion parameters have been passed.");
222 "Cannot pass additional bounding box parameters (sizes, expansion, etc) if we are " 223 "not using bounding boxes");
238 const auto & block_names = getParam<std::vector<SubdomainName>>(
"from_blocks");
240 for (
const auto & b : block_names)
242 paramError(
"from_blocks",
"The block '", b,
"' was not found in the mesh");
244 if (!block_names.empty())
246 const auto ids = from_moose_mesh.getSubdomainIDs(block_names);
253 const auto & boundary_names = getParam<std::vector<BoundaryName>>(
"from_boundaries");
254 for (
const auto & bn : boundary_names)
256 paramError(
"from_boundaries",
"The boundary '", bn,
"' was not found in the mesh");
258 if (!boundary_names.empty())
260 const auto boundary_ids = from_moose_mesh.getBoundaryIDs(boundary_names);
267 const auto & mesh_div_name = getParam<MeshDivisionName>(
"from_mesh_division");
273 mooseInfo(
"'from_mesh_division_usage' is set to use a spatial restriction but the " 274 "'from_mesh_division' for source app of global index " +
276 " covers the entire mesh. Do not expect any restriction from a mesh " 277 "division that covers the entire mesh");
282 "Source mesh division cannot match target mesh division if no target mesh " 283 "division is specified");
288 "Cannot match source mesh division index to target subapp index if there is " 289 "only one target: the parent app (not a subapp)");
292 mooseWarning(
"Attempting to match target subapp index with the number of source mesh " 293 "divisions, which is " +
295 " while there are " + std::to_string(
getToMultiApp()->numGlobalApps()) +
301 "We do not support using target subapp index for source division behavior and " 302 "matching the division index for the target mesh division behavior.");
305 paramError(
"from_mesh_division_usage",
"User must specify a 'from_mesh_division_usage'");
309 "'from_mesh_division' must be specified if the usage method is specified");
318 const auto & block_names = getParam<std::vector<SubdomainName>>(
"to_blocks");
319 for (
const auto & b : block_names)
321 paramError(
"to_blocks",
"The block '", b,
"' was not found in the mesh");
323 if (!block_names.empty())
325 const auto ids = to_moose_mesh.getSubdomainIDs(block_names);
332 const auto & boundary_names = getParam<std::vector<BoundaryName>>(
"to_boundaries");
333 for (
const auto & bn : boundary_names)
335 paramError(
"to_boundaries",
"The boundary '", bn,
"' was not found in the mesh");
337 if (!boundary_names.empty())
339 const auto boundary_ids = to_moose_mesh.getBoundaryIDs(boundary_names);
346 const auto & mesh_div_name = getParam<MeshDivisionName>(
"to_mesh_division");
352 mooseInfo(
"'to_mesh_division_usage' is set to use a spatial restriction but the " 353 "'to_mesh_division' for target application of global index " +
355 " covers the entire mesh. Do not expect any restriction from a mesh " 356 "division that covers the entire mesh");
362 "Target mesh division cannot match source mesh division if no source mesh " 363 "division is specified");
366 mooseWarning(
"Source and target mesh divisions do not have the same number of bins. If " 367 "this is what you expect, please reach out to a MOOSE or app developer to " 368 "ensure appropriate use");
374 "to_mesh_division_usage",
375 "Cannot match target mesh division index to source subapp index if there is only one " 376 "source: the parent app (not a subapp)");
378 mooseWarning(
"Attempting to match source subapp index with the number of target mesh " 379 "divisions, which is " +
381 " while there are " + std::to_string(
getFromMultiApp()->numGlobalApps()) +
385 "from_mesh_division_usage",
386 "We do not support using source subapp index for the target division behavior and " 387 "matching the division index for the source mesh division behavior.");
390 paramError(
"to_mesh_division_usage",
"User must specify a 'to_mesh_division_usage'");
394 "'to_mesh_division' must be specified if usage method '" +
409 paramError(
"source_variable_components",
"Component must be passed for an array variable");
412 "Component passed is larger than size of variable");
425 paramError(
"target_variable_components",
"Component must be passed for an array variable");
428 "Component passed is larger than size of variable");
462 "MultiAppGeneralFieldTransfer::execute()_" +
name(), 5,
"Transfer execution " +
name());
512 mooseAssert(i <
_var_size,
"The variable of index " << i <<
" does not exist");
528 auto gather_functor =
530 const std::vector<std::pair<Point, unsigned int>> & incoming_locations,
531 std::vector<std::pair<Real, Real>> & outgoing_vals)
533 outgoing_vals.resize(
534 incoming_locations.size(),
545 auto action_functor = [
this, &i, &dofobject_to_valsvec, &interp_caches, &distance_caches](
547 const std::vector<std::pair<Point, unsigned int>> & my_outgoing_points,
548 const std::vector<std::pair<Real, Real>> & incoming_vals)
558 dofobject_to_valsvec,
565 const std::pair<Real, Real> * ex =
nullptr;
566 libMesh::Parallel::pull_parallel_vector_data(
567 comm(), outgoing_points, gather_functor, action_functor, ex);
579 std::set<processor_id_type> & processors)
606 for (
unsigned int i_from = from0; i_from < from0 +
_froms_per_proc[i_proc]; ++i_from)
610 processors.insert(i_proc);
613 mooseAssert(i_from <
getFromMultiApp()->numGlobalApps(),
"We should not reach this");
618 "Should only be one source processor when using more processors than source apps");
632 if (
distance < nearest_max_distance)
636 unsigned int from0 = 0;
640 for (
unsigned int i_from = from0; i_from < from0 +
_froms_per_proc[i_proc]; ++i_from)
647 processors.insert(i_proc);
658 processors.insert(i_proc);
673 if (target_div == saved_target_div)
676 saved_target_div = target_div;
683 processors.insert(i_proc);
689 mooseError(
"No algorithm were selected to find which processes may send value data " 690 "for a each target point. Please either specify using bounding boxes, " 691 "greedy search, or to_mesh_division-based parameters");
696 "Cannot find a source application to provide a value at point: ",
699 "It must be that mismatched meshes, between the source and target application, are being " 700 "used.\nIf you are using the bounding boxes or nearest-app heuristics, or mesh-divisions, " 701 "please consider using the greedy_search to confirm. Then consider choosing a different " 702 "transfer type.\nThis check can be turned off by setting 'error_on_miss' to false. The " 703 "'extrapolation_constant' parameter will be used to set the local value at missed points.");
709 const unsigned int problem_id,
712 std::set<processor_id_type> processors;
720 for (
const auto pid : processors)
723 unsigned int required_source_division = 0;
737 outgoing_points[pid].push_back(std::pair<Point, unsigned int>(
point, required_source_division));
768 auto sys_num = to_sys->
number();
775 const auto & to_mesh = to_moose_mesh.getMesh();
778 if (fe_type.order >
CONSTANT && !is_nodal)
783 const std::vector<unsigned int> varvec(1, var_num);
789 request_gather(*to_sys, f, &g, nullsetter, varvec);
793 mooseError(
"Higher order discontinuous elemental variables are not supported for " 795 "restricted transfers");
800 mooseError(
"Higher order variable support not implemented for target mesh division " 801 "unless the mesh is fully covered / indexed in the mesh division. This must be " 802 "set programmatically in the MeshDivision object used.");
807 ? to_mesh.active_local_elements_begin()
808 : to_mesh.active_local_subdomain_set_elements_begin(
_to_blocks);
811 ? to_mesh.active_local_elements_end()
812 : to_mesh.active_local_subdomain_set_elements_end(
_to_blocks);
816 request_gather.
project(to_elem_range);
823 (*
_to_transforms[global_i_to])(p), point_id++, i_to, outgoing_points);
827 mooseError(
"We don't currently support variables with gradient degrees of freedom");
831 for (
const auto & node : to_mesh.local_node_ptr_range())
834 if (node->n_dofs(sys_num, var_num) < 1)
855 (*
_to_transforms[global_i_to])(*node), node->id(), i_to, outgoing_points);
860 for (
const auto & elem :
861 as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
864 if (elem->n_dofs(sys_num, var_num) < 1)
896 unsigned int local_start = 0;
902 local_bboxes[i_from] =
_from_bboxes[local_start + i_from];
908 const unsigned int var_index,
909 std::vector<PointInfo> & pointInfoVec,
910 const std::vector<std::pair<Point, unsigned int>> & point_requests,
911 const std::vector<std::pair<Real, Real>> & incoming_vals,
916 mooseAssert(pointInfoVec.size() == incoming_vals.size(),
917 "Number of dof objects does not equal to the number of incoming values");
920 for (
const auto & pointinfo : pointInfoVec)
923 const auto problem_id = pointinfo.problem_id;
924 const auto dof_object_id = pointinfo.dof_object_id;
933 if (fe_type.order >
CONSTANT && !is_nodal)
936 InterpCache & value_cache = interp_caches[problem_id];
937 InterpCache & distance_cache = distance_caches[problem_id];
939 point_requests[val_offset].first);
940 const Number val = incoming_vals[val_offset].first;
943 if (!distance_cache.
hasKey(p))
952 registerConflict(problem_id, dof_object_id, p, incoming_vals[val_offset].second,
false);
962 value_cache[p] = val;
963 distance_cache[p] = incoming_vals[val_offset].second;
975 const DofObject * dof_object_ptr =
nullptr;
976 const auto sys_num = to_sys.number();
979 dof_object_ptr = to_mesh.
node_ptr(dof_object_id);
982 dof_object_ptr = to_mesh.
elem_ptr(dof_object_id);
987 mooseAssert(dof_object_ptr->
n_dofs(sys_num, var_num) == 1,
988 "Unexpectedly found " << dof_object_ptr->
n_dofs(sys_num, var_num)
989 <<
"dofs instead of 1");
992 auto & dofobject_to_val = dofobject_to_valsvec[problem_id];
995 auto values_ptr = dofobject_to_val.find(dof_object_id);
997 if (values_ptr == dofobject_to_val.end())
1000 auto & val = dofobject_to_val[dof_object_id];
1002 val.interp = incoming_vals[val_offset].first;
1006 val.distance = incoming_vals[val_offset].second;
1010 auto & val = values_ptr->second;
1014 incoming_vals[val_offset].first,
1016 incoming_vals[val_offset].second))
1022 "Registration of received equi-distant value conflict");
1023 registerConflict(problem_id, dof_object_id, p, incoming_vals[val_offset].second,
false);
1038 val.interp = incoming_vals[val_offset].first;
1040 val.distance = incoming_vals[val_offset].second;
1063 const unsigned int var_index,
1075 const auto potential_conflict = *conflict_it;
1076 bool overlap_found =
false;
1079 const unsigned int problem_id = std::get<0>(potential_conflict);
1080 const dof_id_type dof_object_id = std::get<1>(potential_conflict);
1081 const Point p = std::get<2>(potential_conflict);
1092 if (fe_type.order >
CONSTANT && !is_nodal)
1094 auto cached_distance = distance_caches[problem_id].find(p);
1095 if (cached_distance == distance_caches[problem_id].end())
1096 mooseError(
"Conflict point was not found in the map of all origin-target distances");
1099 overlap_found =
true;
1103 dofobject_to_valsvec[problem_id].find(dof_object_id)->second.distance,
distance))
1104 overlap_found =
true;
1116 const unsigned int var_index,
1131 std::vector<std::tuple<Point, Real>> potential_conflicts;
1139 const auto potential_conflict = *conflict_it;
1140 const unsigned int i_from = std::get<0>(potential_conflict);
1141 Point p = std::get<2>(potential_conflict);
1152 potential_conflicts.push_back(std::make_tuple(p,
distance));
1156 std::sort(potential_conflicts.begin(), potential_conflicts.end());
1157 potential_conflicts.erase(unique(potential_conflicts.begin(),
1158 potential_conflicts.end(),
1162 std::abs(std::get<1>(l) - std::get<1>(r)) < TOLERANCE;
1164 potential_conflicts.end());
1166 std::vector<std::tuple<Point, Real>> real_conflicts;
1167 real_conflicts.reserve(potential_conflicts.size());
1170 for (
auto conflict_it = potential_conflicts.begin(); conflict_it != potential_conflicts.end();
1174 auto potential_conflict = *conflict_it;
1175 const Point p = std::get<0>(potential_conflict);
1180 bool target_found =
false;
1181 bool conflict_real =
false;
1196 if (fe_type.order >
CONSTANT && !is_nodal)
1199 auto cached_distance = distance_caches[i_to].find(local_p);
1200 if (cached_distance != distance_caches[i_to].end())
1202 target_found =
true;
1206 conflict_real =
true;
1214 auto pl =
_to_problems[i_to]->mesh().getPointLocator();
1215 pl->enable_out_of_mesh_mode();
1218 auto node = pl->locate_node(local_p);
1221 dof_object_id = node->id();
1225 auto elem = (*pl)(local_p);
1227 dof_object_id = elem->id();
1229 pl->disable_out_of_mesh_mode();
1236 if (dofobject_to_valsvec[i_to].find(dof_object_id) == dofobject_to_valsvec[i_to].end())
1239 target_found =
true;
1243 dofobject_to_valsvec[i_to].find(dof_object_id)->second.distance,
distance))
1244 conflict_real =
true;
1248 if (target_found && conflict_real)
1249 real_conflicts.push_back(potential_conflict);
1262 const auto potential_conflict = *conflict_it;
1263 const unsigned int i_from = std::get<0>(potential_conflict);
1264 Point p = std::get<2>(potential_conflict);
1273 if (std::find_if(real_conflicts.begin(),
1274 real_conflicts.end(),
1279 }) == real_conflicts.end())
1288 const unsigned int var_index,
1301 unsigned int num_outputs = 0;
1302 std::string local_conflicts_string =
"";
1303 std::string potential_reasons =
1304 "Are some points in target mesh equidistant from the sources " 1305 "(nodes/centroids/apps/positions, depending on transfer) in origin mesh(es)?\n";
1307 potential_reasons +=
"Are multiple subapps overlapping?\n";
1310 const unsigned int problem_id = std::get<0>(conflict);
1311 Point p = std::get<2>(conflict);
1314 std::string origin_domain_message;
1323 origin_domain_message =
"In source child app " + std::to_string(app_id) +
" mesh,";
1333 origin_domain_message =
"In target app mesh,";
1336 origin_domain_message =
"In reference (post-coordinate collapse) mesh,";
1339 origin_domain_message =
"In source parent app mesh,";
1342 local_conflicts_string += origin_domain_message +
" point: (" + std::to_string(p(0)) +
1343 ", " + std::to_string(p(1)) +
", " + std::to_string(p(2)) +
1344 "), equi-distance: " + std::to_string(std::get<3>(conflict)) +
1347 local_conflicts_string +=
1348 "Maximum output of the search for value conflicts has been reached. Further conflicts " 1349 "will not be output.\nIncrease 'search_value_conflicts_max_log' to output more.";
1352 std::string source_str =
"unknown";
1356 source_str =
"user object '" + getParam<UserObjectName>(
"source_user_object") +
"'";
1359 ", multiple valid values from equidistant points were " 1360 "found in the origin mesh for source " +
1362 " target points.\n" + potential_reasons +
"Conflicts detected at :\n" +
1363 local_conflicts_string);
1369 unsigned int num_outputs = 0;
1370 std::string received_conflicts_string =
"";
1371 std::string potential_reasons =
1372 "Are some points in target mesh equidistant from the sources " 1373 "(nodes/centroids/apps/positions, depending on transfer) in origin mesh(es)?\n";
1375 potential_reasons +=
"Are multiple subapps overlapping?\n";
1379 const unsigned int problem_id = std::get<0>(conflict);
1380 const Point p = std::get<2>(conflict);
1383 std::string target_domain_message;
1387 target_domain_message =
"In target child app " + std::to_string(app_id) +
" mesh,";
1390 target_domain_message =
"In target parent app mesh,";
1393 received_conflicts_string += target_domain_message +
" point: (" + std::to_string(p(0)) +
1394 ", " + std::to_string(p(1)) +
", " + std::to_string(p(2)) +
1395 "), equi-distance: " + std::to_string(std::get<3>(conflict)) +
1398 received_conflicts_string +=
1399 "Maximum output of the search for value conflicts has been reached. Further conflicts " 1400 "will not be output.\nIncrease 'search_value_conflicts_max_log' to output more.";
1403 ", multiple valid values from equidistant points were " 1404 "received for target variable '" +
1406 " target points.\n" + potential_reasons +
"Conflicts detected at :\n" +
1407 received_conflicts_string);
1413 mooseInfo(
"Automated diagnosis did not detect floating point indetermination in transfer");
1416 "Automated diagnosis did not detect any floating point indetermination in " 1417 "the transfer. You may consider turning it off using `search_value_conflicts=false` " 1418 "to improve performance/scalability.");
1429 const unsigned int var_index,
1438 auto & dofobject_to_val = dofobject_to_valsvec[problem_id];
1450 auto sys_num = to_sys->
number();
1455 if (fe_type.order >
CONSTANT && !is_nodal)
1465 const std::vector<unsigned int> varvec(1, var_num);
1471 set_solution(*to_sys, f,
nullptr, setter, varvec);
1475 ? to_mesh.active_local_elements_begin()
1476 : to_mesh.active_local_subdomain_set_elements_begin(
_to_blocks);
1479 ? to_mesh.active_local_elements_end()
1480 : to_mesh.active_local_subdomain_set_elements_end(
_to_blocks);
1484 set_solution.
project(active_local_elem_range);
1488 for (
const auto & val_pair : dofobject_to_val)
1490 const auto dof_object_id = val_pair.first;
1494 dof_object = to_mesh.
node_ptr(dof_object_id);
1496 dof_object = to_mesh.
elem_ptr(dof_object_id);
1498 const auto dof = dof_object->
dof_number(sys_num, var_num, 0);
1499 const auto val = val_pair.second.interp;
1504 const auto target_location =
1508 const auto info_msg =
"\nThis check can be turned off by setting 'error_on_miss' to " 1509 "false. The 'extrapolation_constant' parameter will be used to set " 1510 "the local value at missed points.";
1515 " could be located. Node details:\n",
1516 _to_meshes[problem_id]->nodePtr(dof_object_id)->get_info(),
1523 " could be located. Element details:\n",
1524 _to_meshes[problem_id]->elemPtr(dof_object_id)->get_info(),
1552 const std::vector<BoundingBox> & local_bboxes,
1554 const unsigned int only_from_mesh_div,
1555 Real & distance)
const 1563 const auto transformed_pt =
_from_transforms[from_global_num]->mapBack(pt);
1581 Point nearest_position_source;
1592 mooseError(
"Rotation and scaling currently unsupported with nearest positions transfer.");
1595 const Real distance_to_position_nearest_source = (pt - nearest_position_source).
norm();
1596 const Real distance_to_nearest_position = (pt - nearest_position).
norm();
1603 distance_to_nearest_position))
1607 distance = distance_to_position_nearest_source;
1613 !
inMesh(pl, transformed_pt))
1625 return (elem !=
nullptr);
1630 const Elem * elem)
const 1638 const Elem * elem)
const 1646 const Node * node)
const 1648 const auto & node_blocks =
mesh.getNodeBlockIds(*node);
1649 std::set<SubdomainID> u;
1650 std::set_intersection(
blocks.begin(),
1652 node_blocks.begin(),
1654 std::inserter(u, u.begin()));
1664 return (elem !=
nullptr);
1670 const Node * node)
const 1673 std::vector<BoundaryID> vec_to_fill;
1675 std::set<BoundaryID> vec_to_fill_set(vec_to_fill.begin(), vec_to_fill.end());
1676 std::set<BoundaryID> u;
1677 std::set_intersection(boundaries.begin(),
1679 vec_to_fill_set.begin(),
1680 vec_to_fill_set.end(),
1681 std::inserter(u, u.begin()));
1688 const Elem * elem)
const 1692 std::vector<BoundaryID> vec_to_fill;
1693 std::vector<BoundaryID> vec_to_fill_temp;
1698 vec_to_fill.insert(vec_to_fill.end(), vec_to_fill_temp.begin(), vec_to_fill_temp.end());
1704 vec_to_fill.insert(vec_to_fill.end(), vec_to_fill_temp.begin(), vec_to_fill_temp.end());
1706 std::set<BoundaryID> vec_to_fill_set(vec_to_fill.begin(), vec_to_fill.end());
1709 std::set<BoundaryID> u;
1710 std::set_intersection(boundaries.begin(),
1712 vec_to_fill_set.begin(),
1713 vec_to_fill_set.end(),
1714 std::inserter(u, u.begin()));
1720 const std::set<SubdomainID> & block_restriction,
1727 if (block_restriction.empty())
1728 elem = (*pl)(
point);
1730 elem = (*pl)(
point, &block_restriction);
1739 const Point & pt,
const unsigned int i_local,
const unsigned int only_from_this_mesh_div)
const 1753 source_mesh_div != only_from_this_mesh_div)
1758 source_mesh_div != only_from_this_mesh_div)
1772 paramError(
"skip_coordinate_collapsing",
"Coordinate collapsing not implemented");
1783 Real distance_to_position_at_index = (pt - nearest_position_at_index).
norm();
1784 const Real distance_to_nearest_position = (pt - nearest_position).
norm();
1787 distance_to_nearest_position))
1790 else if (nearest_position == nearest_position_at_index)
1797 nearest_position_at_index,
1798 " detected near point ",
1808 std::array<Point, 2> source_points = {{bbox.first, bbox.second}};
1810 std::array<Point, 8> all_points;
1811 for (
unsigned int x = 0; x < 2; x++)
1812 for (
unsigned int y = 0; y < 2; y++)
1813 for (
unsigned int z = 0; z < 2; z++)
1814 all_points[x + 2 * y + 4 * z] =
1815 Point(source_points[x](0), source_points[y](1), source_points[z](2));
1817 Real max_distance = 0.;
1819 for (
unsigned int i = 0; i < 8; i++)
1826 return max_distance;
1832 std::array<Point, 2> source_points = {{bbox.first, bbox.second}};
1834 std::array<Point, 8> all_points;
1835 for (
unsigned int x = 0; x < 2; x++)
1836 for (
unsigned int y = 0; y < 2; y++)
1837 for (
unsigned int z = 0; z < 2; z++)
1838 all_points[x + 2 * y + 4 * z] =
1839 Point(source_points[x](0), source_points[y](1), source_points[z](2));
1843 for (
unsigned int i = 0; i < 8; i++)
1850 return min_distance;
1853 std::vector<BoundingBox>
1856 std::vector<std::pair<Point, Point>> bb_points(
_from_meshes.size());
1857 const Real min_r = std::numeric_limits<Real>::lowest();
1864 bool at_least_one =
false;
1867 for (
const auto & elem :
as_range(from_mesh.getMesh().local_elements_begin(),
1868 from_mesh.getMesh().local_elements_end()))
1878 at_least_one =
true;
1891 if ((from_mesh.getUniqueCoordSystem() ==
Moose::COORD_RZ) && (LIBMESH_DIM == 3))
1911 bb_points[j] =
static_cast<std::pair<Point, Point>
>(bbox);
1918 std::vector<BoundingBox> bboxes(bb_points.size());
1919 for (
const auto i :
make_range(bb_points.size()))
1920 bboxes[i] =
static_cast<BoundingBox>(bb_points[i]);
1927 for (
const auto j :
make_range(bboxes.size()))
1929 const auto current_width = (bboxes[j].second - bboxes[j].first)(i);
1937 std::vector<unsigned int>
1940 std::vector<unsigned int> global_app_start_per_proc(1, -1);
1944 return global_app_start_per_proc;
1950 mooseAssert(var_index <
_from_var_names.size(),
"No source variable at this index");
1960 mooseAssert(var_index <
_to_var_names.size(),
"No target variable at this index");
1976 const auto bbox = to_mesh->getInflatedProcessorBoundingBox();
1982 return max_dimension;
1988 Real current_distance,
1989 Real new_distance)
const
std::vector< BoundingBox > _from_bboxes
Bounding boxes for all source applications.
void mooseInfo(Args &&... args) const
std::vector< std::unique_ptr< MultiAppCoordTransform > > _to_transforms
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
virtual void evaluateInterpValues(const std::vector< std::pair< Point, unsigned int >> &incoming_points, std::vector< std::pair< Real, Real >> &outgoing_vals)=0
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
void examineReceivedValueConflicts(const unsigned int var_index, const DofobjectToInterpValVec &dofobject_to_valsvec, const InterpCaches &distance_caches)
Remove potential value conflicts that did not materialize because another source was closer Several e...
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
const Point & getNearestPosition(const Point &target, bool initial) const
Find the nearest Position for a given point.
void cacheOutgoingPointInfo(const Point point, const dof_id_type dof_object_id, const unsigned int problem_id, ProcessorToPointVec &outgoing_points)
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
static void transformBoundingBox(libMesh::BoundingBox &box, const MultiAppCoordTransform &transform)
Transform a bounding box according to the transformations in the provided coordinate transformation o...
const std::shared_ptr< MultiApp > getFromMultiApp() const
Get the MultiApp to transfer data from.
bool hasBoundaryName(const MeshBase &input_mesh, const BoundaryName &name)
Whether a particular boundary name exists in the mesh.
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 ...
bool _source_app_must_contain_point
Whether the source app mesh must actually contain the points for them to be considered or whether the...
const bool _skip_coordinate_collapsing
Whether to skip coordinate collapsing (transformations of coordinates between applications using diff...
void registerConflict(unsigned int problem, dof_id_type dof_id, Point p, Real dist, bool local)
Register a potential value conflict, e.g.
VariableName getFromVarName(unsigned int var_index)
Get the source variable name, with the suffix for array/vector variables.
const ExecFlagType & getCurrentExecuteOnFlag() const
Return/set the current execution flag.
const InputParameters & parameters() const
Get the parameters of the object.
void locatePointReceivers(const Point point, std::set< processor_id_type > &processors)
std::vector< std::unique_ptr< libMesh::PointLocatorBase > > _from_point_locators
Point locators, useful to examine point location with regards to domain restriction.
unsigned int count() const
Get the number of components Note: For standard and vector variables, the number is one...
const std::vector< VariableName > _from_var_names
Name of variables transferring from.
virtual void execute() override
Execute the transfer.
MultiAppGeneralFieldTransfer(const InputParameters ¶meters)
std::vector< FEProblemBase * > _to_problems
processor_id_type rank() const
Number BetterOutOfMeshValue
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
const Parallel::Communicator & comm() const
bool acceptPointMeshDivision(const Point &pt, const unsigned int i_local, const unsigned int only_from_this_mesh_div) const
Whether a point lies inside the mesh division delineated by the MeshDivision object.
virtual void postExecute()
Add some extra work if necessary after execute().
std::vector< unsigned int > getGlobalStartAppPerProc() const
Get global index for the first app each processes owns Requires a global communication, must be called on every domain simultaneously.
FEProblemBase & _fe_problem
const std::shared_ptr< MultiApp > getToMultiApp() const
Get the MultiApp to transfer data to.
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
static InputParameters validParams()
This class provides an interface for common operations on field variables of both FE and FV types wit...
const Point & getPosition(unsigned int index, bool initial) const
Getter for a single position at a known index.
const Parallel::Communicator & _communicator
std::vector< Real > _fixed_bbox_size
Set the bounding box sizes manually.
std::vector< const MeshDivision * > _from_mesh_divisions
Division of the origin mesh.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
std::vector< const MeshDivision * > _to_mesh_divisions
Division of the target mesh.
unsigned int _var_size
The number of variables to transfer.
std::vector< Point > & points_requested()
const BoundaryInfo & get_boundary_info() const
const Real _default_extrapolation_value
Value to use when no received data is valid for a target location.
bool inMesh(const libMesh::PointLocatorBase *const pl, const Point &pt) const
bool closestToPosition(unsigned int pos_index, const Point &pt) const
Whether a point is closest to a position at the index specified than any other position.
bool hasFromMultiApp() const
Whether the transfer owns a non-null from_multi_app.
const Positions & getPositionsObject(const std::string &name) const
Get the Positions object by its name.
const std::vector< unsigned int > _from_var_components
Origin array/vector variable components.
Real distance(const Point &p)
virtual void getAppInfo() override
This method will fill information into the convenience member variables (_to_problems, _from_meshes, etc.)
Point getPointInTargetAppFrame(const Point &p, unsigned int local_i_to, const std::string &phase) const
Get the target app point from a point in the reference frame.
VariableName getToVarName(unsigned int var_index)
Get the target variable name, with the suffix for array/vector variables.
std::set< BoundaryID > _from_boundaries
Origin boundary(ies) restriction.
void outputValueConflicts(const unsigned int var_index, const DofobjectToInterpValVec &dofobject_to_valsvec, const InterpCaches &distance_caches)
Report on conflicts between overlapping child apps, equidistant origin points etc.
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
auto max(const L &left, const R &right)
std::vector< unsigned int > _to_local2global_map
Given local app index, returns global app index.
const Positions * _nearest_positions_obj
unsigned int variable_number(std::string_view var) const
Real bboxMinDistance(const Point &p, const BoundingBox &bbox) const
Compute minimum distance.
unsigned int getGlobalTargetAppIndex(unsigned int i_to) const
Return the global app index from the local index in the "to-multiapp" transfer direction.
bool _displaced_target_mesh
True if displaced mesh is used for the target mesh, otherwise false.
void extractOutgoingPoints(const unsigned int var_index, ProcessorToPointVec &outgoing_points)
std::set< SubdomainID > _to_blocks
Target block(s) restriction.
unsigned int n_dofs(const unsigned int s, const unsigned int var=libMesh::invalid_uint) const
processor_id_type size() const
std::unordered_map< processor_id_type, std::vector< std::pair< Point, unsigned int > > > ProcessorToPointVec
A map from pid to a set of points.
Point getMaxToProblemsBBoxDimensions() const
Obtains the max dimensions to scale all points in the mesh.
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
dof_id_type dof_object_id
virtual void prepareEvaluationOfInterpValues(const unsigned int var_index)=0
const std::vector< unsigned int > _to_var_components
Target array/vector variable components.
processor_id_type n_processors() const
Real bboxMaxDistance(const Point &p, const BoundingBox &bbox) const
Compute max distance.
unsigned int getNearestPositionIndex(const Point &target, bool initial) const
Find the nearest Position index for a given point.
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 isBetterOutOfMeshValue(Number val)
std::vector< MooseMesh * > _from_meshes
std::vector< std::tuple< unsigned int, dof_id_type, Point, Real > > _local_conflicts
Keeps track of all local equidistant points to requested points, creating an indetermination in which...
const bool _use_bounding_boxes
Whether to use bounding boxes to determine the applications that may receive point requests then send...
Value request recording base class.
bool acceptPointInOriginMesh(unsigned int i_from, const std::vector< BoundingBox > &local_bboxes, const Point &pt, const unsigned int mesh_div, Real &distance) const
void project(const ConstElemRange &range)
virtual unsigned int n_nodes() const=0
std::set< BoundaryID > _to_boundaries
Target boundary(ies) restriction.
std::vector< unsigned int > _froms_per_proc
Number of source/from applications per processor. This vector is indexed by processor id...
std::vector< std::tuple< unsigned int, dof_id_type, Point, Real > > _received_conflicts
Keeps track of all received conflicts.
const Point & min() const
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
std::vector< std::unordered_map< dof_id_type, InterpInfo > > DofobjectToInterpValVec
A vector, indexed by to-problem id, of maps from dof object to interpolation values.
Real _bbox_factor
How much we should relax bounding boxes.
bool _error_on_miss
Error out when some points can not be located.
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
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
std::vector< unsigned int > getFromsPerProc()
Return the number of "from" domains that each processor owns.
virtual void init() override
Transfers variables on possibly different meshes while conserving a user defined property (Postproces...
bool _search_value_conflicts
Whether to look for conflicts between origin points, multiple valid values for a target point...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
unsigned int getGlobalSourceAppIndex(unsigned int i_from) const
Return the global app index from the local index in the "from-multiapp" transfer direction.
MooseApp & _app
The MOOSE application this is associated with.
An unordered map indexed by Point, eg 3 floating point numbers Because floating point rounding errors...
void transferVariable(unsigned int i)
Performs the transfer for the variable of index i.
std::string stringify(const T &t)
conversion to string
unsigned int INVALID_DIVISION_INDEX
Invalid subdomain id to return when outside the mesh division.
void examineLocalValueConflicts(const unsigned int var_index, const DofobjectToInterpValVec &dofobject_to_valsvec, const InterpCaches &distance_caches)
Remove potential value conflicts that did not materialize because another source was closer Several e...
bool detectConflict(Real value_1, Real value_2, Real distance_1, Real distance_2) const
Detects whether two source values are valid and equidistant for a desired target location.
bool hasSubdomainName(const MeshBase &input_mesh, const SubdomainName &name)
Whether a particular subdomain name exists in the mesh.
std::vector< BoundingBox > getRestrictedFromBoundingBoxes() const
Get from bounding boxes for given domains and boundaries.
SimpleRange< NodeRefIter > node_ref_range()
virtual const Elem * elem_ptr(const dof_id_type i) const=0
virtual unsigned int n_sides() const=0
virtual void addReporter(const std::string &type, const std::string &name, InputParameters ¶meters)
Add a Reporter object to the simulation.
bool absolute_fuzzy_equals(const T &var1, const T2 &var2, const Real tol=TOLERANCE *TOLERANCE)
const FEType & variable_type(const unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
bool _already_output_search_value_conflicts
Whether we already output the search value conflicts.
const MooseEnum & _to_mesh_division_behavior
How to use the target mesh divisions to restrict the transfer.
virtual void postExecute() override
Add some extra work if necessary after execute().
const Node * node_ptr(const unsigned int i) const
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
std::vector< std::unique_ptr< MultiAppCoordTransform > > _from_transforms
IntRange< T > make_range(T beg, T end)
bool hasToMultiApp() const
Whether the transfer owns a non-null to_multi_app.
Value request response base class.
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::set< SubdomainID > _from_blocks
Origin block(s) restriction.
std::vector< unsigned int > _from_local2global_map
Given local app index, returns global app index.
const unsigned int _search_value_conflicts_max_log
How many conflicts are output to console.
std::vector< InterpCache > InterpCaches
A vector of such caches, indexed by to_problem.
static InputParameters validParams()
std::unique_ptr< NumericVector< Number > > current_local_solution
void extractLocalFromBoundingBoxes(std::vector< BoundingBox > &local_bboxes)
void extendBoundingBoxes(const Real factor, std::vector< libMesh::BoundingBox > &bboxes) const
Extends bounding boxes to avoid missing points.
std::vector< MooseVariableFieldBase * > _to_variables
The target variables.
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
ProcessorToPointInfoVec _processor_to_pointInfoVec
A map from processor to pointInfo vector.
const bool _elemental_boundary_restriction_on_sides
Whether elemental variable boundary restriction is considered by element side or element nodes...
virtual void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup...
void prepareToTransfer()
Initialize supporting attributes like bounding boxes, processor app indexes etc.
virtual const Node * node_ptr(const dof_id_type i) const=0
processor_id_type processor_id() const
virtual void getAppInfo()
This method will fill information into the convenience member variables (_to_problems, _from_meshes, etc.)
auto min(const L &left, const R &right)
const DofMap & get_dof_map() const
void setSolutionVectorValues(const unsigned int var_index, const DofobjectToInterpValVec &dofobject_to_valsvec, const InterpCaches &interp_caches)
unsigned int hasKey(Point p)
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
bool onBoundaries(const std::set< BoundaryID > &boundaries, const MooseMesh &mesh, const Node *node) const
std::vector< FEProblemBase * > _from_problems
void ErrorVector unsigned int
auto index_range(const T &sizable)
bool absoluteFuzzyGreaterThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether a variable is greater than another variable within an absolute tolerance...
std::vector< MooseMesh * > _to_meshes
bool _greedy_search
Whether or not a greedy strategy will be used If true, all the partitions will be checked for a given...
void cacheIncomingInterpVals(processor_id_type pid, const unsigned int var_index, std::vector< PointInfo > &pointInfoVec, const std::vector< std::pair< Point, unsigned int >> &point_requests, const std::vector< std::pair< Real, Real >> &incoming_vals, DofobjectToInterpValVec &dofobject_to_valsvec, InterpCaches &interp_caches, InterpCaches &distance_caches)
std::vector< unsigned int > _global_app_start_per_proc
First app each processor owns, indexed by processor If no app on the processor, will have a -1 for th...
const MooseEnum & _from_mesh_division_behavior
How to use the origin mesh divisions to restrict the transfer.
bool inBlocks(const std::set< SubdomainID > &blocks, const Elem *elem) const
const bool _use_nearest_app
Whether to keep track of the distance from the requested point to the app position.
const ExecFlagType EXEC_INITIAL