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

#include <GrainTracker.h>

Inheritance diagram for GrainTracker:
[legend]

Classes

struct  CacheValues
 
struct  PartialFeatureData
 

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...
 

Public Member Functions

 GrainTracker (const InputParameters &parameters)
 
virtual ~GrainTracker ()
 
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 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 void meshChanged () override
 
virtual Real getValue () override
 
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...
 
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

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...
 
virtual void newGrainCreated (unsigned int new_grain_id)
 This method is called when a new grain is detected. 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< MeshTools::BoundingBox > &bboxes1, std::vector< MeshTools::BoundingBox > &bboxes2) const
 This method returns the minimum periodic distance between two vectors of bounding boxes. More...
 
Real centroidRegionDistance (std::vector< MeshTools::BoundingBox > &bboxes1, std::vector< MeshTools::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...
 
bool flood (const DofObject *dof_object, std::size_t current_index, FeatureData *feature)
 This method will "mark" all entities on neighboring elements that are above the supplied threshold. 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, std::size_t current_index, 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 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 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, std::size_t current_index, 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, std::size_t current_index, FeatureData *feature, bool expand_halos_only, bool disjoint_only)
 
void serialize (std::string &serialized_buffer)
 These routines packs/unpack the _feature_map data into a structure suitable for parallel communication operations. More...
 
void deserialize (std::vector< std::string > &serialized_buffers)
 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...
 

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 int _tracking_step
 The timestep to begin tracking grains. More...
 
const unsigned int _halo_level
 The thickness of the halo surrounding each grain. 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...
 
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...
 
bool _first_time
 Boolean to indicate the first time this object executes. More...
 
bool _error_on_grain_creation
 Boolean to terminate with an error if a new grain is created during the simulation. More...
 
std::vector< MooseVariable * > _vars
 The vector of coupled in 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. More...
 
std::vector< FeatureData > _feature_sets
 The data structure used to hold the globally unique features. 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::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
 
bool _is_elemental
 Determines if the flood counter is elements or not (nodes) More...
 
bool _is_master
 Convenience variable for testing master rank. More...
 

Static Protected Attributes

static const unsigned int _max_renumbering_recursion = 4
 Depth of renumbering recursion (a depth of zero means no recursion) More...
 

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...
 

Detailed Description

Definition at line 23 of file GrainTracker.h.

Member Enumeration Documentation

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

Definition at line 88 of file FeatureFloodCount.h.

89  {
90  UNIQUE_REGION,
91  VARIABLE_COLORING,
92  GHOSTED_ENTITIES,
93  HALOS,
94  CENTROID,
95  ACTIVE_BOUNDS,
96  };
Enumerator
FILL 
USE 
BYPASS 

Definition at line 51 of file GrainTracker.h.

52  {
53  FILL,
54  USE,
55  BYPASS
56  };
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 105 of file FeatureFloodCount.h.

105  : unsigned char
106  {
107  CLEAR = 0x0,
108  MARKED = 0x1,
109  DIRTY = 0x2,
110  INACTIVE = 0x4
111  };

Constructor & Destructor Documentation

GrainTracker::GrainTracker ( const InputParameters &  parameters)

Definition at line 56 of file GrainTracker.C.

57  : FeatureFloodCount(parameters),
59  _tracking_step(getParam<int>("tracking_step")),
60  _halo_level(getParam<unsigned int>("halo_level")),
61  _n_reserve_ops(getParam<unsigned short>("reserve_op")),
63  _reserve_op_threshold(getParam<Real>("reserve_op_threshold")),
64  _remap(getParam<bool>("remap_grains")),
65  _nl(_fe_problem.getNonlinearSystemBase()),
66  _feature_sets_old(declareRestartableData<std::vector<FeatureData>>("unique_grains")),
67  _poly_ic_uo(parameters.isParamValid("polycrystal_ic_uo")
68  ? &getUserObject<PolycrystalUserObjectBase>("polycrystal_ic_uo")
69  : nullptr),
70  _first_time(true),
71  _error_on_grain_creation(getParam<bool>("error_on_grain_creation")),
75  _is_transient(_subproblem.isTransient())
76 {
77  if (_tracking_step > 0 && _poly_ic_uo)
78  mooseError("Can't start tracking after the initial condition when using a polycrystal_ic_uo");
79 }
FeatureFloodCount(const InputParameters &parameters)
This class defines the interface for the GrainTracking objects.
const std::size_t _n_vars
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:228
NonlinearSystemBase & _nl
A reference to the nonlinear system (used for retrieving solution vectors)
Definition: GrainTracker.h:199
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:231
bool _first_time
Boolean to indicate the first time this object executes.
Definition: GrainTracker.h:214
const PolycrystalUserObjectBase * _poly_ic_uo
An optional IC UserObject which can provide initial data structures to this object.
Definition: GrainTracker.h:208
const Real _reserve_op_threshold
The threshold above (or below) where a grain may be found on a reserve op field.
Definition: GrainTracker.h:193
const unsigned int _halo_level
The thickness of the halo surrounding each grain.
Definition: GrainTracker.h:180
const bool _remap
Inidicates whether remapping should be done or not (remapping is independent of tracking) ...
Definition: GrainTracker.h:196
const bool _is_transient
Boolean to indicate whether this is a Steady or Transient solve.
Definition: GrainTracker.h:234
bool _error_on_grain_creation
Boolean to terminate with an error if a new grain is created during the simulation.
Definition: GrainTracker.h:221
const int _tracking_step
The timestep to begin tracking grains.
Definition: GrainTracker.h:177
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:225
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:190
std::vector< FeatureData > & _feature_sets_old
This data structure holds the map of unique grains from the previous time step.
Definition: GrainTracker.h:205
const unsigned short _n_reserve_ops
The number of reserved order parameters.
Definition: GrainTracker.h:186
GrainTracker::~GrainTracker ( )
virtual

Definition at line 81 of file GrainTracker.C.

81 {}

Member Function Documentation

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 1382 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::getFeatures(), and FeatureFloodCount::prepareDataForTransfer().

1383 {
1384  if (_is_elemental)
1385  {
1386  for (auto entity : feature._local_ids)
1387  {
1388  Elem * elem = _mesh.elemPtr(entity);
1389 
1390  for (auto node_n = decltype(elem->n_nodes())(0); node_n < elem->n_nodes(); ++node_n)
1391  {
1392  auto iters = _periodic_node_map.equal_range(elem->node(node_n));
1393 
1394  for (auto it = iters.first; it != iters.second; ++it)
1395  {
1396  feature._periodic_nodes.insert(it->first);
1397  feature._periodic_nodes.insert(it->second);
1398  }
1399  }
1400  }
1401  }
1402  else
1403  {
1404  for (auto entity : feature._local_ids)
1405  {
1406  auto iters = _periodic_node_map.equal_range(entity);
1407 
1408  for (auto it = iters.first; it != iters.second; ++it)
1409  {
1410  feature._periodic_nodes.insert(it->first);
1411  feature._periodic_nodes.insert(it->second);
1412  }
1413  }
1414  }
1415 }
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 ...
bool _is_elemental
Determines if the flood counter is elements or not (nodes)
MooseMesh & _mesh
A reference to the mesh.
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 933 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::getFeatures(), and FeatureFloodCount::mergeSets().

934 {
935  return f1.mergeable(f2);
936 }
void GrainTracker::assignGrains ( )
protected

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 357 of file GrainTracker.C.

Referenced by finalize().

358 {
359  mooseAssert(_first_time, "assignGrains may only be called on the first tracking step");
360 
366  if (_is_master)
367  {
368  mooseAssert(!_feature_sets.empty(), "Feature sets empty!");
369 
370  // Find the largest grain ID, this requires sorting if the ID is not already set
371  sortAndLabel();
373 
374  for (auto & grain : _feature_sets)
375  grain._status = Status::MARKED; // Mark the grain
376 
377  // Set up the first reserve grain index based on the largest grain ID
379  } // is_master
380 
381  /*************************************************************
382  ****************** COLLECTIVE WORK SECTION ******************
383  *************************************************************/
384 
385  // Make IDs on all non-master ranks consistent
387 
388  // Build up an id to index map
389  _communicator.broadcast(_max_curr_grain_id);
391 
392  // Now trigger the newGrainCreated() callback on all ranks
393  for (auto new_id = decltype(_max_curr_grain_id)(0); new_id <= _max_curr_grain_id; ++new_id)
394  newGrainCreated(new_id);
395 }
void sortAndLabel()
Sort and assign ids to features based on their position in the container after sorting.
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:231
bool _first_time
Boolean to indicate the first time this object executes.
Definition: GrainTracker.h:214
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
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:225
void buildFeatureIdToLocalIndices(unsigned int max_id)
This method builds a lookup map for retrieving the right local feature (by index) given a global inde...
void scatterAndUpdateRanks()
Calls buildLocalToGlobalIndices to build the individual local to global indicies for each rank and sc...
virtual void newGrainCreated(unsigned int new_grain_id)
This method is called when a new grain is detected.
Definition: GrainTracker.C:682
bool GrainTracker::attemptGrainRenumber ( FeatureData &  grain,
unsigned int  depth,
unsigned int  max_depth 
)
protected

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 1028 of file GrainTracker.C.

Referenced by remapGrains().

1029 {
1030  // End the recursion of our breadth first search
1031  if (depth > max_depth)
1032  return false;
1033 
1034  std::size_t curr_var_index = grain._var_index;
1035 
1036  std::vector<std::map<Node *, CacheValues>> cache;
1037 
1038  std::vector<std::list<GrainDistance>> min_distances(_vars.size());
1039 
1045  computeMinDistancesFromGrain(grain, min_distances);
1046 
1057  // clang-format off
1058  std::sort(min_distances.begin(), min_distances.end(),
1059  [](const std::list<GrainDistance> & lhs, const std::list<GrainDistance> & rhs)
1060  {
1061  // Sort lists in reverse order (largest distance first)
1062  // These empty cases are here to make this comparison stable
1063  if (lhs.empty())
1064  return false;
1065  else if (rhs.empty())
1066  return true;
1067  else
1068  return lhs.begin()->_distance > rhs.begin()->_distance;
1069  });
1070  // clang-format on
1071 
1072  for (auto & list_ref : min_distances)
1073  {
1074  const auto target_it = list_ref.begin();
1075  if (target_it == list_ref.end())
1076  continue;
1077 
1078  // If the distance is positive we can just remap and be done
1079  if (target_it->_distance > 0)
1080  {
1081  _console << COLOR_GREEN << "- Depth " << depth << ": Remapping grain #" << grain._id
1082  << " from variable index " << curr_var_index << " to " << target_it->_var_index;
1083  if (target_it->_distance == std::numeric_limits<Real>::max())
1084  _console << " which currently contains zero grains." << COLOR_DEFAULT;
1085  else
1086  _console << " whose closest grain (#" << target_it->_grain_id << ") is at a distance of "
1087  << target_it->_distance << "\n"
1088  << COLOR_DEFAULT;
1089 
1090  grain._status |= Status::DIRTY;
1091  grain._var_index = target_it->_var_index;
1092  return true;
1093  }
1094 
1095  // If the distance isn't positive we just need to make sure that none of the grains represented
1096  // by the target variable index would intersect this one if we were to remap
1097  auto next_target_it = target_it;
1098  bool intersection_hit = false;
1099  std::ostringstream oss;
1100  while (!intersection_hit && next_target_it != list_ref.end())
1101  {
1102  if (next_target_it->_distance > 0)
1103  break;
1104 
1105  mooseAssert(next_target_it->_grain_index < _feature_sets.size(),
1106  "Error in indexing target grain in attemptGrainRenumber");
1107  FeatureData & next_target_grain = _feature_sets[next_target_it->_grain_index];
1108 
1109  // If any grains touch we're done here
1110  if (grain.halosIntersect(next_target_grain))
1111  intersection_hit = true;
1112  else
1113  oss << " #" << next_target_it->_grain_id;
1114 
1115  ++next_target_it;
1116  }
1117 
1118  if (!intersection_hit)
1119  {
1120  _console << COLOR_GREEN << "- Depth " << depth << ": Remapping grain #" << grain._id
1121  << " from variable index " << curr_var_index << " to " << target_it->_var_index
1122  << " whose closest grain:" << oss.str()
1123  << " is inside our bounding box but whose halo(s) are not touching.\n"
1124  << COLOR_DEFAULT;
1125 
1126  grain._status |= Status::DIRTY;
1127  grain._var_index = target_it->_var_index;
1128  return true;
1129  }
1130 
1131  // If we reach this part of the loop, there is no simple renumbering that can be done.
1132  mooseAssert(target_it->_grain_index < _feature_sets.size(),
1133  "Error in indexing target grain in attemptGrainRenumber");
1134  FeatureData & target_grain = _feature_sets[target_it->_grain_index];
1135 
1143  if (target_it->_distance < -1)
1144  return false;
1145 
1146  // Make sure this grain isn't marked. If it is, we can't recurse here
1147  if ((target_grain._status & Status::MARKED) == Status::MARKED)
1148  return false;
1149 
1155  grain._var_index = target_it->_var_index;
1156  grain._status |= Status::MARKED;
1157  if (attemptGrainRenumber(target_grain, depth + 1, max_depth))
1158  {
1159  // SUCCESS!
1160  _console << COLOR_GREEN << "- Depth " << depth << ": Remapping grain #" << grain._id
1161  << " from variable index " << curr_var_index << " to " << target_it->_var_index
1162  << '\n'
1163  << COLOR_DEFAULT;
1164 
1165  // Now we need to mark the grain as DIRTY since the recursion succeeded.
1166  grain._status |= Status::DIRTY;
1167  return true;
1168  }
1169  else
1170  // FAILURE, We need to set our var index back after failed recursive step
1171  grain._var_index = curr_var_index;
1172 
1173  // ALWAYS "unmark" (or clear the MARKED status) after recursion so it can be used by other remap
1174  // operations
1175  grain._status &= ~Status::MARKED;
1176  }
1177 
1178  return false;
1179 }
Status
This enumeration is used to indicate status of the grains in the _unique_grains data structure...
std::vector< MooseVariable * > _vars
The vector of coupled in variables.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
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:954
bool attemptGrainRenumber(FeatureData &grain, unsigned int depth, unsigned int max_depth)
This is the recursive part of the remapping algorithm.
Real GrainTracker::boundingRegionDistance ( std::vector< MeshTools::BoundingBox > &  bboxes1,
std::vector< MeshTools::BoundingBox > &  bboxes2 
) const
protected

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 1463 of file GrainTracker.C.

