17#include "libmesh/mesh_tools.h"
18#include "libmesh/periodic_boundaries.h"
19#include "libmesh/point_locator_base.h"
23const unsigned int INVALID_COLOR = std::numeric_limits<unsigned int>::max();
33 std::vector<unsigned int> & colors,
34 unsigned int n_vertices,
38 std::vector<unsigned int> & colors,
39 unsigned int n_vertices,
43 const MeshBase & mesh,
44 const PointLocatorBase & point_locator,
45 const PeriodicBoundaries * pb,
46 std::set<dof_id_type> & halo_ids);
48std::vector<unsigned int>
54 Real grain_num = centerpoints.size();
56 std::vector<unsigned int> assigned_op(grain_num);
57 std::vector<int> min_op_ind(op_num);
58 std::vector<Real> min_op_dist(op_num);
61 for (
unsigned int grain = 0; grain < grain_num; grain++)
68 for (
unsigned int i = 0; i < op_num; ++i)
70 min_op_dist[i] =
mesh.minPeriodicDistance(var, centerpoints[grain], centerpoints[i]);
71 min_op_ind[assigned_op[i]] = i;
75 for (
unsigned int i = op_num; i < grain; ++i)
77 Real dist =
mesh.minPeriodicDistance(var, centerpoints[grain], centerpoints[i]);
78 if (min_op_dist[assigned_op[i]] > dist)
80 min_op_dist[assigned_op[i]] = dist;
81 min_op_ind[assigned_op[i]] = i;
87 assigned_op[grain] = grain;
92 unsigned int mx_ind = 0;
93 for (
unsigned int i = 1; i < op_num; ++i)
94 if (min_op_dist[mx_ind] < min_op_dist[i])
97 assigned_op[grain] = mx_ind;
105 const std::vector<Point> & centerpoints,
110 unsigned int grain_num = centerpoints.size();
112 Real min_distance = maxsize;
113 unsigned int min_index = grain_num;
115 for (
unsigned int grain = 0; grain < grain_num; grain++)
117 Real
distance =
mesh.minPeriodicDistance(var, centerpoints[grain],
p);
126 if (min_index >= grain_num)
127 mooseError(
"ERROR in PolycrystalVoronoiVoidIC: didn't find minimum values in grain_value_calc");
134 const std::map<dof_id_type, unsigned int> & entity_to_grain,
136 const PeriodicBoundaries * pb,
137 unsigned int n_grains,
141 return buildElementalGrainAdjacencyMatrix(entity_to_grain, mesh, pb, n_grains);
143 return buildNodalGrainAdjacencyMatrix(entity_to_grain, mesh, pb, n_grains);
148 const std::map<dof_id_type, unsigned int> & element_to_grain,
150 const PeriodicBoundaries * pb,
151 unsigned int n_grains)
153 AdjacencyMatrix<Real> adjacency_matrix(n_grains);
156 mesh.errorIfDistributedMesh(
"advanced_op_assignment = true");
158 std::vector<const Elem *> all_active_neighbors;
160 std::vector<std::set<dof_id_type>> local_ids(n_grains);
161 std::vector<std::set<dof_id_type>> halo_ids(n_grains);
163 std::unique_ptr<PointLocatorBase> point_locator =
mesh.getMesh().sub_point_locator();
164 for (
const auto & elem :
mesh.
getMesh().active_element_ptr_range())
166 std::map<dof_id_type, unsigned int>::const_iterator grain_it =
167 element_to_grain.find(elem->id());
168 mooseAssert(grain_it != element_to_grain.end(),
"Element not found in map");
169 unsigned int my_grain = grain_it->second;
171 all_active_neighbors.clear();
173 for (
unsigned int i = 0; i < elem->n_neighbors(); ++i)
175 const Elem * neighbor_ancestor = elem->topological_neighbor(i, mesh, *point_locator, pb);
176 if (neighbor_ancestor)
179 neighbor_ancestor->active_family_tree_by_topological_neighbor(
180 all_active_neighbors, elem, mesh, *point_locator, pb,
false);
184 for (std::vector<const Elem *>::const_iterator neighbor_it = all_active_neighbors.begin();
185 neighbor_it != all_active_neighbors.end();
188 const Elem * neighbor = *neighbor_it;
189 std::map<dof_id_type, unsigned int>::const_iterator grain_it2 =
190 element_to_grain.find(neighbor->id());
191 mooseAssert(grain_it2 != element_to_grain.end(),
"Element not found in map");
192 unsigned int their_grain = grain_it2->second;
194 if (my_grain != their_grain)
205 local_ids[my_grain].insert(elem->id());
206 local_ids[their_grain].insert(neighbor->id());
209 halo_ids[my_grain].insert(neighbor->id());
210 halo_ids[their_grain].insert(elem->id());
217 std::set<dof_id_type> set_difference;
218 for (
unsigned int i = 0; i < n_grains; ++i)
220 std::set<dof_id_type> orig_halo_ids(halo_ids[i]);
224 for (std::set<dof_id_type>::iterator entity_it = orig_halo_ids.begin();
225 entity_it != orig_halo_ids.end();
230 mesh.elemPtr(*entity_it),
mesh.getMesh(), *point_locator, pb, halo_ids[i]);
235 set_difference.clear();
239 local_ids[i].begin(),
241 std::insert_iterator<std::set<dof_id_type>>(set_difference, set_difference.begin()));
243 halo_ids[i].swap(set_difference);
248 std::set<dof_id_type> set_intersection;
249 for (
unsigned int i = 0; i < n_grains; ++i)
250 for (
unsigned int j = i + 1; j < n_grains; ++j)
252 set_intersection.clear();
253 std::set_intersection(
258 std::insert_iterator<std::set<dof_id_type>>(set_intersection, set_intersection.begin()));
260 if (!set_intersection.empty())
262 adjacency_matrix(i, j) = 1.;
263 adjacency_matrix(j, i) = 1.;
267 return adjacency_matrix;
272 const std::map<dof_id_type, unsigned int> & node_to_grain,
274 const PeriodicBoundaries * ,
275 unsigned int n_grains)
278 std::vector<std::vector<const Elem *>> nodes_to_elem_map;
279 MeshTools::build_nodes_to_elem_map(
mesh.getMesh(), nodes_to_elem_map);
281 AdjacencyMatrix<Real> adjacency_matrix(n_grains);
283 const auto end =
mesh.getMesh().active_nodes_end();
284 for (
auto nl =
mesh.getMesh().active_nodes_begin(); nl != end; ++nl)
286 const Node * node = *nl;
287 std::map<dof_id_type, unsigned int>::const_iterator grain_it = node_to_grain.find(node->id());
288 mooseAssert(grain_it != node_to_grain.end(),
"Node not found in map");
289 unsigned int my_grain = grain_it->second;
291 std::vector<const Node *> nodal_neighbors;
292 MeshTools::find_nodal_neighbors(
mesh.getMesh(), *node, nodes_to_elem_map, nodal_neighbors);
295 for (
unsigned int i = 0; i < nodal_neighbors.size(); ++i)
297 const Node * neighbor_node = nodal_neighbors[i];
298 std::map<dof_id_type, unsigned int>::const_iterator grain_it2 =
299 node_to_grain.find(neighbor_node->id());
300 mooseAssert(grain_it2 != node_to_grain.end(),
"Node not found in map");
301 unsigned int their_grain = grain_it2->second;
303 if (my_grain != their_grain)
311 adjacency_matrix(my_grain, their_grain) = 1.;
315 return adjacency_matrix;
318std::vector<unsigned int>
320 unsigned int n_grains,
327 if (coloring_algorithm ==
"bt")
329 if (!
colorGraph(adjacency_matrix, grain_to_op, n_grains, n_ops, 0))
331 "Unable to find a valid Grain to op configuration, do you have enough op variables?");
335 const std::string & ca_str = coloring_algorithm;
336 Real * am_data = adjacency_matrix.
rawDataPtr();
338 am_data, n_grains, n_ops, grain_to_op, ca_str.c_str());
347 return MooseEnum(
"legacy bt jp power greedy",
"legacy");
353 return "The grain neighbor graph coloring algorithm to use. \"legacy\" is the original "
355 "which does not guarantee a valid coloring. \"bt\" is a simple backtracking algorithm "
356 "which will produce a valid coloring but has potential exponential run time. The "
357 "remaining algorithms require PETSc but are recommended for larger problems (See "
366 const MeshBase & mesh,
367 const PointLocatorBase & point_locator,
368 const PeriodicBoundaries * pb,
369 std::set<dof_id_type> & halo_ids)
371 mooseAssert(elem,
"Elem is NULL");
373 std::vector<const Elem *> all_active_neighbors;
376 for (
unsigned int i = 0; i < elem->n_neighbors(); ++i)
378 const Elem * neighbor_ancestor = elem->topological_neighbor(i,
mesh, point_locator, pb);
379 if (neighbor_ancestor)
382 neighbor_ancestor->active_family_tree_by_topological_neighbor(
383 all_active_neighbors, elem,
mesh, point_locator, pb,
false);
387 for (std::vector<const Elem *>::const_iterator neighbor_it = all_active_neighbors.begin();
388 neighbor_it != all_active_neighbors.end();
391 halo_ids.insert((*neighbor_it)->id());
399 std::vector<unsigned int> & colors,
400 unsigned int n_vertices,
401 unsigned int n_colors,
405 if (vertex == n_vertices)
409 for (
unsigned int color_idx = 0; color_idx < n_colors; ++color_idx)
413 unsigned int color = (vertex + color_idx) % n_colors;
415 if (
isGraphValid(adjacency_matrix, colors, n_vertices, vertex, color))
417 colors[vertex] = color;
419 if (
colorGraph(adjacency_matrix, colors, n_vertices, n_colors, vertex + 1))
432 std::vector<unsigned int> & colors,
433 unsigned int n_vertices,
438 for (
unsigned int neighbor = 0; neighbor < n_vertices; ++neighbor)
439 if (adjacency_matrix(vertex, neighbor) && color == colors[neighbor])
void mooseError(Args &&... args)
const unsigned int INVALID_COLOR
void colorAdjacencyMatrix(PetscScalar *adjacency_matrix, unsigned int size, unsigned int colors, std::vector< unsigned int > &vertex_colors, const char *coloring_algorithm)
T & getMesh(MooseMesh &mesh)
function to cast mesh
Real distance(const Point &p)