Exemplo n.º 1
0
void
GrainTracker::remapGrains()
{
  // Don't remap grains if the current simulation step is before the specified tracking step
  if (_t_step < _tracking_step)
    return;

  /**
   * Loop over each grain and see if the bounding spheres of the current grain intersect with the spheres of any other grains
   * represented by the same variable.
   */
  unsigned times_through_loop = 0;
  bool variables_remapped;
  do
  {
    Moose::out << "Remap Loop: " << times_through_loop << std::endl;

    variables_remapped = false;
    for (std::map<unsigned int, UniqueGrain *>::iterator grain_it1 = _unique_grains.begin();
         grain_it1 != _unique_grains.end(); ++grain_it1)
    {
      if (grain_it1->second->status == INACTIVE)
        continue;

      for (std::map<unsigned int, UniqueGrain *>::iterator grain_it2 = _unique_grains.begin();
           grain_it2 != _unique_grains.end(); ++grain_it2)
      {
        // Don't compare a grain with itself and don't try to remap inactive grains
        if (grain_it1 == grain_it2 || grain_it2->second->status == INACTIVE)
          continue;

        if (grain_it1->second->variable_idx == grain_it2->second->variable_idx &&                  // Are the grains represented by the same variable?
            boundingRegionDistance(grain_it1->second->sphere_ptrs, grain_it2->second->sphere_ptrs, false) < 0)  // If so, do their spheres intersect?
        {
          // If so, remap one of them
          swapSolutionValues(grain_it1, grain_it2, times_through_loop);

          // Since something was remapped, we need to inspect all the grains again to make sure that previously ok grains
          // aren't in some new nearly intersecting state.  Setting this Boolean to true will trigger the loop again
          variables_remapped = true;

          // Since the current grain has just been remapped we don't want to loop over any more potential grains (the inner for loop)
          break;
        }
      }
    }

    if (++times_through_loop >= 5 && processor_id() == 0)
      mooseError(COLOR_RED << "Five passes through the remapping loop and grains are still being remapped, perhaps you need more op variables?" << COLOR_DEFAULT);

  } while (variables_remapped);
  Moose::out << "Done Remapping" << std::endl;
}
Exemplo n.º 2
0
bool
GrainTracker::attemptGrainRenumber(MooseSharedPointer<FeatureData> grain, unsigned int grain_id, unsigned int depth, unsigned int max)
{
  // End the recursion of our breadth first search
  if (depth > max)
    return false;

  unsigned int curr_var_idx = grain->_var_idx;

  std::map<Node *, CacheValues> cache;

  std::vector<std::list<GrainDistance> > min_distances(_vars.size());

  /**
   * We have two grains that are getting close represented by the same order parameter.
   * We need to map to the variable whose closest grain to this one is furthest away by sphere to sphere distance.
   */
  computeMinDistancesFromGrain(grain, min_distances);

  /**
   * We have a vector of the distances to the closest grains represented by each of our variables.  We just need to pick
   * a suitable grain to replace with.  We will start with the maximum of this this list: (max of the mins), but will settle
   * for next to largest and so forth as we make more attempts at remapping grains.  This is a graph coloring problem so
   * more work will be required to optimize this process.
   *
   * Note: We don't have an explicit check here to avoid remapping a  variable to itself.  This is unnecessary since the
   * min_distance of a variable is explicitly set up above.
   */

  std::sort(min_distances.begin(), min_distances.end(), GrainDistanceSorter());

  _console << "\n********************************************\nDistances list for grain " << grain_id << '\n';
  for (unsigned int i = 0; i < min_distances.size(); ++i)
  {
    for (std::list<GrainDistance>::iterator min_it = min_distances[i].begin(); min_it != min_distances[i].end(); ++min_it)
      _console << min_it->_distance << ": " << min_it->_grain_id << ": " <<  min_it->_var_index << '\n';
    _console << '\n';
  }

  for (unsigned int i = 0; i < min_distances.size(); ++i)
  {
    std::list<GrainDistance>::const_iterator target_it = min_distances[i].begin();
    if (target_it == min_distances[i].end())
      continue;

    // If the distance is positive we can just remap and be done
    if (target_it->_distance > 0)
    {
      Moose::out
        << COLOR_GREEN
        << "- Depth " << depth << ": Remapping grain #" << grain_id << " from variable index " << curr_var_idx
        << " to " << target_it->_var_index << " whose closest grain (#" << target_it->_grain_id
        << ") is at a distance of " << target_it->_distance << "\n"
        << COLOR_DEFAULT;

      swapSolutionValues(grain, target_it->_var_index, cache, BYPASS, depth);
      return true;
    }

    // If the distance isn't positive we just need to make sure that none of the grains represented by the
    // target variable index would intersect this one if we were to remap
    std::list<GrainDistance>::const_iterator next_target_it = target_it;
    bool intersection_hit = false;
    std::ostringstream oss;
    while (!intersection_hit && next_target_it != min_distances[i].end())
    {
      if (next_target_it->_distance > 0)
        break;

      mooseAssert(_unique_grains.find(next_target_it->_grain_id) != _unique_grains.end(), "Error in indexing target grain in attemptGrainRenumber");
      MooseSharedPointer<FeatureData> next_target_grain = _unique_grains[next_target_it->_grain_id];

      // If any grains touch we're done here
      if (setsIntersect(grain->_halo_ids.begin(), grain->_halo_ids.end(),
                        next_target_grain->_halo_ids.begin(), next_target_grain->_halo_ids.end()))
        intersection_hit = true;
      else
        oss << " #" << next_target_it->_grain_id;

      ++next_target_it;
    }

    if (!intersection_hit)
    {
      Moose::out
        << COLOR_GREEN
        << "- Depth " << depth << ": Remapping grain #" << grain_id << " from variable index " << curr_var_idx
        << " to " << target_it->_var_index << " whose closest grain(s):" << oss.str()
        << " are inside our bounding sphere but whose halo(s) are not touching.\n"
        << COLOR_DEFAULT;

      swapSolutionValues(grain, target_it->_var_index, cache, BYPASS, depth);
      return true;
    }

    // If we reach this part of the loop, there is no simple renumbering that can be done.
    mooseAssert(_unique_grains.find(target_it->_grain_id) != _unique_grains.end(), "Error in indexing target grain in attemptGrainRenumber");
    MooseSharedPointer<FeatureData> target_grain = _unique_grains[target_it->_grain_id];

    // Make sure this grain isn't marked. If it is, we can't recurse here
    if (target_grain->_merged)
      return false;

    // Save the solution values in case we overright them during recursion
    swapSolutionValues(grain, target_it->_var_index, cache, FILL, depth);

    // TODO: Make sure this distance is -1 or higher or fine intersections only exist for a single variable
    // Propose a new variable index for the current grain and recurse
    grain->_var_idx = target_it->_var_index;
    grain->_merged = true;
    if (attemptGrainRenumber(target_grain, target_it->_grain_id, depth+1, max))
    {
      // SUCCESS!
      Moose::out
        << COLOR_GREEN
        << "- Depth " << depth << ": Remapping grain #" << grain_id << " from variable index " << curr_var_idx
        << " to " << target_it->_var_index << '\n'
        << COLOR_DEFAULT;

      // NOTE: swapSolutionValues currently reads the current variable index off the grain. We need to set
      //       back here before calling this method.
      grain->_var_idx = curr_var_idx;
      swapSolutionValues(grain, target_it->_var_index, cache, USE, depth);

      return true;
    }
    else
      // Need to set our var index back after failed recursive step
      grain->_var_idx = curr_var_idx;

    // Always "unmark" the grain after the recursion so it can be used by other remap operations
    grain->_merged = false;
  }

  return false;
}