5#ifndef DUNE_GEOMETRY_REFERENCEELEMENTIMPLEMENTATION_HH 
    6#define DUNE_GEOMETRY_REFERENCEELEMENTIMPLEMENTATION_HH 
   20#include <dune/common/hybridutilities.hh> 
   22#include <dune/common/iteratorrange.hh> 
   25#include <dune/geometry/referenceelement.hh> 
   42      template< 
class ctype, 
int dim >
 
   43      class ReferenceElementContainer;
 
   46    template< 
class ctype, 
int dim >
 
   47    struct ReferenceElements;
 
   54      using Dune::Impl::isPrism;
 
   55      using Dune::Impl::isPyramid;
 
   56      using Dune::Impl::baseTopologyId;
 
   57      using Dune::Impl::prismConstruction;
 
   58      using Dune::Impl::pyramidConstruction;
 
   59      using Dune::Impl::numTopologies;
 
   62      unsigned int size ( 
unsigned int topologyId, 
int dim, 
int codim );
 
   73      unsigned int subTopologyId ( 
unsigned int topologyId, 
int dim, 
int codim, 
unsigned int i );
 
   80      void subTopologyNumbering ( 
unsigned int topologyId, 
int dim, 
int codim, 
unsigned int i, 
int subcodim,
 
   81                                  unsigned int *beginOut, 
unsigned int *endOut );
 
   89      template< 
class ct, 
int cdim >
 
   91      checkInside ( 
unsigned int topologyId, 
int dim, 
const FieldVector< ct, cdim > &x, ct tolerance, ct factor = ct( 1 ) )
 
   93        assert( (dim >= 0) && (dim <= cdim) );
 
   94        assert( topologyId < numTopologies( dim ) );
 
   98            const ct baseFactor = (isPrism( topologyId, dim ) ? factor : factor - x[ dim-1 ]);
 
   99            if( (x[ dim-1 ] > -tolerance) && (factor - x[ dim-1 ] > -tolerance) )
 
  100              return checkInside< ct, cdim >( baseTopologyId( topologyId, dim ), dim-1, x, tolerance, baseFactor );
 
  113      template< 
class ct, 
int cdim >
 
  115      referenceCorners ( 
unsigned int topologyId, 
int dim, FieldVector< ct, cdim > *corners )
 
  117        assert( (dim >= 0) && (dim <= cdim) );
 
  118        assert( topologyId < numTopologies( dim ) );
 
  122            const unsigned int nBaseCorners
 
  123              = referenceCorners( baseTopologyId( topologyId, dim ), dim-1, corners );
 
  124            assert( nBaseCorners == 
size( baseTopologyId( topologyId, dim ), dim-1, dim-1 ) );
 
  125            if( isPrism( topologyId, dim ) )
 
  127                std::copy( corners, corners + nBaseCorners, corners + nBaseCorners );
 
  128                for( 
unsigned int i = 0; i < nBaseCorners; ++i )
 
  129                  corners[ i+nBaseCorners ][ dim-1 ] = ct( 1 );
 
  130                return 2*nBaseCorners;
 
  134                corners[ nBaseCorners ] = FieldVector< ct, cdim >( ct( 0 ) );
 
  135                corners[ nBaseCorners ][ dim-1 ] = ct( 1 );
 
  136                return nBaseCorners+1;
 
  141            *corners = FieldVector< ct, cdim >( ct( 0 ) );
 
  151      unsigned long referenceVolumeInverse ( 
unsigned int topologyId, 
int dim );
 
  154      inline ct referenceVolume ( 
unsigned int topologyId, 
int dim )
 
  156        return ct( 1 ) / ct( referenceVolumeInverse( topologyId, dim ) );
 
  164      template< 
class ct, 
int cdim >
 
  166      referenceOrigins ( 
unsigned int topologyId, 
int dim, 
int codim, FieldVector< ct, cdim > *origins )
 
  168        assert( (dim >= 0) && (dim <= cdim) );
 
  169        assert( topologyId < numTopologies( dim ) );
 
  170        assert( (codim >= 0) && (codim <= dim) );
 
  174            const unsigned int baseId = baseTopologyId( topologyId, dim );
 
  175            if( isPrism( topologyId, dim ) )
 
  177                const unsigned int n = (codim < dim ? referenceOrigins( baseId, dim-1, codim, origins ) : 0);
 
  178                const unsigned int m = referenceOrigins( baseId, dim-1, codim-1, origins+n );
 
  179                for( 
unsigned int i = 0; i < m; ++i )
 
  181                    origins[ n+m+i ] = origins[ n+i ];
 
  182                    origins[ n+m+i ][ dim-1 ] = ct( 1 );
 
  188                const unsigned int m = referenceOrigins( baseId, dim-1, codim-1, origins );
 
  191                    origins[ m ] = FieldVector< ct, cdim >( ct( 0 ) );
 
  192                    origins[ m ][ dim-1 ] = ct( 1 );
 
  196                  return m+referenceOrigins( baseId, dim-1, codim, origins+m );
 
  201            origins[ 0 ] = FieldVector< ct, cdim >( ct( 0 ) );
 
  211      template< 
