diff --git a/src/fem/boundary.cc b/src/fem/boundary.cc index 05fc02059..70121bd58 100644 --- a/src/fem/boundary.cc +++ b/src/fem/boundary.cc @@ -1,337 +1,349 @@ /** * @file boundary.cc * * @author Dana Christen * * @date Wed Mar 06 09:30:00 2013 * * @brief Stores information relevent to the notion of domain boundary and surfaces. * * @section LICENSE * * Copyright (©) 2010-2011 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 "boundary.hh" #include "mesh.hh" #include "aka_csr.hh" #include "mesh_utils.hh" #include "sub_boundary.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Boundary::Boundary(const Mesh & mesh, const ID & id, const ID & parent_id, const MemoryID & mem_id) :memory_id(mem_id), num_boundaries(0), mesh(mesh) { AKANTU_DEBUG_IN(); std::stringstream sstr; if(parent_id != "") sstr << parent_id << ":"; sstr << id; this->id = sstr.str(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Boundary::~Boundary() { for(BoundaryList::iterator boundaries_iter = boundaries.begin(); boundaries_iter != boundaries.end(); boundaries_iter++) { delete boundaries_iter->second; } } /* -------------------------------------------------------------------------- */ Boundary::BoundaryTypeSet Boundary::getBoundaryElementTypes() { // find surface element type that exists in this mesh (from David's code) UInt dim = mesh.getSpatialDimension(); BoundaryTypeSet surface_types; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); for (Mesh::ConnectivityTypeList::const_iterator it = type_list.begin(); it != type_list.end(); ++it) { ElementType surface_type = mesh.getFacetType(*it); if (mesh.getSpatialDimension(*it) == dim && mesh.getNbElement(surface_type) != 0) { surface_types.insert(surface_type); } } return surface_types; } /* -------------------------------------------------------------------------- */ void Boundary::addElementAndNodesToBoundaryAlloc(const std::string & boundary_name, const ElementType & elem_type, UInt elem_id) { UInt nb_nodes_per_element = mesh.getNbNodesPerElement(elem_type); BoundaryList::iterator boundaries_iter = boundaries.find(boundary_name); //XXX _not_ghost = correct ? const Array & connectivity = mesh.getConnectivity(elem_type, _not_ghost); if(boundaries_iter == boundaries.end()) { // Manual construction of the sub-boundary ID std::stringstream sstr; sstr <<"subBoundary_" << boundary_name; SubBoundary * subB = new SubBoundary(boundary_name, sstr.str(), id, memory_id); boundaries_iter = boundaries.insert(boundaries_iter, std::pair(boundary_name, subB)); this->num_boundaries++; //std::cout << "Allocating a subBoundary! Name: " << boundary_name << std::endl; } boundaries_iter->second->addElement(elem_type, elem_id); for (UInt n(0); n < nb_nodes_per_element; n++) { boundaries_iter->second->addNode(connectivity(elem_id, n)); } } /* -------------------------------------------------------------------------- */ void Boundary::createBoundariesFromGeometry() { AKANTU_DEBUG_IN(); CSR node_to_elem; /// Get list of surface elements UInt spatial_dimension = mesh.getSpatialDimension(); // buildNode2Elements(mesh, node_offset, node_to_elem, spatial_dimension-1); MeshUtils::buildNode2Elements(mesh, node_to_elem, spatial_dimension-1); /// Find which types of elements have been linearized const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); ElementType lin_element_type[nb_types]; UInt nb_lin_types = 0; UInt nb_nodes_per_element[nb_types]; UInt nb_nodes_per_element_p1[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types+1]; ElementType type_p1; for(it = type_list.begin(); it != type_list.end(); ++it) { //std::cout <<"Main type: " << *it << std::endl; ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) { continue; } ElementType facet_type = mesh.getFacetType(type); //std::cout <<"Facet type: " << facet_type << std::endl; lin_element_type[nb_lin_types] = facet_type; nb_nodes_per_element[nb_lin_types] = Mesh::getNbNodesPerElement(facet_type); type_p1 = Mesh::getP1ElementType(facet_type); nb_nodes_per_element_p1[nb_lin_types] = Mesh::getNbNodesPerElement(type_p1); conn_val[nb_lin_types] = mesh.getConnectivity(facet_type, _not_ghost).values; nb_element[nb_lin_types] = mesh.getNbElement(facet_type, _not_ghost); nb_lin_types++; } for (UInt i = 1; i < nb_lin_types; ++i) { nb_element[i] += nb_element[i+1]; } for (UInt i = nb_lin_types; i > 0; --i) { nb_element[i] = nb_element[i-1]; } nb_element[0] = 0; /// Find close surfaces Array surface_value_id(1, nb_element[nb_lin_types], -1); Int * surf_val = surface_value_id.storage(); UInt nb_boundaries = 0; UInt nb_cecked_elements; UInt nb_elements_to_ceck; UInt * elements_to_ceck = new UInt [nb_element[nb_lin_types]]; memset(elements_to_ceck, 0, nb_element[nb_lin_types]*sizeof(UInt)); for (UInt lin_el = 0; lin_el < nb_element[nb_lin_types]; ++lin_el) { if(surf_val[lin_el] != -1) continue; /* Surface id already assigned */ /* First element of new surface */ surf_val[lin_el] = nb_boundaries; nb_cecked_elements = 0; nb_elements_to_ceck = 1; memset(elements_to_ceck, 0, nb_element[nb_lin_types]*sizeof(UInt)); elements_to_ceck[0] = lin_el; // Find others elements belonging to this surface while(nb_cecked_elements < nb_elements_to_ceck) { UInt ceck_lin_el = elements_to_ceck[nb_cecked_elements]; // Transform linearized index of element into ElementType one UInt lin_type_nb = 0; while (ceck_lin_el >= nb_element[lin_type_nb+1]) { lin_type_nb++; } UInt ceck_el = ceck_lin_el - nb_element[lin_type_nb]; // Get connected elements UInt el_offset = ceck_el*nb_nodes_per_element[lin_type_nb]; for (UInt n = 0; n < nb_nodes_per_element_p1[lin_type_nb]; ++n) { UInt node_id = conn_val[lin_type_nb][el_offset + n]; CSR::iterator it_n; for (it_n = node_to_elem.begin(node_id); it_n != node_to_elem.end(node_id); ++it_n) { if(surf_val[*it_n] == -1) { /* Found new surface element */ surf_val[*it_n] = nb_boundaries; elements_to_ceck[nb_elements_to_ceck] = *it_n; nb_elements_to_ceck++; } } } nb_cecked_elements++; } nb_boundaries++; } delete [] elements_to_ceck; /// Transform local linearized element index in the global one for (UInt i = 0; i < nb_lin_types; ++i) { nb_element[i] = nb_element[i+1] - nb_element[i]; } UInt el_offset = 0; for(UInt type_it = 0; type_it < nb_lin_types; ++type_it) { ElementType type = lin_element_type[type_it]; //std::cout << "Second type: " << type << std::endl; for (UInt el = 0; el < nb_element[type_it]; ++el) { std::stringstream sstr; sstr << surf_val[el+el_offset]; std::string surf_name(sstr.str()); //std::cout << "Inserting elements and nodes to surface " << surf_name << std::endl; addElementAndNodesToBoundaryAlloc(surf_name, type, el); } //std::cout << "Offset +" << nb_element[type_it] << std::endl; el_offset += nb_element[type_it]; } BoundaryList::iterator subB_iter = boundaries.begin(); BoundaryList::iterator subB_iter_end = boundaries.end(); for(;subB_iter != subB_iter_end; ++subB_iter) { - subB_iter->second->cleanUpNodeList(); - subB_iter->second->addDumpBoundary(mesh, *subB_iter->second, mesh.getSpatialDimension()-1, _not_ghost, _ek_regular); + SubBoundary & sub = *subB_iter->second; + sub.cleanUpNodeList(); + sub.addDumpFilteredMesh(mesh, + sub.elements, + sub.nodes, + mesh.getSpatialDimension() - 1, + _not_ghost, + _ek_regular); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Boundary::createBoundariesFromMeshData(const std::string & dataset_name) { BoundaryTypeSet surface_types = getBoundaryElementTypes(); for(BoundaryTypeSet::const_iterator type_it = surface_types.begin(); type_it != surface_types.end(); ++type_it) { const Array & dataset = mesh.getData(*type_it, dataset_name); UInt nb_element = mesh.getNbElement(*type_it); AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element, "Not the same number of elements in the map from MeshData and in the mesh!"); // FIXME This could be improved (performance...) for(UInt i(0); i < nb_element; ++i) { std::stringstream sstr; sstr << dataset(i); std::string boundary_name = sstr.str(); addElementAndNodesToBoundaryAlloc(boundary_name, *type_it, i); } } BoundaryList::iterator subB_iter = boundaries.begin(); BoundaryList::iterator subB_iter_end = boundaries.end(); for(;subB_iter != subB_iter_end; ++subB_iter) { - subB_iter->second->cleanUpNodeList(); - subB_iter->second->addDumpBoundary(mesh, *subB_iter->second, mesh.getSpatialDimension()-1, _not_ghost, _ek_regular); + SubBoundary & sub = *subB_iter->second; + sub.cleanUpNodeList(); + sub.addDumpFilteredMesh(mesh, + sub.elements, + sub.nodes, + mesh.getSpatialDimension() - 1, + _not_ghost, + _ek_regular); } } template void Boundary::createBoundariesFromMeshData(const std::string & dataset_name); template void Boundary::createBoundariesFromMeshData(const std::string & dataset_name); /* -------------------------------------------------------------------------- */ void Boundary::createBoundariesFromMeshData(const std::string & dataset_name) { createBoundariesFromMeshData(dataset_name); } /* -------------------------------------------------------------------------- */ void Boundary::printself(std::ostream & stream) const { for(const_iterator it(begin()); it != end(); ++it) { stream << "-- Boundary \"" << it->getName() << "\":" << std::endl; // Loop over the nodes stream << "---- " << it->getNbNodes() << " nodes"; if(AKANTU_DEBUG_TEST(dblDump)) { stream << ":" << std::endl; stream << "------ "; for(SubBoundary::nodes_const_iterator nodes_it(it->nodes_begin()); nodes_it!= it->nodes_end(); ++nodes_it) { stream << *nodes_it << " "; } } stream << std::endl; // Loop over the element types stream << "---- Elements:" << std::endl; Mesh::type_iterator type_it = mesh.firstType(mesh.getSpatialDimension()-1); Mesh::type_iterator type_end = mesh.lastType(mesh.getSpatialDimension()-1); for(; type_it != type_end; ++type_it) { stream << "------ Type " << *type_it; const Array & element_ids = it->getElements(*type_it); if(AKANTU_DEBUG_TEST(dblDump)) { stream << ":" << std::endl; stream << "-------- "; // Loop over the corresponding elements in the SubBoundary for(UInt i(0); igetElements(*type_it); } } stream << std::endl; } /* -------------------------------------------------------------------------- */ void Boundary::dump() { for(iterator it(begin()); it != end(); ++it) { it->dump(); } } __END_AKANTU__ diff --git a/src/fem/sub_boundary.cc b/src/fem/sub_boundary.cc index 12f1262bb..29b000b63 100644 --- a/src/fem/sub_boundary.cc +++ b/src/fem/sub_boundary.cc @@ -1,65 +1,71 @@ /** * @file boundary.cc * * @author Dana Christen * * @date Wed Mar 06 09:30:00 2013 * * @brief Stores information relevent to the notion of domain boundary and surfaces. * * @section LICENSE * * Copyright (©) 2010-2011 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 "sub_boundary.hh" #include "mesh.hh" #include "aka_csr.hh" #include "mesh_utils.hh" __BEGIN_AKANTU__ -SubBoundary::SubBoundary(const std::string & _name, const ID & _id, const ID & parent_id, const MemoryID & mem_id) -:Dumpable(parent_id + "_" + _id), id(parent_id + "_" + _id), memory_id(mem_id), name(_name), nodes(0, 1, id + ":nodes"), elements("elements", id, memory_id) -{ +SubBoundary::SubBoundary(const std::string & _name, + const ID & _id, + const ID & parent_id, + const MemoryID & mem_id) : + Dumpable(parent_id + "_" + _id), + id(parent_id + "_" + _id), + memory_id(mem_id), name(_name), + nodes(0, 1, id + ":nodes"), + elements("elements", id, memory_id) { } /* -------------------------------------------------------------------------- */ void SubBoundary::printself(std::ostream & stream) const { } /* -------------------------------------------------------------------------- */ void SubBoundary::cleanUpNodeList() { UInt size_before = nodes.getSize(); UInt * newEnd; UInt * begin = nodes.storage(); UInt * end = nodes.storage()+nodes.getSize(); std::sort(begin, end); newEnd = std::unique(begin, end); UInt crop_size = end-newEnd; UInt size_after = size_before - crop_size; nodes.resize(size_after); } __END_AKANTU__ diff --git a/src/io/dumper/dumpable.hh b/src/io/dumper/dumpable.hh index 746fb2b48..833215846 100644 --- a/src/io/dumper/dumpable.hh +++ b/src/io/dumper/dumpable.hh @@ -1,257 +1,259 @@ /** * @file dumpable.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date Fri Oct 26 21:52:40 2012 * * @brief Interface for object who wants to dump themselves * * @section LICENSE * * Copyright (©) 2010-2011 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 "aka_common.hh" #ifdef AKANTU_USE_IOHELPER #include "dumper_paraview.hh" #endif //AKANTU_USE_IOHELPER #ifndef __AKANTU_DUMPABLE_HH__ #define __AKANTU_DUMPABLE_HH__ __BEGIN_AKANTU__ #ifdef AKANTU_USE_IOHELPER template class Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Dumpable(const std::string & filename) : dumper(filename) { }; virtual ~Dumpable() { }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void addDumpMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined) { dumper.registerMesh(mesh, spatial_dimension, ghost_type, element_kind); } - void addDumpBoundary(const Mesh & mesh, - const SubBoundary & boundary, - UInt spatial_dimension = _all_dimensions, - const GhostType & ghost_type = _not_ghost, - const ElementKind & element_kind = _ek_not_defined) { - dumper.registerBoundary(mesh, - boundary, - spatial_dimension, - ghost_type, - element_kind); + void addDumpFilteredMesh(const Mesh & mesh, + const ByElementTypeArray & elements_filter, + const Array & nodes_filter, + UInt spatial_dimension = _all_dimensions, + const GhostType & ghost_type = _not_ghost, + const ElementKind & element_kind = _ek_not_defined) { + dumper.registerFilteredMesh(mesh, + elements_filter, + nodes_filter, + spatial_dimension, + ghost_type, + element_kind); } virtual void addDumpField(const std::string & field_id) { AKANTU_DEBUG_TO_IMPLEMENT(); }; virtual void addDumpFieldExternal(__attribute__((unused)) const std::string & field_id, __attribute__((unused)) DumperIOHelper::Field * field) { dumper.registerField(field_id, field); } template void addDumpFieldExternal(const std::string & field_id, const Array & field) { DumperIOHelper::Field * field_cont = new DumperIOHelper::NodalField(field); dumper.registerField(field_id, field_cont); } template void addDumpFieldExternal(const std::string & field_id, const ByElementTypeArray & field, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined) { DumperIOHelper::Field * field_cont = new DumperIOHelper::ElementalField(field, spatial_dimension, ghost_type, element_kind); dumper.registerField(field_id, field_cont); } void removeDumpField(const std::string & field_id) { dumper.unRegisterField(field_id); } void setDirectory(const std::string & directory) { dumper.setDirectory(directory); } void setBaseName(const std::string & basename) { dumper.setBaseName(basename); } void dump() { dumper.dump(); } protected: void addDumpFieldToDumper(const std::string & field_id, DumperIOHelper::Field * field) { dumper.registerField(field_id, field); } protected: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_NOT_CONST(Dumper, dumper, Dumper &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: Dumper dumper; }; #else /* -------------------------------------------------------------------------- */ class DumperIOHelper { public: class Field; }; class DumperParaview; class Mesh; class SubBoundary; /* -------------------------------------------------------------------------- */ template class Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Dumpable(const std::string & filename) { }; virtual ~Dumpable() { }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void addDumpMesh(__attribute__((unused)) const Mesh & mesh, __attribute__((unused)) UInt spatial_dimension = _all_dimensions, __attribute__((unused)) const GhostType & ghost_type = _not_ghost, __attribute__((unused)) const ElementKind & element_kind = _ek_not_defined) { } void addDumpBoundary(__attribute__((unused)) const Mesh & mesh, __attribute__((unused)) const SubBoundary & boundary, __attribute__((unused)) UInt spatial_dimension = _all_dimensions, __attribute__((unused)) const GhostType & ghost_type = _not_ghost, __attribute__((unused)) const ElementKind & element_kind = _ek_not_defined) { } virtual void addDumpField(__attribute__((unused)) const std::string & field_id){ AKANTU_DEBUG_TO_IMPLEMENT(); }; virtual void addDumpFieldExternal(__attribute__((unused)) const std::string & field_id, __attribute__((unused)) DumperIOHelper::Field * field) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } template void addDumpFieldExternal(__attribute__((unused)) const std::string & field_id, __attribute__((unused)) const Array & field) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } template void addDumpFieldExternal(__attribute__((unused)) const std::string & field_id, __attribute__((unused)) const ByElementTypeArray & field, __attribute__((unused)) UInt spatial_dimension = _all_dimensions, __attribute__((unused)) const GhostType & ghost_type = _not_ghost, __attribute__((unused)) const ElementKind & element_kind = _ek_not_defined) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } virtual void addDumpFieldArray(__attribute__((unused)) const std::string & field_id) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); }; virtual void addDumpFieldTensor(__attribute__((unused)) const std::string & field_id) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); }; void removeDumpField(__attribute__((unused)) const std::string & field_id) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void setDirectory(__attribute__((unused)) const std::string & directory) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void setBaseName(__attribute__((unused)) const std::string & basename) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } void dump() { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } protected: void addDumpFieldToDumper(__attribute__((unused)) const std::string & field_id, __attribute__((unused)) DumperIOHelper::Field * field) { AKANTU_DEBUG_WARNING("No dumper activated at compilation, turn on AKANTU_USE_IOHELPER in cmake."); } protected: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; #endif //AKANTU_USE_IOHELPER __END_AKANTU__ #endif /* __AKANTU_DUMPABLE_HH__ */ diff --git a/src/io/dumper/dumper_iohelper.cc b/src/io/dumper/dumper_iohelper.cc index d446f542b..ed24749f2 100644 --- a/src/io/dumper/dumper_iohelper.cc +++ b/src/io/dumper/dumper_iohelper.cc @@ -1,194 +1,196 @@ /** * @file dumper_iohelper.cc * * @author Nicolas Richart * * @date Fri Oct 26 21:52:40 2012 * * @brief implementation of DumperIOHelper * * @section LICENSE * * Copyright (©) 2010-2011 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 "dumper_iohelper.hh" #include "sub_boundary.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ DumperIOHelper::DumperIOHelper() : count(0) { } /* -------------------------------------------------------------------------- */ DumperIOHelper::~DumperIOHelper() { for (Fields::iterator it = fields.begin(); it != fields.end(); ++it) { delete it->second; } delete dumper; } /* -------------------------------------------------------------------------- */ void DumperIOHelper::dump() { std::stringstream filename_sstr; filename_sstr << filename << "_" << std::setw(4) << std::setfill('0') << count; try { dumper->dump(filename_sstr.str()); } catch (iohelper::IOHelperException & e) { AKANTU_DEBUG_ERROR("I was not able to dump your data with a Dumper: " << e.what()); } ++count; } void DumperIOHelper::registerMesh(const Mesh & mesh, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { #if defined(AKANTU_COHESIVE_ELEMENT) if (element_kind == _ek_cohesive) { registerField("connectivities", new DumperIOHelper::CohesiveConnectivityField(mesh, spatial_dimension, ghost_type)); } else #endif registerField("connectivities", new DumperIOHelper::ElementalField(mesh.getConnectivities(), spatial_dimension, ghost_type, element_kind)); registerField("element_type", new DumperIOHelper::ElementTypeField<>(mesh, spatial_dimension, ghost_type, element_kind)); registerField("positions", new DumperIOHelper::NodalField(mesh.getNodes())); } -void DumperIOHelper::registerBoundary(const Mesh & mesh, - const SubBoundary & boundary, - UInt spatial_dimension, - const GhostType & ghost_type, - const ElementKind & element_kind) { +void DumperIOHelper::registerFilteredMesh(const Mesh & mesh, + const ByElementTypeArray & elements_filter, + const Array & nodes_filter, + UInt spatial_dimension, + const GhostType & ghost_type, + const ElementKind & element_kind) { registerField("connectivities", new DumperIOHelper::FilteredConnectivityField(mesh.getConnectivities(), - boundary.getElements(), - boundary.getNodes(), + elements_filter, + nodes_filter, spatial_dimension, ghost_type, element_kind)); registerField("element_type", new DumperIOHelper::ElementTypeField(mesh, spatial_dimension, ghost_type, element_kind, - &boundary.getElements())); + &elements_filter)); + registerField("positions", new DumperIOHelper::NodalField(mesh.getNodes(), 0, 0, - &boundary.getNodes())); + &nodes_filter)); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::registerField(const std::string & field_id, Field * field) { Fields::iterator it = fields.find(field_id); if(it != fields.end()) AKANTU_DEBUG_ERROR("The field " << field_id << " is already registered in this Dumper"); fields[field_id] = field; field->registerToDumper(field_id, *dumper); } /* -------------------------------------------------------------------------- */ void DumperIOHelper::unRegisterField(const std::string & field_id) { Fields::iterator it = fields.find(field_id); if(it == fields.end()) AKANTU_DEBUG_ERROR("The field " << field_id << " is not registered in this Dumper"); delete it->second; fields.erase(it); } /* -------------------------------------------------------------------------- */ template iohelper::ElemType DumperIOHelper::getIOHelperType() { AKANTU_DEBUG_TO_IMPLEMENT(); return iohelper::MAX_ELEM_TYPE; } template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_segment_2>() { return iohelper::LINE1; } template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_segment_3>() { return iohelper::LINE2; } template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_triangle_3>() { return iohelper::TRIANGLE1; } template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_triangle_6>() { return iohelper::TRIANGLE2; } template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_quadrangle_4>() { return iohelper::QUAD1; } template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_quadrangle_8>() { return iohelper::QUAD2; } template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_tetrahedron_4>() { return iohelper::TETRA1; } template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_tetrahedron_10>() { return iohelper::TETRA2; } template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_hexahedron_8>() { return iohelper::HEX1; } #if defined(AKANTU_COHESIVE_ELEMENT) template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_cohesive_2d_4>() { return iohelper::COH2D4; } template <> iohelper::ElemType DumperIOHelper::getIOHelperType<_cohesive_2d_6>() { return iohelper::COH2D6; } #endif /* -------------------------------------------------------------------------- */ iohelper::ElemType DumperIOHelper::getIOHelperType(ElementType type) { iohelper::ElemType ioh_type = iohelper::MAX_ELEM_TYPE; #define GET_IOHELPER_TYPE(type) \ ioh_type = DumperIOHelper::getIOHelperType(); AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_IOHELPER_TYPE); #undef GET_IOHELPER_TYPE return ioh_type; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/io/dumper/dumper_iohelper.hh b/src/io/dumper/dumper_iohelper.hh index c1e4caeff..5c4534220 100644 --- a/src/io/dumper/dumper_iohelper.hh +++ b/src/io/dumper/dumper_iohelper.hh @@ -1,234 +1,238 @@ /** * @file dumper_iohelper.hh * * @author Nicolas Richart * * @date Fri Oct 26 21:52:40 2012 * * @brief Define the akantu dumper interface for IOhelper dumpers * * @section LICENSE * * Copyright (©) 2010-2011 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 "aka_common.hh" #include "aka_types.hh" +#include "aka_vector.hh" #include #include "mesh.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DUMPER_IOHELPER_HH__ #define __AKANTU_DUMPER_IOHELPER_HH__ __BEGIN_AKANTU__ class DumperIOHelper { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: DumperIOHelper(); virtual ~DumperIOHelper(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: class Field; void registerMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); - void registerBoundary(const Mesh & mesh, - const SubBoundary & boundary, - UInt spatial_dimension = _all_dimensions, - const GhostType & ghost_type = _not_ghost, - const ElementKind & element_kind = _ek_not_defined); + void registerFilteredMesh(const Mesh & mesh, + const ByElementTypeArray & elements_filter, + const Array & nodes_filter, + UInt spatial_dimension = _all_dimensions, + const GhostType & ghost_type = _not_ghost, + const ElementKind & element_kind = _ek_not_defined); void registerField(const std::string & field_id, Field * field); void unRegisterField(const std::string & field_id); void dump(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Dumper, *dumper, iohelper::Dumper &) static iohelper::ElemType getIOHelperType(ElementType type); protected: template static iohelper::ElemType getIOHelperType(); public: /* ------------------------------------------------------------------------ */ /* Field descriptors */ /* ------------------------------------------------------------------------ */ /// Field interface class Field { public: Field() : padding_n(0), padding_m(0) {} virtual ~Field() {}; virtual void registerToDumper(const std::string & id, iohelper::Dumper & dupmer) = 0; virtual void setPadding(UInt n, UInt m = 1) { padding_n = n; padding_m = m; } protected: UInt padding_n, padding_m; }; /* ------------------------------------------------------------------------ */ template class R> class iterator_helper; template class R> class PaddingHelper; /* ------------------------------------------------------------------------ */ /* Nodal field wrapper */ - template + template, + class Filter = Array > class NodalField; /* ------------------------------------------------------------------------ */ /* Generic class used as interface for the others */ template class ret_type, class daughter, bool filtered > class element_iterator; template class ret_type, class daughter, bool filtered> class generic_quadrature_point_iterator; template class ret_type, bool filtered> class quadrature_point_iterator; template class ret_type, bool filtered> class GenericElementalField; template class ret_type, bool filtered> class GenericQuadraturePointsField; template class ret_type, template class, bool> class iterator_type = quadrature_point_iterator, bool filtered = false> class QuadraturePointsField; /* ------------------------------------------------------------------------ */ /* Elemental Fields wrapper */ template class element_type_field_iterator; template class element_partition_field_iterator; class cohesive_connectivity_field_iterator; template class ret_type, bool filtered> class elemental_field_iterator; class filtered_connectivity_field_iterator; template class ElementTypeField; template class ElementPartitionField; template class ret_type = Vector, bool filtered = false> class ElementalField; class CohesiveConnectivityField; class FilteredConnectivityField; /* ------------------------------------------------------------------------ */ /* Material Field wrapper */ template class ret_type, template class> class padding_helper_type, template class, bool> class int_iterator, bool filtered> class generic_internal_material_field_iterator; template class ret_type, bool filtered> class internal_material_field_iterator; template class ret_type, bool filtered> class material_stress_field_iterator; template class ret_type, bool filtered> class material_strain_field_iterator; template class ret_type = Vector, template class, bool> class iterator_type = internal_material_field_iterator, bool filtered = false> class InternalMaterialField; template class R> class MaterialPaddingHelper; template class R> class StressPaddingHelper; template class R> class StrainPaddingHelper; /* ------------------------------------------------------------------------ */ /* Field homogenizing wrapper */ template class sub_type> class PaddingHomogenizingFunctor; template class sub_type> class AvgHomogenizingFunctor; template class, template class, bool> class, bool > class Container, template class, bool> class sub_iterator = internal_material_field_iterator, template class> class Funct = AvgHomogenizingFunctor, template class ret_type = Vector, bool filtered = false> class HomogenizedField; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// internal iohelper::Dumper iohelper::Dumper * dumper; typedef std::map Fields; /// list of registered fields to dump Fields fields; /// dump counter UInt count; /// filename std::string filename; }; #include "dumper_iohelper_tmpl.hh" __END_AKANTU__ #endif /* __AKANTU_DUMPER_IOHELPER_HH__ */ diff --git a/src/io/dumper/dumper_iohelper_tmpl_nodal_field.hh b/src/io/dumper/dumper_iohelper_tmpl_nodal_field.hh index e8c2a2950..a46804ae9 100644 --- a/src/io/dumper/dumper_iohelper_tmpl_nodal_field.hh +++ b/src/io/dumper/dumper_iohelper_tmpl_nodal_field.hh @@ -1,165 +1,165 @@ /** * @file dumper_iohelper_tmpl_nodal_field.hh * * @author Nicolas Richart * * @date Fri Oct 26 21:52:40 2012 * * @brief Description of nodal fields * * @section LICENSE * * Copyright (©) 2010-2011 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 . * */ /* -------------------------------------------------------------------------- */ -template -class DumperIOHelper::NodalField : public Field { +template +class DumperIOHelper::NodalField : public Field { public: /* -----------------------------------------------------------------------*/ class iterator : public iohelper::iterator< T, iterator, Vector > { public: iterator(T * vect, UInt offset, UInt n, UInt stride, __attribute__ ((unused)) const UInt * filter = NULL) : internal_it(vect), offset(offset), n(n), stride(stride) {} bool operator!=(const iterator & it) const { return internal_it != it.internal_it; } iterator & operator++() { internal_it += offset; return *this; }; Vector operator* (){ return Vector(internal_it + stride, n); }; private: T * internal_it; UInt offset, n, stride; }; /* ---------------------------------------------------------------------- */ - NodalField(const Array & field, UInt n = 0, UInt stride = 0, __attribute__ ((unused)) const Array * filter = NULL) : + NodalField(const Container & field, UInt n = 0, UInt stride = 0, __attribute__ ((unused)) const Filter * filter = NULL) : field(field), n(n), stride(stride) { AKANTU_DEBUG_ASSERT(filter == NULL, "Filter passed to unfiltered NodalField!"); if(n == 0) { this->n = field.getNbComponent() - stride; } } virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) { dumper.addNodeDataField(id, *this); } inline iterator begin() { return iterator(field.storage(), field.getNbComponent(), n, stride); } inline iterator end () { return iterator(field.storage() + field.getNbComponent()*field.getSize(), field.getNbComponent(), n, stride); } bool isHomogeneous() { return true; } virtual UInt getDim() { if(this->padding_n && this->padding_m) return this->padding_n * this->padding_m; else return n; } UInt size() { return field.getSize(); } iohelper::DataType getDataType() { return iohelper::getDataType(); } private: - const Array & field; + const Container & field; UInt n, stride; }; /* -------------------------------------------------------------------------- */ -template -class DumperIOHelper::NodalField : public Field { +template +class DumperIOHelper::NodalField : public Field { public: /* ------------------------------------------------------------------------ */ class iterator : public iohelper::iterator< T, iterator, Vector > { public: iterator(T * const vect, UInt _offset, UInt _n, UInt _stride, const UInt * filter) : internal_it(vect), offset(_offset), n(_n), stride(_stride), filter(filter) {} bool operator!=(const iterator & it) const { return filter != it.filter; } iterator & operator++() { ++filter; return *this; } Vector operator* () { return Vector(internal_it + *(filter)*offset + stride, n); } private: T * const internal_it; UInt offset, n, stride; const UInt * filter; }; /* ---------------------------------------------------------------------- */ - NodalField(const Array & _field, + NodalField(const Container & _field, UInt _n = 0, UInt _stride = 0, - const Array * filter = NULL) + const Filter * filter = NULL) : field(_field), n(_n), stride(_stride), filter(filter) { AKANTU_DEBUG_ASSERT(filter != NULL, "No filter passed to filtered NodalField!"); AKANTU_DEBUG_ASSERT(filter->getNbComponent()==1, "Multi-component filter given to NodalField!"); if(n == 0) { this->n = field.getNbComponent() - stride; } } virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) { dumper.addNodeDataField(id, *this); } inline iterator begin() { return iterator(field.storage(), field.getNbComponent(), n, stride, filter->storage()); } inline iterator end() { return iterator(field.storage(), field.getNbComponent(), n, stride, filter->storage()+filter->getSize()); } bool isHomogeneous() { return true; } virtual UInt getDim() { if(this->padding_n && this->padding_m) return this->padding_n * this->padding_m; else return n; } UInt size() { return filter->getSize(); } iohelper::DataType getDataType() { return iohelper::getDataType(); } private: - const Array & field; + const Container & field; UInt n, stride; - const Array * filter; + const Filter * filter; }; diff --git a/src/model/model.cc b/src/model/model.cc index fe05fb49c..e115ea625 100644 --- a/src/model/model.cc +++ b/src/model/model.cc @@ -1,173 +1,210 @@ /** * @file model.cc * * @author Guillaume Anciaux * @author David Simon Kammer * @author Nicolas Richart * * @date Mon Oct 03 12:24:07 2011 * * @brief implementation of model common parts * * @section LICENSE * * Copyright (©) 2010-2011 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 "sub_boundary.hh" #include "model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Model::Model(Mesh& m, const ID & id, const MemoryID & memory_id) : Memory(memory_id), mesh(m), id(id),synch_registry(NULL),is_pbc_slave_node(0,1,"is_pbc_slave_node") { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Model::createSynchronizerRegistry(DataAccessor * data_accessor){ synch_registry = new SynchronizerRegistry(*data_accessor); } /* -------------------------------------------------------------------------- */ void Model::setPBC(UInt x, UInt y, UInt z){ Mesh & mesh = getFEM().getMesh(); mesh.computeBoundingBox(); if (x) MeshUtils::computePBCMap(mesh, 0, pbc_pair); if (y) MeshUtils::computePBCMap(mesh, 1, pbc_pair); if (z) MeshUtils::computePBCMap(mesh, 2, pbc_pair); } /* -------------------------------------------------------------------------- */ void Model::setPBC(SurfacePairList & surface_pairs, ElementType surface_e_type){ Mesh & mesh = getFEM().getMesh(); SurfacePairList::iterator s_it; for(s_it = surface_pairs.begin(); s_it != surface_pairs.end(); ++s_it) { MeshUtils::computePBCMap(mesh, *s_it, surface_e_type, pbc_pair); } } /* -------------------------------------------------------------------------- */ void Model::initPBC() { Mesh & mesh = getFEM().getMesh(); std::map::iterator it = pbc_pair.begin(); std::map::iterator end = pbc_pair.end(); is_pbc_slave_node.resize(mesh.getNbNodes()); #ifndef AKANTU_NDEBUG Real * coords = mesh.getNodes().values; UInt dim = mesh.getSpatialDimension(); #endif while(it != end){ UInt i1 = (*it).first; is_pbc_slave_node(i1) = true; #ifndef AKANTU_NDEBUG UInt i2 = (*it).second; AKANTU_DEBUG_INFO("pairing " << i1 << " (" << coords[dim*i1] << "," << coords[dim*i1+1] << "," << coords[dim*i1+2] << ") with " << i2 << " (" << coords[dim*i2] << "," << coords[dim*i2+1] << "," << coords[dim*i2+2] << ")"); #endif ++it; } } /* -------------------------------------------------------------------------- */ Synchronizer & Model::createParallelSynch(MeshPartition * partition, __attribute__((unused)) DataAccessor * data_accessor){ AKANTU_DEBUG_IN(); /* ------------------------------------------------------------------------ */ /* Parallel initialization */ /* ------------------------------------------------------------------------ */ StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); DistributedSynchronizer * synch = NULL; if(prank == 0) synch = DistributedSynchronizer::createDistributedSynchronizerMesh(getFEM().getMesh(), partition); else synch = DistributedSynchronizer::createDistributedSynchronizerMesh(getFEM().getMesh(), NULL); AKANTU_DEBUG_OUT(); return *synch; } /* -------------------------------------------------------------------------- */ Model::~Model() { AKANTU_DEBUG_IN(); FEMMap::iterator it; for (it = fems.begin(); it != fems.end(); ++it) { if(it->second) delete it->second; } for (it = fems_boundary.begin(); it != fems_boundary.end(); ++it) { if(it->second) delete it->second; } delete synch_registry; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void Model::dumpBoundary(const std::string & name) { +void Model::dumpBoundary(const std::string & boundary_name) { Boundary & boundary = mesh.getBoundary(); - Boundary::iterator bit = boundary.find(name); + Boundary::iterator bit = boundary.find(boundary_name); Boundary::iterator bend = boundary.end(); if(bit == bend) { - AKANTU_EXCEPTION("No boundary named " << name << "!"); + AKANTU_EXCEPTION("No boundary named " << boundary_name << "!"); } bit->dump(); } /* -------------------------------------------------------------------------- */ void Model::dumpBoundary() { Boundary & boundary = mesh.getBoundary(); Boundary::iterator bit = boundary.begin(); Boundary::iterator bend = boundary.end(); for(; bit != bend; ++bit) { bit->dump(); } } +/* -------------------------------------------------------------------------- */ +void Model::setBoundaryDirectory(const std::string & directory) { + Boundary & boundary = mesh.getBoundary(); + Boundary::iterator bit = boundary.begin(); + Boundary::iterator bend = boundary.end(); + + for (; bit != bend; ++bit) { + bit->setDirectory(directory); + } +} + +/* -------------------------------------------------------------------------- */ +void Model::setBoundaryDirectory(const std::string & directory, + const std::string & boundary_name) { + Boundary & boundary = mesh.getBoundary(); + Boundary::iterator bit = boundary.find(boundary_name); + Boundary::iterator bend = boundary.end(); + + if(bit == bend) { + AKANTU_EXCEPTION("No boundary named " << boundary_name << "!"); + } + bit->setDirectory(directory); +} + +/* -------------------------------------------------------------------------- */ +void Model::setBoundaryBaseName(const std::string & basename, + const std::string & boundary_name) { + Boundary & boundary = mesh.getBoundary(); + Boundary::iterator bit = boundary.find(boundary_name); + Boundary::iterator bend = boundary.end(); + + if(bit == bend) { + AKANTU_EXCEPTION("No boundary named " << boundary_name << "!"); + } + bit->setBaseName(basename); +} + /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/model.hh b/src/model/model.hh index 52da50126..a8b91cd50 100644 --- a/src/model/model.hh +++ b/src/model/model.hh @@ -1,239 +1,244 @@ /** * @file model.hh * * @author Guillaume Anciaux * @author David Simon Kammer * @author Nicolas Richart * * @date Tue Jul 27 18:15:37 2010 * * @brief Interface of a model * * @section LICENSE * * Copyright (©) 2010-2011 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_MODEL_HH__ #define __AKANTU_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "mesh.hh" #include "fem.hh" #include "mesh_utils.hh" #include "synchronizer_registry.hh" #include "distributed_synchronizer.hh" #include "static_communicator.hh" #include "mesh_partition.hh" #include "dof_synchronizer.hh" #include "pbc_synchronizer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class Model : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef Mesh mesh_type; Model(Mesh& mesh, const ID & id = "model", const MemoryID & memory_id = 0); virtual ~Model(); typedef std::map FEMMap; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initModel() = 0; /// create the synchronizer registry object void createSynchronizerRegistry(DataAccessor * data_accessor); /// create a parallel synchronizer and distribute the mesh Synchronizer & createParallelSynch(MeshPartition * partition, DataAccessor * data_accessor); /// change local equation number so that PBC is assembled properly void changeLocalEquationNumberforPBC(std::map & pbc_pair,UInt dimension); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const = 0; /// initialize the model for PBC void setPBC(UInt x, UInt y, UInt z); void setPBC(SurfacePairList & surface_pairs, ElementType surface_e_type); virtual void initPBC(); void dumpBoundary(const std::string & boundary_name); void dumpBoundary(); + void setBoundaryDirectory(const std::string & directory); + void setBoundaryDirectory(const std::string & directory, + const std::string & boundary_name); + void setBoundaryBaseName(const std::string & basename, + const std::string & boundary_name); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get id of model AKANTU_GET_MACRO(ID, id, const ID) /// get the number of surfaces AKANTU_GET_MACRO(Mesh, mesh, Mesh&); /// return the object hadling equation numbers AKANTU_GET_MACRO(DOFSynchronizer, *dof_synchronizer, const DOFSynchronizer &) /// synchronize the boundary in case of parallel run virtual void synchronizeBoundaries() {}; /// return the fem object associated with a provided name inline FEM & getFEM(const ID & name = "") const; /// return the fem boundary object associated with a provided name virtual FEM & getFEMBoundary(const ID & name = ""); /// register a fem object associated with name template inline void registerFEMObject(const std::string & name, Mesh & mesh, UInt spatial_dimension); /// unregister a fem object associated with name inline void unRegisterFEMObject(const std::string & name); /// return the synchronizer registry SynchronizerRegistry & getSynchronizerRegistry(); public: /// return the fem object associated with a provided name template inline FEMClass & getFEMClass(std::string name = "") const; /// return the fem boundary object associated with a provided name template inline FEMClass & getFEMClassBoundary(std::string name = ""); /// get the pbc pairs std::map & getPBCPairs(){return pbc_pair;}; /* ------------------------------------------------------------------------ */ /* Pack and unpack helper functions */ /* ------------------------------------------------------------------------ */ public: inline UInt getNbQuadraturePoints(const Array & elements, const ID & fem_id = ID()) const; protected: /// returns if node is slave in pbc inline bool getIsPBCSlaveNode(const UInt node); public: template inline void packElementalDataHelper(const ByElementTypeArray & data_to_pack, CommunicationBuffer & buffer, const Array & elements, bool per_quadrature_point = true, const ID & fem_id = ID()) const; template inline void unpackElementalDataHelper(ByElementTypeArray & data_to_unpack, CommunicationBuffer & buffer, const Array & elements, bool per_quadrature_point = true, const ID & fem_id = ID()) const; protected: template inline void packUnpackElementalDataHelper(ByElementTypeArray & data_to_pack, CommunicationBuffer & buffer, const Array & element, bool per_quadrature_point, const ID & fem_id) const; /* -------------------------------------------------------------------------- */ template inline void packNodalDataHelper(Array & data_to_pack, CommunicationBuffer & buffer, const Array & element) const; template inline void unpackNodalDataHelper(Array & data_to_unpack, CommunicationBuffer & buffer, const Array & element) const; template inline void packUnpackNodalDataHelper(Array & data, CommunicationBuffer & buffer, const Array & elements) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Mesh Mesh & mesh; /// id ID id; /// the main fem object present in all models FEMMap fems; /// the fem object present in all models for boundaries FEMMap fems_boundary; /// default fem object std::string default_fem; /// synchronizer registry SynchronizerRegistry * synch_registry; /// handle the equation number things DOFSynchronizer * dof_synchronizer; /// pbc pairs std::map pbc_pair; /// flag per node to know is pbc slave Array is_pbc_slave_node; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "model_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Model & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MODEL_HH__ */