dune-functions  2.8.0
brezzidouglasmarinibasis.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_BREZZIDOUGLASMARINIBASIS_HH
4 #define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_BREZZIDOUGLASMARINIBASIS_HH
5 
6 #include <array>
7 #include <dune/common/exceptions.hh>
8 #include <dune/geometry/referenceelements.hh>
9 
10 #include <dune/localfunctions/common/virtualinterface.hh>
11 #include <dune/localfunctions/common/virtualwrappers.hh>
12 
13 #include <dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube2d.hh>
14 #include <dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1cube3d.hh>
15 #include <dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini1simplex2d.hh>
16 #include <dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2cube2d.hh>
17 #include <dune/localfunctions/brezzidouglasmarini/brezzidouglasmarini2simplex2d.hh>
18 
23 
24 namespace Dune {
25 namespace Functions {
26 
27 namespace Impl {
28 
29  template<int dim, typename D, typename R, std::size_t k>
30  struct BDMSimplexLocalInfo
31  {
32  static_assert((AlwaysFalse<D>::value),"The requested type of BDM element is not implemented, sorry!");
33  };
34 
35  template<typename D, typename R>
36  struct BDMSimplexLocalInfo<2,D,R,1>
37  {
38  using FiniteElement = BDM1Simplex2DLocalFiniteElement<D,R>;
39  static const std::size_t Variants = 8;
40  };
41 
42  template<typename D, typename R>
43  struct BDMSimplexLocalInfo<2,D,R,2>
44  {
45  using FiniteElement = BDM2Simplex2DLocalFiniteElement<D,R>;
46  static const std::size_t Variants = 8;
47  };
48 
49  template<int dim, typename D, typename R, std::size_t k>
50  struct BDMCubeLocalInfo
51  {
52  static_assert((AlwaysFalse<D>::value),"The requested type of BDM element is not implemented, sorry!");
53  };
54 
55  template<typename D, typename R>
56  struct BDMCubeLocalInfo<2,D,R,1>
57  {
58  using FiniteElement = BDM1Cube2DLocalFiniteElement<D,R>;
59  static const std::size_t Variants = 16;
60  };
61 
62  template<typename D, typename R>
63  struct BDMCubeLocalInfo<2,D,R,2>
64  {
65  using FiniteElement = BDM2Cube2DLocalFiniteElement<D,R>;
66  static const std::size_t Variants = 16;
67  };
68 
69  template<typename D, typename R>
70  struct BDMCubeLocalInfo<3,D,R,1>
71  {
72  using FiniteElement = BDM1Cube3DLocalFiniteElement<D,R>;
73  static const std::size_t Variants = 64;
74  };
75 
76  template<typename GV, int dim, typename R, std::size_t k>
77  class BDMLocalFiniteElementMap
78  {
79  using D = typename GV::ctype;
80  using CubeFiniteElement = typename BDMCubeLocalInfo<dim, D, R, k>::FiniteElement;
81  using SimplexFiniteElement = typename BDMSimplexLocalInfo<dim, D, R, k>::FiniteElement;
82 
83  public:
84 
85  using T = LocalBasisTraits<D, dim, FieldVector<D,dim>, R, dim, FieldVector<R,dim>, FieldMatrix<D,dim,dim> >;
86  using FiniteElement = LocalFiniteElementVirtualInterface<T>;
87 
88  BDMLocalFiniteElementMap(const GV& gv)
89  : is_(&(gv.indexSet())), orient_(gv.size(0))
90  {
91  cubeVariant_.resize(BDMCubeLocalInfo<dim, D, R, k>::Variants);
92  simplexVariant_.resize(BDMSimplexLocalInfo<dim, D, R, k>::Variants);
93 
94  // create all variants
95  for (size_t i = 0; i < cubeVariant_.size(); i++)
96  cubeVariant_[i] = std::make_unique<LocalFiniteElementVirtualImp<CubeFiniteElement> >(CubeFiniteElement(i));
97 
98  for (size_t i = 0; i < simplexVariant_.size(); i++)
99  simplexVariant_[i] = std::make_unique<LocalFiniteElementVirtualImp<SimplexFiniteElement> >(SimplexFiniteElement(i));
100 
101  // compute orientation for all elements
102  // loop once over the grid
103  for(const auto& cell : elements(gv))
104  {
105  unsigned int myId = is_->index(cell);
106  orient_[myId] = 0;
107 
108  for (const auto& intersection : intersections(gv,cell))
109  {
110  if (intersection.neighbor() && (is_->index(intersection.outside()) > myId))
111  orient_[myId] |= (1 << intersection.indexInInside());
112  }
113  }
114  }
115 
117  template<class EntityType>
118  const FiniteElement& find(const EntityType& e) const
119  {
120  if (e.type().isCube())
121  return *cubeVariant_[orient_[is_->index(e)]];
122  else
123  return *simplexVariant_[orient_[is_->index(e)]];
124  }
125 
126  private:
127  std::vector<std::unique_ptr<LocalFiniteElementVirtualImp<CubeFiniteElement> > > cubeVariant_;
128  std::vector<std::unique_ptr<LocalFiniteElementVirtualImp<SimplexFiniteElement> > > simplexVariant_;
129  const typename GV::IndexSet* is_;
130  std::vector<unsigned char> orient_;
131  };
132 
133 
134 } // namespace Impl
135 
136 
137 // *****************************************************************************
138 // This is the reusable part of the basis. It contains
139 //
140 // BrezziDouglasMariniPreBasis
141 // BrezziDouglasMariniNode
142 //
143 // The pre-basis allows to create the others and is the owner of possible shared
144 // state. These components do _not_ depend on the global basis and local view
145 // and can be used without a global basis.
146 // *****************************************************************************
147 
148 template<typename GV, int k>
149 class BrezziDouglasMariniNode;
150 
151 template<typename GV, int k, class MI>
153 {
154  static const int dim = GV::dimension;
155  using FiniteElementMap = typename Impl::BDMLocalFiniteElementMap<GV, dim, double, k>;
156 
157 public:
158 
160  using GridView = GV;
161  using size_type = std::size_t;
162 
164 
166  using IndexSet = Impl::DefaultNodeIndexSet<BrezziDouglasMariniPreBasis>;
167 
169  using MultiIndex = MI;
170 
171  using SizePrefix = Dune::ReservedVector<size_type, 1>;
172 
175  gridView_(gv),
177  {
178  // There is no inherent reason why the basis shouldn't work for grids with more than one
179  // element types. Somebody simply has to sit down and implement the missing bits.
180  if (gv.indexSet().types(0).size() > 1)
181  DUNE_THROW(Dune::NotImplemented, "Brezzi-Douglas-Marini basis is only implemented for grids with a single element type");
182  }
183 
185  {
186  codimOffset_[0] = 0;
187  codimOffset_[1] = codimOffset_[0] + dofsPerCodim_[0] * gridView_.size(0);
188  //if (dim==3) codimOffset_[2] = codimOffset_[1] + dofsPerCodim[1] * gridView_.size(1);
189  }
190 
193  const GridView& gridView() const
194  {
195  return gridView_;
196  }
197 
198  /* \brief Update the stored grid view, to be called if the grid has changed */
199  void update (const GridView& gv)
200  {
201  gridView_ = gv;
202  }
203 
207  Node makeNode() const
208  {
209  return Node{&finiteElementMap_};
210  }
211 
219  [[deprecated("Warning: The IndexSet typedef and the makeIndexSet method are deprecated. "\
220  "As a replacement use the indices() method of the PreBasis directly.")]]
222  {
223  return IndexSet{*this};
224  }
225 
226  size_type size() const
227  {
228  return dofsPerCodim_[0] * gridView_.size(0) + dofsPerCodim_[1] * gridView_.size(1); // only 2d
229  }
230 
232  size_type size(const SizePrefix prefix) const
233  {
234  assert(prefix.size() == 0 || prefix.size() == 1);
235  return (prefix.size() == 0) ? size() : 0;
236  }
237 
240  {
241  return size();
242  }
243 
245  {
246  // The implementation currently only supports grids with a single element type.
247  // We can therefore return the actual number of dofs here.
248  GeometryType elementType = *(gridView_.indexSet().types(0).begin());
249  size_t numFaces = ReferenceElements<double,dim>::general(elementType).size(1);
250  return dofsPerCodim_[0] + dofsPerCodim_[1] * numFaces;
251  }
252 
258  template<typename It>
259  It indices(const Node& node, It it) const
260  {
261  const auto& gridIndexSet = gridView().indexSet();
262  const auto& element = node.element();
263 
264  // throw if element is not of predefined type
265  if (not(element.type().isCube()) and not(element.type().isSimplex()))
266  DUNE_THROW(Dune::NotImplemented, "BrezziDouglasMariniBasis only implemented for cube and simplex elements.");
267 
268  for(std::size_t i=0, end=node.size(); i<end; ++i, ++it)
269  {
270  Dune::LocalKey localKey = node.finiteElement().localCoefficients().localKey(i);
271 
272  // The dimension of the entity that the current dof is related to
273  size_t subentity = localKey.subEntity();
274  size_t codim = localKey.codim();
275 
276  *it = { codimOffset_[codim] +
277  dofsPerCodim_[codim] * gridIndexSet.subIndex(element, subentity, codim) + localKey.index() };
278  }
279 
280  return it;
281  }
282 
283 protected:
285  std::array<size_t,dim+1> codimOffset_;
286  FiniteElementMap finiteElementMap_;
287  // Number of dofs per entity type depending on the entity's codimension and type
288  std::array<int,2> dofsPerCodim_ {{dim*(k-1)*3, dim+(k-1)}};
289 };
290 
291 
292 
293 template<typename GV, int k>
295  public LeafBasisNode
296 {
297  static const int dim = GV::dimension;
298 
299 public:
300 
301  using size_type = std::size_t;
302  using Element = typename GV::template Codim<0>::Entity;
303  using FiniteElementMap = typename Impl::BDMLocalFiniteElementMap<GV, dim, double, k>;
304  using FiniteElement = Impl::GlobalValuedLocalFiniteElement<Impl::ContravariantPiolaTransformator,
305  typename FiniteElementMap::FiniteElement,
306  Element>;
307 
308  BrezziDouglasMariniNode(const FiniteElementMap* finiteElementMap) :
309  element_(nullptr),
310  finiteElementMap_(finiteElementMap)
311  {}
312 
314  const Element& element() const
315  {
316  return *element_;
317  }
318 
324  {
325  return finiteElement_;
326  }
327 
329  void bind(const Element& e)
330  {
331  element_ = &e;
332  finiteElement_.bind((finiteElementMap_->find(*element_)), e);
333  this->setSize(finiteElement_.size());
334  }
335 
336 protected:
337 
341 };
342 
343 
344 
345 namespace BasisFactory {
346 
347 namespace Imp {
348 
349 template<std::size_t k>
350 class BrezziDouglasMariniPreBasisFactory
351 {
352 public:
353  static const std::size_t requiredMultiIndexSize=1;
354 
355  template<class MultiIndex, class GridView>
356  auto makePreBasis(const GridView& gridView) const
358  {
359  return {gridView};
360  }
361 };
362 
363 } // end namespace BasisFactory::Imp
364 
372 template<std::size_t k>
374 {
375  return Imp::BrezziDouglasMariniPreBasisFactory<k>();
376 }
377 
378 } // end namespace BasisFactory
379 
380 
381 
382 // *****************************************************************************
383 // This is the actual global basis implementation based on the reusable parts.
384 // *****************************************************************************
385 
393 template<typename GV, int k>
395 
396 } // end namespace Functions
397 } // end namespace Dune
398 
399 
400 #endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_BREZZIDOUGLASMARINIBASIS_HH
auto brezziDouglasMarini()
Create a pre-basis factory that can create a Brezzi-Douglas-Marini pre-basis.
Definition: brezzidouglasmarinibasis.hh:373
Definition: polynomial.hh:10
Definition: brezzidouglasmarinibasis.hh:296
typename GV::template Codim< 0 >::Entity Element
Definition: brezzidouglasmarinibasis.hh:302
const FiniteElementMap * finiteElementMap_
Definition: brezzidouglasmarinibasis.hh:340
const Element & element() const
Return current element, throw if unbound.
Definition: brezzidouglasmarinibasis.hh:314
std::size_t size_type
Definition: brezzidouglasmarinibasis.hh:301
FiniteElement finiteElement_
Definition: brezzidouglasmarinibasis.hh:338
const FiniteElement & finiteElement() const
Return the LocalFiniteElement for the element we are bound to.
Definition: brezzidouglasmarinibasis.hh:323
typename Impl::BDMLocalFiniteElementMap< GV, dim, double, k > FiniteElementMap
Definition: brezzidouglasmarinibasis.hh:303
const Element * element_
Definition: brezzidouglasmarinibasis.hh:339
Impl::GlobalValuedLocalFiniteElement< Impl::ContravariantPiolaTransformator, typename FiniteElementMap::FiniteElement, Element > FiniteElement
Definition: brezzidouglasmarinibasis.hh:306
void bind(const Element &e)
Bind to element.
Definition: brezzidouglasmarinibasis.hh:329
BrezziDouglasMariniNode(const FiniteElementMap *finiteElementMap)
Definition: brezzidouglasmarinibasis.hh:308
Definition: brezzidouglasmarinibasis.hh:153
BrezziDouglasMariniPreBasis(const GridView &gv)
Constructor for a given grid view object.
Definition: brezzidouglasmarinibasis.hh:174
size_type maxNodeSize() const
Definition: brezzidouglasmarinibasis.hh:244
Node makeNode() const
Create tree node.
Definition: brezzidouglasmarinibasis.hh:207
std::array< int, 2 > dofsPerCodim_
Definition: brezzidouglasmarinibasis.hh:288
Impl::DefaultNodeIndexSet< BrezziDouglasMariniPreBasis > IndexSet
Type of created tree node index set.
Definition: brezzidouglasmarinibasis.hh:166
void update(const GridView &gv)
Definition: brezzidouglasmarinibasis.hh:199
Dune::ReservedVector< size_type, 1 > SizePrefix
Definition: brezzidouglasmarinibasis.hh:171
FiniteElementMap finiteElementMap_
Definition: brezzidouglasmarinibasis.hh:286
size_type size() const
Definition: brezzidouglasmarinibasis.hh:226
IndexSet makeIndexSet() const
Create tree node index set.
Definition: brezzidouglasmarinibasis.hh:221
GridView gridView_
Definition: brezzidouglasmarinibasis.hh:284
It indices(const Node &node, It it) const
Maps from subtree index set [0..size-1] to a globally unique multi index in global basis.
Definition: brezzidouglasmarinibasis.hh:259
GV GridView
The grid view that the FE space is defined on.
Definition: brezzidouglasmarinibasis.hh:160
void initializeIndices()
Definition: brezzidouglasmarinibasis.hh:184
std::array< size_t, dim+1 > codimOffset_
Definition: brezzidouglasmarinibasis.hh:285
size_type size(const SizePrefix prefix) const
Return number possible values for next position in multi index.
Definition: brezzidouglasmarinibasis.hh:232
std::size_t size_type
Definition: brezzidouglasmarinibasis.hh:161
size_type dimension() const
Definition: brezzidouglasmarinibasis.hh:239
MI MultiIndex
Type used for global numbering of the basis vectors.
Definition: brezzidouglasmarinibasis.hh:169
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: brezzidouglasmarinibasis.hh:193
Global basis for given pre-basis.
Definition: defaultglobalbasis.hh:47
size_type size() const
Definition: nodes.hh:140
void setSize(const size_type size)
Definition: nodes.hh:162
Definition: nodes.hh:184