示例#1
0
void
FeatureFloodCount::flood(const DofObject * dof_object, unsigned long current_idx, FeatureData * feature)
{
  if (dof_object == nullptr)
    return;

  // Retrieve the id of the current entity
  auto entity_id = dof_object->id();

  // Has this entity already been marked? - if so move along
  if (_entities_visited[current_idx].find(entity_id) != _entities_visited[current_idx].end())
    return;

  // Mark this entity as visited
  _entities_visited[current_idx][entity_id] = true;

  // Determine which threshold to use based on whether this is an established region
  auto threshold = feature ? _step_connecting_threshold : _step_threshold;

  // Get the value of the current variable for the current entity
  Real entity_value;
  if (_is_elemental)
  {
    const Elem * elem = static_cast<const Elem *>(dof_object);
    std::vector<Point> centroid(1, elem->centroid());
    _subproblem.reinitElemPhys(elem, centroid, 0);
    entity_value = _vars[current_idx]->sln()[0];
  }
  else
    entity_value = _vars[current_idx]->getNodalValue(*static_cast<const Node *>(dof_object));

  // This node hasn't been marked, is it in a feature?  We must respect
  // the user-selected value of _use_less_than_threshold_comparison.
  if (_use_less_than_threshold_comparison && (entity_value < threshold))
    return;

  if (!_use_less_than_threshold_comparison && (entity_value > threshold))
    return;

  /**
   * If we reach this point (i.e. we haven't returned early from this routine),
   * we've found a new mesh entity that's part of a feature.
   */
  auto map_num = _single_map_mode ? decltype(current_idx)(0) : current_idx;

  // New Feature (we need to create it and add it to our data structure)
  if (!feature)
    _partial_feature_sets[map_num].emplace_back(current_idx);

  // Get a handle to the feature we will update (always the last feature in the data structure)
  feature = &_partial_feature_sets[map_num].back();

  // Insert the current entity into the local ids map
  feature->_local_ids.insert(entity_id);

  if (_is_elemental)
    visitElementalNeighbors(static_cast<const Elem *>(dof_object), current_idx, feature, /*expand_halos_only =*/false);
  else
    visitNodalNeighbors(static_cast<const Node *>(dof_object), current_idx, feature, /*expand_halos_only =*/false);
}
示例#2
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);
          }
        }
      }
}
示例#3
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;
}
示例#4
0
void
FeatureFloodCount::flood(const DofObject * dof_object, std::size_t current_index, FeatureData * feature)
{
  if (dof_object == nullptr)
    return;

  // Retrieve the id of the current entity
  auto entity_id = dof_object->id();

  // Has this entity already been marked? - if so move along
  if (_entities_visited[current_index].find(entity_id) != _entities_visited[current_index].end())
    return;

  // See if the current entity either starts a new feature or continues an existing feature
  auto new_id = invalid_id;  // Writable reference to hold an optional id;
  if (!isNewFeatureOrConnectedRegion(dof_object, current_index, feature, new_id))
    return;

  /**
   * If we reach this point (i.e. we haven't returned early from this routine),
   * we've found a new mesh entity that's part of a feature. We need to mark
   * the entity as visited at this point (and not before!) to avoid infinite
   * recursion. If you mark the node too early you risk not coloring in a whole
   * feature any time a "connecting threshold" is used since we may have
   * already visited this entity earlier but it was in-between two thresholds.
   */
  _entities_visited[current_index][entity_id] = true;

  auto map_num = _single_map_mode ? decltype(current_index)(0) : current_index;

  // New Feature (we need to create it and add it to our data structure)
  if (!feature)
  {
    _partial_feature_sets[map_num].emplace_back(current_index, _feature_count++, processor_id());

    // Get a handle to the feature we will update (always the last feature in the data structure)
    feature = &_partial_feature_sets[map_num].back();

    // If new_id is valid, we'll set it in the feature here.
    if (new_id != invalid_id)
      feature->_id = new_id;
  }

  // Insert the current entity into the local ids map
  feature->_local_ids.insert(entity_id);

  /**
   * See if this particular entity cell contributes to the centroid calculation. We
   * only deal with elemental floods and only count it if it's owned by the current
   * processor to avoid skewing the result.
   */
  if (_is_elemental && processor_id() == dof_object->processor_id())
  {
    const Elem * elem = static_cast<const Elem *>(dof_object);

    // Keep track of how many elements participate in the centroid averaging
    feature->_vol_count++;

    // Sum the centroid values for now, we'll average them later
    feature->_centroid += elem->centroid();

    // Does the volume intersect the boundary?
    if (_all_boundary_entity_ids.find(elem->id()) != _all_boundary_entity_ids.end())
      feature->_intersects_boundary = true;
  }

  if (_is_elemental)
    visitElementalNeighbors(static_cast<const Elem *>(dof_object), current_index, feature, /*expand_halos_only =*/false);
  else
    visitNodalNeighbors(static_cast<const Node *>(dof_object), current_index, feature, /*expand_halos_only =*/false);
}