Referenced by computeMinDistancesFromGrain().

1465 {
1472  auto min_distance = std::numeric_limits<Real>::max();
1473  for (const auto & bbox1 : bboxes1)
1474  {
1475  for (const auto & bbox2 : bboxes2)
1476  {
1477  // AABB squared distance
1478  Real curr_distance = 0.0;
1479  bool boxes_overlap = true;
1480  for (unsigned int dim = 0; dim < LIBMESH_DIM; ++dim)
1481  {
1482  const auto & min1 = bbox1.min()(dim);
1483  const auto & max1 = bbox1.max()(dim);
1484  const auto & min2 = bbox2.min()(dim);
1485  const auto & max2 = bbox2.max()(dim);
1486 
1487  if (min1 > max2)
1488  {
1489  const auto delta = max2 - min1;
1490  curr_distance += delta * delta;
1491  boxes_overlap = false;
1492  }
1493  else if (min2 > max1)
1494  {
1495  const auto delta = max1 - min2;
1496  curr_distance += delta * delta;
1497  boxes_overlap = false;
1498  }
1499  }
1500 
1501  if (boxes_overlap)
1502  return -1.0; /* all overlaps are treated the same */
1503 
1504  if (curr_distance < min_distance)
1505  min_distance = curr_distance;
1506  }
1507  }
1508 
1509  return min_distance;
1510 }
void GrainTracker::broadcastAndUpdateGrainData ( )
protected

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 297 of file GrainTracker.C.

Referenced by finalize().

298 {
299  std::vector<PartialFeatureData> root_feature_data;
300  std::vector<std::string> send_buffer(1), recv_buffer;
301 
302  if (_is_master)
303  {
304  root_feature_data.reserve(_feature_sets.size());
305 
306  // Populate a subset of the information in a small data structure
307  std::transform(_feature_sets.begin(),
308  _feature_sets.end(),
309  std::back_inserter(root_feature_data),
310  [](FeatureData & feature) {
311  PartialFeatureData partial_feature;
312  partial_feature.intersects_boundary = feature._intersects_boundary;
313  partial_feature.id = feature._id;
314  partial_feature.centroid = feature._centroid;
315  partial_feature.status = feature._status;
316  return partial_feature;
317  });
318 
319  std::ostringstream oss;
320  dataStore(oss, root_feature_data, this);
321  send_buffer[0].assign(oss.str());
322  }
323 
324  // Broadcast the data to all ranks
325  _communicator.broadcast_packed_range((void *)(nullptr),
326  send_buffer.begin(),
327  send_buffer.end(),
328  (void *)(nullptr),
329  std::back_inserter(recv_buffer));
330 
331  // Unpack and update
332  if (!_is_master)
333  {
334  std::istringstream iss;
335  iss.str(recv_buffer[0]);
336  iss.clear();
337 
338  dataLoad(iss, root_feature_data, this);
339 
340  for (const auto & partial_data : root_feature_data)
341  {
342  // See if this processor has a record of this grain
343  if (partial_data.id < _feature_id_to_local_index.size() &&
344  _feature_id_to_local_index[partial_data.id] != invalid_size_t)
345  {
346  auto & grain = _feature_sets[_feature_id_to_local_index[partial_data.id]];
347  grain._intersects_boundary = partial_data.intersects_boundary;
348  grain._centroid = partial_data.centroid;
349  if (partial_data.status == Status::INACTIVE)
350  grain._status = Status::INACTIVE;
351  }
352  }
353  }
354 }
static const std::size_t invalid_size_t
void dataLoad(std::istream &stream, GrainTracker::PartialFeatureData &feature, void *context)
Definition: GrainTracker.C:36
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
std::vector< std::size_t > _feature_id_to_local_index
The vector recording the grain_id to local index (several indices will contain invalid_size_t) ...
void dataStore(std::ostream &stream, GrainTracker::PartialFeatureData &feature, void *context)
Definition: GrainTracker.C:26
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 453 of file FeatureFloodCount.C.

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

454 {
455  _feature_id_to_local_index.assign(max_id + 1, invalid_size_t);
456  for (auto feature_index = beginIndex(_feature_sets); feature_index < _feature_sets.size();
457  ++feature_index)
458  {
459  if (_feature_sets[feature_index]._status != Status::INACTIVE)
460  {
461  mooseAssert(_feature_sets[feature_index]._id <= max_id,
462  "Feature ID out of range(" << _feature_sets[feature_index]._id << ')');
463  _feature_id_to_local_index[_feature_sets[feature_index]._id] = feature_index;
464  }
465  }
466 }
static const std::size_t invalid_size_t
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
std::vector< std::size_t > _feature_id_to_local_index
The vector recording the grain_id to local index (several indices will contain invalid_size_t) ...
void 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 407 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::getFeatures(), and FeatureFloodCount::scatterAndUpdateRanks().

409 {
410  mooseAssert(_is_master, "This method must only be called on the root processor");
411 
412  counts.assign(_n_procs, 0);
413  // Now size the individual counts vectors based on the largest index seen per processor
414  for (const auto & feature : _feature_sets)
415  for (const auto & local_index_pair : feature._orig_ids)
416  {
417  // local_index_pair.first = ranks, local_index_pair.second = local_index
418  mooseAssert(local_index_pair.first < _n_procs, "Processor ID is out of range");
419  if (local_index_pair.second >= static_cast<std::size_t>(counts[local_index_pair.first]))
420  counts[local_index_pair.first] = local_index_pair.second + 1;
421  }
422 
423  // Build the offsets vector
424  unsigned int globalsize = 0;
425  std::vector<int> offsets(_n_procs); // Type is signed for use with the MPI API
426  for (auto i = beginIndex(offsets); i < offsets.size(); ++i)
427  {
428  offsets[i] = globalsize;
429  globalsize += counts[i];
430  }
431 
432  // Finally populate the master vector
433  local_to_global_all.resize(globalsize, FeatureFloodCount::invalid_size_t);
434  for (const auto & feature : _feature_sets)
435  {
436  // Get the local indices from the feature and build a map
437  for (const auto & local_index_pair : feature._orig_ids)
438  {
439  auto rank = local_index_pair.first;
440  mooseAssert(rank < _n_procs, rank << ", " << _n_procs);
441 
442  auto local_index = local_index_pair.second;
443  auto stacked_local_index = offsets[rank] + local_index;
444 
445  mooseAssert(stacked_local_index < globalsize,
446  "Global index: " << stacked_local_index << " is out of range");
447  local_to_global_all[stacked_local_index] = feature._id;
448  }
449  }
450 }
static const std::size_t invalid_size_t
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
const processor_id_type _n_procs
Convenience variable holding the number of processors in this simulation.
Real GrainTracker::centroidRegionDistance ( std::vector< MeshTools::BoundingBox > &  bboxes1,
std::vector< MeshTools::BoundingBox > &  bboxes2 
) const
protected

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 1436 of file GrainTracker.C.

Referenced by trackGrains().

1438 {
1442  auto min_distance = std::numeric_limits<Real>::max();
1443  for (const auto & bbox1 : bboxes1)
1444  {
1445  const auto centroid_point1 = (bbox1.max() + bbox1.min()) / 2.0;
1446 
1447  for (const auto & bbox2 : bboxes2)
1448  {
1449  const auto centroid_point2 = (bbox2.max() + bbox2.min()) / 2.0;
1450 
1451  // Here we'll calculate a distance between the centroids
1452  auto curr_distance = _mesh.minPeriodicDistance(_var_number, centroid_point1, centroid_point2);
1453 
1454  if (curr_distance < min_distance)
1455  min_distance = curr_distance;
1456  }
1457  }
1458 
1459  return min_distance;
1460 }
unsigned long _var_number
This variable is used to build the periodic node map.
MooseMesh & _mesh
A reference to the mesh.
void FeatureFloodCount::clearDataStructures ( )
protectedvirtualinherited

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

Definition at line 252 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::communicateAndMerge(), and FeatureFloodCount::getFeatures().

253 {
254 }
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.

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

Definition at line 308 of file FeatureFloodCount.C.

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

