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"); }
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"); }
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"); }