class ct, 
int cdim, 
int mydim >
 
  213      referenceEmbeddings ( 
unsigned int topologyId, 
int dim, 
int codim,
 
  214                            FieldVector< ct, cdim > *origins,
 
  215                            FieldMatrix< ct, mydim, cdim > *jacobianTransposeds )
 
  217        assert( (0 <= codim) && (codim <= dim) && (dim <= cdim) );
 
  218        assert( (dim - codim <= mydim) && (mydim <= cdim) );
 
  219        assert( topologyId < numTopologies( dim ) );
 
  221        if( (0 < codim) && (codim <= dim) )
 
  223            const unsigned int baseId = baseTopologyId( topologyId, dim );
 
  224            if( isPrism( topologyId, dim ) )
 
  226                const unsigned int n = (codim < dim ? referenceEmbeddings( baseId, dim-1, codim, origins, jacobianTransposeds ) : 0);
 
  227                for( 
unsigned int i = 0; i < n; ++i )
 
  228                  jacobianTransposeds[ i ][ dim-codim-1 ][ dim-1 ] = ct( 1 );
 
  230                const unsigned int m = referenceEmbeddings( baseId, dim-1, codim-1, origins+n, jacobianTransposeds+n );
 
  231                std::copy( origins+n, origins+n+m, origins+n+m );
 
  232                std::copy( jacobianTransposeds+n, jacobianTransposeds+n+m, jacobianTransposeds+n+m );
 
  233                for( 
unsigned int i = 0; i < m; ++i )
 
  234                  origins[ n+m+i ][ dim-1 ] = ct( 1 );
 
  240                const unsigned int m = referenceEmbeddings( baseId, dim-1, codim-1, origins, jacobianTransposeds );
 
  243                    origins[ m ] = FieldVector< ct, cdim >( ct( 0 ) );
 
  244                    origins[ m ][ dim-1 ] = ct( 1 );
 
  245                    jacobianTransposeds[ m ] = FieldMatrix< ct, mydim, cdim >( ct( 0 ) );
 
  248                else if( codim < dim )
 
  250                    const unsigned int n = referenceEmbeddings( baseId, dim-1, codim, origins+m, jacobianTransposeds+m );
 
  251                    for( 
unsigned int i = 0; i < n; ++i )
 
  253                        for( 
int k = 0; k < dim-1; ++k )
 
  254                          jacobianTransposeds[ m+i ][ dim-codim-1 ][ k ] = -origins[ m+i ][ k ];
 
  255                        jacobianTransposeds[ m+i ][ dim-codim-1 ][ dim-1 ] = ct( 1 );
 
  261        else if( codim == 0 )
 
  263            origins[ 0 ] = FieldVector< ct, cdim >( ct( 0 ) );
 
  264            jacobianTransposeds[ 0 ] = FieldMatrix< ct, mydim, cdim >( ct( 0 ) );
 
  265            for( 
int k = 0; k < dim; ++k )
 
  266              jacobianTransposeds[ 0 ][ k ][ k ] = ct( 1 );
 
  280      template< 
class ct, 
int cdim >
 
  282      referenceIntegrationOuterNormals ( 
unsigned int topologyId, 
int dim,
 
  283                                         const FieldVector< ct, cdim > *origins,
 
  284                                         FieldVector< ct, cdim > *normals )
 
  286        assert( (dim > 0) && (dim <= cdim) );
 
  287        assert( topologyId < numTopologies( dim ) );
 
  291            const unsigned int baseId = baseTopologyId( topologyId, dim );
 
  292            if( isPrism( topologyId, dim ) )
 
  294                const unsigned int numBaseFaces
 
  295                  = referenceIntegrationOuterNormals( baseId, dim-1, origins, normals );
 
  297                for( 
unsigned int i = 0; i < 2; ++i )
 
  299                    normals[ numBaseFaces+i ] = FieldVector< ct, cdim >( ct( 0 ) );
 
  300                    normals[ numBaseFaces+i ][ dim-1 ] = ct( 2*
int( i )-1 );
 
  303                return numBaseFaces+2;
 
  307                normals[ 0 ] = FieldVector< ct, cdim >( ct( 0 ) );
 
  308                normals[ 0 ][ dim-1 ] = ct( -1 );
 
  310                const unsigned int numBaseFaces
 
  311                  = referenceIntegrationOuterNormals( baseId, dim-1, origins+1, normals+1 );
 
  312                for( 
unsigned int i = 1; i <= numBaseFaces; ++i )
 
  313                  normals[ i ][ dim-1 ] = normals[ i ]*origins[ i ];
 
  315                return numBaseFaces+1;
 
  320            for( 
unsigned int i = 0; i < 2; ++i )
 
  322                normals[ i ] = FieldVector< ct, cdim >( ct( 0 ) );
 
  323                normals[ i ][ 0 ] = ct( 2*
int( i )-1 );
 
  330      template< 
