www.mooseframework.org
Public Types | Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
GrainTrackerElasticity Class Reference

Manage a list of elasticity tensors for the grains. More...

#include <GrainTrackerElasticity.h>

Inheritance diagram for GrainTrackerElasticity:
[legend]

Public Types

enum  RemapCacheMode { RemapCacheMode::FILL, RemapCacheMode::USE, RemapCacheMode::BYPASS }
 
enum  FieldType {
  FieldType::UNIQUE_REGION, FieldType::VARIABLE_COLORING, FieldType::GHOSTED_ENTITIES, FieldType::HALOS,
  FieldType::CENTROID, FieldType::ACTIVE_BOUNDS
}
 
enum  Status : unsigned char { Status::CLEAR = 0x0, Status::MARKED = 0x1, Status::DIRTY = 0x2, Status::INACTIVE = 0x4 }
 This enumeration is used to indicate status of the grains in the _unique_grains data structure. More...
 
enum  BoundaryIntersection : unsigned char {
  BoundaryIntersection::NONE = 0x0, BoundaryIntersection::ANY_BOUNDARY = 0x1, BoundaryIntersection::PRIMARY_PERCOLATION_BOUNDARY = 0x2, BoundaryIntersection::SECONDARY_PERCOLATION_BOUNDARY = 0x4,
  BoundaryIntersection::SPECIFIED_BOUNDARY = 0x8
}
 This enumeration is used to inidacate status of boundary intersections. More...
 

Public Member Functions

 GrainTrackerElasticity (const InputParameters &parameters)
 
const RankFourTensorgetData (unsigned int grain_id) const
 return data for selected grain More...
 
virtual void meshChanged () override
 
virtual void initialize () override
 
virtual void execute () override
 
virtual void finalize () override
 
virtual std::size_t getTotalFeatureCount () const override
 Returns the total feature count (active and inactive ids, useful for sizing vectors) More...
 
virtual Real getEntityValue (dof_id_type node_id, FieldType field_type, std::size_t var_index=0) const override
 
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. More...
 
virtual unsigned int getFeatureVar (unsigned int feature_id) const override
 Returns the variable representing the passed in feature. More...
 
virtual std::size_t getNumberActiveGrains () const override
 Returns the number of active grains current stored in the GrainTracker. More...
 
virtual Point getGrainCentroid (unsigned int grain_id) const override
 Returns the centroid for the given grain number. More...
 
virtual bool doesFeatureIntersectBoundary (unsigned int feature_id) const override
 Returns a Boolean indicating whether this feature intersects any boundary. More...
 
virtual bool doesFeatureIntersectSpecifiedBoundary (unsigned int feature_id) const override
 Returns a Boolean indicating whether this feature intersects boundaries in a user-supplied list. More...
 
