5#ifndef DUNE_GEOMETRY_REFERENCEELEMENTIMPLEMENTATION_HH
6#define DUNE_GEOMETRY_REFERENCEELEMENTIMPLEMENTATION_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 );
497 const GeometryType &type (
int i,
int c )
const
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
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 ]) );
617 template<
int... codim >
631 GeometryTable geometries_;
637 template<
class ctype,
int dim >
638 struct ReferenceElementImplementation< ctype,
dim >::SubEntityInfo
651 using SubEntityFlags =
std::bitset<maxSubEntityCount()>;
661 using const_iterator = Base::const_iterator;
663 SubEntityRange(
const iterator&
begin,
const iterator&
end,
const SubEntityFlags&
contains) :
671 containsPtr_(nullptr),
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_ )
705 std::copy( other.numbering_, other.numbering_ + capacity(), numbering_ );
708 ~SubEntityInfo () {
deallocate( numbering_ ); }
710 const SubEntityInfo &
operator= (
const SubEntityInfo &other )
713 offset_ = other.offset_;
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]);
741 const GeometryType &type ()
const {
return type_; }
743 void initialize (
unsigned int topologyId,
int codim,
unsigned int i )
745 const unsigned int subId = Impl::subTopologyId( topologyId,
dim, codim, i );
746 type_ = GeometryType( subId,
dim-codim );
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 );
757 for(
int cc = codim; cc <=
dim; ++cc )
758 Impl::subTopologyNumbering( topologyId,
dim, codim, i, cc-codim, numbering_+offset_[ cc ], numbering_+offset_[ cc+1 ] );
763 containsSubentity_[cc].reset();
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_;
784 template<
class ctype,
int dim >
785 template<
int codim >
786 struct ReferenceElementImplementation< ctype,
dim >::CreateGeometries
789 static typename ReferenceElements< ctype,
dim-cc >::ReferenceElement
796 subRefElement(
const ReferenceElementImplementation< ctype, dim > &refElement,
802 static void apply (
const ReferenceElementImplementation< ctype, dim > &refElement, GeometryTable &geometries )
804 const int size = refElement.size( codim );
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 )
813 std::get< codim >( geometries ).push_back( geometry );
A unique label for each type of element that can occur in a grid.
An implementation of the Geometry interface for affine geometries.
SLList< T, A > & operator=(const SLList< T, A > &other)
static bool contains(const Type &attribute)
void deallocate(pointer p, std::size_t n)
constexpr void forEach(Range &&range, F &&f)
iterator(ParallelIndexSet< TG, TL, N > &indexSet, const Father &father)
static constexpr T binomial(const T &n, const T &k) noexcept
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