DUNE PDELab (git)

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#include <dune/functions/functionspacebases/leafprebasismixin.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_shared<LocalFiniteElementVirtualImp<CubeFiniteElement> >(CubeFiniteElement(i));
97
98 for (size_t i = 0; i < simplexVariant_.size(); i++)
99 simplexVariant_[i] = std::make_shared<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::shared_ptr<LocalFiniteElementVirtualImp<CubeFiniteElement> > > cubeVariant_;
128 std::vector<std::shared_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>
152class BrezziDouglasMariniPreBasis :
153 public LeafPreBasisMixin< BrezziDouglasMariniPreBasis<GV,k> >
154{
155 static const int dim = GV::dimension;
156 using FiniteElementMap = typename Impl::BDMLocalFiniteElementMap<GV, dim, double, k>;
157
158public:
159
161 using GridView = GV;
162 using size_type = std::size_t;
163
164 using Node = BrezziDouglasMariniNode<GV, k>;
165
167 BrezziDouglasMariniPreBasis(const GridView& gv) :
168 gridView_(gv),
169 finiteElementMap_(gv)
170 {
171 // There is no inherent reason why the basis shouldn't work for grids with more than one
172 // element types. Somebody simply has to sit down and implement the missing bits.
173 if (gv.indexSet().types(0).size() > 1)
174 DUNE_THROW(Dune::NotImplemented, "Brezzi-Douglas-Marini basis is only implemented for grids with a single element type");
175 }
176
177 void initializeIndices()
178 {
179 codimOffset_[0] = 0;
180 codimOffset_[1] = codimOffset_[0] + dofsPerCodim_[0] * gridView_.size(0);
181 //if (dim==3) codimOffset_[2] = codimOffset_[1] + dofsPerCodim[1] * gridView_.size(1);
182 }
183
186 const GridView& gridView() const
187 {
188 return gridView_;
189 }
190
191 /* \brief Update the stored grid view, to be called if the grid has changed */
192 void update (const GridView& gv)
193 {
194 gridView_ = gv;
195 }
196
200 Node makeNode() const
201 {
202 return Node{&finiteElementMap_};
203 }
204
205 size_type dimension() const
206 {
207 return dofsPerCodim_[0] * gridView_.size(0) + dofsPerCodim_[1] * gridView_.size(1); // only 2d
208 }
209
210 size_type maxNodeSize() const
211 {
212 // The implementation currently only supports grids with a single element type.
213 // We can therefore return the actual number of dofs here.
214 GeometryType elementType = *(gridView_.indexSet().types(0).begin());
215 size_t numFaces = ReferenceElements<double,dim>::general(elementType).size(1);
216 return dofsPerCodim_[0] + dofsPerCodim_[1] * numFaces;
217 }
218
224 template<typename It>
225 It indices(const Node& node, It it) const
226 {
227 const auto& gridIndexSet = gridView().indexSet();
228 const auto& element = node.element();
229
230 // throw if element is not of predefined type
231 if (not(element.type().isCube()) and not(element.type().isSimplex()))
232 DUNE_THROW(Dune::NotImplemented, "BrezziDouglasMariniBasis only implemented for cube and simplex elements.");
233
234 for(std::size_t i=0, end=node.size(); i<end; ++i, ++it)
235 {
236 Dune::LocalKey localKey = node.finiteElement().localCoefficients().localKey(i);
237
238 // The dimension of the entity that the current dof is related to
239 size_t subentity = localKey.subEntity();
240 size_t codim = localKey.codim();
241
242 *it = { codimOffset_[codim] +
243 dofsPerCodim_[codim] * gridIndexSet.subIndex(element, subentity, codim) + localKey.index() };
244 }
245
246 return it;
247 }
248
249protected:
250 GridView gridView_;
251 std::array<size_t,dim+1> codimOffset_;
252 FiniteElementMap finiteElementMap_;
253 // Number of dofs per entity type depending on the entity's codimension and type
254 std::array<int,2> dofsPerCodim_ {{dim*(k-1)*3, dim+(k-1)}};
255};
256
257
258
259template<typename GV, int k>
260class BrezziDouglasMariniNode :
261 public LeafBasisNode
262{
263 static const int dim = GV::dimension;
264
265public:
266
267 using size_type = std::size_t;
268 using Element = typename GV::template Codim<0>::Entity;
269 using FiniteElementMap = typename Impl::BDMLocalFiniteElementMap<GV, dim, double, k>;
270 using FiniteElement = Impl::GlobalValuedLocalFiniteElement<Impl::ContravariantPiolaTransformator,
271 typename FiniteElementMap::FiniteElement,
272 Element>;
273
274 BrezziDouglasMariniNode(const FiniteElementMap* finiteElementMap) :
275 element_(nullptr),
276 finiteElementMap_(finiteElementMap)
277 {}
278
280 const Element& element() const
281 {
282 return *element_;
283 }
284
289 const FiniteElement& finiteElement() const
290 {
291 return finiteElement_;
292 }
293
295 void bind(const Element& e)
296 {
297 element_ = &e;
298 finiteElement_.bind((finiteElementMap_->find(*element_)), e);
299 this->setSize(finiteElement_.size());
300 }
301
302protected:
303
304 FiniteElement finiteElement_;
305 const Element* element_;
306 const FiniteElementMap* finiteElementMap_;
307};
308
309
310
311namespace BasisFactory {
312
320template<std::size_t k>
322{
323 return [](const auto& gridView) {
324 return BrezziDouglasMariniPreBasis<std::decay_t<decltype(gridView)>, k>(gridView);
325 };
326}
327
328} // end namespace BasisFactory
329
330
331
332// *****************************************************************************
333// This is the actual global basis implementation based on the reusable parts.
334// *****************************************************************************
335
343template<typename GV, int k>
344using BrezziDouglasMariniBasis = DefaultGlobalBasis<BrezziDouglasMariniPreBasis<GV, k> >;
345
346} // end namespace Functions
347} // end namespace Dune
348
349
350#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_BREZZIDOUGLASMARINIBASIS_HH
Describe position of one degree of freedom.
Definition: localkey.hh:24
constexpr unsigned int index() const noexcept
Return offset within subentity.
Definition: localkey.hh:70
constexpr unsigned int codim() const noexcept
Return codim of associated entity.
Definition: localkey.hh:63
constexpr unsigned int subEntity() const noexcept
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:321
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)