13 #include "MooseMesh.h"
14 #include "MooseVariable.h"
16 #include "libmesh/mesh_tools.h"
17 #include "libmesh/periodic_boundaries.h"
18 #include "libmesh/point_locator_base.h"
22 const unsigned int INVALID_COLOR = std::numeric_limits<unsigned int>::max();
32 std::vector<unsigned int> & colors,
33 unsigned int n_vertices,
37 std::vector<unsigned int> & colors,
38 unsigned int n_vertices,
42 const MeshBase & mesh,
43 const PointLocatorBase & point_locator,
44 const PeriodicBoundaries * pb,
45 std::set<dof_id_type> & halo_ids);
47 std::vector<unsigned int>
50 const MooseMesh & mesh,
51 const MooseVariable & var)
53 Real grain_num = centerpoints.size();
55 std::vector<unsigned int> assigned_op(grain_num);
56 std::vector<int> min_op_ind(op_num);
57 std::vector<Real> min_op_dist(op_num);
60 for (
unsigned int grain = 0; grain < grain_num; grain++)
67 for (
unsigned int i = 0; i < op_num; ++i)
70 mesh.minPeriodicDistance(var.number(), 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.number(), 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,
106 const MooseMesh & mesh,
107 const MooseVariable & var,
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.number(), centerpoints[grain], p);
119 if (min_distance > distance)
121 min_distance = distance;
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,
148 const std::map<dof_id_type, unsigned int> & element_to_grain,
150 const PeriodicBoundaries * pb,
151 unsigned int 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]);
232 mooseError(
"Unimplemented");
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);
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;
318 std::vector<unsigned int>
320 unsigned int n_grains,
322 const MooseEnum & coloring_algorithm)
324 Moose::perf_log.push(
"assignOpsToGrains()",
"PolycrystalICTools");
329 if (coloring_algorithm ==
"bt")
331 if (!
colorGraph(adjacency_matrix, grain_to_op, n_grains, n_ops, 0))
333 "Unable to find a valid Grain to op configuration, do you have enough op variables?");
337 #ifdef LIBMESH_HAVE_PETSC
338 const std::string & ca_str = coloring_algorithm;
339 Real * am_data = adjacency_matrix.
rawDataPtr();
340 Moose::PetscSupport::colorAdjacencyMatrix(
341 am_data, n_grains, n_ops, grain_to_op, ca_str.c_str());
343 mooseError(
"Selected coloring algorithm requires PETSc");
347 Moose::perf_log.pop(
"assignOpsToGrains()",
"PolycrystalICTools");
355 return MooseEnum(
"legacy bt jp power greedy",
"legacy");
361 return "The grain neighbor graph coloring algorithm to use. \"legacy\" is the original "
363 "which does not guarantee a valid coloring. \"bt\" is a simple backtracking algorithm "
364 "which will produce a valid coloring but has potential exponential run time. The "
365 "remaining algorithms require PETSc but are recommended for larger problems (See "
374 const MeshBase & mesh,
375 const PointLocatorBase & point_locator,
376 const PeriodicBoundaries * pb,
377 std::set<dof_id_type> & halo_ids)
379 mooseAssert(elem,
"Elem is NULL");
381 std::vector<const Elem *> all_active_neighbors;
384 for (
unsigned int i = 0; i < elem->n_neighbors(); ++i)
386 const Elem * neighbor_ancestor = elem->topological_neighbor(i, mesh, point_locator, pb);
387 if (neighbor_ancestor)
390 neighbor_ancestor->active_family_tree_by_topological_neighbor(
391 all_active_neighbors, elem, mesh, point_locator, pb,
false);
395 for (std::vector<const Elem *>::const_iterator neighbor_it = all_active_neighbors.begin();
396 neighbor_it != all_active_neighbors.end();
399 halo_ids.insert((*neighbor_it)->id());
407 std::vector<unsigned int> & colors,
408 unsigned int n_vertices,
409 unsigned int n_colors,
413 if (vertex == n_vertices)
417 for (
unsigned int color_idx = 0; color_idx < n_colors; ++color_idx)
421 unsigned int color = (vertex + color_idx) % n_colors;
423 if (
isGraphValid(adjacency_matrix, colors, n_vertices, vertex, color))
425 colors[vertex] = color;
427 if (
colorGraph(adjacency_matrix, colors, n_vertices, n_colors, vertex + 1))
440 std::vector<unsigned int> & colors,
441 unsigned int n_vertices,
446 for (
unsigned int neighbor = 0; neighbor < n_vertices; ++neighbor)
447 if (adjacency_matrix(vertex, neighbor) && color == colors[neighbor])