1#ifndef DUNE_FEM_SPACE_RAVIARTTHOMAS_LOCALINTERPOLATION_HH
2#define DUNE_FEM_SPACE_RAVIARTTHOMAS_LOCALINTERPOLATION_HH
17#include <dune/geometry/referenceelements.hh>
21#include <dune/fem/space/basisfunctionset/piolatransformation.hh>
36 template<
unsigned int,
class,
class,
int,
int >
struct RaviartThomasLocalFiniteElement;
47 template<
class LocalFiniteElement >
48 struct RaviartThomasLocalInterpolationBasis
50 static_assert( AlwaysFalse< LocalFiniteElement >::value,
51 "`RaviartThomasLocalInterpolationBasis` not implemented for your choice." );
56 template<
unsigned int id,
class Domain,
class Range,
int dim >
57 struct RaviartThomasLocalInterpolationBasis< RaviartThomasLocalFiniteElement< id, Domain, Range, dim, 0 > >
59 using DomainType = FieldVector< Domain, dim >;
60 using FaceDomainType = FieldVector< Domain, dim-1 >;
61 using RangeType = FieldVector< Range, dim >;
62 using RangeFieldType = Range;
64 RaviartThomasLocalInterpolationBasis () =
default;
65 explicit RaviartThomasLocalInterpolationBasis (
unsigned int orientations ) : orientations_( orientations ) {}
67 void trace (
int facet,
const FaceDomainType& x, std::vector< std::pair< int, RangeFieldType > >& basis )
const
69 assert( basis.size() >=
size( 1 ) );
70 basis[ 0 ] = std::make_pair( facet,
sign( facet ) );
73 void interior (
const DomainType& x, std::vector< std::pair< int, RangeType > >& basis )
const {}
75 constexpr auto size (
int codim )
const -> std::size_t { assert( codim < 2 );
return (codim == 0) ? 0 : 1; }
76 constexpr int order (
int codim )
const { assert( codim < 2 );
return (codim == 0) ? 0 : 1; }
79 auto sign (
int facet )
const -> RangeFieldType {
return (orientations_ & (1u << facet)) ? -1.0 : 1.0; }
81 unsigned int orientations_ = 0;
85 template<
class Domain,
class Range >
86 struct RaviartThomasLocalInterpolationBasis< RaviartThomasLocalFiniteElement<
Dune::
GeometryTypes::simplex(2).id(), Domain, Range, 2, 1 > >
88 using DomainType = FieldVector< Domain, 2 >;
89 using FaceDomainType = FieldVector< Domain, 1 >;
90 using RangeType = FieldVector< Range, 2 >;
91 using RangeFieldType = Range;
93 RaviartThomasLocalInterpolationBasis () =
default;
94 explicit RaviartThomasLocalInterpolationBasis (
unsigned int orientations ) : orientations_( orientations ) {}
96 void trace (
int facet,
const FaceDomainType& x, std::vector< std::pair< int, RangeFieldType > >& basis )
const
98 assert( basis.size() >=
size( 1 ) );
99 const RangeFieldType temp = (facet==1) ? 1.0 - 2.0*x : 2.0*x - 1.0;
100 basis[ 0 ] = std::make_pair( facet,
sign( facet ) );
101 basis[ 1 ] = std::make_pair( facet+3, temp );
104 void interior (
const DomainType& x, std::vector< std::pair< int, RangeType > >& basis )
const
106 assert( basis.size() >=
size( 0 ) );
107 basis[ 0 ] = std::make_pair( 6, RangeType{ 1.0, 0.0 } );
108 basis[ 1 ] = std::make_pair( 7, RangeType{ 0.0, 1.0 } );
111 constexpr auto size (
int codim )
const -> std::size_t { assert( codim < 2 );
return (codim == 0) ? 2 : 2; }
112 constexpr int order (
int codim )
const { assert( codim < 2 );
return (codim == 0) ? 8 : 4; }
116 auto sign (
int facet )
const -> RangeFieldType {
return (orientations_ & (1u << facet)) ? -1.0 : 1.0; }
118 unsigned int orientations_ = 0;
122 template<
class Domain,
class Range >
123 struct RaviartThomasLocalInterpolationBasis< RaviartThomasLocalFiniteElement<
Dune::
GeometryTypes::cube( 2 ).id(), Domain, Range, 2, 1 > >
125 using DomainType = FieldVector< Domain, 2 >;
126 using FaceDomainType = FieldVector< Domain, 1 >;
127 using RangeType = FieldVector< Range, 2 >;
128 using RangeFieldType = Range;
130 RaviartThomasLocalInterpolationBasis () =
default;
131 explicit RaviartThomasLocalInterpolationBasis (
unsigned int orientations ) : orientations_( orientations ) {}
133 void trace (
int facet,
const FaceDomainType& x, std::vector< std::pair< int, RangeFieldType > >& basis )
const
135 assert( basis.size() >=
size( 1 ) );
136 const RangeFieldType temp = (facet > 0 && facet < 3 ) ? 1.0 - 2.0*x : 2.0*x - 1.0;
137 basis[ 0 ] = std::make_pair( 2*facet ,
sign( facet ) );
138 basis[ 1 ] = std::make_pair( 2*facet+1, temp );
141 void interior (
const DomainType& x, std::vector< std::pair< int, RangeType > >& basis )
const
143 assert( basis.size() >=
size( 0 ) );
144 basis[ 0 ] = std::make_pair( 8, RangeType{ 1.0, 0.0 } );
145 basis[ 1 ] = std::make_pair( 9, RangeType{ 0.0, 1.0 } );
146 basis[ 2 ] = std::make_pair( 10, RangeType{ x[1], 0.0 } );
147 basis[ 3 ] = std::make_pair( 11, RangeType{ 0.0, x[0] } );
150 constexpr auto size (
int codim )
const -> std::size_t { assert( codim < 2 );
return (codim == 0) ? 4 : 2; }
151 constexpr int order (
int codim )
const { assert( codim < 2 );
return (codim == 0) ? 3 : 3; }
154 auto sign (
int facet )
const -> RangeFieldType {
return (orientations_ & (1u << facet)) ? -1.0 : 1.0; }
156 unsigned int orientations_ = 0;
160 template<
class Domain,
class Range >
161 struct RaviartThomasLocalInterpolationBasis< RaviartThomasLocalFiniteElement<
Dune::
GeometryTypes::cube( 3 ).id(), Domain, Range, 3, 1 > >
163 using DomainType = FieldVector< Domain, 3 >;
164 using FaceDomainType = FieldVector< Domain, 2 >;
165 using RangeType = FieldVector< Range, 3 >;
166 using RangeFieldType = Range;
168 RaviartThomasLocalInterpolationBasis () =
default;
169 explicit RaviartThomasLocalInterpolationBasis (
unsigned int orientations ) : orientations_( orientations ) {}
171 void trace (
int facet,
const FaceDomainType& x, std::vector< std::pair< int, RangeFieldType > >& basis )
const
173 assert( basis.size() >=
size( 1 ) );
175 const RangeFieldType tempX = 2.0*x[0] - 1.0;
176 const RangeFieldType tempY = 2.0*x[1] - 1.0;
178 basis[ 0 ] = std::make_pair( facet,
sign( facet ) );
184 basis[ 1 ] = std::make_pair( facet+ 6, tempX );
185 basis[ 2 ] = std::make_pair( facet+12, tempY );
186 basis[ 3 ] = std::make_pair( facet+18, tempX*tempY );
190 basis[ 1 ] = std::make_pair( facet+ 6, -tempX );
191 basis[ 2 ] = std::make_pair( facet+12, -tempY );
192 basis[ 3 ] = std::make_pair( facet+18, -tempX*tempY );
195 basis[ 1 ] = std::make_pair( facet+ 6, -tempX );
196 basis[ 2 ] = std::make_pair( facet+12, tempY );
197 basis[ 3 ] = std::make_pair( facet+18, -tempX*tempY );
200 basis[ 1 ] = std::make_pair( facet+ 6, tempX );
201 basis[ 2 ] = std::make_pair( facet+12, -tempY );
202 basis[ 3 ] = std::make_pair( facet+18, tempX*tempY );
207 void interior (
const DomainType& x, std::vector< std::pair< int, RangeType > >& basis )
const
209 assert( basis.size() >=
size( 0 ) );
210 basis[ 0 ] = std::make_pair( 24, RangeType{ 1.0, 0.0, 0.0 } );
211 basis[ 1 ] = std::make_pair( 25, RangeType{ 0.0, 1.0, 0.0 } );
212 basis[ 2 ] = std::make_pair( 26, RangeType{ 0.0, 0.0, 1.0 } );
213 basis[ 3 ] = std::make_pair( 27, RangeType{ x[1], 0.0, 0.0 } );
214 basis[ 4 ] = std::make_pair( 28, RangeType{ x[2], 0.0, 0.0 } );
215 basis[ 5 ] = std::make_pair( 29, RangeType{ 0.0, x[0], 0.0 } );
216 basis[ 6 ] = std::make_pair( 30, RangeType{ 0.0, x[2], 0.0 } );
217 basis[ 7 ] = std::make_pair( 31, RangeType{ 0.0, 0.0, x[0] } );
218 basis[ 8 ] = std::make_pair( 32, RangeType{ 0.0, 0.0, x[1] } );
219 basis[ 9 ] = std::make_pair( 33, RangeType{ x[1]*x[2], 0.0, 0.0 } );
220 basis[ 10 ] = std::make_pair( 34, RangeType{ 0.0, x[0]*x[2], 0.0 } );
221 basis[ 11 ] = std::make_pair( 35, RangeType{ 0.0, 0.0, x[0]*x[1] } );
224 constexpr auto size (
int codim )
const -> std::size_t { assert( codim < 2 );
return (codim == 0) ? 12 : 4; }
225 constexpr int order (
int codim )
const { assert( codim < 2 );
return (codim == 0) ? 3 : 3; }
228 auto sign (
int facet )
const -> RangeFieldType {
return (orientations_ & (1u << facet)) ? -1.0 : 1.0; }
230 unsigned int orientations_ = 0;
235 template<
class Gr
idPart,
class LocalFiniteElement,
int dimRange = Gr
idPart::dimension >
236 class RaviartThomasLocalInterpolation
239 using GridPartType = GridPart;
240 using LocalFiniteElementType = LocalFiniteElement;
242 using EntityType =
typename GridPartType::template Codim< 0 >::EntityType;
245 using LocalInterpolationBasisType = Impl::RaviartThomasLocalInterpolationBasis< LocalFiniteElementType >;
247 using Geometry =
typename EntityType::Geometry;
248 using ReferenceElementType = ReferenceElement< Geometry >;
250 using TransformationType = PiolaTransformation< Geometry, dimRange >;
251 using InverseTransformationType =
typename TransformationType::InverseTransformationType;
253 using RangeType =
typename LocalInterpolationBasisType::RangeType;
254 using RangeFieldType =
typename LocalInterpolationBasisType::RangeFieldType;
256 using VolumeQuadratures = QuadratureRules< typename Geometry::ctype, ReferenceElementType::dimension >;
257 using FaceQuadratures = QuadratureRules< RangeFieldType, ReferenceElementType::dimension-1 >;
260 explicit RaviartThomasLocalInterpolation (
const EntityType& entity )
261 : RaviartThomasLocalInterpolation( entity, 0, -1 )
264 RaviartThomasLocalInterpolation (
const EntityType& entity,
unsigned int orientations,
int order = -1 )
265 : geometry_( entity.geometry() ),
267 localBasis_( orientations ),
271 template<
class LocalFunction,
class LocalDofVector >
272 void interior (
const LocalFunction& lf, LocalDofVector& dofs )
const
274 if ( !hasInterior() )
278 interior_.resize( localBasis().
size( 0 ) );
280 for(
const auto& qp : getQuadrature( (order_ == -1) ? localBasis().order( 0 ) : order_ ) )
282 auto invPiola = inverseTransformation( qp.position() );
284 localBasis().interior( qp.position(), interior_ );
285 auto value = invPiola.apply( lf( qp.position() ) );
287 for (
const auto& base : interior_ )
288 dofs[ base.first ] += qp.weight() * (value * base.second);
292 template<
class LocalFunction,
class LocalDofVector >
293 void trace (
int facet,
const LocalFunction& lf, LocalDofVector& dofs )
const
296 traces_.resize( localBasis().
size( 1 ) );
301 for (
const auto& qp : getQuadrature( facet, (order_ == -1) ? localBasis().order( 1 ) : order_ ) )
303 auto p = embedding.global( qp.position() );
304 auto invPiola = inverseTransformation( p );
306 localBasis().trace( facet, qp.position(), traces_ );
307 auto value = invPiola.apply( lf( p ) );
309 for (
const auto& base : traces_ )
310 dofs[ base.first ] += qp.weight() * (value * normal) * base.second;
314 template<
class LocalFunction,
class LocalDofVector >
315 void interiorTrace (
int facet,
const LocalFunction& lf, LocalDofVector& dofs )
const
317 if ( !hasInterior() )
321 interior_.resize( localBasis().
size( 0 ) );
325 for(
const auto& qp : getQuadrature( facet, (order_ == -1) ? localBasis().order( 0 ) : order_ ) )
327 auto p = embedding.global( qp.position() );
328 auto invPiola = inverseTransformation( p );
330 localBasis().interior( p, interior_ );
331 auto value = invPiola.apply( lf( p ) );
333 for (
const auto& base : interior_ )
334 dofs[ base.first ] += qp.weight() * (value * base.second);
338 template<
class LocalFunction,
class LocalDofVector >
339 void operator() (
const LocalFunction& lf, LocalDofVector& dofs )
const
342 trace( facet, lf, dofs );
346 bool hasInterior ()
const {
return localBasis().size( 0 ) > 0; }
349 auto geometry () const -> const Geometry& {
return geometry_; }
350 auto referenceElement () const -> const ReferenceElementType& {
return refElement_; }
351 auto localBasis () const -> const LocalInterpolationBasisType& {
return localBasis_; }
353 template<
class Po
int >
354 auto transformation (
const Point& p )
const {
return TransformationType( geometry(), p ); }
356 template<
class Po
int >
357 auto inverseTransformation (
const Point& p )
const {
return InverseTransformationType( geometry(), p ); }
364 ReferenceElementType refElement_;
365 LocalInterpolationBasisType localBasis_;
368 mutable std::vector< std::pair< int, RangeFieldType > > traces_;
369 mutable std::vector< std::pair< int, RangeType > > interior_;
static const QuadratureRule & rule(const GeometryType &t, int p, QuadratureType::Enum qt=QuadratureType::GaussLegendre)
select the appropriate QuadratureRule for GeometryType t and order p
Definition: quadraturerules.hh:326
Implements a vector constructed from a given type representing a field and a compile-time given size.
unspecified value type referenceElement(T &&... t)
Returns a reference element for the objects t....
constexpr GeometryType cube(unsigned int dim)
Returns a GeometryType representing a hypercube of dimension dim.
Definition: type.hh:462
constexpr GeometryType simplex(unsigned int dim)
Returns a GeometryType representing a simplex of dimension dim.
Definition: type.hh:453
constexpr Interior interior
PartitionSet for the interior partition.
Definition: partitionset.hh:271
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
int sign(const T &val)
Return the sign of the value.
Definition: math.hh:180
A unique label for each type of element that can occur in a grid.
Traits for type conversions and type information.