Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
interiorpenaltydgassembler.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
4// SPDX-FileCopyrightText: Copyright © DUNE-FUFEM Project contributors, see file AUTHORS.md
5// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
6
7#ifndef IPDG_ASSEMBLER_HH
8#define IPDG_ASSEMBLER_HH
9
10#ifndef DUNE_FUFEM_DISABLE_HEADER_DEPRECATION
11#warning This header is deprecated and will be removed after 2.11. Use Dune::Fufem::Forms instead.
12#endif
13
20// dune-common includes
25
26// dune-istl includes
27#include <dune/istl/matrix.hh>
29
30// dune-fufem includes
32
33namespace Dune::Fufem::Impl {
34
35 template <class Matrix>
37 static void addToDiagonal(Matrix& x, const typename Matrix::field_type a) {
38 for (int i = 0; i < Matrix::rows; ++i)
39 x[i][i] += a;
40 }
41
42 // Specialization for scalars (to be interpreted as 1x1 matrices)
43 template <class Matrix>
45 static void addToDiagonal(Matrix& x, const Matrix& a)
46 {
47 x += a;
48 }
49
50 template <typename FieldType, int n>
51 static void addToDiagonal(
54 x.scalar() += a;
55 }
56
57} // end namespace Dune::Fufem::Impl
58
59
70template <class GridType>
71class
72[[deprecated("This class is deprecated and will be removed after 2.11. Use Dune::Fufem::Forms instead.")]]
74{
75 enum class DGType {SIPG = -1, IIPG = 0, NIPG = 1};
76
77 static const int dim = GridType::dimension -1; // We're on the edges
78 static const int dimworld = GridType::dimensionworld;
79
80 public:
81
82 [[deprecated("This class is deprecated and will be removed after 2.11. Use Dune::Fufem::Forms instead.")]]
84 sigma0_(0),
85 dirichlet_(true),
86 dgType_((double) DGType::SIPG),
87 sigma1_(0) {}
88
89 [[deprecated("This class is deprecated and will be removed after 2.11. Use Dune::Fufem::Forms instead.")]]
90 InteriorPenaltyDGAssembler(double penalty, bool dirichlet=true, DGType dgType=DGType::SIPG, double gradientPenalty=0) :
91 sigma0_(penalty),
92 dirichlet_(dirichlet),
93 dgType_((double) dgType),
94 sigma1_(gradientPenalty) {}
95
97 void setPenalty(double penaltyParameter) {
98 if(penaltyParameter<0.0)
99 DUNE_THROW(Dune::MathError, "Penalty parameter must not be negative");
100 sigma0_ = penaltyParameter;
101 }
102
104 void setGradientPenalty(double gradientPenalty) {
105 if(gradientPenalty<0.0)
106 DUNE_THROW(Dune::MathError, "Penalty parameter must not be negative");
107 sigma1_ = gradientPenalty;
108 }
109
110 template <class Edge, class BoolMatrix, class TestLocalFE, class AnsatzLocalFE>
111 void indices(const Edge& it, BoolMatrix& isNonZero, const TestLocalFE& tFE, const AnsatzLocalFE& aFE) const
112 {
113 isNonZero = dirichlet_; // For boundary edges, only in case of Dirichlet values we need to assemble a local matrix.
114 }
115
116 template <class Edge, class BoolMatrix, class TestLocalFE, class AnsatzLocalFE>
117 void indices(const Edge& it, BoolMatrix& isNonZero, const TestLocalFE& tFEi, const AnsatzLocalFE& aFEi, const TestLocalFE& tFEo, const AnsatzLocalFE& aFEo) const
118 {
119 isNonZero = true;
120 }
121
122
127 template <class Edge, class LocalMatrix, class TestLocalFE, class AnsatzLocalFE>
128 void assemble(const Edge& edge, LocalMatrix& localMatrix, const TestLocalFE& tFE, const AnsatzLocalFE& aFE) const
129 {
130 localMatrix = 0.0;
131
132 // For Neumann data, we don't assemble on boundary edges
133 // TODO: There is no need that this has to be decided globally. It would be very easy to
134 // just decide this edge by edge for mixed b.c..
135 if (!dirichlet_)
136 return;
137
138 using FVdimworld = typename Dune::template FieldVector<double,dimworld>;
139
140 using JacobianType = typename TestLocalFE::Traits::LocalBasisType::Traits::JacobianType;
141 using RangeType = typename TestLocalFE::Traits::LocalBasisType::Traits::RangeType;
142
143 auto rows = localMatrix.N();
144 auto cols = localMatrix.M();
145
146 // get geometries of the edge and the inside element
147 const auto edgeGeometry = edge.geometry();
148 const auto insideGeometry = edge.inside().geometry();
149
150 // Get the length of the edge
151 const auto edgeLength= edgeGeometry.volume();
152
153 // get quadrature rule
154 QuadratureRuleKey tFEquad(edge.type(), tFE.localBasis().order());
155 QuadratureRuleKey quadKey = tFEquad.square();
156
157 const auto& quad = QuadratureRuleCache<double, dim>::rule(quadKey);
158
159 // store gradients of shape functions and base functions
160 std::vector<JacobianType> referenceGradients(tFE.localBasis().size());
161 std::vector<FVdimworld> gradients(tFE.localBasis().size());
162
163 // store values of shape functions
164 std::vector<RangeType> tFEvalues(tFE.localBasis().size());
165
166 // We also need a unit normal on the edge pointing away from the inner element
167 const auto outerNormal = edge.centerUnitOuterNormal();
168
169 // loop over quadrature points
170 for (size_t pt=0; pt < quad.size(); ++pt)
171 {
172 // get quadrature point
173 const auto& quadPos = quad[pt].position();
174
175 // get transposed inverse of Jacobian of transformation
176 const auto& invJacobian = insideGeometry.jacobianInverseTransposed(edge.geometryInInside().global(quadPos));
177
178 // get integration factor
179 const auto integrationElement = edgeGeometry.integrationElement(quadPos);
180
181 // get gradients of shape functions
182 tFE.localBasis().evaluateJacobian(edge.geometryInInside().global(quadPos), referenceGradients);
183
184 // transform gradients
185 for (size_t i=0; i<gradients.size(); ++i)
186 invJacobian.mv(referenceGradients[i][0], gradients[i]);
187
188 // evaluate basis functions
189 tFE.localBasis().evaluateFunction(edge.geometryInInside().global(quadPos), tFEvalues);
190
191 // compute matrix entries
192 auto z = quad[pt].weight() * integrationElement;
193 for (size_t i=0; i<rows; ++i)
194 {
195 for (size_t j=0; j<cols; ++j)
196 {
197 auto zij = -z*tFEvalues[i][0]*(gradients[j]*outerNormal);
198 zij += dgType_*z*tFEvalues[j]*(gradients[i]*outerNormal);
199 zij += sigma0_*z/edgeLength*tFEvalues[i]*tFEvalues[j];
200 // The sigma1_ stabilization term does not effect boundary edges
201 Dune::Fufem::Impl::addToDiagonal(localMatrix[i][j],zij);
202 }
203 }
204 }
205 }
206
215 template <class Edge, class LocalMatrix, class TestLocalFE, class AnsatzLocalFE>
216 void assemble(const Edge& edge, LocalMatrix& localMatrix, const TestLocalFE& tFEinside, const AnsatzLocalFE& aFEinside, const TestLocalFE& tFEoutside, const AnsatzLocalFE& aFEoutside) const
217 {
218
219 localMatrix = 0.0;
220
221 // to avoid too much duplicate code, we write this method, which was designed for the vintage intersection operator assembler, by calling
222 // the newer assembleBlockwise method.
223 using MatrixContainer = Dune::Matrix<LocalMatrix>;
224 auto mc = MatrixContainer(2,2);
225 mc[0][0].setSize(tFEinside.size(), aFEinside.size());
226 mc[0][1].setSize(tFEinside.size(), aFEoutside.size());
227 mc[1][0].setSize(tFEoutside.size(), aFEinside.size());
228 mc[1][1].setSize(tFEoutside.size(), aFEoutside.size());
229
230 // compute entries
231 assembleBlockwise(edge, mc, tFEinside, aFEinside, tFEoutside, aFEoutside);
232
233 // redistribute them into the localMatrix
234 auto rows = localMatrix.N();
235 auto cols = localMatrix.M();
236
237 const auto insideSize = tFEinside.localBasis().size();
238
239 for (size_t i=0; i<rows; ++i)
240 {
241 for (size_t j=0; j<cols; ++j)
242 {
243 // Depending on which elements i and j belong to, perform different operations.
244 // In particular, i (resp. j) < insizeSize corresponds to functions from the inner element
245 // while the others correspond to the outer element
246 if (i < insideSize)
247 localMatrix[i][j] += (j< insideSize) ? mc[0][0][i][j] : mc[0][1][i][j-insideSize];
248 else
249 localMatrix[i][j] += (j< insideSize) ? mc[1][0][i-insideSize][j] : mc[1][1][i-insideSize][j-insideSize];
250 }
251 }
252 }
253
261 template <class Edge, class MC, class TestLocalFE, class AnsatzLocalFE>
262 void assembleBlockwise(const Edge& edge, MC& matrixContainer, const TestLocalFE& tFEinside, const AnsatzLocalFE& aFEinside, const TestLocalFE& tFEoutside, const AnsatzLocalFE& aFEoutside) const
263 {
264
265 using FVdimworld = typename Dune::template FieldVector<double,dimworld>;
266
267 using JacobianType = typename TestLocalFE::Traits::LocalBasisType::Traits::JacobianType;
268 using RangeType = typename TestLocalFE::Traits::LocalBasisType::Traits::RangeType;
269
270 // get geometry and store it
271 const auto edgeGeometry = edge.geometry();
272 const auto insideGeometry = edge.inside().geometry();
273 const auto outsideGeometry = edge.outside().geometry();
274
275 const auto edgeLength = edgeGeometry.volume();
276 matrixContainer = 0.0;
277
278 // get quadrature rule
279 QuadratureRuleKey tFEquad(edge.type(), std::max(tFEinside.localBasis().order(),tFEoutside.localBasis().order()));
280 QuadratureRuleKey quadKey = tFEquad.square();
281
282 const auto& quad = QuadratureRuleCache<double, dim>::rule(quadKey);
283
284 // store gradients for both the inner and outer elements
285 std::vector<JacobianType> insideReferenceGradients(tFEinside.localBasis().size());
286 std::vector<JacobianType> outsideReferenceGradients(tFEoutside.localBasis().size());
287 std::vector<FVdimworld> insideGradients(tFEinside.localBasis().size());
288 std::vector<FVdimworld> outsideGradients(tFEoutside.localBasis().size());
289
290 // store values of shape functions
291 std::vector<RangeType> tFEinsideValues(tFEinside.localBasis().size());
292 std::vector<RangeType> tFEoutsideValues(tFEoutside.localBasis().size());
293
294 const auto outerNormal = edge.centerUnitOuterNormal();
295
296 // loop over quadrature points
297 for (size_t pt=0; pt < quad.size(); ++pt)
298 {
299 // get quadrature point
300 const auto& quadPos = quad[pt].position();
301
302 // get transposed inverse of Jacobian of transformation
303 const auto& invJacobian = insideGeometry.jacobianInverseTransposed(edge.geometryInInside().global(quadPos));
304 const auto& outsideInvJacobian = outsideGeometry.jacobianInverseTransposed(edge.geometryInOutside().global(quadPos));
305
306 // get integration factor
307 const auto integrationElement = edgeGeometry.integrationElement(quadPos);
308
309 // get gradients of shape functions on both the inside and outside element
310 tFEinside.localBasis().evaluateJacobian(edge.geometryInInside().global(quadPos), insideReferenceGradients);
311 tFEoutside.localBasis().evaluateJacobian(edge.geometryInOutside().global(quadPos), outsideReferenceGradients);
312
313 // transform gradients
314 for (size_t i=0; i<insideGradients.size(); ++i)
315 invJacobian.mv(insideReferenceGradients[i][0], insideGradients[i]);
316 for (size_t i=0; i<outsideGradients.size(); ++i)
317 outsideInvJacobian.mv(outsideReferenceGradients[i][0], outsideGradients[i]);
318
319 // evaluate basis functions
320 tFEinside.localBasis().evaluateFunction(edge.geometryInInside().global(quadPos), tFEinsideValues);
321 tFEoutside.localBasis().evaluateFunction(edge.geometryInOutside().global(quadPos), tFEoutsideValues);
322
323 // compute matrix entries
324 auto z = quad[pt].weight() * integrationElement;
325
326 // Basis functions from inside as test functions
327 for (size_t i=0; i<tFEinside.localBasis().size(); ++i)
328 {
329 // Basis functions from inside as ansatz functions
330 for (size_t j=0; j<aFEinside.localBasis().size(); ++j)
331 {
332 // M11, see Riviere, p. 54f
333 auto zij = -0.5*z*tFEinsideValues[i][0]*(insideGradients[j]*outerNormal);
334 zij += 0.5*dgType_*z*tFEinsideValues[j]*(insideGradients[i]*outerNormal);
335 zij += sigma0_*z/edgeLength*tFEinsideValues[i]*tFEinsideValues[j];
336 zij += sigma1_*z/edgeLength*(insideGradients[i]*outerNormal)*(insideGradients[j]*outerNormal);
337 Dune::Fufem::Impl::addToDiagonal(matrixContainer[0][0][i][j],zij);
338 }
339 // Basis functions from outside as ansatz functions
340 for (size_t j=0; j<aFEoutside.localBasis().size(); ++j) {
341 // M12
342 auto zij = -0.5*z*tFEinsideValues[i][0]*(outsideGradients[j]*outerNormal);
343 zij -= 0.5*dgType_*z*tFEoutsideValues[j]*(insideGradients[i]*outerNormal);
344 zij -= sigma0_*z/edgeLength*tFEinsideValues[i]*tFEoutsideValues[j];
345 zij -= sigma1_*z/edgeLength*(insideGradients[i]*outerNormal)*(outsideGradients[j]*outerNormal);
346 Dune::Fufem::Impl::addToDiagonal(matrixContainer[0][1][i][j],zij);
347 }
348 }
349 // Basis functions from outside as test functions
350 for (size_t i=0; i<tFEoutside.localBasis().size(); ++i) {
351 // Basis functions from inside as ansatz functions
352 for (size_t j=0; j<aFEinside.localBasis().size(); ++j) {
353 // M21, see Riviere, p. 54f
354 auto zij = 0.5*z*tFEoutsideValues[i][0]*(insideGradients[j]*outerNormal);
355 zij += 0.5*dgType_*z*tFEinsideValues[j]*(outsideGradients[i]*outerNormal);
356 zij -= sigma0_*z/edgeLength*tFEoutsideValues[i]*tFEinsideValues[j];
357 zij -= sigma1_*z/edgeLength*(outsideGradients[i]*outerNormal)*(insideGradients[j]*outerNormal);
358 Dune::Fufem::Impl::addToDiagonal(matrixContainer[1][0][i][j],zij);
359 }
360 // Basis functions from outside as ansatz functions
361 for (size_t j=0; j<aFEoutside.localBasis().size(); ++j) {
362 // M22
363 auto zij = 0.5*z*tFEoutsideValues[i][0]*(outsideGradients[j]*outerNormal);
364 zij -= 0.5*dgType_*z*tFEoutsideValues[j]*(outsideGradients[i]*outerNormal);
365 zij += sigma0_*z/edgeLength*tFEoutsideValues[i]*tFEoutsideValues[j];
366 zij += sigma1_*z/edgeLength*(outsideGradients[i]*outerNormal)*(outsideGradients[j]*outerNormal);
367 Dune::Fufem::Impl::addToDiagonal(matrixContainer[1][1][i][j],zij);
368 }
369 }
370 }
371 }
372
373 private:
374
375
382 double sigma0_; // Penalizes discontinuities
383
384
386 bool dirichlet_;
387
388 const double dgType_; // -1 leads to the symmetric interior penalty DG variant. {-1,0,1} are possible values.
389
394 double sigma1_; // Penalizes jumps of the normal derivative along the non-boundary edges
395};
396#endif
int size() const
size_type dim() const
#define DUNE_THROW(E,...)
typename Imp::BlockTraits< T >::field_type field_type
const K & scalar() const
Local assembler for edge contributions in the Interior Penalty Discontinuous Galerkin (IPDG) method.
Definition interiorpenaltydgassembler.hh:74
void assemble(const Edge &edge, LocalMatrix &localMatrix, const TestLocalFE &tFE, const AnsatzLocalFE &aFE) const
Assemble penalty term for boundary edges.
Definition interiorpenaltydgassembler.hh:128
void assemble(const Edge &edge, LocalMatrix &localMatrix, const TestLocalFE &tFEinside, const AnsatzLocalFE &aFEinside, const TestLocalFE &tFEoutside, const AnsatzLocalFE &aFEoutside) const
Assemble penalty term for interior edges.
Definition interiorpenaltydgassembler.hh:216
InteriorPenaltyDGAssembler(double penalty, bool dirichlet=true, DGType dgType=DGType::SIPG, double gradientPenalty=0)
Definition interiorpenaltydgassembler.hh:90
void assembleBlockwise(const Edge &edge, MC &matrixContainer, const TestLocalFE &tFEinside, const AnsatzLocalFE &aFEinside, const TestLocalFE &tFEoutside, const AnsatzLocalFE &aFEoutside) const
Assemble penalty term for interior edges.
Definition interiorpenaltydgassembler.hh:262
void indices(const Edge &it, BoolMatrix &isNonZero, const TestLocalFE &tFEi, const AnsatzLocalFE &aFEi, const TestLocalFE &tFEo, const AnsatzLocalFE &aFEo) const
Definition interiorpenaltydgassembler.hh:117
void indices(const Edge &it, BoolMatrix &isNonZero, const TestLocalFE &tFE, const AnsatzLocalFE &aFE) const
Definition interiorpenaltydgassembler.hh:111
InteriorPenaltyDGAssembler()
Definition interiorpenaltydgassembler.hh:83
void setPenalty(double penaltyParameter)
Definition interiorpenaltydgassembler.hh:97
void setGradientPenalty(double gradientPenalty)
Definition interiorpenaltydgassembler.hh:104
A token that specifies a quadrature rule.
Definition quadraturerulecache.hh:39
QuadratureRuleKey square() const
Definition quadraturerulecache.hh:172
static const Dune::QuadratureRule< coord_type, dim > & rule(const Dune::GeometryType &gt, const int order, int refinement)
Definition quadraturerulecache.hh:196
T max(T... args)
T size(T... args)