diff --git a/src/mesh/element_group.cc b/src/mesh/element_group.cc index 2821bd88d..a53abbdb1 100644 --- a/src/mesh/element_group.cc +++ b/src/mesh/element_group.cc @@ -1,167 +1,201 @@ /** * @file element_group.cc * * @author Dana Christen * @author Nicolas Richart * * @date creation: Fri May 03 2013 * @date last modification: Fri Sep 05 2014 * * @brief Stores information relevent to the notion of domain boundary and surfaces. * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include #include "mesh.hh" #include "group_manager.hh" #include "group_manager_inline_impl.cc" #include "dumpable.hh" #include "dumpable_inline_impl.hh" #include "aka_csr.hh" #include "mesh_utils.hh" #include "element_group.hh" #if defined(AKANTU_USE_IOHELPER) # include "dumper_paraview.hh" #endif __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ ElementGroup::ElementGroup(const std::string & group_name, const Mesh & mesh, NodeGroup & node_group, UInt dimension, const std::string & id, const MemoryID & mem_id) : Memory(id, mem_id), mesh(mesh), name(group_name), elements("elements", id, mem_id), node_group(node_group), dimension(dimension) { AKANTU_DEBUG_IN(); #if defined(AKANTU_USE_IOHELPER) this->registerDumper("paraview_" + group_name, group_name, true); this->addDumpFilteredMesh(mesh, elements, node_group.getNodes(), dimension); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ElementGroup::empty() { elements.free(); } /* -------------------------------------------------------------------------- */ void ElementGroup::append(const ElementGroup & other_group) { AKANTU_DEBUG_IN(); node_group.append(other_group.node_group); /// loop on all element types in all dimensions for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; type_iterator it = other_group.firstType(_all_dimensions, ghost_type, _ek_not_defined); type_iterator last = other_group.lastType(_all_dimensions, ghost_type, _ek_not_defined); for (; it != last; ++it) { ElementType type = *it; const Array & other_elem_list = other_group.elements(type, ghost_type); UInt nb_other_elem = other_elem_list.getSize(); Array * elem_list; UInt nb_elem = 0; /// create current type if doesn't exists, otherwise get information if (elements.exists(type, ghost_type)) { elem_list = &elements(type, ghost_type); nb_elem = elem_list->getSize(); } else { elem_list = &(elements.alloc(0, 1, type, ghost_type)); } /// append new elements to current list elem_list->resize(nb_elem + nb_other_elem); std::copy(other_elem_list.begin(), other_elem_list.end(), elem_list->begin() + nb_elem); /// remove duplicates std::sort(elem_list->begin(), elem_list->end()); Array::iterator<> end = std::unique(elem_list->begin(), elem_list->end()); elem_list->resize(end - elem_list->begin()); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ElementGroup::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "ElementGroup [" << std::endl; stream << space << " + name: " << name << std::endl; stream << space << " + dimension: " << dimension << std::endl; elements.printself(stream, indent + 1); node_group.printself(stream, indent + 1); stream << "]" << std::endl; } /* -------------------------------------------------------------------------- */ void ElementGroup::optimize() { // increasing the locality of data when iterating on the element of a group for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; ElementList::type_iterator it = elements.firstType(_all_dimensions, ghost_type); ElementList::type_iterator last = elements.lastType(_all_dimensions, ghost_type); for (; it != last; ++it) { Array & els = elements(*it, ghost_type); std::sort(els.begin(), els.end()); Array::iterator<> end = std::unique(els.begin(), els.end()); els.resize(end - els.begin()); } } node_group.optimize(); } /* -------------------------------------------------------------------------- */ +void ElementGroup::fillFromNodeGroup() { + CSR node_to_elem; + MeshUtils::buildNode2Elements(this->mesh, node_to_elem, this->dimension); + + std::set seen; + + Array::const_iterator<> itn = this->node_group.begin(); + Array::const_iterator<> endn = this->node_group.end(); + for (;itn != endn; ++itn) { + CSR::iterator ite = node_to_elem.begin(*itn); + CSR::iterator ende = node_to_elem.end(*itn); + for (;ite != ende; ++ite) { + const Element & elem = *ite; + if(this->dimension != _all_dimensions && this->dimension != Mesh::getSpatialDimension(elem.type)) continue; + if(seen.find(elem) != seen.end()) continue; + + UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(elem.type); + Array::const_iterator< Vector > conn_it = + this->mesh.getConnectivity(elem.type, elem.ghost_type).begin(nb_nodes_per_element); + const Vector & conn = conn_it[elem.element]; + + UInt count = 0; + for (UInt n = 0; n < conn.size(); ++n) { + count += (this->node_group.getNodes().find(conn(n)) != -1 ? 1 : 0); + } + + if(count == nb_nodes_per_element) this->add(elem); + seen.insert(elem); + } + } + this->optimize(); +} + +/* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/mesh/element_group.hh b/src/mesh/element_group.hh index 2ac622b6f..38ec48f84 100644 --- a/src/mesh/element_group.hh +++ b/src/mesh/element_group.hh @@ -1,175 +1,179 @@ /** * @file element_group.hh * * @author Dana Christen * @author Nicolas Richart * * @date creation: Fri May 03 2013 * @date last modification: Fri Sep 05 2014 * * @brief Stores information relevent to the notion of domain boundary and surfaces. * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_GROUP_HH__ #define __AKANTU_ELEMENT_GROUP_HH__ #include #include "aka_common.hh" #include "aka_memory.hh" #include "element_type_map.hh" #include "node_group.hh" #include "dumpable.hh" __BEGIN_AKANTU__ class Mesh; class Element; /* -------------------------------------------------------------------------- */ class ElementGroup : private Memory, public Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ElementGroup(const std::string & name, const Mesh & mesh, NodeGroup & node_group, UInt dimension = _all_dimensions, const std::string & id = "element_group", const MemoryID & memory_id = 0); /* ------------------------------------------------------------------------ */ /* Type definitions */ /* ------------------------------------------------------------------------ */ public: typedef ElementTypeMapArray ElementList; typedef Array NodeList; /* ------------------------------------------------------------------------ */ /* Node iterator */ /* ------------------------------------------------------------------------ */ typedef NodeGroup::const_node_iterator const_node_iterator; inline const_node_iterator node_begin() const; inline const_node_iterator node_end() const; /* ------------------------------------------------------------------------ */ /* Element iterator */ /* ------------------------------------------------------------------------ */ typedef ElementList::type_iterator type_iterator; inline type_iterator firstType(UInt dim = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & kind = _ek_regular) const; inline type_iterator lastType(UInt dim = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & kind = _ek_regular) const; typedef Array::const_iterator const_element_iterator; inline const_element_iterator element_begin(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; inline const_element_iterator element_end(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// empty the element group void empty(); /// append another group to this group /// BE CAREFUL: it doesn't conserve the element order void append(const ElementGroup & other_group); /// add an element to the group. By default the it does not add the nodes to the group inline void add(const Element & el, bool add_nodes = false, bool check_for_duplicate = true); /// \todo fix the default for add_nodes : make it coherent with the other method - inline void add(const ElementType & type, UInt element, + inline void add(const ElementType & type, UInt element, const GhostType & ghost_type = _not_ghost, bool add_nodes = true, bool check_for_duplicate = true); inline void addNode(UInt node_id, bool check_for_duplicate = true); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; + + /// fill the elements based on the underlying node group. + virtual void fillFromNodeGroup(); + // sort and remove duplicated values void optimize(); private: inline void addElement(const ElementType & elem_type, UInt elem_id, const GhostType & ghost_type); friend class GroupManager; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Elements, elements, UInt); AKANTU_GET_MACRO(Elements, elements, const ElementTypeMapArray &); AKANTU_GET_MACRO(Nodes, node_group.getNodes(), const Array &); AKANTU_GET_MACRO(NodeGroup, node_group, const NodeGroup &); AKANTU_GET_MACRO_NOT_CONST(NodeGroup, node_group, NodeGroup &); AKANTU_GET_MACRO(Dimension, dimension, UInt); AKANTU_GET_MACRO(Name, name, std::string); inline UInt getNbNodes() const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// Mesh to which this group belongs const Mesh & mesh; /// name of the group std::string name; /// list of elements composing the group ElementList elements; /// sub list of nodes which are composing the elements NodeGroup & node_group; /// group dimension UInt dimension; /// empty arry for the iterator to work when an element type not present Array empty_elements; }; /// standard output stream operator inline std::ostream & operator << (std::ostream & stream, const ElementGroup &_this) { _this.printself(stream); return stream; } __END_AKANTU__ #include "element.hh" #include "element_group_inline_impl.cc" #endif /* __AKANTU_ELEMENT_GROUP_HH__ */ diff --git a/src/mesh/group_manager.cc b/src/mesh/group_manager.cc index 1b3bd0114..de3f46df1 100644 --- a/src/mesh/group_manager.cc +++ b/src/mesh/group_manager.cc @@ -1,1032 +1,1001 @@ /** * @file group_manager.cc * * @author Dana Christen * @author Marco Vocialta * @author Nicolas Richart * @author David Simon Kammer * * @date creation: Fri May 03 2013 * @date last modification: Tue Sep 02 2014 * * @brief Stores information about ElementGroup and NodeGroup * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "group_manager.hh" #include "mesh.hh" #include "aka_csr.hh" #include "mesh_utils.hh" #include "element_group.hh" #include "node_group.hh" #include "data_accessor.hh" #include "distributed_synchronizer.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ GroupManager::GroupManager(const Mesh & mesh, const ID & id, const MemoryID & mem_id) : id(id), memory_id(mem_id), mesh(mesh) { AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ GroupManager::~GroupManager() { ElementGroups::iterator eit = element_groups.begin(); ElementGroups::iterator eend = element_groups.end(); for(; eit != eend ; ++eit) delete (eit->second); NodeGroups::iterator nit = node_groups.begin(); NodeGroups::iterator nend = node_groups.end(); for(; nit != nend ; ++nit) delete (nit->second); } /* -------------------------------------------------------------------------- */ NodeGroup & GroupManager::createNodeGroup(const std::string & group_name, bool replace_group) { AKANTU_DEBUG_IN(); NodeGroups::iterator it = node_groups.find(group_name); if(it != node_groups.end()) { if (replace_group) { it->second->empty(); AKANTU_DEBUG_OUT(); return *(it->second); } else AKANTU_EXCEPTION("Trying to create a node group that already exists:" << group_name << "_nodes"); } NodeGroup * node_group = new NodeGroup(group_name, id + ":" + group_name + "_node_group", memory_id); node_groups[group_name] = node_group; AKANTU_DEBUG_OUT(); return *node_group; } /* -------------------------------------------------------------------------- */ template NodeGroup & GroupManager::createFilteredNodeGroup(const std::string & group_name, const NodeGroup & source_node_group, T & filter) { AKANTU_DEBUG_IN(); NodeGroup & node_group = this->createNodeGroup(group_name); node_group.append(source_node_group); if (T::type == FilterFunctor::_node_filter_functor) { node_group.applyNodeFilter(filter); } else { AKANTU_DEBUG_ERROR("ElementFilter cannot be applied to NodeGroup yet." << " Needs to be implemented."); } AKANTU_DEBUG_OUT(); return node_group; } /* -------------------------------------------------------------------------- */ void GroupManager::destroyNodeGroup(const std::string & group_name) { AKANTU_DEBUG_IN(); NodeGroups::iterator nit = node_groups.find(group_name); NodeGroups::iterator nend = node_groups.end(); if (nit != nend) { delete (nit->second); node_groups.erase(nit); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::createElementGroup(const std::string & group_name, UInt dimension, bool replace_group) { AKANTU_DEBUG_IN(); NodeGroup & new_node_group = createNodeGroup(group_name + "_nodes", replace_group); ElementGroups::iterator it = element_groups.find(group_name); if(it != element_groups.end()) { if (replace_group) { it->second->empty(); AKANTU_DEBUG_OUT(); return *(it->second); } else AKANTU_EXCEPTION("Trying to create a element group that already exists:" << group_name); } ElementGroup * element_group = new ElementGroup(group_name, mesh, new_node_group, dimension, id + ":" + group_name + "_element_group", memory_id); node_groups[group_name + "_nodes"] = &new_node_group; element_groups[group_name] = element_group; AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ void GroupManager::destroyElementGroup(const std::string & group_name, bool destroy_node_group) { AKANTU_DEBUG_IN(); ElementGroups::iterator eit = element_groups.find(group_name); ElementGroups::iterator eend = element_groups.end(); if (eit != eend) { if (destroy_node_group) destroyNodeGroup(eit->second->getNodeGroup().getName()); delete (eit->second); element_groups.erase(eit); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::destroyAllElementGroups(bool destroy_node_groups) { AKANTU_DEBUG_IN(); ElementGroups::iterator eit = element_groups.begin(); ElementGroups::iterator eend = element_groups.end(); for(; eit != eend ; ++eit) { if (destroy_node_groups) destroyNodeGroup(eit->second->getNodeGroup().getName()); delete (eit->second); } element_groups.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::createElementGroup(const std::string & group_name, UInt dimension, NodeGroup & node_group) { AKANTU_DEBUG_IN(); if(element_groups.find(group_name) != element_groups.end()) AKANTU_EXCEPTION("Trying to create a element group that already exists:" << group_name); ElementGroup * element_group = new ElementGroup(group_name, mesh, node_group, dimension, id + ":" + group_name + "_element_group", memory_id); element_groups[group_name] = element_group; AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ template ElementGroup & GroupManager::createFilteredElementGroup(const std::string & group_name, UInt dimension, const NodeGroup & node_group, T & filter) { AKANTU_DEBUG_IN(); ElementGroup * element_group = NULL; if (T::type == FilterFunctor::_node_filter_functor) { NodeGroup & filtered_node_group = this->createFilteredNodeGroup(group_name + "_nodes", node_group, filter); element_group = &(this->createElementGroup(group_name, dimension, filtered_node_group)); } else if (T::type == FilterFunctor::_element_filter_functor) { AKANTU_DEBUG_ERROR("Cannot handle an ElementFilter yet. Needs to be implemented."); } AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ class ClusterSynchronizer : public DataAccessor { typedef std::set< std::pair > DistantIDs; public: ClusterSynchronizer(GroupManager & group_manager, UInt element_dimension, std::string cluster_name_prefix, ElementTypeMapArray & element_to_fragment, DistributedSynchronizer & distributed_synchronizer, UInt nb_cluster) : group_manager(group_manager), element_dimension(element_dimension), cluster_name_prefix(cluster_name_prefix), element_to_fragment(element_to_fragment), distributed_synchronizer(distributed_synchronizer), nb_cluster(nb_cluster) { } UInt synchronize() { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt rank = comm.whoAmI(); UInt nb_proc = comm.getNbProc(); /// find starting index to renumber local clusters Array nb_cluster_per_proc(nb_proc); nb_cluster_per_proc(rank) = nb_cluster; comm.allGather(nb_cluster_per_proc.storage(), 1); starting_index = std::accumulate(nb_cluster_per_proc.begin(), nb_cluster_per_proc.begin() + rank, 0); UInt global_nb_fragment = std::accumulate(nb_cluster_per_proc.begin() + rank, nb_cluster_per_proc.end(), starting_index); /// create the local to distant cluster pairs with neighbors distributed_synchronizer.computeBufferSize(*this, _gst_gm_clusters); distributed_synchronizer.asynchronousSynchronize(*this, _gst_gm_clusters); distributed_synchronizer.waitEndSynchronize(*this, _gst_gm_clusters); /// count total number of pairs Array nb_pairs(nb_proc); nb_pairs(rank) = distant_ids.size(); comm.allGather(nb_pairs.storage(), 1); UInt total_nb_pairs = std::accumulate(nb_pairs.begin(), nb_pairs.end(), 0); /// generate pairs global array UInt local_pair_index = std::accumulate(nb_pairs.storage(), nb_pairs.storage() + rank, 0); Array total_pairs(total_nb_pairs, 2); DistantIDs::iterator ids_it = distant_ids.begin(); DistantIDs::iterator ids_end = distant_ids.end(); for (; ids_it != ids_end; ++ids_it, ++local_pair_index) { total_pairs(local_pair_index, 0) = ids_it->first; total_pairs(local_pair_index, 1) = ids_it->second; } /// communicate pairs to all processors nb_pairs *= 2; comm.allGatherV(total_pairs.storage(), nb_pairs.storage()); /// renumber clusters /// generate fragment list std::vector< std::set > global_clusters; UInt total_nb_cluster = 0; Array is_fragment_in_cluster(global_nb_fragment, 1, false); std::queue fragment_check_list; while (total_pairs.getSize() != 0) { /// create a new cluster ++total_nb_cluster; global_clusters.resize(total_nb_cluster); std::set & current_cluster = global_clusters[total_nb_cluster - 1]; UInt first_fragment = total_pairs(0, 0); UInt second_fragment = total_pairs(0, 1); total_pairs.erase(0); fragment_check_list.push(first_fragment); fragment_check_list.push(second_fragment); while (!fragment_check_list.empty()) { UInt current_fragment = fragment_check_list.front(); UInt * total_pairs_end = total_pairs.storage() + total_pairs.getSize() * 2; UInt * fragment_found = std::find(total_pairs.storage(), total_pairs_end, current_fragment); if (fragment_found != total_pairs_end) { UInt position = fragment_found - total_pairs.storage(); UInt pair = position / 2; UInt other_index = (position + 1) % 2; fragment_check_list.push(total_pairs(pair, other_index)); total_pairs.erase(pair); } else { fragment_check_list.pop(); current_cluster.insert(current_fragment); is_fragment_in_cluster(current_fragment) = true; } } } /// add to FragmentToCluster all local fragments for (UInt c = 0; c < global_nb_fragment; ++c) { if (!is_fragment_in_cluster(c)) { ++total_nb_cluster; global_clusters.resize(total_nb_cluster); std::set & current_cluster = global_clusters[total_nb_cluster - 1]; current_cluster.insert(c); } } /// reorganize element groups to match global clusters for (UInt c = 0; c < global_clusters.size(); ++c) { /// create new element group corresponding to current cluster std::stringstream sstr; sstr << cluster_name_prefix << "_" << c; ElementGroup & cluster = group_manager.createElementGroup(sstr.str(), element_dimension, true); std::set::iterator it = global_clusters[c].begin(); std::set::iterator end = global_clusters[c].end(); /// append to current element group all fragments that belong to /// the same cluster if they exist for (; it != end; ++it) { Int local_index = *it - starting_index; if (local_index < 0 || local_index >= Int(nb_cluster)) continue; std::stringstream tmp_sstr; tmp_sstr << "tmp_" << cluster_name_prefix << "_" << local_index; GroupManager::element_group_iterator eg_it = group_manager.element_group_find(tmp_sstr.str()); AKANTU_DEBUG_ASSERT(eg_it != group_manager.element_group_end(), "Temporary fragment \""<< tmp_sstr.str() << "\" not found"); cluster.append(*(eg_it->second)); group_manager.destroyElementGroup(tmp_sstr.str(), true); } } return total_nb_cluster; } private: /// functions for parallel communications inline UInt getNbDataForElements(const Array & elements, SynchronizationTag tag) const { if (tag == _gst_gm_clusters) return elements.getSize() * sizeof(UInt); return 0; } inline void packElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) const { if (tag != _gst_gm_clusters) return; Array::const_iterator<> el_it = elements.begin(); Array::const_iterator<> el_end = elements.end(); for (; el_it != el_end; ++el_it) { const Element & el = *el_it; /// for each element pack its global cluster index buffer << element_to_fragment(el.type, el.ghost_type)(el.element) + starting_index; } } inline void unpackElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) { if (tag != _gst_gm_clusters) return; Array::const_iterator<> el_it = elements.begin(); Array::const_iterator<> el_end = elements.end(); for (; el_it != el_end; ++el_it) { UInt distant_cluster; buffer >> distant_cluster; const Element & el = *el_it; UInt local_cluster = element_to_fragment(el.type, el.ghost_type)(el.element) + starting_index; distant_ids.insert(std::make_pair(local_cluster, distant_cluster)); } } private: GroupManager & group_manager; UInt element_dimension; std::string cluster_name_prefix; ElementTypeMapArray & element_to_fragment; DistributedSynchronizer & distributed_synchronizer; UInt nb_cluster; DistantIDs distant_ids; UInt starting_index; }; /* -------------------------------------------------------------------------- */ /// \todo this function doesn't work in 1D UInt GroupManager::createBoundaryGroupFromGeometry() { UInt spatial_dimension = mesh.getSpatialDimension(); return createClusters(spatial_dimension - 1, "boundary"); } /* -------------------------------------------------------------------------- */ //// \todo if needed element list construction can be optimized by //// templating the filter class UInt GroupManager::createClusters(UInt element_dimension, std::string cluster_name_prefix, const GroupManager::ClusteringFilter & filter, DistributedSynchronizer * distributed_synchronizer, Mesh * mesh_facets) { AKANTU_DEBUG_IN(); UInt nb_proc = StaticCommunicator::getStaticCommunicator().getNbProc(); std::string tmp_cluster_name_prefix = cluster_name_prefix; ElementTypeMapArray * element_to_fragment = NULL; if (nb_proc > 1 && distributed_synchronizer) { element_to_fragment = new ElementTypeMapArray; mesh.initElementTypeMapArray(*element_to_fragment, 1, element_dimension, false, _ek_not_defined, true); tmp_cluster_name_prefix = "tmp_" + tmp_cluster_name_prefix; } /// Get facets bool mesh_facets_created = false; if (!mesh_facets && element_dimension > 0) { mesh_facets = new Mesh(mesh.getSpatialDimension(), mesh.getNodes().getID(), "mesh_facets_for_clusters"); mesh_facets->defineMeshParent(mesh); MeshUtils::buildAllFacets(mesh, *mesh_facets, element_dimension, element_dimension - 1, distributed_synchronizer); } ElementTypeMapArray seen_elements("seen_elements"); mesh.initElementTypeMapArray(seen_elements, 1, element_dimension, false, _ek_not_defined, true); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Element el; el.ghost_type = ghost_type; Mesh::type_iterator type_it = mesh.firstType(element_dimension, ghost_type, _ek_not_defined); Mesh::type_iterator type_end = mesh.lastType (element_dimension, ghost_type, _ek_not_defined); for (; type_it != type_end; ++type_it) { el.type = *type_it; el.kind = Mesh::getKind(*type_it); UInt nb_element = mesh.getNbElement(*type_it, ghost_type); Array & seen_elements_array = seen_elements(el.type, ghost_type); for (UInt e = 0; e < nb_element; ++e) { el.element = e; if (!filter(el)) seen_elements_array(e) = true; } } } Array checked_node(mesh.getNbNodes(), 1, false); UInt nb_cluster = 0; /// keep looping until all elements are seen for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Element uns_el; uns_el.ghost_type = ghost_type; Mesh::type_iterator type_it = mesh.firstType(element_dimension, ghost_type, _ek_not_defined); Mesh::type_iterator type_end = mesh.lastType(element_dimension, ghost_type, _ek_not_defined); for (; type_it != type_end; ++type_it) { uns_el.type = *type_it; Array & seen_elements_vec = seen_elements(uns_el.type, uns_el.ghost_type); for (UInt e = 0; e < seen_elements_vec.getSize(); ++e) { // skip elements that have been already seen if (seen_elements_vec(e) == true) continue; // set current element uns_el.element = e; seen_elements_vec(e) = true; /// create a new cluster std::stringstream sstr; sstr << tmp_cluster_name_prefix << "_" << nb_cluster; ElementGroup & cluster = createElementGroup(sstr.str(), element_dimension, true); ++nb_cluster; // point element are cluster by themself if(element_dimension == 0) { cluster.add(uns_el); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(uns_el.type); Vector connect = mesh.getConnectivity(uns_el.type, uns_el.ghost_type).begin(nb_nodes_per_element)[uns_el.element]; for (UInt n = 0; n < nb_nodes_per_element; ++n) { /// add element's nodes to the cluster UInt node = connect[n]; if (!checked_node(node)) { cluster.addNode(node); checked_node(node) = true; } } continue; } std::queue element_to_add; element_to_add.push(uns_el); /// keep looping until current cluster is complete (no more /// connected elements) while(!element_to_add.empty()) { /// take first element and erase it in the queue Element el = element_to_add.front(); element_to_add.pop(); /// if parallel, store cluster index per element if (nb_proc > 1 && distributed_synchronizer) (*element_to_fragment)(el.type, el.ghost_type)(el.element) = nb_cluster - 1; /// add current element to the cluster cluster.add(el); const Array & element_to_facet = mesh_facets->getSubelementToElement(el.type, el.ghost_type); UInt nb_facet_per_element = element_to_facet.getNbComponent(); for (UInt f = 0; f < nb_facet_per_element; ++f) { const Element & facet = element_to_facet(el.element, f); if (facet == ElementNull) continue; const std::vector & connected_elements = mesh_facets->getElementToSubelement(facet.type, facet.ghost_type)(facet.element); for (UInt elem = 0; elem < connected_elements.size(); ++elem) { const Element & check_el = connected_elements[elem]; // check if this element has to be skipped if (check_el == ElementNull || check_el == el) continue; Array & seen_elements_vec_current = seen_elements(check_el.type, check_el.ghost_type); if (seen_elements_vec_current(check_el.element) == false) { seen_elements_vec_current(check_el.element) = true; element_to_add.push(check_el); } } } UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type); Vector connect = mesh.getConnectivity(el.type, el.ghost_type).begin(nb_nodes_per_element)[el.element]; for (UInt n = 0; n < nb_nodes_per_element; ++n) { /// add element's nodes to the cluster UInt node = connect[n]; if (!checked_node(node)) { cluster.addNode(node, false); checked_node(node) = true; } } } } } } if (nb_proc > 1 && distributed_synchronizer) { ClusterSynchronizer cluster_synchronizer(*this, element_dimension, cluster_name_prefix, *element_to_fragment, *distributed_synchronizer, nb_cluster); nb_cluster = cluster_synchronizer.synchronize(); delete element_to_fragment; } if (mesh_facets_created) delete mesh_facets; if(mesh.isDistributed()) this->synchronizeGroupNames(); AKANTU_DEBUG_OUT(); return nb_cluster; } /* -------------------------------------------------------------------------- */ template void GroupManager::createGroupsFromMeshData(const std::string & dataset_name) { std::set group_names; const ElementTypeMapArray & datas = mesh.getData(dataset_name); typedef typename ElementTypeMapArray::type_iterator type_iterator; std::map group_dim; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { type_iterator type_it = datas.firstType(_all_dimensions, *gt); type_iterator type_end = datas.lastType(_all_dimensions, *gt); for (; type_it != type_end; ++type_it) { const Array & dataset = datas(*type_it, *gt); UInt nb_element = mesh.getNbElement(*type_it, *gt); AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element, "Not the same number of elements ("<< *type_it << ":" << *gt << ") in the map from MeshData (" << dataset.getSize() << ") " << dataset_name <<" and in the mesh (" << nb_element << ")!"); for(UInt e(0); e < nb_element; ++e) { std::stringstream sstr; sstr << dataset(e); std::string gname = sstr.str(); group_names.insert(gname); std::map::iterator it = group_dim.find(gname); if(it == group_dim.end()) { group_dim[gname] = mesh.getSpatialDimension(*type_it); } else { it->second = std::max(it->second, mesh.getSpatialDimension(*type_it)); } } } } std::set::iterator git = group_names.begin(); std::set::iterator gend = group_names.end(); for (;git != gend; ++git) createElementGroup(*git, group_dim[*git]); if(mesh.isDistributed()) this->synchronizeGroupNames(); Element el; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { el.ghost_type = *gt; type_iterator type_it = datas.firstType(_all_dimensions, *gt); type_iterator type_end = datas.lastType(_all_dimensions, *gt); for (; type_it != type_end; ++type_it) { el.type = *type_it; const Array & dataset = datas(*type_it, *gt); UInt nb_element = mesh.getNbElement(*type_it, *gt); AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element, "Not the same number of elements in the map from MeshData and in the mesh!"); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(el.type); Array::const_iterator< Vector > cit = mesh.getConnectivity(*type_it, *gt).begin(nb_nodes_per_element); for(UInt e(0); e < nb_element; ++e, ++cit) { el.element = e; std::stringstream sstr; sstr << dataset(e); ElementGroup & group = getElementGroup(sstr.str()); group.add(el, false, false); const Vector & connect = *cit; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connect[n]; group.addNode(node, false); } } } } git = group_names.begin(); for (;git != gend; ++git) { getElementGroup(*git).optimize(); } } template void GroupManager::createGroupsFromMeshData(const std::string & dataset_name); template void GroupManager::createGroupsFromMeshData(const std::string & dataset_name); /* -------------------------------------------------------------------------- */ void GroupManager::createElementGroupFromNodeGroup(const std::string & name, const std::string & node_group_name, UInt dimension) { NodeGroup & node_group = getNodeGroup(node_group_name); ElementGroup & group = createElementGroup(name, dimension, node_group); - CSR node_to_elem; - MeshUtils::buildNode2Elements(mesh, node_to_elem, dimension); - - std::set seen; - - Array::const_iterator<> itn = node_group.begin(); - Array::const_iterator<> endn = node_group.end(); - for (;itn != endn; ++itn) { - CSR::iterator ite = node_to_elem.begin(*itn); - CSR::iterator ende = node_to_elem.end(*itn); - for (;ite != ende; ++ite) { - const Element & elem = *ite; - if(dimension != _all_dimensions && dimension != Mesh::getSpatialDimension(elem.type)) continue; - if(seen.find(elem) != seen.end()) continue; - - UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(elem.type); - Array::const_iterator< Vector > conn_it = - mesh.getConnectivity(elem.type, elem.ghost_type).begin(nb_nodes_per_element); - const Vector & conn = conn_it[elem.element]; - - UInt count = 0; - for (UInt n = 0; n < conn.size(); ++n) { - count += (node_group.getNodes().find(conn(n)) != -1 ? 1 : 0); - } - - if(count == nb_nodes_per_element) group.add(elem); - - seen.insert(elem); - } - } - - group.optimize(); + group.fillFromNodeGroup(); } /* -------------------------------------------------------------------------- */ void GroupManager::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "GroupManager [" << std::endl; std::set node_group_seen; for(const_element_group_iterator it(element_group_begin()); it != element_group_end(); ++it) { it->second->printself(stream, indent + 1); node_group_seen.insert(it->second->getNodeGroup().getName()); } for(const_node_group_iterator it(node_group_begin()); it != node_group_end(); ++it) { if(node_group_seen.find(it->second->getName()) == node_group_seen.end()) it->second->printself(stream, indent + 1); } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ UInt GroupManager::getNbElementGroups(UInt dimension) const { if(dimension == _all_dimensions) return element_groups.size(); ElementGroups::const_iterator it = element_groups.begin(); ElementGroups::const_iterator end = element_groups.end(); UInt count = 0; for(;it != end; ++it) count += (it->second->getDimension() == dimension); return count; } /* -------------------------------------------------------------------------- */ void GroupManager::checkAndAddGroups(CommunicationBuffer & buffer) { AKANTU_DEBUG_IN(); UInt nb_node_group; buffer >> nb_node_group; AKANTU_DEBUG_INFO("Received " << nb_node_group << " node group names"); for (UInt ng = 0; ng < nb_node_group; ++ng) { std::string node_group_name; buffer >> node_group_name; if(node_groups.find(node_group_name) == node_groups.end()) { this->createNodeGroup(node_group_name); } AKANTU_DEBUG_INFO("Received node goup name: " << node_group_name); } UInt nb_element_group; buffer >> nb_element_group; AKANTU_DEBUG_INFO("Received " << nb_element_group << " element group names"); for (UInt eg = 0; eg < nb_element_group; ++eg) { std::string element_group_name; buffer >> element_group_name; std::string node_group_name; buffer >> node_group_name; UInt dim; buffer >> dim; AKANTU_DEBUG_INFO("Received element group name: " << element_group_name << " corresponding to a " << Int(dim) << "D group with node group " << node_group_name); NodeGroup & node_group = *node_groups[node_group_name]; if(element_groups.find(element_group_name) == element_groups.end()) { this->createElementGroup(element_group_name, dim, node_group); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::fillBufferWithGroupNames(DynamicCommunicationBuffer & comm_buffer) const { AKANTU_DEBUG_IN(); // packing node group names; UInt nb_groups = this->node_groups.size(); comm_buffer << nb_groups; AKANTU_DEBUG_INFO("Sending " << nb_groups << " node group names"); NodeGroups::const_iterator nnames_it = node_groups.begin(); NodeGroups::const_iterator nnames_end = node_groups.end(); for (; nnames_it != nnames_end; ++nnames_it) { std::string node_group_name = nnames_it->first; comm_buffer << node_group_name; AKANTU_DEBUG_INFO("Sending node goupe name: " << node_group_name); } // packing element group names with there associated node group name nb_groups = this->element_groups.size(); comm_buffer << nb_groups; AKANTU_DEBUG_INFO("Sending " << nb_groups << " element group names"); ElementGroups::const_iterator gnames_it = this->element_groups.begin(); ElementGroups::const_iterator gnames_end = this->element_groups.end(); for (; gnames_it != gnames_end; ++gnames_it) { ElementGroup & element_group = *(gnames_it->second); std::string element_group_name = gnames_it->first; std::string node_group_name = element_group.getNodeGroup().getName(); UInt dim = element_group.getDimension(); comm_buffer << element_group_name; comm_buffer << node_group_name; comm_buffer << dim; AKANTU_DEBUG_INFO("Sending element group name: " << element_group_name << " corresponding to a " << Int(dim) << "D group with the node group " << node_group_name); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::synchronizeGroupNames() { AKANTU_DEBUG_IN(); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt nb_proc = comm.getNbProc(); UInt my_rank = comm.whoAmI(); if(nb_proc == 1) return; if(my_rank == 0) { for (UInt p = 1; p < nb_proc; ++p) { CommunicationStatus status; comm.probe(p, p, status); AKANTU_DEBUG_INFO("Got " << printMemorySize(status.getSize()) << " from proc " << p); CommunicationBuffer recv_buffer(status.getSize()); comm.receive(recv_buffer.storage(), recv_buffer.getSize(), p, p); this->checkAndAddGroups(recv_buffer); } DynamicCommunicationBuffer comm_buffer; this->fillBufferWithGroupNames(comm_buffer); UInt buffer_size = comm_buffer.getSize(); comm.broadcast(&buffer_size, 1, 0); AKANTU_DEBUG_INFO("Initiating broadcast with " << printMemorySize(comm_buffer.getSize())); comm.broadcast(comm_buffer.storage(), buffer_size, 0); } else { DynamicCommunicationBuffer comm_buffer; this->fillBufferWithGroupNames(comm_buffer); AKANTU_DEBUG_INFO("Sending " << printMemorySize(comm_buffer.getSize()) << " to proc " << 0); comm.send(comm_buffer.storage(), comm_buffer.getSize(), 0, my_rank); UInt buffer_size = 0; comm.broadcast(&buffer_size, 1, 0); AKANTU_DEBUG_INFO("Receiving broadcast with " << printMemorySize(comm_buffer.getSize())); CommunicationBuffer recv_buffer(buffer_size); comm.broadcast(recv_buffer.storage(), recv_buffer.getSize(), 0); this->checkAndAddGroups(recv_buffer); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ const ElementGroup & GroupManager::getElementGroup(const std::string & name) const { const_element_group_iterator it = element_group_find(name); if(it == element_group_end()) { AKANTU_EXCEPTION("There are no element groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::getElementGroup(const std::string & name) { element_group_iterator it = element_group_find(name); if(it == element_group_end()) { AKANTU_EXCEPTION("There are no element groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ const NodeGroup & GroupManager::getNodeGroup(const std::string & name) const { const_node_group_iterator it = node_group_find(name); if(it == node_group_end()) { AKANTU_EXCEPTION("There are no node groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ NodeGroup & GroupManager::getNodeGroup(const std::string & name) { node_group_iterator it = node_group_find(name); if(it == node_group_end()) { AKANTU_EXCEPTION("There are no node groups named " << name << " associated to the group manager: " << id); } return *(it->second); } __END_AKANTU__ diff --git a/src/mesh/group_manager.hh b/src/mesh/group_manager.hh index 2e5919e6e..cd4967728 100644 --- a/src/mesh/group_manager.hh +++ b/src/mesh/group_manager.hh @@ -1,303 +1,303 @@ /** * @file group_manager.hh * * @author Guillaume Anciaux * @author Dana Christen * @author Nicolas Richart * @author David Simon Kammer * * @date creation: Fri May 03 2013 * @date last modification: Fri Sep 05 2014 * * @brief Stores information relevent to the notion of element and nodes groups. * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_GROUP_MANAGER_HH__ #define __AKANTU_GROUP_MANAGER_HH__ #include #include "aka_common.hh" #include "element_type_map.hh" //#include "dumpable.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ class FEM; class ElementGroup; class NodeGroup; class Mesh; class Element; class DistributedSynchronizer; template class CommunicationBufferTemplated; namespace dumper { class Field; } /* -------------------------------------------------------------------------- */ class GroupManager { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ private: typedef std::map ElementGroups; typedef std::map NodeGroups; public: typedef std::set GroupManagerTypeSet; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: GroupManager(const Mesh & mesh, const ID & id = "group_manager", const MemoryID & memory_id = 0); virtual ~GroupManager(); /* ------------------------------------------------------------------------ */ /* Groups iterators */ /* ------------------------------------------------------------------------ */ public: typedef NodeGroups::iterator node_group_iterator; typedef ElementGroups::iterator element_group_iterator; typedef NodeGroups::const_iterator const_node_group_iterator; typedef ElementGroups::const_iterator const_element_group_iterator; #ifndef SWIG #define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(group_type, \ function, \ param_in, \ param_out) \ inline BOOST_PP_CAT(BOOST_PP_CAT(const_, group_type), _iterator) \ BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) const { \ return BOOST_PP_CAT(group_type, s).function(param_out); \ }; \ \ inline BOOST_PP_CAT(group_type, _iterator) \ BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) { \ return BOOST_PP_CAT(group_type, s).function(param_out); \ } #define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(group_type, function) \ AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(group_type, function, BOOST_PP_EMPTY(), BOOST_PP_EMPTY()) AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, begin); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, end ); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, begin); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, end ); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(element_group, find, const std::string & name, name); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(node_group, find, const std::string & name, name); #endif - + /* ------------------------------------------------------------------------ */ /* Clustering filter */ /* ------------------------------------------------------------------------ */ public: class ClusteringFilter { public: virtual bool operator() (const Element &) const { return true; } }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// create an empty node group NodeGroup & createNodeGroup(const std::string & group_name, bool replace_group = false); /// create a node group from another node group but filtered template NodeGroup & createFilteredNodeGroup(const std::string & group_name, const NodeGroup & node_group, T & filter); /// destroy a node group void destroyNodeGroup(const std::string & group_name); /// create an element group and the associated node group ElementGroup & createElementGroup(const std::string & group_name, UInt dimension = _all_dimensions, bool replace_group = false); /// create an element group from another element group but filtered template ElementGroup & createFilteredElementGroup(const std::string & group_name, UInt dimension, const NodeGroup & node_group, T & filter); /// destroy an element group and the associated node group void destroyElementGroup(const std::string & group_name, bool destroy_node_group = false); /// destroy all element groups and the associated node groups void destroyAllElementGroups(bool destroy_node_groups = false); /// create a element group using an existing node group ElementGroup & createElementGroup(const std::string & group_name, UInt dimension, NodeGroup & node_group); /// create groups based on values stored in a given mesh data template void createGroupsFromMeshData(const std::string & dataset_name); /// create boundaries group by a clustering algorithm \todo extend to parallel UInt createBoundaryGroupFromGeometry(); /// create element clusters for a given dimension UInt createClusters(UInt element_dimension, std::string cluster_name_prefix = "cluster", const ClusteringFilter & filter = ClusteringFilter(), DistributedSynchronizer * distributed_synchronizer = NULL, Mesh * mesh_facets = NULL); /// Create an ElementGroup based on a NodeGroup void createElementGroupFromNodeGroup(const std::string & name, const std::string & node_group, UInt dimension = _all_dimensions); virtual void printself(std::ostream & stream, int indent = 0) const; /// this function insure that the group names are present on all processors /// /!\ it is a SMP call void synchronizeGroupNames(); /// register an elemental field to the given group name (overloading for ElementalPartionField) #ifndef SWIG template class dump_type> - inline dumper::Field * createElementalField(const ElementTypeMapArray & field, + inline dumper::Field * createElementalField(const ElementTypeMapArray & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap nb_data_per_elem = ElementTypeMap()); /// register an elemental field to the given group name (overloading for ElementalField) template class ret_type, template class,bool> class dump_type> - inline dumper::Field * createElementalField(const ElementTypeMapArray & field, + inline dumper::Field * createElementalField(const ElementTypeMapArray & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap nb_data_per_elem = ElementTypeMap()); /// register an elemental field to the given group name (overloading for MaterialInternalField) - template class dump_type> - inline dumper::Field * createElementalField(const ElementTypeMapArray & field, + inline dumper::Field * createElementalField(const ElementTypeMapArray & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap nb_data_per_elem); - + template class ftype> inline dumper::Field * createNodalField(const ftype * field, const std::string & group_name, UInt padding_size = 0); - + template class ftype> inline dumper::Field * createStridedNodalField(const ftype * field, const std::string & group_name, UInt size, UInt stride, UInt padding_size); protected: /// fill a buffer with all the group names void fillBufferWithGroupNames(CommunicationBufferTemplated & comm_buffer) const; /// take a buffer and create the missing groups localy void checkAndAddGroups(CommunicationBufferTemplated & buffer); - + /// register an elemental field to the given group name template - inline dumper::Field * createElementalField(const field_type & field, + inline dumper::Field * createElementalField(const field_type & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap nb_data_per_elem); /// register an elemental field to the given group name template - inline dumper::Field * createElementalFilteredField(const field_type & field, + inline dumper::Field * createElementalFilteredField(const field_type & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap nb_data_per_elem); #endif /* ------------------------------------------------------------------------ */ /* Accessor */ /* ------------------------------------------------------------------------ */ public: const ElementGroup & getElementGroup(const std::string & name) const; const NodeGroup & getNodeGroup(const std::string & name) const; ElementGroup & getElementGroup(const std::string & name); NodeGroup & getNodeGroup(const std::string & name); UInt getNbElementGroups(UInt dimension = _all_dimensions) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id to create element and node groups ID id; /// memory_id to create element and node groups MemoryID memory_id; /// list of the node groups managed NodeGroups node_groups; /// list of the element groups managed ElementGroups element_groups; /// Mesh to which the element belongs const Mesh & mesh; }; /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const GroupManager & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_GROUP_MANAGER_HH__ */