Dune Core Modules (unstable)

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 © 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  decltype(std::declval<Vector>().size(),bool{}) = true,
227  decltype(std::declval<Vector>().resize(0u),bool{}) = true>
228  void interpolate ( const Function &function, Vector &coefficients ) const
229  {
230  coefficients.resize(size());
231  typename Base::template Helper<Function,Vector,true> func( function,coefficients );
232  interpolate(func);
233  }
234 
235  template< class Basis, class Matrix,
236  decltype(std::declval<Matrix>().rows(),bool{}) = true,
237  decltype(std::declval<Matrix>().cols(),bool{}) = true,
238  decltype(std::declval<Matrix>().resize(0u,0u),bool{}) = true>
239  void interpolate ( const Basis &basis, Matrix &matrix ) const
240  {
241  matrix.resize( size(), basis.size() );
242  typename Base::template Helper<Basis,Matrix,false> func( basis,matrix );
243  interpolate(func);
244  }
245 
246  std::size_t order() const
247  {
248  return order_;
249  }
250  std::size_t size() const
251  {
252  return size_;
253  }
254  template <GeometryType::Id geometryId>
255  void build( std::size_t order )
256  {
257  size_ = 0;
258  order_ = order;
259  builder_.template build<geometryId>(order_);
260  if (builder_.testBasis())
261  size_ += dimension*builder_.testBasis()->size();
262  for ( unsigned int f=0; f<builder_.faceSize(); ++f )
263  if (builder_.testFaceBasis(f))
264  size_ += builder_.testFaceBasis(f)->size();
265  }
266 
267  void setLocalKeys(std::vector< LocalKey > &keys) const
268  {
269  keys.resize(size());
270  unsigned int row = 0;
271  for (unsigned int f=0; f<builder_.faceSize(); ++f)
272  {
273  if (builder_.faceSize())
274  for (unsigned int i=0; i<builder_.testFaceBasis(f)->size(); ++i,++row)
275  keys[row] = LocalKey(f,1,i);
276  }
277  if (builder_.testBasis())
278  for (unsigned int i=0; i<builder_.testBasis()->size()*dimension; ++i,++row)
279  keys[row] = LocalKey(0,0,i);
280  assert( row == size() );
281  }
282 
283  protected:
284  template< class Func, class Container, bool type >
285  void interpolate ( typename Base::template Helper<Func,Container,type> &func ) const
286  {
287  const Dune::GeometryType geoType = builder_.type();
288 
289  std::vector< Field > testBasisVal;
290 
291  for (unsigned int i=0; i<size(); ++i)
292  for (unsigned int j=0; j<func.size(); ++j)
293  func.set(i,j,0);
294 
295  unsigned int row = 0;
296 
297  // boundary dofs:
298  typedef Dune::QuadratureRule<Field, dimension-1> FaceQuadrature;
299  typedef Dune::QuadratureRules<Field, dimension-1> FaceQuadratureRules;
300 
301  const auto &refElement = Dune::ReferenceElements< Field, dimension >::general( geoType );
302 
303  for (unsigned int f=0; f<builder_.faceSize(); ++f)
304  {
305  if (!builder_.testFaceBasis(f))
306  continue;
307  testBasisVal.resize(builder_.testFaceBasis(f)->size());
308 
309  const auto &geometry = refElement.template geometry< 1 >( f );
310  const Dune::GeometryType subGeoType( geometry.type().id(), dimension-1 );
311  const FaceQuadrature &faceQuad = FaceQuadratureRules::rule( subGeoType, 2*order_+2 );
312 
313  const unsigned int quadratureSize = faceQuad.size();
314  for( unsigned int qi = 0; qi < quadratureSize; ++qi )
315  {
316  if (dimension>1)
317  builder_.testFaceBasis(f)->template evaluate<0>(faceQuad[qi].position(),testBasisVal);
318  else
319  testBasisVal[0] = 1.;
320  fillBnd( row, testBasisVal,
321  func.evaluate( geometry.global( faceQuad[qi].position() ) ),
322  builder_.normal(f), faceQuad[qi].weight(),
323  func);
324  }
325 
326  row += builder_.testFaceBasis(f)->size();
327  }
328  // element dofs
329  if (builder_.testBasis())
330  {
331  testBasisVal.resize(builder_.testBasis()->size());
332 
333  typedef Dune::QuadratureRule<Field, dimension> Quadrature;
335  const Quadrature &elemQuad = QuadratureRules::rule( geoType, 2*order_+1 );
336 
337  const unsigned int quadratureSize = elemQuad.size();
338  for( unsigned int qi = 0; qi < quadratureSize; ++qi )
339  {
340  builder_.testBasis()->template evaluate<0>(elemQuad[qi].position(),testBasisVal);
341  fillInterior( row, testBasisVal,
342  func.evaluate(elemQuad[qi].position()),
343  elemQuad[qi].weight(),
344  func );
345  }
346 
347  row += builder_.testBasis()->size()*dimension;
348  }
349  assert(row==size());
350  }
351 
352  private:
362  template <class MVal, class RTVal,class Matrix>
363  void fillBnd (unsigned int startRow,
364  const MVal &mVal,
365  const RTVal &rtVal,
366  const FieldVector<Field,dimension> &normal,
367  const Field &weight,
368  Matrix &matrix) const
369  {
370  const unsigned int endRow = startRow+mVal.size();
371  typename RTVal::const_iterator rtiter = rtVal.begin();
372  for ( unsigned int col = 0; col < rtVal.size() ; ++rtiter,++col)
373  {
374  Field cFactor = (*rtiter)*normal;
375  typename MVal::const_iterator miter = mVal.begin();
376  for (unsigned int row = startRow;
377  row!=endRow; ++miter, ++row )
378  {
379  matrix.add(row,col, (weight*cFactor)*(*miter) );
380  }
381  assert( miter == mVal.end() );
382  }
383  }
392  template <class MVal, class RTVal,class Matrix>
393  void fillInterior (unsigned int startRow,
394  const MVal &mVal,
395  const RTVal &rtVal,
396  Field weight,
397  Matrix &matrix) const
398  {
399  const unsigned int endRow = startRow+mVal.size()*dimension;
400  typename RTVal::const_iterator rtiter = rtVal.begin();
401  for ( unsigned int col = 0; col < rtVal.size() ; ++rtiter,++col)
402  {
403  typename MVal::const_iterator miter = mVal.begin();
404  for (unsigned int row = startRow;
405  row!=endRow; ++miter,row+=dimension )
406  {
407  for (unsigned int i=0; i<dimension; ++i)
408  {
409  matrix.add(row+i,col, (weight*(*miter))*(*rtiter)[i] );
410  }
411  }
412  assert( miter == mVal.end() );
413  }
414  }
415 
416  Builder builder_;
417  std::size_t order_;
418  std::size_t size_;
419  };
420 
421  template < unsigned int dim, class Field >
422  struct RaviartThomasL2InterpolationFactory
423  {
424  typedef RTL2InterpolationBuilder<dim,Field> Builder;
425  typedef const RaviartThomasL2Interpolation<dim,Field> Object;
426  typedef std::size_t Key;
427  typedef typename std::remove_const<Object>::type NonConstObject;
428 
429  template <GeometryType::Id geometryId>
430  static Object *create( const Key &key )
431  {
432  if ( !supports<geometryId>(key) )
433  return 0;
434  NonConstObject *interpol = new NonConstObject();
435  interpol->template build<geometryId>(key);
436  return interpol;
437  }
438  template< GeometryType::Id geometryId >
439  static bool supports ( const Key &key )
440  {
441  return GeometryType(geometryId).isSimplex();
442  }
443  static void release( Object *object ) { delete object; }
444  };
445 
446 } // namespace Dune
447 
448 #endif // #ifndef DUNE_LOCALFUNCTIONS_RAVIARTTHOMAS_RAVIARTTHOMASSIMPLEX_RAVIARTTHOMASSIMPLEXINTERPOLATION_HH
Iterator begin()
begin iterator
Definition: densevector.hh:347
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:114
Describe position of one degree of freedom.
Definition: localkey.hh:24
A generic dynamic dense matrix.
Definition: matrix.hh:561
Abstract base class for quadrature rules.
Definition: quadraturerules.hh:212
A container for all quadrature rules of dimension dim
Definition: quadraturerules.hh:258
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:324
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
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 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.
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 2, 22:35, 2024)