Dune-Fufem 2.12-git
Loading...
Searching...
No Matches
boundunaryoperator.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_BOUNDUNARYOPERATOR_HH
8#define DUNE_FUFEM_FORMS_BOUNDUNARYOPERATOR_HH
9
10#include <cstddef>
11#include <type_traits>
12#include <tuple>
13#include <utility>
14
20
22#include <dune/functions/backends/concepts.hh>
24
30
31
32
33namespace Dune::Fufem::Forms {
34
35
54 template<class Op, class V>
56 {
57 using UnaryOperator = Op;
58 using LocalUnaryOperator = decltype(localOperator(std::declval<UnaryOperator>()));
59 using Tree = typename std::decay_t<decltype(std::get<0>(std::declval<UnaryOperator>().basis()))>::LocalView::Tree;
60 using NodeFlags = typename TypeTree::UniformTreeContainer<char, Tree>;
61
62 template<class OP, class Func>
63 static void forEachOperator(OP&& op, Func&& f)
64 {
65 if constexpr (isOperator_v<UnaryOperator>)
66 f(op);
67 else if constexpr (isSumOperator_v<UnaryOperator>)
68 Impl::forEachTupleEntry(op.operators(), f);
69 }
70
74
75 public:
76
77 // Types present in DiscreteGlobalBasisFunctionBase
79 using Vector = V;
81 using GridView = typename Basis::GridView;
83 using Domain = typename EntitySet::GlobalCoordinate;
84 using LocalDomain = typename EntitySet::LocalCoordinate;
85
86 // Types required by Operator interface
87 using Element = typename EntitySet::Element;
89
90 BoundUnaryOperator(const UnaryOperator& unaryOperator, const Vector& coefficients) :
91 cacheId_(*this),
92 unaryOperator_(unaryOperator),
94 entitySet_(std::get<0>(unaryOperator.basis()).gridView())
95 {
96 static_assert(isOperatorOrSumOperator_v<UnaryOperator>, "The type passed to BoundUnaryOperator is not a operator.");
97 static_assert(UnaryOperator::arity==1, "The operator passed to BoundUnaryOperator is not unary.");
98 }
99
101 cacheId_(*this),
102 unaryOperator_(unaryOperator),
103 coefficients_(std::make_shared<const Vector>(std::move(coefficients))),
104 entitySet_(std::get<0>(unaryOperator.basis()).gridView())
105 {
106 static_assert(isOperatorOrSumOperator_v<UnaryOperator>, "The type passed to BoundUnaryOperator is not a operator.");
107 static_assert(UnaryOperator::arity==1, "The operator passed to BoundUnaryOperator is not unary.");
108 }
109
111 cacheId_(*this),
112 unaryOperator_(unaryOperator),
113 coefficients_(std::move(coefficients)),
114 entitySet_(std::get<0>(unaryOperator.basis()).gridView())
115 {
116 static_assert(isOperatorOrSumOperator_v<UnaryOperator>, "The type passed to BoundUnaryOperator is not a operator.");
117 static_assert(UnaryOperator::arity==1, "The operator passed to BoundUnaryOperator is not unary.");
118 }
119
120
121
123 {
124 public:
125
127 using Intersection = typename BoundUnaryOperator::LocalUnaryOperator::Intersection;
130
131 private:
132 static constexpr int dimension = EntitySet::Element::dimension;
133
134 using LocalView = typename Basis::LocalView;
135 using Tree = typename LocalView::Tree;
136 using size_type = typename Basis::LocalView::Tree::size_type;
137 using QuadratureRule = typename CacheManager::QuadratureRule;
138 using QuadraturePoint = typename QuadratureRule::value_type;
140
141 void loadLocalDOFs(const LocalView& localView, std::vector<Coefficient>& localDoFs) const
142 {
143 localDoFs.resize(localView.size());
144 TypeTree::forEachLeafNode(localView.tree(), [&](auto&& node, auto&& treePath) {
145 if (usedNodes_[treePath])
146 for (auto i : Dune::range(node.size()))
147 {
148 auto localIndex = node.localIndex(i);
149 localDoFs[localIndex] = (*coefficients_)[localView.index(localIndex)];
150 }
151 });
152 }
153
154 public:
155
156 LocalOperator(LocalUnaryOperator&& localUnaryOperator, NodeFlags usedNodes, const Basis& basis, std::shared_ptr<const Vector> coefficients, UniqueCacheId cacheId) :
157 basis_(basis),
158 localUnaryOperator_(std::move(localUnaryOperator)),
159 usedNodes_(usedNodes),
160 coefficients_(std::move(coefficients)),
161 internalLocalView_{basis.localView(), basis.localView()},
162 cacheId_(cacheId)
163 {
164 localDoFs_[0].reserve(internalLocalView_[0].maxSize());
165 localDoFs_[1].reserve(internalLocalView_[1].maxSize());
166 localUnaryOperator_.registerLocalViews(internalLocalView_[0]);
167 localUnaryOperator_.registerOutsideLocalViews(internalLocalView_[1]);
168 }
169
171 LocalOperator(LocalUnaryOperator(other.localUnaryOperator_), other.usedNodes_, other.basis_, other.coefficients_, other.cacheId_)
172 {}
173
175 LocalOperator(std::move(other.localUnaryOperator_), other.usedNodes_, other.basis_, other.coefficients_, other.cacheId_)
176 {}
177
178 void bind(const Element& element)
179 {
180 if (externalLocalView_[0] == nullptr)
181 {
182 internalLocalView_[0].bind(element);
183 loadLocalDOFs(internalLocalView_[0], localDoFs_[0]);
184 }
185 else
186 loadLocalDOFs(*(externalLocalView_[0]), localDoFs_[0]);
187 localUnaryOperator_.bind(element);
188 }
189
190 void bind(const Intersection& intersection, const Element& element, const Element& otherElement)
191 {
192 if (externalLocalView_[0] == nullptr)
193 {
194 internalLocalView_[0].bind(element);
195 loadLocalDOFs(internalLocalView_[0], localDoFs_[0]);
196 }
197 else
198 loadLocalDOFs(*(externalLocalView_[0]), localDoFs_[0]);
199 if (externalLocalView_[1] == nullptr)
200 {
201 internalLocalView_[1].bind(otherElement);
202 loadLocalDOFs(internalLocalView_[1], localDoFs_[1]);
203 }
204 else
205 loadLocalDOFs(*(externalLocalView_[1]), localDoFs_[1]);
206 localUnaryOperator_.bind(intersection, element, otherElement);
207 }
208
210 void unbind()
211 {
212 if (externalLocalView_[0] == nullptr)
213 internalLocalView_[0].unbind();
214 if (externalLocalView_[1] == nullptr)
215 internalLocalView_[1].unbind();
216 }
217
218 // Additional interface of local nullary operator
219 auto quadratureRuleKey() const
220 {
221 return localUnaryOperator_.quadratureRuleKey();
222 }
223
225 {
226 auto& valueCache = cacheManager_->template getCache<ValueCache>(cacheIndex_);
227 auto& values = valueCache.getValues();
228 if (valueCache.isEmpty())
229 {
230 const auto& rule = valueCache.rule();
231 for (auto k : Dune::range(rule.size()))
232 {
233 auto& y = values[k];
234 AssignOp()(y, 0);
235 forEachOperator(localUnaryOperator_, [&](auto& op) {
236 sparseForEach(op(k), [&](const auto& value, auto stencilIndex, auto localIndex) {
237 SumOp::addTo(y, MultOp()(localDoFs_[stencilIndex][localIndex], value));
238 });
239 });
240 }
241 valueCache.setEmpty(false);
242 }
243 return Impl::Tensor::RankZeroTensor(values[index]);
244 }
245
250 template<class... LV>
251 void registerLocalViews(const LV&... lvs)
252 {
253 localUnaryOperator_.registerLocalViews(lvs...);
254 Impl::visitMatchingLocalView([&](const auto& localView) {
255 externalLocalView_[0] = &localView;
256 localDoFs_[0].reserve(externalLocalView_[0]->maxSize());
257 }, basis_, lvs...);
258 }
259
260 template<class... LV>
261 void registerOutsideLocalViews(const LV&... lvs)
262 {
263 localUnaryOperator_.registerOutsideLocalViews(lvs...);
264 Impl::visitMatchingLocalView([&](const auto& localView) {
265 externalLocalView_[1] = &localView;
266 localDoFs_[1].reserve(externalLocalView_[1]->maxSize());
267 }, basis_, lvs...);
268 }
269
270 void registerCaches(CacheManager& cacheManager)
271 {
272 localUnaryOperator_.registerCaches(cacheManager);
273 cacheIndex_ = cacheManager.registerCache(cacheId_, ValueCache(true));
274 }
275
277 {
278 localUnaryOperator_.registerOutsideCaches(cacheManager);
279 }
280
281 template<class... OutsideCacheManager>
282 void bindToCaches(CacheManager& cacheManager, OutsideCacheManager&... outsideCacheManager)
283 {
284 localUnaryOperator_.bindToCaches(cacheManager, outsideCacheManager...);
285 cacheManager_ = &cacheManager;
286 }
287
288 private:
289 const Basis& basis_;
290 mutable LocalUnaryOperator localUnaryOperator_;
291 NodeFlags usedNodes_;
292 std::shared_ptr<const Vector> coefficients_;
293 mutable std::array<std::vector<Coefficient>,2> localDoFs_;
294 std::array<LocalView, 2> internalLocalView_;
295 std::array<const LocalView*,2> externalLocalView_ = {nullptr, nullptr};
296 mutable CacheManager* cacheManager_ = nullptr;
297 UniqueCacheId cacheId_;
298 std::size_t cacheIndex_ = 0;
299 };
300
301 auto basis() const
302 {
303 return std::tuple<>();
304 }
305
306 auto treePath() const
307 {
308 return std::tuple<>();
309 }
310
311 friend LocalOperator localOperator(const BoundUnaryOperator& boundUnaryOperator)
312 {
313 const auto& rootBasis = std::get<0>(boundUnaryOperator.unaryOperator_.basis());
314 // Mark all leaf nodes whose DOFs need to be loaded
315 auto localView = rootBasis.localView();
316 auto usedNodes = TypeTree::makeTreeContainer(localView.tree(), [](auto&&) { return char(false); });
317 forEachOperator(boundUnaryOperator.unaryOperator_, [&](auto& op) {
318 const auto& treePath = std::get<0>(op.treePath());
319 const auto& node = Dune::TypeTree::child(localView.tree(), treePath);
320 TypeTree::forEachLeafNode(node, [&](auto&& leafNode, auto&& leafTreePath) {
321 usedNodes[TypeTree::join(treePath,leafTreePath)] = true;
322 });
323 });
324 return LocalOperator(localOperator(boundUnaryOperator.unaryOperator_), usedNodes, rootBasis, boundUnaryOperator.coefficients_, boundUnaryOperator.cacheId_);
325 }
326
328 requires (BoundUnaryOperator::arity==0)
329 {
330 return LocalFunctionAdaptor<LocalOperator>(localOperator(boundUnaryOperator));
331 }
332
337 Range operator()(const Domain& x) const
338 {
339 DUNE_THROW(Dune::NotImplemented, "Evaluation of BoundUnaryOperator in global coordinates is not implemented");
340 }
341
343 const EntitySet& entitySet() const
344 {
345 return entitySet_;
346 }
347
348 const auto& unaryOperator() const
349 {
350 return unaryOperator_;
351 }
352
353 const auto& coefficients() const
354 {
355 return coefficients_;
356 }
357
358 friend auto jacobian(const BoundUnaryOperator& f)
359 {
360 static_assert(isOperator_v<UnaryOperator>, "jacobian(BoundUnaryOperator<SumOperator<...>,V>(...)) is not implemented.");
361 return Dune::Fufem::Forms::BoundUnaryOperator(jacobian(f.unaryOperator_), f.coefficients_);
362 }
363
364 friend auto gradient(const BoundUnaryOperator& f)
365 {
366 static_assert(isOperator_v<UnaryOperator>, "gradient(BoundUnaryOperator<SumOperator<...>,V>(...)) is not implemented.");
367 return Dune::Fufem::Forms::BoundUnaryOperator(gradient(f.unaryOperator_), f.coefficients_);
368 }
369
370 friend auto grad(const BoundUnaryOperator& f)
371 {
372 static_assert(isOperator_v<UnaryOperator>, "grad(BoundUnaryOperator<SumOperator<...>,V>(...)) is not implemented.");
373 return Dune::Fufem::Forms::BoundUnaryOperator(grad(f.unaryOperator_), f.coefficients_);
374 }
375
376 friend auto divergence(const BoundUnaryOperator& f)
377 {
378 static_assert(isOperator_v<UnaryOperator>, "divergence(BoundUnaryOperator<SumOperator<...>,V>(...)) is not implemented.");
379 return Dune::Fufem::Forms::BoundUnaryOperator(divergence(f.unaryOperator_), f.coefficients_);
380 }
381
382 friend auto div(const BoundUnaryOperator& f)
383 {
384 static_assert(isOperator_v<UnaryOperator>, "div(BoundUnaryOperator<SumOperator<...>,V>(...)) is not implemented.");
385 return Dune::Fufem::Forms::BoundUnaryOperator(div(f.unaryOperator_), f.coefficients_);
386 }
387
388 private:
389 UniqueCacheId cacheId_;
390 UnaryOperator unaryOperator_;
391 std::shared_ptr<const Vector> coefficients_;
392 EntitySet entitySet_;
393 };
394
395
396
397} // namespace Dune::Fufem::Forms
398
399
400#endif // DUNE_FUFEM_FORMS_BOUNDUNARYOPERATOR_HH
static constexpr IntegralRange< T > range(T from, T to) noexcept
typename AutonomousValueType< T >::type AutonomousValue
std::ptrdiff_t index() const
#define DUNE_THROW(E,...)
void forEachLeafNode(Tree &&tree, LeafFunc &&leafFunc)
auto makeTreeContainer(const Tree &tree, LeafToValue &&leafToValue)
std::shared_ptr< T > stackobject_to_shared_ptr(T &t)
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
Definition boundunaryoperator.hh:123
void registerOutsideLocalViews(const LV &... lvs)
Definition boundunaryoperator.hh:261
LocalOperator(LocalOperator &&other)
Definition boundunaryoperator.hh:174
void registerCaches(CacheManager &cacheManager)
Definition boundunaryoperator.hh:270
typename BoundUnaryOperator::Range Range
Definition boundunaryoperator.hh:129
void registerOutsideCaches(CacheManager &cacheManager)
Definition boundunaryoperator.hh:276
void bind(const Element &element)
Definition boundunaryoperator.hh:178
LocalOperator(const LocalOperator &other)
Definition boundunaryoperator.hh:170
void bindToCaches(CacheManager &cacheManager, OutsideCacheManager &... outsideCacheManager)
Definition boundunaryoperator.hh:282
typename BoundUnaryOperator::LocalUnaryOperator::Intersection Intersection
Definition boundunaryoperator.hh:127
void registerLocalViews(const LV &... lvs)
Register LocalViews managed outside.
Definition boundunaryoperator.hh:251
LocalOperator(LocalUnaryOperator &&localUnaryOperator, NodeFlags usedNodes, const Basis &basis, std::shared_ptr< const Vector > coefficients, UniqueCacheId cacheId)
Definition boundunaryoperator.hh:156
void unbind()
Unbind the local-function.
Definition boundunaryoperator.hh:210
typename BoundUnaryOperator::Element Element
Definition boundunaryoperator.hh:126
void bind(const Intersection &intersection, const Element &element, const Element &otherElement)
Definition boundunaryoperator.hh:190
auto quadratureRuleKey() const
Definition boundunaryoperator.hh:219
auto operator()(std::size_t index) const
Definition boundunaryoperator.hh:224
Wrapper binding a linear operator to a coefficient vector.
Definition boundunaryoperator.hh:56
auto basis() const
Definition boundunaryoperator.hh:301
const auto & coefficients() const
Definition boundunaryoperator.hh:353
friend LocalOperator localOperator(const BoundUnaryOperator &boundUnaryOperator)
Definition boundunaryoperator.hh:311
friend auto divergence(const BoundUnaryOperator &f)
Definition boundunaryoperator.hh:376
auto treePath() const
Definition boundunaryoperator.hh:306
typename Dune::Functions::GridViewEntitySet< GridView, 0 > EntitySet
Definition boundunaryoperator.hh:82
BoundUnaryOperator(const UnaryOperator &unaryOperator, Vector &&coefficients)
Definition boundunaryoperator.hh:100
const auto & unaryOperator() const
Definition boundunaryoperator.hh:348
friend auto grad(const BoundUnaryOperator &f)
Definition boundunaryoperator.hh:370
friend LocalFunctionAdaptor< LocalOperator > localFunction(const BoundUnaryOperator &boundUnaryOperator)
Definition boundunaryoperator.hh:327
friend auto gradient(const BoundUnaryOperator &f)
Definition boundunaryoperator.hh:364
Dune::AutonomousValue< decltype(std::declval< Vector >()[std::declval< typename Basis::MultiIndex >()])> Coefficient
Definition boundunaryoperator.hh:80
friend auto jacobian(const BoundUnaryOperator &f)
Definition boundunaryoperator.hh:358
typename Basis::GridView GridView
Definition boundunaryoperator.hh:81
BoundUnaryOperator(const UnaryOperator &unaryOperator, std::shared_ptr< const Vector > coefficients)
Definition boundunaryoperator.hh:110
typename EntitySet::GlobalCoordinate Domain
Definition boundunaryoperator.hh:83
const EntitySet & entitySet() const
Get associated set of entities the local-function can be bound to.
Definition boundunaryoperator.hh:343
Range operator()(const Domain &x) const
Evaluate function in global coordinates.
Definition boundunaryoperator.hh:337
typename EntitySet::LocalCoordinate LocalDomain
Definition boundunaryoperator.hh:84
V Vector
Definition boundunaryoperator.hh:79
std::decay_t< decltype(MultOp()(std::declval< Coefficient >(), std::declval< typename UnaryOperator::Range >()))> Range
Definition boundunaryoperator.hh:88
typename EntitySet::Element Element
Definition boundunaryoperator.hh:87
friend auto div(const BoundUnaryOperator &f)
Definition boundunaryoperator.hh:382
BoundUnaryOperator(const UnaryOperator &unaryOperator, const Vector &coefficients)
Definition boundunaryoperator.hh:90
A class for managing caches of different types.
Definition shapefunctioncache.hh:609
Dune::QuadratureRule< CT, dimension > QuadratureRule
Definition shapefunctioncache.hh:611
size_type registerCache(UniqueCacheId uniqueCacheId, Cache &&cache)
Register a new cache.
Definition shapefunctioncache.hh:747
Adaptor for turning a Fufem::Forms LocalOperator into a LocalFunction.
Definition localfunctionadaptor.hh:42
Base class for multilinear operator implementations.
Definition baseclass.hh:73
static constexpr std::size_t arity
Definition baseclass.hh:75
A simple cache implementation storing values.
Definition shapefunctioncache.hh:802
Base class for unary multilinear operator implementations.
Definition baseclass.hh:91
Objects of this class are used to uniquely identifies a cache.
Definition shapefunctioncache.hh:563
T forward(T... args)
auto gradient(const Op &op)
Obtain the gradient of an operator.
Definition userfunctions.hh:1161
auto divergence(const FEFunctionOperator< B, TP, argIndex > &op)
Obtain the divergence of an operator.
Definition userfunctions.hh:1071
auto jacobian(const FEFunctionOperator< B, TP, argIndex > &op)
Obtain the jacobian of an operator.
Definition userfunctions.hh:1058
auto grad(const Op &op)
Obtain the gradient of an operator.
Definition userfunctions.hh:1181
Definition baseclass.hh:22
STL namespace.
T resize(T... args)
Definition localoperators.hh:46
Definition localoperators.hh:397
Definition localoperators.hh:66
static void addTo(K1 &x, const K2 &y)
Definition localoperators.hh:70