3#ifndef DUNE_LOCALFUNCTIONS_NEDELEC_NEDELECSIMPLEX_NEDELECSIMPLEXINTERPOLATION_HH
4#define DUNE_LOCALFUNCTIONS_NEDELEC_NEDELECSIMPLEX_NEDELECSIMPLEXINTERPOLATION_HH
13#include <dune/geometry/referenceelements.hh>
16#include <dune/localfunctions/common/localkey.hh>
17#include <dune/localfunctions/utility/interpolationhelper.hh>
18#include <dune/localfunctions/utility/polynomialbasis.hh>
19#include <dune/localfunctions/orthonormal/orthonormalbasis.hh>
27 template <
unsigned int dim,
class Field >
28 struct NedelecL2InterpolationFactory;
35 class LocalCoefficientsContainer
37 typedef LocalCoefficientsContainer This;
40 template <
class Setter>
41 LocalCoefficientsContainer (
const Setter &setter )
43 setter.setLocalKeys(localKey_);
46 const LocalKey &localKey (
const unsigned int i )
const
49 return localKey_[ i ];
52 std::size_t size ()
const
54 return localKey_.size();
58 std::vector< LocalKey > localKey_;
66 template <
unsigned int dim >
67 struct NedelecCoefficientsFactory
69 typedef std::size_t Key;
70 typedef const LocalCoefficientsContainer Object;
72 template< GeometryType::Id geometryId >
73 static Object *create(
const Key &key )
75 typedef NedelecL2InterpolationFactory< dim, double > InterpolationFactory;
76 if( !supports< geometryId >( key ) )
78 typename InterpolationFactory::Object *interpolation = InterpolationFactory::template create< geometryId >( key );
79 Object *localKeys =
new Object( *interpolation );
80 InterpolationFactory::release( interpolation );
84 template< GeometryType::Id geometryId >
85 static bool supports (
const Key &key )
88 return gt.isTriangle() ||
gt.isTetrahedron() ;
90 static void release( Object *
object ) {
delete object; }
107 template<
unsigned int dim,
class Field >
108 struct NedelecL2InterpolationBuilder
110 static const unsigned int dimension = dim;
113 typedef OrthonormalBasisFactory< dimension, Field > TestBasisFactory;
114 typedef typename TestBasisFactory::Object TestBasis;
117 typedef OrthonormalBasisFactory< dimension-1, Field > TestFaceBasisFactory;
118 typedef typename TestFaceBasisFactory::Object TestFaceBasis;
121 typedef OrthonormalBasisFactory< 1, Field > TestEdgeBasisFactory;
122 typedef typename TestEdgeBasisFactory::Object TestEdgeBasis;
129 typedef std::array<FieldVector< Field, dimension >,dim-1> FaceTangents;
131 NedelecL2InterpolationBuilder () =
default;
133 NedelecL2InterpolationBuilder (
const NedelecL2InterpolationBuilder & ) =
delete;
134 NedelecL2InterpolationBuilder ( NedelecL2InterpolationBuilder && ) =
delete;
136 ~NedelecL2InterpolationBuilder ()
138 TestBasisFactory::release( testBasis_ );
139 for( FaceStructure &f : faceStructure_ )
140 TestFaceBasisFactory::release( f.basis_ );
141 for( EdgeStructure& e : edgeStructure_ )
142 TestEdgeBasisFactory::release( e.basis_ );
145 unsigned int topologyId ()
const
147 return geometry_.id();
155 std::size_t order ()
const
161 unsigned int faceSize ()
const
163 return numberOfFaces_;
167 unsigned int edgeSize ()
const
169 return numberOfEdges_;
173 TestBasis *testBasis ()
const
179 TestFaceBasis *testFaceBasis (
unsigned int f )
const
181 assert( f < faceSize() );
182 return faceStructure_[ f ].basis_;
186 TestEdgeBasis *testEdgeBasis (
unsigned int e )
const
188 assert( e < edgeSize() );
189 return edgeStructure_[ e ].basis_;
192 const Tangent& edgeTangent (
unsigned int e )
const
194 assert( e < edgeSize() );
195 return edgeStructure_[ e ].tangent_;
198 const FaceTangents& faceTangents (
unsigned int f )
const
200 assert( f < faceSize() );
201 return faceStructure_[ f ].faceTangents_;
204 const Normal &normal (
unsigned int f )
const
206 assert( f < faceSize() );
207 return faceStructure_[ f ].normal_;
210 template< GeometryType::Id geometryId >
211 void build ( std::size_t order )
215 geometry_ = geometry;
230 int requiredOrder =
static_cast<int>(dimension==3);
231 testBasis_ = (order > requiredOrder ? TestBasisFactory::template create< geometry >( order-1-requiredOrder ) : nullptr);
235 numberOfFaces_ = refElement.size( 1 );
236 faceStructure_.reserve( numberOfFaces_ );
239 for (std::size_t i=0; i<numberOfFaces_; i++)
241 FieldVector<Field,dimension> zero(0);
242 FaceTangents faceTangents;
243 faceTangents.fill(zero);
246 auto vertices = refElement.subEntities(i,1,dim).begin();
247 auto vertex1 = *vertices;
248 for(
int j=1; j<dim;j++)
250 auto vertex2 = vertices[j];
252 faceTangents[j-1] = refElement.position(vertex2,dim) - refElement.position(vertex1,dim);
257 faceTangents[j-1] *=-1;
273 TestFaceBasis *faceBasis = ( dim == 3 && order > 0 ? Impl::IfGeometryType< CreateFaceBasis, dimension-1 >::apply( refElement.type( i, 1 ), order-1 ) : nullptr);
274 faceStructure_.emplace_back( faceBasis, refElement.integrationOuterNormal(i), faceTangents );
276 assert( faceStructure_.size() == numberOfFaces_ );
278 numberOfEdges_ = refElement.size( dim-1 );
279 edgeStructure_.reserve( numberOfEdges_ );
282 for (std::size_t i=0; i<numberOfEdges_; i++)
284 auto vertexIterator = refElement.subEntities(i,dim-1,dim).begin();
285 auto v0 = *vertexIterator;
286 auto v1 = *(++vertexIterator);
292 auto tangent = std::move(refElement.position(v1,dim) - refElement.position(v0,dim));
294 TestEdgeBasis *edgeBasis = Impl::IfGeometryType< CreateEdgeBasis, 1 >::apply( refElement.type( i, dim-1 ), order );
295 edgeStructure_.emplace_back( edgeBasis, tangent );
297 assert( edgeStructure_.size() == numberOfEdges_ );
305 EdgeStructure( TestEdgeBasis *teb,
const Tangent &t )
306 : basis_( teb ), tangent_( t )
309 TestEdgeBasis *basis_;
313 template< GeometryType::Id edgeGeometryId >
314 struct CreateEdgeBasis
316 static TestEdgeBasis *apply ( std::size_t order ) {
return TestEdgeBasisFactory::template create< edgeGeometryId >( order ); }
322 FaceStructure( TestFaceBasis *tfb,
const Normal& normal,
const FaceTangents& faceTangents )
323 : basis_( tfb ), normal_(normal), faceTangents_( faceTangents )
326 TestFaceBasis *basis_;
328 const FaceTangents faceTangents_;
331 template< GeometryType::Id faceGeometryId >
332 struct CreateFaceBasis
334 static TestFaceBasis *apply ( std::size_t order ) {
return TestFaceBasisFactory::template create< faceGeometryId >( order ); }
337 TestBasis *testBasis_ =
nullptr;
338 std::vector< FaceStructure > faceStructure_;
339 unsigned int numberOfFaces_;
340 std::vector< EdgeStructure > edgeStructure_;
341 unsigned int numberOfEdges_;
356 template<
unsigned int dimension,
class F>
358 :
public InterpolationHelper< F ,dimension >
361 typedef InterpolationHelper<F,dimension> Base;
365 typedef NedelecL2InterpolationBuilder<dimension,Field> Builder;
366 typedef typename Builder::FaceTangents FaceTangents;
373 template<
class Function,
class Vector >
374 auto interpolate (
const Function &function, Vector &coefficients )
const
375 -> std::enable_if_t< std::is_same< decltype(std::declval<Vector>().resize(1) ),
void >::value,
void>
377 coefficients.resize(size());
378 typename Base::template Helper<Function,Vector,true> func( function,coefficients );
382 template<
class Basis,
class Matrix >
383 auto interpolate (
const Basis &basis,
Matrix &matrix )
const
384 -> std::enable_if_t< std::is_same<
385 decltype(std::declval<Matrix>().rowPtr(0)),
typename Matrix::Field* >::value,
void>
387 matrix.resize( size(), basis.size() );
388 typename Base::template Helper<Basis,Matrix,false> func( basis,matrix );
392 std::size_t order()
const
396 std::size_t size()
const
401 template <GeometryType::Id geometryId>
402 void build( std::size_t order )
406 builder_.template build<geometryId>(order_);
407 if (builder_.testBasis())
408 size_ += dimension*builder_.testBasis()->size();
410 for (
unsigned int f=0; f<builder_.faceSize(); ++f )
411 if (builder_.testFaceBasis(f))
412 size_ += (dimension-1)*builder_.testFaceBasis(f)->size();
414 for (
unsigned int e=0; e<builder_.edgeSize(); ++e )
415 if (builder_.testEdgeBasis(e))
416 size_ += builder_.testEdgeBasis(e)->size();
419 void setLocalKeys(std::vector< LocalKey > &keys)
const
422 unsigned int row = 0;
423 for (
unsigned int e=0; e<builder_.edgeSize(); ++e)
425 if (builder_.edgeSize())
426 for (
unsigned int i=0; i<builder_.testEdgeBasis(e)->size(); ++i,++row)
427 keys[row] =
LocalKey(e,dimension-1,i);
429 for (
unsigned int f=0; f<builder_.faceSize(); ++f)
431 if (builder_.faceSize())
432 for (
unsigned int i=0; i<builder_.testFaceBasis(f)->size()*(dimension-1); ++i,++row)
436 if (builder_.testBasis())
437 for (
unsigned int i=0; i<builder_.testBasis()->size()*dimension; ++i,++row)
439 assert( row == size() );
443 template<
class Func,
class Container,
bool type >
444 void interpolate (
typename Base::template Helper<Func,Container,type> &func )
const
448 std::vector<Field> testBasisVal;
450 for (
unsigned int i=0; i<size(); ++i)
451 for (
unsigned int j=0; j<func.size(); ++j)
454 unsigned int row = 0;
462 for (
unsigned int e=0; e<builder_.edgeSize(); ++e)
464 if (!builder_.testEdgeBasis(e))
466 testBasisVal.resize(builder_.testEdgeBasis(e)->size());
468 const auto &geometry = refElement.template geometry< dimension-1 >( e );
470 const EdgeQuadrature &edgeQuad = EdgeQuadratureRules::rule( subGeoType, 2*order_+2 );
472 const unsigned int quadratureSize = edgeQuad.size();
473 for(
unsigned int qi = 0; qi < quadratureSize; ++qi )
476 builder_.testEdgeBasis(e)->template evaluate<0>(edgeQuad[qi].position(),testBasisVal);
478 testBasisVal[0] = 1.;
481 func.evaluate( geometry.global( edgeQuad[qi].position() ) ),
482 builder_.edgeTangent(e),
483 edgeQuad[qi].weight(),
487 row += builder_.testEdgeBasis(e)->size();
494 for (
unsigned int f=0; f<builder_.faceSize(); ++f)
496 if (builder_.testFaceBasis(f))
498 testBasisVal.resize(builder_.testFaceBasis(f)->size());
500 const auto &geometry = refElement.template geometry< 1 >( f );
502 const FaceQuadrature &faceQuad = FaceQuadratureRules::rule( subGeoType, 2*order_+2 );
504 const unsigned int quadratureSize = faceQuad.size();
505 for(
unsigned int qi = 0; qi < quadratureSize; ++qi )
508 builder_.testFaceBasis(f)->template evaluate<0>(faceQuad[qi].position(),testBasisVal);
510 testBasisVal[0] = 1.;
512 computeFaceDofs( row,
514 func.evaluate( geometry.global( faceQuad[qi].position() ) ),
515 builder_.faceTangents(f),
517 faceQuad[qi].weight(),
521 row += builder_.testFaceBasis(f)->size()*(dimension-1);
526 if (builder_.testBasis())
528 testBasisVal.resize(builder_.testBasis()->size());
534 const unsigned int quadratureSize = elemQuad.size();
535 for(
unsigned int qi = 0; qi < quadratureSize; ++qi )
537 builder_.testBasis()->template evaluate<0>(elemQuad[qi].position(),testBasisVal);
538 computeInteriorDofs(row,
540 func.evaluate(elemQuad[qi].position()),
541 elemQuad[qi].weight(),
545 row += builder_.testBasis()->size()*dimension;
560 template <
class MVal,
class NedVal,
class Matrix>
561 void computeEdgeDofs (
unsigned int startRow,
563 const NedVal &nedVal,
568 const unsigned int endRow = startRow+mVal.size();
569 typename NedVal::const_iterator nedIter = nedVal.begin();
570 for (
unsigned int col = 0; col < nedVal.size() ; ++nedIter,++col)
572 Field cFactor = (*nedIter)*tangent;
573 typename MVal::const_iterator mIter = mVal.
begin();
574 for (
unsigned int row = startRow; row!=endRow; ++mIter, ++row )
575 matrix.add(row,col, (weight*cFactor)*(*mIter) );
577 assert( mIter == mVal.end() );
591 template <
class MVal,
class NedVal,
class Matrix>
592 void computeFaceDofs (
unsigned int startRow,
594 const NedVal &nedVal,
595 const FaceTangents& faceTangents,
600 const unsigned int endRow = startRow+mVal.size()*(dimension-1);
601 typename NedVal::const_iterator nedIter = nedVal.begin();
602 for (
unsigned int col = 0; col < nedVal.size() ; ++nedIter,++col)
604 auto const& u=*nedIter;
605 auto const& n=normal;
608 u[0]*n[1]-u[1]*n[0]};
609 typename MVal::const_iterator mIter = mVal.
begin();
610 for (
unsigned int row = startRow; row!=endRow; ++mIter)
612 for(
int i=0; i<dimension-1;i++)
614 auto test = *mIter*faceTangents[i];
615 matrix.add(row+i,col, weight*(nedTimesNormal*test) );
620 assert( mIter == mVal.end() );
632 template <
class MVal,
class NedVal,
class Matrix>
633 void computeInteriorDofs (
unsigned int startRow,
635 const NedVal &nedVal,
639 const unsigned int endRow = startRow+mVal.size()*dimension;
640 typename NedVal::const_iterator nedIter = nedVal.begin();
641 for (
unsigned int col = 0; col < nedVal.size() ; ++nedIter,++col)
643 typename MVal::const_iterator mIter = mVal.begin();
644 for (
unsigned int row = startRow; row!=endRow; ++mIter,row+=dimension )
645 for (
unsigned int i=0; i<dimension; ++i)
646 matrix.add(row+i,col, (weight*(*mIter))*(*nedIter)[i] );
648 assert( mIter == mVal.end() );
658 template <
unsigned int dim,
class Field >
659 struct NedelecL2InterpolationFactory
661 typedef NedelecL2InterpolationBuilder<dim,Field> Builder;
663 typedef std::size_t Key;
664 typedef typename std::remove_const<Object>::type NonConstObject;
666 template <GeometryType::Id geometryId>
667 static Object *create(
const Key &key )
669 if ( !supports<geometryId>(key) )
671 NonConstObject *interpol =
new NonConstObject();
672 interpol->template build<geometryId>(key);
676 template <GeometryType::Id geometryId>
677 static bool supports(
const Key &key )
679 GeometryType
gt = geometryId;
680 return gt.isTriangle() ||
gt.isTetrahedron() ;
682 static void release( Object *
object ) {
delete object; }
Iterator begin()
begin iterator
Definition: densevector.hh:348
Base class template for function classes.
Definition: function.hh:39
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:123
Describe position of one degree of freedom.
Definition: localkey.hh:21
A generic dynamic dense matrix.
Definition: matrix.hh:559
An L2-based interpolation for Nedelec.
Definition: nedelecsimplexinterpolation.hh:359
Abstract base class for quadrature rules.
Definition: quadraturerules.hh:152
A container for all quadrature rules of dimension dim
Definition: quadraturerules.hh:198
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:280
A few common exception classes.
GeometryType
Type representing VTK's entity geometry types.
Definition: common.hh:130
bool gt(const T &first, const T &second, typename EpsilonType< T >::Type epsilon)
test if first greater than second
Definition: float_cmp.cc:156
Dune namespace.
Definition: alignedallocator.hh:11
static const ReferenceElement & general(const GeometryType &type)
get general reference elements
Definition: referenceelements.hh:196
A unique label for each type of element that can occur in a grid.