Ejemplo n.º 1
0
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);
          }
        }
      }
}
Ejemplo n.º 2
0
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;
}