Commit 7004ca4b authored by Jakub Klinkovský's avatar Jakub Klinkovský
Browse files

Added BoundaryTags layer

parent 587ab22d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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();

+25 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <TNL/String.h>
#include <TNL/param-types.h>
#include <TNL/Meshes/Topologies/MeshSubtopology.h>

namespace TNL {
namespace Meshes {
@@ -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 )
@@ -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 )
@@ -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
+2 −3
Original line number Diff line number Diff line
@@ -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;
}
@@ -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;
}

+25 −1
Original line number Diff line number Diff line
@@ -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 >,
@@ -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;

+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