Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
productoperator.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_PRODUCTOPERATOR_HH
8#define DUNE_FUFEM_FORMS_PRODUCTOPERATOR_HH
9
10#include <cstddef>
11#include <type_traits>
12#include <tuple>
13#include <utility>
14#include <functional>
15
17
21
22
23
24namespace Dune::Fufem::Forms::Impl {
25
26 template<class Operator0, class Operator1>
27 struct ProductOperatorBaseTraits
28 {
29 static auto baseType() {
30 if constexpr ((Operator0::arity==1) and (Operator1::arity==0))
32 else if constexpr ((Operator0::arity==0) and (Operator1::arity==1))
34 else
36 }
37 using type = std::decay_t<decltype(baseType())>;
38 };
39
40
41} // namespace Dune::Fufem::Forms::Impl
42
43
44
45namespace Dune::Fufem::Forms {
46
47
48
57 template<class P, class Operator0, class Operator1>
58 class ProductOperator : public Impl::ProductOperatorBaseTraits<Operator0, Operator1>::type
59 {
60 using Contraction = P;
61 using LocalOperator0 = decltype(localOperator(std::declval<Operator0>()));
62 using LocalOperator1 = decltype(localOperator(std::declval<Operator1>()));
63
64 public:
65
66 using Element = typename Operator0::Element;
68
69 ProductOperator(const Contraction& product, const Operator0& operator0, const Operator1& operator1) :
70 product_(product),
71 operator0_(operator0),
72 operator1_(operator1)
73 {
74 static_assert(isOperator_v<Operator0>, "ProductOperator: First factor must be an operator.");
75 static_assert(isOperator_v<Operator1>, "ProductOperator: Second factor must be an operator.");
76 static_assert(Operator0::arity+Operator1::arity <= 2, "ProductOperator: Arity sum of factors must not exceed 2");
77 if constexpr((Operator0::arity==1) and (Operator1::arity==1))
78 static_assert((Operator0::argIndex==0) and (Operator1::argIndex==1), "ProductOperator: Factors must be ordered according to argument index.");
79 }
80
82 {
84 using Op1Tensor = decltype(std::declval<LocalOperator0>()(0));
85 static constexpr bool op1IsLazy = Impl::Tensor::IsLazyTensor<Op1Tensor>::value;
86 public:
87
88 using Element = typename LocalOperator0::Element;
89 using Intersection = typename LocalOperator0::Intersection;
90 using CacheManager = typename LocalOperator0::CacheManager;
91 using Range = typename ProductOperator::Range;
92
93 LocalOperator(const Contraction& product, LocalOperator0&& localOperator0, LocalOperator1&& localOperator1):
94 product_(product),
95 localOperator0_(std::move(localOperator0)),
96 localOperator1_(std::move(localOperator1))
97 {}
98
99 auto quadratureRuleKey() const
100 {
101 return quadratureRuleKey_;
102 }
103
104 void bind(const Element& element)
105 {
106 localOperator0_.bind(element);
107 localOperator1_.bind(element);
108 quadratureRuleKey_ = localOperator0_.quadratureRuleKey().product(localOperator1_.quadratureRuleKey());
109 }
110
111 void bind(const Intersection& intersection, const Element& element, const Element& otherElement)
112 {
113 localOperator0_.bind(intersection, element, otherElement);
114 localOperator1_.bind(intersection, element, otherElement);
115 quadratureRuleKey_ = localOperator0_.quadratureRuleKey().product(localOperator1_.quadratureRuleKey());
116 }
117
118 void unbind()
119 {
120 localOperator0_.unbind();
121 localOperator1_.unbind();
122 }
123
124 template<class... LV>
125 void registerLocalViews(const LV&... lvs)
126 {
127 localOperator0_.registerLocalViews(lvs...);
128 localOperator1_.registerLocalViews(lvs...);
129 }
130
131 template<class... LV>
132 void registerOutsideLocalViews(const LV&... lvs)
133 {
134 localOperator0_.registerOutsideLocalViews(lvs...);
135 localOperator1_.registerOutsideLocalViews(lvs...);
136 }
137
138 void registerCaches(CacheManager& cacheManager)
139 {
140 localOperator0_.registerCaches(cacheManager);
141 localOperator1_.registerCaches(cacheManager);
142 }
143
145 {
146 localOperator0_.registerOutsideCaches(cacheManager);
147 localOperator1_.registerOutsideCaches(cacheManager);
148 }
149
150 template<class... OutsideCacheManager>
151 void bindToCaches(CacheManager& cacheManager, OutsideCacheManager&... outsideCacheManager)
152 {
153 localOperator0_.bindToCaches(cacheManager, outsideCacheManager...);
154 localOperator1_.bindToCaches(cacheManager, outsideCacheManager...);
155 // For a binary product cache evaluation of the second factor
156 if constexpr ((Operator0::arity==1) and (Operator1::arity==1) and (op1IsLazy))
157 {
158 const auto& quadRule = cacheManager.rule();
159 if (op1Cache_.size()<quadRule.size())
160 op1Cache_.resize(quadRule.size());
161 for (auto k : Dune::range(quadRule.size()))
162 {
163 auto y = localOperator1_(k);
164 op1Cache_[k].resize(y.nnz());
165 std::size_t l = 0;
166 sparseForEach(y, [&](const auto& y_j, auto... j) {
167 op1Cache_[k][l++] = y_j;
168 });
169 }
170 }
171 }
172
174 {
175 using namespace Impl::Tensor;
176 using namespace Dune::Indices;
177 auto x = localOperator0_(index);
178 auto y = localOperator1_(index);
179 if constexpr ((Operator0::arity==1) and (Operator1::arity==1) and (op1IsLazy))
180 {
181 auto y_cached = SparseTensor(_2, [&, y, index](auto&& f) {
182 std::size_t l = 0;
183 sparseForEach(y, [&](const auto&, auto... j) {
184 f(op1Cache_[index][l++], j...);
185 });
186 },
187 op1Cache_.size(),
189 );
190 return interleavedOuterProduct(std::cref(product_), x, y_cached);
191 }
192 else
193 return interleavedOuterProduct(std::cref(product_), x, y);
194 }
195
196 private:
197 Contraction product_;
198 LocalOperator0 localOperator0_;
199 LocalOperator1 localOperator1_;
200 QuadratureRuleKey quadratureRuleKey_;
201 Op1Cache op1Cache_;
202 };
203
204 friend LocalOperator localOperator(const ProductOperator& productOperator)
205 {
206 return LocalOperator(productOperator.contraction(), localOperator(productOperator.operator0()), localOperator(productOperator.operator1()));
207 }
208
209 template<bool dummy=true, std::enable_if_t<dummy and (ProductOperator::arity==0), int> = 0>
211 {
212 return LocalFunctionAdaptor<LocalOperator>(localOperator(productOperator));
213 }
214
215 const Operator0& operator0() const
216 {
217 return operator0_;
218 }
219
220 const Operator1& operator1() const
221 {
222 return operator1_;
223 }
224
225 const Contraction& contraction() const
226 {
227 return product_;
228 }
229
230 auto basis() const
231 {
232 return std::tuple_cat(operator0_.basis(), operator1_.basis());
233 }
234
235 auto treePath() const
236 {
237 return std::tuple_cat(operator0_.treePath(), operator1_.treePath());
238 }
239
240 private:
241 Contraction product_;
242 Operator0 operator0_;
243 Operator1 operator1_;
244 };
245
246
247
248} // namespace Dune::Fufem::Forms
249
250#endif // DUNE_FUFEM_FORMS_PRODUCTOPERATOR_HH
static constexpr IntegralRange< std::decay_t< T > > range(T &&from, U &&to) noexcept
std::ptrdiff_t index() const
auto product(const Op &op, const L &l, const R &r)
Generic exterior product of two multilinear operators.
Definition userfunctions.hh:409
STL namespace.
Definition baseclass.hh:22
Base class for multilinear operator implementations.
Definition baseclass.hh:73
Base class for unary multilinear operator implementations.
Definition baseclass.hh:91
Adaptor for turning a Fufem::Forms LocalOperator into a LocalFunction.
Definition localfunctionadaptor.hh:42
Generic product of two multilinear operators.
Definition productoperator.hh:59
const Operator1 & operator1() const
Definition productoperator.hh:220
ProductOperator(const Contraction &product, const Operator0 &operator0, const Operator1 &operator1)
Definition productoperator.hh:69
friend LocalOperator localOperator(const ProductOperator &productOperator)
Definition productoperator.hh:204
decltype(std::declval< Contraction >()(std::declval< typename Operator0::Range >(), std::declval< typename Operator1::Range >())) Range
Definition productoperator.hh:67
const Operator0 & operator0() const
Definition productoperator.hh:215
auto basis() const
Definition productoperator.hh:230
const Contraction & contraction() const
Definition productoperator.hh:225
auto treePath() const
Definition productoperator.hh:235
friend LocalFunctionAdaptor< LocalOperator > localFunction(const ProductOperator &productOperator)
Definition productoperator.hh:210
typename Operator0::Element Element
Definition productoperator.hh:66
typename LocalOperator0::Intersection Intersection
Definition productoperator.hh:89
void registerOutsideLocalViews(const LV &... lvs)
Definition productoperator.hh:132
auto operator()(std::size_t index) const
Definition productoperator.hh:173
void bind(const Element &element)
Definition productoperator.hh:104
typename ProductOperator::Range Range
Definition productoperator.hh:91
void registerCaches(CacheManager &cacheManager)
Definition productoperator.hh:138
typename LocalOperator0::CacheManager CacheManager
Definition productoperator.hh:90
void registerOutsideCaches(CacheManager &cacheManager)
Definition productoperator.hh:144
typename LocalOperator0::Element Element
Definition productoperator.hh:88
void bind(const Intersection &intersection, const Element &element, const Element &otherElement)
Definition productoperator.hh:111
auto quadratureRuleKey() const
Definition productoperator.hh:99
void registerLocalViews(const LV &... lvs)
Definition productoperator.hh:125
void bindToCaches(CacheManager &cacheManager, OutsideCacheManager &... outsideCacheManager)
Definition productoperator.hh:151
LocalOperator(const Contraction &product, LocalOperator0 &&localOperator0, LocalOperator1 &&localOperator1)
Definition productoperator.hh:93
void unbind()
Definition productoperator.hh:118
A token that specifies a quadrature rule.
Definition quadraturerulecache.hh:39
T forward(T... args)
T cref(T... args)
T resize(T... args)
T size(T... args)
T tuple_cat(T... args)