/** * Backtracking graph coloring routines */ bool colorGraph(const PolycrystalICTools::AdjacencyMatrix<Real> & adjacency_matrix, std::vector<unsigned int> & colors, unsigned int n_vertices, unsigned int n_colors, unsigned int vertex) { // Base case: All grains are assigned if (vertex == n_vertices) return true; // Consider this grain and try different ops for (unsigned int color_idx = 0; color_idx < n_colors; ++color_idx) { // We'll try to spread these colors around a bit rather than // packing them all on the first few colors if we have several colors. unsigned int color = (vertex + color_idx) % n_colors; if (isGraphValid(adjacency_matrix, colors, n_vertices, vertex, color)) { colors[vertex] = color; if (colorGraph(adjacency_matrix, colors, n_vertices, n_colors, vertex + 1)) return true; // Backtrack... colors[vertex] = GraphColoring::INVALID_COLOR; } } return false; }
std::vector<unsigned int> PolycrystalICTools::assignOpsToGrains(AdjacencyMatrix<Real> & adjacency_matrix, unsigned int n_grains, unsigned int n_ops, const MooseEnum & coloring_algorithm) { Moose::perf_log.push("assignOpsToGrains()", "PolycrystalICTools"); std::vector<unsigned int> grain_to_op(n_grains, GraphColoring::INVALID_COLOR); // Use a simple backtracking coloring algorithm if (coloring_algorithm == "bt") { if (!colorGraph(adjacency_matrix, grain_to_op, n_grains, n_ops, 0)) mooseError( "Unable to find a valid Grain to op configuration, do you have enough op variables?"); } else // PETSc Coloring algorithms { #ifdef LIBMESH_HAVE_PETSC const std::string & ca_str = coloring_algorithm; Real * am_data = adjacency_matrix.rawDataPtr(); Moose::PetscSupport::colorAdjacencyMatrix( am_data, n_grains, n_ops, grain_to_op, ca_str.c_str()); #else mooseError("Selected coloring algorithm requires PETSc"); #endif } Moose::perf_log.pop("assignOpsToGrains()", "PolycrystalICTools"); return grain_to_op; }
bool PolycrystalUserObjectBase::colorGraph(unsigned int vertex) { // Base case: All grains are assigned if (vertex == _feature_count) return true; // Consider this grain and try different ops for (unsigned int color_idx = 0; color_idx < _op_num; ++color_idx) { // We'll try to spread these colors around a bit rather than // packing them all on the first few colors if we have several colors. unsigned int color = (vertex + color_idx) % _op_num; if (isGraphValid(vertex, color)) { _grain_to_op[vertex] = color; if (colorGraph(vertex + 1)) return true; // Backtrack... _grain_to_op[vertex] = PolycrystalUserObjectBase::INVALID_COLOR; } } return false; }
void PolycrystalUserObjectBase::assignOpsToGrains() { mooseAssert(_is_master, "This routine should only be called on the master rank"); // Moose::perf_log.push("assignOpsToGrains()", "PolycrystalICTools"); // // Use a simple backtracking coloring algorithm if (_coloring_algorithm == "bt") { if (!colorGraph(0)) mooseError("Unable to find a valid grain to op coloring, do you have enough op variables?"); } else // PETSc Coloring algorithms { #ifdef LIBMESH_HAVE_PETSC const std::string & ca_str = _coloring_algorithm; Real * am_data = _adjacency_matrix->get_values().data(); Moose::PetscSupport::colorAdjacencyMatrix( am_data, _feature_count, _vars.size(), _grain_to_op, ca_str.c_str()); #else mooseError("Selected coloring algorithm requires PETSc"); #endif } // Moose::perf_log.pop("assignOpsToGrains()", "PolycrystalICTools"); }
void PolycrystalUserObjectBase::assignOpsToGrains() { mooseAssert(_is_master, "This routine should only be called on the master rank"); Moose::perf_log.push("assignOpsToGrains()", "PolycrystalICTools"); // Use a simple backtracking coloring algorithm if (_coloring_algorithm == "bt") { paramInfo("coloring_algorithm", "The backtracking algorithm has exponential complexity. If you are using very few " "order parameters, or you have several hundred grains or more, you should use one of " "the PETSc coloring algorithms such as \"jp\"."); if (!colorGraph(0)) paramError("op_num", "Unable to find a valid grain to op coloring, Make sure you have created enough " "variables to hold a valid polycrystal initial condition (no grains represented " "by the same variable should be allowed to touch, ~8 for 2D, ~25 for 3D)?"); } else // PETSc Coloring algorithms { #ifdef LIBMESH_HAVE_PETSC const std::string & ca_str = _coloring_algorithm; Real * am_data = _adjacency_matrix->get_values().data(); try { Moose::PetscSupport::colorAdjacencyMatrix( am_data, _feature_count, _vars.size(), _grain_to_op, ca_str.c_str()); } catch (std::runtime_error & e) { paramError("op_num", "Unable to find a valid grain to op coloring, Make sure you have created enough " "variables to hold a valid polycrystal initial condition (no grains represented " "by the same variable should be allowed to touch, ~8 for 2D, ~25 for 3D)?"); } #else mooseError("Selected coloring algorithm requires PETSc"); #endif } Moose::perf_log.pop("assignOpsToGrains()", "PolycrystalICTools"); }