Beispiel #1
0
void
GrainTracker::calculateBubbleVolumes()
{
  Moose::perf_log.push("calculateBubbleVolumes()", "GrainTracker");

  // The size of the bubble array will be sized to the max index of the unique grains map
  unsigned int max_id = _unique_grains.size() ? _unique_grains.rbegin()->first + 1: 0;
  _all_feature_volumes.resize(max_id, 0);

  const MeshBase::const_element_iterator el_end = _mesh.getMesh().active_local_elements_end();
  for (MeshBase::const_element_iterator el = _mesh.getMesh().active_local_elements_begin(); el != el_end; ++el)
  {
    Elem * elem = *el;
    unsigned int elem_n_nodes = elem->n_nodes();
    Real curr_volume = elem->volume();

    for (std::map<unsigned int, MooseSharedPointer<FeatureData> >::iterator it = _unique_grains.begin(); it != _unique_grains.end(); ++it)
    {
      if (it->second->_status == INACTIVE)
        continue;

      if (_is_elemental)
      {
        dof_id_type elem_id = elem->id();
        if (it->second->_local_ids.find(elem_id) != it->second->_local_ids.end())
        {
          mooseAssert(it->first < _all_feature_volumes.size(), "_all_feature_volumes access out of bounds");
          _all_feature_volumes[it->first] += curr_volume;
          break;
        }
      }
      else
      {
        // Count the number of nodes on this element which are flooded.
        unsigned int flooded_nodes = 0;
        for (unsigned int node = 0; node < elem_n_nodes; ++node)
        {
          dof_id_type node_id = elem->node(node);
          if (it->second->_local_ids.find(node_id) != it->second->_local_ids.end())
            ++flooded_nodes;
        }

        // If a majority of the nodes for this element are flooded,
        // assign its volume to the current bubble_counter entry.
        if (flooded_nodes >= elem_n_nodes / 2)
          _all_feature_volumes[it->first] += curr_volume;
      }
    }
  }

  // do all the sums!
  _communicator.sum(_all_feature_volumes);

  Moose::perf_log.pop("calculateBubbleVolumes()", "GrainTracker");
}
Beispiel #2
0
void
NodalFloodCount::calculateBubbleVolumes()
{
  Moose::perf_log.push("calculateBubbleVolume()", "NodalFloodCount");

  // Size our temporary data structure
  std::vector<std::vector<Real> > bubble_volumes(_maps_size);
  for (unsigned int map_num = 0; map_num < _maps_size; ++map_num)
  {
    bubble_volumes[map_num].resize(_bubble_sets[map_num].size());
  }

  std::vector<unsigned int> flood_nodes(_maps_size);
  const MeshBase::const_element_iterator el_end = _mesh.getMesh().active_local_elements_end();
  for (MeshBase::const_element_iterator el = _mesh.getMesh().active_local_elements_begin(); el != el_end; ++el)
  {
    Elem *elem = *el;
    unsigned int elem_n_nodes = elem->n_nodes();
    Real curr_volume = elem->volume();

    for (unsigned int map_num = 0; map_num < _maps_size; ++map_num)
    {
      unsigned int bubble_counter = 0;
      std::list<BubbleData>::const_iterator end = _bubble_sets[map_num].end();
      for (std::list<BubbleData>::const_iterator bubble_it1 = _bubble_sets[map_num].begin(); bubble_it1 != end; ++bubble_it1)
      {
        unsigned int flooded_nodes = 0;
        for (unsigned int node = 0; node < elem_n_nodes; ++node)
        {
          unsigned int node_id = elem->node(node);
          if (bubble_it1->_nodes.find(node_id) != bubble_it1->_nodes.end())
            ++flooded_nodes;
        }

        // Are a majority of the nodes flooded for this element?
        if (flooded_nodes >= elem_n_nodes / 2)
          bubble_volumes[map_num][bubble_counter] += curr_volume;

        ++bubble_counter;
      }
    }
  }

  // Stick all the partial bubble volumes in one long single vector to be gathered on the root processor
  for (unsigned int map_num = 0; map_num < _maps_size; ++map_num)
    _all_bubble_volumes.insert(_all_bubble_volumes.end(), bubble_volumes[map_num].begin(), bubble_volumes[map_num].end());

  _communicator.sum(_all_bubble_volumes); //do all the sums!

  std::sort(_all_bubble_volumes.begin(), _all_bubble_volumes.end(), std::greater<Real>());

  Moose::perf_log.pop("calculateBubbleVolume()", "NodalFloodCount");
}
Beispiel #3
0
void ElemCutter::cut_3D (const Elem & elem,
                         const std::vector<Real> & vertex_distance_func)
{
#ifndef LIBMESH_HAVE_TETGEN

  // current implementation requires tetgen!
  libMesh::err << "ERROR: current libMesh ElemCutter 3D implementation requires\n"
               << "       the \"tetgen\" library!\n"
               << std::endl;
  libmesh_not_implemented();

#else // OK, LIBMESH_HAVE_TETGEN

  std::cout << "Inside cut cell element!\n";

  libmesh_assert (_inside_mesh_3D.get()  != nullptr);
  libmesh_assert (_outside_mesh_3D.get() != nullptr);

  _inside_mesh_3D->clear();
  _outside_mesh_3D->clear();

  for (unsigned int v=0; v<elem.n_vertices(); v++)
    {
      if (vertex_distance_func[v] >= 0.)
        _outside_mesh_3D->add_point (elem.point(v));

      if (vertex_distance_func[v] <= 0.)
        _inside_mesh_3D->add_point (elem.point(v));
    }

  for (const auto & pt : _intersection_pts)
    {
      _inside_mesh_3D->add_point(pt);
      _outside_mesh_3D->add_point(pt);
    }


  // Triangulate!
  _tetgen_inside->triangulate_pointset();
  //_inside_mesh_3D->print_info();
  _tetgen_outside->triangulate_pointset();
  //_outside_mesh_3D->print_info();


  // (below generates some horribly expensive meshes,
  //  but seems immune to the 0 volume problem).
  // _tetgen_inside->pointset_convexhull();
  // _inside_mesh_3D->find_neighbors();
  // _inside_mesh_3D->print_info();
  // _tetgen_inside->triangulate_conformingDelaunayMesh (1.e3, 100.);
  // _inside_mesh_3D->print_info();

  // _tetgen_outside->pointset_convexhull();
  // _outside_mesh_3D->find_neighbors();
  // _outside_mesh_3D->print_info();
  // _tetgen_outside->triangulate_conformingDelaunayMesh (1.e3, 100.);
  // _outside_mesh_3D->print_info();

  std::ostringstream name;

  name << "cut_cell_"
       << cut_cntr++
       << ".dat";
  _inside_mesh_3D->write  ("in_"  + name.str());
  _outside_mesh_3D->write ("out_" + name.str());

  // finally, add the elements to our lists.
  _inside_elem.clear();
  _outside_elem.clear();

  for (const auto & elem : _inside_mesh_3D->element_ptr_range())
    if (elem->volume() > std::numeric_limits<Real>::epsilon())
      _inside_elem.push_back (elem);

  for (const auto & elem : _outside_mesh_3D->element_ptr_range())
    if (elem->volume() > std::numeric_limits<Real>::epsilon())
      _outside_elem.push_back (elem);

#endif
}
void
FeatureFloodCount::calculateBubbleVolumes()
{
  Moose::perf_log.push("calculateBubbleVolume()", "FeatureFloodCount");

  // Figure out which bubbles intersect the boundary if the user has enabled that capability.
  if (_compute_boundary_intersecting_volume)
  {
    // Create a std::set of node IDs which are on the boundary called all_boundary_node_ids.
    std::set<dof_id_type> all_boundary_node_ids;

    // Iterate over the boundary nodes, putting them into the std::set data structure
    MooseMesh::bnd_node_iterator
      boundary_nodes_it  = _mesh.bndNodesBegin(),
      boundary_nodes_end = _mesh.bndNodesEnd();
    for (; boundary_nodes_it != boundary_nodes_end; ++boundary_nodes_it)
    {
      BndNode * boundary_node = *boundary_nodes_it;
      all_boundary_node_ids.insert(boundary_node->_node->id());
    }

    // For each of the _maps_size BubbleData lists, determine if the set
    // of nodes includes any boundary nodes.
    for (unsigned int map_num = 0; map_num < _maps_size; ++map_num)
    {
      std::list<BubbleData>::iterator
        bubble_it = _bubble_sets[map_num].begin(),
        bubble_end = _bubble_sets[map_num].end();

      // Determine boundary intersection for each BubbleData object
      for (; bubble_it != bubble_end; ++bubble_it)
        bubble_it->_intersects_boundary = setsIntersect(all_boundary_node_ids.begin(), all_boundary_node_ids.end(),
                                                        bubble_it->_entity_ids.begin(), bubble_it->_entity_ids.end());
    }
  }

  // Size our temporary data structure
  std::vector<std::vector<Real> > bubble_volumes(_maps_size);
  for (unsigned int map_num = 0; map_num < _maps_size; ++map_num)
    bubble_volumes[map_num].resize(_bubble_sets[map_num].size());

  // Clear pre-existing values and allocate space to store the volume
  // of the boundary-intersecting grains for each variable.
  _total_volume_intersecting_boundary.clear();
  _total_volume_intersecting_boundary.resize(_maps_size);

  // Loop over the active local elements.  For each variable, and for
  // each BubbleData object, check whether a majority of the element's
  // nodes belong to that Bubble, and if so assign the element's full
  // volume to that bubble.
  const MeshBase::const_element_iterator el_end = _mesh.getMesh().active_local_elements_end();
  for (MeshBase::const_element_iterator el = _mesh.getMesh().active_local_elements_begin(); el != el_end; ++el)
  {
    Elem * elem = *el;
    unsigned int elem_n_nodes = elem->n_nodes();
    Real curr_volume = elem->volume();

    for (unsigned int map_num = 0; map_num < _maps_size; ++map_num)
    {
      std::list<BubbleData>::const_iterator
        bubble_it = _bubble_sets[map_num].begin(),
        bubble_end = _bubble_sets[map_num].end();

      for (unsigned int bubble_counter = 0; bubble_it != bubble_end; ++bubble_it, ++bubble_counter)
      {
        // Count the number of nodes on this element which are flooded.
        unsigned int flooded_nodes = 0;
        for (unsigned int node = 0; node < elem_n_nodes; ++node)
        {
          dof_id_type node_id = elem->node(node);
          if (bubble_it->_entity_ids.find(node_id) != bubble_it->_entity_ids.end())
            ++flooded_nodes;
        }

        // If a majority of the nodes for this element are flooded,
        // assign its volume to the current bubble_counter entry.
        if (flooded_nodes >= elem_n_nodes / 2)
        {
          bubble_volumes[map_num][bubble_counter] += curr_volume;

          // If the current bubble also intersects the boundary, also
          // accumlate the volume into the total volume of bubbles
          // which intersect the boundary.
          if (bubble_it->_intersects_boundary)
            _total_volume_intersecting_boundary[map_num] += curr_volume;
        }
      }
    }
  }

  // If we're calculating boundary-intersecting volumes, we have to normalize it by the
  // volume of the entire domain.
  if (_compute_boundary_intersecting_volume)
  {
    // Compute the total area using a bounding box.  FIXME: this
    // assumes the domain is rectangular and 2D, and is probably a
    // little expensive so we should only do it once if possible.
    MeshTools::BoundingBox bbox = MeshTools::bounding_box(_mesh);
    Real total_volume = (bbox.max()(0)-bbox.min()(0))*(bbox.max()(1)-bbox.min()(1));

    // Sum up the partial boundary grain volume contributions from all processors
    _communicator.sum(_total_volume_intersecting_boundary);

    // Scale the boundary intersecting grain volumes by the total domain volume
    for (unsigned int i = 0; i<_total_volume_intersecting_boundary.size(); ++i)
      _total_volume_intersecting_boundary[i] /= total_volume;
  }

  // Stick all the partial bubble volumes in one long single vector to be gathered on the root processor
  for (unsigned int map_num = 0; map_num < _maps_size; ++map_num)
    _all_bubble_volumes.insert(_all_bubble_volumes.end(), bubble_volumes[map_num].begin(), bubble_volumes[map_num].end());

  // do all the sums!
  _communicator.sum(_all_bubble_volumes);

  std::sort(_all_bubble_volumes.begin(), _all_bubble_volumes.end(), std::greater<Real>());

  Moose::perf_log.pop("calculateBubbleVolume()", "FeatureFloodCount");
}