309 {
310  // First we need to transform the raw data into a usable data structure
312 
320  std::vector<std::string> send_buffers(1);
321 
328  std::vector<std::string> recv_buffers;
329  if (_is_master)
330  recv_buffers.reserve(_app.n_processors());
331 
332  serialize(send_buffers[0]);
333 
334  // Free up as much memory as possible here before we do global communication
336 
341  _communicator.gather_packed_range(0,
342  (void *)(nullptr),
343  send_buffers.begin(),
344  send_buffers.end(),
345  std::back_inserter(recv_buffers));
346 
347  if (_is_master)
348  {
349  // The root process now needs to deserialize and merge all of the data
350  deserialize(recv_buffers);
351  recv_buffers.clear();
352 
353  mergeSets();
354  }
355 
356  // Make sure that feature count is communicated to all ranks
357  _communicator.broadcast(_feature_count);
358 }
void serialize(std::string &serialized_buffer)
These routines packs/unpack the _feature_map data into a structure suitable for parallel communicatio...
void deserialize(std::vector< std::string > &serialized_buffers)
This routine takes the vector of byte buffers (one for each processor), deserializes them into a seri...
bool _is_master
Convenience variable for testing master rank.
virtual void clearDataStructures()
Helper routine for clearing up data structures during initialize and prior to parallel communication...
unsigned int _feature_count
The number of features seen by this object (same as summing _feature_counts_per_map) ...
void mergeSets()
This routine is called on the master rank only and stitches together the partial feature pieces seen ...
void prepareDataForTransfer()
This routine uses the local flooded data to build up the local feature data structures (_feature_sets...
void GrainTracker::communicateHaloMap ( )
protected

Definition at line 1379 of file GrainTracker.C.

Referenced by updateFieldInfo().

1380 {
1381  if (_compute_halo_maps)
1382  {
1383  // rank var_index entity_id
1384  std::vector<std::pair<std::size_t, dof_id_type>> halo_ids_all;
1385 
1386  std::vector<int> counts;
1387  std::vector<std::pair<std::size_t, dof_id_type>> local_halo_ids;
1388  std::size_t counter = 0;
1389 
1390  if (_is_master)
1391  {
1392  std::vector<std::vector<std::pair<std::size_t, dof_id_type>>> root_halo_ids(_n_procs);
1393  counts.resize(_n_procs);
1394 
1395  auto & mesh = _mesh.getMesh();
1396  // Loop over the _halo_ids "field" and build minimal lists for all of the other ranks
1397  for (auto var_index = beginIndex(_halo_ids); var_index < _halo_ids.size(); ++var_index)
1398  {
1399  for (const auto & entity_pair : _halo_ids[var_index])
1400  {
1401  DofObject * halo_entity;
1402  if (_is_elemental)
1403  halo_entity = mesh.elem(entity_pair.first);
1404  else
1405  halo_entity = &mesh.node(entity_pair.first);
1406 
1407  root_halo_ids[halo_entity->processor_id()].push_back(
1408  std::make_pair(var_index, entity_pair.first));
1409  }
1410  }
1411 
1412  // Build up the counts vector for MPI scatter
1413  std::size_t global_count = 0;
1414  for (const auto & vector_ref : root_halo_ids)
1415  {
1416  std::copy(vector_ref.begin(), vector_ref.end(), std::back_inserter(halo_ids_all));
1417  counts[counter] = vector_ref.size();
1418  global_count += counts[counter++];
1419  }
1420  }
1421 
1422  _communicator.scatter(halo_ids_all, counts, local_halo_ids);
1423 
1424  // Now add the contributions from the root process to the processor local maps
1425  for (const auto & halo_pair : local_halo_ids)
1426  _halo_ids[halo_pair.first].emplace(std::make_pair(halo_pair.second, halo_pair.first));
1427 
1428  // Finally remove halo markings from stitch regions
1429  for (const auto & grain : _feature_sets)
1430  for (auto local_id : grain._local_ids)
1431  _halo_ids[grain._var_index].erase(local_id);
1432  }
1433 }
std::vector< std::map< dof_id_type, int > > _halo_ids
The data structure for looking up halos around features.
bool _is_elemental
Determines if the flood counter is elements or not (nodes)
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
const bool _compute_halo_maps
Indicates whether or not to communicate halo map information with all ranks.
const processor_id_type _n_procs
Convenience variable holding the number of processors in this simulation.
MooseMesh & _mesh
A reference to the mesh.
static unsigned int counter
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 1083 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::getFeatures(), and FeatureFloodCount::isNewFeatureOrConnectedRegion().

1084 {
1085  return ((_use_less_than_threshold_comparison && (entity_value >= threshold)) ||
1086  (!_use_less_than_threshold_comparison && (entity_value <= threshold)));
1087 }
const bool _use_less_than_threshold_comparison
Use less-than when comparing values against the threshold value.
void GrainTracker::computeMinDistancesFromGrain ( FeatureData &  grain,
std::vector< std::list< GrainDistance >> &  min_distances 
)
protected

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 954 of file GrainTracker.C.

Referenced by attemptGrainRenumber().

956 {
980  for (auto i = beginIndex(_feature_sets); i < _feature_sets.size(); ++i)
981  {
982  auto & other_grain = _feature_sets[i];
983 
984  if (other_grain._var_index == grain._var_index || other_grain._var_index >= _reserve_op_index)
985  continue;
986 
987  auto target_var_index = other_grain._var_index;
988  auto target_grain_index = i;
989  auto target_grain_id = other_grain._id;
990 
991  Real curr_bbox_diff = boundingRegionDistance(grain._bboxes, other_grain._bboxes);
992 
993  GrainDistance grain_distance_obj(
994  curr_bbox_diff, target_var_index, target_grain_index, target_grain_id);
995 
996  // To handle touching halos we penalize the top pick each time we see another
997  if (curr_bbox_diff == -1.0 && !min_distances[target_var_index].empty())
998  {
999  Real last_distance = min_distances[target_var_index].begin()->_distance;
1000  if (last_distance < 0)
1001  grain_distance_obj._distance += last_distance;
1002  }
1003 
1004  // Insertion sort into a list
1005  auto insert_it = min_distances[target_var_index].begin();
1006  while (insert_it != min_distances[target_var_index].end() && !(grain_distance_obj < *insert_it))
1007  ++insert_it;
1008  min_distances[target_var_index].insert(insert_it, grain_distance_obj);
1009  }
1010 
1016  for (auto var_index = beginIndex(_vars); var_index < _reserve_op_index; ++var_index)
1017  {
1018  // Don't put an entry in for matching variable indices (i.e. we can't remap to ourselves)
1019  if (grain._var_index == var_index)
1020  continue;
1021 
1022  if (min_distances[var_index].empty())
1023  min_distances[var_index].emplace_front(std::numeric_limits<Real>::max(), var_index);
1024  }
1025 }
This struct is used to hold distance information to other grains in the simulation.
Definition: GrainTracker.h:241
std::vector< MooseVariable * > _vars
The vector of coupled in variables.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
Real boundingRegionDistance(std::vector< MeshTools::BoundingBox > &bboxes1, std::vector< MeshTools::BoundingBox > &bboxes2) const
This method returns the minimum periodic distance between two vectors of bounding boxes...
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:190
void FeatureFloodCount::deserialize ( std::vector< std::string > &  serialized_buffers)
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.

We should already have the local processor data in the features data structure. Don't unpack the local buffer again.

Definition at line 801 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::communicateAndMerge(), and FeatureFloodCount::getFeatures().

802 {
803  // The input string stream used for deserialization
804  std::istringstream iss;
805 
806  mooseAssert(serialized_buffers.size() == _app.n_processors(),
807  "Unexpected size of serialized_buffers: " << serialized_buffers.size());
808  auto rank = processor_id();
809  for (auto proc_id = beginIndex(serialized_buffers); proc_id < serialized_buffers.size();
810  ++proc_id)
811  {
816  if (proc_id == rank)
817  continue;
818 
819  iss.str(serialized_buffers[proc_id]); // populate the stream with a new buffer
820  iss.clear(); // reset the string stream state
821 
822  // Load the communicated data into all of the other processors' slots
823  dataLoad(iss, _partial_feature_sets, this);
824  }
825 }
void dataLoad(std::istream &stream, FeatureFloodCount::FeatureData &feature, void *context)
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data.
bool GrainTracker::doesFeatureIntersectBoundary ( unsigned int  feature_id) const
overridevirtual

Returns a Boolean indicating whether this feature intersects any boundary.

Reimplemented from FeatureFloodCount.

Definition at line 139 of file GrainTracker.C.

140 {
141  // TODO: This data structure may need to be turned into a Multimap
142  mooseAssert(feature_id < _feature_id_to_local_index.size(), "Grain ID out of bounds");
143 
144  auto feature_index = _feature_id_to_local_index[feature_id];
145  if (feature_index != invalid_size_t)
146  {
147  mooseAssert(feature_index < _feature_sets.size(), "Grain index out of bounds");
148  return _feature_sets[feature_index]._intersects_boundary;
149  }
150 
151  return false;
152 }
static const std::size_t invalid_size_t
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
std::vector< std::size_t > _feature_id_to_local_index
The vector recording the grain_id to local index (several indices will contain invalid_size_t) ...
void GrainTracker::execute ( )
overridevirtual

Reimplemented from FeatureFloodCount.

Definition at line 173 of file GrainTracker.C.

174 {
175  // Don't track grains if the current simulation step is before the specified tracking step
176  if (_t_step < _tracking_step)
177  return;
178 
179  if (_poly_ic_uo && _first_time)
180  return;
181 
182  Moose::perf_log.push("execute()", "GrainTracker");
184  Moose::perf_log.pop("execute()", "GrainTracker");
185 }
bool _first_time
Boolean to indicate the first time this object executes.
Definition: GrainTracker.h:214
virtual void execute() override
const PolycrystalUserObjectBase * _poly_ic_uo
An optional IC UserObject which can provide initial data structures to this object.
Definition: GrainTracker.h:208
const int _tracking_step
The timestep to begin tracking grains.
Definition: GrainTracker.h:177
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 1189 of file FeatureFloodCount.C.

Referenced by finalize(), PolycrystalUserObjectBase::finalize(), and FeatureFloodCount::getFeatures().

1190 {
1191  if (num_layers_to_expand == 0)
1192  return;
1193 
1194  for (auto & list_ref : _partial_feature_sets)
1195  {
1196  for (auto & feature : list_ref)
1197  {
1198  for (auto halo_level = decltype(num_layers_to_expand)(0); halo_level < num_layers_to_expand;
1199  ++halo_level)
1200  {
1205  std::set<dof_id_type> orig_halo_ids(feature._halo_ids);
1206  for (auto entity : orig_halo_ids)
1207  {
1208  if (_is_elemental)
1209  visitElementalNeighbors(_mesh.elemPtr(entity),
1210  feature._var_index,
1211  &feature,
1212  /*expand_halos_only =*/true,
1213  /*disjoint_only =*/false);
1214  else
1215  visitNodalNeighbors(_mesh.nodePtr(entity),
1216  feature._var_index,
1217  &feature,
1218  /*expand_halos_only =*/true);
1219  }
1220 
1225  std::set<dof_id_type> disjoint_orig_halo_ids(feature._disjoint_halo_ids);
1226  for (auto entity : disjoint_orig_halo_ids)
1227  {
1228  if (_is_elemental)
1229  visitElementalNeighbors(_mesh.elemPtr(entity),
1230  feature._var_index,
1231  &feature,
1232  /*expand_halos_only =*/true,
1233  /*disjoint_only =*/true);
1234  else
1235  visitNodalNeighbors(_mesh.nodePtr(entity),
1236  feature._var_index,
1237  &feature,
1238  /*expand_halos_only =*/true);
1239  }
1240  }
1241  }
1242  }
1243 }
void visitElementalNeighbors(const Elem *elem, std::size_t current_index, FeatureData *feature, bool expand_halos_only, bool disjoint_only)
void visitNodalNeighbors(const Node *node, std::size_t current_index, FeatureData *feature, bool expand_halos_only)
These two routines are utility routines used by the flood routine and by derived classes for visiting...
bool _is_elemental
Determines if the flood counter is elements or not (nodes)
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data.
MooseMesh & _mesh
A reference to the mesh.
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 1130 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::getFeatures().

1131 {
1132  const auto & node_to_elem_map = _mesh.nodeToActiveSemilocalElemMap();
1133  decltype(FeatureData::_local_ids) expanded_local_ids;
1134  auto my_processor_id = processor_id();
1135 
1142  for (auto & list_ref : _partial_feature_sets)
1143  {
1144  for (auto & feature : list_ref)
1145  {
1146  expanded_local_ids.clear();
1147 
1148  for (auto entity : feature._local_ids)
1149  {
1150  const Elem * elem = _mesh.elemPtr(entity);
1151  mooseAssert(elem, "elem pointer is NULL");
1152 
1153  // Get the nodes on a current element so that we can add in point neighbors
1154  auto n_nodes = elem->n_vertices();
1155  for (auto i = decltype(n_nodes)(0); i < n_nodes; ++i)
1156  {
1157  const Node * current_node = elem->get_node(i);
1158 
1159  auto elem_vector_it = node_to_elem_map.find(current_node->id());
1160  if (elem_vector_it == node_to_elem_map.end())
1161  mooseError("Error in node to elem map");
1162 
1163  const auto & elem_vector = elem_vector_it->second;
1164 
1165  expanded_local_ids.insert(elem_vector.begin(), elem_vector.end());
1166 
1167  // Now see which elements need to go into the ghosted set
1168  for (auto entity : elem_vector)
1169  {
1170  const Elem * neighbor = _mesh.elemPtr(entity);
1171  mooseAssert(neighbor, "neighbor pointer is NULL");
1172 
1173  if (neighbor->processor_id() != my_processor_id)
1174  feature._ghosted_ids.insert(elem->id());
1175  }
1176  }
1177  }
1178 
1179  // Replace the existing local ids with the expanded local ids
1180  feature._local_ids.swap(expanded_local_ids);
1181 
1182  // Copy the expanded local_ids into the halo_ids container
1183  feature._halo_ids = feature._local_ids;
1184  }
1185  }
1186 }
std::set< dof_id_type > _local_ids
Holds the local ids in the interior of a feature.
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data.
MooseMesh & _mesh
A reference to the mesh.
void GrainTracker::finalize ( )
overridevirtual

Some perf_log operations appear here instead of inside of the named routines because of multiple return paths.

Assign or Track Grains

Broadcast essential data

Remap Grains

Reimplemented from FeatureFloodCount.

Definition at line 232 of file GrainTracker.C.

233 {
239  // Don't track grains if the current simulation step is before the specified tracking step
240  if (_t_step < _tracking_step)
241  return;
242 
243  Moose::perf_log.push("finalize()", "GrainTracker");
244 
245  // Expand the depth of the halos around all grains
246  auto num_halo_layers = _halo_level >= 1
247  ? _halo_level - 1
248  : 0; // The first level of halos already exists so subtract one
249 
250  if (_poly_ic_uo && _first_time)
252  else
253  {
254  expandEdgeHalos(num_halo_layers);
255 
256  // Build up the grain map on the root processor
258  }
259 
263  Moose::perf_log.push("trackGrains()", "GrainTracker");
264  if (_first_time)
265  assignGrains();
266  else
267  trackGrains();
268  Moose::perf_log.pop("trackGrains()", "GrainTracker");
269  _console << "Finished inside of trackGrains" << std::endl;
270 
275 
279  Moose::perf_log.push("remapGrains()", "GrainTracker");
280  if (_remap)
281  remapGrains();
282  Moose::perf_log.pop("remapGrains()", "GrainTracker");
283 
284  updateFieldInfo();
285  _console << "Finished inside of updateFieldInfo" << std::endl;
286 
287  // Set the first time flag false here (after all methods of finalize() have completed)
288  _first_time = false;
289 
290  // TODO: Release non essential memory
291 
292  _console << "Finished inside of GrainTracker" << std::endl;
293  Moose::perf_log.pop("finalize()", "GrainTracker");
294 }
void remapGrains()
This method is called after trackGrains to remap grains that are too close to each other...
Definition: GrainTracker.C:715
void expandEdgeHalos(unsigned int num_layers_to_expand)
This method expands the existing halo set by some width determined by the passed in value...
void trackGrains()
On subsequent time_steps, incoming FeatureData objects are compared to previous time_step information...
Definition: GrainTracker.C:398
void communicateAndMerge()
This routine handles all of the serialization, communication and deserialization of the data structur...
virtual void updateFieldInfo() override
This method is used to populate any of the data structures used for storing field data (nodal or elem...
bool _first_time
Boolean to indicate the first time this object executes.
Definition: GrainTracker.h:214
const PolycrystalUserObjectBase * _poly_ic_uo
An optional IC UserObject which can provide initial data structures to this object.
Definition: GrainTracker.h:208
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:200
void broadcastAndUpdateGrainData()
Broadcast essential Grain information to all processors.
Definition: GrainTracker.C:297
const unsigned int _halo_level
The thickness of the halo surrounding each grain.
Definition: GrainTracker.h:180
const bool _remap
Inidicates whether remapping should be done or not (remapping is independent of tracking) ...
Definition: GrainTracker.h:196
void assignGrains()
When the tracking phase starts (_t_step == _tracking_step) it assigns a unique id to every FeatureDat...
Definition: GrainTracker.C:357
const int _tracking_step
The timestep to begin tracking grains.
Definition: GrainTracker.h:177
bool FeatureFloodCount::flood ( const DofObject *  dof_object,
std::size_t  current_index,
FeatureData feature 
)
protectedinherited

This method will "mark" all entities on neighboring elements that are above the supplied threshold.

If feature is NULL, we are exploring for a new region to mark, otherwise we are in the recursive calls currently marking a region.

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

If we reach this point (i.e. we haven't returned early from this routine), 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 984 of file FeatureFloodCount.C.

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

987 {
988  if (dof_object == nullptr)
989  return false;
990 
991  // Retrieve the id of the current entity
992  auto entity_id = dof_object->id();
993 
994  // Has this entity already been marked? - if so move along
995  if (current_index != invalid_size_t &&
996  _entities_visited[current_index].find(entity_id) != _entities_visited[current_index].end())
997  return false;
998 
999  // See if the current entity either starts a new feature or continues an existing feature
1000  auto new_id = invalid_id; // Writable reference to hold an optional id;
1001  Status status =
1002  Status::INACTIVE; // Status is inactive until we find an entity above the starting threshold
1003  if (!isNewFeatureOrConnectedRegion(dof_object, current_index, feature, status, new_id))
1004  return false;
1005 
1006  mooseAssert(current_index != invalid_size_t, "current_index is invalid");
1007 
1016  _entities_visited[current_index].emplace(entity_id);
1017 
1018  auto map_num = _single_map_mode ? decltype(current_index)(0) : current_index;
1019 
1020  // New Feature (we need to create it and add it to our data structure)
1021  if (!feature)
1022  {
1023  _partial_feature_sets[map_num].emplace_back(
1024  current_index, _feature_count++, processor_id(), status);
1025 
1026  // Get a handle to the feature we will update (always the last feature in the data structure)
1027  feature = &_partial_feature_sets[map_num].back();
1028 
1029  // If new_id is valid, we'll set it in the feature here.
1030  if (new_id != invalid_id)
1031  feature->_id = new_id;
1032  }
1033 
1034  // Insert the current entity into the local ids map
1035  feature->_local_ids.insert(entity_id);
1036 
1042  if (_is_elemental && processor_id() == dof_object->processor_id())
1043  {
1044  const Elem * elem = static_cast<const Elem *>(dof_object);
1045 
1046  // Keep track of how many elements participate in the centroid averaging
1047  feature->_vol_count++;
1048 
1049  // Sum the centroid values for now, we'll average them later
1050  feature->_centroid += elem->centroid();
1051 
1052  // Does the volume intersect the boundary?
1053  if (_all_boundary_entity_ids.find(elem->id()) != _all_boundary_entity_ids.end())
1054  feature->_intersects_boundary = true;
1055  }
1056 
1057  if (_is_elemental)
1058  visitElementalNeighbors(static_cast<const Elem *>(dof_object),
1059  current_index,
1060  feature,
1061  /*expand_halos_only =*/false,
1062  /*disjoint_only =*/false);
1063  else
1064  visitNodalNeighbors(static_cast<const Node *>(dof_object),
1065  current_index,
1066  feature,
1067  /*expand_halos_only =*/false);
1068 
1069  return true;
1070 }
void visitElementalNeighbors(const Elem *elem, std::size_t current_index, FeatureData *feature, bool expand_halos_only, bool disjoint_only)
static const std::size_t invalid_size_t
Status
This enumeration is used to indicate status of the grains in the _unique_grains data structure...
std::vector< std::set< dof_id_type > > _entities_visited
This variable keeps track of which nodes have been visited during execution.
void visitNodalNeighbors(const Node *node, std::size_t current_index, FeatureData *feature, bool expand_halos_only)
These two routines are utility routines used by the flood routine and by derived classes for visiting...
bool _is_elemental
Determines if the flood counter is elements or not (nodes)
std::set< dof_id_type > _all_boundary_entity_ids
The set of entities on the boundary of the domain used for determining if features intersect any boun...
static const unsigned int invalid_id
const bool _single_map_mode
This variable is used to indicate whether or not multiple maps are used during flooding.
unsigned int _feature_count
The number of features seen by this object (same as summing _feature_counts_per_map) ...
virtual 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...
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data.
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 1077 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::getFeatures(), and FeatureFloodCount::isNewFeatureOrConnectedRegion().

1078 {
1080 }
const std::vector<MooseVariable *>& FeatureFloodCount::getCoupledVars ( ) const
inlineinherited

Returns a const vector to the coupled variable pointers.

Definition at line 86 of file FeatureFloodCount.h.

Referenced by AverageGrainVolume::AverageGrainVolume().

86 { return _vars; }
std::vector< MooseVariable * > _vars
The vector of coupled in variables.
Real GrainTracker::getEntityValue ( dof_id_type  node_id,
FieldType  field_type,
std::size_t  var_index = 0 
) const
overridevirtual

Reimplemented from FeatureFloodCount.

Definition at line 84 of file GrainTracker.C.

Referenced by EulerAngleProvider2RGBAux::precalculateValue(), and OutputEulerAngles::precalculateValue().

87 {
88  if (_t_step < _tracking_step)
89  return 0;
90 
91  return FeatureFloodCount::getEntityValue(entity_id, field_type, var_index);
92 }
virtual Real getEntityValue(dof_id_type entity_id, FieldType field_type, std::size_t var_index=0) const
const int _tracking_step
The timestep to begin tracking grains.
Definition: GrainTracker.h:177
const std::vector<FeatureData>& FeatureFloodCount::getFeatures ( ) const
inlineinherited

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

Definition at line 290 of file FeatureFloodCount.h.

Referenced by prepopulateState().

290 { return _feature_sets; }
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
unsigned int GrainTracker::getFeatureVar ( unsigned int  feature_id) const
overridevirtual

Returns the variable representing the passed in feature.

Reimplemented from FeatureFloodCount.

Definition at line 101 of file GrainTracker.C.

102 {
103  return FeatureFloodCount::getFeatureVar(feature_id);
104 }
virtual unsigned int getFeatureVar(unsigned int feature_id) const
Returns the variable representing the passed in feature.
Point GrainTracker::getGrainCentroid ( unsigned int  grain_id) const
overridevirtual

Returns the centroid for the given grain number.

Implements GrainTrackerInterface.

Definition at line 121 of file GrainTracker.C.

122 {
123  mooseAssert(grain_id < _feature_id_to_local_index.size(), "Grain ID out of bounds");
124  auto grain_index = _feature_id_to_local_index[grain_id];
125 
126  if (grain_index != invalid_size_t)
127  {
128  mooseAssert(_feature_id_to_local_index[grain_id] < _feature_sets.size(),
129  "Grain index out of bounds");
130  // Note: This value is parallel consistent, see GrainTracker::broadcastAndUpdateGrainData()
131  return _feature_sets[_feature_id_to_local_index[grain_id]]._centroid;
132  }
133 
134  // Inactive grain
135  return Point();
136 }
static const std::size_t invalid_size_t
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
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) ...
std::vector< unsigned int > GrainTracker::getNewGrainIDs ( ) const
overridevirtual

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

Reimplemented from GrainTrackerInterface.

Definition at line 703 of file GrainTracker.C.

704 {
705  std::vector<unsigned int> new_ids(_max_curr_grain_id - _old_max_grain_id);
706  auto new_id = _old_max_grain_id + 1;
707 
708  // Generate the new ids
709  std::iota(new_ids.begin(), new_ids.end(), new_id);
710 
711  return new_ids;
712 }
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:228
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:231
unsigned int GrainTracker::getNextUniqueID ( )
protected

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 1513 of file GrainTracker.C.

Referenced by trackGrains().

1514 {
1522  _max_curr_grain_id = std::max(_max_curr_grain_id + 1,
1523  _reserve_grain_first_index + _n_reserve_ops /* no +1 here!*/);
1524 
1525  return _max_curr_grain_id;
1526 }
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:231
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:225
const unsigned short _n_reserve_ops
The number of reserved order parameters.
Definition: GrainTracker.h:186
std::size_t GrainTracker::getNumberActiveGrains ( ) const
overridevirtual

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 enountered in EBSD datasets).

Implements GrainTrackerInterface.

Definition at line 107 of file GrainTracker.C.

108 {
109  // Note: This value is parallel consistent, see FeatureFloodCount::communicateAndMerge()
110  return _feature_count;
111 }
unsigned int _feature_count
The number of features seen by this object (same as summing _feature_counts_per_map) ...
Real GrainTracker::getThreshold ( std::size_t  current_index) const
overrideprotectedvirtual

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

Reimplemented from FeatureFloodCount.

Definition at line 188 of file GrainTracker.C.

189 {
190  // If we are inspecting a reserve op parameter, we need to make sure
191  // that there is an entity above the reserve_op threshold before
192  // starting the flood of the feature.
193  if (var_index >= _reserve_op_index)
194  return _reserve_op_threshold;
195  else
196  return _step_threshold;
197 }
const Real _reserve_op_threshold
The threshold above (or below) where a grain may be found on a reserve op field.
Definition: GrainTracker.h:193
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:190
std::size_t GrainTracker::getTotalFeatureCount ( ) const
overridevirtual

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 114 of file GrainTracker.C.

115 {
116  // Note: This value is parallel consistent, see assignGrains()/trackGrains()
117  return _max_curr_grain_id + 1;
118 }
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:231
Real FeatureFloodCount::getValue ( )
overridevirtualinherited

Reimplemented in FauxGrainTracker.

Definition at line 570 of file FeatureFloodCount.C.

571 {
572  return static_cast<Real>(_feature_count);
573 }
unsigned int _feature_count
The number of features seen by this object (same as summing _feature_counts_per_map) ...
const std::vector< unsigned int > & GrainTracker::getVarToFeatureVector ( dof_id_type  elem_id) const
overridevirtual

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 95 of file GrainTracker.C.

Referenced by ComputePolycrystalElasticityTensor::computeQpElasticityTensor().

96 {
98 }
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.
void GrainTracker::initialize ( )
overridevirtual

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 155 of file GrainTracker.C.

156 {
157  // Don't track grains if the current simulation step is before the specified tracking step
158  if (_t_step < _tracking_step)
159  return;
160 
166  if (!_first_time)
168 
170 }
virtual void initialize() override
bool _first_time
Boolean to indicate the first time this object executes.
Definition: GrainTracker.h:214
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
const int _tracking_step
The timestep to begin tracking grains.
Definition: GrainTracker.h:177
std::vector< FeatureData > & _feature_sets_old
This data structure holds the map of unique grains from the previous time step.
Definition: GrainTracker.h:205
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 199 of file FeatureFloodCount.C.

Referenced by PolycrystalUserObjectBase::initialSetup().

200 {
201  // We need one map per coupled variable for normal runs to support overlapping features
202  _entities_visited.resize(_vars.size());
203 
204  // Get a pointer to the PeriodicBoundaries buried in libMesh
205  _pbs = _fe_problem.getNonlinearSystemBase().dofMap().get_periodic_boundaries();
206 
207  meshChanged();
208 
217 }
const std::size_t _n_vars
std::vector< std::set< dof_id_type > > _entities_visited
This variable keeps track of which nodes have been visited during execution.
std::vector< MooseVariable * > _vars
The vector of coupled in variables.
static const unsigned int invalid_id
PeriodicBoundaries * _pbs
A pointer to the periodic boundary constraints object.
std::vector< unsigned int > _empty_var_to_features
virtual void meshChanged() override
bool FeatureFloodCount::isElemental ( ) const
inlineinherited

Definition at line 102 of file FeatureFloodCount.h.

Referenced by FeatureFloodCountAux::FeatureFloodCountAux().

102 { return _is_elemental; }
bool _is_elemental
Determines if the flood counter is elements or not (nodes)
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 1090 of file FeatureFloodCount.C.

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

1095 {
1096  // Get the value of the current variable for the current entity
1097  Real entity_value;
1098  if (_is_elemental)
1099  {
1100  const Elem * elem = static_cast<const Elem *>(dof_object);
1101  std::vector<Point> centroid(1, elem->centroid());
1102  _subproblem.reinitElemPhys(elem, centroid, 0);
1103  entity_value = _vars[current_index]->sln()[0];
1104  }
1105  else
1106  entity_value = _vars[current_index]->getNodalValue(*static_cast<const Node *>(dof_object));
1107 
1108  // If the value compares against our starting threshold, this is definitely part of a feature
1109  // we'll keep
1110  if (compareValueWithThreshold(entity_value, getThreshold(current_index)))
1111  {
1112  Status * status_ptr = &status;
1113 
1114  if (feature)
1115  status_ptr = &feature->_status;
1116 
1117  // Update an existing feature's status or clear the flag on the passed in status
1118  *status_ptr &= ~Status::INACTIVE;
1119  return true;
1120  }
1121 
1126  return compareValueWithThreshold(entity_value, getConnectingThreshold(current_index));
1127 }
Status
This enumeration is used to indicate status of the grains in the _unique_grains data structure...
virtual Real getThreshold(std::size_t current_index) const
Return the starting comparison threshold to use when inspecting an entity during the flood stage...
std::vector< MooseVariable * > _vars
The vector of coupled in variables.
bool _is_elemental
Determines if the flood counter is elements or not (nodes)
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...
virtual Real getConnectingThreshold(std::size_t current_index) const
Return the "connecting" comparison threshold to use when inspecting an entity during the flood stage...
void FeatureFloodCount::mergeSets ( )
protectedinherited

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.

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 828 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::communicateAndMerge(), and FeatureFloodCount::getFeatures().

829 {
830  Moose::perf_log.push("mergeSets()", "FeatureFloodCount");
831 
832  // Since we gathered only on the root process, we only need to merge sets on the root process.
833  mooseAssert(_is_master, "mergeSets() should only be called on the root process");
834 
835  // Local variable used for sizing structures, it will be >= the actual number of features
836  for (auto map_num = decltype(_maps_size)(0); map_num < _maps_size; ++map_num)
837  {
838  for (auto it1 = _partial_feature_sets[map_num].begin();
839  it1 != _partial_feature_sets[map_num].end();
840  /* No increment on it1 */)
841  {
842  bool merge_occured = false;
843  for (auto it2 = _partial_feature_sets[map_num].begin();
844  it2 != _partial_feature_sets[map_num].end();
845  ++it2)
846  {
847  if (it1 != it2 && areFeaturesMergeable(*it1, *it2))
848  {
849  it2->merge(std::move(*it1));
850 
855  _partial_feature_sets[map_num].emplace_back(std::move(*it2));
856 
866  _partial_feature_sets[map_num].erase(it2);
867  it1 = _partial_feature_sets[map_num].erase(it1); // it1 is incremented here!
868 
869  // A merge occurred, this is used to determine whether or not we increment the outer
870  // iterator
871  merge_occured = true;
872 
873  // We need to start the list comparison over for the new it1 so break here
874  break;
875  }
876  } // it2 loop
877 
878  if (!merge_occured) // No merges so we need to manually increment the outer iterator
879  ++it1;
880 
881  } // it1 loop
882  } // map loop
883 
891  // Offset where the current set of features with the same variable id starts in the flat vector
892  unsigned int feature_offset = 0;
893  // Set the member feature count to zero and start counting the actual features
894  _feature_count = 0;
895 
896  for (auto map_num = decltype(_maps_size)(0); map_num < _maps_size; ++map_num)
897  {
898  std::set<dof_id_type> set_difference;
899  for (auto & feature : _partial_feature_sets[map_num])
900  {
901  // If after merging we still have an inactive feature, discard it
902  if (feature._status == Status::CLEAR)
903  {
904  // First we need to calculate the centroid now that we are doing merging all partial
905  // features
906  if (feature._vol_count != 0)
907  feature._centroid /= feature._vol_count;
908 
909  _feature_sets.emplace_back(std::move(feature));
910  ++_feature_count;
911  }
912  }
913 
914  // Record the feature numbers just for the current map
915  _feature_counts_per_map[map_num] = _feature_count - feature_offset;
916 
917  // Now update the running feature count so we can calculate the next map's contribution
918  feature_offset = _feature_count;
919 
920  // Clean up the "moved" objects
921  _partial_feature_sets[map_num].clear();
922  }
923 
929  Moose::perf_log.pop("mergeSets()", "FeatureFloodCount");
930 }
virtual bool areFeaturesMergeable(const FeatureData &f1, const FeatureData &f2) const
Method for determining whether two features are mergeable.
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
const std::size_t _maps_size
Convenience variable holding the size of all the datastructures size by the number of maps...
unsigned int _feature_count
The number of features seen by this object (same as summing _feature_counts_per_map) ...
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data.
std::vector< unsigned int > _feature_counts_per_map
The number of features seen by this object per map.
void FeatureFloodCount::meshChanged ( )
overridevirtualinherited

We need to build a set containing all of the boundary entities to compare against. This will be elements for elemental flooding. Volumes for nodal flooding is not supported

Definition at line 257 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::initialSetup().

258 {
259  _point_locator = _mesh.getMesh().sub_point_locator();
260 
261  _mesh.buildPeriodicNodeMap(_periodic_node_map, _var_number, _pbs);
262 
263  // Build a new node to element map
264  _nodes_to_elem_map.clear();
265  MeshTools::build_nodes_to_elem_map(_mesh.getMesh(), _nodes_to_elem_map);
266 
272  _all_boundary_entity_ids.clear();
273  if (_is_elemental)
274  for (auto elem_it = _mesh.bndElemsBegin(), elem_end = _mesh.bndElemsEnd(); elem_it != elem_end;
275  ++elem_it)
276  _all_boundary_entity_ids.insert((*elem_it)->_elem->id());
277 }
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 ...
bool _is_elemental
Determines if the flood counter is elements or not (nodes)
std::set< dof_id_type > _all_boundary_entity_ids
The set of entities on the boundary of the domain used for determining if features intersect any boun...
unsigned long _var_number
This variable is used to build the periodic node map.
std::vector< std::vector< const Elem * > > _nodes_to_elem_map
The data structure used to find neighboring elements give a node ID.
std::unique_ptr< PointLocatorBase > _point_locator
PeriodicBoundaries * _pbs
A pointer to the periodic boundary constraints object.
MooseMesh & _mesh
A reference to the mesh.
void GrainTracker::newGrainCreated ( unsigned int  new_grain_id)
protectedvirtual

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 in GrainDataTracker< T >, and GrainDataTracker< RankFourTensor >.

Definition at line 682 of file GrainTracker.C.

Referenced by assignGrains(), and trackGrains().

683 {
684  if (!_first_time && _is_master)
685  {
686  mooseAssert(new_grain_id < _feature_id_to_local_index.size(), "new_grain_id is out of bounds");
687  auto grain_index = _feature_id_to_local_index[new_grain_id];
688  mooseAssert(grain_index != invalid_size_t && grain_index < _feature_sets.size(),
689  "new_grain_id appears to be invalid");
690 
691  const auto & grain = _feature_sets[grain_index];
692  _console << COLOR_YELLOW
693  << "\n*****************************************************************************"
694  << "\nCouldn't find a matching grain while working on variable index: "
695  << grain._var_index << "\nCreating new unique grain: " << new_grain_id << '\n'
696  << grain
697  << "\n*****************************************************************************\n"
698  << COLOR_DEFAULT;
699  }
700 }
static const std::size_t invalid_size_t
bool _first_time
Boolean to indicate the first time this object executes.
Definition: GrainTracker.h:214
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
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) ...
std::size_t FeatureFloodCount::numCoupledVars ( ) const
inlineinherited