class ct, 
int cdim >
 
  332      referenceIntegrationOuterNormals ( 
unsigned int topologyId, 
int dim,
 
  333                                         FieldVector< ct, cdim > *normals )
 
  335        assert( (dim > 0) && (dim <= cdim) );
 
  337        FieldVector< ct, cdim > *origins
 
  338          = 
new FieldVector< ct, cdim >[ 
size( topologyId, dim, 1 ) ];
 
  339        referenceOrigins( topologyId, dim, 1, origins );
 
  341        const unsigned int numFaces
 
  342          = referenceIntegrationOuterNormals( topologyId, dim, origins, normals );
 
  343        assert( numFaces == 
size( topologyId, dim, 1 ) );
 
  375    template< 
class ctype_, 
int dim >
 
  376    class ReferenceElementImplementation
 
  382      using ctype = ctype_;
 
  385      using CoordinateField = ctype;
 
  391      static constexpr int dimension = dim;
 
  394      typedef ctype Volume;
 
  398      friend class Impl::ReferenceElementContainer< ctype, dim >;
 
  400      struct SubEntityInfo;
 
  402      template< 
int codim > 
struct CreateGeometries;
 
  406      template< 
int codim >
 
  410        typedef AffineGeometry< ctype, dim-codim, dim > Geometry;
 
  414      ReferenceElementImplementation ( 
const ReferenceElementImplementation& ) = 
delete;
 
  417      ReferenceElementImplementation& operator= ( 
const ReferenceElementImplementation& ) = 
delete;
 
  420      ReferenceElementImplementation () = 
default;
 
  426      int size ( 
int c )
 const 
  428        assert( (c >= 0) && (c <= dim) );
 
  429        return info_[ c ].size();
 
  443      int size ( 
int i, 
int c, 
int cc )
 const 
  445        assert( (i >= 0) && (i < 
size( c )) );
 
  446        return info_[ c ][ i ].size( cc );
 
  462      int subEntity ( 
int i, 
int c, 
int ii, 
int cc )
 const 
  464        assert( (i >= 0) && (i < 
size( c )) );
 
  465        return info_[ c ][ i ].number( ii, cc );
 
  483      auto subEntities ( 
int i, 
int c, 
int cc )
 const 
  485        assert( (i >= 0) && (i < 
size( c )) );
 
  486        return info_[ c ][ i ].numbers( cc );
 
  499        assert( (i >= 0) && (i < 
size( c )) );
 
  500        return info_[ c ][ i ].type();
 
  504      const GeometryType &type ()
 const { 
return type( 0, 0 ); }
 
  515      const Coordinate &position( 
int i, 
int c )
 const 
  517        assert( (c >= 0) && (c <= dim) );
 
  518        return baryCenters_[ c ][ i ];
 
  528      bool checkInside ( 
const Coordinate &local )
 const 
  530        const ctype tolerance = ctype( 64 ) * std::numeric_limits< ctype >::epsilon();
 
  531        return Impl::template checkInside< ctype, dim >( type().
id(), dim, local, tolerance );
 
  545      template< 
int codim >
 
  546      typename Codim< codim >::Geometry geometry ( 
int i )
 const 
  548        return std::get< codim >( geometries_ )[ i ];
 
  552      Volume volume ()
 const 
  564      const Coordinate &integrationOuterNormal ( 
int face )
 const 
  566        assert( (face >= 0) && (face < 
int( integrationNormals_.size() )) );
 
  567        return integrationNormals_[ face ];
 
  571      void initialize ( 
unsigned int topologyId )
 
  573        assert( topologyId < Impl::numTopologies( dim ) );
 
  576        for( 
int codim = 0; codim <= dim; ++codim )
 
  578            const unsigned int size = Impl::size( topologyId, dim, codim );
 
  579            info_[ codim ].resize( 
size );
 
  580            for( 
unsigned int i = 0; i < 
size; ++i )
 
  581              info_[ codim ][ i ].initialize( topologyId, codim, i );
 
  585        const unsigned int numVertices = 
