Dune Core Modules (2.9.0)

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>
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
23namespace Dune {
24namespace Functions {
25
26namespace 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
147template<typename GV, int k>
148class BrezziDouglasMariniNode;
149
150template<typename GV, int k>
151class BrezziDouglasMariniPreBasis
152{
153 static const int dim = GV::dimension;
154 using FiniteElementMap = typename Impl::BDMLocalFiniteElementMap<GV, dim, double, k>;
155
156public:
157
159 using GridView = GV;
160 using size_type = std::size_t;
161
162 using Node = BrezziDouglasMariniNode<GV, k>;
163
164 static constexpr size_type maxMultiIndexSize = 1;
165 static constexpr size_type minMultiIndexSize = 1;
166 static constexpr size_type multiIndexBufferSize = 1;
167
169 BrezziDouglasMariniPreBasis(const GridView& gv) :
170 gridView_(gv),
171 finiteElementMap_(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
179 void initializeIndices()
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
221 size_type dimension() const
222 {
223 return size();
224 }
225
226 size_type maxNodeSize() const
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
265protected:
266 GridView gridView_;
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
275template<typename GV, int k>
276class BrezziDouglasMariniNode :
277 public LeafBasisNode
278{
279 static const int dim = GV::dimension;
280
281public:
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
305 const FiniteElement& finiteElement() const
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
318protected:
319
320 FiniteElement finiteElement_;
321 const Element* element_;
322 const FiniteElementMap* finiteElementMap_;
323};
324
325
326
327namespace BasisFactory {
328
336template<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
359template<typename GV, int k>
360using BrezziDouglasMariniBasis = DefaultGlobalBasis<BrezziDouglasMariniPreBasis<GV, k> >;
361
362} // end namespace Functions
363} // end namespace Dune
364
365
366#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_BREZZIDOUGLASMARINIBASIS_HH
Describe position of one degree of freedom.
Definition: localkey.hh:23
unsigned int index() const
Return offset within subentity.
Definition: localkey.hh:68
unsigned int codim() const
Return codim of associated entity.
Definition: localkey.hh:62
unsigned int subEntity() const
Return number of associated subentity.
Definition: localkey.hh:56
Default exception for dummy implementations.
Definition: exceptions.hh:263
A few common exception classes.
GeometryType
Type representing VTK's entity geometry types.
Definition: common.hh:132
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
auto brezziDouglasMarini()
Create a pre-basis factory that can create a Brezzi-Douglas-Marini pre-basis.
Definition: brezzidouglasmarinibasis.hh:337
Dune namespace.
Definition: alignedallocator.hh:13
static const ReferenceElement & general(const GeometryType &type)
get general reference elements
Definition: referenceelements.hh:198
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)