Dune Core Modules (2.9.0)

raviartthomassimplexinterpolation.hh
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 // SPDX-FileCopyrightInfo: Copyright (C) DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5 #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASSIMPLEX_RAVIARTTHOMASSIMPLEXINTERPOLATION_HH
6 #define DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASSIMPLEX_RAVIARTTHOMASSIMPLEXINTERPOLATION_HH
7 
8 #include <fstream>
9 #include <utility>
10 
12 
14 #include <dune/geometry/referenceelements.hh>
15 #include <dune/geometry/type.hh>
17 
18 #include <dune/localfunctions/common/localkey.hh>
19 #include <dune/localfunctions/utility/interpolationhelper.hh>
20 #include <dune/localfunctions/utility/polynomialbasis.hh>
21 #include <dune/localfunctions/orthonormal/orthonormalbasis.hh>
22 
23 namespace Dune
24 {
25 
26  // Internal Forward Declarations
27  // -----------------------------
28 
29  template < unsigned int dim, class Field >
30  struct RaviartThomasL2InterpolationFactory;
31 
32 
33 
34  // LocalCoefficientsContainer
35  // --------------------------
36 
37  class LocalCoefficientsContainer
38  {
39  typedef LocalCoefficientsContainer This;
40 
41  public:
42  template <class Setter>
43  LocalCoefficientsContainer ( const Setter &setter )
44  {
45  setter.setLocalKeys(localKey_);
46  }
47 
48  const LocalKey &localKey ( const unsigned int i ) const
49  {
50  assert( i < size() );
51  return localKey_[ i ];
52  }
53 
54  std::size_t size () const
55  {
56  return localKey_.size();
57  }
58 
59  private:
60  std::vector< LocalKey > localKey_;
61  };
62 
63 
64 
65  // RaviartThomasCoefficientsFactory
66  // --------------------------------
67 
68  template < unsigned int dim >
69  struct RaviartThomasCoefficientsFactory
70  {
71  typedef std::size_t Key;
72  typedef const LocalCoefficientsContainer Object;
73 
74  template< GeometryType::Id geometryId >
75  static Object *create( const Key &key )
76  {
77  typedef RaviartThomasL2InterpolationFactory< dim, double > InterpolationFactory;
78  if( !supports< geometryId >( key ) )
79  return nullptr;
80  typename InterpolationFactory::Object *interpolation = InterpolationFactory::template create< geometryId >( key );
81  Object *localKeys = new Object( *interpolation );
82  InterpolationFactory::release( interpolation );
83  return localKeys;
84  }
85 
86  template< GeometryType::Id geometryId >
87  static bool supports ( const Key &key )
88  {
89  return GeometryType(geometryId).isSimplex();
90  }
91  static void release( Object *object ) { delete object; }
92  };
93 
94 
95 
96  // RTL2InterpolationBuilder
97  // ------------------------
98 
99  // L2 Interpolation requires:
100  // - for element
101  // - test basis
102  // - for each face (dynamic)
103  // - test basis
104  // - normal
105  template< unsigned int dim, class Field >
106  struct RTL2InterpolationBuilder
107  {
108  static const unsigned int dimension = dim;
109 
110  // for the dofs associated to the element
111  typedef OrthonormalBasisFactory< dimension, Field > TestBasisFactory;
112  typedef typename TestBasisFactory::Object TestBasis;
113 
114  // for the dofs associated to the faces
115  typedef OrthonormalBasisFactory< dimension-1, Field > TestFaceBasisFactory;
116  typedef typename TestFaceBasisFactory::Object TestFaceBasis;
117 
118  // the normals of the faces
119  typedef FieldVector< Field, dimension > Normal;
120 
121  RTL2InterpolationBuilder () = default;
122 
123  RTL2InterpolationBuilder ( const RTL2InterpolationBuilder & ) = delete;
124  RTL2InterpolationBuilder ( RTL2InterpolationBuilder && ) = delete;
125 
126  ~RTL2InterpolationBuilder ()
127  {
128  TestBasisFactory::release( testBasis_ );
129  for( FaceStructure &f : faceStructure_ )
130  TestFaceBasisFactory::release( f.basis_ );
131  }
132 
133  GeometryType type () const { return geometry_; }
134 
135  std::size_t order () const { return order_; }
136 
137  // number of faces
138  unsigned int faceSize () const { return faceSize_; }
139 
140  // basis associated to the element
141  TestBasis *testBasis () const { return testBasis_; }
142 
143  // basis associated to face f
144  TestFaceBasis *testFaceBasis ( unsigned int f ) const { assert( f < faceSize() ); return faceStructure_[ f ].basis_; }
145 
146  // normal of face f
147  const Normal &normal ( unsigned int f ) const { assert( f < faceSize() ); return *(faceStructure_[ f ].normal_); }
148 
149  template< GeometryType::Id geometryId >
150  void build ( std::size_t order )
151  {
152  constexpr GeometryType geometry = geometryId;
153  geometry_ = geometry;
154  order_ = order;
155 
156  testBasis_ = (order > 0 ? TestBasisFactory::template create< geometry >( order-1 ) : nullptr);
157 
158  const auto &refElement = ReferenceElements< Field, dimension >::general( type() );
159  faceSize_ = refElement.size( 1 );
160  faceStructure_.reserve( faceSize_ );
161  for( unsigned int face = 0; face < faceSize_; ++face )
162  {
163  /* For simplices or cubes of arbitrary dimension you could just use
164  *
165  * ```
166  * GeometryType faceGeometry = Impl::getBase(geometry_);
167  * TestFaceBasis *faceBasis = TestFaceBasisFactory::template create< faceGeometry >( order );
168  * ```
169  *
170  * For i.e. Prisms and Pyramids in 3d this does not work because they contain squares and triangles as faces.
171  * And depending on the dynamic face index a different face geometry is needed.
172  *
173  */
174  TestFaceBasis *faceBasis = Impl::toGeometryTypeIdConstant<dimension-1>(refElement.type( face, 1 ), [&](auto faceGeometryTypeId) {
175  return TestFaceBasisFactory::template create< decltype(faceGeometryTypeId)::value >( order );
176  });
177  faceStructure_.emplace_back( faceBasis, refElement.integrationOuterNormal( face ) );
178  }
179  assert( faceStructure_.size() == faceSize_ );
180  }
181 
182  private:
183  struct FaceStructure
184  {
185  FaceStructure( TestFaceBasis *tfb, const Normal &n )
186  : basis_( tfb ), normal_( &n )
187  {}
188 
189  TestFaceBasis *basis_;
191  };
192 
193  std::vector< FaceStructure > faceStructure_;
194  TestBasis *testBasis_ = nullptr;
195  GeometryType geometry_;
196  unsigned int faceSize_;
197  std::size_t order_;
198  };
199 
200 
201 
202  // RaviartThomasL2Interpolation
203  // ----------------------------
204 
210  template< unsigned int dimension, class F>
212  : public InterpolationHelper< F ,dimension >
213  {
215  typedef InterpolationHelper<F,dimension> Base;
216 
217  public:
218  typedef F Field;
219  typedef RTL2InterpolationBuilder<dimension,Field> Builder;
221  : order_(0),
222  size_(0)
223  {}
224 
225  template< class Function, class Vector >
226  auto interpolate ( const Function &function, Vector &coefficients ) const
227  -> std::enable_if_t< std::is_same< decltype(std::declval<Vector>().resize(1) ),void >::value,void>
228  {
229  coefficients.resize(size());
230  typename Base::template Helper<Function,Vector,true> func( function,coefficients );
231  interpolate(func);
232  }
233 
234  template< class Basis, class Matrix >
235  auto interpolate ( const Basis &basis, Matrix &matrix ) const
236  -> std::enable_if_t< std::is_same<
237  decltype(std::declval<Matrix>().rowPtr(0)), typename Matrix::Field* >::value,void>
238  {
239  matrix.resize( size(), basis.size() );
240  typename Base::template Helper<Basis,Matrix,false> func( basis,matrix );
241  interpolate(func);
242  }
243 
244  std::size_t order() const
245  {
246  return order_;
247  }
248  std::size_t size() const
249  {
250  return size_;
251  }
252  template <GeometryType::Id geometryId>
253  void build( std::size_t order )
254  {
255  size_ = 0;
256  order_ = order;
257  builder_.template build<geometryId>(order_);
258  if (builder_.testBasis())
259  size_ += dimension*builder_.testBasis()->size();
260  for ( unsigned int f=0; f<builder_.faceSize(); ++f )
261  if (builder_.testFaceBasis(f))
262  size_ += builder_.testFaceBasis(f)->size();
263  }
264 
265  void setLocalKeys(std::vector< LocalKey > &keys) const
266  {
267  keys.resize(size());
268  unsigned int row = 0;
269  for (unsigned int f=0; f<builder_.faceSize(); ++f)
270  {
271  if (builder_.faceSize())
272  for (unsigned int i=0; i<builder_.testFaceBasis(f)->size(); ++i,++row)
273  keys[row] = LocalKey(f,1,i);
274  }
275  if (builder_.testBasis())
276  for (unsigned int i=0; i<builder_.testBasis()->size()*dimension; ++i,++row)
277  keys[row] = LocalKey(0,0,i);
278  assert( row == size() );
279  }
280 
281  protected:
282  template< class Func, class Container, bool type >
283  void interpolate ( typename Base::template Helper<Func,Container,type> &func ) const
284  {
285  const Dune::GeometryType geoType = builder_.type();
286 
287  std::vector< Field > testBasisVal;
288 
289  for (unsigned int i=0; i<size(); ++i)
290  for (unsigned int j=0; j<func.size(); ++j)
291  func.set(i,j,0);
292 
293  unsigned int row = 0;
294 
295  // boundary dofs:
296  typedef Dune::QuadratureRule<Field, dimension-1> FaceQuadrature;
297  typedef Dune::QuadratureRules<Field, dimension-1> FaceQuadratureRules;
298 
299  const auto &refElement = Dune::ReferenceElements< Field, dimension >::general( geoType );
300 
301  for (unsigned int f=0; f<builder_.faceSize(); ++f)
302  {
303  if (!builder_.testFaceBasis(f))
304  continue;
305  testBasisVal.resize(builder_.testFaceBasis(f)->size());
306 
307  const auto &geometry = refElement.template geometry< 1 >( f );
308  const Dune::GeometryType subGeoType( geometry.type().id(), dimension-1 );
309  const FaceQuadrature &faceQuad = FaceQuadratureRules::rule( subGeoType, 2*order_+2 );
310 
311  const unsigned int quadratureSize = faceQuad.size();
312  for( unsigned int qi = 0; qi < quadratureSize; ++qi )
313  {
314  if (dimension>1)
315  builder_.testFaceBasis(f)->template evaluate<0>(faceQuad[qi].position(),testBasisVal);
316  else
317  testBasisVal[0] = 1.;
318  fillBnd( row, testBasisVal,
319  func.evaluate( geometry.global( faceQuad[qi].position() ) ),
320  builder_.normal(f), faceQuad[qi].weight(),
321  func);
322  }
323 
324  row += builder_.testFaceBasis(f)->size();
325  }
326  // element dofs
327  if (builder_.testBasis())
328  {
329  testBasisVal.resize(builder_.testBasis()->size());
330 
331  typedef Dune::QuadratureRule<Field, dimension> Quadrature;
333  const Quadrature &elemQuad = QuadratureRules::rule( geoType, 2*order_+1 );
334 
335  const unsigned int quadratureSize = elemQuad.size();
336  for( unsigned int qi = 0; qi < quadratureSize; ++qi )
337  {
338  builder_.testBasis()->template evaluate<0>(elemQuad[qi].position(),testBasisVal);
339  fillInterior( row, testBasisVal,
340  func.evaluate(elemQuad[qi].position()),
341  elemQuad[qi].weight(),
342  func );
343  }
344 
345  row += builder_.testBasis()->size()*dimension;
346  }
347  assert(row==size());
348  }
349 
350  private:
360  template <class MVal, class RTVal,class Matrix>
361  void fillBnd (unsigned int startRow,
362  const MVal &mVal,
363  const RTVal &rtVal,
364  const FieldVector<Field,dimension> &normal,
365  const Field &weight,
366  Matrix &matrix) const
367  {
368  const unsigned int endRow = startRow+mVal.size();
369  typename RTVal::const_iterator rtiter = rtVal.begin();
370  for ( unsigned int col = 0; col < rtVal.size() ; ++rtiter,++col)
371  {
372  Field cFactor = (*rtiter)*normal;
373  typename MVal::const_iterator miter = mVal.begin();
374  for (unsigned int row = startRow;
375  row!=endRow; ++miter, ++row )
376  {
377  matrix.add(row,col, (weight*cFactor)*(*miter) );
378  }
379  assert( miter == mVal.end() );
380  }
381  }
390  template <class MVal, class RTVal,class Matrix>
391  void fillInterior (unsigned int startRow,
392  const MVal &mVal,
393  const RTVal &rtVal,
394  Field weight,
395  Matrix &matrix) const
396  {
397  const unsigned int endRow = startRow+mVal.size()*dimension;
398  typename RTVal::const_iterator rtiter = rtVal.begin();
399  for ( unsigned int col = 0; col < rtVal.size() ; ++rtiter,++col)
400  {
401  typename MVal::const_iterator miter = mVal.begin();
402  for (unsigned int row = startRow;
403  row!=endRow; ++miter,row+=dimension )
404  {
405  for (unsigned int i=0; i<dimension; ++i)
406  {
407  matrix.add(row+i,col, (weight*(*miter))*(*rtiter)[i] );
408  }
409  }
410  assert( miter == mVal.end() );
411  }
412  }
413 
414  Builder builder_;
415  std::size_t order_;
416  std::size_t size_;
417  };
418 
419  template < unsigned int dim, class Field >
420  struct RaviartThomasL2InterpolationFactory
421  {
422  typedef RTL2InterpolationBuilder<dim,Field> Builder;
423  typedef const RaviartThomasL2Interpolation<dim,Field> Object;
424  typedef std::size_t Key;
425  typedef typename std::remove_const<Object>::type NonConstObject;
426 
427  template <GeometryType::Id geometryId>
428  static Object *create( const Key &key )
429  {
430  if ( !supports<geometryId>(key) )
431  return 0;
432  NonConstObject *interpol = new NonConstObject();
433  interpol->template build<geometryId>(key);
434  return interpol;
435  }
436  template< GeometryType::Id geometryId >
437  static bool supports ( const Key &key )
438  {
439  return GeometryType(geometryId).isSimplex();
440  }
441  static void release( Object *object ) { delete object; }
442  };
443 
444 } // namespace Dune
445 
446 #endif // #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASSIMPLEX_RAVIARTTHOMASSIMPLEXINTERPOLATION_HH
Iterator begin()
begin iterator
Definition: densevector.hh:347
Base class template for function classes.
Definition: function.hh:41
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:125
Describe position of one degree of freedom.
Definition: localkey.hh:23
A generic dynamic dense matrix.
Definition: matrix.hh:561
Abstract base class for quadrature rules.
Definition: quadraturerules.hh:154
A container for all quadrature rules of dimension dim
Definition: quadraturerules.hh:200
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:266
An L2-based interpolation for Raviart Thomas.
Definition: raviartthomassimplexinterpolation.hh:213
A few common exception classes.
GeometryType
Type representing VTK's entity geometry types.
Definition: common.hh:132
Dune namespace.
Definition: alignedallocator.hh:13
static const ReferenceElement & general(const GeometryType &type)
get general reference elements
Definition: referenceelements.hh:198
A unique label for each type of element that can occur in a grid.
Helper classes to provide indices for geometrytypes for use in a vector.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 1, 22:29, 2024)