size( dim );
 
  586        baryCenters_[ dim ].resize( numVertices );
 
  587        Impl::referenceCorners( topologyId, dim, &(baryCenters_[ dim ][ 0 ]) );
 
  590        for( 
int codim = 0; codim < dim; ++codim )
 
  592            baryCenters_[ codim ].resize( 
size(codim) );
 
  593            for( 
int i = 0; i < 
size( codim ); ++i )
 
  595                baryCenters_[ codim ][ i ] = Coordinate( ctype( 0 ) );
 
  596                const unsigned int numCorners = 
size( i, codim, dim );
 
  597                for( 
unsigned int j = 0; j < numCorners; ++j )
 
  598                  baryCenters_[ codim ][ i ] += baryCenters_[ dim ][ subEntity( i, codim, j, dim ) ];
 
  599                baryCenters_[ codim ][ i ] *= ctype( 1 ) / ctype( numCorners );
 
  604        volume_ = Impl::template referenceVolume< ctype >( topologyId, dim );
 
  609            integrationNormals_.resize( 
size( 1 ) );
 
  610            Impl::referenceIntegrationOuterNormals( topologyId, dim, &(integrationNormals_[ 0 ]) );
 
  614        Hybrid::forEach( std::make_index_sequence< dim+1 >{}, [ & ]( 
auto i ){ CreateGeometries< i >::apply( *
this, geometries_ ); } );
 
  617      template< 
int... codim >
 
  618      static std::tuple< std::vector< typename Codim< codim >::Geometry >... >
 
  619      makeGeometryTable ( std::integer_sequence< int, codim... > );
 
  622      typedef decltype( makeGeometryTable( std::make_integer_sequence< int, dim+1 >() ) ) GeometryTable;
 
  627      std::vector< Coordinate > baryCenters_[ dim+1 ];
 
  628      std::vector< Coordinate > integrationNormals_;
 
  631      GeometryTable geometries_;
 
  633      std::vector< SubEntityInfo > info_[ dim+1 ];
 
  637    template< 
class ctype, 
int dim >
 
  638    struct ReferenceElementImplementation< ctype, dim >::SubEntityInfo
 
  643      static constexpr std::size_t maxSubEntityCount()
 
  645        std::size_t maxCount=0;
 
  646        for(std::size_t codim=0; codim<=dim; ++codim)
 
  647          maxCount = 
std::max(maxCount, 
binomial(std::size_t(dim),codim)*(1 << codim));
 
  651      using SubEntityFlags = std::bitset<maxSubEntityCount()>;
 
  660        using iterator = Base::iterator;
 
  661        using const_iterator = Base::const_iterator;
 
  663        SubEntityRange(
const iterator& begin, 
const iterator& end, 
const SubEntityFlags& 
contains) :
 
  671          containsPtr_(nullptr),
 
  675        std::size_t 
size()
 const 
  682          return (*containsPtr_)[i];
 
  686        const SubEntityFlags* containsPtr_;
 
  694        : numbering_( nullptr )
 
  696        std::fill( offset_.begin(), offset_.end(), 0 );
 
  699      SubEntityInfo ( 
const SubEntityInfo &other )
 
  700        : offset_( other.offset_ ),
 
  701          type_( other.type_ ),
 
  702          containsSubentity_( other.containsSubentity_ )
 
  704        numbering_ = allocate();
 
  705        std::copy( other.numbering_, other.numbering_ + capacity(), numbering_ );
 
  708      ~SubEntityInfo () { deallocate( numbering_ ); }
 
  710      const SubEntityInfo &operator= ( 
const SubEntityInfo &other )
 
  713        offset_ = other.offset_;
 
  715        deallocate( numbering_ );
 
  716        numbering_ = allocate();
 
  717        std::copy( other.numbering_, other.numbering_ + capacity(), numbering_ );
 
  719        containsSubentity_ = other.containsSubentity_;
 
  724      int size ( 
int cc )
 const 
  726        assert( (cc >= 0) && (cc <= dim) );
 
  727        return (offset_[ cc+1 ] - offset_[ cc ]);
 
  730      int number ( 
int ii, 
int cc )
 const 
  732        assert( (ii >= 0) && (ii < 
size( cc )) );
 
  733        return numbering_[ offset_[ cc ] + ii ];
 
  736      auto numbers ( 
int cc )
 const 
  738        return SubEntityRange( numbering_ + offset_[ cc ], numbering_ + offset_[ cc+1 ], containsSubentity_[cc]);
 
  743      void initialize ( 
unsigned int topologyId, 
int codim, 
unsigned int i )
 
  745        const unsigned int subId = Impl::subTopologyId( topologyId, dim, codim, i );
 
  749        for( 
int cc = 0; cc <= codim; ++cc )
 
  751        for( 
int cc = codim; cc <= dim; ++cc )
 
  752          offset_[ cc+1 ] = offset_[ cc ] + Impl::size( subId, dim-codim, cc-codim );
 
  755        deallocate( numbering_ );
 
  756        numbering_ = allocate();
 
  757        for( 
int cc = codim; cc <= dim; ++cc )
 
  758          Impl::subTopologyNumbering( topologyId, dim, codim, i, cc-codim, numbering_+offset_[ cc ], numbering_+offset_[ cc+1 ] );
 
  761        for(std::size_t cc=0; cc<= dim; ++cc)
 
  763          containsSubentity_[cc].reset();
 
  764          for(std::size_t idx=0; idx<std::size_t(
size(cc)); ++idx)
 
  765            containsSubentity_[cc][number(idx,cc)] = 