Returns the number of coupled varaibles.

Definition at line 77 of file FeatureFloodCount.h.

77 { return _n_vars; }
const std::size_t _n_vars
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).

We need to adjust the halo markings before sending. We need to discard all of the local cell information but not any of the stitch region information. To do that we subtract off the ghosted cells from the local cells and use that in the set difference operation with the halo_ids.

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

Definition at line 721 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::communicateAndMerge(), and FeatureFloodCount::getFeatures().

722 {
723  MeshBase & mesh = _mesh.getMesh();
724 
725  std::set<dof_id_type> local_ids_no_ghost, set_difference;
726 
727  for (auto & list_ref : _partial_feature_sets)
728  {
729  for (auto & feature : list_ref)
730  {
731  // Now extend the bounding box by the halo region
732  if (_is_elemental)
733  feature.updateBBoxExtremes(mesh);
734  else
735  {
736  for (auto & halo_id : feature._halo_ids)
737  updateBBoxExtremesHelper(feature._bboxes[0], mesh.node(halo_id));
738  }
739 
746  std::set_difference(feature._local_ids.begin(),
747  feature._local_ids.end(),
748  feature._ghosted_ids.begin(),
749  feature._ghosted_ids.end(),
750  std::insert_iterator<std::set<dof_id_type>>(local_ids_no_ghost,
751  local_ids_no_ghost.begin()));
752 
753  std::set_difference(
754  feature._halo_ids.begin(),
755  feature._halo_ids.end(),
756  local_ids_no_ghost.begin(),
757  local_ids_no_ghost.end(),
758  std::insert_iterator<std::set<dof_id_type>>(set_difference, set_difference.begin()));
759  feature._halo_ids.swap(set_difference);
760  local_ids_no_ghost.clear();
761  set_difference.clear();
762 
763  mooseAssert(!feature._local_ids.empty(), "local entity ids cannot be empty");
764 
769  feature._min_entity_id = *feature._local_ids.begin();
770 
771  // Periodic node ids
773  }
774  }
775 }
void appendPeriodicNeighborNodes(FeatureData &feature) const
This routine adds the periodic node information to our data structure prior to packing the data this ...
bool _is_elemental
Determines if the flood counter is elements or not (nodes)
void updateBBoxExtremesHelper(MeshTools::BoundingBox &bbox, const Point &node)
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data.
MooseMesh & _mesh
A reference to the mesh.
void GrainTracker::prepopulateState ( const FeatureFloodCount ffc_object)
protected

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 200 of file GrainTracker.C.

