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