true;
 
  770      int codim ()
 const { 
return dim - type().dim(); }
 
  772      unsigned int *allocate () { 
return (capacity() != 0 ? 
new unsigned int[ capacity() ] : 
nullptr); }
 
  773      void deallocate ( 
unsigned int *ptr ) { 
delete[] ptr; }
 
  774      unsigned int capacity ()
 const { 
return offset_[ dim+1 ]; }
 
  777      unsigned int *numbering_;
 
  778      std::array< unsigned int, dim+2 > offset_;
 
  780      std::array< SubEntityFlags, dim+1> containsSubentity_;
 
  784    template< 
class ctype, 
int dim >
 
  785    template< 
int codim >
 
  786    struct ReferenceElementImplementation< ctype, dim >::CreateGeometries
 
  789      static typename ReferenceElements< ctype, dim-cc >::ReferenceElement
 
  790      subRefElement( 
const ReferenceElementImplementation< ctype, dim > &refElement, 
int i, std::integral_constant< int, cc > )
 
  796      subRefElement(
const ReferenceElementImplementation< ctype, dim > &refElement,
 
  797                    [[maybe_unused]] 
int i, std::integral_constant<int, 0>)
 
  802      static void apply ( 
const ReferenceElementImplementation< ctype, dim > &refElement, GeometryTable &geometries )
 
  804        const int size = refElement.size( codim );
 
  805        std::vector< FieldVector< ctype, dim > > origins( 
size );
 
  806        std::vector< FieldMatrix< ctype, dim - codim, dim > > jacobianTransposeds( 
size );
 
  807        Impl::referenceEmbeddings( refElement.type().id(), dim, codim, &(origins[ 0 ]), &(jacobianTransposeds[ 0 ]) );
 
  809        std::get< codim >( geometries ).reserve( 
size );
 
  810        for( 
int i = 0; i < 
size; ++i )
 
  812            typename Codim< codim >::Geometry geometry( subRefElement( refElement, i, std::integral_constant< int, codim >() ), origins[ i ], jacobianTransposeds[ i ] );
 
  813            std::get< codim >( geometries ).push_back( geometry );
 
An implementation of the Geometry interface for affine geometries.
 
Simple range between a begin and an end iterator.
Definition: iteratorrange.hh:26
 
GeometryType
Type representing VTK's entity geometry types.
Definition: common.hh:132
 
Implements a matrix constructed from a given type representing a field and compile-time given number ...
 
Implements a vector constructed from a given type representing a field and a compile-time given size.
 
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:257
 
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:485
 
Some useful basic math stuff.
 
Dune namespace.
Definition: alignedallocator.hh:13
 
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
 
static constexpr T binomial(const T &n, const T &k) noexcept
calculate the binomial coefficient n over k as a constexpr
Definition: math.hh:113
 
constexpr std::bool_constant<((II==value)||...)> contains(std::integer_sequence< T, II... >, std::integral_constant< T, value >)
Checks whether or not a given sequence contains a value.
Definition: integersequence.hh:137
 
typename Container::ReferenceElement ReferenceElement
The reference element type.
Definition: referenceelements.hh:146
 
static const ReferenceElement & general(const GeometryType &type)
get general reference elements
Definition: referenceelements.hh:156
 
A unique label for each type of element that can occur in a grid.
 
Traits for type conversions and type information.