Referenced by finalize().

201 {
202  mooseAssert(_first_time, "This method should only be called on the first invocation");
203 
204  _feature_sets.clear();
205 
211  if (_is_master)
212  {
213  const auto & features = ffc_object.getFeatures();
214  for (auto & feature : features)
215  _feature_sets.emplace_back(feature.duplicate());
216 
217  _feature_count = _feature_sets.size();
218  }
219  else
220  {
221  const auto & features = ffc_object.getFeatures();
222  _partial_feature_sets[0].clear();
223  for (auto & feature : features)
224  _partial_feature_sets[0].emplace_back(feature.duplicate());
225  }
226 
227  // Make sure that feature count is communicated to all ranks
228  _communicator.broadcast(_feature_count);
229 }
const std::vector< FeatureData > & getFeatures() const
Return a constant reference to the vector of all discovered features.
bool _first_time
Boolean to indicate the first time this object executes.
Definition: GrainTracker.h:214
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
unsigned int _feature_count
The number of features seen by this object (same as summing _feature_counts_per_map) ...
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data.
void GrainTracker::remapGrains ( )
protected

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 715 of file GrainTracker.C.

Referenced by finalize().

716 {
717  // Don't remap grains if the current simulation step is before the specified tracking step
718  if (_t_step < _tracking_step)
719  return;
720 
721  _console << "Running remap Grains" << std::endl;
722 
729  std::map<unsigned int, std::size_t> grain_id_to_new_var;
730 
731  // Items are added to this list when split grains are found
732  std::list<std::pair<std::size_t, std::size_t>> split_pairs;
733 
742  if (_is_master)
743  {
744  // Build the map to detect difference in _var_index mappings after the remap operation
745  std::map<unsigned int, std::size_t> grain_id_to_existing_var_index;
746  for (auto & grain : _feature_sets)
747  {
748  // Unmark the grain so it can be used in the remap loop
749  grain._status = Status::CLEAR;
750 
751  grain_id_to_existing_var_index[grain._id] = grain._var_index;
752  }
753 
754  // Make sure that all split pieces of any grain are on the same OP
755  for (auto i = beginIndex(_feature_sets); i < _feature_sets.size(); ++i)
756  {
757  auto & grain1 = _feature_sets[i];
758 
759  for (auto j = beginIndex(_feature_sets); j < _feature_sets.size(); ++j)
760  {
761  auto & grain2 = _feature_sets[j];
762  if (i == j)
763  continue;
764 
765  // The first condition below is there to prevent symmetric checks (duplicate values)
766  if (i < j && grain1._id == grain2._id)
767  {
768  split_pairs.push_front(std::make_pair(i, j));
769  if (grain1._var_index != grain2._var_index)
770  {
771  _console << COLOR_YELLOW << "Split Grain (#" << grain1._id
772  << ") detected on unmatched OPs (" << grain1._var_index << ", "
773  << grain2._var_index << ") attempting to remap to " << grain1._var_index
774  << ".\n"
775  << COLOR_DEFAULT;
776 
781  grain1._var_index = grain2._var_index;
782  grain1._status |= Status::DIRTY;
783  }
784  }
785  }
786  }
787 
791  bool any_grains_remapped = false;
792  bool grains_remapped;
793  do
794  {
795  grains_remapped = false;
796  for (auto & grain1 : _feature_sets)
797  {
798  // We need to remap any grains represented on any variable index above the cuttoff
799  if (grain1._var_index >= _reserve_op_index)
800  {
801  _console << COLOR_YELLOW << "\nGrain #" << grain1._id
802  << " detected on a reserved order parameter #" << grain1._var_index
803  << ", remapping to another variable\n"
804  << COLOR_DEFAULT;
805 
806  for (auto max = decltype(_max_renumbering_recursion)(0);
808  ++max)
809  if (max < _max_renumbering_recursion)
810  {
811  if (attemptGrainRenumber(grain1, 0, max))
812  break;
813  }
814  else if (!attemptGrainRenumber(grain1, 0, max))
815  {
816  _console << std::flush;
817  mooseError(COLOR_RED,
818  "Unable to find any suitable order parameters for remapping."
819  " Perhaps you need more op variables?\n\n",
820  COLOR_DEFAULT);
821  }
822 
823  grains_remapped = true;
824  }
825 
826  for (auto & grain2 : _feature_sets)
827  {
828  // Don't compare a grain with itself and don't try to remap inactive grains
829  if (&grain1 == &grain2)
830  continue;
831 
832  if (grain1._var_index == grain2._var_index && // grains represented by same variable?
833  grain1._id != grain2._id && // are they part of different grains?
834  grain1.boundingBoxesIntersect(grain2) && // do bboxes intersect (coarse level)?
835  grain1.halosIntersect(grain2)) // do they actually overlap (fine level)?
836  {
837  _console << COLOR_YELLOW << "\nGrain #" << grain1._id << " intersects Grain #"
838  << grain2._id << " (variable index: " << grain1._var_index << ")\n"
839  << COLOR_DEFAULT;
840 
841  for (auto max = decltype(_max_renumbering_recursion)(0);
843  ++max)
844  if (max < _max_renumbering_recursion)
845  {
846  if (attemptGrainRenumber(grain1, 0, max))
847  break;
848  }
849  else if (!attemptGrainRenumber(grain1, 0, max) &&
850  !attemptGrainRenumber(grain2, 0, max))
851  {
852  _console << std::flush;
853  mooseError(COLOR_RED,
854  "Unable to find any suitable order parameters for remapping."
855  " Perhaps you need more op variables?\n\n",
856  COLOR_DEFAULT);
857  }
858 
859  grains_remapped = true;
860  }
861  }
862  }
863  any_grains_remapped |= grains_remapped;
864  } while (grains_remapped);
865 
866  // Verify that split grains are still intact
867  for (auto & split_pair : split_pairs)
868  if (_feature_sets[split_pair.first]._var_index != _feature_sets[split_pair.first]._var_index)
869  mooseError("Split grain remapped - This case is currently not handled");
870 
876  for (auto & grain : _feature_sets)
877  {
878  mooseAssert(grain_id_to_existing_var_index.find(grain._id) !=
879  grain_id_to_existing_var_index.end(),
880  "Missing unique ID");
881 
882  auto old_var_index = grain_id_to_existing_var_index[grain._id];
883 
884  if (old_var_index != grain._var_index)
885  {
886  mooseAssert(static_cast<bool>(grain._status & Status::DIRTY), "grain status is incorrect");
887 
888  grain_id_to_new_var.emplace_hint(
889  grain_id_to_new_var.end(),
890  std::pair<unsigned int, std::size_t>(grain._id, grain._var_index));
891 
900  grain._var_index = old_var_index;
901  // Clear the DIRTY status as well for consistency
902  grain._status &= ~Status::DIRTY;
903  }
904  }
905 
906  if (!grain_id_to_new_var.empty())
907  {
908  _console << "\nFinal remapping tally:\n";
909  for (const auto & remap_pair : grain_id_to_new_var)
910  _console << "Grain #" << remap_pair.first << " var_index "
911  << grain_id_to_existing_var_index[remap_pair.first] << " -> " << remap_pair.second
912  << '\n';
913  _console << "Communicating swaps with remaining processors..." << std::endl;
914  }
915  } // root processor
916 
917  // Communicate the std::map to all ranks
918  _communicator.broadcast(grain_id_to_new_var);
919 
920  // Perform swaps if any occurred
921  if (!grain_id_to_new_var.empty())
922  {
923  // Cache for holding values during swaps
924  std::vector<std::map<Node *, CacheValues>> cache(_n_vars);
925 
926  // Perform the actual swaps on all processors
927  for (auto & grain : _feature_sets)
928  {
929  // See if this grain was remapped
930  auto new_var_it = grain_id_to_new_var.find(grain._id);
931  if (new_var_it != grain_id_to_new_var.end())
932  swapSolutionValues(grain, new_var_it->second, cache, RemapCacheMode::FILL);
933  }
934 
935  for (auto & grain : _feature_sets)
936  {
937  // See if this grain was remapped
938  auto new_var_it = grain_id_to_new_var.find(grain._id);
939  if (new_var_it != grain_id_to_new_var.end())
940  swapSolutionValues(grain, new_var_it->second, cache, RemapCacheMode::USE);
941  }
942 
943  _nl.solution().close();
944  _nl.solutionOld().close();
945  _nl.solutionOlder().close();
946 
947  _fe_problem.getNonlinearSystemBase().system().update();
948 
949  _console << "Swaps complete" << std::endl;
950  }
951 }
const std::size_t _n_vars
static const unsigned int _max_renumbering_recursion
Depth of renumbering recursion (a depth of zero means no recursion)
Definition: GrainTracker.h:183
Status
This enumeration is used to indicate status of the grains in the _unique_grains data structure...
NonlinearSystemBase & _nl
A reference to the nonlinear system (used for retrieving solution vectors)
Definition: GrainTracker.h:199
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
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...
bool attemptGrainRenumber(FeatureData &grain, unsigned int depth, unsigned int max_depth)
This is the recursive part of the remapping algorithm.
const int _tracking_step
The timestep to begin tracking grains.
Definition: GrainTracker.h:177
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:190
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 502 of file FeatureFloodCount.C.

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

