Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://www.mooseframework.org
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #pragma once
11 :
12 : #include "Coupleable.h"
13 : #include "GeneralPostprocessor.h"
14 : #include "InfixIterator.h"
15 : #include "MooseVariableDependencyInterface.h"
16 : #include "BoundaryRestrictable.h"
17 :
18 : #include <iterator>
19 : #include <list>
20 : #include <set>
21 : #include <vector>
22 :
23 : #include "libmesh/bounding_box.h"
24 : #include "libmesh/periodic_boundaries.h"
25 :
26 : // External includes
27 : #include "boost/bitmask_operators.h"
28 :
29 : // Forward Declarations
30 : class MooseMesh;
31 :
32 : /**
33 : * This object will mark nodes or elements of continuous regions all with a unique number for the
34 : * purpose of counting or "coloring" unique regions in a solution. It is designed to work with
35 : * either a single variable, or multiple variables.
36 : *
37 : * Note: When inspecting multiple variables, those variables must not have regions of interest
38 : * that overlap or they will not be correctly colored.
39 : */
40 : class FeatureFloodCount : public GeneralPostprocessor,
41 : public Coupleable,
42 : public MooseVariableDependencyInterface,
43 : public BoundaryRestrictable
44 : {
45 : public:
46 : static InputParameters validParams();
47 :
48 : FeatureFloodCount(const InputParameters & parameters);
49 :
50 : virtual void initialSetup() override;
51 : virtual void meshChanged() override;
52 : virtual void initialize() override;
53 : virtual void execute() override;
54 : virtual void finalize() override;
55 : virtual Real getValue() const override;
56 :
57 : /// Return the number of active features
58 : std::size_t getNumberActiveFeatures() const;
59 :
60 : /// Returns the total feature count (active and inactive ids, useful for sizing vectors)
61 : virtual std::size_t getTotalFeatureCount() const;
62 :
63 : /// Returns a Boolean indicating whether this feature intersects _any_ boundary
64 : virtual bool doesFeatureIntersectBoundary(unsigned int feature_id) const;
65 :
66 : /// Returns a Boolean indicating whether this feature intersects boundaries in a user-supplied list
67 : virtual bool doesFeatureIntersectSpecifiedBoundary(unsigned int feature_id) const;
68 :
69 : /// Returns a Boolean indicating whether this feature is percolated (e.g. intersects at least two
70 : /// different boundaries from sets supplied by the user)
71 : virtual bool isFeaturePercolated(unsigned int feature_id) const;
72 :
73 : /// Returns the centroid of the designated feature (only supported without periodic boundaries)
74 : virtual Point featureCentroid(unsigned int feature_id) const;
75 :
76 : /**
77 : * Returns a list of active unique feature ids for a particular element. The vector is indexed by
78 : * variable number with each entry containing either an invalid size_t type (no feature active at
79 : * that location) or a feature id if the variable is non-zero at that location.
80 : */
81 : virtual const std::vector<unsigned int> & getVarToFeatureVector(dof_id_type elem_id) const;
82 :
83 : /// Returns the variable representing the passed in feature
84 : virtual unsigned int getFeatureVar(unsigned int feature_id) const;
85 :
86 : /// Returns the number of coupled varaibles
87 : std::size_t numCoupledVars() const { return _n_vars; }
88 :
89 : ///@{
90 : /// Constants used for invalid indices set to the max value of std::size_t type
91 : static const std::size_t invalid_size_t;
92 : static const unsigned int invalid_id;
93 : static const processor_id_type invalid_proc_id;
94 : ///@}
95 :
96 : /// Returns a const vector to the coupled variable pointers
97 : const std::vector<MooseVariable *> & getCoupledVars() const { return _vars; }
98 :
99 : /// Returns a const vector to the coupled MooseVariableFEBase pointers
100 198 : const std::vector<MooseVariableFEBase *> & getFECoupledVars() const { return _fe_vars; }
101 :
102 : enum class FieldType
103 : {
104 : UNIQUE_REGION,
105 : VARIABLE_COLORING,
106 : GHOSTED_ENTITIES,
107 : HALOS,
108 : CENTROID,
109 : ACTIVE_BOUNDS,
110 : INTERSECTS_SPECIFIED_BOUNDARY,
111 : };
112 :
113 : // Retrieve field information
114 : virtual Real
115 : getEntityValue(dof_id_type entity_id, FieldType field_type, std::size_t var_index = 0) const;
116 :
117 2663 : inline bool isElemental() const { return _is_elemental; }
118 :
119 : /// This enumeration is used to indicate status of the grains in the _unique_grains data structure
120 : enum class Status : unsigned char
121 : {
122 : CLEAR = 0x0,
123 : MARKED = 0x1,
124 : DIRTY = 0x2,
125 : INACTIVE = 0x4
126 : };
127 :
128 : /// This enumeration is used to inidacate status of boundary intersections.
129 : enum class BoundaryIntersection : unsigned char
130 : {
131 : NONE = 0x0,
132 : ANY_BOUNDARY = 0x1,
133 : PRIMARY_PERCOLATION_BOUNDARY = 0x2,
134 : SECONDARY_PERCOLATION_BOUNDARY = 0x4,
135 : SPECIFIED_BOUNDARY = 0x8
136 : };
137 :
138 : class FeatureData
139 : {
140 : public:
141 : /**
142 : * The primary underlying container type used to hold the data in each FeatureData.
143 : * Supported types are std::set<dof_id_type> or std::vector<dof_id_type>.
144 : *
145 : * Note: Testing has shown that vector container _may_ be slightly faster, but I
146 : * believe much more data needs to be gathered to be sure. Perhaps more work could be performed
147 : * to keep sorted sets to eliminate any extra work we do by occasionally performing a linear
148 : * find or resorting the vector could help. For now, vector it is.
149 : */
150 : using container_type = std::vector<dof_id_type>;
151 :
152 34162 : FeatureData() : FeatureData(std::numeric_limits<std::size_t>::max(), Status::INACTIVE) {}
153 :
154 14999 : FeatureData(std::size_t var_index,
155 : unsigned int local_index,
156 : processor_id_type rank,
157 : Status status)
158 14999 : : FeatureData(var_index, status)
159 : {
160 14999 : _orig_ids = {std::make_pair(rank, local_index)};
161 14999 : }
162 :
163 32080 : FeatureData(std::size_t var_index,
164 : Status status,
165 : unsigned int id = invalid_id,
166 : std::vector<BoundingBox> bboxes = {BoundingBox()})
167 32080 : : _var_index(var_index),
168 32080 : _id(id),
169 32080 : _bboxes(bboxes), // Assume at least one bounding box
170 32080 : _min_entity_id(DofObject::invalid_id),
171 32080 : _vol_count(0),
172 32080 : _status(status),
173 32080 : _boundary_intersection(BoundaryIntersection::NONE)
174 : {
175 32080 : }
176 :
177 : ///@{
178 : // Default Move constructors
179 40260 : FeatureData(FeatureData && /* f */) = default;
180 18359 : FeatureData & operator=(FeatureData && /* f */) = default;
181 : ///@}
182 :
183 : ///@{
184 : /**
185 : * Update the minimum and maximum coordinates of a bounding box
186 : * given a Point, Elem or BBox parameter.
187 : */
188 : void updateBBoxExtremes(MeshBase & mesh);
189 : void updateBBoxExtremes(BoundingBox & bbox, const BoundingBox & rhs_bbox);
190 : ///@}
191 :
192 : /**
193 : * Determines if any of this FeatureData's bounding boxes overlap with
194 : * the other FeatureData's bounding boxes.
195 : */
196 : bool boundingBoxesIntersect(const FeatureData & rhs) const;
197 :
198 : /**
199 : * The routine called to see if two features are mergeable:
200 : * - Features must be represented by the same variable (_var_index)
201 : * - Features must either intersect on halos or
202 : * - Features must intersect on a periodic BC
203 : *
204 : * Optimization: We may use the bounding boxes as a coarse-level check before checking
205 : * halo intersection.
206 : */
207 : bool mergeable(const FeatureData & rhs) const;
208 :
209 : /**
210 : * This routine indicates whether two features can be consolidated, that is, one feature is
211 : * reasonably expected to be part of another. This is different than mergable in that a portion
212 : * of the feature is expected to be completely identical. This happens in the distributed work
213 : * scenario when a feature that is partially owned by a processor is merged on a different
214 : * processor (where local entities are not sent or available). However, later that feature
215 : * ends back up on the original processor and just needs to be consolidated.
216 : */
217 : bool canConsolidate(const FeatureData & rhs) const;
218 :
219 : ///@{
220 : /**
221 : * Determine if one of this FeaturesData's member sets intersects
222 : * the other FeatureData's corresponding set.
223 : */
224 : bool halosIntersect(const FeatureData & rhs) const;
225 : bool periodicBoundariesIntersect(const FeatureData & rhs) const;
226 : bool ghostedIntersect(const FeatureData & rhs) const;
227 : ///@}
228 :
229 : /**
230 : * Located the overlapping bounding box between this Feature and the
231 : * other Feature and expands that overlapping box accordingly.
232 : */
233 : void mergeBBoxes(std::vector<BoundingBox> & bboxes, bool physical_intersection);
234 :
235 : /**
236 : * Merges another Feature Data into this one. This method leaves rhs
237 : * in an inconsistent state.
238 : */
239 : void merge(FeatureData && rhs);
240 :
241 : /**
242 : * Consolidates features, i.e. merges local entities but leaves everything else untouched.
243 : */
244 : void consolidate(FeatureData && rhs);
245 :
246 : // TODO: Doco
247 : void clear();
248 :
249 : /// Comparison operator for sorting individual FeatureDatas
250 60965 : bool operator<(const FeatureData & rhs) const
251 : {
252 60965 : if (_id != invalid_id)
253 : {
254 : mooseAssert(rhs._id != invalid_id, "Asymmetric setting of ids detected during sort");
255 :
256 : // Sort based on ids
257 50493 : return _id < rhs._id;
258 : }
259 : else
260 : // Sort based on processor independent information (mesh and variable info)
261 10472 : return _var_index < rhs._var_index ||
262 11893 : (_var_index == rhs._var_index && _min_entity_id < rhs._min_entity_id);
263 : }
264 :
265 : /// stream output operator
266 : friend std::ostream & operator<<(std::ostream & out, const FeatureData & feature);
267 :
268 : /// Holds the ghosted ids for a feature (the ids which will be used for stitching
269 : container_type _ghosted_ids;
270 :
271 : /// Holds the local ids in the interior of a feature.
272 : /// This data structure is only maintained on the local processor
273 : container_type _local_ids;
274 :
275 : /// Holds the ids surrounding the feature
276 : container_type _halo_ids;
277 :
278 : /// Holds halo ids that extend onto a non-topologically connected surface
279 : container_type _disjoint_halo_ids;
280 :
281 : /// Holds the nodes that belong to the feature on a periodic boundary
282 : container_type _periodic_nodes;
283 :
284 : /// The Moose variable where this feature was found (often the "order parameter")
285 : std::size_t _var_index;
286 :
287 : /// An ID for this feature
288 : unsigned int _id;
289 :
290 : /// The vector of bounding boxes completely enclosing this feature
291 : /// (multiple used with periodic constraints)
292 : std::vector<BoundingBox> _bboxes;
293 :
294 : /// Original processor/local ids
295 : std::list<std::pair<processor_id_type, unsigned int>> _orig_ids;
296 :
297 : /// The minimum entity seen in the _local_ids, used for sorting features
298 : dof_id_type _min_entity_id;
299 :
300 : /// The count of entities contributing to the volume calculation
301 : std::size_t _vol_count;
302 :
303 : /// The centroid of the feature (average of coordinates from entities participating in
304 : /// the volume calculation)
305 : Point _centroid;
306 :
307 : /// The status of a feature (used mostly in derived classes like the GrainTracker)
308 : Status _status;
309 :
310 : /// Enumeration indicating boundary intersection status
311 : BoundaryIntersection _boundary_intersection;
312 :
313 1574 : FeatureData duplicate() const { return FeatureData(*this); }
314 :
315 : private:
316 : ///@{
317 : /**
318 : * We do not expect these objects to ever be copied. This is important since they are stored in
319 : * standard containers directly. To enforce this, we are explicitly marking these methods
320 : * private. They can be triggered through an explicit call to "duplicate".
321 : */
322 1574 : FeatureData(const FeatureData & /* f */) = default;
323 : FeatureData & operator=(const FeatureData & /* f */) = default;
324 : ///@}
325 : };
326 :
327 : /// Return a constant reference to the vector of all discovered features
328 134 : const std::vector<FeatureData> & getFeatures() const { return _feature_sets; }
329 :
330 : protected:
331 : /**
332 : * Returns a Boolean indicating whether the entity is on one of the desired boundaries.
333 : */
334 : template <typename T>
335 : bool isBoundaryEntity(const T * entity) const;
336 :
337 : /**
338 : * This method is used to populate any of the data structures used for storing field data (nodal
339 : * or elemental). It is called at the end of finalize and can make use of any of the data
340 : * structures created during the execution of this postprocessor.
341 : */
342 : virtual void updateFieldInfo();
343 :
344 : /**
345 : * This method will check if the current entity is above the supplied threshold and "mark" it. It
346 : * will then inspect neighboring entities that are above the connecting threshold and add them to
347 : * the current feature.
348 : *
349 : * @return Boolean indicating whether a new feature was found while exploring the current entity.
350 : */
351 : bool flood(const DofObject * dof_object, std::size_t current_index);
352 :
353 : /**
354 : * Return the starting comparison threshold to use when inspecting an entity during the flood
355 : * stage.
356 : */
357 : virtual Real getThreshold(std::size_t current_index) const;
358 :
359 : /**
360 : * Return the "connecting" comparison threshold to use when inspecting an entity during the flood
361 : * stage.
362 : */
363 : virtual Real getConnectingThreshold(std::size_t current_index) const;
364 :
365 : /**
366 : * This method is used to determine whether the current entity value is part of a feature or not.
367 : * Comparisons can either be greater than or less than the threshold which is controlled via
368 : * input parameter.
369 : */
370 : bool compareValueWithThreshold(Real entity_value, Real threshold) const;
371 :
372 : /**
373 : * Method called during the recursive flood routine that should return whether or not the current
374 : * entity is part of the current feature (if one is being explored), or if it's the start
375 : * of a new feature.
376 : */
377 : virtual bool isNewFeatureOrConnectedRegion(const DofObject * dof_object,
378 : std::size_t & current_index,
379 : FeatureData *& feature,
380 : Status & status,
381 : unsigned int & new_id);
382 :
383 : /**
384 : * This method takes all of the partial features and expands the local, ghosted, and halo sets
385 : * around those regions to account for the diffuse interface. Rather than using any kind of
386 : * recursion here, we simply expand the region by all "point" neighbors from the actual grain
387 : * cells since all point neighbors will contain contributions to the region.
388 : */
389 : void expandPointHalos();
390 :
391 : /**
392 : * This method expands the existing halo set by some width determined by the passed in value.
393 : * This method does NOT mask off any local IDs.
394 : */
395 : void expandEdgeHalos(unsigned int num_layers_to_expand);
396 :
397 : ///@{
398 : /**
399 : * These two routines are utility routines used by the flood routine and by derived classes for
400 : * visiting neighbors. Since the logic is different for the elemental versus nodal case it's
401 : * easier to split them up.
402 : */
403 : void visitNodalNeighbors(const Node * node, FeatureData * feature, bool expand_halos_only);
404 : void visitElementalNeighbors(const Elem * elem,
405 : FeatureData * feature,
406 : bool expand_halos_only,
407 : bool disjoint_only);
408 : ///@}
409 :
410 : /**
411 : * The actual logic for visiting neighbors is abstracted out here. This method is templated to
412 : * handle the Nodal
413 : * and Elemental cases together.
414 : */
415 : template <typename T>
416 : void visitNeighborsHelper(const T * curr_entity,
417 : std::vector<const T *> neighbor_entities,
418 : FeatureData * feature,
419 : bool expand_halos_only,
420 : bool topological_neighbor,
421 : bool disjoint_only);
422 :
423 : /**
424 : * This routine uses the local flooded data to build up the local feature data structures
425 : * (_partial feature_sets). This routine does not perform any communication so the
426 : * _partial_feature_sets data structure will only contain information from the local processor
427 : * after calling this routine. Any existing data in the _partial_feature_sets structure is
428 : * destroyed by calling this routine.
429 : *
430 : * _partial_feature_sets layout:
431 : * The outer vector is sized to one when _single_map_mode == true, otherwise it is sized for the
432 : * number of coupled variables. The inner list represents the flooded regions (local only after
433 : * this call but fully populated after parallel communication and stitching).
434 : */
435 : virtual void prepareDataForTransfer();
436 :
437 : /**
438 : * This routines packs the _partial_feature_sets data into a structure suitable for parallel
439 : * communication operations.
440 : */
441 : void serialize(std::string & serialized_buffer, unsigned int var_num = invalid_id);
442 :
443 : /**
444 : * This routine takes the vector of byte buffers (one for each processor), deserializes them
445 : * into a series of FeatureSet objects, and appends them to the _feature_sets data structure.
446 : *
447 : * Note: It is assumed that local processor information may already be stored in the _feature_sets
448 : * data structure so it is not cleared before insertion.
449 : */
450 : void deserialize(std::vector<std::string> & serialized_buffers,
451 : unsigned int var_num = invalid_id);
452 :
453 : /**
454 : * This routine is called on the primary rank only and stitches together the partial
455 : * feature pieces seen on any processor.
456 : */
457 : virtual void mergeSets();
458 :
459 : /**
460 : * This method consolidates all of the merged information from _partial_feature_sets into
461 : * the _feature_sets vectors.
462 : */
463 : virtual void
464 : consolidateMergedFeatures(std::vector<std::list<FeatureData>> * saved_data = nullptr);
465 :
466 : /**
467 : * Method for determining whether two features are mergeable. This routine exists because
468 : * derived classes may need to override this function rather than use the mergeable method
469 : * in the FeatureData object.
470 : */
471 : virtual bool areFeaturesMergeable(const FeatureData & f1, const FeatureData & f2) const;
472 :
473 : /**
474 : * Returns a number indicating the number of merge helpers when running in parallel based
475 : * on certain implementer decided criteria. This is a communication versus computation
476 : * trade-off that we are almost always willing to make except for small problems. The
477 : * decision however may be more complicated for some derived classes.
478 : */
479 : virtual processor_id_type numberOfDistributedMergeHelpers() const;
480 :
481 : /**
482 : * This routine handles all of the serialization, communication and deserialization of the data
483 : * structures containing FeatureData objects.
484 : */
485 : void communicateAndMerge();
486 :
487 908 : virtual void restoreOriginalDataStructures(std::vector<std::list<FeatureData>> &) {}
488 :
489 : /**
490 : * Sort and assign ids to features based on their position in the container after sorting.
491 : */
492 : void sortAndLabel();
493 :
494 : /**
495 : * Calls buildLocalToGlobalIndices to build the individual local to global indicies for each rank
496 : * and scatters that information to all ranks. Finally, the non-primary ranks update their own
497 : * data structures to reflect the global mappings.
498 : */
499 : void scatterAndUpdateRanks();
500 :
501 : /**
502 : * This routine populates a stacked vector of local to global indices per rank and the associated
503 : * count vector for scattering the vector to the ranks. The individual vectors can be different
504 : * sizes. The ith vector will be distributed to the ith processor including the primary rank.
505 : * e.g.
506 : * [ ... n_0 ] [ ... n_1 ] ... [ ... n_m ]
507 : *
508 : * It is intended to be overridden in derived classes.
509 : */
510 : virtual void buildLocalToGlobalIndices(std::vector<std::size_t> & local_to_global_all,
511 : std::vector<int> & counts) const;
512 :
513 : /**
514 : * This method builds a lookup map for retrieving the right local feature (by index) given a
515 : * global index or id. max_id is passed to size the vector properly and may or may not be a
516 : * globally consistent number. The assumption is that any id that is later queried from this
517 : * object that is higher simply doesn't exist on the local processor.
518 : */
519 : void buildFeatureIdToLocalIndices(unsigned int max_id);
520 :
521 : /**
522 : * Helper routine for clearing up data structures during initialize and prior to parallel
523 : * communication.
524 : */
525 : virtual void clearDataStructures();
526 :
527 : /**
528 : * Update the feature's attributes to indicate boundary intersections
529 : */
530 : void updateBoundaryIntersections(FeatureData & feature) const;
531 :
532 : /**
533 : * This routine adds the periodic node information to our data structure prior to packing the data
534 : * this makes those periodic neighbors appear much like ghosted nodes in a multiprocessor setting
535 : */
536 : void appendPeriodicNeighborNodes(FeatureData & feature) const;
537 :
538 : /**
539 : * This routine updates the _region_offsets variable which is useful for quickly determining
540 : * the proper global number for a feature when using multimap mode
541 : */
542 : void updateRegionOffsets();
543 :
544 : /*************************************************
545 : *************** Data Structures *****************
546 : ************************************************/
547 : /// The vector of coupled in variables
548 : std::vector<MooseVariableFEBase *> _fe_vars;
549 : /// The vector of coupled in variables cast to MooseVariable
550 : std::vector<MooseVariable *> _vars;
551 :
552 : /// Reference to the dof_map containing the coupled variables
553 : const DofMap & _dof_map;
554 :
555 : /// The threshold above (or below) where an entity may begin a new region (feature)
556 : const Real _threshold;
557 : Real _step_threshold;
558 :
559 : /// The threshold above (or below) which neighboring entities are flooded
560 : /// (where regions can be extended but not started)
561 : const Real _connecting_threshold;
562 : Real _step_connecting_threshold;
563 :
564 : /// A reference to the mesh
565 : MooseMesh & _mesh;
566 :
567 : /**
568 : * This variable is used to build the periodic node map.
569 : * Assumption: We are going to assume that either all variables are periodic or none are.
570 : * This assumption can be relaxed at a later time if necessary.
571 : */
572 : unsigned long _var_number;
573 :
574 : /// This variable is used to indicate whether or not multiple maps are used during flooding
575 : const bool _single_map_mode;
576 :
577 : const bool _condense_map_info;
578 :
579 : /// This variable is used to indicate whether or not we identify features with
580 : /// unique numbers on multiple maps
581 : const bool _global_numbering;
582 :
583 : /// This variable is used to indicate whether the maps will contain unique region
584 : /// information or just the variable numbers owning those regions
585 : const bool _var_index_mode;
586 :
587 : /// Indicates whether or not to communicate halo map information with all ranks
588 : const bool _compute_halo_maps;
589 :
590 : /// Indicates whether or not the var to feature map is populated.
591 : const bool _compute_var_to_feature_map;
592 :
593 : /**
594 : * Use less-than when comparing values against the threshold value.
595 : * True by default. If false, then greater-than comparison is used
596 : * instead.
597 : */
598 : const bool _use_less_than_threshold_comparison;
599 :
600 : // Convenience variable holding the number of variables coupled into this object
601 : const std::size_t _n_vars;
602 :
603 : /// Convenience variable holding the size of all the datastructures size by the number of maps
604 : const std::size_t _maps_size;
605 :
606 : /// Convenience variable holding the number of processors in this simulation
607 : const processor_id_type _n_procs;
608 :
609 : /**
610 : * This variable keeps track of which nodes have been visited during execution. We don't use the
611 : * _feature_map for this since we don't want to explicitly store data for all the unmarked nodes
612 : * in a serialized datastructures.
613 : * This keeps our overhead down since this variable never needs to be communicated.
614 : */
615 : std::vector<std::set<dof_id_type>> _entities_visited;
616 :
617 : /**
618 : * This map keeps track of which variables own which nodes. We need a vector of them for multimap
619 : * mode where multiple variables can own a single mode.
620 : *
621 : * Note: This map is only populated when "show_var_coloring" is set to true.
622 : */
623 : std::vector<std::map<dof_id_type, int>> _var_index_maps;
624 :
625 : /// The data structure used to find neighboring elements give a node ID
626 : std::unordered_map<dof_id_type, std::vector<const Elem *>> _nodes_to_elem_map;
627 :
628 : /// The number of features seen by this object per map
629 : std::vector<unsigned int> _feature_counts_per_map;
630 :
631 : /// The number of features seen by this object (same as summing _feature_counts_per_map)
632 : unsigned int _feature_count;
633 :
634 : /**
635 : * The data structure used to hold partial and communicated feature data, during the discovery and
636 : * merging phases. The outer vector is indexed by map number (often variable number). The inner
637 : * list is an unordered list of partially discovered features.
638 : */
639 : std::vector<std::list<FeatureData>> _partial_feature_sets;
640 :
641 : /**
642 : * The data structure used to hold the globally unique features. The sorting of the vector is
643 : * implementation defined and may not correspond to anything useful. The ID of each feature should
644 : * be queried from the FeatureData objects.
645 : */
646 : std::vector<FeatureData> & _feature_sets;
647 :
648 : /**
649 : * Derived objects (e.g. the GrainTracker) may require restartable data to track information
650 : * across time steps. The FeatureFloodCounter however does not. This container is here so that
651 : * we have the flexabilty to switch between volatile and non-volatile storage. The _feature_sets
652 : * data structure can conditionally refer to this structure or a MOOSE-provided structure, which
653 : * is backed up.
654 : */
655 : std::vector<FeatureData> _volatile_feature_sets;
656 :
657 : /**
658 : * The feature maps contain the raw flooded node information and eventually the unique grain
659 : * numbers. We have a vector of them so we can create one per variable if that level of detail
660 : * is desired.
661 : */
662 : std::vector<std::map<dof_id_type, int>> _feature_maps;
663 :
664 : /// The vector recording the local to global feature indices
665 : std::vector<std::size_t> _local_to_global_feature_map;
666 :
667 : /// The vector recording the grain_id to local index (several indices will contain invalid_size_t)
668 : std::vector<std::size_t> _feature_id_to_local_index;
669 :
670 : /// A pointer to the periodic boundary constraints object
671 : libMesh::PeriodicBoundaries * _pbs;
672 :
673 : std::unique_ptr<libMesh::PointLocatorBase> _point_locator;
674 :
675 : /// Average value of the domain which can optionally be used to find features in a field
676 : const PostprocessorValue & _element_average_value;
677 :
678 : /// The map for holding reconstructed ghosted element information
679 : std::map<dof_id_type, int> _ghosted_entity_ids;
680 :
681 : /**
682 : * The data structure for looking up halos around features. The outer vector is for splitting out
683 : * the information per variable. The inner map holds the actual halo information
684 : */
685 : std::vector<std::map<dof_id_type, int>> _halo_ids;
686 :
687 : /**
688 : * The data structure which is a list of nodes that are constrained to other nodes
689 : * based on the imposed periodic boundary conditions.
690 : */
691 : std::multimap<dof_id_type, dof_id_type> _periodic_node_map;
692 :
693 : /// The set of entities on the boundary of the domain used for determining
694 : /// if features intersect any boundary
695 : std::unordered_set<dof_id_type> _all_boundary_entity_ids;
696 :
697 : std::map<dof_id_type, std::vector<unsigned int>> _entity_var_to_features;
698 :
699 : std::vector<unsigned int> _empty_var_to_features;
700 :
701 : std::vector<BoundaryID> _primary_perc_bnds;
702 : std::vector<BoundaryID> _secondary_perc_bnds;
703 :
704 : std::vector<BoundaryID> _specified_bnds;
705 :
706 : /// Determines if the flood counter is elements or not (nodes)
707 : const bool _is_elemental;
708 :
709 : /// Indicates that this object should only run on one or more boundaries
710 : bool _is_boundary_restricted;
711 :
712 : /// Boundary element range pointer
713 : ConstBndElemRange * _bnd_elem_range;
714 :
715 : /// Convenience variable for testing primary rank
716 : const bool _is_primary;
717 :
718 : private:
719 : template <class T>
720 : static inline void sort(std::set<T> & /*container*/)
721 : {
722 : // Sets are already sorted, do nothing
723 : }
724 :
725 : template <class T>
726 74995 : static inline void sort(std::vector<T> & container)
727 : {
728 74995 : std::sort(container.begin(), container.end());
729 74995 : }
730 :
731 : template <class T>
732 : static inline void reserve(std::set<T> & /*container*/, std::size_t /*size*/)
733 : {
734 : // Sets are trees, no reservations necessary
735 : }
736 :
737 : template <class T>
738 : static inline void reserve(std::vector<T> & container, std::size_t size)
739 : {
740 67524 : container.reserve(size);
741 67524 : }
742 :
743 : template <class T>
744 : static inline bool contains(std::set<T> & container, const T & item)
745 : {
746 : return container.find(item) != container.end();
747 : }
748 :
749 : template <class T>
750 : static inline bool contains(std::vector<T> & container, const T & item)
751 : {
752 172045782 : for (const auto & cont_item : container)
753 171401482 : if (item == cont_item)
754 : return true;
755 : return false;
756 : }
757 :
758 : /// The data structure for maintaining entities to flood during discovery
759 : std::deque<const DofObject *> _entity_queue;
760 : };
761 :
762 : template <>
763 : void dataStore(std::ostream & stream, FeatureFloodCount::FeatureData & feature, void * context);
764 : template <>
765 : void dataStore(std::ostream & stream, BoundingBox & bbox, void * context);
766 :
767 : template <>
768 : void dataLoad(std::istream & stream, FeatureFloodCount::FeatureData & feature, void * context);
769 : template <>
770 : void dataLoad(std::istream & stream, BoundingBox & bbox, void * context);
771 :
772 : template <>
773 : struct enable_bitmask_operators<FeatureFloodCount::Status>
774 : {
775 : static const bool enable = true;
776 : };
777 :
778 : template <>
779 : struct enable_bitmask_operators<FeatureFloodCount::BoundaryIntersection>
780 : {
781 : static const bool enable = true;
782 : };
|