Commit b37161a8 authored by Ján Bobot's avatar Ján Bobot Committed by Jakub Klinkovský
Browse files

Generalization of Mesh Initialization to handle Polygons

- added Polygon specialization for EntitySeed and EntitySeedHash that uses Array instead of StaticArray to handle variable number of cornerIds
- refactored template argument EntityDimensionTag of SubentitySeedsCreator to EntityTopology to allow specializing for Polygons
- added Polygon specialization for SubentitySeedsCreator to handle variable amounts of vertices per polygon
- added getSubentitiesCount function to SubentitySeedsCreator to retrieve number of subentities to be created from passed in vertices
- modified Initializer::initSubentityMatrix function to retrieve capacities from a method argument instead of creating them statically from traits and to pass in retrieved capacities to Mesh::setSubentitiesCounts
- removed EntityInitializer::initSubvertexMatrix function and replaced all calls to it with Initializer::initSubentityMatrix
- modified EntityInitializerLayer::initSuperentities and InitializerLayer::initEntities functions to calculate subentity matrix capacities before a call to Initializer::initSubentityMatrix
parent bdbd12c4
Loading
Loading
Loading
Loading
+25 −11
Original line number Diff line number Diff line
@@ -56,11 +56,6 @@ class EntityInitializer
   using InitializerType  = Initializer< MeshConfig >;

public:
   static void initSubvertexMatrix( const GlobalIndexType entitiesCount, InitializerType& initializer )
   {
      initializer.template initSubentityMatrix< EntityTopology::dimension, 0 >( entitiesCount );
   }

   static void initEntity( const GlobalIndexType entityIndex, const SeedType& entitySeed, InitializerType& initializer )
   {
      // this is necessary if we want to use existing entities instead of intermediate seeds to create subentity seeds
@@ -82,7 +77,6 @@ class EntityInitializer< MeshConfig, EntityTopology, false >
   using SeedType         = EntitySeed< MeshConfig, EntityTopology >;
   using InitializerType  = Initializer< MeshConfig >;
public:
   static void initSubvertexMatrix( const GlobalIndexType entitiesCount, InitializerType& initializer ) {}
   static void initEntity( const GlobalIndexType entityIndex, const SeedType& entitySeed, InitializerType& initializer ) {}
};

@@ -111,6 +105,7 @@ class EntityInitializerLayer< MeshConfig,
                                            typename SuperdimensionTag::Decrement >;
   using InitializerType            = Initializer< MeshConfig >;
   using MeshType                   = typename InitializerType::MeshType;
   using MeshTraitsType            = typename MeshType::MeshTraitsType;

   using GlobalIndexType            = typename MeshTraits< MeshConfig >::GlobalIndexType;
   using LocalIndexType             = typename MeshTraits< MeshConfig >::LocalIndexType;
@@ -118,8 +113,9 @@ class EntityInitializerLayer< MeshConfig,
   using SubentityTopology          = typename SubentityTraitsType::EntityTopology;
   using SuperentityTraitsType      = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >;
   using SuperentityTopology        = typename SuperentityTraitsType::EntityTopology;
   using SubentitySeedsCreatorType  = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >;
   using SubentitySeedsCreatorType  = SubentitySeedsCreator< MeshConfig, SuperentityTopology, SubdimensionTag >;
   using SuperentityMatrixType      = typename MeshTraits< MeshConfig >::SuperentityMatrixType;
   using NeighborCountsArray        = typename MeshTraitsType::NeighborCountsArray;

public:
   static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh )
@@ -128,8 +124,16 @@ public:

      const GlobalIndexType subentitiesCount = mesh.template getEntitiesCount< SubdimensionTag::value >();
      const GlobalIndexType superentitiesCount = mesh.template getEntitiesCount< SuperdimensionTag::value >();

      if( SubdimensionTag::value > 0 )
         meshInitializer.template initSubentityMatrix< SuperdimensionTag::value, SubdimensionTag::value >( superentitiesCount, subentitiesCount );
      {
         NeighborCountsArray capacities( superentitiesCount );

         for( GlobalIndexType superentityIndex = 0; superentityIndex < capacities.getSize(); superentityIndex++ )
            capacities[ superentityIndex ] = SubentitySeedsCreatorType::getSubentitiesCount( meshInitializer.template getSubvertices< SuperdimensionTag::value >( superentityIndex ) );

         meshInitializer.template initSubentityMatrix< SuperdimensionTag::value, SubdimensionTag::value >( capacities, subentitiesCount );
      }

      // counter for superentities of each subentity
      auto& superentitiesCounts = meshInitializer.template getSuperentitiesCountsArray< SubdimensionTag::value, SuperdimensionTag::value >();