virtual bool isFeaturePercolated (unsigned int feature_id) const override
 Returns a Boolean indicating whether this feature is percolated (e.g. More...
 
virtual std::vector< unsigned int > getNewGrainIDs () const override
 This method returns all of the new ids generated in an invocation of the GrainTracker. More...
 
virtual void initialSetup () override
 
virtual Real getValue () override
 
std::size_t getNumberActiveFeatures () const
 Return the number of active features. More...
 
virtual Point featureCentroid (unsigned int feature_id) const
 Returns the centroid of the designated feature (only supported without periodic boundaries) More...
 
std::size_t numCoupledVars () const
 Returns the number of coupled varaibles. More...
 
const std::vector< MooseVariable * > & getCoupledVars () const
 Returns a const vector to the coupled variable pointers. More...
 
const std::vector< MooseVariableFEBase * > & getFECoupledVars () const
 Returns a const vector to the coupled MooseVariableFEBase pointers. More...
 
bool isElemental () const
 
const std::vector< FeatureData > & getFeatures () const
 Return a constant reference to the vector of all discovered features. More...
 

Static Public Attributes

static const std::size_t invalid_size_t = std::numeric_limits<std::size_t>::max()
 
static const unsigned int invalid_id = std::numeric_limits<unsigned int>::max()
 

Protected Member Functions

RankFourTensor newGrain (unsigned int new_grain_id)
 implement this method to initialize the data for the new grain More...
 
virtual void newGrainCreated (unsigned int new_grain_id)
 This method is called when a new grain is detected. More...
 
virtual void updateFieldInfo () override
 This method is used to populate any of the data structures used for storing field data (nodal or elemental). More...
 
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. More...
 
void prepopulateState (const FeatureFloodCount &ffc_object)
 This method extracts the necessary state from the passed in object necessary to continue tracking grains. More...
 
void communicateHaloMap ()
 
void assignGrains ()
 When the tracking phase starts (_t_step == _tracking_step) it assigns a unique id to every FeatureData object found by the FeatureFloodCount object. More...
 
void trackGrains ()
 On subsequent time_steps, incoming FeatureData objects are compared to previous time_step information to track grains between time steps. More...
 
void remapGrains ()
 This method is called after trackGrains to remap grains that are too close to each other. More...
 
void broadcastAndUpdateGrainData ()
 Broadcast essential Grain information to all processors. More...
 
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 for a given grain. More...
 
bool attemptGrainRenumber (FeatureData &grain, unsigned int depth, unsigned int max_depth)
 This is the recursive part of the remapping algorithm. More...
 
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. More...
 
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. More...
 
Real boundingRegionDistance (std::vector< BoundingBox > &bboxes1, std::vector< BoundingBox > &bboxes2) const
 This method returns the minimum periodic distance between two vectors of bounding boxes. More...
 
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 boxes. More...
 
unsigned int getNextUniqueID ()
 Retrieve the next unique grain number if a new grain is detected during trackGrains. More...
 
template<typename T >
bool isBoundaryEntity (const T *entity) const
 Returns a Boolean indicating whether the entity is on one of the desired boundaries. More...
 
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. More...
 
virtual Real getConnectingThreshold (std::size_t current_index) const
 Return the "connecting" comparison threshold to use when inspecting an entity during the flood stage. More...
 
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. More...
 
virtual bool isNewFeatureOrConnectedRegion (const DofObject *dof_object, std::size_t &current_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 is part of the current feature (if one is being explored), or if it's the start of a new feature. More...
 
void expandPointHalos ()
 This method takes all of the partial features and expands the local, ghosted, and halo sets around those regions to account for the diffuse interface. More...
 
void expandEdgeHalos (unsigned int num_layers_to_expand)
 This method expands the existing halo set by some width determined by the passed in value. More...
 
template<typename T >
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. More...
 
void prepareDataForTransfer ()
 This routine uses the local flooded data to build up the local feature data structures (_feature_sets). More...
 
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 communication operations. More...
 
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 series of FeatureSet objects, and appends them to the _feature_sets data structure. More...
 
virtual void mergeSets ()
 This routine is called on the master rank only and stitches together the partial feature pieces seen on any processor. More...
 
virtual bool areFeaturesMergeable (const FeatureData &f1, const FeatureData &f2) const
 Method for determining whether two features are mergeable. More...
 
void communicateAndMerge ()
 This routine handles all of the serialization, communication and deserialization of the data structures containing FeatureData objects. More...
 
void sortAndLabel ()
 Sort and assign ids to features based on their position in the container after sorting. More...
 
void scatterAndUpdateRanks ()
 Calls buildLocalToGlobalIndices to build the individual local to global indicies for each rank and scatters that information to all ranks. More...
 
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 vector for scattering the vector to the ranks. More...
 
void buildFeatureIdToLocalIndices (unsigned int max_id)
 This method builds a lookup map for retrieving the right local feature (by index) given a global index or id. More...
 
virtual void clearDataStructures ()
 Helper routine for clearing up data structures during initialize and prior to parallel communication. More...
 
void updateBoundaryIntersections (FeatureData &feature) const
 Update the feature's attributes to indicate boundary intersections. More...
 
void appendPeriodicNeighborNodes (FeatureData &feature) const
 This routine adds the periodic node information to our data structure prior to packing the data this makes those periodic neighbors appear much like ghosted nodes in a multiprocessor setting. More...
 
void updateRegionOffsets ()
 This routine updates the _region_offsets variable which is useful for quickly determining the proper global number for a feature when using multimap mode. More...
 
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 neighbors. More...
 
void visitElementalNeighbors (const Elem *elem, FeatureData *feature, bool expand_halos_only, bool disjoint_only)
 

Static Protected Member Functions

template<class InputIterator >
static bool setsIntersect (InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2)
 This method detects whether two sets intersect without building a result set. More...
 

Protected Attributes

const bool _random_rotations
 generate random rotations when the Euler Angle provider runs out of data (otherwise error out) More...
 
RankFourTensor _C_ijkl
 unrotated elasticity tensor More...
 
const EulerAngleProvider_euler
 object providing the Euler angles More...
 
std::vector< RankFourTensor_grain_data
 per grain data More...
 
const int _tracking_step
 The timestep to begin tracking grains. More...
 
const unsigned short _halo_level
 The thickness of the halo surrounding each grain. More...
 
const unsigned short _max_remap_recursion_depth
 Depth of renumbering recursion (a depth of zero means no recursion) More...
 
const unsigned short _n_reserve_ops
 The number of reserved order parameters. More...
 
const std::size_t _reserve_op_index
 The cutoff index where if variable index >= this number, no remapping TO that variable will occur. More...
 
const Real _reserve_op_threshold
 The threshold above (or below) where a grain may be found on a reserve op field. More...
 
const bool _remap
 Inidicates whether remapping should be done or not (remapping is independent of tracking) More...
 
const bool _tolerate_failure
 Indicates whether we should continue after a remap failure (will result in non-physical results) More...
 
NonlinearSystemBase & _nl
 A reference to the nonlinear system (used for retrieving solution vectors) More...
 
std::vector< FeatureData_feature_sets_old
 This data structure holds the map of unique grains from the previous time step. More...
 
const PolycrystalUserObjectBase_poly_ic_uo
 An optional IC UserObject which can provide initial data structures to this object. More...
 
const short _verbosity_level
 Verbosity level controlling the amount of information printed to the console. More...
 
bool & _first_time
 Boolean to indicate the first time this object executes. More...
 
const bool _error_on_grain_creation
 Boolean to terminate with an error if a new grain is created during the simulation. More...
 
std::vector< MooseVariableFEBase * > _fe_vars
 The vector of coupled in variables. More...
 
std::vector< MooseVariable * > _vars
 The vector of coupled in variables cast to MooseVariable. More...
 
const DofMap & _dof_map
 Reference to the dof_map containing the coupled variables. More...
 
const Real _threshold
 The threshold above (or below) where an entity may begin a new region (feature) More...
 
Real _step_threshold
 
const Real _connecting_threshold
 The threshold above (or below) which neighboring entities are flooded (where regions can be extended but not started) More...
 
Real _step_connecting_threshold
 
MooseMesh & _mesh
 A reference to the mesh. More...
 
unsigned long _var_number
 This variable is used to build the periodic node map. More...
 
const bool _single_map_mode
 This variable is used to indicate whether or not multiple maps are used during flooding. More...
 
const bool _condense_map_info
 
const bool _global_numbering
 This variable is used to indicate whether or not we identify features with unique numbers on multiple maps. More...
 
const bool _var_index_mode
 This variable is used to indicate whether the maps will contain unique region information or just the variable numbers owning those regions. More...
 
const bool _compute_halo_maps
 Indicates whether or not to communicate halo map information with all ranks. More...
 
const bool _compute_var_to_feature_map
 Indicates whether or not the var to feature map is populated. More...
 
const bool _use_less_than_threshold_comparison
 Use less-than when comparing values against the threshold value. More...
 
const std::size_t _n_vars
 
const std::size_t _maps_size
 Convenience variable holding the size of all the datastructures size by the number of maps. More...
 
const processor_id_type _n_procs
 Convenience variable holding the number of processors in this simulation. More...
 
std::vector< std::set< dof_id_type > > _entities_visited
 This variable keeps track of which nodes have been visited during execution. More...
 
std::vector< std::map< dof_id_type, int > > _var_index_maps
 This map keeps track of which variables own which nodes. More...
 
std::vector< std::vector< const Elem * > > _nodes_to_elem_map
 The data structure used to find neighboring elements give a node ID. More...
 
std::vector< unsigned int > _feature_counts_per_map
 The number of features seen by this object per map. More...
 
unsigned int _feature_count
 The number of features seen by this object (same as summing _feature_counts_per_map) More...
 
std::vector< std::list< FeatureData > > _partial_feature_sets
 The data structure used to hold partial and communicated feature data, during the discovery and merging phases. More...
 
std::vector< FeatureData > & _feature_sets
 The data structure used to hold the globally unique features. More...
 
std::vector< FeatureData_volatile_feature_sets
 Derived objects (e.g. More...
 
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. More...
 
std::vector< std::size_t > _local_to_global_feature_map
 The vector recording the local to global feature indices. More...
 
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) More...
 
PeriodicBoundaries * _pbs
 A pointer to the periodic boundary constraints object. More...
 
std::unique_ptr< PointLocatorBase > _point_locator
 
const PostprocessorValue & _element_average_value
 Average value of the domain which can optionally be used to find features in a field. More...
 
std::map< dof_id_type, int > _ghosted_entity_ids
 The map for holding reconstructed ghosted element information. More...
 
std::vector< std::map< dof_id_type, int > > _halo_ids
 The data structure for looking up halos around features. More...
 
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 periodic boundary conditions. More...
 
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 boundary. More...
 
std::map< dof_id_type, std::vector< unsigned int > > _entity_var_to_features
 
std::vector< unsigned int > _empty_var_to_features
 
std::vector< BoundaryID > _primary_perc_bnds
 
std::vector< BoundaryID > _secondary_perc_bnds
 
std::vector< BoundaryID > _specified_bnds
 
const bool _is_elemental
 Determines if the flood counter is elements or not (nodes) More...
 
bool _is_boundary_restricted
 Indicates that this object should only run on one or more boundaries. More...
 
ConstBndElemRange * _bnd_elem_range
 Boundary element range pointer. More...
 
const bool _is_master
 Convenience variable for testing master rank. More...
 

Private Member Functions

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_sets vectors. More...
 

Static Private Member Functions

template<class T >
static void sort (std::set< T > &)
 
template<class T >
static void sort (std::vector< T > &container)
 
template<class T >
static void reserve (std::set< T > &, std::size_t)
 
template<class T >
static void reserve (std::vector< T > &container, std::size_t size)
 

Private Attributes

unsigned int _reserve_grain_first_index
 Holds the first unique grain index when using _reserve_op (all the remaining indices are sequential) More...
 
unsigned int _old_max_grain_id
 The previous max grain id (needed to figure out which ids are new in a given step) More...
 
unsigned int & _max_curr_grain_id
 Holds the next "regular" grain ID (a grain found or remapped to the standard op vars) More...
 
const bool _is_transient
 Boolean to indicate whether this is a Steady or Transient solve. More...
 
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) More...
 
const PerfID _finalize_timer
 Timers. More...
 
const PerfID _remap_timer
 
const PerfID _track_grains
 
const PerfID _broadcast_update
 
const PerfID _update_field_info
 
std::deque< const DofObject * > _entity_queue
 The data structure for maintaining entities to flood during discovery. More...
 
const bool _distribute_merge_work
 Keeps track of whether we are distributing the merge work. More...
 
const PerfID _execute_timer
 Timers. More...
 
const PerfID _merge_timer
 
const PerfID _comm_and_merge
 
const PerfID _expand_halos
 
const PerfID _prepare_for_transfer
 
const PerfID _consolidate_merged_features
 

Detailed Description

Manage a list of elasticity tensors for the grains.

Definition at line 24 of file GrainTrackerElasticity.h.

Member Enumeration Documentation

◆ BoundaryIntersection

enum FeatureFloodCount::BoundaryIntersection : unsigned char
stronginherited

This enumeration is used to inidacate status of boundary intersections.

Enumerator
NONE 
ANY_BOUNDARY 
PRIMARY_PERCOLATION_BOUNDARY 
SECONDARY_PERCOLATION_BOUNDARY 
SPECIFIED_BOUNDARY 

Definition at line 129 of file FeatureFloodCount.h.

129  : unsigned char
130  {
131  NONE = 0x0,
132  ANY_BOUNDARY = 0x1,
133  PRIMARY_PERCOLATION_BOUNDARY = 0x2,
134  SECONDARY_PERCOLATION_BOUNDARY = 0x4,
135  SPECIFIED_BOUNDARY = 0x8
136  };

◆ FieldType

enum FeatureFloodCount::FieldType
stronginherited
Enumerator
UNIQUE_REGION 
VARIABLE_COLORING 
GHOSTED_ENTITIES 
HALOS 
CENTROID 
ACTIVE_BOUNDS 

Definition at line 103 of file FeatureFloodCount.h.

104  {
105  UNIQUE_REGION,
106  VARIABLE_COLORING,
107  GHOSTED_ENTITIES,
108  HALOS,
109  CENTROID,
110  ACTIVE_BOUNDS,
111  };

◆ RemapCacheMode

enum GrainTracker::RemapCacheMode
stronginherited
Enumerator
FILL 
USE 
BYPASS 

Definition at line 53 of file GrainTracker.h.

54  {
55  FILL,
56  USE,
57  BYPASS
58  };

◆ Status

enum FeatureFloodCount::Status : unsigned char
stronginherited

This enumeration is used to indicate status of the grains in the _unique_grains data structure.

Enumerator
CLEAR 
MARKED 
DIRTY 
INACTIVE 

Definition at line 120 of file FeatureFloodCount.h.

120  : unsigned char
121  {
122  CLEAR = 0x0,
123  MARKED = 0x1,
124  DIRTY = 0x2,
125  INACTIVE = 0x4
126  };

Constructor & Destructor Documentation

◆ GrainTrackerElasticity()

GrainTrackerElasticity::GrainTrackerElasticity ( const InputParameters &  parameters)

Definition at line 34 of file GrainTrackerElasticity.C.

36  _random_rotations(getParam<bool>("random_rotations")),
37  _C_ijkl(getParam<std::vector<Real>>("C_ijkl"),
38  getParam<MooseEnum>("fill_method").getEnum<RankFourTensor::FillMethod>()),
39  _euler(getUserObject<EulerAngleProvider>("euler_angle_provider"))
40 {
41 }

Member Function Documentation

◆ appendPeriodicNeighborNodes()

void FeatureFloodCount::appendPeriodicNeighborNodes ( FeatureData feature) const
protectedinherited

This routine adds the periodic node information to our data structure prior to packing the data this makes those periodic neighbors appear much like ghosted nodes in a multiprocessor setting.

Definition at line 1771 of file FeatureFloodCount.C.

1772 {
1773  if (_is_elemental)
1774  {
1775  for (auto entity : feature._local_ids)
1776  {
1777  Elem * elem = _mesh.elemPtr(entity);
1778 
1779  for (MooseIndex(elem->n_nodes()) node_n = 0; node_n < elem->n_nodes(); ++node_n)
1780  {
1781  auto iters = _periodic_node_map.equal_range(elem->node_id(node_n));
1782 
1783  for (auto it = iters.first; it != iters.second; ++it)
1784  {
1785  feature._periodic_nodes.insert(feature._periodic_nodes.end(), it->first);
1786  feature._periodic_nodes.insert(feature._periodic_nodes.end(), it->second);
1787  }
1788  }
1789  }
1790  }
1791  else
1792  {
1793  for (auto entity : feature._local_ids)
1794  {
1795  auto iters = _periodic_node_map.equal_range(entity);
1796 
1797  for (auto it = iters.first; it != iters.second; ++it)
1798  {
1799  feature._periodic_nodes.insert(feature._periodic_nodes.end(), it->first);
1800  feature._periodic_nodes.insert(feature._periodic_nodes.end(), it->second);
1801  }
1802  }
1803  }
1804 
1805  // TODO: Remove duplicates
1806 }

Referenced by FeatureFloodCount::prepareDataForTransfer().

◆ areFeaturesMergeable()

bool FeatureFloodCount::areFeaturesMergeable ( const FeatureData f1,
const FeatureData f2 
) const
protectedvirtualinherited

Method for determining whether two features are mergeable.

This routine exists because derived classes may need to override this function rather than use the mergeable method in the FeatureData object.

Reimplemented in PolycrystalUserObjectBase.

Definition at line 1243 of file FeatureFloodCount.C.

1244 {
1245  return f1.mergeable(f2);
1246 }

Referenced by FeatureFloodCount::mergeSets().

◆ assignGrains()

void GrainTracker::assignGrains ( )
protectedinherited

When the tracking phase starts (_t_step == _tracking_step) it assigns a unique id to every FeatureData object found by the FeatureFloodCount object.

We need to assign grainIDs to get the simulation going. We'll use the default sorting that doesn't require valid grainIDs (relies on _min_entity_id and _var_index). These will be the unique grain numbers that we must track for remainder of the simulation.

Definition at line 450 of file GrainTracker.C.

451 {
452  mooseAssert(_first_time, "assignGrains may only be called on the first tracking step");
453 
459  if (_is_master)
460  {
461  // Find the largest grain ID, this requires sorting if the ID is not already set
462  sortAndLabel();
463 
464  if (_feature_sets.empty())
465  {
468  }
469  else
470  {
471  _max_curr_grain_id = _feature_sets.back()._id;
473  }
474 
475  for (auto & grain : _feature_sets)
476  grain._status = Status::MARKED; // Mark the grain
477 
478  } // is_master
479 
480  /*************************************************************
481  ****************** COLLECTIVE WORK SECTION ******************
482  *************************************************************/
483 
484  // Make IDs on all non-master ranks consistent
486 
487  // Build up an id to index map
488  _communicator.broadcast(_max_curr_grain_id);
490 
491  // Now trigger the newGrainCreated() callback on all ranks
493  for (unsigned int new_id = 0; new_id <= _max_curr_grain_id; ++new_id)
494  newGrainCreated(new_id);

Referenced by GrainTracker::finalize().

◆ attemptGrainRenumber()

bool GrainTracker::attemptGrainRenumber ( FeatureData grain,
unsigned int  depth,
unsigned int  max_depth 
)
protectedinherited

This is the recursive part of the remapping algorithm.

It attempts to remap a grain to a new index and recurses until max_depth is reached.

We have two grains that are getting close represented by the same order parameter. We need to map to the variable whose closest grain to this one is furthest away by bounding region to bounding region distance.

We have a vector of the distances to the closest grains represented by each of our variables. We just need to pick a suitable grain to replace with. We will start with the maximum of this this list: (max of the mins), but will settle for next to largest and so forth as we make more attempts at remapping grains. This is a graph coloring problem so more work will be required to optimize this process.

Note: We don't have an explicit check here to avoid remapping a variable to itself. This is unnecessary since the min_distance of a variable is explicitly set up above.

If we get to this case and the best distance is less than -1, we are in big trouble. This means that grains represented by all of the remaining order parameters are overlapping this one in at least two places. We'd have to maintain multiple recursive chains, or just start over from scratch... Let's just return false and see if there is another remapping option.

Propose a new variable index for the current grain and recurse. We don't need to mark the status as DIRTY here since the recursion may fail. For now, we'll just add MARKED to the status.

Definition at line 1259 of file GrainTracker.C.

1262 {
1263  // End the recursion of our breadth first search
1264  if (depth > max_depth)
1265  return false;
1266 
1267  std::size_t curr_var_index = grain._var_index;
1268 
1269  std::vector<std::map<Node *, CacheValues>> cache;
1270 
1271  std::vector<std::list<GrainDistance>> min_distances(_vars.size());
1272 
1278  computeMinDistancesFromGrain(grain, min_distances);
1279 
1290  // clang-format off
1291  std::sort(min_distances.begin(), min_distances.end(),
1292  [](const std::list<GrainDistance> & lhs, const std::list<GrainDistance> & rhs)
1293  {
1294  // Sort lists in reverse order (largest distance first)
1295  // These empty cases are here to make this comparison stable
1296  if (lhs.empty())
1297  return false;
1298  else if (rhs.empty())
1299  return true;
1300  else
1301  return lhs.begin()->_distance > rhs.begin()->_distance;
1302  });
1303  // clang-format on
1304 
1305  for (auto & list_ref : min_distances)
1306  {
1307  const auto target_it = list_ref.begin();
1308  if (target_it == list_ref.end())
1309  continue;
1310 
1311  // If the distance is positive we can just remap and be done
1312  if (target_it->_distance > 0)
1313  {
1314  if (_verbosity_level > 0)
1315  {
1316  _console << COLOR_GREEN << "- Depth " << depth << ": Remapping grain #" << grain._id
1317  << " from variable index " << curr_var_index << " to " << target_it->_var_index;
1318  if (target_it->_distance == std::numeric_limits<Real>::max())
1319  _console << " which currently contains zero grains.\n\n" << COLOR_DEFAULT;
1320  else
1321  _console << " whose closest grain (#" << target_it->_grain_id << ") is at a distance of "
1322  << std::sqrt(target_it->_distance) << "\n\n"
1323  << COLOR_DEFAULT;
1324  }
1325 
1326  grain._status |= Status::DIRTY;
1327  grain._var_index = target_it->_var_index;
1328  return true;
1329  }
1330 
1331  // If the distance isn't positive we just need to make sure that none of the grains represented
1332  // by the target variable index would intersect this one if we were to remap
1333  {
1334  auto next_target_it = target_it;
1335  bool intersection_hit = false;
1336  unsigned short num_close_targets = 0;
1337  std::ostringstream oss;
1338  while (!intersection_hit && next_target_it != list_ref.end())
1339  {
1340  if (next_target_it->_distance > 0)
1341  break;
1342 
1343  mooseAssert(next_target_it->_grain_index < _feature_sets.size(),
1344  "Error in indexing target grain in attemptGrainRenumber");
1345  FeatureData & next_target_grain = _feature_sets[next_target_it->_grain_index];
1346 
1347  // If any grains touch we're done here
1348  if (grain.halosIntersect(next_target_grain))
1349  intersection_hit = true;
1350  else
1351  {
1352  if (num_close_targets > 0)
1353  oss << ", "; // delimiter
1354  oss << "#" << next_target_it->_grain_id;
1355  }
1356 
1357  ++next_target_it;
1358  ++num_close_targets;
1359  }
1360 
1361  if (!intersection_hit)
1362  {
1363  if (_verbosity_level > 0)
1364  {
1365  _console << COLOR_GREEN << "- Depth " << depth << ": Remapping grain #" << grain._id
1366  << " from variable index " << curr_var_index << " to " << target_it->_var_index;
1367 
1368  if (num_close_targets == 1)
1369  _console << " whose closest grain (" << oss.str()
1370  << ") is inside our bounding box but whose halo is not touching.\n\n"
1371  << COLOR_DEFAULT;
1372  else
1373  _console << " whose closest grains (" << oss.str()
1374  << ") are inside our bounding box but whose halos are not touching.\n\n"
1375  << COLOR_DEFAULT;
1376  }
1377 
1378  grain._status |= Status::DIRTY;
1379  grain._var_index = target_it->_var_index;
1380  return true;
1381  }
1382  }
1383 
1384  // If we reach this part of the loop, there is no simple renumbering that can be done.
1385  mooseAssert(target_it->_grain_index < _feature_sets.size(),
1386  "Error in indexing target grain in attemptGrainRenumber");
1387  FeatureData & target_grain = _feature_sets[target_it->_grain_index];
1388 
1396  if (target_it->_distance < -1)
1397  return false;
1398 
1399  // Make sure this grain isn't marked. If it is, we can't recurse here
1400  if ((target_grain._status & Status::MARKED) == Status::MARKED)
1401  return false;
1402 
1408  grain._var_index = target_it->_var_index;
1409  grain._status |= Status::MARKED;
1410  if (attemptGrainRenumber(target_grain, depth + 1, max_depth))
1411  {
1412  // SUCCESS!
1413  if (_verbosity_level > 0)
1414  _console << COLOR_GREEN << "- Depth " << depth << ": Remapping grain #" << grain._id
1415  << " from variable index " << curr_var_index << " to " << target_it->_var_index
1416  << "\n\n"
1417  << COLOR_DEFAULT;
1418 
1419  // Now we need to mark the grain as DIRTY since the recursion succeeded.
1420  grain._status |= Status::DIRTY;
1421  return true;
1422  }
1423  else
1424  // FAILURE, We need to set our var index back after failed recursive step
1425  grain._var_index = curr_var_index;
1426 
1427  // ALWAYS "unmark" (or clear the MARKED status) after recursion so it can be used by other remap
1428  // operations
1429  grain._status &= ~Status::MARKED;
1430  }
1431 

Referenced by GrainTracker::remapGrains().

◆ boundingRegionDistance()

Real GrainTracker::boundingRegionDistance ( std::vector< BoundingBox > &  bboxes1,
std::vector< BoundingBox > &  bboxes2 
) const
protectedinherited

This method returns the minimum periodic distance between two vectors of bounding boxes.

If the bounding boxes overlap the result is always -1.0.

The region that each grain covers is represented by a bounding box large enough to encompassing all the points within that grain. When using periodic boundaries, we may have several discrete "pieces" of a grain each represented by a bounding box. The distance between any two grains is defined as the minimum distance between any pair of boxes, one selected from each grain.

Definition at line 1745 of file GrainTracker.C.

1749 {
1756  auto min_distance = std::numeric_limits<Real>::max();
1757  for (const auto & bbox1 : bboxes1)
1758  {
1759  for (const auto & bbox2 : bboxes2)
1760  {
1761  // AABB squared distance
1762  Real curr_distance = 0.0;
1763  bool boxes_overlap = true;
1764  for (unsigned int dim = 0; dim < LIBMESH_DIM; ++dim)
1765  {
1766  const auto & min1 = bbox1.min()(dim);
1767  const auto & max1 = bbox1.max()(dim);
1768  const auto & min2 = bbox2.min()(dim);
1769  const auto & max2 = bbox2.max()(dim);
1770 
1771  if (min1 > max2)
1772  {
1773  const auto delta = max2 - min1;
1774  curr_distance += delta * delta;
1775  boxes_overlap = false;
1776  }
1777  else if (min2 > max1)
1778  {
1779  const auto delta = max1 - min2;
1780  curr_distance += delta * delta;
1781  boxes_overlap = false;
1782  }
1783  }
1784 
1785  if (boxes_overlap)
1786  return -1.0; /* all overlaps are treated the same */
1787 
1788  if (curr_distance < min_distance)
1789  min_distance = curr_distance;
1790  }
1791  }
1792 

Referenced by GrainTracker::computeMinDistancesFromGrain().

◆ broadcastAndUpdateGrainData()

void GrainTracker::broadcastAndUpdateGrainData ( )
protectedinherited

Broadcast essential Grain information to all processors.

This method is used to get certain attributes like centroids distributed and whether or not a grain intersects a boundary updated.

Definition at line 388 of file GrainTracker.C.

389 {
390  TIME_SECTION(_broadcast_update);
391 
392  std::vector<PartialFeatureData> root_feature_data;
393  std::vector<std::string> send_buffer(1), recv_buffer;
394 
395  if (_is_master)
396  {
397  root_feature_data.reserve(_feature_sets.size());
398 
399  // Populate a subset of the information in a small data structure
400  std::transform(_feature_sets.begin(),
401  _feature_sets.end(),
402  std::back_inserter(root_feature_data),
403  [](FeatureData & feature) {
404  PartialFeatureData partial_feature;
405  partial_feature.boundary_intersection = feature._boundary_intersection;
406  partial_feature.id = feature._id;
407  partial_feature.centroid = feature._centroid;
408  partial_feature.status = feature._status;
409  return partial_feature;
410  });
411 
412  std::ostringstream oss;
413  dataStore(oss, root_feature_data, this);
414  send_buffer[0].assign(oss.str());
415  }
416 
417  // Broadcast the data to all ranks
418  _communicator.broadcast_packed_range((void *)(nullptr),
419  send_buffer.begin(),
420  send_buffer.end(),
421  (void *)(nullptr),
422  std::back_inserter(recv_buffer));
423 
424  // Unpack and update
425  if (!_is_master)
426  {
427  std::istringstream iss;
428  iss.str(recv_buffer[0]);
429  iss.clear();
430 
431  dataLoad(iss, root_feature_data, this);
432 
433  for (const auto & partial_data : root_feature_data)
434  {
435  // See if this processor has a record of this grain
436  if (partial_data.id < _feature_id_to_local_index.size() &&
437  _feature_id_to_local_index[partial_data.id] != invalid_size_t)
438  {
439  auto & grain = _feature_sets[_feature_id_to_local_index[partial_data.id]];
440  grain._boundary_intersection = partial_data.boundary_intersection;
441  grain._centroid = partial_data.centroid;
442  if (partial_data.status == Status::INACTIVE)
443  grain._status = Status::INACTIVE;
444  }
445  }
446  }
447 }

Referenced by GrainTracker::finalize().

◆ buildFeatureIdToLocalIndices()

void FeatureFloodCount::buildFeatureIdToLocalIndices ( unsigned int  max_id)
protectedinherited

This method builds a lookup map for retrieving the right local feature (by index) given a global index or id.

max_id is passed to size the vector properly and may or may not be a globally consistent number. The assumption is that any id that is later queried from this object that is higher simply doesn't exist on the local processor.

Definition at line 665 of file FeatureFloodCount.C.

666 {
667  _feature_id_to_local_index.assign(max_id + 1, invalid_size_t);
668  for (MooseIndex(_feature_sets) feature_index = 0; feature_index < _feature_sets.size();
669  ++feature_index)
670  {
671  if (_feature_sets[feature_index]._status != Status::INACTIVE)
672  {
673  mooseAssert(_feature_sets[feature_index]._id <= max_id,
674  "Feature ID out of range(" << _feature_sets[feature_index]._id << ')');
675  _feature_id_to_local_index[_feature_sets[feature_index]._id] = feature_index;
676  }
677  }
678 }

Referenced by GrainTracker::assignGrains(), FeatureFloodCount::scatterAndUpdateRanks(), and GrainTracker::trackGrains().

◆ buildLocalToGlobalIndices()

void FeatureFloodCount::buildLocalToGlobalIndices ( std::vector< std::size_t > &  local_to_global_all,
std::vector< int > &  counts 
) const
protectedvirtualinherited

This routine populates a stacked vector of local to global indices per rank and the associated count vector for scattering the vector to the ranks.

The individual vectors can be different sizes. The ith vector will be distributed to the ith processor including the master rank. e.g. [ ... n_0 ] [ ... n_1 ] ... [ ... n_m ]

It is intended to be overridden in derived classes.

Definition at line 619 of file FeatureFloodCount.C.

621 {
622  mooseAssert(_is_master, "This method must only be called on the root processor");
623 
624  counts.assign(_n_procs, 0);
625  // Now size the individual counts vectors based on the largest index seen per processor
626  for (const auto & feature : _feature_sets)
627  for (const auto & local_index_pair : feature._orig_ids)
628  {
629  // local_index_pair.first = ranks, local_index_pair.second = local_index
630  mooseAssert(local_index_pair.first < _n_procs, "Processor ID is out of range");
631  if (local_index_pair.second >= static_cast<std::size_t>(counts[local_index_pair.first]))
632  counts[local_index_pair.first] = local_index_pair.second + 1;
633  }
634 
635  // Build the offsets vector
636  unsigned int globalsize = 0;
637  std::vector<int> offsets(_n_procs); // Type is signed for use with the MPI API
638  for (MooseIndex(offsets) i = 0; i < offsets.size(); ++i)
639  {
640  offsets[i] = globalsize;
641  globalsize += counts[i];
642  }
643 
644  // Finally populate the master vector
645  local_to_global_all.resize(globalsize, FeatureFloodCount::invalid_size_t);
646  for (const auto & feature : _feature_sets)
647  {
648  // Get the local indices from the feature and build a map
649  for (const auto & local_index_pair : feature._orig_ids)
650  {
651  auto rank = local_index_pair.first;
652  mooseAssert(rank < _n_procs, rank << ", " << _n_procs);
653 
654  auto local_index = local_index_pair.second;
655  auto stacked_local_index = offsets[rank] + local_index;
656 
657  mooseAssert(stacked_local_index < globalsize,
658  "Global index: " << stacked_local_index << " is out of range");
659  local_to_global_all[stacked_local_index] = feature._id;
660  }
661  }
662 }

Referenced by FeatureFloodCount::scatterAndUpdateRanks().

◆ centroidRegionDistance()

Real GrainTracker::centroidRegionDistance ( std::vector< BoundingBox > &  bboxes1,
std::vector< BoundingBox > &  bboxes2 
) const
protectedinherited

This method returns the minimum periodic distance between the centroids of two vectors of bounding boxes.

Find the minimum centroid distance between any to pieces of the grains.

Definition at line 1718 of file GrainTracker.C.

1722 {
1726  auto min_distance = std::numeric_limits<Real>::max();
1727  for (const auto & bbox1 : bboxes1)
1728  {
1729  const auto centroid_point1 = (bbox1.max() + bbox1.min()) / 2.0;
1730 
1731  for (const auto & bbox2 : bboxes2)
1732  {
1733  const auto centroid_point2 = (bbox2.max() + bbox2.min()) / 2.0;
1734 
1735  // Here we'll calculate a distance between the centroids
1736  auto curr_distance = _mesh.minPeriodicDistance(_var_number, centroid_point1, centroid_point2);
1737 
1738  if (curr_distance < min_distance)
1739  min_distance = curr_distance;
1740  }
1741  }
1742 

Referenced by GrainTracker::trackGrains().

◆ clearDataStructures()

void FeatureFloodCount::clearDataStructures ( )
protectedvirtualinherited

Helper routine for clearing up data structures during initialize and prior to parallel communication.

Definition at line 330 of file FeatureFloodCount.C.

331 {
332 }

Referenced by FeatureFloodCount::communicateAndMerge().

◆ communicateAndMerge()

void FeatureFloodCount::communicateAndMerge ( )
protectedinherited

This routine handles all of the serialization, communication and deserialization of the data structures containing FeatureData objects.

The libMesh packed range routines handle the communication of the individual string buffers. Here we need to create a container to hold our type to serialize. It'll always be size one because we are sending a single byte stream of all the data to other processors. The stream need not be the same size on all processors.

Additionally we need to create a different container to hold the received byte buffers. The container type need not match the send container type. However, We do know the number of incoming buffers (num processors) so we'll go ahead and use a vector.

When we distribute merge work, we are reducing computational work by adding more communication. Each of the first _n_vars processors will receive one variable worth of information to merge. After each of those processors has merged that information, it'll be sent to the master processor where final consolidation will occur.

Send the data from all processors to the first _n_vars processors to create a complete global feature maps for each variable.

A call to gather_packed_range seems to populate the receiving buffer on all processors, not just the receiving buffer on the actual receiving processor. If we plan to call this function repeatedly, we must clear the buffers each time on all non-receiving processors. On the actual receiving processor, we'll save off the buffer for use later.

The FeatureFloodCount and derived algorithms rely on having the data structures intact on all non-zero ranks. This is because local-only information (local entities) is never communicated and thus must remain intact. However, the distributed merging will destroy that information. The easiest thing to do is to swap out the data structure while we perform the distributed merge work.

Send the data from the merging processors to the root to create a complete global feature map.

Send the data from all processors to the root to create a complete global feature map.

Definition at line 412 of file FeatureFloodCount.C.

413 {
414  TIME_SECTION(_comm_and_merge);
415 
416  // First we need to transform the raw data into a usable data structure
418 
426  std::vector<std::string> send_buffers(1);
427 
434  std::vector<std::string> recv_buffers, deserialize_buffers;
435 
443  {
444  auto rank = processor_id();
445  bool is_merging_processor = rank < _n_vars;
446 
447  if (is_merging_processor)
448  recv_buffers.reserve(_app.n_processors());
449 
450  for (MooseIndex(_n_vars) i = 0; i < _n_vars; ++i)
451  {
452  serialize(send_buffers[0], i);
453 
458  _communicator.gather_packed_range(i,
459  (void *)(nullptr),
460  send_buffers.begin(),
461  send_buffers.end(),
462  std::back_inserter(recv_buffers));
463 
470  if (rank == i)
471  recv_buffers.swap(deserialize_buffers);
472  else
473  recv_buffers.clear();
474  }
475 
476  // Setup a new communicator for doing merging communication operations
477  Parallel::Communicator merge_comm;
478 
479  // TODO: Update to MPI_UNDEFINED when libMesh bug is fixed.
480  _communicator.split(is_merging_processor ? 0 : 1, rank, merge_comm);
481 
482  if (is_merging_processor)
483  {
491  std::vector<std::list<FeatureData>> tmp_data(_partial_feature_sets.size());
492  tmp_data.swap(_partial_feature_sets);
493 
494  deserialize(deserialize_buffers, processor_id());
495 
496  send_buffers[0].clear();
497  recv_buffers.clear();
498  deserialize_buffers.clear();
499 
500  // Merge one variable's worth of data
501  mergeSets();
502 
503  // Now we need to serialize again to send to the master (only the processors who did work)
504  serialize(send_buffers[0]);
505 
506  // Free up as much memory as possible here before we do global communication
508 
513  merge_comm.gather_packed_range(0,
514  (void *)(nullptr),
515  send_buffers.begin(),
516  send_buffers.end(),
517  std::back_inserter(recv_buffers));
518 
519  if (_is_master)
520  {
521  // The root process now needs to deserialize all of the data
522  deserialize(recv_buffers);
523 
524  send_buffers[0].clear();
525  recv_buffers.clear();
526 
527  consolidateMergedFeatures(&tmp_data);
528  }
529  else
530  // Restore our original data on non-zero ranks
531  tmp_data.swap(_partial_feature_sets);
532  }
533  }
534 
535  // Serialized merging (master does all the work)
536  else
537  {
538  if (_is_master)
539  recv_buffers.reserve(_app.n_processors());
540 
541  serialize(send_buffers[0]);
542 
543  // Free up as much memory as possible here before we do global communication
545 
550  _communicator.gather_packed_range(0,
551  (void *)(nullptr),
552  send_buffers.begin(),
553  send_buffers.end(),
554  std::back_inserter(recv_buffers));
555 
556  if (_is_master)
557  {
558  // The root process now needs to deserialize all of the data
559  deserialize(recv_buffers);
560  recv_buffers.clear();
561 
562  mergeSets();
563 
565  }
566  }
567 
568  // Make sure that feature count is communicated to all ranks
569  _communicator.broadcast(_feature_count);
570 }

Referenced by GrainTracker::finalize(), and FeatureFloodCount::finalize().

◆ communicateHaloMap()

void GrainTracker::communicateHaloMap ( )
protectedinherited

Finally remove halo markings from interior regions. This step is necessary because we expand halos before we do communication but that expansion can and will likely go into the interior of the grain (from a single processor's perspective). We could expand halos after merging, but that would likely be less scalable.

Definition at line 1632 of file GrainTracker.C.

1635 {
1636  if (_compute_halo_maps)
1637  {
1638  // rank var_index entity_id
1639  std::vector<std::pair<std::size_t, dof_id_type>> halo_ids_all;
1640 
1641  std::vector<int> counts;
1642  std::vector<std::pair<std::size_t, dof_id_type>> local_halo_ids;
1643  std::size_t counter = 0;
1644 
1645  const bool isDistributedMesh = _mesh.isDistributedMesh();
1646 
1647  if (_is_master)
1648  {
1649  std::vector<std::vector<std::pair<std::size_t, dof_id_type>>> root_halo_ids(_n_procs);
1650  counts.resize(_n_procs);
1651 
1652  // Loop over the _halo_ids "field" and build minimal lists for all of the other ranks
1653  for (MooseIndex(_halo_ids) var_index = 0; var_index < _halo_ids.size(); ++var_index)
1654  {
1655  for (const auto & entity_pair : _halo_ids[var_index])
1656  {
1657  auto entity_id = entity_pair.first;
1658  if (isDistributedMesh)
1659  {
1660  // Check to see which contiguous range this entity ID falls into
1661  auto range_it =
1662  std::lower_bound(_all_ranges.begin(),
1663  _all_ranges.end(),
1664  entity_id,
1665  [](const std::pair<dof_id_type, dof_id_type> range,
1666  dof_id_type entity_id) { return range.second < entity_id; });
1667 
1668  mooseAssert(range_it != _all_ranges.end(), "No range round?");
1669 
1670  // Recover the index from the iterator
1671  auto proc_id = std::distance(_all_ranges.begin(), range_it);
1672 
1673  // Now add this halo entity to the map for the corresponding proc to scatter latter
1674  root_halo_ids[proc_id].push_back(std::make_pair(var_index, entity_id));
1675  }
1676  else
1677  {
1678  DofObject * halo_entity;
1679  if (_is_elemental)
1680  halo_entity = _mesh.queryElemPtr(entity_id);
1681  else
1682  halo_entity = _mesh.queryNodePtr(entity_id);
1683 
1684  if (halo_entity)
1685  root_halo_ids[halo_entity->processor_id()].push_back(
1686  std::make_pair(var_index, entity_id));
1687  }
1688  }
1689  }
1690 
1691  // Build up the counts vector for MPI scatter
1692  std::size_t global_count = 0;
1693  for (const auto & vector_ref : root_halo_ids)
1694  {
1695  std::copy(vector_ref.begin(), vector_ref.end(), std::back_inserter(halo_ids_all));
1696  counts[counter] = vector_ref.size();
1697  global_count += counts[counter++];
1698  }
1699  }
1700 
1701  _communicator.scatter(halo_ids_all, counts, local_halo_ids);
1702 
1703  // Now add the contributions from the root process to the processor local maps
1704  for (const auto & halo_pair : local_halo_ids)
1705  _halo_ids[halo_pair.first].emplace(std::make_pair(halo_pair.second, halo_pair.first));
1706 
1713  for (const auto & grain : _feature_sets)
1714  for (auto local_id : grain._local_ids)
1715  _halo_ids[grain._var_index].erase(local_id);

Referenced by GrainTracker::updateFieldInfo().

◆ compareValueWithThreshold()

bool FeatureFloodCount::compareValueWithThreshold ( Real  entity_value,
Real  threshold 
) const
protectedinherited

This method is used to determine whether the current entity value is part of a feature or not.

Comparisons can either be greater than or less than the threshold which is controlled via input parameter.

Definition at line 1418 of file FeatureFloodCount.C.

1419 {
1420  return ((_use_less_than_threshold_comparison && (entity_value >= threshold)) ||
1421  (!_use_less_than_threshold_comparison && (entity_value <= threshold)));
1422 }

Referenced by FeatureFloodCount::isNewFeatureOrConnectedRegion().

◆ computeMinDistancesFromGrain()

void GrainTracker::computeMinDistancesFromGrain ( FeatureData grain,
std::vector< std::list< GrainDistance >> &  min_distances 
)
protectedinherited

Populates and sorts a min_distances vector with the minimum distances to all grains in the simulation for a given grain.

There are _vars.size() entries in the outer vector, one for each order parameter. A list of grains with the same OP are ordered in lists per OP.

In the diagram below assume we have 4 order parameters. The grain with the asterisk needs to be remapped. All order parameters are used in neighboring grains. For all "touching" grains, the value of the corresponding entry in min_distances will be a negative integer representing the number of immediate neighbors with that order parameter.

Note: Only the first member of the pair (the distance) is shown in the array below. e.g. [-2.0, -max, -1.0, -2.0]

After sorting, variable index 2 (value: -1.0) be at the end of the array and will be the first variable we attempt to renumber the current grain to.

   __       ___
     \  0  /   \
   2  \___/  1  \___
      /   \     /   \
   __/  1  \___/  2  \
     \  *  /   \     /
   3  \___/  3  \___/
      /   \     /
   __/  0  \___/

See if we have any completely open OPs (excluding reserve order parameters) or the order parameter corresponding to this grain, we need to put them in the list or the grain tracker won't realize that those vars are available for remapping.

Definition at line 1185 of file GrainTracker.C.

1189 {
1213  for (MooseIndex(_feature_sets) i = 0; i < _feature_sets.size(); ++i)
1214  {
1215  auto & other_grain = _feature_sets[i];
1216 
1217  if (other_grain._var_index == grain._var_index || other_grain._var_index >= _reserve_op_index)
1218  continue;
1219 
1220  auto target_var_index = other_grain._var_index;
1221  auto target_grain_index = i;
1222  auto target_grain_id = other_grain._id;
1223 
1224  Real curr_bbox_diff = boundingRegionDistance(grain._bboxes, other_grain._bboxes);
1225 
1226  GrainDistance grain_distance_obj(
1227  curr_bbox_diff, target_var_index, target_grain_index, target_grain_id);
1228 
1229  // To handle touching halos we penalize the top pick each time we see another
1230  if (curr_bbox_diff == -1.0 && !min_distances[target_var_index].empty())
1231  {
1232  Real last_distance = min_distances[target_var_index].begin()->_distance;
1233  if (last_distance < 0)
1234  grain_distance_obj._distance += last_distance;
1235  }
1236 
1237  // Insertion sort into a list
1238  auto insert_it = min_distances[target_var_index].begin();
1239  while (insert_it != min_distances[target_var_index].end() && !(grain_distance_obj < *insert_it))
1240  ++insert_it;
1241  min_distances[target_var_index].insert(insert_it, grain_distance_obj);
1242  }
1243 
1249  for (MooseIndex(_vars) var_index = 0; var_index < _reserve_op_index; ++var_index)
1250  {
1251  // Don't put an entry in for matching variable indices (i.e. we can't remap to ourselves)
1252  if (grain._var_index == var_index)
1253  continue;
1254 
1255  if (min_distances[var_index].empty())
1256  min_distances[var_index].emplace_front(std::numeric_limits<Real>::max(), var_index);

Referenced by GrainTracker::attemptGrainRenumber().

◆ consolidateMergedFeatures()

void FeatureFloodCount::consolidateMergedFeatures ( std::vector< std::list< FeatureData >> *  saved_data = nullptr)
privateinherited

This method consolidates all of the merged information from _partial_feature_sets into the _feature_sets vectors.

Now that the merges are complete we need to adjust the centroid, and halos. Additionally, To make several of the sorting and tracking algorithms more straightforward, we will move the features into a flat vector. Finally we can count the final number of features and find the max local index seen on any processor Note: This is all occurring on rank 0 only!

IMPORTANT: FeatureFloodCount::_feature_count is set on rank 0 at this point but we can't broadcast it here because this routine is not collective.

Definition at line 1176 of file FeatureFloodCount.C.

1177 {
1178  TIME_SECTION(_consolidate_merged_features);
1179 
1187  mooseAssert(_is_master, "cosolidateMergedFeatures() may only be called on the master processor");
1188 
1189  // Offset where the current set of features with the same variable id starts in the flat vector
1190  unsigned int feature_offset = 0;
1191  // Set the member feature count to zero and start counting the actual features
1192  _feature_count = 0;
1193 
1194  for (MooseIndex(_maps_size) map_num = 0; map_num < _maps_size; ++map_num)
1195  {
1196  for (auto & feature : _partial_feature_sets[map_num])
1197  {
1198  if (saved_data)
1199  {
1200  for (auto it = (*saved_data)[map_num].begin(); it != (*saved_data)[map_num].end();
1201  /* no increment */)
1202  {
1203  if (feature.canConsolidate(*it))
1204  {
1205  feature.consolidate(std::move(*it));
1206  it = (*saved_data)[map_num].erase(it); // increment
1207  }
1208  else
1209  ++it;
1210  }
1211  }
1212 
1213  // If after merging we still have an inactive feature, discard it
1214  if (feature._status == Status::CLEAR)
1215  {
1216  // First we need to calculate the centroid now that we are doing merging all partial
1217  // features
1218  if (feature._vol_count != 0)
1219  feature._centroid /= feature._vol_count;
1220 
1221  _feature_sets.emplace_back(std::move(feature));
1222  ++_feature_count;
1223  }
1224  }
1225 
1226  // Record the feature numbers just for the current map
1227  _feature_counts_per_map[map_num] = _feature_count - feature_offset;
1228 
1229  // Now update the running feature count so we can calculate the next map's contribution
1230  feature_offset = _feature_count;
1231 
1232  // Clean up the "moved" objects
1233  _partial_feature_sets[map_num].clear();
1234  }
1235 
1240 }

Referenced by FeatureFloodCount::communicateAndMerge().

◆ deserialize()

void FeatureFloodCount::deserialize ( std::vector< std::string > &  serialized_buffers,
unsigned int  var_num = invalid_id 
)
protectedinherited

This routine takes the vector of byte buffers (one for each processor), deserializes them into a series of FeatureSet objects, and appends them to the _feature_sets data structure.

Note: It is assumed that local processor information may already be stored in the _feature_sets data structure so it is not cleared before insertion.

Usually we have the local processor data already in the _partial_feature_sets data structure. However, if we are doing distributed merge work, we also need to preserve all of the original data for use in later stages of the algorithm so it'll have been swapped out with clean buffers. This leaves us a choice, either we just duplicate the Features from the original data structure after we've swapped out the buffer, or we go ahead and unpack data that we would normally already have. So during distributed merging, that's exactly what we'll do. Later however when the master is doing the final consolidating, we'll opt to just skip the local unpacking. To tell the difference, between these two modes, we just need to see if a var_num was passed in.

Definition at line 1086 of file FeatureFloodCount.C.

1087 {
1088  // The input string stream used for deserialization
1089  std::istringstream iss;
1090 
1091  auto rank = processor_id();
1092 
1093  for (MooseIndex(serialized_buffers) proc_id = 0; proc_id < serialized_buffers.size(); ++proc_id)
1094  {
1106  if (var_num == invalid_id && proc_id == rank)
1107  continue;
1108 
1109  iss.str(serialized_buffers[proc_id]); // populate the stream with a new buffer
1110  iss.clear(); // reset the string stream state
1111 
1112  // Load the gathered data into the data structure.
1113  if (var_num == invalid_id)
1114  dataLoad(iss, _partial_feature_sets, this);
1115  else
1116  dataLoad(iss, _partial_feature_sets[var_num], this);
1117  }
1118 }

Referenced by FeatureFloodCount::communicateAndMerge().

◆ doesFeatureIntersectBoundary()

bool GrainTracker::doesFeatureIntersectBoundary ( unsigned int  feature_id) const
overridevirtualinherited

Returns a Boolean indicating whether this feature intersects any boundary.

Reimplemented from FeatureFloodCount.

Definition at line 175 of file GrainTracker.C.

176 {
177  // TODO: This data structure may need to be turned into a Multimap
178  mooseAssert(feature_id < _feature_id_to_local_index.size(), "Grain ID out of bounds");
179 
180  auto feature_index = _feature_id_to_local_index[feature_id];
181  if (feature_index != invalid_size_t)
182  {
183  mooseAssert(feature_index < _feature_sets.size(), "Grain index out of bounds");
184  return _feature_sets[feature_index]._boundary_intersection != BoundaryIntersection::NONE;
185  }
186 
187  return false;
188 }

◆ doesFeatureIntersectSpecifiedBoundary()

bool GrainTracker::doesFeatureIntersectSpecifiedBoundary ( unsigned int  feature_id) const
overridevirtualinherited

Returns a Boolean indicating whether this feature intersects boundaries in a user-supplied list.

Reimplemented from FeatureFloodCount.

Definition at line 191 of file GrainTracker.C.

192 {
193  // TODO: This data structure may need to be turned into a Multimap
194  mooseAssert(feature_id < _feature_id_to_local_index.size(), "Grain ID out of bounds");
195 
196  auto feature_index = _feature_id_to_local_index[feature_id];
197  if (feature_index != invalid_size_t)
198  {
199  mooseAssert(feature_index < _feature_sets.size(), "Grain index out of bounds");
200  return ((_feature_sets[feature_index]._boundary_intersection &
202  }
203 
204  return false;
205 }

◆ execute()

void GrainTracker::execute ( )
overridevirtualinherited

Reimplemented from FeatureFloodCount.

Definition at line 273 of file GrainTracker.C.

274 {
275  // Don't track grains if the current simulation step is before the specified tracking step
276  if (_t_step < _tracking_step)
277  return;
278 
279  if (_poly_ic_uo && _first_time)
280  return;
281 
283 }

◆ expandEdgeHalos()

void FeatureFloodCount::expandEdgeHalos ( unsigned int  num_layers_to_expand)
protectedinherited

This method expands the existing halo set by some width determined by the passed in value.

This method does NOT mask off any local IDs.

Create a copy of the halo set so that as we insert new ids into the set we don't continue to iterate on those new ids.

We have to handle disjoint halo IDs slightly differently. Once you are disjoint, you can't go back so make sure that we keep placing these IDs in the disjoint set.

Definition at line 1527 of file FeatureFloodCount.C.

1528 {
1529  if (num_layers_to_expand == 0)
1530  return;
1531 
1532  TIME_SECTION(_expand_halos);
1533 
1534  for (auto & list_ref : _partial_feature_sets)
1535  {
1536  for (auto & feature : list_ref)
1537  {
1538  for (MooseIndex(num_layers_to_expand) halo_level = 0; halo_level < num_layers_to_expand;
1539  ++halo_level)
1540  {
1545  FeatureData::container_type orig_halo_ids(feature._halo_ids);
1546  for (auto entity : orig_halo_ids)
1547  {
1548  if (_is_elemental)
1549  visitElementalNeighbors(_mesh.elemPtr(entity),
1550  &feature,
1551  /*expand_halos_only =*/true,
1552  /*disjoint_only =*/false);
1553  else
1554  visitNodalNeighbors(_mesh.nodePtr(entity),
1555  &feature,
1556  /*expand_halos_only =*/true);
1557  }
1558 
1563  FeatureData::container_type disjoint_orig_halo_ids(feature._disjoint_halo_ids);
1564  for (auto entity : disjoint_orig_halo_ids)
1565  {
1566  if (_is_elemental)
1567  visitElementalNeighbors(_mesh.elemPtr(entity),
1568 
1569  &feature,
1570  /*expand_halos_only =*/true,
1571  /*disjoint_only =*/true);
1572  else
1573  visitNodalNeighbors(_mesh.nodePtr(entity),
1574 
1575  &feature,
1576  /*expand_halos_only =*/true);
1577  }
1578  }
1579  }
1580  }
1581 }

Referenced by GrainTracker::finalize(), and PolycrystalUserObjectBase::finalize().

◆ expandPointHalos()

void FeatureFloodCount::expandPointHalos ( )
protectedinherited

This method takes all of the partial features and expands the local, ghosted, and halo sets around those regions to account for the diffuse interface.

Rather than using any kind of recursion here, we simply expand the region by all "point" neighbors from the actual grain cells since all point neighbors will contain contributions to the region.

To expand the feature element region to the actual flooded region (nodal basis) we need to add in all point neighbors of the current local region for each feature. This is because the elemental variable influence spreads from the elemental data out exactly one element from every mesh point.

Definition at line 1465 of file FeatureFloodCount.C.

1466 {
1467  const auto & node_to_elem_map = _mesh.nodeToActiveSemilocalElemMap();
1468  FeatureData::container_type expanded_local_ids;
1469  auto my_processor_id = processor_id();
1470 
1477  for (auto & list_ref : _partial_feature_sets)
1478  {
1479  for (auto & feature : list_ref)
1480  {
1481  expanded_local_ids.clear();
1482 
1483  for (auto entity : feature._local_ids)
1484  {
1485  const Elem * elem = _mesh.elemPtr(entity);
1486  mooseAssert(elem, "elem pointer is NULL");
1487 
1488  // Get the nodes on a current element so that we can add in point neighbors
1489  auto n_nodes = elem->n_vertices();
1490  for (MooseIndex(n_nodes) i = 0; i < n_nodes; ++i)
1491  {
1492  const Node * current_node = elem->node_ptr(i);
1493 
1494  auto elem_vector_it = node_to_elem_map.find(current_node->id());
1495  if (elem_vector_it == node_to_elem_map.end())
1496  mooseError("Error in node to elem map");
1497 
1498  const auto & elem_vector = elem_vector_it->second;
1499 
1500  std::copy(elem_vector.begin(),
1501  elem_vector.end(),
1502  std::insert_iterator<FeatureData::container_type>(expanded_local_ids,
1503  expanded_local_ids.end()));
1504 
1505  // Now see which elements need to go into the ghosted set
1506  for (auto entity : elem_vector)
1507  {
1508  const Elem * neighbor = _mesh.elemPtr(entity);
1509  mooseAssert(neighbor, "neighbor pointer is NULL");
1510 
1511  if (neighbor->processor_id() != my_processor_id)
1512  feature._ghosted_ids.insert(feature._ghosted_ids.end(), elem->id());
1513  }
1514  }
1515  }
1516 
1517  // Replace the existing local ids with the expanded local ids
1518  feature._local_ids.swap(expanded_local_ids);
1519 
1520  // Copy the expanded local_ids into the halo_ids container
1521  feature._halo_ids = feature._local_ids;
1522  }
1523  }
1524 }

◆ featureCentroid()

Point FeatureFloodCount::featureCentroid ( unsigned int  feature_id) const
virtualinherited

Returns the centroid of the designated feature (only supported without periodic boundaries)

Definition at line 900 of file FeatureFloodCount.C.

901 {
902  if (feature_id >= _feature_id_to_local_index.size())
903  return invalid_id;
904 
905  auto local_index = _feature_id_to_local_index[feature_id];
906 
907  Real invalid_coord = std::numeric_limits<Real>::max();
908  Point p(invalid_coord, invalid_coord, invalid_coord);
909  if (local_index != invalid_size_t)
910  {
911  mooseAssert(local_index < _feature_sets.size(), "local_index out of bounds");
912  p = _feature_sets[local_index]._centroid;
913  }
914  return p;
915 }

Referenced by FeatureVolumeVectorPostprocessor::execute().

◆ finalize()

void GrainTracker::finalize ( )
overridevirtualinherited

Assign or Track Grains

Broadcast essential data

Remap Grains

Reimplemented from FeatureFloodCount.

Definition at line 330 of file GrainTracker.C.

331 {
332  // Don't track grains if the current simulation step is before the specified tracking step
333  if (_t_step < _tracking_step)
334  return;
335 
336  TIME_SECTION(_finalize_timer);
337 
338  // Expand the depth of the halos around all grains
339  auto num_halo_layers = _halo_level >= 1
340  ? _halo_level - 1
341  : 0; // The first level of halos already exists so subtract one
342 
343  if (_poly_ic_uo && _first_time)
345  else
346  {
347  expandEdgeHalos(num_halo_layers);
348 
349  // Build up the grain map on the root processor
351  }
352 
356  if (_first_time)
357  assignGrains();
358  else
359  trackGrains();
360 
361  if (_verbosity_level > 1)
362  _console << "Finished inside of trackGrains" << std::endl;
363 
368 
372  if (_remap)
373  remapGrains();
374 
375  updateFieldInfo();
376  if (_verbosity_level > 1)
377  _console << "Finished inside of updateFieldInfo\n";
378 
379  // Set the first time flag false here (after all methods of finalize() have completed)
380  _first_time = false;
381 
382  // TODO: Release non essential memory
383  if (_verbosity_level > 0)
384  _console << "Finished inside of GrainTracker\n" << std::endl;
385 }

◆ flood()

bool FeatureFloodCount::flood ( const DofObject *  dof_object,
std::size_t  current_index 
)
protectedinherited

This method will check if the current entity is above the supplied threshold and "mark" it.

It will then inspect neighboring entities that are above the connecting threshold and add them to the current feature.

Returns
Boolean indicating whether a new feature was found while exploring the current entity.

If we reach this point (i.e. we haven't continued to the next queue entry), we've found a new mesh entity that's part of a feature. We need to mark the entity as visited at this point (and not before!) to avoid infinite recursion. If you mark the node too early you risk not coloring in a whole feature any time a "connecting threshold" is used since we may have already visited this entity earlier but it was in-between two thresholds.

See if this particular entity cell contributes to the centroid calculation. We only deal with elemental floods and only count it if it's owned by the current processor to avoid skewing the result.

Definition at line 1294 of file FeatureFloodCount.C.

1296 {
1297  // if (dof_object == nullptr || dof_object == libMesh::remote_elem)
1298  // return false;
1299  mooseAssert(dof_object, "DOF object is nullptr");
1300  mooseAssert(_entity_queue.empty(), "Entity queue is not empty when starting a feature");
1301 
1302  // Kick off the exploration of a new feature
1303  _entity_queue.push_front(dof_object);
1304 
1305  bool return_value = false;
1306  FeatureData * feature = nullptr;
1307  while (!_entity_queue.empty())
1308  {
1309  const DofObject * curr_dof_object = _entity_queue.back();
1310  const Elem * elem = _is_elemental ? static_cast<const Elem *>(curr_dof_object) : nullptr;
1311  _entity_queue.pop_back();
1312 
1313  // Retrieve the id of the current entity
1314  auto entity_id = curr_dof_object->id();
1315 
1316  // Has this entity already been marked? - if so move along
1317  if (current_index != invalid_size_t &&
1318  _entities_visited[current_index].find(entity_id) != _entities_visited[current_index].end())
1319  continue;
1320 
1321  // Are we outside of the range we should be working in?
1322  if (_is_elemental && !_dof_map.is_evaluable(*elem))
1323  continue;
1324 
1325  // See if the current entity either starts a new feature or continues an existing feature
1326  auto new_id = invalid_id; // Writable reference to hold an optional id;
1327  Status status =
1328  Status::INACTIVE; // Status is inactive until we find an entity above the starting threshold
1329 
1330  // Make sure that the Assembly object has the right element and subdomain information set
1331  // since we are moving through the mesh in a manual fashion.
1332  if (_is_elemental)
1333  _fe_problem.setCurrentSubdomainID(elem, 0);
1334 
1335  if (!isNewFeatureOrConnectedRegion(curr_dof_object, current_index, feature, status, new_id))
1336  {
1337  // If we have an active feature, we just found a halo entity
1338  if (feature)
1339  feature->_halo_ids.insert(feature->_halo_ids.end(), entity_id);
1340  continue;
1341  }
1342 
1343  mooseAssert(current_index != invalid_size_t, "current_index is invalid");
1344 
1353  return_value = true;
1354  _entities_visited[current_index].insert(entity_id);
1355 
1356  auto map_num = _single_map_mode ? decltype(current_index)(0) : current_index;
1357 
1358  // New Feature (we need to create it and add it to our data structure)
1359  if (!feature)
1360  {
1361  _partial_feature_sets[map_num].emplace_back(
1362  current_index, _feature_count++, processor_id(), status);
1363 
1364  // Get a handle to the feature we will update (always the last feature in the data structure)
1365  feature = &_partial_feature_sets[map_num].back();
1366 
1367  // If new_id is valid, we'll set it in the feature here.
1368  if (new_id != invalid_id)
1369  feature->_id = new_id;
1370  }
1371 
1372  // Insert the current entity into the local ids data structure
1373  feature->_local_ids.insert(feature->_local_ids.end(), entity_id);
1374 
1380  if (_is_elemental && processor_id() == curr_dof_object->processor_id())
1381  {
1382  // Keep track of how many elements participate in the centroid averaging
1383  feature->_vol_count++;
1384 
1385  // Sum the centroid values for now, we'll average them later
1386  feature->_centroid += elem->centroid();
1387 
1388  // // Does the volume intersect the boundary?
1389  // if (_all_boundary_entity_ids.find(elem->id()) != _all_boundary_entity_ids.end())
1390  // feature->_intersects_boundary = true;
1391  }
1392 
1393  if (_is_elemental)
1395  feature,
1396  /*expand_halos_only =*/false,
1397  /*disjoint_only =*/false);
1398  else
1399  visitNodalNeighbors(static_cast<const Node *>(curr_dof_object),
1400  feature,
1401  /*expand_halos_only =*/false);
1402  }
1403 
1404  return return_value;
1405 }

Referenced by FeatureFloodCount::execute(), and PolycrystalUserObjectBase::execute().

◆ getConnectingThreshold()

Real FeatureFloodCount::getConnectingThreshold ( std::size_t  current_index) const
protectedvirtualinherited

Return the "connecting" comparison threshold to use when inspecting an entity during the flood stage.

Definition at line 1412 of file FeatureFloodCount.C.

1413 {
1415 }

Referenced by FeatureFloodCount::isNewFeatureOrConnectedRegion().

◆ getCoupledVars()

const std::vector<MooseVariable *>& FeatureFloodCount::getCoupledVars ( ) const
inlineinherited

Returns a const vector to the coupled variable pointers.

Definition at line 98 of file FeatureFloodCount.h.

98 { return _vars; }

Referenced by AverageGrainVolume::AverageGrainVolume(), and FeatureVolumeVectorPostprocessor::FeatureVolumeVectorPostprocessor().

◆ getData()

const RankFourTensor & GrainDataTracker< RankFourTensor >::getData ( unsigned int  grain_id) const
inherited

return data for selected grain

Definition at line 44 of file GrainDataTracker.h.

45 {
46  mooseAssert(grain_id < _grain_data.size(), "Requested data for invalid grain index.");
47  return _grain_data[grain_id];
48 }

◆ getEntityValue()

Real GrainTracker::getEntityValue ( dof_id_type  node_id,
FieldType  field_type,
std::size_t  var_index = 0 
) const
overridevirtualinherited

Reimplemented from FeatureFloodCount.

Definition at line 120 of file GrainTracker.C.

123 {
124  if (_t_step < _tracking_step)
125  return 0;
126 
127  return FeatureFloodCount::getEntityValue(entity_id, field_type, var_index);
128 }

Referenced by OutputEulerAngles::precalculateValue().

◆ getFeatures()

const std::vector<FeatureData>& FeatureFloodCount::getFeatures ( ) const
inlineinherited

Return a constant reference to the vector of all discovered features.

Definition at line 340 of file FeatureFloodCount.h.

340 { return _feature_sets; }

Referenced by GrainTracker::prepopulateState().

◆ getFeatureVar()

unsigned int GrainTracker::getFeatureVar ( unsigned int  feature_id) const
overridevirtualinherited

Returns the variable representing the passed in feature.

Reimplemented from FeatureFloodCount.

Definition at line 137 of file GrainTracker.C.

138 {
139  return FeatureFloodCount::getFeatureVar(feature_id);
140 }

◆ getFECoupledVars()

const std::vector<MooseVariableFEBase *>& FeatureFloodCount::getFECoupledVars ( ) const
inlineinherited

Returns a const vector to the coupled MooseVariableFEBase pointers.

Definition at line 101 of file FeatureFloodCount.h.

101 { return _fe_vars; }

Referenced by AverageGrainVolume::AverageGrainVolume().

◆ getGrainCentroid()

Point GrainTracker::getGrainCentroid ( unsigned int  grain_id) const
overridevirtualinherited

Returns the centroid for the given grain number.

Implements GrainTrackerInterface.

Definition at line 157 of file GrainTracker.C.

158 {
159  mooseAssert(grain_id < _feature_id_to_local_index.size(), "Grain ID out of bounds");
160  auto grain_index = _feature_id_to_local_index[grain_id];
161 
162  if (grain_index != invalid_size_t)
163  {
164  mooseAssert(_feature_id_to_local_index[grain_id] < _feature_sets.size(),
165  "Grain index out of bounds");
166  // Note: This value is parallel consistent, see GrainTracker::broadcastAndUpdateGrainData()
167  return _feature_sets[_feature_id_to_local_index[grain_id]]._centroid;
168  }
169 
170  // Inactive grain
171  return Point();
172 }

◆ getNewGrainIDs()

std::vector< unsigned int > GrainTracker::getNewGrainIDs ( ) const
overridevirtualinherited

This method returns all of the new ids generated in an invocation of the GrainTracker.

Reimplemented from GrainTrackerInterface.

Definition at line 901 of file GrainTracker.C.

904 {
905  std::vector<unsigned int> new_ids(_max_curr_grain_id - _old_max_grain_id);
906  auto new_id = _old_max_grain_id + 1;
907 
908  // Generate the new ids
909  std::iota(new_ids.begin(), new_ids.end(), new_id);
910 

◆ getNextUniqueID()

unsigned int GrainTracker::getNextUniqueID ( )
protectedinherited

Retrieve the next unique grain number if a new grain is detected during trackGrains.

This method handles reserve order parameter indices properly. Direct access to the next index should be avoided.

Get the next unique grain ID but make sure to respect reserve ids. Note, that the first valid ID for a new grain is _reserve_grain_first_index + _n_reserve_ops because _reserve_grain_first_index IS a valid index. It does not point to the last valid index of the non-reserved grains.

Definition at line 1795 of file GrainTracker.C.

1798 {
1807  _reserve_grain_first_index + _n_reserve_ops /* no +1 here!*/);
1808 

Referenced by GrainTracker::trackGrains().

◆ getNumberActiveFeatures()

std::size_t FeatureFloodCount::getNumberActiveFeatures ( ) const
inherited

Return the number of active features.

Definition at line 791 of file FeatureFloodCount.C.

792 {
793  // Note: This value is parallel consistent, see FeatureFloodCount::communicateAndMerge()
794  return _feature_count;
795 }

Referenced by AverageGrainVolume::getValue().

◆ getNumberActiveGrains()

std::size_t GrainTracker::getNumberActiveGrains ( ) const
overridevirtualinherited

Returns the number of active grains current stored in the GrainTracker.

This value is the same value reported when the GrainTracker (FeatureFloodObject) is used as a Postprocessor.

Note: This value will count each piece of a split grain (often encountered in EBSD data sets).

Implements GrainTrackerInterface.

Definition at line 143 of file GrainTracker.C.

144 {
145  // Note: This value is parallel consistent, see FeatureFloodCount::communicateAndMerge()
146  return _feature_count;
147 }

◆ getThreshold()

Real GrainTracker::getThreshold ( std::size_t  current_index) const
overrideprotectedvirtualinherited

Return the starting comparison threshold to use when inspecting an entity during the flood stage.

Reimplemented from FeatureFloodCount.

Definition at line 286 of file GrainTracker.C.

287 {
288  // If we are inspecting a reserve op parameter, we need to make sure
289  // that there is an entity above the reserve_op threshold before
290  // starting the flood of the feature.
291  if (var_index >= _reserve_op_index)
292  return _reserve_op_threshold;
293  else
294  return _step_threshold;
295 }

◆ getTotalFeatureCount()

std::size_t GrainTracker::getTotalFeatureCount ( ) const
overridevirtualinherited

Returns the total feature count (active and inactive ids, useful for sizing vectors)

Since the FeatureFloodCount object doesn't maintain any information about features between invocations. The maximum id in use is simply the number of features.

Reimplemented from FeatureFloodCount.

Definition at line 150 of file GrainTracker.C.

151 {
152  // Note: This value is parallel consistent, see assignGrains()/trackGrains()
154 }

◆ getValue()

Real FeatureFloodCount::getValue ( )
overridevirtualinherited

Reimplemented in FauxGrainTracker.

Definition at line 785 of file FeatureFloodCount.C.

786 {
787  return static_cast<Real>(_feature_count);
788 }

◆ getVarToFeatureVector()

const std::vector< unsigned int > & GrainTracker::getVarToFeatureVector ( dof_id_type  elem_id) const
overridevirtualinherited

Returns a list of active unique feature ids for a particular element.

The vector is indexed by variable number with each entry containing either an invalid size_t type (no feature active at that location) or a feature id if the variable is non-zero at that location.

Reimplemented from FeatureFloodCount.

Definition at line 131 of file GrainTracker.C.

132 {
134 }

Referenced by ComputePolycrystalElasticityTensor::computeQpElasticityTensor().

◆ initialize()

void GrainTracker::initialize ( )
overridevirtualinherited

If we are passed the first time, we need to save the existing grains before beginning the tracking on the current step. We'll do that with a swap since the _feature_sets contents will be cleared anyway.

Reimplemented from FeatureFloodCount.

Definition at line 230 of file GrainTracker.C.

231 {
232  // Don't track grains if the current simulation step is before the specified tracking step
233  if (_t_step < _tracking_step)
234  return;
235 
241  if (!_first_time)
243 
245 }

◆ initialSetup()

void FeatureFloodCount::initialSetup ( )
overridevirtualinherited

Size the empty var to features vector to the number of coupled variables. This empty vector (but properly sized) vector is returned for elements that are queried but are not in the structure (which also shouldn't happen). The user is warned in this case but this helps avoid extra bounds checking in user code and avoids segfaults.

Reimplemented in PolycrystalUserObjectBase.

Definition at line 277 of file FeatureFloodCount.C.

278 {
279  // We need one map per coupled variable for normal runs to support overlapping features
280  _entities_visited.resize(_vars.size());
281 
282  // Get a pointer to the PeriodicBoundaries buried in libMesh
283  _pbs = _fe_problem.getNonlinearSystemBase().dofMap().get_periodic_boundaries();
284 
285  meshChanged();
286 
295 }

Referenced by PolycrystalUserObjectBase::initialSetup().

◆ isBoundaryEntity()

template<typename T >
bool FeatureFloodCount::isBoundaryEntity ( const T *  entity) const
protectedinherited

Returns a Boolean indicating whether the entity is on one of the desired boundaries.

Definition at line 1810 of file FeatureFloodCount.C.

1811 {
1812  mooseAssert(_bnd_elem_range, "Boundary Element Range is nullptr");
1813 
1814  if (entity)
1815  for (const auto & belem : *_bnd_elem_range)
1816  // Only works for Elements
1817  if (belem->_elem->id() == entity->id() && hasBoundary(belem->_bnd_id))
1818  return true;
1819 
1820  return false;
1821 }

Referenced by FeatureFloodCount::visitNeighborsHelper().

◆ isElemental()

bool FeatureFloodCount::isElemental ( ) const
inlineinherited

Definition at line 117 of file FeatureFloodCount.h.

117 { return _is_elemental; }

Referenced by FeatureFloodCountAux::FeatureFloodCountAux().

◆ isFeaturePercolated()

bool GrainTracker::isFeaturePercolated ( unsigned int  feature_id) const
overridevirtualinherited

Returns a Boolean indicating whether this feature is percolated (e.g.

intersects at least two different boundaries from sets supplied by the user)

Reimplemented from FeatureFloodCount.

Definition at line 208 of file GrainTracker.C.

209 {
210  // TODO: This data structure may need to be turned into a Multimap
211  mooseAssert(feature_id < _feature_id_to_local_index.size(), "Grain ID out of bounds");
212 
213  auto feature_index = _feature_id_to_local_index[feature_id];
214  if (feature_index != invalid_size_t)
215  {
216  mooseAssert(feature_index < _feature_sets.size(), "Grain index out of bounds");
217  bool primary = ((_feature_sets[feature_index]._boundary_intersection &
220  bool secondary = ((_feature_sets[feature_index]._boundary_intersection &
223  return (primary && secondary);
224  }
225 
226  return false;
227 }

◆ isNewFeatureOrConnectedRegion()

bool FeatureFloodCount::isNewFeatureOrConnectedRegion ( const DofObject *  dof_object,
std::size_t &  current_index,
FeatureData *&  feature,
Status status,
unsigned int &  new_id 
)
protectedvirtualinherited

Method called during the recursive flood routine that should return whether or not the current entity is part of the current feature (if one is being explored), or if it's the start of a new feature.

If the value is only above the connecting threshold, it's still part of a feature but possibly part of one that we'll discard if there is never any starting threshold encountered.

Reimplemented in PolycrystalUserObjectBase.

Definition at line 1425 of file FeatureFloodCount.C.

1430 {
1431  // Get the value of the current variable for the current entity
1432  Real entity_value;
1433  if (_is_elemental)
1434  {
1435  const Elem * elem = static_cast<const Elem *>(dof_object);
1436  std::vector<Point> centroid(1, elem->centroid());
1437  _subproblem.reinitElemPhys(elem, centroid, 0, /* suppress_displaced_init = */ true);
1438  entity_value = _vars[current_index]->sln()[0];
1439  }
1440  else
1441  entity_value = _vars[current_index]->getNodalValue(*static_cast<const Node *>(dof_object));
1442 
1443  // If the value compares against our starting threshold, this is definitely part of a feature
1444  // we'll keep
1445  if (compareValueWithThreshold(entity_value, getThreshold(current_index)))
1446  {
1447  Status * status_ptr = &status;
1448 
1449  if (feature)
1450  status_ptr = &feature->_status;
1451 
1452  // Update an existing feature's status or clear the flag on the passed in status
1453  *status_ptr &= ~Status::INACTIVE;
1454  return true;
1455  }
1456 
1461  return compareValueWithThreshold(entity_value, getConnectingThreshold(current_index));
1462 }

Referenced by FeatureFloodCount::flood().

◆ mergeSets()

void FeatureFloodCount::mergeSets ( )
protectedvirtualinherited

This routine is called on the master rank only and stitches together the partial feature pieces seen on any processor.

Insert the new entity at the end of the list so that it may be checked against all other partial features again.

Now remove both halves the merged features: it2 contains the "moved" feature cell just inserted at the back of the list, it1 contains the mostly empty other half. We have to be careful about the order in which these two elements are deleted. We delete it2 first since we don't care where its iterator points after the deletion. We are going to break out of this loop anyway. If we delete it1 first, it may end up pointing at the same location as it2 which after the second deletion would cause both of the iterators to be invalidated.

Reimplemented in PolycrystalUserObjectBase.

Definition at line 1121 of file FeatureFloodCount.C.

1122 {
1123  TIME_SECTION(_merge_timer);
1124 
1125  // When working with _distribute_merge_work all of the maps will be empty except for one
1126  for (MooseIndex(_maps_size) map_num = 0; map_num < _maps_size; ++map_num)
1127  {
1128  for (auto it1 = _partial_feature_sets[map_num].begin();
1129  it1 != _partial_feature_sets[map_num].end();
1130  /* No increment on it1 */)
1131  {
1132  bool merge_occured = false;
1133  for (auto it2 = _partial_feature_sets[map_num].begin();
1134  it2 != _partial_feature_sets[map_num].end();
1135  ++it2)
1136  {
1137  if (it1 != it2 && areFeaturesMergeable(*it1, *it2))
1138  {
1139  it2->merge(std::move(*it1));
1140 
1145  _partial_feature_sets[map_num].emplace_back(std::move(*it2));
1146 
1156  _partial_feature_sets[map_num].erase(it2);
1157  it1 = _partial_feature_sets[map_num].erase(it1); // it1 is incremented here!
1158 
1159  // A merge occurred, this is used to determine whether or not we increment the outer
1160  // iterator
1161  merge_occured = true;
1162 
1163  // We need to start the list comparison over for the new it1 so break here
1164  break;
1165  }
1166  } // it2 loop
1167 
1168  if (!merge_occured) // No merges so we need to manually increment the outer iterator
1169  ++it1;
1170 
1171  } // it1 loop
1172  } // map loop
1173 }

Referenced by FeatureFloodCount::communicateAndMerge().

◆ meshChanged()

void GrainTracker::meshChanged ( )
overridevirtualinherited

Reimplemented from FeatureFloodCount.

Definition at line 248 of file GrainTracker.C.

249 {
250  // Update the element ID ranges for use when computing halo maps
251  if (_compute_halo_maps && _mesh.isDistributedMesh())
252  {
253  _all_ranges.clear();
254 
255  auto range = std::make_pair(std::numeric_limits<dof_id_type>::max(),
256  std::numeric_limits<dof_id_type>::min());
257  for (const auto & current_elem : _mesh.getMesh().active_local_element_ptr_range())
258  {
259  auto id = current_elem->id();
260  if (id < range.first)
261  range.first = id;
262  else if (id > range.second)
263  range.second = id;
264  }
265 
266  _communicator.gather(0, range, _all_ranges);
267  }
268 
270 }

◆ newGrain()

RankFourTensor GrainTrackerElasticity::newGrain ( unsigned int  new_grain_id)
protectedvirtual

implement this method to initialize the data for the new grain

Implements GrainDataTracker< RankFourTensor >.

Definition at line 44 of file GrainTrackerElasticity.C.

45 {
46  EulerAngles angles;
47 
48  if (new_grain_id < _euler.getGrainNum())
49  angles = _euler.getEulerAngles(new_grain_id);
50  else
51  {
53  angles.random();
54  else
55  mooseError("GrainTrackerElasticity has run out of grain rotation data.");
56  }
57 
58  RankFourTensor C_ijkl = _C_ijkl;
59  C_ijkl.rotate(RotationTensor(RealVectorValue(angles)));
60 
61  return C_ijkl;
62 }

◆ newGrainCreated()

void GrainDataTracker< RankFourTensor >::newGrainCreated ( unsigned int  new_grain_id)
protectedvirtualinherited

This method is called when a new grain is detected.

It can be overridden by a derived class to handle setting new properties on the newly created grain.

Reimplemented from GrainTracker.

Definition at line 52 of file GrainDataTracker.h.

53 {
54  if (_grain_data.size() <= new_grain_id)
55  _grain_data.resize(new_grain_id + 1);
56 
57  _grain_data[new_grain_id] = newGrain(new_grain_id);
58 }

◆ numCoupledVars()

std::size_t FeatureFloodCount::numCoupledVars ( ) const
inlineinherited

Returns the number of coupled varaibles.

Definition at line 89 of file FeatureFloodCount.h.

89 { return _n_vars; }

◆ prepareDataForTransfer()

void FeatureFloodCount::prepareDataForTransfer ( )
protectedinherited

This routine uses the local flooded data to build up the local feature data structures (_feature_sets).

This routine does not perform any communication so the _feature_sets data structure will only contain information from the local processor after calling this routine. Any existing data in the _feature_sets structure is destroyed by calling this routine.

_feature_sets layout: The outer vector is sized to one when _single_map_mode == true, otherwise it is sized for the number of coupled variables. The inner list represents the flooded regions (local only after this call but fully populated after parallel communication and stitching).

If using a vector container, we need to sort all of the data structures for later operations such as checking for intersection and merging. The following "sort" function does nothing when invoked on a std::set.

Save off the min entity id present in the feature to uniquely identify the feature regardless of n_procs

Definition at line 1017 of file FeatureFloodCount.C.

1018 {
1019  TIME_SECTION(_prepare_for_transfer);
1020 
1021  MeshBase & mesh = _mesh.getMesh();
1022 
1023  FeatureData::container_type local_ids_no_ghost, set_difference;
1024 
1025  for (auto & list_ref : _partial_feature_sets)
1026  {
1027  for (auto & feature : list_ref)
1028  {
1029  // See if the feature intersects a boundary or perhaps one of the percolation boundaries.
1030  updateBoundaryIntersections(feature);
1031 
1032  // Periodic node ids
1033  appendPeriodicNeighborNodes(feature);
1034 
1040  FeatureFloodCount::sort(feature._ghosted_ids);
1041  FeatureFloodCount::sort(feature._local_ids);
1042  FeatureFloodCount::sort(feature._halo_ids);
1043  FeatureFloodCount::sort(feature._disjoint_halo_ids);
1044  FeatureFloodCount::sort(feature._periodic_nodes);
1045 
1046  // Now extend the bounding box by the halo region
1047  if (_is_elemental)
1048  feature.updateBBoxExtremes(mesh);
1049  else
1050  {
1051  for (auto & halo_id : feature._halo_ids)
1052  updateBBoxExtremesHelper(feature._bboxes[0], mesh.point(halo_id));
1053  }
1054 
1055  mooseAssert(!feature._local_ids.empty(), "local entity ids cannot be empty");
1056 
1061  feature._min_entity_id = *feature._local_ids.begin();
1062  }
1063  }
1064 }

Referenced by FeatureFloodCount::communicateAndMerge().

◆ prepopulateState()

void GrainTracker::prepopulateState ( const FeatureFloodCount ffc_object)
protectedinherited

This method extracts the necessary state from the passed in object necessary to continue tracking grains.

This method is meant to be used with the PolycrystalUserobjectBase class that sets up initial conditions for Polycrystal simulations. We can use the state of that object rather than rediscovering everything ourselves.

The minimum information needed to bootstrap the GrainTracker is as follows: _feature_sets _feature_count

Definition at line 298 of file GrainTracker.C.

299 {
300  mooseAssert(_first_time, "This method should only be called on the first invocation");
301 
302  _feature_sets.clear();
303 
309  if (_is_master)
310  {
311  const auto & features = ffc_object.getFeatures();
312  for (auto & feature : features)
313  _feature_sets.emplace_back(feature.duplicate());
314 
315  _feature_count = _feature_sets.size();
316  }
317  else
318  {
319  const auto & features = ffc_object.getFeatures();
320  _partial_feature_sets[0].clear();
321  for (auto & feature : features)
322  _partial_feature_sets[0].emplace_back(feature.duplicate());
323  }
324 
325  // Make sure that feature count is communicated to all ranks
326  _communicator.broadcast(_feature_count);
327 }

Referenced by GrainTracker::finalize().

◆ remapGrains()

void GrainTracker::remapGrains ( )
protectedinherited

This method is called after trackGrains to remap grains that are too close to each other.

Map used for communicating remap indices to all ranks This map isn't populated until after the remap loop. It's declared here before we enter the root scope since it's needed by all ranks during the broadcast.

The remapping algorithm is recursive. We will use the status variable in each FeatureData to track which grains are currently being remapped so we don't have runaway recursion. To begin we need to clear all of the active (MARKED) flags (CLEAR).

Additionally we need to record each grain's variable index so that we can communicate changes to the non-root ranks later in a single batch.

We're not going to try very hard to look for a suitable remapping. Just set it to what we want and hope it all works out. Make the GrainTracker great again!

Loop over each grain and see if any grains represented by the same variable are "touching"

The remapping loop is complete but only on the master process. Now we need to build the remap map and communicate it to the remaining processors.

Since the remapping algorithm only runs on the root process, the variable index on the master's grains is inconsistent from the rest of the ranks. These are the grains with a status of DIRTY. As we build this map we will temporarily switch these variable indices back to the correct value so that all processors use the same algorithm to remap.

Definition at line 913 of file GrainTracker.C.

916 {
917  // Don't remap grains if the current simulation step is before the specified tracking step
918  if (_t_step < _tracking_step)
919  return;
920 
921  TIME_SECTION(_remap_timer);
922 
923  if (_verbosity_level > 1)
924  _console << "Running remap Grains\n" << std::endl;
925 
932  std::map<unsigned int, std::size_t> grain_id_to_new_var;
933 
934  // Items are added to this list when split grains are found
935  std::list<std::pair<std::size_t, std::size_t>> split_pairs;
936 
945  if (_is_master)
946  {
947  // Build the map to detect difference in _var_index mappings after the remap operation
948  std::map<unsigned int, std::size_t> grain_id_to_existing_var_index;
949  for (auto & grain : _feature_sets)
950  {
951  // Unmark the grain so it can be used in the remap loop
952  grain._status = Status::CLEAR;
953 
954  grain_id_to_existing_var_index[grain._id] = grain._var_index;
955  }
956 
957  // Make sure that all split pieces of any grain are on the same OP
958  for (MooseIndex(_feature_sets) i = 0; i < _feature_sets.size(); ++i)
959  {
960  auto & grain1 = _feature_sets[i];
961 
962  for (MooseIndex(_feature_sets) j = 0; j < _feature_sets.size(); ++j)
963  {
964  auto & grain2 = _feature_sets[j];
965  if (i == j)
966  continue;
967 
968  // The first condition below is there to prevent symmetric checks (duplicate values)
969  if (i < j && grain1._id == grain2._id)
970  {
971  split_pairs.push_front(std::make_pair(i, j));
972  if (grain1._var_index != grain2._var_index)
973  {
974  if (_verbosity_level > 0)
975  _console << COLOR_YELLOW << "Split Grain (#" << grain1._id
976  << ") detected on unmatched OPs (" << grain1._var_index << ", "
977  << grain2._var_index << ") attempting to remap to " << grain1._var_index
978  << ".\n"
979  << COLOR_DEFAULT;
980 
985  grain1._var_index = grain2._var_index;
986  grain1._status |= Status::DIRTY;
987  }
988  }
989  }
990  }
991 
995  bool any_grains_remapped = false;
996  bool grains_remapped;
997 
998  std::set<unsigned int> notify_ids;
999  do
1000  {
1001  grains_remapped = false;
1002  notify_ids.clear();
1003 
1004  for (auto & grain1 : _feature_sets)
1005  {
1006  // We need to remap any grains represented on any variable index above the cuttoff
1007  if (grain1._var_index >= _reserve_op_index)
1008  {
1009  if (_verbosity_level > 0)
1010  _console << COLOR_YELLOW << "\nGrain #" << grain1._id
1011  << " detected on a reserved order parameter #" << grain1._var_index
1012  << ", remapping to another variable\n"
1013  << COLOR_DEFAULT;
1014 
1015  for (MooseIndex(_max_remap_recursion_depth) max = 0; max <= _max_remap_recursion_depth;
1016  ++max)
1017  if (max < _max_remap_recursion_depth)
1018  {
1019  if (attemptGrainRenumber(grain1, 0, max))
1020  break;
1021  }
1022  else if (!attemptGrainRenumber(grain1, 0, max))
1023  {
1024  _console << std::flush;
1025  std::stringstream oss;
1026  oss << "Unable to find any suitable order parameters for remapping while working "
1027  << "with Grain #" << grain1._id << ", which is on a reserve order parameter.\n"
1028  << "\n\nPossible Resolutions:\n"
1029  << "\t- Add more order parameters to your simulation (8 for 2D, 28 for 3D)\n"
1030  << "\t- Increase adaptivity or reduce your grain boundary widths\n"
1031  << "\t- Make sure you are not starting with too many grains for the mesh size\n";
1032  mooseError(oss.str());
1033  }
1034 
1035  grains_remapped = true;
1036  }
1037 
1038  for (auto & grain2 : _feature_sets)
1039  {
1040  // Don't compare a grain with itself and don't try to remap inactive grains
1041  if (&grain1 == &grain2)
1042  continue;
1043 
1044  if (grain1._var_index == grain2._var_index && // grains represented by same variable?
1045  grain1._id != grain2._id && // are they part of different grains?
1046  grain1.boundingBoxesIntersect(grain2) && // do bboxes intersect (coarse level)?
1047  grain1.halosIntersect(grain2)) // do they actually overlap (fine level)?
1048  {
1049  if (_verbosity_level > 0)
1050  _console << COLOR_YELLOW << "Grain #" << grain1._id << " intersects Grain #"
1051  << grain2._id << " (variable index: " << grain1._var_index << ")\n"
1052  << COLOR_DEFAULT;
1053 
1054  for (MooseIndex(_max_remap_recursion_depth) max = 0; max <= _max_remap_recursion_depth;
1055  ++max)
1056  {
1057  if (max < _max_remap_recursion_depth)
1058  {
1059  if (attemptGrainRenumber(grain1, 0, max))
1060  {
1061  grains_remapped = true;
1062  break;
1063  }
1064  }
1065  else if (!attemptGrainRenumber(grain1, 0, max) &&
1066  !attemptGrainRenumber(grain2, 0, max))
1067  {
1068  notify_ids.insert(grain1._id);
1069  notify_ids.insert(grain2._id);
1070  }
1071  }
1072  }
1073  }
1074  }
1075  any_grains_remapped |= grains_remapped;
1076  } while (grains_remapped);
1077 
1078  if (!notify_ids.empty())
1079  {
1080  _console << std::flush;
1081  std::stringstream oss;
1082  oss << "Unable to find any suitable order parameters for remapping while working "
1083  << "with the following grain IDs:\n"
1084  << Moose::stringify(notify_ids, ", ", "", true) << "\n\nPossible Resolutions:\n"
1085  << "\t- Add more order parameters to your simulation (8 for 2D, 28 for 3D)\n"
1086  << "\t- Increase adaptivity or reduce your grain boundary widths\n"
1087  << "\t- Make sure you are not starting with too many grains for the mesh size\n";
1088 
1089  if (_tolerate_failure)
1090  mooseWarning(oss.str());
1091  else
1092  mooseError(oss.str());
1093  }
1094 
1095  // Verify that split grains are still intact
1096  for (auto & split_pair : split_pairs)
1097  if (_feature_sets[split_pair.first]._var_index != _feature_sets[split_pair.first]._var_index)
1098  mooseError("Split grain remapped - This case is currently not handled");
1099 
1105  for (auto & grain : _feature_sets)
1106  {
1107  mooseAssert(grain_id_to_existing_var_index.find(grain._id) !=
1108  grain_id_to_existing_var_index.end(),
1109  "Missing unique ID");
1110 
1111  auto old_var_index = grain_id_to_existing_var_index[grain._id];
1112 
1113  if (old_var_index != grain._var_index)
1114  {
1115  mooseAssert(static_cast<bool>(grain._status & Status::DIRTY), "grain status is incorrect");
1116 
1117  grain_id_to_new_var.emplace_hint(
1118  grain_id_to_new_var.end(),
1119  std::pair<unsigned int, std::size_t>(grain._id, grain._var_index));
1120 
1129  grain._var_index = old_var_index;
1130  // Clear the DIRTY status as well for consistency
1131  grain._status &= ~Status::DIRTY;
1132  }
1133  }
1134 
1135  if (!grain_id_to_new_var.empty())
1136  {
1137  if (_verbosity_level > 1)
1138  {
1139  _console << "Final remapping tally:\n";
1140  for (const auto & remap_pair : grain_id_to_new_var)
1141  _console << "Grain #" << remap_pair.first << " var_index "
1142  << grain_id_to_existing_var_index[remap_pair.first] << " -> "
1143  << remap_pair.second << '\n';
1144  _console << "Communicating swaps with remaining processors..." << std::endl;
1145  }
1146  }
1147  } // root processor
1148 
1149  // Communicate the std::map to all ranks
1150  _communicator.broadcast(grain_id_to_new_var);
1151 
1152  // Perform swaps if any occurred
1153  if (!grain_id_to_new_var.empty())
1154  {
1155  // Cache for holding values during swaps
1156  std::vector<std::map<Node *, CacheValues>> cache(_n_vars);
1157 
1158  // Perform the actual swaps on all processors
1159  for (auto & grain : _feature_sets)
1160  {
1161  // See if this grain was remapped
1162  auto new_var_it = grain_id_to_new_var.find(grain._id);
1163  if (new_var_it != grain_id_to_new_var.end())
1164  swapSolutionValues(grain, new_var_it->second, cache, RemapCacheMode::FILL);
1165  }
1166 
1167  for (auto & grain : _feature_sets)
1168  {
1169  // See if this grain was remapped
1170  auto new_var_it = grain_id_to_new_var.find(grain._id);
1171  if (new_var_it != grain_id_to_new_var.end())
1172  swapSolutionValues(grain, new_var_it->second, cache, RemapCacheMode::USE);
1173  }
1174 
1175  _nl.solution().close();
1176  _nl.solutionOld().close();
1177  _nl.solutionOlder().close();
1178 
1179  _fe_problem.getNonlinearSystemBase().system().update();
1180 
1181  if (_verbosity_level > 1)
1182  _console << "Swaps complete" << std::endl;

Referenced by GrainTracker::finalize().

◆ reserve() [1/2]

template<class T >
static void FeatureFloodCount::reserve ( std::set< T > &  ,
std::size_t   
)
inlinestaticprivateinherited

Definition at line 748 of file FeatureFloodCount.h.

750  {
751  // Sets are trees, no reservations necessary

Referenced by FeatureFloodCount::FeatureData::consolidate(), FeatureFloodCount::FeatureData::merge(), and FeatureFloodCount::FeatureData::updateBBoxExtremes().

◆ reserve() [2/2]

template<class T >
static void FeatureFloodCount::reserve ( std::vector< T > &  container,
std::size_t  size 
)
inlinestaticprivateinherited

Definition at line 754 of file FeatureFloodCount.h.

756  {
757  container.reserve(size);

◆ scatterAndUpdateRanks()

void FeatureFloodCount::scatterAndUpdateRanks ( )
protectedinherited

Calls buildLocalToGlobalIndices to build the individual local to global indicies for each rank and scatters that information to all ranks.

Finally, the non-master ranks update their own data structures to reflect the global mappings.

On non-root processors we can't maintain the full _feature_sets data structure since we don't have all of the global information. We'll move the items from the partial feature sets into a flat structure maintaining order and update the internal IDs with the proper global ID.

Important: Make sure we clear the local status if we received a valid global index for this feature. It's possible that we have a status of INVALID on the local processor because there was never any starting threshold found. However, the root processor wouldn't have sent an index if it didn't find a starting threshold connected to our local piece.

Definition at line 717 of file FeatureFloodCount.C.

718 {
719  // local to global map (one per processor)
720  std::vector<int> counts;
721  std::vector<std::size_t> local_to_global_all;
722  if (_is_master)
723  buildLocalToGlobalIndices(local_to_global_all, counts);
724 
725  // Scatter local_to_global indices to all processors and store in class member variable
726  _communicator.scatter(local_to_global_all, counts, _local_to_global_feature_map);
727 
728  std::size_t largest_global_index = std::numeric_limits<std::size_t>::lowest();
729  if (!_is_master)
730  {
732 
739  for (auto & list_ref : _partial_feature_sets)
740  {
741  for (auto & feature : list_ref)
742  {
743  mooseAssert(feature._orig_ids.size() == 1, "feature._orig_ids length doesn't make sense");
744 
745  auto global_index = FeatureFloodCount::invalid_size_t;
746  auto local_index = feature._orig_ids.begin()->second;
747 
748  if (local_index < _local_to_global_feature_map.size())
749  global_index = _local_to_global_feature_map[local_index];
750 
751  if (global_index != FeatureFloodCount::invalid_size_t)
752  {
753  if (global_index > largest_global_index)
754  largest_global_index = global_index;
755 
756  // Set the correct global index
757  feature._id = global_index;
758 
766  feature._status &= ~Status::INACTIVE;
767 
768  // Move the feature into the correct place
769  _feature_sets[local_index] = std::move(feature);
770  }
771  }
772  }
773  }
774  else
775  {
776  for (auto global_index : local_to_global_all)
777  if (global_index != FeatureFloodCount::invalid_size_t && global_index > largest_global_index)
778  largest_global_index = global_index;
779  }
780 
781  buildFeatureIdToLocalIndices(largest_global_index);
782 }

Referenced by GrainTracker::assignGrains(), FeatureFloodCount::finalize(), and GrainTracker::trackGrains().

◆ serialize()

void FeatureFloodCount::serialize ( std::string &  serialized_buffer,
unsigned int  var_num = invalid_id 
)
protectedinherited

This routines packs the _partial_feature_sets data into a structure suitable for parallel communication operations.

Definition at line 1067 of file FeatureFloodCount.C.

1068 {
1069  // stream for serializing the _partial_feature_sets data structure to a byte stream
1070  std::ostringstream oss;
1071 
1072  mooseAssert(var_num == invalid_id || var_num < _partial_feature_sets.size(),
1073  "var_num out of range");
1074 
1075  // Serialize everything
1076  if (var_num == invalid_id)
1077  dataStore(oss, _partial_feature_sets, this);
1078  else
1079  dataStore(oss, _partial_feature_sets[var_num], this);
1080 
1081  // Populate the passed in string pointer with the string stream's buffer contents
1082  serialized_buffer.assign(oss.str());
1083 }

Referenced by FeatureFloodCount::communicateAndMerge().

◆ setsIntersect()

template<class InputIterator >
static bool FeatureFloodCount::setsIntersect ( InputIterator  first1,
InputIterator  last1,
InputIterator  first2,
InputIterator  last2 
)
inlinestaticprotectedinherited

This method detects whether two sets intersect without building a result set.

It exits as soon as any intersection is detected.

Definition at line 543 of file FeatureFloodCount.h.

547  {
548  while (first1 != last1 && first2 != last2)
549  {
550  if (*first1 == *first2)
551  return true;
552 
553  if (*first1 < *first2)
554  ++first1;
555  else if (*first1 > *first2)
556  ++first2;
557  }
558  return false;
559  }

Referenced by FeatureFloodCount::FeatureData::ghostedIntersect(), FeatureFloodCount::FeatureData::halosIntersect(), and FeatureFloodCount::FeatureData::periodicBoundariesIntersect().

◆ sort() [1/2]

template<class T >
static void FeatureFloodCount::sort ( std::set< T > &  )
inlinestaticprivateinherited

Definition at line 736 of file FeatureFloodCount.h.

738  {
739  // Sets are already sorted, do nothing

Referenced by FeatureFloodCount::prepareDataForTransfer().

◆ sort() [2/2]

template<class T >
static void FeatureFloodCount::sort ( std::vector< T > &  container)
inlinestaticprivateinherited

Definition at line 742 of file FeatureFloodCount.h.

744  {
745  std::sort(container.begin(), container.end());

◆ sortAndLabel()

void FeatureFloodCount::sortAndLabel ( )
protectedinherited

Sort and assign ids to features based on their position in the container after sorting.

Perform a sort to give a parallel unique sorting to the identified features. We use the "min_entity_id" inside each feature to assign it's position in the sorted vector.

Sanity check. Now that we've sorted the flattened vector of features we need to make sure that the counts vector still lines up appropriately with each feature's _var_index.

Definition at line 573 of file FeatureFloodCount.C.

574 {
575  mooseAssert(_is_master, "sortAndLabel can only be called on the master");
576 
582  std::sort(_feature_sets.begin(), _feature_sets.end());
583 
584 #ifndef NDEBUG
585 
590  unsigned int feature_offset = 0;
591  for (MooseIndex(_maps_size) map_num = 0; map_num < _maps_size; ++map_num)
592  {
593  // Skip empty map checks
594  if (_feature_counts_per_map[map_num] == 0)
595  continue;
596 
597  // Check the begin and end of the current range
598  auto range_front = feature_offset;
599  auto range_back = feature_offset + _feature_counts_per_map[map_num] - 1;
600 
601  mooseAssert(range_front <= range_back && range_back < _feature_count,
602  "Indexing error in feature sets");
603 
604  if (!_single_map_mode && (_feature_sets[range_front]._var_index != map_num ||
605  _feature_sets[range_back]._var_index != map_num))
606  mooseError("Error in _feature_sets sorting, map index: ", map_num);
607 
608  feature_offset += _feature_counts_per_map[map_num];
609  }
610 #endif
611 
612  // Label the features with an ID based on the sorting (processor number independent value)
613  for (MooseIndex(_feature_sets) i = 0; i < _feature_sets.size(); ++i)
614  if (_feature_sets[i]._id == invalid_id)
615  _feature_sets[i]._id = i;
616 }

Referenced by GrainTracker::assignGrains(), and FeatureFloodCount::finalize().

◆ swapSolutionValues()

void GrainTracker::swapSolutionValues ( FeatureData grain,
std::size_t  new_var_index,
std::vector< std::map< Node *, CacheValues >> &  cache,
RemapCacheMode  cache_mode 
)
protectedinherited

A routine for moving all of the solution values from a given grain to a new variable number.

It is called with different modes to only cache, or actually do the work, or bypass the cache altogether.

Definition at line 1434 of file GrainTracker.C.

1440 {
1441  MeshBase & mesh = _mesh.getMesh();
1442 
1443  // Remap the grain
1444  std::set<Node *> updated_nodes_tmp; // Used only in the elemental case
1445  for (auto entity : grain._local_ids)
1446  {
1447  if (_is_elemental)
1448  {
1449  Elem * elem = mesh.query_elem_ptr(entity);
1450  if (!elem)
1451  continue;
1452 
1453  for (unsigned int i = 0; i < elem->n_nodes(); ++i)
1454  {
1455  Node * curr_node = elem->node_ptr(i);
1456  if (updated_nodes_tmp.find(curr_node) == updated_nodes_tmp.end())
1457  {
1458  // cache this node so we don't attempt to remap it again within this loop
1459  updated_nodes_tmp.insert(curr_node);
1460  swapSolutionValuesHelper(curr_node, grain._var_index, new_var_index, cache, cache_mode);
1461  }
1462  }
1463  }
1464  else
1466  mesh.query_node_ptr(entity), grain._var_index, new_var_index, cache, cache_mode);
1467  }
1468 
1469  // Update the variable index in the unique grain datastructure after swaps are complete
1470  if (cache_mode == RemapCacheMode::USE || cache_mode == RemapCacheMode::BYPASS)

Referenced by GrainTracker::remapGrains().

◆ swapSolutionValuesHelper()

void GrainTracker::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 
)
protectedinherited

Helper method for actually performing the swaps.

Finally zero out the old variable. When using the FILL/USE combination to read/write variables, it's important to zero the variable on the FILL stage and not the USE stage. The reason for this is handling swaps as illustrated in the following diagram


/ \/ \ If adjacent grains (overlapping flood region) end up / 1 /\ 2 \ swapping variable indices and variables are zeroed on \ 2*\/ 1* / "USE", the overlap region will be incorrectly zeroed ___/___/ by whichever variable is written to second.

Definition at line 1473 of file GrainTracker.C.

1480 {
1481  if (curr_node && curr_node->processor_id() == processor_id())
1482  {
1483  // Reinit the node so we can get and set values of the solution here
1484  _subproblem.reinitNode(curr_node, 0);
1485 
1486  // Local variables to hold values being transferred
1487  Real current, old = 0, older = 0;
1488  // Retrieve the value either from the old variable or cache
1489  if (cache_mode == RemapCacheMode::FILL || cache_mode == RemapCacheMode::BYPASS)
1490  {
1491  current = _vars[curr_var_index]->dofValues()[0];
1492  if (_is_transient)
1493  {
1494  old = _vars[curr_var_index]->dofValuesOld()[0];
1495  older = _vars[curr_var_index]->dofValuesOlder()[0];
1496  }
1497  }
1498  else // USE
1499  {
1500  const auto cache_it = cache[curr_var_index].find(curr_node);
1501  mooseAssert(cache_it != cache[curr_var_index].end(), "Error in cache");
1502  current = cache_it->second.current;
1503  old = cache_it->second.old;
1504  older = cache_it->second.older;
1505  }
1506 
1507  // Cache the value or use it!
1508  if (cache_mode == RemapCacheMode::FILL)
1509  {
1510  cache[curr_var_index][curr_node].current = current;
1511  cache[curr_var_index][curr_node].old = old;
1512  cache[curr_var_index][curr_node].older = older;
1513  }
1514  else // USE or BYPASS
1515  {
1516  const auto & dof_index = _vars[new_var_index]->nodalDofIndex();
1517 
1518  // Transfer this solution from the old to the current
1519  _nl.solution().set(dof_index, current);
1520  if (_is_transient)
1521  {
1522  _nl.solutionOld().set(dof_index, old);
1523  _nl.solutionOlder().set(dof_index, older);
1524  }
1525  }
1526 
1539  if (cache_mode == RemapCacheMode::FILL || cache_mode == RemapCacheMode::BYPASS)
1540  {
1541  const auto & dof_index = _vars[curr_var_index]->nodalDofIndex();
1542 
1543  // Set the DOF for the current variable to zero
1544  _nl.solution().set(dof_index, 0.0);
1545  if (_is_transient)
1546  {
1547  _nl.solutionOld().set(dof_index, 0.0);
1548  _nl.solutionOlder().set(dof_index, 0.0);
1549  }
1550  }

Referenced by GrainTracker::swapSolutionValues().

◆ trackGrains()

void GrainTracker::trackGrains ( )
protectedinherited

On subsequent time_steps, incoming FeatureData objects are compared to previous time_step information to track grains between time steps.

This method updates the _feature_sets data structure. This method should only be called on the root processor

Only the master rank does tracking, the remaining ranks wait to receive local to global indices from the master.

To track grains across time steps, we will loop over our unique grains and link each one up with one of our new unique grains. The criteria for doing this will be to find the unique grain in the new list with a matching variable index whose centroid is closest to this unique grain.

The _feature_sets vector is constructed by _var_index so we can avoid looping over all indices. We can quickly jump to the first matching index to reduce the number of comparisons and terminate our loop when our variable index stops matching.

Don't try to do any matching unless the bounding boxes at least overlap. This is to avoid the corner case of having a grain split and a grain disappear during the same time step!

It's possible that multiple existing grains will map to a single new grain (indicated by finding multiple matches when we are building this map). This will happen any time a grain disappears during this time step. We need to figure out the rightful owner in this case and inactivate the old grain.

If the grain we just marked inactive was the one whose index was in the new grain to existing grain map (other_old_grain). Then we need to update the map to point to the new match winner.

At this point we have should have only two cases left to handle: Case 1: A grain in the new set who has an unset status (These are new grains, previously untracked) This case is easy to understand. Since we are matching up grains by looking at the old set and finding closest matches in the new set, any grain in the new set that isn't matched up is simply new since some other grain satisfied each and every request from the old set.

Case 2: A grain in the old set who has an unset status (These are inactive grains that haven't been marked) We can only fall into this case when the very last grain on a given variable disappears during the current time step. In that case we never have a matching _var_index in the comparison loop above so that old grain never competes for any new grain which means it can't be marked inactive in the loop above.

Now we need to figure out what kind of "new" grain this is. Is it a nucleating grain that we're just barely seeing for the first time or is it a "splitting" grain. A grain that gets pinched into two or more pieces usually as it is being absorbed by other grains or possibly due to external forces. We have to handle splitting grains this way so as to no confuse them with regular grains that just happen to be in contact in this step.

Splitting Grain: An grain that is unmatched by any old grain on the same order parameter with touching halos.

Nucleating Grain: A completely new grain appearing somewhere in the domain not overlapping any other grain's halo.

To figure out which case we are dealing with, we have to make another pass over all of the existing grains with matching variable indices to see if any of them have overlapping halos.

The "try-harder loop": OK so we still have an extra grain in the new set that isn't matched up against the old set and since the order parameter isn't reserved. We aren't really expecting a new grain. Let's try to make a few more attempts to see if this is a split grain even though it failed to match the criteria above. This might happen if the halo front is advancing too fast!

In this loop we'll make an attempt to match up this new grain to the old halos. If adaptivity is happening this could fail as elements in the new set may be at a different level than in the old set. If we get multiple matches, we'll compare the grain volumes (based on elements, not integrated to choose the closest).

Future ideas: Look at the volume fraction of the new grain and overlay it over the volume fraction of the old grain (would require more saved information, or an aux field hanging around (subject to projection problems).

Note that the old grains we are looking at will already be marked from the earlier tracking phase. We are trying to see if this unmatched grain is part of a larger whole. To do that we'll look at the halos across the time step.

Trigger callback for new grains

Definition at line 497 of file GrainTracker.C.

499 {
500  TIME_SECTION(_track_grains);
501 
502  mooseAssert(!_first_time, "Track grains may only be called when _tracking_step > _t_step");
503 
504  // Used to track indices for which to trigger the new grain callback on (used on all ranks)
506 
511  if (_is_master)
512  {
513  // Reset Status on active unique grains
514  std::vector<unsigned int> map_sizes(_maps_size);
515  for (auto & grain : _feature_sets_old)
516  {
517  if (grain._status != Status::INACTIVE)
518  {
519  grain._status = Status::CLEAR;
520  map_sizes[grain._var_index]++;
521  }
522  }
523 
524  // Print out stats on overall tracking changes per var_index
525  if (_verbosity_level > 0)
526  {
527  _console << "\nGrain Tracker Status:";
528  for (MooseIndex(_maps_size) map_num = 0; map_num < _maps_size; ++map_num)
529  {
530  _console << "\nGrains active index " << map_num << ": " << map_sizes[map_num] << " -> "
531  << _feature_counts_per_map[map_num];
532  if (map_sizes[map_num] > _feature_counts_per_map[map_num])
533  _console << "--";
534  else if (map_sizes[map_num] < _feature_counts_per_map[map_num])
535  _console << "++";
536  }
537  _console << '\n' << std::endl;
538  }
539 
540  // Before we track grains, lets sort them so that we get parallel consistent answers
541  std::sort(_feature_sets.begin(), _feature_sets.end());
542 
549  std::vector<std::size_t> new_grain_index_to_existing_grain_index(_feature_sets.size(),
551 
552  for (MooseIndex(_feature_sets_old) old_grain_index = 0;
553  old_grain_index < _feature_sets_old.size();
554  ++old_grain_index)
555  {
556  auto & old_grain = _feature_sets_old[old_grain_index];
557 
558  if (old_grain._status == Status::INACTIVE) // Don't try to find matches for inactive grains
559  continue;
560 
561  std::size_t closest_match_index = invalid_size_t;
562  Real min_centroid_diff = std::numeric_limits<Real>::max();
563 
569  // clang-format off
570  auto start_it =
571  std::lower_bound(_feature_sets.begin(), _feature_sets.end(), old_grain._var_index,
572  [](const FeatureData & item, std::size_t var_index)
573  {
574  return item._var_index < var_index;
575  });
576  // clang-format on
577 
578  // We only need to examine grains that have matching variable indices
579  bool any_boxes_intersect = false;
580  for (MooseIndex(_feature_sets)
581  new_grain_index = std::distance(_feature_sets.begin(), start_it);
582  new_grain_index < _feature_sets.size() &&
583  _feature_sets[new_grain_index]._var_index == old_grain._var_index;
584  ++new_grain_index)
585  {
586  auto & new_grain = _feature_sets[new_grain_index];
587 
592  if (new_grain.boundingBoxesIntersect(old_grain))
593  {
594  any_boxes_intersect = true;
595  Real curr_centroid_diff = centroidRegionDistance(old_grain._bboxes, new_grain._bboxes);
596  if (curr_centroid_diff <= min_centroid_diff)
597  {
598  closest_match_index = new_grain_index;
599  min_centroid_diff = curr_centroid_diff;
600  }
601  }
602  }
603 
604  if (_verbosity_level > 2 && !any_boxes_intersect)
605  _console << "\nNo intersecting bounding boxes found while trying to match grain "
606  << old_grain;
607 
608  // found a match
609  if (closest_match_index != invalid_size_t)
610  {
617  auto curr_index = new_grain_index_to_existing_grain_index[closest_match_index];
618  if (curr_index != invalid_size_t)
619  {
620  // The new feature being competed for
621  auto & new_grain = _feature_sets[closest_match_index];
622 
623  // The other old grain competing to match up to the same new grain
624  auto & other_old_grain = _feature_sets_old[curr_index];
625 
626  auto centroid_diff1 = centroidRegionDistance(new_grain._bboxes, old_grain._bboxes);
627  auto centroid_diff2 = centroidRegionDistance(new_grain._bboxes, other_old_grain._bboxes);
628 
629  auto & inactive_grain = (centroid_diff1 < centroid_diff2) ? other_old_grain : old_grain;
630 
631  inactive_grain._status = Status::INACTIVE;
632  if (_verbosity_level > 0)
633  {
634  _console << COLOR_GREEN << "Marking Grain " << inactive_grain._id
635  << " as INACTIVE (variable index: " << inactive_grain._var_index << ")\n"
636  << COLOR_DEFAULT;
637  if (_verbosity_level > 1)
638  _console << inactive_grain;
639  }
640 
646  if (&inactive_grain == &other_old_grain)
647  new_grain_index_to_existing_grain_index[closest_match_index] = old_grain_index;
648  }
649  else
650  new_grain_index_to_existing_grain_index[closest_match_index] = old_grain_index;
651  }
652  }
653 
654  // Mark all resolved grain matches
655  for (MooseIndex(new_grain_index_to_existing_grain_index) new_index = 0;
656  new_index < new_grain_index_to_existing_grain_index.size();
657  ++new_index)
658  {
659  auto curr_index = new_grain_index_to_existing_grain_index[new_index];
660 
661  // This may be a new grain, we'll handle that case below
662  if (curr_index == invalid_size_t)
663  continue;
664 
665  mooseAssert(_feature_sets_old[curr_index]._id != invalid_id,
666  "Invalid ID in old grain structure");
667 
668  _feature_sets[new_index]._id = _feature_sets_old[curr_index]._id; // Transfer ID
669  _feature_sets[new_index]._status = Status::MARKED; // Mark the status in the new set
670  _feature_sets_old[curr_index]._status = Status::MARKED; // Mark the status in the old set
671  }
672 
687  // Case 1 (new grains in _feature_sets):
688  for (MooseIndex(_feature_sets) grain_num = 0; grain_num < _feature_sets.size(); ++grain_num)
689  {
690  auto & grain = _feature_sets[grain_num];
691 
692  // New Grain
693  if (grain._status == Status::CLEAR)
694  {
713  // clang-format off
714  auto start_it =
715  std::lower_bound(_feature_sets.begin(), _feature_sets.end(), grain._var_index,
716  [](const FeatureData & item, std::size_t var_index)
717  {
718  return item._var_index < var_index;
719  });
720  // clang-format on
721 
722  // Loop over matching variable indices
723  for (MooseIndex(_feature_sets)
724  new_grain_index = std::distance(_feature_sets.begin(), start_it);
725  new_grain_index < _feature_sets.size() &&
726  _feature_sets[new_grain_index]._var_index == grain._var_index;
727  ++new_grain_index)
728  {
729  auto & other_grain = _feature_sets[new_grain_index];
730 
731  // Splitting grain?
732  if (grain_num != new_grain_index && // Make sure indices aren't pointing at the same grain
733  other_grain._status == Status::MARKED && // and that the other grain is indeed marked
734  other_grain.boundingBoxesIntersect(grain) && // and the bboxes intersect
735  other_grain.halosIntersect(grain)) // and the halos also intersect
736  // TODO: Inspect combined volume and see if it's "close" to the expected value
737  {
738  grain._id = other_grain._id; // Set the duplicate ID
739  grain._status = Status::MARKED; // Mark it
740 
741  if (_verbosity_level > 0)
742  _console << COLOR_YELLOW << "Split Grain Detected #" << grain._id
743  << " (variable index: " << grain._var_index << ")\n"
744  << COLOR_DEFAULT;
745  if (_verbosity_level > 1)
746  _console << grain << other_grain;
747  }
748  }
749 
750  if (grain._var_index < _reserve_op_index)
751  {
770  if (_verbosity_level > 1)
771  _console << COLOR_YELLOW
772  << "Trying harder to detect a split grain while examining grain on variable "
773  "index "
774  << grain._var_index << '\n'
775  << COLOR_DEFAULT;
776 
777  std::vector<std::size_t> old_grain_indices;
778  for (MooseIndex(_feature_sets_old) old_grain_index = 0;
779  old_grain_index < _feature_sets_old.size();
780  ++old_grain_index)
781  {
782  auto & old_grain = _feature_sets_old[old_grain_index];
783 
784  if (old_grain._status == Status::INACTIVE)
785  continue;
786 
792  if (grain._var_index == old_grain._var_index &&
793  grain.boundingBoxesIntersect(old_grain) && grain.halosIntersect(old_grain))
794  old_grain_indices.push_back(old_grain_index);
795  }
796 
797  if (old_grain_indices.size() == 1)
798  {
799  grain._id = _feature_sets_old[old_grain_indices[0]]._id;
800  grain._status = Status::MARKED;
801 
802  if (_verbosity_level > 0)
803  _console << COLOR_YELLOW << "Split Grain Detected #" << grain._id
804  << " (variable index: " << grain._var_index << ")\n"
805  << COLOR_DEFAULT;
806  }
807  else if (old_grain_indices.size() > 1)
808  _console
809  << COLOR_RED << "Split Grain Likely Detected #" << grain._id
810  << " Need more information to find correct candidate - contact a developer!\n\n"
811  << COLOR_DEFAULT;
812  }
813 
814  // Must be a nucleating grain (status is still not set)
815  if (grain._status == Status::CLEAR)
816  {
817  auto new_index = getNextUniqueID();
818  grain._id = new_index; // Set the ID
819  grain._status = Status::MARKED; // Mark it
820 
821  if (_verbosity_level > 0)
822  _console << COLOR_YELLOW << "Nucleating Grain Detected "
823  << " (variable index: " << grain._var_index << ")\n"
824  << COLOR_DEFAULT;
825  if (_verbosity_level > 1)
826  _console << grain;
827  }
828  }
829  }
830 
831  // Case 2 (inactive grains in _feature_sets_old)
832  for (auto & grain : _feature_sets_old)
833  {
834  if (grain._status == Status::CLEAR)
835  {
836  grain._status = Status::INACTIVE;
837  if (_verbosity_level > 0)
838  {
839  _console << COLOR_GREEN << "Marking Grain " << grain._id
840  << " as INACTIVE (variable index: " << grain._var_index << ")\n"
841  << COLOR_DEFAULT;
842  if (_verbosity_level > 1)
843  _console << grain;
844  }
845  }
846  }
847  } // is_master
848 
849  /*************************************************************
850  ****************** COLLECTIVE WORK SECTION ******************
851  *************************************************************/
852 
853  // Make IDs on all non-master ranks consistent
855 
856  // Build up an id to index map
857  _communicator.broadcast(_max_curr_grain_id);
859 
864  {
865  for (auto new_id = _old_max_grain_id + 1; new_id <= _max_curr_grain_id; ++new_id)
866  {
867  // Don't trigger the callback on the reserve IDs
869  {
870  // See if we've been instructed to terminate with an error
872  mooseError(
873  "Error: New grain detected and \"error_on_new_grain_creation\" is set to true");
874  else
875  newGrainCreated(new_id);
876  }
877  }

Referenced by GrainTracker::finalize().

◆ updateBoundaryIntersections()

void FeatureFloodCount::updateBoundaryIntersections ( FeatureData feature) const
protectedinherited

Update the feature's attributes to indicate boundary intersections.

Definition at line 1724 of file FeatureFloodCount.C.

1725 {
1726  if (_is_elemental)
1727  {
1728  for (auto entity : feature._local_ids)
1729  {
1730  // See if this feature is on a boundary if we haven't already figured that out
1731  if ((feature._boundary_intersection & BoundaryIntersection::ANY_BOUNDARY) ==
1733  {
1734  Elem * elem = _mesh.elemPtr(entity);
1735  if (elem && elem->on_boundary())
1736  feature._boundary_intersection |= BoundaryIntersection::ANY_BOUNDARY;
1737  }
1738 
1739  // Now see if the feature touches the primary and/or secondary boundary IDs if we haven't
1740  // figured that out already
1741  if ((feature._boundary_intersection & BoundaryIntersection::PRIMARY_PERCOLATION_BOUNDARY) ==
1743  {
1744  for (auto primary_id : _primary_perc_bnds)
1745  if (_mesh.isBoundaryElem(entity, primary_id))
1746  feature._boundary_intersection |= BoundaryIntersection::PRIMARY_PERCOLATION_BOUNDARY;
1747  }
1748 
1749  if ((feature._boundary_intersection & BoundaryIntersection::SECONDARY_PERCOLATION_BOUNDARY) ==
1751  {
1752  for (auto secondary_id : _secondary_perc_bnds)
1753  if (_mesh.isBoundaryElem(entity, secondary_id))
1754  feature._boundary_intersection |= BoundaryIntersection::SECONDARY_PERCOLATION_BOUNDARY;
1755  }
1756 
1757  // See if the feature contacts any of the user-specified boundaries if we haven't
1758  // done so already
1759  if ((feature._boundary_intersection & BoundaryIntersection::SPECIFIED_BOUNDARY) ==
1761  {
1762  for (auto specified_id : _specified_bnds)
1763  if (_mesh.isBoundaryElem(entity, specified_id))
1764  feature._boundary_intersection |= BoundaryIntersection::SPECIFIED_BOUNDARY;
1765  }
1766  }
1767  }
1768 }

Referenced by FeatureFloodCount::prepareDataForTransfer().

◆ updateFieldInfo()

void GrainTracker::updateFieldInfo ( )
overrideprotectedvirtualinherited

This method is used to populate any of the data structures used for storing field data (nodal or elemental).

It is called at the end of finalize and can make use of any of the data structures created during the execution of this postprocessor.

Reimplemented from FeatureFloodCount.

Definition at line 1553 of file GrainTracker.C.

1556 {
1557  TIME_SECTION(_update_field_info);
1558 
1559  for (MooseIndex(_maps_size) map_num = 0; map_num < _maps_size; ++map_num)
1560  _feature_maps[map_num].clear();
1561 
1562  std::map<dof_id_type, Real> tmp_map;
1563 
1564  for (const auto & grain : _feature_sets)
1565  {
1566  std::size_t curr_var = grain._var_index;
1567  std::size_t map_index = (_single_map_mode || _condense_map_info) ? 0 : curr_var;
1568 
1569  for (auto entity : grain._local_ids)
1570  {
1571  // Highest variable value at this entity wins
1572  Real entity_value = std::numeric_limits<Real>::lowest();
1573  if (_is_elemental)
1574  {
1575  const Elem * elem = _mesh.elemPtr(entity);
1576  std::vector<Point> centroid(1, elem->centroid());
1577  if (_poly_ic_uo && _first_time)
1578  {
1579  entity_value = _poly_ic_uo->getVariableValue(grain._var_index, centroid[0]);
1580  }
1581  else
1582  {
1583  _fe_problem.reinitElemPhys(elem, centroid, 0, /* suppress_displaced_init = */ true);
1584  entity_value = _vars[curr_var]->sln()[0];
1585  }
1586  }
1587  else
1588  {
1589  auto node_ptr = _mesh.nodePtr(entity);
1590  entity_value = _vars[curr_var]->getNodalValue(*node_ptr);
1591  }
1592 
1593  if (entity_value != std::numeric_limits<Real>::lowest() &&
1594  (tmp_map.find(entity) == tmp_map.end() || entity_value > tmp_map[entity]))
1595  {
1596  mooseAssert(grain._id != invalid_id, "Missing Grain ID");
1597  _feature_maps[map_index][entity] = grain._id;
1598 
1599  if (_var_index_mode)
1600  _var_index_maps[map_index][entity] = grain._var_index;
1601 
1602  tmp_map[entity] = entity_value;
1603  }
1604 
1606  {
1607  auto insert_pair = moose_try_emplace(
1608  _entity_var_to_features, entity, std::vector<unsigned int>(_n_vars, invalid_id));
1609  auto & vec_ref = insert_pair.first->second;
1610 
1611  if (insert_pair.second)
1612  {
1613  // insert the reserve op numbers (if appropriate)
1614  for (MooseIndex(_n_reserve_ops) reserve_index = 0; reserve_index < _n_reserve_ops;
1615  ++reserve_index)
1616  vec_ref[reserve_index] = _reserve_grain_first_index + reserve_index;
1617  }
1618  vec_ref[grain._var_index] = grain._id;
1619  }
1620  }
1621 
1622  if (_compute_halo_maps)
1623  for (auto entity : grain._halo_ids)
1624  _halo_ids[grain._var_index][entity] = grain._var_index;
1625 
1626  for (auto entity : grain._ghosted_ids)
1627  _ghosted_entity_ids[entity] = 1;
1628  }
1629 

Referenced by GrainTracker::finalize().

◆ updateRegionOffsets()

void FeatureFloodCount::updateRegionOffsets ( )
protectedinherited

This routine updates the _region_offsets variable which is useful for quickly determining the proper global number for a feature when using multimap mode.

◆ visitElementalNeighbors()

void FeatureFloodCount::visitElementalNeighbors ( const Elem *  elem,
FeatureData feature,
bool  expand_halos_only,
bool  disjoint_only 
)
protectedinherited

Retrieve only the active neighbors for each side of this element, append them to the list of active neighbors

If the current element (passed into this method) doesn't have a connected neighbor but does have a topological neighbor, this might be a new disjoint region that we'll need to represent with a separate bounding box. To find out for sure, we'll need see if the new neighbors are present in any of the halo or disjoint halo sets. If they are not present, this is a new region.

This neighbor is NULL which means we need to expand the bounding box here in case this grain is up against multiple domain edges so we don't end up with a degenerate bounding box.

Definition at line 1584 of file FeatureFloodCount.C.

1588 {
1589  mooseAssert(elem, "Elem is NULL");
1590 
1591  std::vector<const Elem *> all_active_neighbors;
1592  MeshBase & mesh = _mesh.getMesh();
1593 
1594  // Loop over all neighbors (at the the same level as the current element)
1595  for (MooseIndex(elem->n_neighbors()) i = 0; i < elem->n_neighbors(); ++i)
1596  {
1597  const Elem * neighbor_ancestor = nullptr;
1598  bool topological_neighbor = false;
1599 
1604  neighbor_ancestor = elem->neighbor_ptr(i);
1605  if (neighbor_ancestor)
1606  {
1607  if (neighbor_ancestor == libMesh::remote_elem)
1608  continue;
1609 
1610  neighbor_ancestor->active_family_tree_by_neighbor(all_active_neighbors, elem, false);
1611  }
1612  else
1613  {
1614  neighbor_ancestor = elem->topological_neighbor(i, mesh, *_point_locator, _pbs);
1615 
1623  if (neighbor_ancestor)
1624  {
1625  neighbor_ancestor->active_family_tree_by_topological_neighbor(
1626  all_active_neighbors, elem, mesh, *_point_locator, _pbs, false);
1627 
1628  topological_neighbor = true;
1629  }
1630  else
1631  {
1637  updateBBoxExtremesHelper(feature->_bboxes[0], *elem);
1638  }
1639  }
1640 
1641  visitNeighborsHelper(elem,
1642  all_active_neighbors,
1643  feature,
1644  expand_halos_only,
1645  topological_neighbor,
1646  disjoint_only);
1647 
1648  all_active_neighbors.clear();
1649  }
1650 }

Referenced by FeatureFloodCount::expandEdgeHalos(), and FeatureFloodCount::flood().

◆ visitNeighborsHelper()

template<typename T >
void FeatureFloodCount::visitNeighborsHelper ( const T *  curr_entity,
std::vector< const T * >  neighbor_entities,
FeatureData feature,
bool  expand_halos_only,
bool  topological_neighbor,
bool  disjoint_only 
)
protectedinherited

The actual logic for visiting neighbors is abstracted out here.

This method is templated to handle the Nodal and Elemental cases together.

Only recurse where we own this entity and it's a topologically connected entity. We shouldn't even attempt to flood to the periodic boundary because we won't have solution information and if we are using DistributedMesh we probably won't have geometric information either.

When we only recurse on entities we own, we can never get more than one away from a local entity which should be in the ghosted zone.

Premark neighboring entities with a halo mark. These entities may or may not end up being part of the feature. We will not update the _entities_visited data structure here.

Definition at line 1667 of file FeatureFloodCount.C.

1673 {
1674  // Loop over all active element neighbors
1675  for (const auto neighbor : neighbor_entities)
1676  {
1677  if (neighbor && (!_is_boundary_restricted || isBoundaryEntity(neighbor)))
1678  {
1679  if (expand_halos_only)
1680  {
1681  auto entity_id = neighbor->id();
1682 
1683  if (topological_neighbor || disjoint_only)
1684  feature->_disjoint_halo_ids.insert(feature->_disjoint_halo_ids.end(), entity_id);
1685  else if (feature->_local_ids.find(entity_id) == feature->_local_ids.end())
1686  feature->_halo_ids.insert(feature->_halo_ids.end(), entity_id);
1687  }
1688  else
1689  {
1690  auto my_processor_id = processor_id();
1691 
1692  if (!topological_neighbor && neighbor->processor_id() != my_processor_id)
1693  feature->_ghosted_ids.insert(feature->_ghosted_ids.end(), curr_entity->id());
1694 
1704  if (curr_entity->processor_id() == my_processor_id ||
1705  neighbor->processor_id() == my_processor_id)
1706  {
1713  if (topological_neighbor || disjoint_only)
1714  feature->_disjoint_halo_ids.insert(feature->_disjoint_halo_ids.end(), neighbor->id());
1715  else
1716  _entity_queue.push_front(neighbor);
1717  }
1718  }
1719  }
1720  }
1721 }

Referenced by FeatureFloodCount::visitElementalNeighbors(), and FeatureFloodCount::visitNodalNeighbors().

◆ visitNodalNeighbors()

void FeatureFloodCount::visitNodalNeighbors ( const Node *  node,
FeatureData feature,
bool  expand_halos_only 
)
protectedinherited

These two routines are utility routines used by the flood routine and by derived classes for visiting neighbors.

Since the logic is different for the elemental versus nodal case it's easier to split them up.

Definition at line 1653 of file FeatureFloodCount.C.

1656 {
1657  mooseAssert(node, "Node is NULL");
1658 
1659  std::vector<const Node *> all_active_neighbors;
1660  MeshTools::find_nodal_neighbors(_mesh.getMesh(), *node, _nodes_to_elem_map, all_active_neighbors);
1661 
1662  visitNeighborsHelper(node, all_active_neighbors, feature, expand_halos_only, false, false);
1663 }

Referenced by FeatureFloodCount::expandEdgeHalos(), and FeatureFloodCount::flood().

Member Data Documentation

◆ _all_boundary_entity_ids

std::unordered_set<dof_id_type> FeatureFloodCount::_all_boundary_entity_ids
protectedinherited

The set of entities on the boundary of the domain used for determining if features intersect any boundary.

Definition at line 711 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::meshChanged().

◆ _all_ranges

std::vector<std::pair<dof_id_type, dof_id_type> > GrainTracker::_all_ranges
privateinherited

Data structure to hold element ID ranges when using Distributed Mesh (populated on rank 0 only)

Definition at line 248 of file GrainTracker.h.

Referenced by GrainTracker::communicateHaloMap(), and GrainTracker::meshChanged().

◆ _bnd_elem_range

ConstBndElemRange* FeatureFloodCount::_bnd_elem_range
protectedinherited

Boundary element range pointer.

Definition at line 729 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::execute(), and FeatureFloodCount::isBoundaryEntity().

◆ _broadcast_update

const PerfID GrainTracker::_broadcast_update
privateinherited

Definition at line 254 of file GrainTracker.h.

Referenced by GrainTracker::broadcastAndUpdateGrainData().

◆ _C_ijkl

RankFourTensor GrainTrackerElasticity::_C_ijkl
protected

unrotated elasticity tensor

Definition at line 36 of file GrainTrackerElasticity.h.

Referenced by newGrain().

◆ _comm_and_merge

const PerfID FeatureFloodCount::_comm_and_merge
privateinherited

Definition at line 775 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::communicateAndMerge().

◆ _compute_halo_maps

const bool FeatureFloodCount::_compute_halo_maps
protectedinherited

Indicates whether or not to communicate halo map information with all ranks.

Definition at line 604 of file FeatureFloodCount.h.

Referenced by GrainTracker::communicateHaloMap(), GrainTracker::meshChanged(), GrainTracker::updateFieldInfo(), and FeatureFloodCount::updateFieldInfo().

◆ _compute_var_to_feature_map

const bool FeatureFloodCount::_compute_var_to_feature_map
protectedinherited

Indicates whether or not the var to feature map is populated.

Definition at line 607 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::getVarToFeatureVector(), GrainTracker::updateFieldInfo(), and FeatureFloodCount::updateFieldInfo().

◆ _condense_map_info

const bool FeatureFloodCount::_condense_map_info
protectedinherited

◆ _connecting_threshold

const Real FeatureFloodCount::_connecting_threshold
protectedinherited

The threshold above (or below) which neighboring entities are flooded (where regions can be extended but not started)

Definition at line 577 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::initialize().

◆ _consolidate_merged_features

const PerfID FeatureFloodCount::_consolidate_merged_features
privateinherited

Definition at line 779 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::consolidateMergedFeatures().

◆ _distribute_merge_work

const bool FeatureFloodCount::_distribute_merge_work
privateinherited

Keeps track of whether we are distributing the merge work.

Definition at line 769 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::communicateAndMerge().

◆ _dof_map

const DofMap& FeatureFloodCount::_dof_map
protectedinherited

Reference to the dof_map containing the coupled variables.

Definition at line 569 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::flood().

◆ _element_average_value

const PostprocessorValue& FeatureFloodCount::_element_average_value
protectedinherited

Average value of the domain which can optionally be used to find features in a field.

Definition at line 692 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::initialize().

◆ _empty_var_to_features

std::vector<unsigned int> FeatureFloodCount::_empty_var_to_features
protectedinherited

◆ _entities_visited

std::vector<std::set<dof_id_type> > FeatureFloodCount::_entities_visited
protectedinherited

This variable keeps track of which nodes have been visited during execution.

We don't use the _feature_map for this since we don't want to explicitly store data for all the unmarked nodes in a serialized datastructures. This keeps our overhead down since this variable never needs to be communicated.

Definition at line 631 of file FeatureFloodCount.h.

Referenced by PolycrystalUserObjectBase::execute(), FeatureFloodCount::flood(), FeatureFloodCount::initialize(), FeatureFloodCount::initialSetup(), and PolycrystalUserObjectBase::isNewFeatureOrConnectedRegion().

◆ _entity_queue

std::deque<const DofObject *> FeatureFloodCount::_entity_queue
privateinherited

The data structure for maintaining entities to flood during discovery.

Definition at line 766 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::flood(), and FeatureFloodCount::visitNeighborsHelper().

◆ _entity_var_to_features

std::map<dof_id_type, std::vector<unsigned int> > FeatureFloodCount::_entity_var_to_features
protectedinherited

◆ _error_on_grain_creation

const bool GrainTracker::_error_on_grain_creation
protectedinherited

Boolean to terminate with an error if a new grain is created during the simulation.

This is for simulations where new grains are not expected. Note, this does not impact the initial callback to newGrainCreated() nor does it get triggered for splitting grains.

Definition at line 232 of file GrainTracker.h.

Referenced by GrainTracker::trackGrains().

◆ _euler

const EulerAngleProvider& GrainTrackerElasticity::_euler
protected

object providing the Euler angles

Definition at line 39 of file GrainTrackerElasticity.h.

Referenced by newGrain().

◆ _execute_timer

const PerfID FeatureFloodCount::_execute_timer
privateinherited

Timers.

Definition at line 772 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::execute().

◆ _expand_halos

const PerfID FeatureFloodCount::_expand_halos
privateinherited

Definition at line 776 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::expandEdgeHalos().

◆ _fe_vars

std::vector<MooseVariableFEBase *> FeatureFloodCount::_fe_vars
protectedinherited

The vector of coupled in variables.

Definition at line 564 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::FeatureFloodCount(), and FeatureFloodCount::getFECoupledVars().

◆ _feature_count

unsigned int FeatureFloodCount::_feature_count
protectedinherited

◆ _feature_counts_per_map

std::vector<unsigned int> FeatureFloodCount::_feature_counts_per_map
protectedinherited

The number of features seen by this object per map.

Definition at line 645 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::consolidateMergedFeatures(), FeatureFloodCount::sortAndLabel(), and GrainTracker::trackGrains().

◆ _feature_id_to_local_index

std::vector<std::size_t> FeatureFloodCount::_feature_id_to_local_index
protectedinherited

◆ _feature_maps

std::vector<std::map<dof_id_type, int> > FeatureFloodCount::_feature_maps
protectedinherited

The feature maps contain the raw flooded node information and eventually the unique grain numbers.

We have a vector of them so we can create one per variable if that level of detail is desired.

Definition at line 678 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::getEntityValue(), FeatureFloodCount::initialize(), GrainTracker::updateFieldInfo(), and FeatureFloodCount::updateFieldInfo().

◆ _feature_sets

std::vector<FeatureData>& FeatureFloodCount::_feature_sets
protectedinherited

The data structure used to hold the globally unique features.

The sorting of the vector is implementation defined and may not correspond to anything useful. The ID of each feature should be queried from the FeatureData objects.

Definition at line 662 of file FeatureFloodCount.h.

Referenced by GrainTracker::assignGrains(), GrainTracker::attemptGrainRenumber(), GrainTracker::broadcastAndUpdateGrainData(), FeatureFloodCount::buildFeatureIdToLocalIndices(), PolycrystalUserObjectBase::buildGrainAdjacencyMatrix(), FeatureFloodCount::buildLocalToGlobalIndices(), GrainTracker::communicateHaloMap(), GrainTracker::computeMinDistancesFromGrain(), FeatureFloodCount::consolidateMergedFeatures(), FeatureFloodCount::doesFeatureIntersectBoundary(), GrainTracker::doesFeatureIntersectBoundary(), FeatureFloodCount::doesFeatureIntersectSpecifiedBoundary(), GrainTracker::doesFeatureIntersectSpecifiedBoundary(), FeatureFloodCount::featureCentroid(), PolycrystalUserObjectBase::finalize(), FeatureFloodCount::getEntityValue(), FeatureFloodCount::getFeatures(), FeatureFloodCount::getFeatureVar(), GrainTracker::getGrainCentroid(), GrainTracker::initialize(), FeatureFloodCount::initialize(), GrainTracker::isFeaturePercolated(), FeatureFloodCount::isFeaturePercolated(), GrainTracker::newGrainCreated(), GrainTracker::prepopulateState(), GrainTracker::remapGrains(), FeatureFloodCount::scatterAndUpdateRanks(), FeatureFloodCount::sortAndLabel(), GrainTracker::trackGrains(), GrainTracker::updateFieldInfo(), and FeatureFloodCount::updateFieldInfo().

◆ _feature_sets_old

std::vector<FeatureData> GrainTracker::_feature_sets_old
protectedinherited

This data structure holds the map of unique grains from the previous time step.

The information is updated each timestep to track grains over time.

Definition at line 211 of file GrainTracker.h.

Referenced by GrainTracker::initialize(), and GrainTracker::trackGrains().

◆ _finalize_timer

const PerfID GrainTracker::_finalize_timer
privateinherited

Timers.

Definition at line 251 of file GrainTracker.h.

Referenced by GrainTracker::finalize().

◆ _first_time

bool& GrainTracker::_first_time
protectedinherited

Boolean to indicate the first time this object executes.

Note: _tracking_step isn't enough if people skip initial or execute more than once per step.

Definition at line 225 of file GrainTracker.h.

Referenced by GrainTracker::assignGrains(), GrainTracker::execute(), GrainTracker::finalize(), GrainTracker::initialize(), GrainTracker::newGrainCreated(), GrainTracker::prepopulateState(), GrainTracker::trackGrains(), and GrainTracker::updateFieldInfo().

◆ _ghosted_entity_ids

std::map<dof_id_type, int> FeatureFloodCount::_ghosted_entity_ids
protectedinherited

The map for holding reconstructed ghosted element information.

Definition at line 695 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::getEntityValue(), FeatureFloodCount::initialize(), GrainTracker::updateFieldInfo(), and FeatureFloodCount::updateFieldInfo().

◆ _global_numbering

const bool FeatureFloodCount::_global_numbering
protectedinherited

This variable is used to indicate whether or not we identify features with unique numbers on multiple maps.

Definition at line 597 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::updateFieldInfo().

◆ _grain_data

std::vector<RankFourTensor > GrainDataTracker< RankFourTensor >::_grain_data
protectedinherited

per grain data

Definition at line 34 of file GrainDataTracker.h.

◆ _halo_ids

std::vector<std::map<dof_id_type, int> > FeatureFloodCount::_halo_ids
protectedinherited

The data structure for looking up halos around features.

The outer vector is for splitting out the information per variable. The inner map holds the actual halo information

Definition at line 701 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::FeatureData::clear(), GrainTracker::communicateHaloMap(), FeatureFloodCount::getEntityValue(), FeatureFloodCount::FeatureData::halosIntersect(), FeatureFloodCount::initialize(), FeatureFloodCount::FeatureData::merge(), GrainTracker::updateFieldInfo(), and FeatureFloodCount::updateFieldInfo().

◆ _halo_level

const unsigned short GrainTracker::_halo_level
protectedinherited

The thickness of the halo surrounding each grain.

Definition at line 183 of file GrainTracker.h.

Referenced by GrainTracker::finalize().

◆ _is_boundary_restricted

bool FeatureFloodCount::_is_boundary_restricted
protectedinherited

Indicates that this object should only run on one or more boundaries.

Definition at line 726 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::execute(), FeatureFloodCount::FeatureFloodCount(), and FeatureFloodCount::visitNeighborsHelper().

◆ _is_elemental

const bool FeatureFloodCount::_is_elemental
protectedinherited

◆ _is_master

const bool FeatureFloodCount::_is_master
protectedinherited

◆ _is_transient

const bool GrainTracker::_is_transient
privateinherited

Boolean to indicate whether this is a Steady or Transient solve.

Definition at line 245 of file GrainTracker.h.

Referenced by GrainTracker::swapSolutionValuesHelper().

◆ _local_to_global_feature_map

std::vector<std::size_t> FeatureFloodCount::_local_to_global_feature_map
protectedinherited

The vector recording the local to global feature indices.

Definition at line 681 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::scatterAndUpdateRanks().

◆ _maps_size

const std::size_t FeatureFloodCount::_maps_size
protectedinherited

◆ _max_curr_grain_id

unsigned int& GrainTracker::_max_curr_grain_id
privateinherited

Holds the next "regular" grain ID (a grain found or remapped to the standard op vars)

Definition at line 242 of file GrainTracker.h.

Referenced by GrainTracker::assignGrains(), GrainTracker::getNewGrainIDs(), GrainTracker::getNextUniqueID(), GrainTracker::getTotalFeatureCount(), and GrainTracker::trackGrains().

◆ _max_remap_recursion_depth

const unsigned short GrainTracker::_max_remap_recursion_depth
protectedinherited

Depth of renumbering recursion (a depth of zero means no recursion)

Definition at line 186 of file GrainTracker.h.

Referenced by GrainTracker::remapGrains().

◆ _merge_timer

const PerfID FeatureFloodCount::_merge_timer
privateinherited

Definition at line 773 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::mergeSets().

◆ _mesh

MooseMesh& FeatureFloodCount::_mesh
protectedinherited

◆ _n_procs

const processor_id_type FeatureFloodCount::_n_procs
protectedinherited

Convenience variable holding the number of processors in this simulation.

Definition at line 623 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::buildLocalToGlobalIndices(), and GrainTracker::communicateHaloMap().

◆ _n_reserve_ops

const unsigned short GrainTracker::_n_reserve_ops
protectedinherited

The number of reserved order parameters.

Definition at line 189 of file GrainTracker.h.

Referenced by GrainTracker::getNextUniqueID(), GrainTracker::trackGrains(), and GrainTracker::updateFieldInfo().

◆ _n_vars

const std::size_t FeatureFloodCount::_n_vars
protectedinherited

◆ _nl

NonlinearSystemBase& GrainTracker::_nl
protectedinherited

A reference to the nonlinear system (used for retrieving solution vectors)

Definition at line 205 of file GrainTracker.h.

Referenced by GrainTracker::remapGrains(), and GrainTracker::swapSolutionValuesHelper().

◆ _nodes_to_elem_map

std::vector<std::vector<const Elem *> > FeatureFloodCount::_nodes_to_elem_map
protectedinherited

The data structure used to find neighboring elements give a node ID.

Definition at line 642 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::meshChanged(), and FeatureFloodCount::visitNodalNeighbors().

◆ _old_max_grain_id

unsigned int GrainTracker::_old_max_grain_id
privateinherited

The previous max grain id (needed to figure out which ids are new in a given step)

Definition at line 239 of file GrainTracker.h.

Referenced by GrainTracker::getNewGrainIDs(), and GrainTracker::trackGrains().

◆ _partial_feature_sets

std::vector<std::list<FeatureData> > FeatureFloodCount::_partial_feature_sets
protectedinherited

The data structure used to hold partial and communicated feature data, during the discovery and merging phases.

The outer vector is indexed by map number (often variable number). The inner list is an unordered list of partially discovered features.

Definition at line 655 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::communicateAndMerge(), FeatureFloodCount::consolidateMergedFeatures(), FeatureFloodCount::deserialize(), FeatureFloodCount::expandEdgeHalos(), FeatureFloodCount::expandPointHalos(), FeatureFloodCount::flood(), FeatureFloodCount::initialize(), PolycrystalUserObjectBase::mergeSets(), FeatureFloodCount::mergeSets(), FeatureFloodCount::prepareDataForTransfer(), GrainTracker::prepopulateState(), FeatureFloodCount::scatterAndUpdateRanks(), and FeatureFloodCount::serialize().

◆ _pbs

PeriodicBoundaries* FeatureFloodCount::_pbs
protectedinherited

◆ _periodic_node_map

std::multimap<dof_id_type, dof_id_type> FeatureFloodCount::_periodic_node_map
protectedinherited

The data structure which is a list of nodes that are constrained to other nodes based on the imposed periodic boundary conditions.

Definition at line 707 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::appendPeriodicNeighborNodes(), FauxGrainTracker::getEntityValue(), FeatureFloodCount::getEntityValue(), and FeatureFloodCount::meshChanged().

◆ _point_locator

std::unique_ptr<PointLocatorBase> FeatureFloodCount::_point_locator
protectedinherited

◆ _poly_ic_uo

const PolycrystalUserObjectBase* GrainTracker::_poly_ic_uo
protectedinherited

An optional IC UserObject which can provide initial data structures to this object.

Definition at line 214 of file GrainTracker.h.

Referenced by GrainTracker::execute(), GrainTracker::finalize(), GrainTracker::GrainTracker(), and GrainTracker::updateFieldInfo().

◆ _prepare_for_transfer

const PerfID FeatureFloodCount::_prepare_for_transfer
privateinherited

Definition at line 778 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::prepareDataForTransfer().

◆ _primary_perc_bnds

std::vector<BoundaryID> FeatureFloodCount::_primary_perc_bnds
protectedinherited

◆ _random_rotations

const bool GrainTrackerElasticity::_random_rotations
protected

generate random rotations when the Euler Angle provider runs out of data (otherwise error out)

Definition at line 33 of file GrainTrackerElasticity.h.

Referenced by newGrain().

◆ _remap

const bool GrainTracker::_remap
protectedinherited

Inidicates whether remapping should be done or not (remapping is independent of tracking)

Definition at line 199 of file GrainTracker.h.

Referenced by GrainTracker::finalize().

◆ _remap_timer

const PerfID GrainTracker::_remap_timer
privateinherited

Definition at line 252 of file GrainTracker.h.

Referenced by GrainTracker::remapGrains().

◆ _reserve_grain_first_index

unsigned int GrainTracker::_reserve_grain_first_index
privateinherited

Holds the first unique grain index when using _reserve_op (all the remaining indices are sequential)

Definition at line 236 of file GrainTracker.h.

Referenced by GrainTracker::assignGrains(), GrainTracker::getNextUniqueID(), GrainTracker::trackGrains(), and GrainTracker::updateFieldInfo().

◆ _reserve_op_index

const std::size_t GrainTracker::_reserve_op_index
protectedinherited

The cutoff index where if variable index >= this number, no remapping TO that variable will occur.

Definition at line 193 of file GrainTracker.h.

Referenced by GrainTracker::computeMinDistancesFromGrain(), GrainTracker::getThreshold(), GrainTracker::remapGrains(), and GrainTracker::trackGrains().

◆ _reserve_op_threshold

const Real GrainTracker::_reserve_op_threshold
protectedinherited

The threshold above (or below) where a grain may be found on a reserve op field.

Definition at line 196 of file GrainTracker.h.

Referenced by GrainTracker::getThreshold().

◆ _secondary_perc_bnds

std::vector<BoundaryID> FeatureFloodCount::_secondary_perc_bnds
protectedinherited

◆ _single_map_mode

const bool FeatureFloodCount::_single_map_mode
protectedinherited

This variable is used to indicate whether or not multiple maps are used during flooding.

Definition at line 591 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::flood(), PolycrystalUserObjectBase::PolycrystalUserObjectBase(), FeatureFloodCount::sortAndLabel(), GrainTracker::updateFieldInfo(), and FeatureFloodCount::updateFieldInfo().

◆ _specified_bnds

std::vector<BoundaryID> FeatureFloodCount::_specified_bnds
protectedinherited

◆ _step_connecting_threshold

Real FeatureFloodCount::_step_connecting_threshold
protectedinherited

◆ _step_threshold

Real FeatureFloodCount::_step_threshold
protectedinherited

◆ _threshold

const Real FeatureFloodCount::_threshold
protectedinherited

The threshold above (or below) where an entity may begin a new region (feature)

Definition at line 572 of file FeatureFloodCount.h.

Referenced by FauxGrainTracker::execute(), and FeatureFloodCount::initialize().

◆ _tolerate_failure

const bool GrainTracker::_tolerate_failure
protectedinherited

Indicates whether we should continue after a remap failure (will result in non-physical results)

Definition at line 202 of file GrainTracker.h.

Referenced by GrainTracker::GrainTracker(), and GrainTracker::remapGrains().

◆ _track_grains

const PerfID GrainTracker::_track_grains
privateinherited

Definition at line 253 of file GrainTracker.h.

Referenced by GrainTracker::trackGrains().

◆ _tracking_step

const int GrainTracker::_tracking_step
protectedinherited

◆ _update_field_info

const PerfID GrainTracker::_update_field_info
privateinherited

Definition at line 255 of file GrainTracker.h.

Referenced by GrainTracker::updateFieldInfo().

◆ _use_less_than_threshold_comparison

const bool FeatureFloodCount::_use_less_than_threshold_comparison
protectedinherited

Use less-than when comparing values against the threshold value.

True by default. If false, then greater-than comparison is used instead.

Definition at line 614 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::compareValueWithThreshold(), and FauxGrainTracker::execute().

◆ _var_index_maps

std::vector<std::map<dof_id_type, int> > FeatureFloodCount::_var_index_maps
protectedinherited

This map keeps track of which variables own which nodes.

We need a vector of them for multimap mode where multiple variables can own a single mode.

Note: This map is only populated when "show_var_coloring" is set to true.

Definition at line 639 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::FeatureFloodCount(), FeatureFloodCount::getEntityValue(), FeatureFloodCount::initialize(), GrainTracker::updateFieldInfo(), and FeatureFloodCount::updateFieldInfo().

◆ _var_index_mode

const bool FeatureFloodCount::_var_index_mode
protectedinherited

This variable is used to indicate whether the maps will contain unique region information or just the variable numbers owning those regions.

Definition at line 601 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::FeatureFloodCount(), FeatureFloodCount::getEntityValue(), FeatureFloodCount::initialize(), GrainTracker::updateFieldInfo(), and FeatureFloodCount::updateFieldInfo().

◆ _var_number

unsigned long FeatureFloodCount::_var_number
protectedinherited

This variable is used to build the periodic node map.

Assumption: We are going to assume that either all variables are periodic or none are. This assumption can be relaxed at a later time if necessary.

Definition at line 588 of file FeatureFloodCount.h.

Referenced by GrainTracker::centroidRegionDistance(), and FeatureFloodCount::meshChanged().

◆ _vars

std::vector<MooseVariable *> FeatureFloodCount::_vars
protectedinherited

◆ _verbosity_level

const short GrainTracker::_verbosity_level
protectedinherited

Verbosity level controlling the amount of information printed to the console.

Definition at line 219 of file GrainTracker.h.

Referenced by GrainTracker::attemptGrainRenumber(), GrainTracker::finalize(), GrainTracker::remapGrains(), and GrainTracker::trackGrains().

◆ _volatile_feature_sets

std::vector<FeatureData> FeatureFloodCount::_volatile_feature_sets
protectedinherited

Derived objects (e.g.

the GrainTracker) may require restartable data to track information across time steps. The FeatureFloodCounter however does not. This container is here so that we have the flexabilty to switch between volatile and non-volatile storage. The _feature_sets data structure can conditionally refer to this structure or a MOOSE-provided structure, which is backed up.

Definition at line 671 of file FeatureFloodCount.h.

◆ invalid_id

const unsigned int FeatureFloodCount::invalid_id = std::numeric_limits<unsigned int>::max()
staticinherited

◆ invalid_size_t

const std::size_t FeatureFloodCount::invalid_size_t = std::numeric_limits<std::size_t>::max()
staticinherited

The documentation for this class was generated from the following files:
FeatureFloodCount::expandEdgeHalos
void expandEdgeHalos(unsigned int num_layers_to_expand)
This method expands the existing halo set by some width determined by the passed in value.
Definition: FeatureFloodCount.C:1527
GrainDataTracker< RankFourTensor >::newGrain
virtual RankFourTensor newGrain(unsigned int new_grain_id)=0
implement this method to initialize the data for the new grain
FeatureFloodCount::_var_index_mode
const bool _var_index_mode
This variable is used to indicate whether the maps will contain unique region information or just the...
Definition: FeatureFloodCount.h:601
GrainTracker::_reserve_grain_first_index
unsigned int _reserve_grain_first_index
Holds the first unique grain index when using _reserve_op (all the remaining indices are sequential)
Definition: GrainTracker.h:236
FeatureFloodCount::_condense_map_info
const bool _condense_map_info
Definition: FeatureFloodCount.h:593
GrainTracker::_halo_level
const unsigned short _halo_level
The thickness of the halo surrounding each grain.
Definition: GrainTracker.h:183
FeatureFloodCount::_secondary_perc_bnds
std::vector< BoundaryID > _secondary_perc_bnds
Definition: FeatureFloodCount.h:718
GrainTracker::assignGrains
void assignGrains()
When the tracking phase starts (_t_step == _tracking_step) it assigns a unique id to every FeatureDat...
Definition: GrainTracker.C:450
GrainTracker::_error_on_grain_creation
const bool _error_on_grain_creation
Boolean to terminate with an error if a new grain is created during the simulation.
Definition: GrainTracker.h:232
FeatureFloodCount::invalid_size_t
static const std::size_t invalid_size_t
Definition: FeatureFloodCount.h:93
FeatureFloodCount::scatterAndUpdateRanks
void scatterAndUpdateRanks()
Calls buildLocalToGlobalIndices to build the individual local to global indicies for each rank and sc...
Definition: FeatureFloodCount.C:717
FeatureFloodCount::_mesh
MooseMesh & _mesh
A reference to the mesh.
Definition: FeatureFloodCount.h:581
FeatureFloodCount::prepareDataForTransfer
void prepareDataForTransfer()
This routine uses the local flooded data to build up the local feature data structures (_feature_sets...
Definition: FeatureFloodCount.C:1017
FeatureFloodCount::getEntityValue
virtual Real getEntityValue(dof_id_type entity_id, FieldType field_type, std::size_t var_index=0) const
Definition: FeatureFloodCount.C:918
FeatureFloodCount::BoundaryIntersection::SECONDARY_PERCOLATION_BOUNDARY
FeatureFloodCount::getVarToFeatureVector
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.
Definition: FeatureFloodCount.C:701
FeatureFloodCount::_merge_timer
const PerfID _merge_timer
Definition: FeatureFloodCount.h:773
GrainTracker::_feature_sets_old
std::vector< FeatureData > _feature_sets_old
This data structure holds the map of unique grains from the previous time step.
Definition: GrainTracker.h:211
GrainTracker::_old_max_grain_id
unsigned int _old_max_grain_id
The previous max grain id (needed to figure out which ids are new in a given step)
Definition: GrainTracker.h:239
FeatureFloodCount::FeatureData::container_type
std::set< dof_id_type > container_type
The primary underlying container type used to hold the data in each FeatureData.
Definition: FeatureFloodCount.h:149
FeatureFloodCount::_comm_and_merge
const PerfID _comm_and_merge
Definition: FeatureFloodCount.h:775
FeatureFloodCount::Status
Status
This enumeration is used to indicate status of the grains in the _unique_grains data structure.
Definition: FeatureFloodCount.h:120
FeatureFloodCount::communicateAndMerge
void communicateAndMerge()
This routine handles all of the serialization, communication and deserialization of the data structur...
Definition: FeatureFloodCount.C:412
FeatureFloodCount::_entities_visited
std::vector< std::set< dof_id_type > > _entities_visited
This variable keeps track of which nodes have been visited during execution.
Definition: FeatureFloodCount.h:631
GrainTracker::newGrainCreated
virtual void newGrainCreated(unsigned int new_grain_id)
This method is called when a new grain is detected.
Definition: GrainTracker.C:880
FeatureFloodCount::getThreshold
virtual Real getThreshold(std::size_t current_index) const
Return the starting comparison threshold to use when inspecting an entity during the flood stage.
Definition: FeatureFloodCount.C:1407
GrainTrackerElasticity::_random_rotations
const bool _random_rotations
generate random rotations when the Euler Angle provider runs out of data (otherwise error out)
Definition: GrainTrackerElasticity.h:33
FeatureFloodCount::areFeaturesMergeable
virtual bool areFeaturesMergeable(const FeatureData &f1, const FeatureData &f2) const
Method for determining whether two features are mergeable.
Definition: FeatureFloodCount.C:1243
FeatureFloodCount::isBoundaryEntity
bool isBoundaryEntity(const T *entity) const
Returns a Boolean indicating whether the entity is on one of the desired boundaries.
Definition: FeatureFloodCount.C:1810
GrainTracker::_n_reserve_ops
const unsigned short _n_reserve_ops
The number of reserved order parameters.
Definition: GrainTracker.h:189
GrainTracker::boundingRegionDistance
Real boundingRegionDistance(std::vector< BoundingBox > &bboxes1, std::vector< BoundingBox > &bboxes2) const
This method returns the minimum periodic distance between two vectors of bounding boxes.
Definition: GrainTracker.C:1745
FeatureFloodCount::visitNodalNeighbors
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...
Definition: FeatureFloodCount.C:1653
FeatureFloodCount::_is_master
const bool _is_master
Convenience variable for testing master rank.
Definition: FeatureFloodCount.h:732
GrainTracker::updateFieldInfo
virtual void updateFieldInfo() override
This method is used to populate any of the data structures used for storing field data (nodal or elem...
Definition: GrainTracker.C:1553
GrainTracker::_broadcast_update
const PerfID _broadcast_update
Definition: GrainTracker.h:254
FeatureFloodCount::buildLocalToGlobalIndices
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 ...
Definition: FeatureFloodCount.C:619
FeatureFloodCount::_specified_bnds
std::vector< BoundaryID > _specified_bnds
Definition: FeatureFloodCount.h:720
GrainDistance
This struct is used to hold distance information to other grains in the simulation.
Definition: GrainTracker.h:263
FeatureFloodCount::initialize
virtual void initialize() override
Definition: FeatureFloodCount.C:298
GrainDataTracker< RankFourTensor >
FeatureFloodCount::Status::CLEAR
GrainTracker::RemapCacheMode::USE
FeatureFloodCount::BoundaryIntersection::SPECIFIED_BOUNDARY
counter
static unsigned int counter
Definition: ContactPenetrationAuxAction.C:17
FeatureFloodCount::sortAndLabel
void sortAndLabel()
Sort and assign ids to features based on their position in the container after sorting.
Definition: FeatureFloodCount.C:573
dataLoad
void dataLoad(std::istream &stream, FeatureFloodCount::FeatureData &feature, void *context)
Definition: FeatureFloodCount.C:64
FeatureFloodCount::consolidateMergedFeatures
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...
Definition: FeatureFloodCount.C:1176
FeatureFloodCount::sort
static void sort(std::set< T > &)
Definition: FeatureFloodCount.h:736
FeatureFloodCount::appendPeriodicNeighborNodes
void appendPeriodicNeighborNodes(FeatureData &feature) const
This routine adds the periodic node information to our data structure prior to packing the data this ...
Definition: FeatureFloodCount.C:1771
GrainTracker::broadcastAndUpdateGrainData
void broadcastAndUpdateGrainData()
Broadcast essential Grain information to all processors.
Definition: GrainTracker.C:388
FeatureFloodCount::_step_connecting_threshold
Real _step_connecting_threshold
Definition: FeatureFloodCount.h:578
GrainTracker::_poly_ic_uo
const PolycrystalUserObjectBase * _poly_ic_uo
An optional IC UserObject which can provide initial data structures to this object.
Definition: GrainTracker.h:214
FeatureFloodCount::_consolidate_merged_features
const PerfID _consolidate_merged_features
Definition: FeatureFloodCount.h:779
GrainTracker::prepopulateState
void prepopulateState(const FeatureFloodCount &ffc_object)
This method extracts the necessary state from the passed in object necessary to continue tracking gra...
Definition: GrainTracker.C:298
GrainTracker::computeMinDistancesFromGrain
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...
Definition: GrainTracker.C:1185
GrainTracker::swapSolutionValues
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.
Definition: GrainTracker.C:1434
FeatureFloodCount::getFeatures
const std::vector< FeatureData > & getFeatures() const
Return a constant reference to the vector of all discovered features.
Definition: FeatureFloodCount.h:340
FeatureFloodCount::visitNeighborsHelper
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.
Definition: FeatureFloodCount.C:1667
FeatureFloodCount::_var_number
unsigned long _var_number
This variable is used to build the periodic node map.
Definition: FeatureFloodCount.h:588
FeatureFloodCount::_feature_sets
std::vector< FeatureData > & _feature_sets
The data structure used to hold the globally unique features.
Definition: FeatureFloodCount.h:662
GrainTracker::RemapCacheMode::BYPASS
FeatureFloodCount::_entity_var_to_features
std::map< dof_id_type, std::vector< unsigned int > > _entity_var_to_features
Definition: FeatureFloodCount.h:713
GrainTrackerElasticity::_euler
const EulerAngleProvider & _euler
object providing the Euler angles
Definition: GrainTrackerElasticity.h:39
GrainTracker::swapSolutionValuesHelper
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.
Definition: GrainTracker.C:1473
GrainTracker::trackGrains
void trackGrains()
On subsequent time_steps, incoming FeatureData objects are compared to previous time_step information...
Definition: GrainTracker.C:497
FeatureFloodCount::getFeatureVar
virtual unsigned int getFeatureVar(unsigned int feature_id) const
Returns the variable representing the passed in feature.
Definition: FeatureFloodCount.C:809
GrainTracker::_max_curr_grain_id
unsigned int & _max_curr_grain_id
Holds the next "regular" grain ID (a grain found or remapped to the standard op vars)
Definition: GrainTracker.h:242
EulerAngleProvider::getGrainNum
virtual unsigned int getGrainNum() const =0
FeatureFloodCount::_nodes_to_elem_map
std::vector< std::vector< const Elem * > > _nodes_to_elem_map
The data structure used to find neighboring elements give a node ID.
Definition: FeatureFloodCount.h:642
FeatureFloodCount::_single_map_mode
const bool _single_map_mode
This variable is used to indicate whether or not multiple maps are used during flooding.
Definition: FeatureFloodCount.h:591
GrainTracker::_finalize_timer
const PerfID _finalize_timer
Timers.
Definition: GrainTracker.h:251
FeatureFloodCount::_point_locator
std::unique_ptr< PointLocatorBase > _point_locator
Definition: FeatureFloodCount.h:689
GrainTracker::_all_ranges
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)
Definition: GrainTracker.h:248
FeatureFloodCount::_use_less_than_threshold_comparison
const bool _use_less_than_threshold_comparison
Use less-than when comparing values against the threshold value.
Definition: FeatureFloodCount.h:614
GrainTracker::_remap
const bool _remap
Inidicates whether remapping should be done or not (remapping is independent of tracking)
Definition: GrainTracker.h:199
FeatureFloodCount::_ghosted_entity_ids
std::map< dof_id_type, int > _ghosted_entity_ids
The map for holding reconstructed ghosted element information.
Definition: FeatureFloodCount.h:695
FeatureFloodCount::_maps_size
const std::size_t _maps_size
Convenience variable holding the size of all the datastructures size by the number of maps.
Definition: FeatureFloodCount.h:620
GrainTracker::RemapCacheMode::FILL
FeatureFloodCount::_partial_feature_sets
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data, during the discovery and mergi...
Definition: FeatureFloodCount.h:655
GrainTracker::_nl
NonlinearSystemBase & _nl
A reference to the nonlinear system (used for retrieving solution vectors)
Definition: GrainTracker.h:205
FeatureFloodCount::_dof_map
const DofMap & _dof_map
Reference to the dof_map containing the coupled variables.
Definition: FeatureFloodCount.h:569
FeatureFloodCount::_fe_vars
std::vector< MooseVariableFEBase * > _fe_vars
The vector of coupled in variables.
Definition: FeatureFloodCount.h:564
RotationTensor
This is a RealTensor version of a rotation matrix It is instantiated with the Euler angles,...
Definition: RotationTensor.h:29
GrainTracker::centroidRegionDistance
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...
Definition: GrainTracker.C:1718
dataStore
void dataStore(std::ostream &stream, GrainTracker::PartialFeatureData &feature, void *context)
Definition: GrainTracker.C:28
FeatureFloodCount::_is_elemental
const bool _is_elemental
Determines if the flood counter is elements or not (nodes)
Definition: FeatureFloodCount.h:723
updateBBoxExtremesHelper
void updateBBoxExtremesHelper(BoundingBox &bbox, const Point &node)
Definition: FeatureFloodCount.C:2205
FeatureFloodCount::_empty_var_to_features
std::vector< unsigned int > _empty_var_to_features
Definition: FeatureFloodCount.h:715
GrainTracker::attemptGrainRenumber
bool attemptGrainRenumber(FeatureData &grain, unsigned int depth, unsigned int max_depth)
This is the recursive part of the remapping algorithm.
Definition: GrainTracker.C:1259
FeatureFloodCount::visitElementalNeighbors
void visitElementalNeighbors(const Elem *elem, FeatureData *feature, bool expand_halos_only, bool disjoint_only)
Definition: FeatureFloodCount.C:1584
FeatureFloodCount::_vars
std::vector< MooseVariable * > _vars
The vector of coupled in variables cast to MooseVariable.
Definition: FeatureFloodCount.h:566
FeatureFloodCount::_halo_ids
std::vector< std::map< dof_id_type, int > > _halo_ids
The data structure for looking up halos around features.
Definition: FeatureFloodCount.h:701
GrainTracker::_update_field_info
const PerfID _update_field_info
Definition: GrainTracker.h:255
FeatureFloodCount::execute
virtual void execute() override
Definition: FeatureFloodCount.C:358
FeatureFloodCount::invalid_id
static const unsigned int invalid_id
Definition: FeatureFloodCount.h:94
FeatureFloodCount::mergeSets
virtual void mergeSets()
This routine is called on the master rank only and stitches together the partial feature pieces seen ...
Definition: FeatureFloodCount.C:1121
GrainTracker::_is_transient
const bool _is_transient
Boolean to indicate whether this is a Steady or Transient solve.
Definition: GrainTracker.h:245
GrainTracker::_tracking_step
const int _tracking_step
The timestep to begin tracking grains.
Definition: GrainTracker.h:180
FeatureFloodCount::_pbs
PeriodicBoundaries * _pbs
A pointer to the periodic boundary constraints object.
Definition: FeatureFloodCount.h:687
FeatureFloodCount::clearDataStructures
virtual void clearDataStructures()
Helper routine for clearing up data structures during initialize and prior to parallel communication.
Definition: FeatureFloodCount.C:330
FeatureFloodCount::Status::INACTIVE
GrainTracker::_reserve_op_index
const std::size_t _reserve_op_index
The cutoff index where if variable index >= this number, no remapping TO that variable will occur.
Definition: GrainTracker.h:193
FeatureFloodCount::_feature_maps
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.
Definition: FeatureFloodCount.h:678
GrainTracker::_max_remap_recursion_depth
const unsigned short _max_remap_recursion_depth
Depth of renumbering recursion (a depth of zero means no recursion)
Definition: GrainTracker.h:186
FeatureFloodCount::compareValueWithThreshold
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.
Definition: FeatureFloodCount.C:1418
FeatureFloodCount::deserialize
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...
Definition: FeatureFloodCount.C:1086
EulerAngles::random
void random()
Definition: EulerAngles.C:73
FeatureFloodCount::_feature_id_to_local_index
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)
Definition: FeatureFloodCount.h:684
FeatureFloodCount::_distribute_merge_work
const bool _distribute_merge_work
Keeps track of whether we are distributing the merge work.
Definition: FeatureFloodCount.h:769
RankFourTensorTempl
Definition: ACGrGrElasticDrivingForce.h:20
FeatureFloodCount::_compute_halo_maps
const bool _compute_halo_maps
Indicates whether or not to communicate halo map information with all ranks.
Definition: FeatureFloodCount.h:604
FeatureFloodCount::BoundaryIntersection::ANY_BOUNDARY
GrainTracker::_reserve_op_threshold
const Real _reserve_op_threshold
The threshold above (or below) where a grain may be found on a reserve op field.
Definition: GrainTracker.h:196
dataLoad
void dataLoad(std::istream &stream, GrainTracker::PartialFeatureData &feature, void *context)
Definition: GrainTracker.C:38
PolycrystalUserObjectBase::getVariableValue
virtual Real getVariableValue(unsigned int op_index, const Point &p) const =0
Returns the variable value for a given op_index and mesh point.
FeatureFloodCount::getConnectingThreshold
virtual Real getConnectingThreshold(std::size_t current_index) const
Return the "connecting" comparison threshold to use when inspecting an entity during the flood stage.
Definition: FeatureFloodCount.C:1412
GrainTracker::_track_grains
const PerfID _track_grains
Definition: GrainTracker.h:253
GrainTracker::_verbosity_level
const short _verbosity_level
Verbosity level controlling the amount of information printed to the console.
Definition: GrainTracker.h:219
FeatureFloodCount::_feature_count
unsigned int _feature_count
The number of features seen by this object (same as summing _feature_counts_per_map)
Definition: FeatureFloodCount.h:648
GrainTracker::remapGrains
void remapGrains()
This method is called after trackGrains to remap grains that are too close to each other.
Definition: GrainTracker.C:913
GrainTracker::_tolerate_failure
const bool _tolerate_failure
Indicates whether we should continue after a remap failure (will result in non-physical results)
Definition: GrainTracker.h:202
GrainTracker::getNextUniqueID
unsigned int getNextUniqueID()
Retrieve the next unique grain number if a new grain is detected during trackGrains.
Definition: GrainTracker.C:1795
FeatureFloodCount::_is_boundary_restricted
bool _is_boundary_restricted
Indicates that this object should only run on one or more boundaries.
Definition: FeatureFloodCount.h:726
GrainDataTracker< RankFourTensor >::_grain_data
std::vector< RankFourTensor > _grain_data
per grain data
Definition: GrainDataTracker.h:34
FeatureFloodCount::isNewFeatureOrConnectedRegion
virtual bool isNewFeatureOrConnectedRegion(const DofObject *dof_object, std::size_t &current_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...
Definition: FeatureFloodCount.C:1425
FeatureFloodCount::Status::DIRTY
FeatureFloodCount::_bnd_elem_range
ConstBndElemRange * _bnd_elem_range
Boundary element range pointer.
Definition: FeatureFloodCount.h:729
FeatureFloodCount::buildFeatureIdToLocalIndices
void buildFeatureIdToLocalIndices(unsigned int max_id)
This method builds a lookup map for retrieving the right local feature (by index) given a global inde...
Definition: FeatureFloodCount.C:665
EulerAngles
Euler angle triplet.
Definition: EulerAngles.h:22
GrainTracker::_remap_timer
const PerfID _remap_timer
Definition: GrainTracker.h:252
FeatureFloodCount::BoundaryIntersection::NONE
FeatureFloodCount::_entity_queue
std::deque< const DofObject * > _entity_queue
The data structure for maintaining entities to flood during discovery.
Definition: FeatureFloodCount.h:766
FeatureFloodCount::_compute_var_to_feature_map
const bool _compute_var_to_feature_map
Indicates whether or not the var to feature map is populated.
Definition: FeatureFloodCount.h:607
GrainTrackerElasticity::_C_ijkl
RankFourTensor _C_ijkl
unrotated elasticity tensor
Definition: GrainTrackerElasticity.h:36
FeatureFloodCount::_periodic_node_map
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 ...
Definition: FeatureFloodCount.h:707
FeatureFloodCount::_step_threshold
Real _step_threshold
Definition: FeatureFloodCount.h:573
EulerAngleProvider::getEulerAngles
virtual const EulerAngles & getEulerAngles(unsigned int) const =0
FeatureFloodCount::_prepare_for_transfer
const PerfID _prepare_for_transfer
Definition: FeatureFloodCount.h:778
dataStore
void dataStore(std::ostream &stream, FeatureFloodCount::FeatureData &feature, void *context)
Definition: FeatureFloodCount.C:33
FeatureFloodCount::_n_procs
const processor_id_type _n_procs
Convenience variable holding the number of processors in this simulation.
Definition: FeatureFloodCount.h:623
FeatureFloodCount::_var_index_maps
std::vector< std::map< dof_id_type, int > > _var_index_maps
This map keeps track of which variables own which nodes.
Definition: FeatureFloodCount.h:639
FeatureFloodCount::_expand_halos
const PerfID _expand_halos
Definition: FeatureFloodCount.h:776
FeatureFloodCount::_n_vars
const std::size_t _n_vars
Definition: FeatureFloodCount.h:617
FeatureFloodCount::_local_to_global_feature_map
std::vector< std::size_t > _local_to_global_feature_map
The vector recording the local to global feature indices.
Definition: FeatureFloodCount.h:681
FeatureFloodCount::updateBoundaryIntersections
void updateBoundaryIntersections(FeatureData &feature) const
Update the feature's attributes to indicate boundary intersections.
Definition: FeatureFloodCount.C:1724
FeatureFloodCount::meshChanged
virtual void meshChanged() override
Definition: FeatureFloodCount.C:335
FeatureFloodCount::_feature_counts_per_map
std::vector< unsigned int > _feature_counts_per_map
The number of features seen by this object per map.
Definition: FeatureFloodCount.h:645
FeatureFloodCount::BoundaryIntersection::PRIMARY_PERCOLATION_BOUNDARY
FeatureFloodCount::_primary_perc_bnds
std::vector< BoundaryID > _primary_perc_bnds
Definition: FeatureFloodCount.h:717
FeatureFloodCount::serialize
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...
Definition: FeatureFloodCount.C:1067
FeatureFloodCount::Status::MARKED
GrainTracker::_first_time
bool & _first_time
Boolean to indicate the first time this object executes.
Definition: GrainTracker.h:225