Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
integratedskeletonbilinearform.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 DUNE_FUFEM_FORMS_INTEGRATEDSKELETONBILINEARFORM_HH
8#define DUNE_FUFEM_FORMS_INTEGRATEDSKELETONBILINEARFORM_HH
9
10#include <cstddef>
11#include <type_traits>
12#include <utility>
13
17
23
24
25
26namespace Dune::Fufem::Forms {
27
28
29
43 template<class BilinearOperator, class Patch, class QuadratureHint=Dune::Fufem::Forms::QuadratureHints::KeepOrder>
45 {
47 using TestRootLocalView = typename TestRootBasis::LocalView;
48 using TestRootTree = typename TestRootLocalView::Tree;
49
51 using AnsatzRootLocalView = typename AnsatzRootBasis::LocalView;
52 using AnsatzRootTree = typename AnsatzRootLocalView::Tree;
53
54 using LocalOperator = decltype(localOperator(std::declval<BilinearOperator>()));
55
57 using QuadratureRule = typename CacheManager::QuadratureRule;
58 using QuadraturePoint = typename QuadratureRule::value_type;
59
60 public:
61 using Element = typename BilinearOperator::Element;
62 using Intersection = typename TestRootBasis::GridView::Intersection;
63
64 IntegratedSkeletonBilinearForm(const BilinearOperator& sumOperator, const Patch& patch, QuadratureHint quadratureHint)
65 : sumOperator_(sumOperator)
66 , sumLocalOperator_(localOperator(sumOperator_))
67 , sumLocalOperatorFlipped_(localOperator(sumOperator_))
68 , patch_(patch)
69 , quadratureHint_(quadratureHint)
70 {}
71
72 IntegratedSkeletonBilinearForm(const BilinearOperator& sumOperator, const Patch& patch)
74 : IntegratedSkeletonBilinearForm(sumOperator, patch, QuadratureHint{})
75 {}
76
77 const BilinearOperator& integrandOperator() const
78 {
79 return sumOperator_;
80 }
81
82 // Dune::Assembler interface
83
84 void bindLocalViews (const TestRootLocalView& testLocalView, const AnsatzRootLocalView& ansatzLocalView)
85 {
86 sumLocalOperator_.registerLocalViews(testLocalView.rootLocalView(), ansatzLocalView.rootLocalView());
87 sumLocalOperator_.registerCaches(insideCache_);
88 sumLocalOperatorFlipped_.registerOutsideLocalViews(testLocalView.rootLocalView(), ansatzLocalView.rootLocalView());
89 sumLocalOperatorFlipped_.registerOutsideCaches(insideCache_);
90 insidePtr_ = &testLocalView.element();
91 }
92
93 void bindOutsideLocalViews (const TestRootLocalView& testLocalView, const AnsatzRootLocalView& ansatzLocalView)
94 {
95 sumLocalOperator_.registerOutsideLocalViews(testLocalView.rootLocalView(), ansatzLocalView.rootLocalView());
96 sumLocalOperator_.registerOutsideCaches(outsideCache_);
97 sumLocalOperatorFlipped_.registerLocalViews(testLocalView.rootLocalView(), ansatzLocalView.rootLocalView());
98 sumLocalOperatorFlipped_.registerCaches(outsideCache_);
99 outsidePtr_ = &testLocalView.element();
100 }
101
102 void bindElement (const Element& element)
103 {}
104
105 template <class LocalPatterns>
106 void assembleInteriorIntersectionMatrixPattern (const Intersection& intersection, LocalPatterns& localPatterns)
107 {
108 if (not patch_.contains(intersection))
109 return;
110 localPatterns[0][0].addAll();
111 localPatterns[0][1].addAll();
112 localPatterns[1][0].addAll();
113 localPatterns[1][1].addAll();
114 }
115
116 template <class LocalMatrices>
117 void assembleInteriorIntersectionMatrix (const Intersection& intersection, LocalMatrices& localMatrices)
118 {
119 using namespace Dune::Indices;
120 using namespace Dune::Fufem::Forms::Impl::Tensor;
121
122 if (not patch_.contains(intersection))
123 return;
124
125 bool isOriented = true;
126 if constexpr (requires { patch_.isOriented(intersection); })
127 isOriented = patch_.isOriented(intersection);
128
129 // LocalMatrices only supports localMatrices[i][j][k][l] and localMatrices[i][j](k,l).
130 // The TensorView provides the unified access via localTensor(i,j,k,l).
131 auto localTensor = TensorView(localMatrices, _4);
132
133 if (isOriented)
134 {
135 sumLocalOperator_.bind(intersection, *insidePtr_, *outsidePtr_);
136
137 const auto& geometry = intersection.geometry();
138 const auto& geometryInInside = intersection.geometryInInside();
139 const auto& geometryInOutside = intersection.geometryInOutside();
140
141 // Since we will often have many boundary terms (e.g. for DG)
142 // while evaluations are currently not cached across elements,
143 // we use a single quadrature rule for all addends despite the
144 // fact that a lower order might also be sufficient for some of them.
145 auto key = quadratureHint_(sumLocalOperator_.quadratureRuleKey());
146 key.setGeometryType(geometry.type());
148
149 // Notice that we cannot easily cache evaluation by identifying quadrature rules
150 // on intersections across different elements. To guarantee that quadrature
151 // points match up on inside and outside, we have to compute the element coordinates
152 // of intersection quadrature points using the intersection. This has the effect
153 // that the e.g. points on face 2 may be different on two elements because the
154 // intersections are not oriented consistently. The latter problem could be solved
155 // by computing the element coordinates using the reference element embedding, but
156 // then inside and outside quadrature points would not match up.
157 //
158 // Hence we take the intersection approach (which is also robust wrt. non-conforming
159 // intersections) and do not cache across different intersections so far.
160 // Since the operator expects a cache, we use caches that are reset for any intersection.
161 insideRule_.resize(rule.size(), QuadraturePoint(typename QuadraturePoint::Vector(), 0));
162 for (auto k : Dune::range(rule.size()))
163 insideRule_[k] = QuadraturePoint(geometryInInside.global(rule[k].position()), 0);
164 insideCache_.setRule(insideRule_);
165
166 outsideRule_.resize(rule.size(), QuadraturePoint(typename QuadraturePoint::Vector(), 0));
167 for (auto k : Dune::range(rule.size()))
168 outsideRule_[k] = QuadraturePoint(geometryInOutside.global(rule[k].position()), 0);
169 outsideCache_.setRule(outsideRule_);
170
171 sumLocalOperator_.bindToCaches(insideCache_, outsideCache_);
172
173 for (auto k : Dune::range(rule.size()))
174 {
175 Impl::forEachTupleEntry(sumLocalOperator_.operators(), [&](auto& op) {
176 const auto integrationWeight = rule[k].weight() * geometry.integrationElement(rule[k].position());
177 axpy(integrationWeight, op(k), localTensor);
178 });
179 }
180 }
181 else
182 {
183 // If the intersection is not oriented, we need to flip the two leading indices
184 auto flippedLocalTensor = FlipIndices(localTensor, _2);
185
186 sumLocalOperatorFlipped_.bind(intersection, *outsidePtr_, *insidePtr_);
187
188 const auto& geometry = intersection.geometry();
189 const auto& geometryInInside = intersection.geometryInInside();
190 const auto& geometryInOutside = intersection.geometryInOutside();
191
192 // Since we will often have many boundary terms (e.g. for DG)
193 // while evaluations are currently not cached across elements,
194 // we use a single quadrature rule for all addends despite the
195 // fact that a lower order might also be sufficient for some of them.
196 auto key = quadratureHint_(sumLocalOperatorFlipped_.quadratureRuleKey());
197 key.setGeometryType(geometry.type());
199
200 // Notice that we cannot easily cache evaluation by identifying quadrature rules
201 // on intersections across different elements. To guarantee that quadrature
202 // points match up on inside and outside, we have to compute the element coordinates
203 // of intersection quadrature points using the intersection. This has the effect
204 // that the e.g. points on face 2 may be different on two elements because the
205 // intersections are not oriented consistently. The latter problem could be solved
206 // by computing the element coordinates using the reference element embedding, but
207 // then inside and outside quadrature points would not match up.
208 //
209 // Hence we take the intersection approach (which is also robust wrt. non-conforming
210 // intersections) and do not cache across different intersections so far.
211 // Since the operator expects a cache, we use caches that are reset for any intersection.
212 insideRule_.resize(rule.size(), QuadraturePoint(typename QuadraturePoint::Vector(), 0));
213 for (auto k : Dune::range(rule.size()))
214 insideRule_[k] = QuadraturePoint(geometryInInside.global(rule[k].position()), 0);
215 insideCache_.setRule(insideRule_);
216
217 outsideRule_.resize(rule.size(), QuadraturePoint(typename QuadraturePoint::Vector(), 0));
218 for (auto k : Dune::range(rule.size()))
219 outsideRule_[k] = QuadraturePoint(geometryInOutside.global(rule[k].position()), 0);
220 outsideCache_.setRule(outsideRule_);
221
222 sumLocalOperatorFlipped_.bindToCaches(outsideCache_, insideCache_);
223
224 for (auto k : Dune::range(rule.size()))
225 {
226 Impl::forEachTupleEntry(sumLocalOperatorFlipped_.operators(), [&](auto& op) {
227 const auto integrationWeight = rule[k].weight() * geometry.integrationElement(rule[k].position());
228 axpy(integrationWeight, op(k), flippedLocalTensor);
229 });
230 }
231 }
232
233 }
234
235 private:
236 const BilinearOperator sumOperator_;
237 mutable LocalOperator sumLocalOperator_;
238 mutable LocalOperator sumLocalOperatorFlipped_;
239 const Element* insidePtr_ = nullptr;
240 const Element* outsidePtr_ = nullptr;
241 mutable QuadratureRule insideRule_;
242 mutable QuadratureRule outsideRule_;
243 CacheManager insideCache_;
244 CacheManager outsideCache_;
245 const Patch& patch_;
246 QuadratureHint quadratureHint_;
247 };
248
249 template<class BilinearOperator, class Patch>
251
252
253
254 template<class BilinearOperator, class Patch, class QuadratureHint>
255 struct IsLocalAssembler<IntegratedSkeletonBilinearForm<BilinearOperator, Patch, QuadratureHint>> : public std::true_type {};
256
257
258
259} // namespace Dune::Fufem::Forms
260
261
262#endif // DUNE_FUFEM_FORMS_INTEGRATEDSKELETONBILINEARFORM_HH
static constexpr IntegralRange< T > range(T from, T to) noexcept
Definition baseclass.hh:22
Local assembler corresponding to a skeleton bilinear form.
Definition integratedskeletonbilinearform.hh:45
void bindOutsideLocalViews(const TestRootLocalView &testLocalView, const AnsatzRootLocalView &ansatzLocalView)
Definition integratedskeletonbilinearform.hh:93
IntegratedSkeletonBilinearForm(const BilinearOperator &sumOperator, const Patch &patch, QuadratureHint quadratureHint)
Definition integratedskeletonbilinearform.hh:64
typename TestRootBasis::GridView::Intersection Intersection
Definition integratedskeletonbilinearform.hh:62
void assembleInteriorIntersectionMatrix(const Intersection &intersection, LocalMatrices &localMatrices)
Definition integratedskeletonbilinearform.hh:117
void assembleInteriorIntersectionMatrixPattern(const Intersection &intersection, LocalPatterns &localPatterns)
Definition integratedskeletonbilinearform.hh:106
typename BilinearOperator::Element Element
Definition integratedskeletonbilinearform.hh:61
IntegratedSkeletonBilinearForm(const BilinearOperator &sumOperator, const Patch &patch)
Definition integratedskeletonbilinearform.hh:72
const BilinearOperator & integrandOperator() const
Definition integratedskeletonbilinearform.hh:77
void bindElement(const Element &element)
Definition integratedskeletonbilinearform.hh:102
void bindLocalViews(const TestRootLocalView &testLocalView, const AnsatzRootLocalView &ansatzLocalView)
Definition integratedskeletonbilinearform.hh:84
Definition localsumassembler.hh:80
A class for managing caches of different types.
Definition shapefunctioncache.hh:612
Dune::QuadratureRule< CT, dimension > QuadratureRule
Definition shapefunctioncache.hh:614
static const Dune::QuadratureRule< coord_type, dim > & rule(const Dune::GeometryType &gt, const int order, int refinement)
Definition quadraturerulecache.hh:196
T forward(T... args)