17 #include "libmesh/mesh_tools.h" 18 #include "libmesh/periodic_boundaries.h" 19 #include "libmesh/point_locator_base.h" 25 const unsigned int INVALID_COLOR = std::numeric_limits<unsigned int>::max();
35 std::vector<unsigned int> & colors,
36 unsigned int n_vertices,
40 std::vector<unsigned int> & colors,
41 unsigned int n_vertices,
48 std::set<dof_id_type> & halo_ids);
50 std::vector<unsigned int>
56 Real grain_num = centerpoints.size();
58 std::vector<unsigned int> assigned_op(grain_num);
59 std::vector<int> min_op_ind(op_num);
60 std::vector<Real> min_op_dist(op_num);
63 for (
unsigned int grain = 0; grain < grain_num; grain++)
70 for (
unsigned int i = 0; i < op_num; ++i)
73 mesh.minPeriodicDistance(var.
number(), centerpoints[grain], centerpoints[i]);
74 min_op_ind[assigned_op[i]] = i;
78 for (
unsigned int i = op_num; i < grain; ++i)
80 Real dist =
mesh.minPeriodicDistance(var.
number(), centerpoints[grain], centerpoints[i]);
81 if (min_op_dist[assigned_op[i]] > dist)
83 min_op_dist[assigned_op[i]] = dist;
84 min_op_ind[assigned_op[i]] = i;
90 assigned_op[grain] = grain;
95 unsigned int mx_ind = 0;
96 for (
unsigned int i = 1; i < op_num; ++i)
97 if (min_op_dist[mx_ind] < min_op_dist[i])
100 assigned_op[grain] = mx_ind;
108 const std::vector<Point> & centerpoints,
113 unsigned int grain_num = centerpoints.size();
115 Real min_distance = maxsize;
116 unsigned int min_index = grain_num;
118 for (
unsigned int grain = 0; grain < grain_num; grain++)
122 if (min_distance > distance)
129 if (min_index >= grain_num)
130 mooseError(
"ERROR in PolycrystalVoronoiVoidIC: didn't find minimum values in grain_value_calc");
137 const std::map<dof_id_type, unsigned int> & entity_to_grain,
140 unsigned int n_grains,
151 const std::map<dof_id_type, unsigned int> & element_to_grain,
154 unsigned int n_grains)
159 mesh.errorIfDistributedMesh(
"advanced_op_assignment = true");
161 std::vector<const Elem *> all_active_neighbors;
163 std::vector<std::set<dof_id_type>> local_ids(n_grains);
164 std::vector<std::set<dof_id_type>> halo_ids(n_grains);
167 for (
const auto & elem :
mesh.getMesh().active_element_ptr_range())
169 std::map<dof_id_type, unsigned int>::const_iterator grain_it =
170 element_to_grain.find(elem->id());
171 mooseAssert(grain_it != element_to_grain.end(),
"Element not found in map");
172 unsigned int my_grain = grain_it->second;
174 all_active_neighbors.clear();
176 for (
unsigned int i = 0; i < elem->n_neighbors(); ++i)
179 if (neighbor_ancestor)
183 all_active_neighbors, elem,
mesh, *point_locator, pb,
false);
187 for (std::vector<const Elem *>::const_iterator neighbor_it = all_active_neighbors.begin();
188 neighbor_it != all_active_neighbors.end();
191 const Elem * neighbor = *neighbor_it;
192 std::map<dof_id_type, unsigned int>::const_iterator grain_it2 =
193 element_to_grain.find(neighbor->
id());
194 mooseAssert(grain_it2 != element_to_grain.end(),
"Element not found in map");
195 unsigned int their_grain = grain_it2->second;
197 if (my_grain != their_grain)
208 local_ids[my_grain].insert(elem->id());
209 local_ids[their_grain].insert(neighbor->
id());
212 halo_ids[my_grain].insert(neighbor->
id());
213 halo_ids[their_grain].insert(elem->id());
220 std::set<dof_id_type> set_difference;
221 for (
unsigned int i = 0; i < n_grains; ++i)
223 std::set<dof_id_type> orig_halo_ids(halo_ids[i]);
227 for (std::set<dof_id_type>::iterator entity_it = orig_halo_ids.begin();
228 entity_it != orig_halo_ids.end();
233 mesh.elemPtr(*entity_it),
mesh.getMesh(), *point_locator, pb, halo_ids[i]);
238 set_difference.clear();
242 local_ids[i].begin(),
244 std::insert_iterator<std::set<dof_id_type>>(set_difference, set_difference.begin()));
246 halo_ids[i].swap(set_difference);
251 std::set<dof_id_type> set_intersection;
252 for (
unsigned int i = 0; i < n_grains; ++i)
253 for (
unsigned int j = i + 1;
j < n_grains; ++
j)
255 set_intersection.clear();
256 std::set_intersection(
261 std::insert_iterator<std::set<dof_id_type>>(set_intersection, set_intersection.begin()));
263 if (!set_intersection.empty())
265 adjacency_matrix(i,
j) = 1.;
266 adjacency_matrix(
j, i) = 1.;
270 return adjacency_matrix;
275 const std::map<dof_id_type, unsigned int> & node_to_grain,
278 unsigned int n_grains)
281 std::vector<std::vector<const Elem *>> nodes_to_elem_map;
286 const auto end =
mesh.getMesh().active_nodes_end();
287 for (
auto nl =
mesh.getMesh().active_nodes_begin(); nl != end; ++nl)
289 const Node * node = *nl;
290 std::map<dof_id_type, unsigned int>::const_iterator grain_it = node_to_grain.find(node->
id());
291 mooseAssert(grain_it != node_to_grain.end(),
"Node not found in map");
292 unsigned int my_grain = grain_it->second;
294 std::vector<const Node *> nodal_neighbors;
298 for (
unsigned int i = 0; i < nodal_neighbors.size(); ++i)
300 const Node * neighbor_node = nodal_neighbors[i];
301 std::map<dof_id_type, unsigned int>::const_iterator grain_it2 =
302 node_to_grain.find(neighbor_node->
id());
303 mooseAssert(grain_it2 != node_to_grain.end(),
"Node not found in map");
304 unsigned int their_grain = grain_it2->second;
306 if (my_grain != their_grain)
314 adjacency_matrix(my_grain, their_grain) = 1.;
318 return adjacency_matrix;
321 std::vector<unsigned int>
323 unsigned int n_grains,
330 if (coloring_algorithm ==
"bt")
332 if (!
colorGraph(adjacency_matrix, grain_to_op, n_grains, n_ops, 0))
334 "Unable to find a valid Grain to op configuration, do you have enough op variables?");
338 const std::string & ca_str = coloring_algorithm;
341 am_data, n_grains, n_ops, grain_to_op, ca_str.c_str());
350 return MooseEnum(
"legacy bt jp power greedy",
"legacy");
356 return "The grain neighbor graph coloring algorithm to use. \"legacy\" is the original " 358 "which does not guarantee a valid coloring. \"bt\" is a simple backtracking algorithm " 359 "which will produce a valid coloring but has potential exponential run time. The " 360 "remaining algorithms require PETSc but are recommended for larger problems (See " 372 std::set<dof_id_type> & halo_ids)
374 mooseAssert(elem,
"Elem is NULL");
376 std::vector<const Elem *> all_active_neighbors;
379 for (
unsigned int i = 0; i < elem->
n_neighbors(); ++i)
382 if (neighbor_ancestor)
386 all_active_neighbors, elem,
mesh, point_locator, pb,
false);
390 for (std::vector<const Elem *>::const_iterator neighbor_it = all_active_neighbors.begin();
391 neighbor_it != all_active_neighbors.end();
394 halo_ids.insert((*neighbor_it)->id());
402 std::vector<unsigned int> & colors,
403 unsigned int n_vertices,
404 unsigned int n_colors,
408 if (vertex == n_vertices)
412 for (
unsigned int color_idx = 0; color_idx < n_colors; ++color_idx)
416 unsigned int color = (vertex + color_idx) % n_colors;
418 if (
isGraphValid(adjacency_matrix, colors, n_vertices, vertex, color))
420 colors[vertex] = color;
422 if (
colorGraph(adjacency_matrix, colors, n_vertices, n_colors, vertex + 1))
435 std::vector<unsigned int> & colors,
436 unsigned int n_vertices,
441 for (
unsigned int neighbor = 0; neighbor < n_vertices; ++neighbor)
442 if (adjacency_matrix(vertex, neighbor) && color == colors[neighbor])
void active_family_tree_by_topological_neighbor(std::vector< const Elem * > &family, const Elem *neighbor, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb, bool reset=true) const
std::unique_ptr< PointLocatorBase > sub_point_locator() const
const Elem * topological_neighbor(const unsigned int i, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
void mooseError(Args &&... args)
unsigned int number() const
const unsigned int INVALID_COLOR
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
Real distance(const Point &p)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int n_neighbors() const
void colorAdjacencyMatrix(PetscScalar *adjacency_matrix, unsigned int size, unsigned int colors, std::vector< unsigned int > &vertex_colors, const char *coloring_algorithm)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")