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