Esempio n. 1
0
void
GrainTracker::swapSolutionValues(MooseSharedPointer<FeatureData> grain, unsigned int var_idx, std::map<Node *, CacheValues> & cache,
                                 REMAP_CACHE_MODE cache_mode, unsigned int depth)
{
  MeshBase & mesh = _mesh.getMesh();

  // Remap the grain
  std::set<Node *> updated_nodes_tmp; // Used only in the elemental case
  for (std::set<dof_id_type>::const_iterator entity_it = grain->_local_ids.begin();
       entity_it != grain->_local_ids.end(); ++entity_it)
  {
    if (_is_elemental)
    {
      Elem * elem = mesh.query_elem(*entity_it);
      if (!elem)
        continue;

      for (unsigned int i = 0; i < elem->n_nodes(); ++i)
      {
        Node * curr_node = elem->get_node(i);
        if (updated_nodes_tmp.find(curr_node) == updated_nodes_tmp.end())
        {
          updated_nodes_tmp.insert(curr_node);         // cache this node so we don't attempt to remap it again within this loop
          swapSolutionValuesHelper(curr_node, grain->_var_idx, var_idx, cache, cache_mode);
        }
      }
    }
    else
      swapSolutionValuesHelper(mesh.query_node_ptr(*entity_it), grain->_var_idx, var_idx, cache, cache_mode);
  }

  // Update the variable index in the unique grain datastructure
  grain->_var_idx = var_idx;

  // Close all of the solution vectors (we only need to do this once after all swaps are complete)
  if (depth == 0)
  {
    _nl.solution().close();
    _nl.solutionOld().close();
    _nl.solutionOlder().close();

    _fe_problem.getNonlinearSystem().sys().update();
  }
}
Esempio n. 2
0
void
GrainTracker::swapSolutionValues(std::map<unsigned int, UniqueGrain *>::iterator & grain_it1,
                                 std::map<unsigned int, UniqueGrain *>::iterator & grain_it2,
                                 unsigned int attempt_number)
{
  NumericVector<Real> & solution         =  _nl.solution();
  NumericVector<Real> & solution_old     =  _nl.solutionOld();
  NumericVector<Real> & solution_older   =  _nl.solutionOlder();

  unsigned int curr_var_idx = grain_it1->second->variable_idx;
  /**
   * 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.
   */
  std::vector<Real> min_distances(_vars.size(), std::numeric_limits<Real>::max());

  // Make sure that we don't attempt to remap to the same variable
  min_distances[curr_var_idx] = -std::numeric_limits<Real>::max();

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

    unsigned int potential_var_idx = grain_it3->second->variable_idx;

    Real curr_bounding_sphere_diff = boundingRegionDistance(grain_it1->second->sphere_ptrs, grain_it3->second->sphere_ptrs, false);
    if (curr_bounding_sphere_diff < min_distances[potential_var_idx])
      min_distances[potential_var_idx] = curr_bounding_sphere_diff;
  }

  /**
   * 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 unecessary since the
   * min_distance of a variable is explicitly set up above.
   */
  unsigned int nth_largest_idx = min_distances.size() - attempt_number - 1;

  // nth element destroys the original array so we need to copy it first
  std::vector<Real> min_distances_copy(min_distances);
  std::nth_element(min_distances_copy.begin(), min_distances_copy.end()+nth_largest_idx, min_distances_copy.end());

  // Now find the location of the nth element in the original vector
  unsigned int new_variable_idx = std::distance(min_distances.begin(),
                                                std::find(min_distances.begin(),
                                                          min_distances.end(),
                                                          min_distances_copy[nth_largest_idx]));

  Moose::out
    << COLOR_YELLOW
    << "Grain #: " << grain_it1->first << " intersects Grain #: " << grain_it2->first
    << " (variable index: " << grain_it1->second->variable_idx << ")\n"
    << COLOR_DEFAULT;

  if (min_distances[new_variable_idx] < 0)
  {
    Moose::out
      << COLOR_YELLOW
      << "*****************************************************************************************************\n"
      << "Warning: No suitable variable found for remapping. Will attempt to remap in next loop if necessary...\n"
      << "*****************************************************************************************************\n"
      << COLOR_DEFAULT;
    return;
  }

  Moose::out
    << COLOR_GREEN
    << "Remapping to: " << new_variable_idx << " whose closest grain is at a distance of " << min_distances[new_variable_idx] << "\n"
    << COLOR_DEFAULT;

  MeshBase & mesh = _mesh.getMesh();

  // Remap the grain
  std::set<Node *> updated_nodes_tmp; // Used only in the elemental case
  for (std::set<dof_id_type>::const_iterator entity_it = grain_it1->second->entities_ptr->begin();
       entity_it != grain_it1->second->entities_ptr->end(); ++entity_it)
  {
    if (_is_elemental)
    {
      Elem *elem = mesh.query_elem(*entity_it);
      if (!elem)
        continue;

      for (unsigned int i=0; i < elem->n_nodes(); ++i)
      {
        Node *curr_node = elem->get_node(i);
        if (updated_nodes_tmp.find(curr_node) == updated_nodes_tmp.end())
        {
          updated_nodes_tmp.insert(curr_node);         // cache this node so we don't attempt to remap it again within this loop
          swapSolutionValuesHelper(curr_node, curr_var_idx, new_variable_idx, solution, solution_old, solution_older);
        }
      }
    }
    else
      swapSolutionValuesHelper(mesh.query_node_ptr(*entity_it), curr_var_idx, new_variable_idx, solution, solution_old, solution_older);
  }

  // Update the variable index in the unique grain datastructure
  grain_it1->second->variable_idx = new_variable_idx;

  // Close all of the solution vectors
  solution.close();
  solution_old.close();
  solution_older.close();

  _fe_problem.getNonlinearSystem().sys().update();

}