dune-functions  2.9.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 
22 
23 namespace Dune {
24 namespace Functions {
25 
26 namespace Impl {
27 
28  template<int dim, typename D, typename R, std::size_t k>
29  struct BDMSimplexLocalInfo
30  {
31  static_assert((AlwaysFalse<D>::value),"The requested type of BDM element is not implemented, sorry!");
32  };
33 
34  template<typename D, typename R>
35  struct BDMSimplexLocalInfo<2,D,R,1>
36  {
37  using FiniteElement = BDM1Simplex2DLocalFiniteElement<D,R>;
38  static const std::size_t Variants = 8;
39  };
40 
41  template<typename D, typename R>
42  struct BDMSimplexLocalInfo<2,D,R,2>
43  {
44  using FiniteElement = BDM2Simplex2DLocalFiniteElement<D,R>;
45  static const std::size_t Variants = 8;
46  };
47 
48  template<int dim, typename D, typename R, std::size_t k>
49  struct BDMCubeLocalInfo
50  {
51  static_assert((AlwaysFalse<D>::value),"The requested type of BDM element is not implemented, sorry!");
52  };
53 
54  template<typename D, typename R>
55  struct BDMCubeLocalInfo<2,D,R,1>
56  {
57  using FiniteElement = BDM1Cube2DLocalFiniteElement<D,R>;
58  static const std::size_t Variants = 16;
59  };
60 
61  template<typename D, typename R>
62  struct BDMCubeLocalInfo<2,D,R,2>
63  {
64  using FiniteElement = BDM2Cube2DLocalFiniteElement<D,R>;
65  static const std::size_t Variants = 16;
66  };
67 
68  template<typename D, typename R>
69  struct BDMCubeLocalInfo<3,D,R,1>
70  {
71  using FiniteElement = BDM1Cube3DLocalFiniteElement<D,R>;
72  static const std::size_t Variants = 64;
73  };
74 
75  template<typename GV, int dim, typename R, std::size_t k>
76  class BDMLocalFiniteElementMap
77  {
78  using D = typename GV::ctype;
79  using CubeFiniteElement = typename BDMCubeLocalInfo<dim, D, R, k>::FiniteElement;
80  using SimplexFiniteElement = typename BDMSimplexLocalInfo<dim, D, R, k>::FiniteElement;
81 
82  public:
83 
84  using T = LocalBasisTraits<D, dim, FieldVector<D,dim>, R, dim, FieldVector<R,dim>, FieldMatrix<D,dim,dim> >;
85  using FiniteElement = LocalFiniteElementVirtualInterface<T>;
86 
87  BDMLocalFiniteElementMap(const GV& gv)
88  : is_(&(gv.indexSet())), orient_(gv.size(0))
89  {
90  cubeVariant_.resize(BDMCubeLocalInfo<dim, D, R, k>::Variants);
91  simplexVariant_.resize(BDMSimplexLocalInfo<dim, D, R, k>::Variants);
92 
93  // create all variants
94  for (size_t i = 0; i < cubeVariant_.size(); i++)
95  cubeVariant_[i] = std::make_unique<LocalFiniteElementVirtualImp<CubeFiniteElement> >(CubeFiniteElement(i));
96 
97  for (size_t i = 0; i < simplexVariant_.size(); i++)
98  simplexVariant_[i] = std::make_unique<LocalFiniteElementVirtualImp<SimplexFiniteElement> >(SimplexFiniteElement(i));
99 
100  // compute orientation for all elements
101  // loop once over the grid
102  for(const auto& cell : elements(gv))
103  {
104  unsigned int myId = is_->index(cell);
105  orient_[myId] = 0;
106 
107  for (const auto& intersection : intersections(gv,cell))
108  {
109  if (intersection.neighbor() && (is_->index(intersection.outside()) > myId))
110  orient_[myId] |= (1 << intersection.indexInInside());
111  }
112  }
113  }
114 
116  template<class EntityType>
117  const FiniteElement& find(const EntityType& e) const
118  {
119  if (e.type().isCube())
120  return *cubeVariant_[orient_[is_->index(e)]];
121  else
122  return *simplexVariant_[orient_[is_->index(e)]];
123  }
124 
125  private:
126  std::vector<std::unique_ptr<LocalFiniteElementVirtualImp<CubeFiniteElement> > > cubeVariant_;
127  std::vector<std::unique_ptr<LocalFiniteElementVirtualImp<SimplexFiniteElement> > > simplexVariant_;
128  const typename GV::IndexSet* is_;
129  std::vector<unsigned char> orient_;
130  };
131 
132 
133 } // namespace Impl
134 
135 
136 // *****************************************************************************
137 // This is the reusable part of the basis. It contains
138 //
139 // BrezziDouglasMariniPreBasis
140 // BrezziDouglasMariniNode
141 //
142 // The pre-basis allows to create the others and is the owner of possible shared
143 // state. These components do _not_ depend on the global basis and local view
144 // and can be used without a global basis.
145 // *****************************************************************************
146 
147 template<typename GV, int k>
148 class BrezziDouglasMariniNode;
149 
150 template<typename GV, int k>
152 {
153  static const int dim = GV::dimension;
154  using FiniteElementMap = typename Impl::BDMLocalFiniteElementMap<GV, dim, double, k>;
155 
156 public:
157 
159  using GridView = GV;
160  using size_type = std::size_t;
161 
163 
164  static constexpr size_type maxMultiIndexSize = 1;
165  static constexpr size_type minMultiIndexSize = 1;
166  static constexpr size_type multiIndexBufferSize = 1;
167 
170  gridView_(gv),
172  {
173  // There is no inherent reason why the basis shouldn't work for grids with more than one
174  // element types. Somebody simply has to sit down and implement the missing bits.
175  if (gv.indexSet().types(0).size() > 1)
176  DUNE_THROW(Dune::NotImplemented, "Brezzi-Douglas-Marini basis is only implemented for grids with a single element type");
177  }
178 
180  {
181  codimOffset_[0] = 0;
182  codimOffset_[1] = codimOffset_[0] + dofsPerCodim_[0] * gridView_.size(0);
183  //if (dim==3) codimOffset_[2] = codimOffset_[1] + dofsPerCodim[1] * gridView_.size(1);
184  }
185 
188  const GridView& gridView() const
189  {
190  return gridView_;
191  }
192 
193  /* \brief Update the stored grid view, to be called if the grid has changed */
194  void update (const GridView& gv)
195  {
196  gridView_ = gv;
197  }
198 
202  Node makeNode() const
203  {
204  return Node{&finiteElementMap_};
205  }
206 
207  size_type size() const
208  {
209  return dofsPerCodim_[0] * gridView_.size(0) + dofsPerCodim_[1] * gridView_.size(1); // only 2d
210  }
211 
213  template<class SizePrefix>
214  size_type size(const SizePrefix prefix) const
215  {
216  assert(prefix.size() == 0 || prefix.size() == 1);
217  return (prefix.size() == 0) ? size() : 0;
218  }
219 
222  {
223  return size();
224  }
225 
227  {
228  // The implementation currently only supports grids with a single element type.
229  // We can therefore return the actual number of dofs here.
230  GeometryType elementType = *(gridView_.indexSet().types(0).begin());
231  size_t numFaces = ReferenceElements<double,dim>::general(elementType).size(1);
232  return dofsPerCodim_[0] + dofsPerCodim_[1] * numFaces;
233  }
234 
240  template<typename It>
241  It indices(const Node& node, It it) const
242  {
243  const auto& gridIndexSet = gridView().indexSet();
244  const auto& element = node.element();
245 
246  // throw if element is not of predefined type
247  if (not(element.type().isCube()) and not(element.type().isSimplex()))
248  DUNE_THROW(Dune::NotImplemented, "BrezziDouglasMariniBasis only implemented for cube and simplex elements.");
249 
250  for(std::size_t i=0, end=node.size(); i<end; ++i, ++it)
251  {
252  Dune::LocalKey localKey = node.finiteElement().localCoefficients().localKey(i);
253 
254  // The dimension of the entity that the current dof is related to
255  size_t subentity = localKey.subEntity();
256  size_t codim = localKey.codim();
257 
258  *it = { codimOffset_[codim] +
259  dofsPerCodim_[codim] * gridIndexSet.subIndex(element, subentity, codim) + localKey.index() };
260  }
261 
262  return it;
263  }
264 
265 protected:
267  std::array<size_t,dim+1> codimOffset_;
268  FiniteElementMap finiteElementMap_;
269  // Number of dofs per entity type depending on the entity's codimension and type
270  std::array<int,2> dofsPerCodim_ {{dim*(k-1)*3, dim+(k-1)}};
271 };
272 
273 
274 
275 template<typename GV, int k>
277  public LeafBasisNode
278 {
279  static const int dim = GV::dimension;
280 
281 public:
282 
283  using size_type = std::size_t;
284  using Element = typename GV::template Codim<0>::Entity;
285  using FiniteElementMap = typename Impl::BDMLocalFiniteElementMap<GV, dim, double, k>;
286  using FiniteElement = Impl::GlobalValuedLocalFiniteElement<Impl::ContravariantPiolaTransformator,
287  typename FiniteElementMap::FiniteElement,
288  Element>;
289 
290  BrezziDouglasMariniNode(const FiniteElementMap* finiteElementMap) :
291  element_(nullptr),
292  finiteElementMap_(finiteElementMap)
293  {}
294 
296  const Element& element() const
297  {
298  return *element_;
299  }
300 
306  {
307  return finiteElement_;
308  }
309 
311  void bind(const Element& e)
312  {
313  element_ = &e;
314  finiteElement_.bind((finiteElementMap_->find(*element_)), e);
315  this->setSize(finiteElement_.size());
316  }
317 
318 protected:
319 
323 };
324 
325 
326 
327 namespace BasisFactory {
328 
336 template<std::size_t k>
338 {
339  return [](const auto& gridView) {
340  return BrezziDouglasMariniPreBasis<std::decay_t<decltype(gridView)>, k>(gridView);
341  };
342 }
343 
344 } // end namespace BasisFactory
345 
346 
347 
348 // *****************************************************************************
349 // This is the actual global basis implementation based on the reusable parts.
350 // *****************************************************************************
351 
359 template<typename GV, int k>
361 
362 } // end namespace Functions
363 } // end namespace Dune
364 
365 
366 #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:337
Definition: polynomial.hh:10
Definition: brezzidouglasmarinibasis.hh:278
typename GV::template Codim< 0 >::Entity Element
Definition: brezzidouglasmarinibasis.hh:284
const FiniteElementMap * finiteElementMap_
Definition: brezzidouglasmarinibasis.hh:322
const Element & element() const
Return current element, throw if unbound.
Definition: brezzidouglasmarinibasis.hh:296
std::size_t size_type
Definition: brezzidouglasmarinibasis.hh:283
FiniteElement finiteElement_
Definition: brezzidouglasmarinibasis.hh:320
const FiniteElement & finiteElement() const
Return the LocalFiniteElement for the element we are bound to.
Definition: brezzidouglasmarinibasis.hh:305
typename Impl::BDMLocalFiniteElementMap< GV, dim, double, k > FiniteElementMap
Definition: brezzidouglasmarinibasis.hh:285
const Element * element_
Definition: brezzidouglasmarinibasis.hh:321
Impl::GlobalValuedLocalFiniteElement< Impl::ContravariantPiolaTransformator, typename FiniteElementMap::FiniteElement, Element > FiniteElement
Definition: brezzidouglasmarinibasis.hh:288
void bind(const Element &e)
Bind to element.
Definition: brezzidouglasmarinibasis.hh:311
BrezziDouglasMariniNode(const FiniteElementMap *finiteElementMap)
Definition: brezzidouglasmarinibasis.hh:290
Definition: brezzidouglasmarinibasis.hh:152
std::size_t size_type
Definition: brezzidouglasmarinibasis.hh:160
std::array< int, 2 > dofsPerCodim_
Definition: brezzidouglasmarinibasis.hh:270
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: brezzidouglasmarinibasis.hh:188
size_type dimension() const
Definition: brezzidouglasmarinibasis.hh:221
static constexpr size_type minMultiIndexSize
Definition: brezzidouglasmarinibasis.hh:165
static constexpr size_type maxMultiIndexSize
Definition: brezzidouglasmarinibasis.hh:164
std::array< size_t, dim+1 > codimOffset_
Definition: brezzidouglasmarinibasis.hh:267
size_type size(const SizePrefix prefix) const
Return number possible values for next position in multi index.
Definition: brezzidouglasmarinibasis.hh:214
Node makeNode() const
Create tree node.
Definition: brezzidouglasmarinibasis.hh:202
GV GridView
The grid view that the FE space is defined on.
Definition: brezzidouglasmarinibasis.hh:159
BrezziDouglasMariniPreBasis(const GridView &gv)
Constructor for a given grid view object.
Definition: brezzidouglasmarinibasis.hh:169
FiniteElementMap finiteElementMap_
Definition: brezzidouglasmarinibasis.hh:268
void update(const GridView &gv)
Definition: brezzidouglasmarinibasis.hh:194
void initializeIndices()
Definition: brezzidouglasmarinibasis.hh:179
size_type size() const
Definition: brezzidouglasmarinibasis.hh:207
static constexpr size_type multiIndexBufferSize
Definition: brezzidouglasmarinibasis.hh:166
size_type maxNodeSize() const
Definition: brezzidouglasmarinibasis.hh:226
GridView gridView_
Definition: brezzidouglasmarinibasis.hh:266
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:241
Global basis for given pre-basis.
Definition: defaultglobalbasis.hh:46
size_type size() const
Definition: nodes.hh:142
void setSize(const size_type size)
Definition: nodes.hh:164
Definition: nodes.hh:186