Loading src/TNL/Meshes/Mesh.h +6 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,12 @@ class Mesh static constexpr int getMeshDimension(); using StorageBaseType::isBoundaryEntity; using StorageBaseType::getBoundaryEntitiesCount; using StorageBaseType::getBoundaryEntityIndex; using StorageBaseType::getInteriorEntitiesCount; using StorageBaseType::getInteriorEntityIndex; template< int Dimension > static constexpr bool entitiesAvailable(); Loading src/TNL/Meshes/MeshConfigBase.h +25 −3 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <TNL/String.h> #include <TNL/param-types.h> #include <TNL/Meshes/Topologies/MeshSubtopology.h> namespace TNL { namespace Meshes { Loading Loading @@ -65,14 +66,14 @@ struct MeshConfigBase static constexpr bool entityStorage( int dimension ) { /**** * Vertices and cells must always be stored * Vertices and cells must always be stored. */ return true; //return ( dimension == 0 || dimension == cellDimension ); } /**** * Storage of subentities of mesh entities * Storage of subentities of mesh entities. */ template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimension ) Loading @@ -96,7 +97,7 @@ struct MeshConfigBase } /**** * Storage of superentities of mesh entities * Storage of superentities of mesh entities. */ template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimension ) Loading @@ -104,6 +105,27 @@ struct MeshConfigBase return entityStorage( EntityTopology::dimension ); //return false; } /**** * Storage of boundary tags of mesh entities. Necessary for the mesh traverser. * * The configuration must satisfy the following necessary conditions in * order to provide boundary tags: * - faces must be stored * - faces must store the cell indices in the superentity layer * - if dim(entity) < dim(face), the entities on which the tags are stored * must be stored as subentities of faces * TODO: check this in the MeshConfigValidator */ template< typename EntityTopology > static constexpr bool boundaryTagsStorage( EntityTopology ) { using FaceTopology = typename MeshSubtopology< CellTopology, meshDimension - 1 >::Topology; return entityStorage( meshDimension - 1 ) && superentityStorage( FaceTopology(), meshDimension ) && ( EntityTopology::dimension >= meshDimension - 1 || subentityStorage( FaceTopology(), EntityTopology::dimension ) ); //return false; } }; } // namespace Meshes Loading src/TNL/Meshes/MeshDetails/Mesh_impl.h +2 −3 Original line number Diff line number Diff line Loading @@ -133,7 +133,8 @@ load( File& file ) std::cerr << "Mesh loading failed." << std::endl; return false; } // update pointers from entities into the superentity storage network // TODO: this could be done from the storage layer // update pointers from entities into the subentity and superentity storage networks MeshEntityStorageRebinder< Mesh< MeshConfig > >::exec( *this ); return true; } Loading Loading @@ -163,8 +164,6 @@ init( typename MeshTraitsType::PointArrayType& points, MeshInitializer< MeshConfig> meshInitializer; if( ! meshInitializer.createMesh( points, cellSeeds, *this ) ) return false; // update pointers from entities into the superentity storage network MeshEntityStorageRebinder< Mesh< MeshConfig > >::exec( *this ); return true; } Loading src/TNL/Meshes/MeshDetails/config/MeshConfigValidator.h +25 −1 Original line number Diff line number Diff line Loading @@ -71,6 +71,28 @@ class MeshConfigValidatorSupertopologyLayer< MeshConfig, EntityTopology, Dimensi {}; template< typename MeshConfig, typename EntityTopology, bool BoundaryTagsStorage = MeshConfig::boundaryTagsStorage( EntityTopology() ) > class MeshConfigValidatorBoundaryTagsLayer { using FaceTopology = typename MeshSubtopology< typename MeshConfig::CellTopology, MeshConfig::meshDimension - 1 >::Topology; static_assert( MeshConfig::entityStorage( MeshConfig::meshDimension - 1 ), "Faces must be stored when any entity has boundary tags." ); static_assert( MeshConfig::superentityStorage( FaceTopology(), MeshConfig::meshDimension ), "Faces must store the cell superentity indices when any entity has boundary tags." ); static_assert( EntityTopology::dimension >= MeshConfig::meshDimension - 1 || MeshConfig::subentityStorage( FaceTopology(), EntityTopology::dimension ), "Faces must store the subentity indices of the entities on which the boundary tags are stored." ); }; template< typename MeshConfig, typename EntityTopology > class MeshConfigValidatorBoundaryTagsLayer< MeshConfig, EntityTopology, false > { }; template< typename MeshConfig, int dimension > class MeshConfigValidatorLayer : public MeshConfigValidatorLayer< MeshConfig, dimension - 1 >, Loading @@ -79,7 +101,9 @@ class MeshConfigValidatorLayer DimensionTag< dimension - 1 > >, public MeshConfigValidatorSupertopologyLayer< MeshConfig, typename MeshSubtopology< typename MeshConfig::CellTopology, dimension >::Topology, DimensionTag< MeshConfig::CellTopology::dimension > > DimensionTag< MeshConfig::CellTopology::dimension > >, public MeshConfigValidatorBoundaryTagsLayer< MeshConfig, typename MeshSubtopology< typename MeshConfig::CellTopology, dimension >::Topology > { using Topology = typename MeshSubtopology< typename MeshConfig::CellTopology, dimension >::Topology; Loading src/TNL/Meshes/MeshDetails/initializer/BoundaryTagsInitializer.h 0 → 100644 +147 −0 Original line number Diff line number Diff line /*************************************************************************** BoundaryTagsInitializer.h - description ------------------- begin : Dec 26, 2016 copyright : (C) 2016 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ /* See Copyright Notice in tnl/Copyright */ #pragma once #include <TNL/StaticFor.h> #include <TNL/Meshes/DimensionTag.h> #include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> #include <TNL/Meshes/Topologies/MeshEntityTopology.h> namespace TNL { namespace Meshes { template< typename Mesh, typename CurrentDimension = DimensionTag< Mesh::getMeshDimension() > > struct BoundaryTagsNeedInitialization { using EntityTopology = typename MeshEntityTopology< typename Mesh::Config, CurrentDimension >::Topology; static constexpr bool value = Mesh::Config::boundaryTagsStorage( EntityTopology() ) || BoundaryTagsNeedInitialization< Mesh, typename CurrentDimension::Decrement >::value; }; template< typename Mesh > struct BoundaryTagsNeedInitialization< Mesh, DimensionTag< 0 > > { using EntityTopology = typename MeshEntityTopology< typename Mesh::Config, DimensionTag< 0 > >::Topology; static constexpr bool value = Mesh::Config::boundaryTagsStorage( EntityTopology() ); }; template< typename Mesh, bool AnyBoundaryTags = BoundaryTagsNeedInitialization< Mesh >::value > class BoundaryTagsInitializer { using GlobalIndexType = typename Mesh::Config::GlobalIndexType; using LocalIndexType = typename Mesh::Config::LocalIndexType; using FaceTraits = typename MeshTraits< typename Mesh::Config >::template EntityTraits< Mesh::getMeshDimension() - 1 >; using FaceType = typename FaceTraits::EntityType; public: template< typename MeshInitializer > static bool exec( MeshInitializer& initializer, Mesh& mesh ) { StaticFor< int, 0, Mesh::getMeshDimension() + 1, ResetBoundaryTags >::exec( initializer ); const GlobalIndexType facesCount = mesh.template getEntitiesCount< Mesh::getMeshDimension() - 1 >(); for( GlobalIndexType faceIndex = 0; faceIndex < facesCount; faceIndex++ ) { const auto& face = mesh.template getEntity< Mesh::getMeshDimension() - 1 >( faceIndex ); if( face.template getSuperentitiesCount< Mesh::getMeshDimension() >() == 1 ) { // initialize the face initializer.template setIsBoundaryEntity< Mesh::getMeshDimension() - 1 >( faceIndex, true ); // initialize the cell superentity const GlobalIndexType cellIndex = face.template getSuperentityIndex< Mesh::getMeshDimension() >( 0 ); initializer.template setIsBoundaryEntity< Mesh::getMeshDimension() >( cellIndex, true ); // initialize all subentities StaticFor< int, 0, Mesh::getMeshDimension() - 1, InitializeSubentities >::exec( initializer, faceIndex, face ); } } // hack due to StaticFor operating only with void return type bool result = true; StaticFor< int, 0, Mesh::getMeshDimension() + 1, UpdateBoundaryIndices >::exec( initializer, result ); return result; } private: template< int Dimension > struct ResetBoundaryTags { template< typename MeshInitializer > static void exec( MeshInitializer& initializer ) { initializer.template resetBoundaryTags< Dimension >(); } }; template< int Subdimension > class InitializeSubentities { using SubentityTopology = typename MeshEntityTopology< typename Mesh::Config, DimensionTag< Subdimension > >::Topology; static constexpr bool enabled = Mesh::Config::boundaryTagsStorage( SubentityTopology() ); // _T is necessary to force *partial* specialization, since explicit specializations // at class scope are forbidden template< bool enabled = true, typename _T = void > struct Worker { template< typename MeshInitializer > static void exec( MeshInitializer& initializer, const GlobalIndexType& faceIndex, const FaceType& face ) { auto subentitiesCount = face.template getSubentitiesCount< Subdimension >(); for( decltype(subentitiesCount) i = 0; i < subentitiesCount; i++ ) { const GlobalIndexType subentityIndex = face.template getSubentityIndex< Subdimension >( i ); initializer.template setIsBoundaryEntity< Subdimension >( subentityIndex, true ); } } }; template< typename _T > struct Worker< false, _T > { template< typename MeshInitializer > static void exec( MeshInitializer& initializer, const GlobalIndexType& faceIndex, const FaceType& face ) {} }; public: template< typename MeshInitializer > static void exec( MeshInitializer& initializer, const GlobalIndexType& faceIndex, const FaceType& face ) { Worker< enabled >::exec( initializer, faceIndex, face ); } }; template< int Dimension > struct UpdateBoundaryIndices { template< typename MeshInitializer > static void exec( MeshInitializer& initializer, bool& result ) { result &= initializer.template updateBoundaryIndices< Dimension >(); } }; }; template< typename Mesh > struct BoundaryTagsInitializer< Mesh, false > { template< typename MeshInitializer > static bool exec( MeshInitializer& initializer, Mesh& mesh ) { return true; } }; } // namespace Meshes } // namespace TNL Loading
src/TNL/Meshes/Mesh.h +6 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,12 @@ class Mesh static constexpr int getMeshDimension(); using StorageBaseType::isBoundaryEntity; using StorageBaseType::getBoundaryEntitiesCount; using StorageBaseType::getBoundaryEntityIndex; using StorageBaseType::getInteriorEntitiesCount; using StorageBaseType::getInteriorEntityIndex; template< int Dimension > static constexpr bool entitiesAvailable(); Loading
src/TNL/Meshes/MeshConfigBase.h +25 −3 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <TNL/String.h> #include <TNL/param-types.h> #include <TNL/Meshes/Topologies/MeshSubtopology.h> namespace TNL { namespace Meshes { Loading Loading @@ -65,14 +66,14 @@ struct MeshConfigBase static constexpr bool entityStorage( int dimension ) { /**** * Vertices and cells must always be stored * Vertices and cells must always be stored. */ return true; //return ( dimension == 0 || dimension == cellDimension ); } /**** * Storage of subentities of mesh entities * Storage of subentities of mesh entities. */ template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimension ) Loading @@ -96,7 +97,7 @@ struct MeshConfigBase } /**** * Storage of superentities of mesh entities * Storage of superentities of mesh entities. */ template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimension ) Loading @@ -104,6 +105,27 @@ struct MeshConfigBase return entityStorage( EntityTopology::dimension ); //return false; } /**** * Storage of boundary tags of mesh entities. Necessary for the mesh traverser. * * The configuration must satisfy the following necessary conditions in * order to provide boundary tags: * - faces must be stored * - faces must store the cell indices in the superentity layer * - if dim(entity) < dim(face), the entities on which the tags are stored * must be stored as subentities of faces * TODO: check this in the MeshConfigValidator */ template< typename EntityTopology > static constexpr bool boundaryTagsStorage( EntityTopology ) { using FaceTopology = typename MeshSubtopology< CellTopology, meshDimension - 1 >::Topology; return entityStorage( meshDimension - 1 ) && superentityStorage( FaceTopology(), meshDimension ) && ( EntityTopology::dimension >= meshDimension - 1 || subentityStorage( FaceTopology(), EntityTopology::dimension ) ); //return false; } }; } // namespace Meshes Loading
src/TNL/Meshes/MeshDetails/Mesh_impl.h +2 −3 Original line number Diff line number Diff line Loading @@ -133,7 +133,8 @@ load( File& file ) std::cerr << "Mesh loading failed." << std::endl; return false; } // update pointers from entities into the superentity storage network // TODO: this could be done from the storage layer // update pointers from entities into the subentity and superentity storage networks MeshEntityStorageRebinder< Mesh< MeshConfig > >::exec( *this ); return true; } Loading Loading @@ -163,8 +164,6 @@ init( typename MeshTraitsType::PointArrayType& points, MeshInitializer< MeshConfig> meshInitializer; if( ! meshInitializer.createMesh( points, cellSeeds, *this ) ) return false; // update pointers from entities into the superentity storage network MeshEntityStorageRebinder< Mesh< MeshConfig > >::exec( *this ); return true; } Loading
src/TNL/Meshes/MeshDetails/config/MeshConfigValidator.h +25 −1 Original line number Diff line number Diff line Loading @@ -71,6 +71,28 @@ class MeshConfigValidatorSupertopologyLayer< MeshConfig, EntityTopology, Dimensi {}; template< typename MeshConfig, typename EntityTopology, bool BoundaryTagsStorage = MeshConfig::boundaryTagsStorage( EntityTopology() ) > class MeshConfigValidatorBoundaryTagsLayer { using FaceTopology = typename MeshSubtopology< typename MeshConfig::CellTopology, MeshConfig::meshDimension - 1 >::Topology; static_assert( MeshConfig::entityStorage( MeshConfig::meshDimension - 1 ), "Faces must be stored when any entity has boundary tags." ); static_assert( MeshConfig::superentityStorage( FaceTopology(), MeshConfig::meshDimension ), "Faces must store the cell superentity indices when any entity has boundary tags." ); static_assert( EntityTopology::dimension >= MeshConfig::meshDimension - 1 || MeshConfig::subentityStorage( FaceTopology(), EntityTopology::dimension ), "Faces must store the subentity indices of the entities on which the boundary tags are stored." ); }; template< typename MeshConfig, typename EntityTopology > class MeshConfigValidatorBoundaryTagsLayer< MeshConfig, EntityTopology, false > { }; template< typename MeshConfig, int dimension > class MeshConfigValidatorLayer : public MeshConfigValidatorLayer< MeshConfig, dimension - 1 >, Loading @@ -79,7 +101,9 @@ class MeshConfigValidatorLayer DimensionTag< dimension - 1 > >, public MeshConfigValidatorSupertopologyLayer< MeshConfig, typename MeshSubtopology< typename MeshConfig::CellTopology, dimension >::Topology, DimensionTag< MeshConfig::CellTopology::dimension > > DimensionTag< MeshConfig::CellTopology::dimension > >, public MeshConfigValidatorBoundaryTagsLayer< MeshConfig, typename MeshSubtopology< typename MeshConfig::CellTopology, dimension >::Topology > { using Topology = typename MeshSubtopology< typename MeshConfig::CellTopology, dimension >::Topology; Loading
src/TNL/Meshes/MeshDetails/initializer/BoundaryTagsInitializer.h 0 → 100644 +147 −0 Original line number Diff line number Diff line /*************************************************************************** BoundaryTagsInitializer.h - description ------------------- begin : Dec 26, 2016 copyright : (C) 2016 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ /* See Copyright Notice in tnl/Copyright */ #pragma once #include <TNL/StaticFor.h> #include <TNL/Meshes/DimensionTag.h> #include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> #include <TNL/Meshes/Topologies/MeshEntityTopology.h> namespace TNL { namespace Meshes { template< typename Mesh, typename CurrentDimension = DimensionTag< Mesh::getMeshDimension() > > struct BoundaryTagsNeedInitialization { using EntityTopology = typename MeshEntityTopology< typename Mesh::Config, CurrentDimension >::Topology; static constexpr bool value = Mesh::Config::boundaryTagsStorage( EntityTopology() ) || BoundaryTagsNeedInitialization< Mesh, typename CurrentDimension::Decrement >::value; }; template< typename Mesh > struct BoundaryTagsNeedInitialization< Mesh, DimensionTag< 0 > > { using EntityTopology = typename MeshEntityTopology< typename Mesh::Config, DimensionTag< 0 > >::Topology; static constexpr bool value = Mesh::Config::boundaryTagsStorage( EntityTopology() ); }; template< typename Mesh, bool AnyBoundaryTags = BoundaryTagsNeedInitialization< Mesh >::value > class BoundaryTagsInitializer { using GlobalIndexType = typename Mesh::Config::GlobalIndexType; using LocalIndexType = typename Mesh::Config::LocalIndexType; using FaceTraits = typename MeshTraits< typename Mesh::Config >::template EntityTraits< Mesh::getMeshDimension() - 1 >; using FaceType = typename FaceTraits::EntityType; public: template< typename MeshInitializer > static bool exec( MeshInitializer& initializer, Mesh& mesh ) { StaticFor< int, 0, Mesh::getMeshDimension() + 1, ResetBoundaryTags >::exec( initializer ); const GlobalIndexType facesCount = mesh.template getEntitiesCount< Mesh::getMeshDimension() - 1 >(); for( GlobalIndexType faceIndex = 0; faceIndex < facesCount; faceIndex++ ) { const auto& face = mesh.template getEntity< Mesh::getMeshDimension() - 1 >( faceIndex ); if( face.template getSuperentitiesCount< Mesh::getMeshDimension() >() == 1 ) { // initialize the face initializer.template setIsBoundaryEntity< Mesh::getMeshDimension() - 1 >( faceIndex, true ); // initialize the cell superentity const GlobalIndexType cellIndex = face.template getSuperentityIndex< Mesh::getMeshDimension() >( 0 ); initializer.template setIsBoundaryEntity< Mesh::getMeshDimension() >( cellIndex, true ); // initialize all subentities StaticFor< int, 0, Mesh::getMeshDimension() - 1, InitializeSubentities >::exec( initializer, faceIndex, face ); } } // hack due to StaticFor operating only with void return type bool result = true; StaticFor< int, 0, Mesh::getMeshDimension() + 1, UpdateBoundaryIndices >::exec( initializer, result ); return result; } private: template< int Dimension > struct ResetBoundaryTags { template< typename MeshInitializer > static void exec( MeshInitializer& initializer ) { initializer.template resetBoundaryTags< Dimension >(); } }; template< int Subdimension > class InitializeSubentities { using SubentityTopology = typename MeshEntityTopology< typename Mesh::Config, DimensionTag< Subdimension > >::Topology; static constexpr bool enabled = Mesh::Config::boundaryTagsStorage( SubentityTopology() ); // _T is necessary to force *partial* specialization, since explicit specializations // at class scope are forbidden template< bool enabled = true, typename _T = void > struct Worker { template< typename MeshInitializer > static void exec( MeshInitializer& initializer, const GlobalIndexType& faceIndex, const FaceType& face ) { auto subentitiesCount = face.template getSubentitiesCount< Subdimension >(); for( decltype(subentitiesCount) i = 0; i < subentitiesCount; i++ ) { const GlobalIndexType subentityIndex = face.template getSubentityIndex< Subdimension >( i ); initializer.template setIsBoundaryEntity< Subdimension >( subentityIndex, true ); } } }; template< typename _T > struct Worker< false, _T > { template< typename MeshInitializer > static void exec( MeshInitializer& initializer, const GlobalIndexType& faceIndex, const FaceType& face ) {} }; public: template< typename MeshInitializer > static void exec( MeshInitializer& initializer, const GlobalIndexType& faceIndex, const FaceType& face ) { Worker< enabled >::exec( initializer, faceIndex, face ); } }; template< int Dimension > struct UpdateBoundaryIndices { template< typename MeshInitializer > static void exec( MeshInitializer& initializer, bool& result ) { result &= initializer.template updateBoundaryIndices< Dimension >(); } }; }; template< typename Mesh > struct BoundaryTagsInitializer< Mesh, false > { template< typename MeshInitializer > static bool exec( MeshInitializer& initializer, Mesh& mesh ) { return true; } }; } // namespace Meshes } // namespace TNL