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