void GrainTracker::expandHalos() { processor_id_type n_procs = _app.n_processors(); for (unsigned int map_num = 0; map_num < _maps_size; ++map_num) for (processor_id_type rank = 0; rank < n_procs; ++rank) for (std::vector<FeatureData>::iterator it = _partial_feature_sets[rank][map_num].begin(); it != _partial_feature_sets[rank][map_num].end(); ++it) { FeatureData & feature = *it; for (unsigned int halo_level = 1; halo_level < _halo_level; ++halo_level) { /** * Create a copy of the halo set so that as we insert new ids into the * set we don't continue to iterate on those new ids. */ std::set<dof_id_type> orig_halo_ids(feature._halo_ids); for (std::set<dof_id_type>::iterator entity_it = orig_halo_ids.begin(); entity_it != orig_halo_ids.end(); ++entity_it) { if (_is_elemental) visitElementalNeighbors(_mesh.elemPtr(*entity_it), feature._var_idx, &feature, /*recurse =*/false); else visitNodalNeighbors(_mesh.nodePtr(*entity_it), feature._var_idx, &feature, /*recurse =*/false); } } } }
PolycrystalICTools::AdjacencyMatrix<Real> PolycrystalICTools::buildElementalGrainAdjacencyMatrix( const std::map<dof_id_type, unsigned int> & element_to_grain, MooseMesh & mesh, const PeriodicBoundaries * pb, unsigned int n_grains) { AdjacencyMatrix<Real> adjacency_matrix(n_grains); // We can't call this in the constructor, it appears that _mesh_ptr is always NULL there. mesh.errorIfDistributedMesh("advanced_op_assignment = true"); std::vector<const Elem *> all_active_neighbors; std::vector<std::set<dof_id_type>> local_ids(n_grains); std::vector<std::set<dof_id_type>> halo_ids(n_grains); std::unique_ptr<PointLocatorBase> point_locator = mesh.getMesh().sub_point_locator(); for (const auto & elem : mesh.getMesh().active_element_ptr_range()) { std::map<dof_id_type, unsigned int>::const_iterator grain_it = element_to_grain.find(elem->id()); mooseAssert(grain_it != element_to_grain.end(), "Element not found in map"); unsigned int my_grain = grain_it->second; all_active_neighbors.clear(); // Loop over all neighbors (at the the same level as the current element) for (unsigned int i = 0; i < elem->n_neighbors(); ++i) { const Elem * neighbor_ancestor = elem->topological_neighbor(i, mesh, *point_locator, pb); if (neighbor_ancestor) // Retrieve only the active neighbors for each side of this element, append them to the list // of active neighbors neighbor_ancestor->active_family_tree_by_topological_neighbor( all_active_neighbors, elem, mesh, *point_locator, pb, false); } // Loop over all active element neighbors for (std::vector<const Elem *>::const_iterator neighbor_it = all_active_neighbors.begin(); neighbor_it != all_active_neighbors.end(); ++neighbor_it) { const Elem * neighbor = *neighbor_it; std::map<dof_id_type, unsigned int>::const_iterator grain_it2 = element_to_grain.find(neighbor->id()); mooseAssert(grain_it2 != element_to_grain.end(), "Element not found in map"); unsigned int their_grain = grain_it2->second; if (my_grain != their_grain) { /** * We've found a grain neighbor interface. In order to assign order parameters though, we * need to make sure that we build out a small buffer region to avoid literal "corner cases" * where nodes on opposite corners of a QUAD end up with the same OP because those nodes are * not nodal neighbors. To do that we'll build a halo region based on these interface nodes. * For now, we need to record the nodes inside of the grain and those outside of the grain. */ // First add corresponding element and grain information local_ids[my_grain].insert(elem->id()); local_ids[their_grain].insert(neighbor->id()); // Now add opposing element and grain information halo_ids[my_grain].insert(neighbor->id()); halo_ids[their_grain].insert(elem->id()); } // adjacency_matrix[my_grain][their_grain] = 1; } } // Build up the halos std::set<dof_id_type> set_difference; for (unsigned int i = 0; i < n_grains; ++i) { std::set<dof_id_type> orig_halo_ids(halo_ids[i]); for (unsigned int halo_level = 0; halo_level < PolycrystalICTools::HALO_THICKNESS; ++halo_level) { for (std::set<dof_id_type>::iterator entity_it = orig_halo_ids.begin(); entity_it != orig_halo_ids.end(); ++entity_it) { if (true) visitElementalNeighbors( mesh.elemPtr(*entity_it), mesh.getMesh(), *point_locator, pb, halo_ids[i]); else mooseError("Unimplemented"); } set_difference.clear(); std::set_difference( halo_ids[i].begin(), halo_ids[i].end(), local_ids[i].begin(), local_ids[i].end(), std::insert_iterator<std::set<dof_id_type>>(set_difference, set_difference.begin())); halo_ids[i].swap(set_difference); } } // Finally look at the halo intersections to build the connectivity graph std::set<dof_id_type> set_intersection; for (unsigned int i = 0; i < n_grains; ++i) for (unsigned int j = i + 1; j < n_grains; ++j) { set_intersection.clear(); std::set_intersection( halo_ids[i].begin(), halo_ids[i].end(), halo_ids[j].begin(), halo_ids[j].end(), std::insert_iterator<std::set<dof_id_type>>(set_intersection, set_intersection.begin())); if (!set_intersection.empty()) { adjacency_matrix(i, j) = 1.; adjacency_matrix(j, i) = 1.; } } return adjacency_matrix; }