503 {
504  // local to global map (one per processor)
505  std::vector<int> counts;
506  std::vector<std::size_t> local_to_global_all;
507  if (_is_master)
508  buildLocalToGlobalIndices(local_to_global_all, counts);
509 
510  // Scatter local_to_global indices to all processors and store in class member variable
511  _communicator.scatter(local_to_global_all, counts, _local_to_global_feature_map);
512 
513  std::size_t largest_global_index = std::numeric_limits<std::size_t>::lowest();
514  if (!_is_master)
515  {
517 
524  for (auto & list_ref : _partial_feature_sets)
525  {
526  for (auto & feature : list_ref)
527  {
528  mooseAssert(feature._orig_ids.size() == 1, "feature._orig_ids length doesn't make sense");
529 
530  auto global_index = FeatureFloodCount::invalid_size_t;
531  auto local_index = feature._orig_ids.begin()->second;
532 
533  if (local_index < _local_to_global_feature_map.size())
534  global_index = _local_to_global_feature_map[local_index];
535 
536  if (global_index != FeatureFloodCount::invalid_size_t)
537  {
538  if (global_index > largest_global_index)
539  largest_global_index = global_index;
540 
541  // Set the correct global index
542  feature._id = global_index;
543 
551  feature._status &= ~Status::INACTIVE;
552 
553  // Move the feature into the correct place
554  _feature_sets[local_index] = std::move(feature);
555  }
556  }
557  }
558  }
559  else
560  {
561  for (auto global_index : local_to_global_all)
562  if (global_index != FeatureFloodCount::invalid_size_t && global_index > largest_global_index)
563  largest_global_index = global_index;
564  }
565 
566  buildFeatureIdToLocalIndices(largest_global_index);
567 }
static const std::size_t invalid_size_t
Status
This enumeration is used to indicate status of the grains in the _unique_grains data structure...
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
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 ...
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data.
void buildFeatureIdToLocalIndices(unsigned int max_id)
This method builds a lookup map for retrieving the right local feature (by index) given a global inde...
std::vector< std::size_t > _local_to_global_feature_map
The vector recording the local to global feature indices.
void FeatureFloodCount::serialize ( std::string &  serialized_buffer)
protectedinherited

These routines packs/unpack the _feature_map data into a structure suitable for parallel communication operations.

See the comments in these routines for the exact data structure layout.

Call the MOOSE serialization routines to serialize this processor's data. Note: The _partial_feature_sets data structure will be empty for all other processors

Definition at line 778 of file FeatureFloodCount.C.

Referenced by FeatureFloodCount::communicateAndMerge(), and FeatureFloodCount::getFeatures().

779 {
780  // stream for serializing the _partial_feature_sets data structure to a byte stream
781  std::ostringstream oss;
782 
787  dataStore(oss, _partial_feature_sets, this);
788 
789  // Populate the passed in string pointer with the string stream's buffer contents
790  serialized_buffer.assign(oss.str());
791 }
void dataStore(std::ostream &stream, FeatureFloodCount::FeatureData &feature, void *context)
std::vector< std::list< FeatureData > > _partial_feature_sets
The data structure used to hold partial and communicated feature data.
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 482 of file FeatureFloodCount.h.

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

486  {
487  while (first1 != last1 && first2 != last2)
488  {
489  if (*first1 == *first2)
490  return true;
491 
492  if (*first1 < *first2)
493  ++first1;
494  else if (*first1 > *first2)
495  ++first2;
496  }
497  return false;
498  }
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 361 of file FeatureFloodCount.C.

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

362 {
363  mooseAssert(_is_master, "sortAndLabel can only be called on the master");
364 
370  std::sort(_feature_sets.begin(), _feature_sets.end());
371 
372 #ifndef NDEBUG
373 
378  unsigned int feature_offset = 0;
379  for (auto map_num = beginIndex(_feature_counts_per_map); map_num < _maps_size; ++map_num)
380  {
381  // Skip empty map checks
382  if (_feature_counts_per_map[map_num] == 0)
383  continue;
384 
385  // Check the begin and end of the current range
386  auto range_front = feature_offset;
387  auto range_back = feature_offset + _feature_counts_per_map[map_num] - 1;
388 
389  mooseAssert(range_front <= range_back && range_back < _feature_count,
390  "Indexing error in feature sets");
391 
392  if (!_single_map_mode && (_feature_sets[range_front]._var_index != map_num ||
393  _feature_sets[range_back]._var_index != map_num))
394  mooseError("Error in _feature_sets sorting, map index: ", map_num);
395 
396  feature_offset += _feature_counts_per_map[map_num];
397  }
398 #endif
399 
400  // Label the features with an ID based on the sorting (processor number independent value)
401  for (auto i = beginIndex(_feature_sets); i < _feature_sets.size(); ++i)
402  if (_feature_sets[i]._id == invalid_id)
403  _feature_sets[i]._id = i;
404 }
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
const std::size_t _maps_size
Convenience variable holding the size of all the datastructures size by the number of maps...
static const unsigned int invalid_id
const bool _single_map_mode
This variable is used to indicate whether or not multiple maps are used during flooding.
unsigned int _feature_count
The number of features seen by this object (same as summing _feature_counts_per_map) ...
std::vector< unsigned int > _feature_counts_per_map
The number of features seen by this object per map.
void GrainTracker::swapSolutionValues ( FeatureData &  grain,
std::size_t  new_var_index,
std::vector< std::map< Node *, CacheValues >> &  cache,
RemapCacheMode  cache_mode 
)
protected

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 1182 of file GrainTracker.C.

Referenced by remapGrains().

1186 {
1187  MeshBase & mesh = _mesh.getMesh();
1188 
1189  // Remap the grain
1190  std::set<Node *> updated_nodes_tmp; // Used only in the elemental case
1191  for (auto entity : grain._local_ids)
1192  {
1193  if (_is_elemental)
1194  {
1195  Elem * elem = mesh.query_elem(entity);
1196  if (!elem)
1197  continue;
1198 
1199  for (unsigned int i = 0; i < elem->n_nodes(); ++i)
1200  {
1201  Node * curr_node = elem->get_node(i);
1202  if (updated_nodes_tmp.find(curr_node) == updated_nodes_tmp.end())
1203  {
1204  // cache this node so we don't attempt to remap it again within this loop
1205  updated_nodes_tmp.insert(curr_node);
1206  swapSolutionValuesHelper(curr_node, grain._var_index, new_var_index, cache, cache_mode);
1207  }
1208  }
1209  }
1210  else
1212  mesh.query_node_ptr(entity), grain._var_index, new_var_index, cache, cache_mode);
1213  }
1214 
1215  // Update the variable index in the unique grain datastructure after swaps are complete
1216  if (cache_mode == RemapCacheMode::USE || cache_mode == RemapCacheMode::BYPASS)
1217  grain._var_index = new_var_index;
1218 }
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.
bool _is_elemental
Determines if the flood counter is elements or not (nodes)
MooseMesh & _mesh
A reference to the mesh.
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 
)
protected

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 1221 of file GrainTracker.C.

Referenced by swapSolutionValues().

1226 {
1227  if (curr_node && curr_node->processor_id() == processor_id())
1228  {
1229  // Reinit the node so we can get and set values of the solution here
1230  _subproblem.reinitNode(curr_node, 0);
1231 
1232  // Local variables to hold values being transferred
1233  Real current, old = 0, older = 0;
1234  // Retrieve the value either from the old variable or cache
1235  if (cache_mode == RemapCacheMode::FILL || cache_mode == RemapCacheMode::BYPASS)
1236  {
1237  current = _vars[curr_var_index]->nodalSln()[0];
1238  if (_is_transient)
1239  {
1240  old = _vars[curr_var_index]->nodalSlnOld()[0];
1241  older = _vars[curr_var_index]->nodalSlnOlder()[0];
1242  }
1243  }
1244  else // USE
1245  {
1246  const auto cache_it = cache[curr_var_index].find(curr_node);
1247  mooseAssert(cache_it != cache[curr_var_index].end(), "Error in cache");
1248  current = cache_it->second.current;
1249  old = cache_it->second.old;
1250  older = cache_it->second.older;
1251  }
1252 
1253  // Cache the value or use it!
1254  if (cache_mode == RemapCacheMode::FILL)
1255  {
1256  cache[curr_var_index][curr_node].current = current;
1257  cache[curr_var_index][curr_node].old = old;
1258  cache[curr_var_index][curr_node].older = older;
1259  }
1260  else // USE or BYPASS
1261  {
1262  const auto & dof_index = _vars[new_var_index]->nodalDofIndex();
1263 
1264  // Transfer this solution from the old to the current
1265  _nl.solution().set(dof_index, current);
1266  if (_is_transient)
1267  {
1268  _nl.solutionOld().set(dof_index, old);
1269  _nl.solutionOlder().set(dof_index, older);
1270  }
1271  }
1272 
1285  if (cache_mode == RemapCacheMode::FILL || cache_mode == RemapCacheMode::BYPASS)
1286  {
1287  const auto & dof_index = _vars[curr_var_index]->nodalDofIndex();
1288 
1289  // Set the DOF for the current variable to zero
1290  _nl.solution().set(dof_index, 0.0);
1291  if (_is_transient)
1292  {
1293  _nl.solutionOld().set(dof_index, 0.0);
1294  _nl.solutionOlder().set(dof_index, 0.0);
1295  }
1296  }
1297  }
1298 }
NonlinearSystemBase & _nl
A reference to the nonlinear system (used for retrieving solution vectors)
Definition: GrainTracker.h:199
std::vector< MooseVariable * > _vars
The vector of coupled in variables.
const bool _is_transient
Boolean to indicate whether this is a Steady or Transient solve.
Definition: GrainTracker.h:234
void GrainTracker::trackGrains ( )
protected

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.

