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