19 #include "libmesh/periodic_boundary_base.h" 58 "ElementSideNeighborLayers",
62 { rm_params.
set<
unsigned short>(
"layers") = obj_params.
get<
unsigned short>(
"halo_level"); }
70 params.
set<
bool>(
"restartable_required") =
true;
74 "Absolute value of the lower bound for the variable value that represents " 75 "a region not assigned to the grain. Must be positive, but the actual " 76 "value used is -bound_value.");
78 params.
addClassDescription(
"Grain Tracker object for running reduced order parameter simulations " 79 "without grain coalescence.");
87 _tracking_step(getParam<
int>(
"tracking_step")),
88 _halo_level(getParam<unsigned short>(
"halo_level")),
89 _max_remap_recursion_depth(getParam<unsigned short>(
"max_remap_recursion_depth")),
90 _n_reserve_ops(getParam<unsigned short>(
"reserve_op")),
91 _reserve_op_index(_n_reserve_ops <= _n_vars ? _n_vars - _n_reserve_ops : 0),
92 _reserve_op_threshold(getParam<
Real>(
"reserve_op_threshold")),
93 _bound_value(getParam<
Real>(
"bound_value")),
94 _remap(getParam<bool>(
"remap_grains")),
95 _tolerate_failure(getParam<bool>(
"tolerate_failure")),
96 _poly_ic_uo(parameters.isParamValid(
"polycrystal_ic_uo")
99 _verbosity_level(getParam<short>(
"verbosity_level")),
100 _first_time(declareRestartableData<bool>(
"first_time", true)),
101 _error_on_grain_creation(getParam<bool>(
"error_on_grain_creation")),
102 _reserve_grain_first_index(0),
103 _old_max_grain_id(0),
104 _max_curr_grain_id(declareRestartableData<unsigned
int>(
"max_curr_grain_id", invalid_id)),
105 _is_transient(_subproblem.isTransient())
109 "Tolerate failure has been set to true. Non-physical simulation results " 110 "are possible, you will be notified in the event of a failed remapping operation.");
113 mooseError(
"Can't start tracking after the initial condition when using a polycrystal_ic_uo");
121 std::size_t var_index)
const 129 const std::vector<unsigned int> &
164 "Grain index out of bounds");
182 mooseAssert(feature_index <
_feature_sets.size(),
"Grain index out of bounds");
198 mooseAssert(feature_index <
_feature_sets.size(),
"Grain index out of bounds");
199 return ((
_feature_sets[feature_index]._boundary_intersection &
215 mooseAssert(feature_index <
_feature_sets.size(),
"Grain index out of bounds");
216 bool primary = ((
_feature_sets[feature_index]._boundary_intersection &
219 bool secondary = ((
_feature_sets[feature_index]._boundary_intersection &
222 return (primary && secondary);
254 auto range = std::make_pair(std::numeric_limits<dof_id_type>::max(),
255 std::numeric_limits<dof_id_type>::min());
256 for (
const auto & current_elem :
_mesh.
getMesh().active_local_element_ptr_range())
258 auto id = current_elem->id();
259 if (
id < range.first)
261 else if (
id > range.second)
299 mooseAssert(
_first_time,
"This method should only be called on the first invocation");
311 for (
auto & feature : features)
320 for (
auto & feature : features)
335 TIME_SECTION(
"finalize", 3,
"Finalizing GrainTracker");
361 _console <<
"Finished inside of trackGrains" << std::endl;
376 _console <<
"Finished inside of updateFieldInfo" << std::endl;
383 _console <<
"Finished inside of GrainTracker\n" << std::endl;
389 TIME_SECTION(
"broadcastAndUpdateGrainData", 3,
"Broadcasting and Updating Grain Data");
391 std::vector<PartialFeatureData> root_feature_data;
392 std::vector<std::string> send_buffer(1), recv_buffer;
401 std::back_inserter(root_feature_data),
406 partial_feature.
id = feature._id;
407 partial_feature.
centroid = feature._centroid;
408 partial_feature.
status = feature._status;
409 return partial_feature;
412 std::ostringstream oss;
414 send_buffer[0].assign(oss.str());
422 std::back_inserter(recv_buffer));
427 std::istringstream iss;
428 iss.str(recv_buffer[0]);
431 dataLoad(iss, root_feature_data,
this);
433 for (
const auto & partial_data : root_feature_data)
440 grain._boundary_intersection = partial_data.boundary_intersection;
441 grain._centroid = partial_data.centroid;
452 mooseAssert(
_first_time,
"assignGrains may only be called on the first tracking step");
500 TIME_SECTION(
"trackGrains", 3,
"Tracking Grains");
502 mooseAssert(!
_first_time,
"Track grains may only be called when _tracking_step > _t_step");
514 std::vector<unsigned int> map_sizes(
_maps_size);
520 map_sizes[grain._var_index]++;
527 _console <<
"\nGrain Tracker Status:";
530 _console <<
"\nGrains active index " << map_num <<
": " << map_sizes[map_num] <<
" -> " 549 std::vector<std::size_t> new_grain_index_to_existing_grain_index(
_feature_sets.size(),
560 Real min_centroid_diff = std::numeric_limits<Real>::max();
570 [](
const FeatureData & item, std::size_t var_index)
577 bool any_boxes_intersect =
false;
579 new_grain_index = std::distance(
_feature_sets.begin(), start_it);
581 _feature_sets[new_grain_index]._var_index == old_grain._var_index;
590 if (new_grain.boundingBoxesIntersect(old_grain))
592 any_boxes_intersect =
true;
594 if (curr_centroid_diff <= min_centroid_diff)
596 closest_match_index = new_grain_index;
597 min_centroid_diff = curr_centroid_diff;
603 _console <<
"\nNo intersecting bounding boxes found while trying to match grain " 615 auto curr_index = new_grain_index_to_existing_grain_index[closest_match_index];
627 auto & inactive_grain = (centroid_diff1 < centroid_diff2) ? other_old_grain : old_grain;
632 _console << COLOR_GREEN <<
"Marking Grain " << inactive_grain._id
633 <<
" as INACTIVE (variable index: " << inactive_grain._var_index <<
")\n" 644 if (&inactive_grain == &other_old_grain)
645 new_grain_index_to_existing_grain_index[closest_match_index] = old_grain_index;
648 new_grain_index_to_existing_grain_index[closest_match_index] = old_grain_index;
653 for (
const auto new_index :
index_range(new_grain_index_to_existing_grain_index))
655 auto curr_index = new_grain_index_to_existing_grain_index[new_index];
662 "Invalid ID in old grain structure");
712 [](
const FeatureData & item, std::size_t var_index)
720 new_grain_index = std::distance(
_feature_sets.begin(), start_it);
722 _feature_sets[new_grain_index]._var_index == grain._var_index;
728 if (grain_num != new_grain_index &&
730 other_grain.boundingBoxesIntersect(grain) &&
731 other_grain.halosIntersect(grain))
734 grain._id = other_grain._id;
738 _console << COLOR_YELLOW <<
"Split Grain Detected #" << grain._id
739 <<
" (variable index: " << grain._var_index <<
")\n" 768 <<
"Trying harder to detect a split grain while examining grain on variable " 770 << grain._var_index <<
'\n' 773 std::vector<std::size_t> old_grain_indices;
786 if (grain._var_index == old_grain._var_index &&
787 grain.boundingBoxesIntersect(old_grain) && grain.halosIntersect(old_grain))
788 old_grain_indices.push_back(old_grain_index);
791 if (old_grain_indices.size() == 1)
797 _console << COLOR_YELLOW <<
"Split Grain Detected #" << grain._id
798 <<
" (variable index: " << grain._var_index <<
")\n" 801 else if (old_grain_indices.size() > 1)
803 << COLOR_RED <<
"Split Grain Likely Detected #" << grain._id
804 <<
" Need more information to find correct candidate - contact a developer!\n\n" 812 grain._id = new_index;
816 _console << COLOR_YELLOW <<
"Nucleating Grain Detected " 817 <<
" (variable index: " << grain._var_index <<
")\n" 833 _console << COLOR_GREEN <<
"Marking Grain " << grain._id
834 <<
" as INACTIVE (variable index: " << grain._var_index <<
")\n" 867 "Error: New grain detected and \"error_on_new_grain_creation\" is set to true");
883 "new_grain_id appears to be invalid");
887 <<
"\n*****************************************************************************" 888 <<
"\nCouldn't find a matching grain while working on variable index: " 889 << grain._var_index <<
"\nCreating new unique grain: " << new_grain_id <<
'\n' 891 <<
"\n*****************************************************************************\n" 896 std::vector<unsigned int>
903 std::iota(new_ids.begin(), new_ids.end(), new_id);
915 TIME_SECTION(
"remapGrains", 3,
"Remapping Grains");
918 _console <<
"Running remap Grains\n" << std::endl;
926 std::map<unsigned int, std::size_t> grain_id_to_new_var;
929 std::list<std::pair<std::size_t, std::size_t>> split_pairs;
942 std::map<unsigned int, std::size_t> grain_id_to_existing_var_index;
948 grain_id_to_existing_var_index[grain._id] = grain._var_index;
963 if (i <
j && grain1._id == grain2._id)
965 split_pairs.push_front(std::make_pair(i,
j));
966 if (grain1._var_index != grain2._var_index)
969 _console << COLOR_YELLOW <<
"Split Grain (#" << grain1._id
970 <<
") detected on unmatched OPs (" << grain1._var_index <<
", " 971 << grain2._var_index <<
") attempting to remap to " << grain1._var_index
979 grain1._var_index = grain2._var_index;
989 bool grains_remapped;
991 std::set<unsigned int> notify_ids;
994 grains_remapped =
false;
1003 _console << COLOR_YELLOW <<
"\nGrain #" << grain1._id
1004 <<
" detected on a reserved order parameter #" << grain1._var_index
1005 <<
", remapping to another variable\n" 1017 std::stringstream oss;
1018 oss <<
"Unable to find any suitable order parameters for remapping while working " 1019 <<
"with Grain #" << grain1._id <<
", which is on a reserve order parameter.\n" 1020 <<
"\n\nPossible Resolutions:\n" 1021 <<
"\t- Add more order parameters to your simulation (8 for 2D, 28 for 3D)\n" 1022 <<
"\t- Increase adaptivity or reduce your grain boundary widths\n" 1023 <<
"\t- Make sure you are not starting with too many grains for the mesh size\n";
1027 grains_remapped =
true;
1033 if (&grain1 == &grain2)
1036 if (grain1._var_index == grain2._var_index &&
1037 grain1._id != grain2._id &&
1038 grain1.boundingBoxesIntersect(grain2) &&
1039 grain1.halosIntersect(grain2))
1042 _console << COLOR_YELLOW <<
"Grain #" << grain1._id <<
" intersects Grain #" 1043 << grain2._id <<
" (variable index: " << grain1._var_index <<
")\n" 1052 grains_remapped =
true;
1059 notify_ids.insert(grain1._id);
1060 notify_ids.insert(grain2._id);
1066 }
while (grains_remapped);
1068 if (!notify_ids.empty())
1071 std::stringstream oss;
1072 oss <<
"Unable to find any suitable order parameters for remapping while working " 1073 <<
"with the following grain IDs:\n" 1074 <<
Moose::stringify(notify_ids,
", ",
"",
true) <<
"\n\nPossible Resolutions:\n" 1075 <<
"\t- Add more order parameters to your simulation (8 for 2D, 28 for 3D)\n" 1076 <<
"\t- Increase adaptivity or reduce your grain boundary widths\n" 1077 <<
"\t- Make sure you are not starting with too many grains for the mesh size\n";
1086 for (
auto & split_pair : split_pairs)
1088 mooseError(
"Split grain remapped - This case is currently not handled");
1097 mooseAssert(grain_id_to_existing_var_index.find(grain._id) !=
1098 grain_id_to_existing_var_index.end(),
1099 "Missing unique ID");
1101 auto old_var_index = grain_id_to_existing_var_index[grain._id];
1103 if (old_var_index != grain._var_index)
1105 mooseAssert(static_cast<bool>(grain._status &
Status::DIRTY),
"grain status is incorrect");
1107 grain_id_to_new_var.emplace_hint(
1108 grain_id_to_new_var.end(),
1109 std::pair<unsigned int, std::size_t>(grain._id, grain._var_index));
1119 grain._var_index = old_var_index;
1121 grain._status &= ~
Status::DIRTY;
1125 if (!grain_id_to_new_var.empty())
1129 _console <<
"Final remapping tally:\n";
1130 for (
const auto & remap_pair : grain_id_to_new_var)
1131 _console <<
"Grain #" << remap_pair.first <<
" var_index " 1132 << grain_id_to_existing_var_index[remap_pair.first] <<
" -> " 1133 << remap_pair.second <<
'\n';
1134 _console <<
"Communicating swaps with remaining processors..." << std::endl;
1143 if (!grain_id_to_new_var.empty())
1146 std::vector<std::map<Node *, CacheValues>> cache(
_n_vars);
1152 auto new_var_it = grain_id_to_new_var.find(grain._id);
1153 if (new_var_it != grain_id_to_new_var.end())
1160 auto new_var_it = grain_id_to_new_var.find(grain._id);
1161 if (new_var_it != grain_id_to_new_var.end())
1172 _console <<
"Swaps complete" << std::endl;
1178 std::vector<std::list<GrainDistance>> & min_distances)
1210 auto target_var_index = other_grain._var_index;
1211 auto target_grain_index = i;
1212 auto target_grain_id = other_grain._id;
1217 curr_bbox_diff, target_var_index, target_grain_index, target_grain_id);
1220 if (curr_bbox_diff == -1.0 && !min_distances[target_var_index].empty())
1222 Real last_distance = min_distances[target_var_index].begin()->_distance;
1223 if (last_distance < 0)
1224 grain_distance_obj.
_distance += last_distance;
1228 auto insert_it = min_distances[target_var_index].begin();
1229 while (insert_it != min_distances[target_var_index].end() && !(grain_distance_obj < *insert_it))
1231 min_distances[target_var_index].insert(insert_it, grain_distance_obj);
1245 if (min_distances[var_index].empty())
1246 min_distances[var_index].emplace_front(std::numeric_limits<Real>::max(), var_index);
1254 if (depth > max_depth)
1257 std::size_t curr_var_index = grain.
_var_index;
1259 std::vector<std::map<Node *, CacheValues>> cache;
1261 std::vector<std::list<GrainDistance>> min_distances(
_vars.size());
1281 std::sort(min_distances.begin(), min_distances.end(),
1282 [](
const std::list<GrainDistance> & lhs,
const std::list<GrainDistance> & rhs)
1288 else if (rhs.empty())
1291 return lhs.begin()->_distance > rhs.begin()->_distance;
1295 for (
auto & list_ref : min_distances)
1297 const auto target_it = list_ref.begin();
1298 if (target_it == list_ref.end())
1302 if (target_it->_distance > 0)
1306 _console << COLOR_GREEN <<
"- Depth " << depth <<
": Remapping grain #" << grain.
_id 1307 <<
" from variable index " << curr_var_index <<
" to " << target_it->_var_index;
1308 if (target_it->_distance == std::numeric_limits<Real>::max())
1309 _console <<
" which currently contains zero grains.\n\n" << COLOR_DEFAULT;
1311 _console <<
" whose closest grain (#" << target_it->_grain_id <<
") is at a distance of " 1312 << std::sqrt(target_it->_distance) <<
"\n\n" 1324 auto next_target_it = target_it;
1325 bool intersection_hit =
false;
1326 unsigned short num_close_targets = 0;
1327 std::ostringstream oss;
1328 while (!intersection_hit && next_target_it != list_ref.end())
1330 if (next_target_it->_distance > 0)
1333 mooseAssert(next_target_it->_grain_index <
_feature_sets.size(),
1334 "Error in indexing target grain in attemptGrainRenumber");
1339 intersection_hit =
true;
1342 if (num_close_targets > 0)
1344 oss <<
"#" << next_target_it->_grain_id;
1348 ++num_close_targets;
1351 if (!intersection_hit)
1355 _console << COLOR_GREEN <<
"- Depth " << depth <<
": Remapping grain #" << grain.
_id 1356 <<
" from variable index " << curr_var_index <<
" to " << target_it->_var_index;
1358 if (num_close_targets == 1)
1359 _console <<
" whose closest grain (" << oss.str()
1360 <<
") is inside our bounding box but whose halo is not touching.\n\n" 1363 _console <<
" whose closest grains (" << oss.str()
1364 <<
") are inside our bounding box but whose halos are not touching.\n\n" 1376 "Error in indexing target grain in attemptGrainRenumber");
1386 if (target_it->_distance < -1)
1404 _console << COLOR_GREEN <<
"- Depth " << depth <<
": Remapping grain #" << grain.
_id 1405 <<
" from variable index " << curr_var_index <<
" to " << target_it->_var_index
1427 std::size_t new_var_index,
1428 std::vector<std::map<Node *, CacheValues>> & cache,
1434 std::set<Node *> updated_nodes_tmp;
1439 Elem * elem =
mesh.query_elem_ptr(entity);
1443 for (
unsigned int i = 0; i < elem->n_nodes(); ++i)
1445 Node * curr_node = elem->node_ptr(i);
1446 if (updated_nodes_tmp.find(curr_node) == updated_nodes_tmp.end())
1449 updated_nodes_tmp.insert(curr_node);
1456 mesh.query_node_ptr(entity), grain.
_var_index, new_var_index, cache, cache_mode);
1466 std::size_t curr_var_index,
1467 std::size_t new_var_index,
1468 std::vector<std::map<Node *, CacheValues>> & cache,
1471 if (curr_node && curr_node->processor_id() ==
processor_id())
1477 Real current, old = 0, older = 0;
1481 current =
_vars[curr_var_index]->dofValues()[0];
1484 old =
_vars[curr_var_index]->dofValuesOld()[0];
1485 older =
_vars[curr_var_index]->dofValuesOlder()[0];
1490 const auto cache_it = cache[curr_var_index].find(curr_node);
1491 mooseAssert(cache_it != cache[curr_var_index].end(),
"Error in cache");
1492 current = cache_it->second.current;
1493 old = cache_it->second.old;
1494 older = cache_it->second.older;
1500 cache[curr_var_index][curr_node].current = current;
1501 cache[curr_var_index][curr_node].old = old;
1502 cache[curr_var_index][curr_node].older = older;
1506 const auto & dof_index =
_vars[new_var_index]->nodalDofIndex();
1531 const auto & dof_index =
_vars[curr_var_index]->nodalDofIndex();
1547 TIME_SECTION(
"updateFieldInfo", 3,
"Updating Field Info");
1552 std::map<dof_id_type, Real> tmp_map;
1556 std::size_t curr_var = grain._var_index;
1559 for (
auto entity : grain._local_ids)
1562 Real entity_value = std::numeric_limits<Real>::lowest();
1566 std::vector<Point> centroid(1, elem->vertex_average());
1574 entity_value =
_vars[curr_var]->sln()[0];
1580 entity_value =
_vars[curr_var]->getNodalValue(*node_ptr);
1583 if (entity_value != std::numeric_limits<Real>::lowest() &&
1584 (tmp_map.find(entity) == tmp_map.end() || entity_value > tmp_map[entity]))
1586 mooseAssert(grain._id !=
invalid_id,
"Missing Grain ID");
1592 tmp_map[entity] = entity_value;
1599 auto & vec_ref = insert_pair.first->second;
1601 if (insert_pair.second)
1607 vec_ref[grain._var_index] = grain._id;
1612 for (
auto entity : grain._halo_ids)
1613 _halo_ids[grain._var_index][entity] = grain._var_index;
1615 for (
auto entity : grain._ghosted_ids)
1628 std::vector<std::pair<std::size_t, dof_id_type>> halo_ids_all;
1630 std::vector<int> counts;
1631 std::vector<std::pair<std::size_t, dof_id_type>> local_halo_ids;
1632 std::size_t counter = 0;
1638 std::vector<std::vector<std::pair<std::size_t, dof_id_type>>> root_halo_ids(
_n_procs);
1644 for (
const auto & entity_pair :
_halo_ids[var_index])
1646 auto entity_id = entity_pair.first;
1647 if (isDistributedMesh)
1654 [](
const std::pair<dof_id_type, dof_id_type> range,
1655 dof_id_type entity_id) {
return range.second < entity_id; });
1657 mooseAssert(range_it !=
_all_ranges.end(),
"No range round?");
1660 auto proc_id = std::distance(
_all_ranges.begin(), range_it);
1663 root_halo_ids[proc_id].push_back(std::make_pair(var_index, entity_id));
1667 DofObject * halo_entity;
1674 root_halo_ids[halo_entity->processor_id()].push_back(
1675 std::make_pair(var_index, entity_id));
1681 for (
const auto & vector_ref : root_halo_ids)
1683 std::copy(vector_ref.begin(), vector_ref.end(), std::back_inserter(halo_ids_all));
1684 counts[counter] = vector_ref.size();
1692 for (
const auto & halo_pair : local_halo_ids)
1693 _halo_ids[halo_pair.first].emplace(std::make_pair(halo_pair.second, halo_pair.first));
1702 for (
auto local_id : grain._local_ids)
1703 _halo_ids[grain._var_index].erase(local_id);
1709 std::vector<BoundingBox> & bboxes2)
const 1714 auto min_distance = std::numeric_limits<Real>::max();
1715 for (
const auto & bbox1 : bboxes1)
1717 const auto centroid_point1 = (bbox1.max() + bbox1.min()) / 2.0;
1719 for (
const auto & bbox2 : bboxes2)
1721 const auto centroid_point2 = (bbox2.max() + bbox2.min()) / 2.0;
1726 if (curr_distance < min_distance)
1727 min_distance = curr_distance;
1731 return min_distance;
1736 std::vector<BoundingBox> & bboxes2)
const 1744 auto min_distance = std::numeric_limits<Real>::max();
1745 for (
const auto & bbox1 : bboxes1)
1747 for (
const auto & bbox2 : bboxes2)
1750 Real curr_distance = 0.0;
1751 bool boxes_overlap =
true;
1752 for (
unsigned int dim = 0;
dim < LIBMESH_DIM; ++
dim)
1754 const auto & min1 = bbox1.min()(
dim);
1755 const auto & max1 = bbox1.max()(
dim);
1756 const auto & min2 = bbox2.min()(
dim);
1757 const auto & max2 = bbox2.max()(
dim);
1761 const auto delta = max2 - min1;
1763 boxes_overlap =
false;
1765 else if (min2 > max1)
1767 const auto delta = max1 - min2;
1769 boxes_overlap =
false;
1776 if (curr_distance < min_distance)
1777 min_distance = curr_distance;
1781 return min_distance;
1806 std::numeric_limits<
std::size_t>::
max(),
1807 std::numeric_limits<unsigned
int>::
max())
1812 std::size_t var_index,
1813 std::size_t grain_index,
1814 unsigned int grain_id)
1815 : _distance(
distance), _var_index(var_index), _grain_index(grain_index), _grain_id(grain_id)
void remapGrains()
This method is called after trackGrains to remap grains that are too close to each other...
bool halosIntersect(const FeatureData &rhs) const
Determine if one of this FeaturesData's member sets intersects the other FeatureData's corresponding ...
virtual bool doesFeatureIntersectBoundary(unsigned int feature_id) const override
Returns a Boolean indicating whether this feature intersects any boundary.
std::vector< BoundingBox > _bboxes
The vector of bounding boxes completely enclosing this feature (multiple used with periodic constrain...
void expandEdgeHalos(unsigned int num_layers_to_expand)
This method expands the existing halo set by some width determined by the passed in value...
void broadcast_packed_range(const Context *context1, Iter range_begin, const Iter range_end, OutputContext *context2, OutputIter out, const unsigned int root_id=0, std::size_t approx_buffer_size=1000000) const
virtual std::vector< unsigned int > getNewGrainIDs() const override
This method returns all of the new ids generated in an invocation of the GrainTracker.
This class defines the interface for the GrainTracking objects.
void scatter(const std::vector< T, A > &data, T &recv, const unsigned int root_id=0) const
const std::size_t _n_vars
static const std::size_t invalid_size_t
static InputParameters validParams()
virtual Elem * elemPtr(const dof_id_type i)
NumericVector< Number > & solution()
virtual const std::vector< unsigned int > & getVarToFeatureVector(dof_id_type elem_id) const
Returns a list of active unique feature ids for a particular element.
virtual void execute() override
virtual bool isFeaturePercolated(unsigned int feature_id) const override
Returns a Boolean indicating whether this feature is percolated (e.g.
virtual void meshChanged() override
const bool _condense_map_info
void gather(const unsigned int root_id, const T &send_data, std::vector< T, A > &recv) const
Status
This enumeration is used to indicate status of the grains in the _unique_grains data structure...
virtual Real getVariableValue(unsigned int op_index, const Point &p) const =0
Returns the variable value for a given op_index and mesh point.
bool & _first_time
Boolean to indicate the first time this object executes.
static InputParameters validParams()
virtual libMesh::System & system()=0
std::vector< FeatureData > & _feature_sets
The data structure used to hold the globally unique features.
std::vector< FeatureData > _feature_sets_old
This data structure holds the map of unique grains from the previous time step.
int delta(unsigned int i, unsigned int j)
Delta function, which returns zero if $i j$ and unity if $i=j$.
virtual const Node * queryNodePtr(const dof_id_type i) const
const bool _error_on_grain_creation
Boolean to terminate with an error if a new grain is created during the simulation.
const bool _is_primary
Convenience variable for testing primary rank.
void trackGrains()
On subsequent time_steps, incoming FeatureData objects are compared to previous time_step information...
This object provides the base capability for creating proper polycrystal ICs.
std::map< dof_id_type, std::vector< unsigned int > > _entity_var_to_features
void communicateAndMerge()
This routine handles all of the serialization, communication and deserialization of the data structur...
virtual void initialize() override
NumericVector< Number > & solutionOlder()
const Parallel::Communicator & _communicator
unsigned int _old_max_grain_id
The previous max grain id (needed to figure out which ids are new in a given step) ...
void swapSolutionValuesHelper(Node *curr_node, std::size_t curr_var_index, std::size_t new_var_index, std::vector< std::map< Node *, CacheValues >> &cache, RemapCacheMode cache_mode)
Helper method for actually performing the swaps.
virtual void finalize() override
unsigned int & _max_curr_grain_id
Holds the next "regular" grain ID (a grain found or remapped to the standard op vars) ...
std::pair< typename M::iterator, bool > moose_try_emplace(M &m, const typename M::key_type &k, Args &&... args)
const std::vector< FeatureData > & getFeatures() const
Return a constant reference to the vector of all discovered features.
registerMooseObject("PhaseFieldApp", GrainTracker)
virtual std::size_t getTotalFeatureCount() const override
Returns the total feature count (active and inactive ids, useful for sizing vectors) ...
Real distance(const Point &p)
const PolycrystalUserObjectBase *const _poly_ic_uo
An optional IC UserObject which can provide initial data structures to this object.
Real centroidRegionDistance(std::vector< BoundingBox > &bboxes1, std::vector< BoundingBox > &bboxes2) const
This method returns the minimum periodic distance between the centroids of two vectors of bounding bo...
void mooseWarning(Args &&... args) const
std::map< dof_id_type, int > _ghosted_entity_ids
The map for holding reconstructed ghosted element information.
This struct is used to hold distance information to other grains in the simulation.
auto max(const L &left, const R &right)
virtual Elem * queryElemPtr(const dof_id_type i)
void storeHelper(std::ostream &stream, P &data, void *context)
Real boundingRegionDistance(std::vector< BoundingBox > &bboxes1, std::vector< BoundingBox > &bboxes2) const
This method returns the minimum periodic distance between two vectors of bounding boxes...
void dataLoad(std::istream &stream, GrainTracker::PartialFeatureData &feature, void *context)
void sortAndLabel()
Sort and assign ids to features based on their position in the container after sorting.
virtual void updateFieldInfo() override
This method is used to populate any of the data structures used for storing field data (nodal or elem...
const Real _bound_value
Absolute value of the lower bound used to represent a region not assigned to this grain...
virtual const std::vector< unsigned int > & getVarToFeatureVector(dof_id_type elem_id) const override
Returns a list of active unique feature ids for a particular element.
void communicateHaloMap()
virtual unsigned int getFeatureVar(unsigned int feature_id) const
Returns the variable representing the passed in feature.
GrainTracker(const InputParameters ¶meters)
std::vector< std::map< dof_id_type, int > > _halo_ids
The data structure for looking up halos around features.
virtual void reinitNode(const Node *node, const THREAD_ID tid)=0
BoundaryIntersection boundary_intersection
std::vector< MooseVariable * > _vars
The vector of coupled in variables cast to MooseVariable.
virtual void execute() override
std::size_t _var_index
The Moose variable where this feature was found (often the "order parameter")
void prepopulateState(const FeatureFloodCount &ffc_object)
This method extracts the necessary state from the passed in object necessary to continue tracking gra...
void broadcastAndUpdateGrainData()
Broadcast essential Grain information to all processors.
GrainDistance(Real distance, std::size_t var_index)
virtual const Node * nodePtr(const dof_id_type i) const
unsigned long _var_number
This variable is used to build the periodic node map.
This object will mark nodes or elements of continuous regions all with a unique number for the purpos...
const Real _reserve_op_threshold
The threshold above (or below) where a grain may be found on a reserve op field.
const std::size_t _maps_size
Convenience variable holding the size of all the datastructures size by the number of maps...
virtual void initialize() override
void computeMinDistancesFromGrain(FeatureData &grain, std::vector< std::list< GrainDistance >> &min_distances)
Populates and sorts a min_distances vector with the minimum distances to all grains in the simulation...
void swapSolutionValues(FeatureData &grain, std::size_t new_var_index, std::vector< std::map< Node *, CacheValues >> &cache, RemapCacheMode cache_mode)
A routine for moving all of the solution values from a given grain to a new variable number...
const short _verbosity_level
Verbosity level controlling the amount of information printed to the console.
static const unsigned int invalid_id
std::string stringify(const T &t)
Real minPeriodicDistance(unsigned int nonlinear_var_num, Point p, Point q) const
std::vector< std::map< dof_id_type, int > > _feature_maps
The feature maps contain the raw flooded node information and eventually the unique grain numbers...
const bool _single_map_mode
This variable is used to indicate whether or not multiple maps are used during flooding.
unsigned int _feature_count
The number of features seen by this object (same as summing _feature_counts_per_map) ...
virtual std::size_t getNumberActiveGrains() const override
Returns the number of active grains current stored in the GrainTracker.
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data, during the discovery and mergi...
const bool _compute_halo_maps
Indicates whether or not to communicate halo map information with all ranks.
std::vector< std::pair< dof_id_type, dof_id_type > > _all_ranges
Data structure to hold element ID ranges when using Distributed Mesh (populated on rank 0 only) ...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const bool _remap
Inidicates whether remapping should be done or not (remapping is independent of tracking) ...
const bool _is_elemental
Determines if the flood counter is elements or not (nodes)
container_type _local_ids
Holds the local ids in the interior of a feature.
FEProblemBase & _fe_problem
bool attemptGrainRenumber(FeatureData &grain, unsigned int depth, unsigned int max_depth)
This is the recursive part of the remapping algorithm.
const processor_id_type _n_procs
Convenience variable holding the number of processors in this simulation.
IntRange< T > make_range(T beg, T end)
static InputParameters validParams()
const bool _is_transient
Boolean to indicate whether this is a Steady or Transient solve.
virtual bool doesFeatureIntersectSpecifiedBoundary(unsigned int feature_id) const override
Returns a Boolean indicating whether this feature intersects boundaries in a user-supplied list...
virtual void meshChanged() override
std::vector< unsigned int > _feature_counts_per_map
The number of features seen by this object per map.
void mooseError(Args &&... args) const
std::vector< std::size_t > _feature_id_to_local_index
The vector recording the grain_id to local index (several indices will contain invalid_size_t) ...
void dataStore(std::ostream &stream, GrainTracker::PartialFeatureData &feature, void *context)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
void assignGrains()
When the tracking phase starts (_t_step == _tracking_step) it assigns a unique id to every FeatureDat...
virtual void set(const numeric_index_type i, const Number value)=0
Status _status
The status of a feature (used mostly in derived classes like the GrainTracker)
const ConsoleStream _console
bool operator<(const GrainDistance &rhs) const
const int _tracking_step
The timestep to begin tracking grains.
unsigned int _reserve_grain_first_index
Holds the first unique grain index when using _reserve_op (all the remaining indices are sequential) ...
virtual Real getEntityValue(dof_id_type node_id, FieldType field_type, std::size_t var_index=0) const override
const unsigned short _halo_level
The thickness of the halo surrounding each grain.
const std::size_t _reserve_op_index
The cutoff index where if variable index >= this number, no remapping TO that variable will occur...
NumericVector< Number > & solutionOld()
const unsigned short _max_remap_recursion_depth
Depth of renumbering recursion (a depth of zero means no recursion)
MooseMesh & _mesh
A reference to the mesh.
processor_id_type processor_id() const
virtual bool isDistributedMesh() const
virtual Point getGrainCentroid(unsigned int grain_id) const override
Returns the centroid for the given grain number.
virtual Real getEntityValue(dof_id_type entity_id, FieldType field_type, std::size_t var_index=0) const
void buildFeatureIdToLocalIndices(unsigned int max_id)
This method builds a lookup map for retrieving the right local feature (by index) given a global inde...
void scatterAndUpdateRanks()
Calls buildLocalToGlobalIndices to build the individual local to global indicies for each rank and sc...
virtual void reinitElemPhys(const Elem *elem, const std::vector< Point > &phys_points_in_elem, const THREAD_ID tid) override
virtual unsigned int getFeatureVar(unsigned int feature_id) const override
Returns the variable representing the passed in feature.
void paramInfo(const std::string ¶m, Args... args) const
void loadHelper(std::istream &stream, P &data, void *context)
virtual void newGrainCreated(unsigned int new_grain_id)
This method is called when a new grain is detected.
const bool _compute_var_to_feature_map
Indicates whether or not the var to feature map is populated.
void ErrorVector unsigned int
auto index_range(const T &sizable)
virtual Real getThreshold(std::size_t current_index) const override
Return the starting comparison threshold to use when inspecting an entity during the flood stage...
const bool _tolerate_failure
Indicates whether we should continue after a remap failure (will result in non-physical results) ...
const bool _var_index_mode
This variable is used to indicate whether the maps will contain unique region information or just the...
unsigned int getNextUniqueID()
Retrieve the next unique grain number if a new grain is detected during trackGrains.
unsigned int _id
An ID for this feature.
std::vector< std::map< dof_id_type, int > > _var_index_maps
This map keeps track of which variables own which nodes.
const unsigned short _n_reserve_ops
The number of reserved order parameters.