21#include "libmesh/dof_map.h"
22#include "libmesh/mesh_tools.h"
23#include "libmesh/periodic_boundaries.h"
24#include "libmesh/point_locator_base.h"
25#include "libmesh/remote_elem.h"
55dataStore(std::ostream & stream, BoundingBox & bbox,
void * context)
86dataLoad(std::istream & stream, BoundingBox & bbox,
void * context)
106 "The variable(s) for which to find connected regions of interests, i.e. \"features\".");
108 "threshold", 0.5,
"The threshold value for which a new feature may be started");
110 "connecting_threshold",
111 "The threshold for which an existing feature may be extended (defaults to \"threshold\")");
112 params.
addParam<
bool>(
"use_single_map",
114 "Determine whether information is tracked per "
115 "coupled variable or consolidated into one "
120 "Determines whether we condense all the node values when in multimap mode (default: false)");
121 params.
addParam<
bool>(
"use_global_numbering",
123 "Determine whether or not global numbers are "
124 "used to label features on multiple maps "
126 params.
addParam<
bool>(
"enable_var_coloring",
128 "Instruct the Postprocessor to populate the variable index map.");
132 "Instruct the Postprocessor to communicate proper halo information to all ranks");
133 params.
addParam<
bool>(
"compute_var_to_feature_map",
135 "Instruct the Postprocessor to compute the active vars to features map");
137 "use_less_than_threshold_comparison",
139 "Controls whether features are defined to be less than or greater than the threshold value.");
141 params.
addParam<std::vector<BoundaryName>>(
142 "primary_percolation_boundaries",
143 "A list of boundaries used in conjunction with the corresponding "
144 "\"secondary_percolation_boundaries\" parameter for determining if a feature creates a path "
145 "connecting any pair of boundaries");
146 params.
addParam<std::vector<BoundaryName>>(
147 "secondary_percolation_boundaries",
148 "Paired boundaries with \"primaryary_percolation_boundaries\" parameter");
149 params.
addParam<std::vector<BoundaryName>>(
150 "specified_boundaries",
151 "An optional list of boundaries; if supplied, each feature is checked to determine whether "
152 "it intersects any of the specified boundaries in this list.");
161 params.
set<
bool>(
"use_displaced_mesh") =
false;
170 "use_single_map condense_map_info use_global_numbering primary_percolation_boundaries",
173 MooseEnum flood_type(
"NODAL ELEMENTAL",
"ELEMENTAL");
176 "Determines whether the flood algorithm runs on nodes or elements");
178 params.
addClassDescription(
"The object is able to find and count \"connected components\" in any "
179 "solution field or number of solution fields. A primary example would "
180 "be to count \"bubbles\".");
183 Moose::RelationshipManagerType::GEOMETRIC |
184 Moose::RelationshipManagerType::ALGEBRAIC);
194 _fe_vars(getCoupledMooseVars()),
195 _vars(getCoupledStandardMooseVars()),
196 _dof_map(_vars[0]->dofMap()),
197 _threshold(getParam<Real>(
"threshold")),
198 _connecting_threshold(isParamValid(
"connecting_threshold")
199 ? getParam<Real>(
"connecting_threshold")
200 : getParam<Real>(
"threshold")),
201 _mesh(_subproblem.
mesh()),
202 _var_number(_fe_vars[0]->number()),
203 _single_map_mode(getParam<bool>(
"use_single_map")),
204 _condense_map_info(getParam<bool>(
"condense_map_info")),
205 _global_numbering(getParam<bool>(
"use_global_numbering")),
206 _var_index_mode(getParam<bool>(
"enable_var_coloring")),
207 _compute_halo_maps(getParam<bool>(
"compute_halo_maps")),
208 _compute_var_to_feature_map(getParam<bool>(
"compute_var_to_feature_map")),
209 _use_less_than_threshold_comparison(getParam<bool>(
"use_less_than_threshold_comparison")),
210 _n_vars(_fe_vars.size()),
211 _maps_size(_single_map_mode ? 1 : _fe_vars.size()),
212 _n_procs(_app.n_processors()),
213 _feature_counts_per_map(_maps_size),
215 _partial_feature_sets(_maps_size),
216 _feature_sets(getParam<bool>(
"restartable_required")
217 ? declareRestartableData<
std::vector<
FeatureData>>(
"feature_sets")
218 : _volatile_feature_sets),
219 _feature_maps(_maps_size),
221 _element_average_value(parameters.isParamValid(
"elem_avg_value")
222 ? getPostprocessorValue(
"elem_avg_value")
224 _halo_ids(_maps_size),
225 _is_elemental(getParam<
MooseEnum>(
"flood_entity_type") ==
"ELEMENTAL"),
226 _is_primary(processor_id() == 0)
238 for (
auto & var :
_vars)
241 var->dofValuesOlder();
247 parameters.
get<std::vector<BoundaryName>>(
"primary_percolation_boundaries"));
250 parameters.
get<std::vector<BoundaryName>>(
"secondary_percolation_boundaries"));
254 "primary_percolation_boundaries and secondary_percolation_boundaries must both be "
255 "supplied when checking for percolation");
287 for (
const auto map_num : make_range(
_maps_size))
346 TIME_SECTION(
"execute", 3,
"Flooding Features");
351 mooseInfo(
"Using EXPERIMENTAL boundary restricted FeatureFloodCount object!\n");
360 const Elem * elem = belem->_elem;
363 if (elem->processor_id() == rank)
366 for (
const auto var_num : index_range(
_vars))
367 flood(elem, var_num);
373 for (
const auto & current_elem :
_mesh.
getMesh().active_local_element_ptr_range())
378 for (
const auto var_num : index_range(
_vars))
379 flood(current_elem, var_num);
383 auto n_nodes = current_elem->n_vertices();
384 for (
const auto i : make_range(
n_nodes))
386 const Node * current_node = current_elem->node_ptr(i);
388 for (
const auto var_num : index_range(
_vars))
389 flood(current_node, var_num);
405 TIME_SECTION(
"communicateAndMerge", 3,
"Communicating and Merging");
417 std::vector<std::string> send_buffers(1);
425 std::vector<std::string> recv_buffers, deserialize_buffers;
435 if (n_merging_procs > 1)
438 bool is_merging_processor = rank < n_merging_procs;
440 if (is_merging_processor)
443 for (
const auto i : make_range(n_merging_procs))
453 send_buffers.begin(),
455 std::back_inserter(recv_buffers));
464 recv_buffers.swap(deserialize_buffers);
466 recv_buffers.clear();
470 Parallel::Communicator merge_comm;
474 if (is_merging_processor)
488 send_buffers[0].clear();
489 recv_buffers.clear();
490 deserialize_buffers.clear();
505 merge_comm.gather_packed_range(0,
507 send_buffers.begin(),
509 std::back_inserter(recv_buffers));
516 send_buffers[0].clear();
517 recv_buffers.clear();
544 send_buffers.begin(),
546 std::back_inserter(recv_buffers));
552 recv_buffers.clear();
570 mooseAssert(
_is_primary,
"sortAndLabel can only be called on the primary");
585 unsigned int feature_offset = 0;
586 for (
const auto map_num : make_range(
_maps_size))
593 auto range_front = feature_offset;
596 mooseAssert(range_front <= range_back && range_back <
_feature_count,
597 "Indexing error in feature sets");
601 mooseError(
"Error in _feature_sets sorting, map index: ", map_num);
615 std::vector<int> & counts)
const
617 mooseAssert(
_is_primary,
"This method must only be called on the root processor");
622 for (
const auto & local_index_pair : feature._orig_ids)
625 mooseAssert(local_index_pair.first <
_n_procs,
"Processor ID is out of range");
626 if (local_index_pair.second >=
static_cast<std::size_t
>(counts[local_index_pair.first]))
627 counts[local_index_pair.first] = local_index_pair.second + 1;
631 unsigned int globalsize = 0;
633 for (
const auto i : index_range(offsets))
635 offsets[i] = globalsize;
636 globalsize += counts[i];
644 for (
const auto & local_index_pair : feature._orig_ids)
646 auto rank = local_index_pair.first;
649 auto local_index = local_index_pair.second;
650 auto stacked_local_index = offsets[rank] + local_index;
652 mooseAssert(stacked_local_index < globalsize,
653 "Global index: " << stacked_local_index <<
" is out of range");
654 local_to_global_all[stacked_local_index] = feature._id;
668 "Feature ID out of range(" <<
_feature_sets[feature_index]._id <<
')');
677 TIME_SECTION(
"finalize", 3,
"Finalizing Feature Identification");
693const std::vector<unsigned int> &
697 "Please set \"compute_var_to_feature_map = true\" to use this interface method"));
702 mooseAssert(pos->second.size() ==
_n_vars,
"Variable to feature vector not sized properly");
713 std::vector<int> counts;
714 std::vector<std::size_t> local_to_global_all;
721 std::size_t largest_global_index = std::numeric_limits<std::size_t>::lowest();
734 for (
auto & feature : list_ref)
736 mooseAssert(feature._orig_ids.size() == 1,
"feature._orig_ids length doesn't make sense");
739 auto local_index = feature._orig_ids.begin()->second;
746 if (global_index > largest_global_index)
747 largest_global_index = global_index;
750 feature._id = global_index;
769 for (
auto global_index : local_to_global_all)
771 largest_global_index = global_index;
775 std::vector<std::pair<unsigned int, int>> intersection_state;
777 intersection_state.emplace_back(feature._id,
static_cast<int>(feature._boundary_intersection));
783 std::map<unsigned int, int> consolidated_intersection_state;
785 for (
const auto & [
id, state] : intersection_state)
786 consolidated_intersection_state[
id] |= state;
793 feature._boundary_intersection |=
833 mooseAssert(local_index <
_feature_sets.size(),
"local_index out of bounds");
853 mooseAssert(local_index <
_feature_sets.size(),
"local_index out of bounds");
873 mooseAssert(local_index <
_feature_sets.size(),
"local_index out of bounds");
895 mooseAssert(local_index <
_feature_sets.size(),
"local_index out of bounds");
896 bool primary = ((
_feature_sets[local_index]._boundary_intersection &
899 bool secondary = ((
_feature_sets[local_index]._boundary_intersection &
916 Real invalid_coord = std::numeric_limits<Real>::max();
917 Point
p(invalid_coord, invalid_coord, invalid_coord);
920 mooseAssert(local_index <
_feature_sets.size(),
"local_index out of bounds");
929 std::size_t var_index)
const
931 auto use_default =
false;
938 mooseAssert(var_index <
_maps_size,
"Index out of range");
944 const auto entity_it =
_feature_maps[var_index].find(entity_id);
947 return entity_it->second;
956 "\"enable_var_coloring\" must be set to true to pull back the VARIABLE_COLORING field");
961 return entity_it->second;
971 return entity_it->second;
980 const auto entity_it =
_halo_ids[var_index].find(entity_id);
981 if (entity_it !=
_halo_ids[var_index].end())
982 return entity_it->second;
990 const auto entity_it =
_halo_ids[map_num].find(entity_id);
992 if (entity_it !=
_halo_ids[map_num].end())
993 return entity_it->second;
1003 "Centroids are not correct when using periodic boundaries, contact the MOOSE team"));
1013 if (elem_ptr->contains_point(feature._centroid))
1023 if (ids.size() != 0)
1036 TIME_SECTION(
"prepareDataForTransfer", 3,
"Preparing Data For Transfer");
1044 for (
auto & feature : list_ref)
1065 feature.updateBBoxExtremes(
mesh);
1068 for (
auto & halo_id : feature._halo_ids)
1072 mooseAssert(!feature._local_ids.empty(),
"local entity ids cannot be empty");
1078 feature._min_entity_id = *feature._local_ids.begin();
1087 std::ostringstream oss;
1090 "var_num out of range");
1099 serialized_buffer.assign(oss.str());
1106 std::istringstream iss;
1110 for (
const auto proc_id : index_range(serialized_buffers))
1123 if (var_num ==
invalid_id && proc_id == rank)
1126 iss.str(serialized_buffers[proc_id]);
1140 TIME_SECTION(
"mergeSets", 3,
"Merging Sets");
1143 for (
const auto map_num : make_range(
_maps_size))
1149 bool merge_occured =
false;
1156 it2->merge(std::move(*it1));
1178 merge_occured =
true;
1195 TIME_SECTION(
"consolidateMergedFeatures", 3,
"Consolidating Merged Features");
1206 "cosolidateMergedFeatures() may only be called on the primary processor");
1208 "Data structure size mismatch");
1211 unsigned int feature_offset = 0;
1220 for (
auto it = (*saved_data)[map_num].begin(); it != (*saved_data)[map_num].end();
1223 if (feature.canConsolidate(*it))
1225 feature.consolidate(std::move(*it));
1226 it = (*saved_data)[map_num].erase(it);
1238 if (feature._vol_count != 0)
1239 feature._centroid /= feature._vol_count;
1255 (*saved_data)[map_num].clear();
1291 : feature._var_index;
1294 for (
auto entity : feature._local_ids)
1296 _feature_maps[map_index][entity] =
static_cast<int>(feature._id);
1306 auto & vec_ref = insert_pair.first->second;
1307 vec_ref[feature._var_index] = feature._id;
1313 for (
auto entity : feature._halo_ids)
1314 _halo_ids[map_index][entity] =
static_cast<int>(feature._id);
1317 for (
auto entity : feature._ghosted_ids)
1322 mooseError(
"Local numbering currently disabled");
1332 mooseAssert(dof_object,
"DOF object is nullptr");
1333 mooseAssert(
_entity_queue.empty(),
"Entity queue is not empty when starting a feature");
1338 bool return_value =
false;
1343 const Elem * elem =
_is_elemental ?
static_cast<const Elem *
>(curr_dof_object) :
nullptr;
1347 auto entity_id = curr_dof_object->id();
1376 mooseAssert(current_index !=
invalid_size_t,
"current_index is invalid");
1386 return_value =
true;
1389 auto map_num =
_single_map_mode ?
decltype(current_index)(0) : current_index;
1402 feature->
_id = new_id;
1419 feature->
_centroid += elem->vertex_average();
1437 return return_value;
1461 std::size_t & current_index,
1470 const Elem * elem =
static_cast<const Elem *
>(dof_object);
1471 std::vector<Point> centroid(1, elem->vertex_average());
1473 entity_value =
_vars[current_index]->sln()[0];
1476 entity_value =
_vars[current_index]->getNodalValue(*
static_cast<const Node *
>(dof_object));
1482 Status * status_ptr = &status;
1485 status_ptr = &feature->
_status;
1514 for (
auto & feature : list_ref)
1516 expanded_local_ids.clear();
1518 for (
auto entity : feature._local_ids)
1521 mooseAssert(elem,
"elem pointer is NULL");
1524 auto n_nodes = elem->n_vertices();
1525 for (
const auto i : make_range(
n_nodes))
1527 const Node * current_node = elem->node_ptr(i);
1529 auto elem_vector_it = node_to_elem_map.find(current_node->id());
1530 if (elem_vector_it == node_to_elem_map.end())
1533 const auto & elem_vector = elem_vector_it->second;
1535 std::copy(elem_vector.begin(),
1537 std::insert_iterator<FeatureData::container_type>(expanded_local_ids,
1538 expanded_local_ids.end()));
1541 for (
auto entity : elem_vector)
1544 mooseAssert(neighbor,
"neighbor pointer is NULL");
1546 if (neighbor->processor_id() != my_processor_id)
1547 feature._ghosted_ids.insert(feature._ghosted_ids.end(), elem->id());
1553 feature._local_ids.swap(expanded_local_ids);
1556 feature._halo_ids = feature._local_ids;
1564 if (num_layers_to_expand == 0)
1567 TIME_SECTION(
"expandEdgeHalos", 3,
"Expanding Edge Halos");
1571 for (
auto & feature : list_ref)
1573 for (
unsigned short halo_level = 0; halo_level < num_layers_to_expand; ++halo_level)
1580 for (
auto entity : orig_halo_ids)
1598 for (
auto entity : disjoint_orig_halo_ids)
1620 bool expand_halos_only,
1623 mooseAssert(elem,
"Elem is NULL");
1625 std::vector<const Elem *> all_active_neighbors;
1629 for (
const auto i : make_range(elem->n_neighbors()))
1631 const Elem * neighbor_ancestor =
nullptr;
1632 bool topological_neighbor =
false;
1638 neighbor_ancestor = elem->neighbor_ptr(i);
1640 if (neighbor_ancestor)
1648 if (neighbor_ancestor->is_remote())
1651 neighbor_ancestor->active_family_tree_by_neighbor(all_active_neighbors, elem,
false);
1664 if (neighbor_ancestor)
1672 if (neighbor_ancestor->is_remote())
1675 neighbor_ancestor->active_family_tree_by_topological_neighbor(
1678 topological_neighbor =
true;
1692 all_active_neighbors,
1695 topological_neighbor,
1698 all_active_neighbors.clear();
1705 bool expand_halos_only)
1707 mooseAssert(node,
"Node is NULL");
1709 std::vector<const Node *> all_active_neighbors;
1715template <
typename T>
1718 std::vector<const T *> neighbor_entities,
1720 bool expand_halos_only,
1721 bool topological_neighbor,
1725 for (
const auto neighbor : neighbor_entities)
1729 if (expand_halos_only)
1731 auto entity_id = neighbor->id();
1733 if (topological_neighbor || disjoint_only)
1742 if (!topological_neighbor && neighbor->processor_id() != my_processor_id)
1754 if (curr_entity->processor_id() == my_processor_id ||
1755 neighbor->processor_id() == my_processor_id)
1763 if (topological_neighbor || disjoint_only)
1785 if (elem && elem->on_boundary())
1829 for (
const auto node_n : make_range(elem->n_nodes()))
1833 for (
auto it = iters.first; it != iters.second; ++it)
1847 for (
auto it = iters.first; it != iters.second; ++it)
1858template <
typename T>
1867 if (belem->_elem->id() == entity->id() &&
hasBoundary(belem->_bnd_id))
1888 std::insert_iterator<FeatureData::container_type>(all_primary_region_ids,
1889 all_primary_region_ids.begin()));
1892 std::list<dof_id_type> disjoint_elem_id_list;
1895 all_primary_region_ids.begin(),
1896 all_primary_region_ids.end(),
1897 std::insert_iterator<std::list<dof_id_type>>(disjoint_elem_id_list,
1898 disjoint_elem_id_list.begin()));
1907 for (
auto elem_id : disjoint_elem_id_list)
1909 BoundingBox elem_bbox;
1912 bool found_match =
false;
1915 if (bbox.intersects(elem_bbox, TOLERANCE))
1939 std::insert_iterator<FeatureData::container_type>(set_union, set_union.begin()));
1949 bbox.min()(i) = std::min(bbox.min()(i), rhs_bbox.min()(i));
1950 bbox.max()(i) = std::max(bbox.max()(i), rhs_bbox.max()(i));
1958 for (
const auto & bbox_lhs : _bboxes)
1959 for (
const auto & bbox_rhs : rhs.
_bboxes)
1975 return MooseUtils::setsIntersect(_periodic_nodes, rhs.
_periodic_nodes);
1981 return MooseUtils::setsIntersect(_ghosted_ids, rhs.
_ghosted_ids);
1988 ((boundingBoxesIntersect(rhs) &&
1989 ghostedIntersect(rhs))
1991 periodicBoundariesIntersect(rhs)));
1997 for (
const auto & orig_id_pair1 : _orig_ids)
1998 for (
const auto & orig_id_pair2 : rhs.
_orig_ids)
1999 if (orig_id_pair1 == orig_id_pair2)
2008 mooseAssert(_var_index == rhs._var_index,
"Mismatched variable index in merge");
2009 mooseAssert(_id == rhs._id,
"Mismatched auxiliary id in merge");
2014 std::set_union(_local_ids.begin(),
2016 rhs._local_ids.begin(),
2017 rhs._local_ids.end(),
2018 std::insert_iterator<FeatureData::container_type>(set_union, set_union.begin()));
2019 _local_ids.swap(set_union);
2023 std::set_union(_periodic_nodes.begin(),
2024 _periodic_nodes.end(),
2025 rhs._periodic_nodes.begin(),
2026 rhs._periodic_nodes.end(),
2027 std::insert_iterator<FeatureData::container_type>(set_union, set_union.begin()));
2028 _periodic_nodes.swap(set_union);
2032 std::set_union(_ghosted_ids.begin(),
2034 rhs._ghosted_ids.begin(),
2035 rhs._ghosted_ids.end(),
2036 std::insert_iterator<FeatureData::container_type>(set_union, set_union.begin()));
2045 bool physical_intersection = (_ghosted_ids.size() + rhs._ghosted_ids.size() > set_union.size());
2046 _ghosted_ids.swap(set_union);
2052 _bboxes.reserve(_bboxes.size() + rhs._bboxes.size());
2053 std::copy(rhs._bboxes.begin(), rhs._bboxes.end(), std::back_inserter(_bboxes));
2055 mergeBBoxes(_bboxes, physical_intersection);
2059 std::set_union(_disjoint_halo_ids.begin(),
2060 _disjoint_halo_ids.end(),
2061 rhs._disjoint_halo_ids.begin(),
2062 rhs._disjoint_halo_ids.end(),
2063 std::insert_iterator<FeatureData::container_type>(set_union, set_union.begin()));
2064 _disjoint_halo_ids.swap(set_union);
2070 rhs._halo_ids.begin(),
2071 rhs._halo_ids.end(),
2072 std::insert_iterator<FeatureData::container_type>(set_union, set_union.begin()));
2076 _orig_ids.splice(_orig_ids.end(), std::move(rhs._orig_ids));
2079 _min_entity_id = std::min(_min_entity_id, rhs._min_entity_id);
2087 "Flags in invalid state");
2090 _status &= rhs._status;
2093 _boundary_intersection |= rhs._boundary_intersection;
2095 _vol_count += rhs._vol_count;
2096 _centroid += rhs._centroid;
2102 mooseAssert(_var_index == rhs._var_index,
"Mismatched variable index in merge");
2103 mooseAssert(_id == rhs._id,
"Mismatched auxiliary id in merge");
2107 std::set_union(_local_ids.begin(),
2109 rhs._local_ids.begin(),
2110 rhs._local_ids.end(),
2111 std::insert_iterator<FeatureData::container_type>(set_union, set_union.begin()));
2112 _local_ids.swap(set_union);
2115 "Flags in invalid state");
2122 _periodic_nodes.clear();
2124 _disjoint_halo_ids.clear();
2125 _ghosted_ids.clear();
2132 bool physical_intersection)
2142 std::list<BoundingBox> box_list(bboxes.begin(), bboxes.end());
2144 auto box_expanded =
false;
2145 for (
auto it1 = box_list.begin(); it1 != box_list.end(); )
2147 auto merge_occured =
false;
2148 for (
auto it2 = box_list.begin(); it2 != box_list.end(); ++it2)
2150 if (it1 != it2 && it1->intersects(*it2, TOLERANCE))
2152 updateBBoxExtremes(*it2, *it1);
2153 box_list.emplace_back(std::move(*it2));
2155 box_list.erase(it2);
2156 it1 = box_list.erase(it1);
2158 box_expanded =
true;
2159 merge_occured =
true;
2172 bboxes.resize(box_list.size());
2173 std::copy(box_list.begin(), box_list.end(), bboxes.begin());
2176 if (physical_intersection && !box_expanded)
2178 std::ostringstream oss;
2179 oss <<
"LHS BBoxes:\n";
2180 for (
const auto i : index_range(_bboxes))
2181 oss <<
"Max: " << _bboxes[i].max() <<
" Min: " << _bboxes[i].min() <<
'\n';
2183 ::mooseError(
"No Bounding Boxes Expanded - This is a catastrophic error!\n", oss.str());
2190 static const bool debug =
true;
2192 out <<
"Grain ID: ";
2200 out <<
"\nGhosted Entities: ";
2202 out << ghosted_id <<
" ";
2204 out <<
"\nLocal Entities: ";
2206 out << local_id <<
" ";
2208 out <<
"\nHalo Entities: ";
2210 out << halo_id <<
" ";
2212 out <<
"\nPeriodic Node IDs: ";
2214 out << periodic_node <<
" ";
2218 for (
const auto & bbox : feature.
_bboxes)
2220 out <<
"\nMax: " << bbox.max() <<
" Min: " << bbox.min();
2223 out <<
"\nStatus: ";
2235 out <<
"\nOrig IDs (rank, index): ";
2236 for (
const auto & orig_pair : feature.
_orig_ids)
2237 out <<
'(' << orig_pair.first <<
", " << orig_pair.second <<
") ";
2238 out <<
"\nVar_index: " << feature.
_var_index;
2241 out <<
"\n" << std::endl;
2255 bbox.min()(i) = std::min(bbox.min()(i), node(i));
2256 bbox.max()(i) = std::max(bbox.max()(i), node(i));
2263 for (
const auto node_n : make_range(elem.n_nodes()))
2271 std::numeric_limits<processor_id_type>::max();
boundary_id_type BoundaryID
void storeHelper(std::ostream &stream, P &data, void *context)
void loadHelper(std::istream &stream, P &data, void *context)
registerMooseObject("PhaseFieldApp", FeatureFloodCount)
void dataStore(std::ostream &stream, FeatureFloodCount::FeatureData &feature, void *context)
void updateBBoxExtremesHelper(BoundingBox &bbox, const Point &node)
void dataLoad(std::istream &stream, FeatureFloodCount::FeatureData &feature, void *context)
void dataStore(std::ostream &stream, FeatureFloodCount::FeatureData &feature, void *context)
void dataLoad(std::istream &stream, FeatureFloodCount::FeatureData &feature, void *context)
std::pair< typename M::iterator, bool > moose_try_emplace(M &m, const typename M::key_type &k, Args &&... args)
bool hasBoundary(const BoundaryName &name) const
virtual bool boundaryRestricted() const
static InputParameters validParams()
virtual void setCurrentSubdomainID(const Elem *elem, const THREAD_ID tid) override
Status _status
The status of a feature (used mostly in derived classes like the GrainTracker)
void updateBBoxExtremes(MeshBase &mesh)
Update the minimum and maximum coordinates of a bounding box given a Point, Elem or BBox parameter.
std::vector< BoundingBox > _bboxes
The vector of bounding boxes completely enclosing this feature (multiple used with periodic constrain...
container_type _halo_ids
Holds the ids surrounding the feature.
BoundaryIntersection _boundary_intersection
Enumeration indicating boundary intersection status.
container_type _disjoint_halo_ids
Holds halo ids that extend onto a non-topologically connected surface.
void consolidate(FeatureData &&rhs)
Consolidates features, i.e.
std::list< std::pair< processor_id_type, unsigned int > > _orig_ids
Original processor/local ids.
void mergeBBoxes(std::vector< BoundingBox > &bboxes, bool physical_intersection)
Located the overlapping bounding box between this Feature and the other Feature and expands that over...
dof_id_type _min_entity_id
The minimum entity seen in the _local_ids, used for sorting features.
std::vector< dof_id_type > container_type
The primary underlying container type used to hold the data in each FeatureData.
bool boundingBoxesIntersect(const FeatureData &rhs) const
Determines if any of this FeatureData's bounding boxes overlap with the other FeatureData's bounding ...
bool mergeable(const FeatureData &rhs) const
The routine called to see if two features are mergeable:
bool canConsolidate(const FeatureData &rhs) const
This routine indicates whether two features can be consolidated, that is, one feature is reasonably e...
container_type _local_ids
Holds the local ids in the interior of a feature.
std::size_t _var_index
The Moose variable where this feature was found (often the "order parameter")
bool ghostedIntersect(const FeatureData &rhs) const
bool halosIntersect(const FeatureData &rhs) const
Determine if one of this FeaturesData's member sets intersects the other FeatureData's corresponding ...
bool periodicBoundariesIntersect(const FeatureData &rhs) const
Point _centroid
The centroid of the feature (average of coordinates from entities participating in the volume calcula...
unsigned int _id
An ID for this feature.
std::size_t _vol_count
The count of entities contributing to the volume calculation.
void merge(FeatureData &&rhs)
Merges another Feature Data into this one.
container_type _periodic_nodes
Holds the nodes that belong to the feature on a periodic boundary.
container_type _ghosted_ids
Holds the ghosted ids for a feature (the ids which will be used for stitching.
This object will mark nodes or elements of continuous regions all with a unique number for the purpos...
void appendPeriodicNeighborNodes(FeatureData &feature) const
This routine adds the periodic node information to our data structure prior to packing the data this ...
static void sort(std::set< T > &)
std::vector< std::set< dof_id_type > > _entities_visited
This variable keeps track of which nodes have been visited during execution.
const bool _is_elemental
Determines if the flood counter is elements or not (nodes)
const bool _is_primary
Convenience variable for testing primary rank.
const bool _var_index_mode
This variable is used to indicate whether the maps will contain unique region information or just the...
bool isBoundaryEntity(const T *entity) const
Returns a Boolean indicating whether the entity is on one of the desired boundaries.
std::unordered_set< dof_id_type > _all_boundary_entity_ids
The set of entities on the boundary of the domain used for determining if features intersect any boun...
virtual void clearDataStructures()
Helper routine for clearing up data structures during initialize and prior to parallel communication.
std::vector< MooseVariable * > _vars
The vector of coupled in variables cast to MooseVariable.
std::deque< const DofObject * > _entity_queue
The data structure for maintaining entities to flood during discovery.
static InputParameters validParams()
const DofMap & _dof_map
Reference to the dof_map containing the coupled variables.
const bool _global_numbering
This variable is used to indicate whether or not we identify features with unique numbers on multiple...
const processor_id_type _n_procs
Convenience variable holding the number of processors in this simulation.
virtual unsigned int getFeatureVar(unsigned int feature_id) const
Returns the variable representing the passed in feature.
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)
Real _step_connecting_threshold
virtual void prepareDataForTransfer()
This routine uses the local flooded data to build up the local feature data structures (_partial feat...
virtual bool areFeaturesMergeable(const FeatureData &f1, const FeatureData &f2) const
Method for determining whether two features are mergeable.
std::vector< BoundaryID > _specified_bnds
static bool contains(std::set< T > &container, const T &item)
virtual void meshChanged() override
const PostprocessorValue & _element_average_value
Average value of the domain which can optionally be used to find features in a field.
virtual void initialSetup() override
virtual void mergeSets()
This routine is called on the primary rank only and stitches together the partial feature pieces seen...
void buildFeatureIdToLocalIndices(unsigned int max_id)
This method builds a lookup map for retrieving the right local feature (by index) given a global inde...
unsigned int _feature_count
The number of features seen by this object (same as summing _feature_counts_per_map)
std::vector< unsigned int > _feature_counts_per_map
The number of features seen by this object per map.
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.
virtual void initialize() override
std::vector< std::map< dof_id_type, int > > _halo_ids
The data structure for looking up halos around features.
bool flood(const DofObject *dof_object, std::size_t current_index)
This method will check if the current entity is above the supplied threshold and "mark" it.
unsigned long _var_number
This variable is used to build the periodic node map.
std::vector< BoundaryID > _secondary_perc_bnds
virtual bool isNewFeatureOrConnectedRegion(const DofObject *dof_object, std::size_t ¤t_index, FeatureData *&feature, Status &status, unsigned int &new_id)
Method called during the recursive flood routine that should return whether or not the current entity...
virtual Point featureCentroid(unsigned int feature_id) const
Returns the centroid of the designated feature (only supported without periodic boundaries)
ConstBndElemRange * _bnd_elem_range
Boundary element range pointer.
std::vector< std::size_t > _local_to_global_feature_map
The vector recording the local to global feature indices.
Status
This enumeration is used to indicate status of the grains in the _unique_grains data structure.
void visitNeighborsHelper(const T *curr_entity, std::vector< const T * > neighbor_entities, FeatureData *feature, bool expand_halos_only, bool topological_neighbor, bool disjoint_only)
The actual logic for visiting neighbors is abstracted out here.
const std::size_t _maps_size
Convenience variable holding the size of all the datastructures size by the number of maps.
std::vector< std::map< dof_id_type, int > > _var_index_maps
This map keeps track of which variables own which nodes.
virtual bool doesFeatureIntersectBoundary(unsigned int feature_id) const
Returns a Boolean indicating whether this feature intersects any boundary.
std::unordered_map< dof_id_type, std::vector< const Elem * > > _nodes_to_elem_map
The data structure used to find neighboring elements give a node ID.
bool compareValueWithThreshold(Real entity_value, Real threshold) const
This method is used to determine whether the current entity value is part of a feature or not.
const bool _use_less_than_threshold_comparison
Use less-than when comparing values against the threshold value.
virtual void execute() override
void serialize(std::string &serialized_buffer, unsigned int var_num=invalid_id)
This routines packs the _partial_feature_sets data into a structure suitable for parallel communicati...
std::size_t getNumberActiveFeatures() const
Return the number of active features.
libMesh::PeriodicBoundaries * _pbs
A pointer to the periodic boundary constraints object.
const bool _condense_map_info
const bool _single_map_mode
This variable is used to indicate whether or not multiple maps are used during flooding.
FeatureFloodCount(const InputParameters ¶meters)
static const std::size_t invalid_size_t
virtual processor_id_type numberOfDistributedMergeHelpers() const
Returns a number indicating the number of merge helpers when running in parallel based on certain imp...
static const unsigned int invalid_id
std::vector< MooseVariableFEBase * > _fe_vars
The vector of coupled in variables.
void scatterAndUpdateRanks()
Calls buildLocalToGlobalIndices to build the individual local to global indicies for each rank and sc...
bool _is_boundary_restricted
Indicates that this object should only run on one or more boundaries.
virtual void buildLocalToGlobalIndices(std::vector< std::size_t > &local_to_global_all, std::vector< int > &counts) const
This routine populates a stacked vector of local to global indices per rank and the associated count ...
virtual Real getEntityValue(dof_id_type entity_id, FieldType field_type, std::size_t var_index=0) const
std::map< dof_id_type, std::vector< unsigned int > > _entity_var_to_features
void deserialize(std::vector< std::string > &serialized_buffers, unsigned int var_num=invalid_id)
This routine takes the vector of byte buffers (one for each processor), deserializes them into a seri...
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data, during the discovery and mergi...
static void reserve(std::set< T > &, std::size_t)
virtual void restoreOriginalDataStructures(std::vector< std::list< FeatureData > > &)
virtual bool isFeaturePercolated(unsigned int feature_id) const
Returns a Boolean indicating whether this feature is percolated (e.g.
std::vector< FeatureData > & _feature_sets
The data structure used to hold the globally unique features.
void communicateAndMerge()
This routine handles all of the serialization, communication and deserialization of the data structur...
void sortAndLabel()
Sort and assign ids to features based on their position in the container after sorting.
const std::size_t _n_vars
void visitNodalNeighbors(const Node *node, FeatureData *feature, bool expand_halos_only)
These two routines are utility routines used by the flood routine and by derived classes for visiting...
const bool _compute_halo_maps
Indicates whether or not to communicate halo map information with all ranks.
std::vector< unsigned int > _empty_var_to_features
virtual Real getValue() const override
void updateBoundaryIntersections(FeatureData &feature) const
Update the feature's attributes to indicate boundary intersections.
virtual Real getThreshold(std::size_t current_index) const
Return the starting comparison threshold to use when inspecting an entity during the flood stage.
const Real _threshold
The threshold above (or below) where an entity may begin a new region (feature)
const bool _compute_var_to_feature_map
Indicates whether or not the var to feature map is populated.
virtual void consolidateMergedFeatures(std::vector< std::list< FeatureData > > *saved_data=nullptr)
This method consolidates all of the merged information from _partial_feature_sets into the _feature_s...
MooseMesh & _mesh
A reference to the mesh.
BoundaryIntersection
This enumeration is used to inidacate status of boundary intersections.
@ SECONDARY_PERCOLATION_BOUNDARY
@ PRIMARY_PERCOLATION_BOUNDARY
virtual std::size_t getTotalFeatureCount() const
Returns the total feature count (active and inactive ids, useful for sizing vectors)
std::multimap< dof_id_type, dof_id_type > _periodic_node_map
The data structure which is a list of nodes that are constrained to other nodes based on the imposed ...
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 visitElementalNeighbors(const Elem *elem, FeatureData *feature, bool expand_halos_only, bool disjoint_only)
virtual bool doesFeatureIntersectSpecifiedBoundary(unsigned int feature_id) const
Returns a Boolean indicating whether this feature intersects boundaries in a user-supplied list.
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 updateFieldInfo()
This method is used to populate any of the data structures used for storing field data (nodal or elem...
std::map< dof_id_type, int > _ghosted_entity_ids
The map for holding reconstructed ghosted element information.
const Real _connecting_threshold
The threshold above (or below) which neighboring entities are flooded (where regions can be extended ...
static const processor_id_type invalid_proc_id
@ INTERSECTS_SPECIFIED_BOUNDARY
std::unique_ptr< libMesh::PointLocatorBase > _point_locator
void expandPointHalos()
This method takes all of the partial features and expands the local, ghosted, and halo sets around th...
virtual void finalize() override
std::vector< BoundaryID > _primary_perc_bnds
virtual Real getConnectingThreshold(std::size_t current_index) const
Return the "connecting" comparison threshold to use when inspecting an entity during the flood stage.
static InputParameters validParams()
const InputParameters & parameters() const
void paramError(const std::string ¶m, Args... args) const
void mooseError(Args &&... args) const
void mooseWarning(Args &&... args) const
void mooseInfo(Args &&... args) const
bool isBoundaryElem(dof_id_type elem_id) const
virtual Elem * elemPtr(const dof_id_type i)
const std::unordered_map< dof_id_type, std::vector< dof_id_type > > & nodeToElemMap()
virtual bnd_elem_iterator bndElemsBegin()
void buildPeriodicNodeMap(std::multimap< dof_id_type, dof_id_type > &periodic_node_map, unsigned int var_number, libMesh::PeriodicBoundaries *pbs) const
std::vector< BoundaryID > getBoundaryIDs(const Elem *const elem, const unsigned short int side) const
virtual const Node * nodePtr(const dof_id_type i) const
virtual bnd_elem_iterator bndElemsEnd()
libMesh::StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement * > * getBoundaryElementRange()
void addMooseVariableDependency(MooseVariableFieldBase *var)
virtual void reinitElemPhys(const Elem *elem, const std::vector< Point > &phys_points_in_elem, const THREAD_ID tid)=0
virtual bool isTransient() const=0
virtual libMesh::DofMap & dofMap()
void split(int color, int key, Communicator &target) const
void gather_packed_range(const unsigned int root_id, Context *context, Iter range_begin, const Iter range_end, OutputIter out, std::size_t approx_buffer_size=1000000) const
void scatter(const std::vector< T, A > &data, T &recv, const unsigned int root_id=0) const
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
void gather(const unsigned int root_id, const T &send_data, std::vector< T, A > &recv) const
FEProblemBase & _fe_problem
PeriodicBoundaries * get_periodic_boundaries()
const Parallel::Communicator & _communicator
processor_id_type processor_id() const
processor_id_type n_processors() const
static constexpr std::size_t dim
uint8_t processor_id_type
static constexpr Real TOLERANCE
const dof_id_type n_nodes