@@ -138,6 +142,7 @@ public:

      for( GlobalIndexType superentityIndex = 0; superentityIndex < superentitiesCount; superentityIndex++ )
      {
         //TODO: try to pass capacitites in to avoid calculating number of non-zero elements in a row
         auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.template getSubvertices< SuperdimensionTag::value >( superentityIndex ) );
         for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ )
         {
@@ -194,12 +199,14 @@ class EntityInitializerLayer< MeshConfig,
                                            typename SuperdimensionTag::Decrement >;
   using InitializerType           = Initializer< MeshConfig >;
   using MeshType                  = typename InitializerType::MeshType;
   using MeshTraitsType            = typename MeshType::MeshTraitsType;

   using GlobalIndexType           = typename MeshTraits< MeshConfig >::GlobalIndexType;
   using LocalIndexType            = typename MeshTraits< MeshConfig >::LocalIndexType;
   using SuperentityTraitsType     = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >;
   using SuperentityTopology       = typename SuperentityTraitsType::EntityTopology;
   using SubentitySeedsCreatorType = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >;
   using SubentitySeedsCreatorType = SubentitySeedsCreator< MeshConfig, SuperentityTopology, SubdimensionTag >;
   using NeighborCountsArray       = typename MeshTraitsType::NeighborCountsArray;

public:
   static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh )
@@ -209,7 +216,14 @@ public:
      const GlobalIndexType subentitiesCount = mesh.template getEntitiesCount< SubdimensionTag::value >();
      const GlobalIndexType superentitiesCount = mesh.template getEntitiesCount< SuperdimensionTag::value >();
      if( SubdimensionTag::value > 0 )
         meshInitializer.template initSubentityMatrix< SuperdimensionTag::value, SubdimensionTag::value >( superentitiesCount, subentitiesCount );
      {
         NeighborCountsArray capacities( superentitiesCount );

         for( GlobalIndexType superentityIndex = 0; superentityIndex < capacities.getSize(); superentityIndex++ )
            capacities[ superentityIndex ] = SubentitySeedsCreatorType::getSubentitiesCount( meshInitializer.template getSubvertices< SuperdimensionTag::value >( superentityIndex ) );

         meshInitializer.template initSubentityMatrix< SuperdimensionTag::value, SubdimensionTag::value >( capacities, subentitiesCount );
      }
         
      for( GlobalIndexType superentityIndex = 0;
           superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >();
@@ -259,7 +273,7 @@ class EntityInitializerLayer< MeshConfig,
   using SubentityTopology          = typename SubentityTraitsType::EntityTopology;
   using SuperentityTraitsType      = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >;
   using SuperentityTopology        = typename SuperentityTraitsType::EntityTopology;
   using SubentitySeedsCreatorType  = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >;
   using SubentitySeedsCreatorType  = SubentitySeedsCreator< MeshConfig, SuperentityTopology, SubdimensionTag >;
   using SuperentityMatrixType      = typename MeshTraits< MeshConfig >::SuperentityMatrixType;

public:
+68 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#pragma once

#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
#include <TNL/Meshes/Topologies/Polygon.h>

namespace TNL {
namespace Meshes {
@@ -107,6 +108,53 @@ class EntitySeed< MeshConfig, Topologies::Vertex >
      IdArrayType cornerIds;
};

template< typename MeshConfig >
class EntitySeed< MeshConfig, Topologies::Polygon >
{
   using MeshConfigTraits = MeshTraits< MeshConfig >;

public:
   using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType;
   using LocalIndexType  = typename MeshTraits< MeshConfig >::LocalIndexType;
   using DeviceType      = typename MeshTraits< MeshConfig >::DeviceType;
   using IdArrayType     = Containers::Array< GlobalIndexType, DeviceType, LocalIndexType >;
   using HashType        = EntitySeedHash< EntitySeed >;
   using KeyEqual        = EntitySeedEq< EntitySeed >;

   void setCornersCount( const LocalIndexType& cornersCount )
   {
      TNL_ASSERT_GE( cornersCount, 3, "cornersCount must be at least 3" );
      this->cornerIds.setSize( cornersCount );
   }

   LocalIndexType getCornersCount() const
   {
      return this->cornerIds.getSize();
   }

   void setCornerId( const LocalIndexType& cornerIndex, const GlobalIndexType& pointIndex )
   {
      TNL_ASSERT_GE( cornerIndex, 0, "corner index must be non-negative" );
      TNL_ASSERT_LT( cornerIndex, getCornersCount(), "corner index is out of bounds" );
      TNL_ASSERT_GE( pointIndex, 0, "point index must be non-negative" );

      this->cornerIds[ cornerIndex ] = pointIndex;
   }

   IdArrayType& getCornerIds()
   {
      return cornerIds;
   }

   const IdArrayType& getCornerIds() const
   {
      return cornerIds;
   }

private:
   IdArrayType cornerIds;
};

template< typename MeshConfig, typename EntityTopology >
std::ostream& operator<<( std::ostream& str, const EntitySeed< MeshConfig, EntityTopology >& e )
{
@@ -132,6 +180,26 @@ struct EntitySeedHash
   }
};

template< typename MeshConfig >
struct EntitySeedHash< EntitySeed< MeshConfig, Topologies::Polygon > >
{
   using Seed = EntitySeed< MeshConfig, Topologies::Polygon >;

   std::size_t operator()( const Seed& seed ) const
   {
      using LocalIndexType = typename Seed::LocalIndexType;
      using GlobalIndexType = typename Seed::GlobalIndexType;

      // Note that we must use an associative function to combine the hashes,
      // because we *want* to ignore the order of the corner IDs.
      std::size_t hash = 0;
      for( LocalIndexType i = 0; i < seed.getCornersCount(); i++ )
//         hash ^= std::hash< GlobalIndexType >{}( seed.getCornerIds()[ i ] );
         hash += std::hash< GlobalIndexType >{}( seed.getCornerIds()[ i ] );
      return hash;
   }
};

template< typename EntitySeed >
struct EntitySeedEq
{
+23 −12
Original line number Diff line number Diff line
@@ -80,7 +80,10 @@ class Initializer
      using CellSeedArrayType = typename MeshTraitsType::CellSeedArrayType;
      using GlobalIndexType   = typename MeshTraitsType::GlobalIndexType;
      using LocalIndexType    = typename MeshTraitsType::LocalIndexType;
      using NeighborCountsArray = typename MeshTraitsType::NeighborCountsArray;

      template< int Dimension, int Subdimension >
      using SubentityMatrixRowsCapacitiesType = typename MeshTraitsType::template SubentityMatrixType< Dimension, Subdimension >::RowsCapacitiesType;

      // The points and cellSeeds arrays will be reset when not needed to save memory.
      void createMesh( PointArrayType& points,
@@ -97,19 +100,14 @@ class Initializer
      }

      template< int Dimension, int Subdimension >
      void initSubentityMatrix( const GlobalIndexType entitiesCount, GlobalIndexType subentitiesCount = 0 )
      void initSubentityMatrix( const NeighborCountsArray& capacities, GlobalIndexType subentitiesCount = 0 )
      {
         if( Subdimension == 0 )
            subentitiesCount = mesh->template getEntitiesCount< 0 >();
         auto& matrix = mesh->template getSubentitiesMatrix< Dimension, Subdimension >();
         matrix.setDimensions( entitiesCount, subentitiesCount );
         using EntityTraitsType    = typename MeshTraitsType::template EntityTraits< Dimension >;
         using EntityTopology      = typename EntityTraitsType::EntityTopology;
         using SubentityTraitsType = typename MeshTraitsType::template SubentityTraits< EntityTopology, Subdimension >;
         constexpr int count = SubentityTraitsType::count;
         typename std::decay_t<decltype(matrix)>::RowsCapacitiesType capacities( entitiesCount );
         capacities.setValue( count );
         matrix.setDimensions( capacities.getSize(), subentitiesCount );
         matrix.setRowCapacities( capacities );
         mesh->template setSubentitiesCounts< Dimension, Subdimension >( capacities );
      }

      template< int Dimension >
@@ -171,6 +169,7 @@ class InitializerLayer< MeshConfig, typename MeshTraits< MeshConfig >::Dimension
   using InitializerType       = Initializer< MeshConfig >;
   using EntityInitializerType = EntityInitializer< MeshConfig, EntityTopology >;
   using CellSeedArrayType     = typename MeshTraitsType::CellSeedArrayType;
   using NeighborCountsArray   = typename MeshTraitsType::NeighborCountsArray;

   public:

@@ -178,7 +177,14 @@ class InitializerLayer< MeshConfig, typename MeshTraits< MeshConfig >::Dimension
      {
         //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl;
         initializer.template setEntitiesCount< DimensionTag::value >( cellSeeds.getSize() );
         initializer.template initSubentityMatrix< DimensionTag::value, 0 >( cellSeeds.getSize() );

         NeighborCountsArray capacities( cellSeeds.getSize() );

         for( LocalIndexType i = 0; i < capacities.getSize(); i++ )
            capacities[ i ] = cellSeeds[ i ].getCornersCount();

         initializer.template initSubentityMatrix< EntityTopology::dimension, 0 >( capacities );

         for( GlobalIndexType i = 0; i < cellSeeds.getSize(); i++ )
            EntityInitializerType::initEntity( i, cellSeeds[ i ], initializer );
         cellSeeds.reset();
@@ -212,12 +218,13 @@ class InitializerLayer
   using SeedType              = EntitySeed< MeshConfig, EntityTopology >;
   using SeedIndexedSet        = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedIndexedSetType;
   using SeedSet               = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedSetType;
   using NeighborCountsArray   = typename MeshTraitsType::NeighborCountsArray;

   public:

      GlobalIndexType getEntitiesCount( InitializerType& initializer, MeshType& mesh )
      {
         using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >;
         using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, typename MeshTraitsType::CellTopology, DimensionTag >;
         SeedSet seedSet;

         for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ )
@@ -241,9 +248,13 @@ class InitializerLayer
         //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl;
         const GlobalIndexType numberOfEntities = getEntitiesCount( initializer, mesh );
         initializer.template setEntitiesCount< DimensionTag::value >( numberOfEntities );
         EntityInitializerType::initSubvertexMatrix( numberOfEntities, initializer );

         using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >;
         NeighborCountsArray capacities( numberOfEntities );
         int vertexCount = MeshTraitsType::template SubentityTraits< EntityTopology, 0 >::count;
         capacities.setValue( vertexCount );
         initializer.template initSubentityMatrix< EntityTopology::dimension, 0 >( capacities );

         using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, typename MeshTraitsType::CellTopology, DimensionTag >;
         for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ )
         {
            auto subentitySeeds = SubentitySeedsCreator::create( initializer.template getSubvertices< MeshType::getMeshDimension() >( i ) );
+102 −9
Original line number Diff line number Diff line
@@ -18,20 +18,20 @@

#include <TNL/Algorithms/staticFor.h>
#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
#include <TNL/Meshes/Topologies/Polygon.h>

namespace TNL {
namespace Meshes {

template< typename MeshConfig,
          typename EntityDimensionTag,
          typename EntityTopology,
          typename SubentityDimensionTag >
class SubentitySeedsCreator
{
   using MeshTraitsType        = MeshTraits< MeshConfig >;
   using LocalIndexType        = typename MeshTraitsType::LocalIndexType;
   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< EntityDimensionTag::value >;
   using EntityTopology        = typename EntityTraitsType::EntityTopology;
   using SubvertexAccessorType = typename MeshTraitsType::SubentityMatrixType::RowView;
   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< EntityTopology::dimension >;
   using SubvertexAccessorType = typename MeshTraitsType::template SubentityMatrixType< EntityTopology::dimension, SubentityDimensionTag::value >::RowView;
   using SubentityTraits       = typename MeshTraitsType::template SubentityTraits< EntityTopology, SubentityDimensionTag::value >;
   using SubentityTopology     = typename SubentityTraits::SubentityTopology;

@@ -57,17 +57,66 @@ public:

      return subentitySeeds;
   }

   static LocalIndexType getSubentitiesCount( const SubvertexAccessorType& subvertices )
   {
      return SubentityTraits::count;
   }
};

template< typename MeshConfig >
class SubentitySeedsCreator< MeshConfig, Topologies::Polygon, DimensionTag< 1 > >
{
   using MeshTraitsType        = MeshTraits< MeshConfig >;
   using DeviceType            = typename MeshTraitsType::DeviceType;
   using LocalIndexType        = typename MeshTraitsType::LocalIndexType;
   using EntityTopology        = Topologies::Polygon;
   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< EntityTopology::dimension >;
   using SubvertexAccessorType = typename MeshTraitsType::template SubentityMatrixType< EntityTopology::dimension, 1 >::RowView;
   using SubentityTraits       = typename MeshTraitsType::template SubentityTraits< EntityTopology, 1 >;
   using SubentityTopology     = typename SubentityTraits::SubentityTopology;

public:
   using SubentitySeed = EntitySeed< MeshConfig, SubentityTopology >;
   using SubentitySeedArray = Containers::Array< SubentitySeed, DeviceType, LocalIndexType >;
   
   static SubentitySeedArray create( const SubvertexAccessorType& subvertices )
   {
      SubentitySeedArray seeds;
      LocalIndexType verticesCount = getVerticesCount( subvertices );
      seeds.setSize( verticesCount );

      for( LocalIndexType i = 0; i < seeds.getSize(); i++ )
      {
         SubentitySeed& seed = seeds[ i ];
         seed.setCornerId( 0, subvertices.getColumnIndex( i ) );
         seed.setCornerId( 1, subvertices.getColumnIndex( (i + 1) % verticesCount ) );
      }

      return seeds;
   }

   static LocalIndexType getSubentitiesCount( const SubvertexAccessorType& subvertices )
   {
      return getVerticesCount( subvertices );
   }
private:
   static LocalIndexType getVerticesCount( const SubvertexAccessorType& subvertices )
   {
      LocalIndexType i;
      for( i = 0; i < subvertices.getSize() && subvertices.getColumnIndex( i ) >= 0; i++ ) {}
      return i;
   }
};

template< typename MeshConfig,
          typename EntityDimensionTag >
class SubentitySeedsCreator< MeshConfig, EntityDimensionTag, DimensionTag< 0 > >
          typename EntityTopology >
class SubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag< 0 > >
{
   using MeshTraitsType        = MeshTraits< MeshConfig >;
   using LocalIndexType        = typename MeshTraitsType::LocalIndexType;
   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< EntityDimensionTag::value >;
   using EntityTopology        = typename EntityTraitsType::EntityTopology;
   using SubvertexAccessorType = typename MeshTraitsType::SubentityMatrixType::RowView;
   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< EntityTopology::dimension >;
   using SubvertexAccessorType = typename MeshTraitsType::template SubentityMatrixType< EntityTopology::dimension, 0 >::RowView;
   using SubentityTraits       = typename MeshTraitsType::template SubentityTraits< EntityTopology, 0 >;
   using SubentityTopology     = typename SubentityTraits::SubentityTopology;

@@ -81,6 +130,50 @@ public:
         seeds[ i ].setCornerId( 0, subvertices.getColumnIndex( i ) );
      return seeds;
   }

   static LocalIndexType getSubentitiesCount( const SubvertexAccessorType& subvertices )
   {
      return subvertices.getSize();
   }
};

template< typename MeshConfig >
class SubentitySeedsCreator< MeshConfig, Topologies::Polygon, DimensionTag< 0 > >
{
   using MeshTraitsType        = MeshTraits< MeshConfig >;
   using DeviceType            = typename MeshTraitsType::DeviceType;
   using LocalIndexType        = typename MeshTraitsType::LocalIndexType;
   using EntityTopology        = Topologies::Polygon;
   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< EntityTopology::dimension >;
   using SubvertexAccessorType = typename MeshTraitsType::template SubentityMatrixType< EntityTopology::dimension, 0 >::RowView;
   using SubentityTraits       = typename MeshTraitsType::template SubentityTraits< EntityTopology, 0 >;
   using SubentityTopology     = typename SubentityTraits::SubentityTopology;

public:
   using SubentitySeedArray = Containers::Array< EntitySeed< MeshConfig, SubentityTopology >, DeviceType, LocalIndexType >;

   static SubentitySeedArray create( const SubvertexAccessorType& subvertices )
   {
      SubentitySeedArray seeds;
      seeds.setSize( getVerticesCount( subvertices ) );

      for( LocalIndexType i = 0; i < seeds.getSize(); i++ )
         seeds[ i ].setCornerId( 0, subvertices.getColumnIndex( i ) );

      return seeds;
   }

   static LocalIndexType getSubentitiesCount( const SubvertexAccessorType& subvertices )
   {
      return getVerticesCount( subvertices );
   }
private:
   static LocalIndexType getVerticesCount( const SubvertexAccessorType& subvertices )
   {
      LocalIndexType i;
      for( i = 0; i < subvertices.getSize() && subvertices.getColumnIndex( i ) >= 0; i++ ) {}
      return i;
   }
};

} // namespace Meshes