DUNE-FUNCTIONS (2.8)

brezzidouglasmarinibasis.hh
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
19#include <dune/functions/functionspacebases/globalvaluedlocalfiniteelement.hh>
20#include <dune/functions/functionspacebases/nodes.hh>
21#include <dune/functions/functionspacebases/defaultglobalbasis.hh>
22#include <dune/functions/functionspacebases/flatmultiindex.hh>
23
24namespace Dune {
25namespace Functions {
26
27namespace 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
148template<typename GV, int k>
149class BrezziDouglasMariniNode;
150
151template<typename GV, int k, class MI>
152class BrezziDouglasMariniPreBasis
153{
154 static const int dim = GV::dimension;
155 using FiniteElementMap = typename Impl::BDMLocalFiniteElementMap<GV, dim, double, k>;
156
157public:
158
160 using GridView = GV;
161 using size_type = std::size_t;
162
163 using Node = BrezziDouglasMariniNode<GV, k>;
164
166 using IndexSet = Impl::DefaultNodeIndexSet<BrezziDouglasMariniPreBasis>;
167
169 using MultiIndex = MI;
170
171 using SizePrefix = Dune::ReservedVector<size_type, 1>;
172
174 BrezziDouglasMariniPreBasis(const GridView& gv) :
175 gridView_(gv),
176 finiteElementMap_(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
184 void initializeIndices()
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.")]]
221 IndexSet makeIndexSet() const
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
239 size_type dimension() const
240 {
241 return size();
242 }
243
244 size_type maxNodeSize() const
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
283protected:
284 GridView gridView_;
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
293template<typename GV, int k>
294class BrezziDouglasMariniNode :
295 public LeafBasisNode
296{
297 static const int dim = GV::dimension;
298
299public:
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
323 const FiniteElement& finiteElement() const
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
336protected:
337
338 FiniteElement finiteElement_;
339 const Element* element_;
340 const FiniteElementMap* finiteElementMap_;
341};
342
343
344
345namespace BasisFactory {
346
347namespace Imp {
348
349template<std::size_t k>
350class BrezziDouglasMariniPreBasisFactory
351{
352public:
353 static const std::size_t requiredMultiIndexSize=1;
354
355 template<class MultiIndex, class GridView>
356 auto makePreBasis(const GridView& gridView) const
357 -> BrezziDouglasMariniPreBasis<GridView, k, MultiIndex>
358 {
359 return {gridView};
360 }
361};
362
363} // end namespace BasisFactory::Imp
364
372template<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
393template<typename GV, int k>
394using BrezziDouglasMariniBasis = DefaultGlobalBasis<BrezziDouglasMariniPreBasis<GV, k, FlatMultiIndex<std::size_t>> >;
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)