Trigger callback for new grains

Definition at line 398 of file GrainTracker.C.

Referenced by finalize().

399 {
400  mooseAssert(!_first_time, "Track grains may only be called when _tracking_step > _t_step");
401 
402  // Used to track indices for which to trigger the new grain callback on (used on all ranks)
404 
409  if (_is_master)
410  {
411  // Reset Status on active unique grains
412  std::vector<unsigned int> map_sizes(_maps_size);
413  for (auto & grain : _feature_sets_old)
414  {
415  if (grain._status != Status::INACTIVE)
416  {
417  grain._status = Status::CLEAR;
418  map_sizes[grain._var_index]++;
419  }
420  }
421 
422  // Print out stats on overall tracking changes per var_index
423  for (auto map_num = decltype(_maps_size)(0); map_num < _maps_size; ++map_num)
424  {
425  _console << "\nGrains active index " << map_num << ": " << map_sizes[map_num] << " -> "
426  << _feature_counts_per_map[map_num];
427  if (map_sizes[map_num] > _feature_counts_per_map[map_num])
428  _console << "--";
429  else if (map_sizes[map_num] < _feature_counts_per_map[map_num])
430  _console << "++";
431  }
432  _console << '\n' << std::endl;
433 
440  std::vector<std::size_t> new_grain_index_to_existing_grain_index(_feature_sets.size(),
442 
443  for (auto old_grain_index = beginIndex(_feature_sets_old);
444  old_grain_index < _feature_sets_old.size();
445  ++old_grain_index)
446  {
447  auto & old_grain = _feature_sets_old[old_grain_index];
448 
449  if (old_grain._status == Status::INACTIVE) // Don't try to find matches for inactive grains
450  continue;
451 
452  std::size_t closest_match_index = invalid_size_t;
453  Real min_centroid_diff = std::numeric_limits<Real>::max();
454 
460  // clang-format off
461  auto start_it =
462  std::lower_bound(_feature_sets.begin(), _feature_sets.end(), old_grain._var_index,
463  [](const FeatureData & item, std::size_t var_index)
464  {
465  return item._var_index < var_index;
466  });
467  // clang-format on
468 
469  // We only need to examine grains that have matching variable indices
470  for (decltype(_feature_sets.size()) new_grain_index =
471  std::distance(_feature_sets.begin(), start_it);
472  new_grain_index < _feature_sets.size() &&
473  _feature_sets[new_grain_index]._var_index == old_grain._var_index;
474  ++new_grain_index)
475  {
476  auto & new_grain = _feature_sets[new_grain_index];
477 
482  if (new_grain.boundingBoxesIntersect(old_grain))
483  {
484  Real curr_centroid_diff = centroidRegionDistance(old_grain._bboxes, new_grain._bboxes);
485  if (curr_centroid_diff <= min_centroid_diff)
486  {
487  closest_match_index = new_grain_index;
488  min_centroid_diff = curr_centroid_diff;
489  }
490  }
491  }
492 
493  // found a match
494  if (closest_match_index != invalid_size_t)
495  {
502  auto curr_index = new_grain_index_to_existing_grain_index[closest_match_index];
503  if (curr_index != invalid_size_t)
504  {
505  // The new feature being competed for
506  auto & new_grain = _feature_sets[closest_match_index];
507 
508  // The other old grain competing to match up to the same new grain
509  auto & other_old_grain = _feature_sets_old[curr_index];
510 
511  auto centroid_diff1 = centroidRegionDistance(new_grain._bboxes, old_grain._bboxes);
512  auto centroid_diff2 = centroidRegionDistance(new_grain._bboxes, other_old_grain._bboxes);
513 
514  auto & inactive_grain = (centroid_diff1 < centroid_diff2) ? other_old_grain : old_grain;
515 
516  inactive_grain._status = Status::INACTIVE;
517  _console << COLOR_GREEN << "Marking Grain " << inactive_grain._id
518  << " as INACTIVE (variable index: " << inactive_grain._var_index << ")\n"
519  << COLOR_DEFAULT << inactive_grain;
520 
526  if (&inactive_grain == &other_old_grain)
527  new_grain_index_to_existing_grain_index[closest_match_index] = old_grain_index;
528  }
529  else
530  new_grain_index_to_existing_grain_index[closest_match_index] = old_grain_index;
531  }
532  }
533 
534  // Mark all resolved grain matches
535  for (auto new_index = beginIndex(new_grain_index_to_existing_grain_index);
536  new_index < new_grain_index_to_existing_grain_index.size();
537  ++new_index)
538  {
539  auto curr_index = new_grain_index_to_existing_grain_index[new_index];
540 
541  // This may be a new grain, we'll handle that case below
542  if (curr_index == invalid_size_t)
543  continue;
544 
545  mooseAssert(_feature_sets_old[curr_index]._id != invalid_id,
546  "Invalid ID in old grain structure");
547 
548  _feature_sets[new_index]._id = _feature_sets_old[curr_index]._id; // Transfer ID
549  _feature_sets[new_index]._status = Status::MARKED; // Mark the status in the new set
550  _feature_sets_old[curr_index]._status = Status::MARKED; // Mark the status in the old set
551  }
552 
567  // Case 1 (new grains in _feature_sets):
568  for (auto grain_num = beginIndex(_feature_sets); grain_num < _feature_sets.size(); ++grain_num)
569  {
570  auto & grain = _feature_sets[grain_num];
571 
572  // New Grain
573  if (grain._status == Status::CLEAR)
574  {
593  // clang-format off
594  auto start_it =
595  std::lower_bound(_feature_sets.begin(), _feature_sets.end(), grain._var_index,
596  [](const FeatureData & item, std::size_t var_index)
597  {
598  return item._var_index < var_index;
599  });
600  // clang-format on
601 
602  // Loop over matching variable indices
603  for (decltype(_feature_sets.size()) new_grain_index =
604  std::distance(_feature_sets.begin(), start_it);
605  new_grain_index < _feature_sets.size() &&
606  _feature_sets[new_grain_index]._var_index == grain._var_index;
607  ++new_grain_index)
608  {
609  auto & other_grain = _feature_sets[new_grain_index];
610 
611  // Splitting grain?
612  if (grain_num != new_grain_index && // Make sure indices aren't pointing at the same grain
613  other_grain._status == Status::MARKED && // and that the other grain is indeed marked
614  other_grain.boundingBoxesIntersect(grain) && // and the bboxes intersect
615  other_grain.halosIntersect(grain)) // and the halos also intersect
616  // TODO: Inspect combined volume and see if it's "close" to the expected value
617  {
618  grain._id = other_grain._id; // Set the duplicate ID
619  grain._status = Status::MARKED; // Mark it
620  _console << COLOR_YELLOW << "Split Grain Detected "
621  << " (variable index: " << grain._var_index << ")\n"
622  << COLOR_DEFAULT << grain << other_grain;
623  }
624  }
625 
626  // Must be a nucleating grain (status is still not set)
627  if (grain._status == Status::CLEAR)
628  {
629  auto new_index = getNextUniqueID();
630  grain._id = new_index; // Set the ID
631  grain._status = Status::MARKED; // Mark it
632  }
633  }
634  }
635 
636  // Case 2 (inactive grains in _feature_sets_old)
637  for (auto & grain : _feature_sets_old)
638  {
639  if (grain._status == Status::CLEAR)
640  {
641  grain._status = Status::INACTIVE;
642  _console << COLOR_GREEN << "Marking Grain " << grain._id
643  << " as INACTIVE (variable index: " << grain._var_index << ")\n"
644  << COLOR_DEFAULT << grain;
645  }
646  }
647  } // is_master
648 
649  /*************************************************************
650  ****************** COLLECTIVE WORK SECTION ******************
651  *************************************************************/
652 
653  // Make IDs on all non-master ranks consistent
655 
656  // Build up an id to index map
657  _communicator.broadcast(_max_curr_grain_id);
659 
664  {
665  for (auto new_id = _old_max_grain_id + 1; new_id <= _max_curr_grain_id; ++new_id)
666  {
667  // Don't trigger the callback on the reserve IDs
669  {
670  // See if we've been instructed to terminate with an error
672  mooseError(
673  "Error: New grain detected and \"error_on_new_grain_creation\" is set to true");
674  else
675  newGrainCreated(new_id);
676  }
677  }
678  }
679 }
static const std::size_t invalid_size_t
Real centroidRegionDistance(std::vector< MeshTools::BoundingBox > &bboxes1, std::vector< MeshTools::BoundingBox > &bboxes2) const
This method returns the minimum periodic distance between the centroids of two vectors of bounding bo...
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:228
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:231
bool _first_time
Boolean to indicate the first time this object executes.
Definition: GrainTracker.h:214
bool _is_master
Convenience variable for testing master rank.
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
const std::size_t _maps_size
Convenience variable holding the size of all the datastructures size by the number of maps...
static const unsigned int invalid_id
bool _error_on_grain_creation
Boolean to terminate with an error if a new grain is created during the simulation.
Definition: GrainTracker.h:221
std::vector< unsigned int > _feature_counts_per_map
The number of features seen by this object per map.
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:225
void buildFeatureIdToLocalIndices(unsigned int max_id)
This method builds a lookup map for retrieving the right local feature (by index) given a global inde...
void scatterAndUpdateRanks()
Calls buildLocalToGlobalIndices to build the individual local to global indicies for each rank and sc...
std::vector< FeatureData > & _feature_sets_old
This data structure holds the map of unique grains from the previous time step.
Definition: GrainTracker.h:205
virtual void newGrainCreated(unsigned int new_grain_id)
This method is called when a new grain is detected.
Definition: GrainTracker.C:682
unsigned int getNextUniqueID()
Retrieve the next unique grain number if a new grain is detected during trackGrains.
const unsigned short _n_reserve_ops
The number of reserved order parameters.
Definition: GrainTracker.h:186
void GrainTracker::updateFieldInfo ( )
overrideprotectedvirtual

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 1301 of file GrainTracker.C.

Referenced by finalize().

1302 {
1303  for (auto map_num = decltype(_maps_size)(0); map_num < _maps_size; ++map_num)
1304  _feature_maps[map_num].clear();
1305 
1306  std::map<dof_id_type, Real> tmp_map;
1307  MeshBase & mesh = _mesh.getMesh();
1308 
1309  for (const auto & grain : _feature_sets)
1310  {
1311  std::size_t curr_var = grain._var_index;
1312  std::size_t map_index = (_single_map_mode || _condense_map_info) ? 0 : curr_var;
1313 
1314  for (auto entity : grain._local_ids)
1315  {
1316  // Highest variable value at this entity wins
1317  Real entity_value = std::numeric_limits<Real>::lowest();
1318  if (_is_elemental)
1319  {
1320  const Elem * elem = mesh.elem(entity);
1321  std::vector<Point> centroid(1, elem->centroid());
1322  if (_poly_ic_uo && _first_time)
1323  {
1324  entity_value = _poly_ic_uo->getVariableValue(grain._var_index, centroid[0]);
1325  }
1326  else
1327  {
1328  _fe_problem.reinitElemPhys(elem, centroid, 0);
1329  entity_value = _vars[curr_var]->sln()[0];
1330  }
1331  }
1332  else
1333  {
1334  Node & node = mesh.node(entity);
1335  entity_value = _vars[curr_var]->getNodalValue(node);
1336  }
1337 
1338  if (entity_value != std::numeric_limits<Real>::lowest() &&
1339  (tmp_map.find(entity) == tmp_map.end() || entity_value > tmp_map[entity]))
1340  {
1341  mooseAssert(grain._id != invalid_id, "Missing Grain ID");
1342  _feature_maps[map_index][entity] = grain._id;
1343 
1344  if (_var_index_mode)
1345  _var_index_maps[map_index][entity] = grain._var_index;
1346 
1347  tmp_map[entity] = entity_value;
1348  }
1349 
1351  {
1352  auto insert_pair = moose_try_emplace(
1353  _entity_var_to_features, entity, std::vector<unsigned int>(_n_vars, invalid_id));
1354  auto & vec_ref = insert_pair.first->second;
1355 
1356  if (insert_pair.second)
1357  {
1358  // insert the reserve op numbers (if appropriate)
1359  for (auto reserve_index = decltype(_n_reserve_ops)(0); reserve_index < _n_reserve_ops;
1360  ++reserve_index)
1361  vec_ref[reserve_index] = _reserve_grain_first_index + reserve_index;
1362  }
1363  vec_ref[grain._var_index] = grain._id;
1364  }
1365  }
1366 
1367  if (_compute_halo_maps)
1368  for (auto entity : grain._halo_ids)
1369  _halo_ids[grain._var_index][entity] = grain._var_index;
1370 
1371  for (auto entity : grain._ghosted_ids)
1372  _ghosted_entity_ids[entity] = 1;
1373  }
1374 
1376 }
const std::size_t _n_vars
const bool _condense_map_info
std::map< dof_id_type, std::vector< unsigned int > > _entity_var_to_features
std::map< dof_id_type, int > _ghosted_entity_ids
The map for holding reconstructed ghosted element information.
void communicateHaloMap()
std::vector< std::map< dof_id_type, int > > _halo_ids
The data structure for looking up halos around features.
std::vector< MooseVariable * > _vars
The vector of coupled in variables.
bool _first_time
Boolean to indicate the first time this object executes.
Definition: GrainTracker.h:214
bool _is_elemental
Determines if the flood counter is elements or not (nodes)
const PolycrystalUserObjectBase * _poly_ic_uo
An optional IC UserObject which can provide initial data structures to this object.
Definition: GrainTracker.h:208
std::vector< FeatureData > _feature_sets
The data structure used to hold the globally unique features.
const std::size_t _maps_size
Convenience variable holding the size of all the datastructures size by the number of maps...
static const unsigned int invalid_id
std::vector< std::map< dof_id_type, int > > _feature_maps
The feature maps contain the raw flooded node information and eventually the unique grain numbers...
const bool _single_map_mode
This variable is used to indicate whether or not multiple maps are used during flooding.
const bool _compute_halo_maps
Indicates whether or not to communicate halo map information with all ranks.
virtual Real getVariableValue(unsigned int op_index, const Point &p) const =0
Returns the variable value for a given op_index and mesh point.
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:225
MooseMesh & _mesh
A reference to the mesh.
const bool _compute_var_to_feature_map
Indicates whether or not the var to feature map is populated.
const bool _var_index_mode
This variable is used to indicate whether the maps will contain unique region information or just the...
std::vector< std::map< dof_id_type, int > > _var_index_maps
This map keeps track of which variables own which nodes.
const unsigned short _n_reserve_ops
The number of reserved order parameters.
Definition: GrainTracker.h:186
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.

Referenced by FeatureFloodCount::getFeatures().

void FeatureFloodCount::visitElementalNeighbors ( const Elem *  elem,
std::size_t  current_index,
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.

Definition at line 1246 of file FeatureFloodCount.C.

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

1251 {
1252  mooseAssert(elem, "Elem is NULL");
1253 
1254  std::vector<const Elem *> all_active_neighbors;
1255  MeshBase & mesh = _mesh.getMesh();
1256 
1257  // Loop over all neighbors (at the the same level as the current element)
1258  // Loop over all neighbors (at the the same level as the current element)
1259  for (auto i = decltype(elem->n_neighbors())(0); i < elem->n_neighbors(); ++i)
1260  {
1261  const Elem * neighbor_ancestor = nullptr;
1262  bool topological_neighbor = false;
1263 
1268  neighbor_ancestor = elem->neighbor(i);
1269  if (neighbor_ancestor)
1270  neighbor_ancestor->active_family_tree_by_neighbor(all_active_neighbors, elem, false);
1271  else // if (expand_halos_only /*&& feature->_periodic_nodes.empty()*/)
1272  {
1273  neighbor_ancestor = elem->topological_neighbor(i, mesh, *_point_locator, _pbs);
1274 
1282  if (neighbor_ancestor)
1283  {
1284  neighbor_ancestor->active_family_tree_by_topological_neighbor(
1285  all_active_neighbors, elem, mesh, *_point_locator, _pbs, false);
1286 
1287  topological_neighbor = true;
1288 
1289  // for (const auto neighbor : all_active_neighbors)
1290  // feature->_disjoint_halo_ids.insert(neighbor->id());
1291  }
1292  }
1293 
1294  visitNeighborsHelper(elem,
1295  all_active_neighbors,
1296  current_index,
1297  feature,
1298  expand_halos_only,
1299  topological_neighbor,
1300  disjoint_only);
1301 
1302  all_active_neighbors.clear();
1303  }
1304 }
void visitNeighborsHelper(const T *curr_entity, std::vector< const T * > neighbor_entities, std::size_t current_index, FeatureData *feature, bool expand_halos_only, bool topological_neighbor, bool disjoint_only)
The actual logic for visiting neighbors is abstracted out here.
std::unique_ptr< PointLocatorBase > _point_locator
PeriodicBoundaries * _pbs
A pointer to the periodic boundary constraints object.
MooseMesh & _mesh
A reference to the mesh.
template<typename T >
void FeatureFloodCount::visitNeighborsHelper ( const T *  curr_entity,
std::vector< const T * >  neighbor_entities,
std::size_t  current_index,
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 1323 of file FeatureFloodCount.C.

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

1330 {
1331  // Loop over all active element neighbors
1332  for (const auto neighbor : neighbor_entities)
1333  {
1334  if (neighbor)
1335  {
1336  if (expand_halos_only)
1337  {
1338  if (topological_neighbor || disjoint_only)
1339  feature->_disjoint_halo_ids.insert(neighbor->id());
1340  else
1341  feature->_halo_ids.insert(neighbor->id());
1342  }
1343  else
1344  {
1345  auto my_processor_id = processor_id();
1346 
1347  if (!topological_neighbor && neighbor->processor_id() != my_processor_id)
1348  feature->_ghosted_ids.insert(curr_entity->id());
1349 
1359  if (curr_entity->processor_id() == my_processor_id)
1360  {
1367  if (topological_neighbor || disjoint_only)
1368  feature->_disjoint_halo_ids.insert(neighbor->id());
1369  else
1370  {
1371  feature->_halo_ids.insert(neighbor->id());
1372 
1373  flood(neighbor, current_index, feature);
1374  }
1375  }
1376  }
1377  }
1378  }
1379 }
bool flood(const DofObject *dof_object, std::size_t current_index, FeatureData *feature)
This method will "mark" all entities on neighboring elements that are above the supplied threshold...
void FeatureFloodCount::visitNodalNeighbors ( const Node *  node,
std::size_t  current_index,
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 1307 of file FeatureFloodCount.C.

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

1311 {
1312  mooseAssert(node, "Node is NULL");
1313 
1314  std::vector<const Node *> all_active_neighbors;
1315  MeshTools::find_nodal_neighbors(_mesh.getMesh(), *node, _nodes_to_elem_map, all_active_neighbors);
1316 
1318  node, all_active_neighbors, current_index, feature, expand_halos_only, false, false);
1319 }
void visitNeighborsHelper(const T *curr_entity, std::vector< const T * > neighbor_entities, std::size_t current_index, FeatureData *feature, bool expand_halos_only, bool topological_neighbor, bool disjoint_only)
The actual logic for visiting neighbors is abstracted out here.
std::vector< std::vector< const Elem * > > _nodes_to_elem_map
The data structure used to find neighboring elements give a node ID.
MooseMesh & _mesh
A reference to the mesh.

Member Data Documentation

std::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 637 of file FeatureFloodCount.h.

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

const bool FeatureFloodCount::_compute_halo_maps
protectedinherited

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

Definition at line 540 of file FeatureFloodCount.h.

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

const bool FeatureFloodCount::_compute_var_to_feature_map
protectedinherited

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

Definition at line 543 of file FeatureFloodCount.h.

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

const bool FeatureFloodCount::_condense_map_info
protectedinherited

Definition at line 529 of file FeatureFloodCount.h.

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

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 513 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::initialize().

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 618 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::initialize().

std::vector<unsigned int> FeatureFloodCount::_empty_var_to_features
protectedinherited
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 567 of file FeatureFloodCount.h.

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

std::map<dof_id_type, std::vector<unsigned int> > FeatureFloodCount::_entity_var_to_features
protectedinherited
bool GrainTracker::_error_on_grain_creation
protected

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 221 of file GrainTracker.h.

Referenced by trackGrains().

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

The number of features seen by this object per map.

Definition at line 581 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::mergeSets(), FeatureFloodCount::sortAndLabel(), and trackGrains().

std::vector<std::size_t> FeatureFloodCount::_feature_id_to_local_index
protectedinherited
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 604 of file FeatureFloodCount.h.

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

std::vector<FeatureData> FeatureFloodCount::_feature_sets
protectedinherited
std::vector<FeatureData>& GrainTracker::_feature_sets_old
protected

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 205 of file GrainTracker.h.

Referenced by initialize(), and trackGrains().

bool GrainTracker::_first_time
protected

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 214 of file GrainTracker.h.

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

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

The map for holding reconstructed ghosted element information.

Definition at line 621 of file FeatureFloodCount.h.

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

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 533 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::updateFieldInfo().

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 627 of file FeatureFloodCount.h.

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

const unsigned int GrainTracker::_halo_level
protected

The thickness of the halo surrounding each grain.

Definition at line 180 of file GrainTracker.h.

Referenced by finalize().

bool FeatureFloodCount::_is_elemental
protectedinherited
bool FeatureFloodCount::_is_master
protectedinherited
const bool GrainTracker::_is_transient
private

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

Definition at line 234 of file GrainTracker.h.

Referenced by swapSolutionValuesHelper().

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

The vector recording the local to global feature indices.

Definition at line 607 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::scatterAndUpdateRanks().

const std::size_t FeatureFloodCount::_maps_size
protectedinherited

Convenience variable holding the size of all the datastructures size by the number of maps.

Definition at line 556 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::FeatureFloodCount(), FeatureFloodCount::getEntityValue(), FeatureFloodCount::initialize(), FeatureFloodCount::mergeSets(), FeatureFloodCount::sortAndLabel(), trackGrains(), and updateFieldInfo().

unsigned int GrainTracker::_max_curr_grain_id
private

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

Definition at line 231 of file GrainTracker.h.

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

const unsigned int GrainTracker::_max_renumbering_recursion = 4
staticprotected

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

Definition at line 183 of file GrainTracker.h.

Referenced by remapGrains().

MooseMesh& FeatureFloodCount::_mesh
protectedinherited
const processor_id_type FeatureFloodCount::_n_procs
protectedinherited

Convenience variable holding the number of processors in this simulation.

Definition at line 559 of file FeatureFloodCount.h.

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

const unsigned short GrainTracker::_n_reserve_ops
protected

The number of reserved order parameters.

Definition at line 186 of file GrainTracker.h.

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

const std::size_t FeatureFloodCount::_n_vars
protectedinherited
NonlinearSystemBase& GrainTracker::_nl
protected

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

Definition at line 199 of file GrainTracker.h.

Referenced by remapGrains(), and swapSolutionValuesHelper().

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 578 of file FeatureFloodCount.h.

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

unsigned int GrainTracker::_old_max_grain_id
private

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

Definition at line 228 of file GrainTracker.h.

Referenced by getNewGrainIDs(), and trackGrains().

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

The data structure used to hold partial and communicated feature data.

The data structure mirrors that found in _feature_sets, but contains one additional vector indexed by processor id

Definition at line 591 of file FeatureFloodCount.h.

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

PeriodicBoundaries* FeatureFloodCount::_pbs
protectedinherited

A pointer to the periodic boundary constraints object.

Definition at line 613 of file FeatureFloodCount.h.

Referenced by FeatureFloodCount::initialSetup(), FeatureFloodCount::meshChanged(), and FeatureFloodCount::visitElementalNeighbors().

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 633 of file FeatureFloodCount.h.

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

std::unique_ptr<PointLocatorBase> FeatureFloodCount::_point_locator
protectedinherited
const PolycrystalUserObjectBase* GrainTracker::_poly_ic_uo
protected

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

Definition at line 208 of file GrainTracker.h.

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

const bool GrainTracker::_remap
protected

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

Definition at line 196 of file GrainTracker.h.

Referenced by finalize().

unsigned int GrainTracker::_reserve_grain_first_index
private

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

Definition at line 225 of file GrainTracker.h.

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

const std::size_t GrainTracker::_reserve_op_index
protected

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

Definition at line 190 of file GrainTracker.h.

Referenced by computeMinDistancesFromGrain(), getThreshold(), and remapGrains().

const Real GrainTracker::_reserve_op_threshold
protected

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

Definition at line 193 of file GrainTracker.h.

Referenced by getThreshold().

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 527 of file FeatureFloodCount.h.

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

Real FeatureFloodCount::_step_connecting_threshold
protectedinherited
Real FeatureFloodCount::_step_threshold
protectedinherited
const Real FeatureFloodCount::_threshold
protectedinherited

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

Definition at line 508 of file FeatureFloodCount.h.

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

const int GrainTracker::_tracking_step
protected

The timestep to begin tracking grains.

Definition at line 177 of file GrainTracker.h.

Referenced by execute(), finalize(), getEntityValue(), GrainTracker(), initialize(), and remapGrains().

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 550 of file FeatureFloodCount.h.

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

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 575 of file FeatureFloodCount.h.

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

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 537 of file FeatureFloodCount.h.

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

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 524 of file FeatureFloodCount.h.

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

std::vector<MooseVariable *> FeatureFloodCount::_vars
protectedinherited
const unsigned int FeatureFloodCount::invalid_id = std::numeric_limits<unsigned int>::max()
staticinherited
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: