Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
userfunctions.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_USERFUNCTIONS_HH
8#define DUNE_FUFEM_FORMS_USERFUNCTIONS_HH
9
10#include <cstddef>
11#include <type_traits>
12#include <utility>
13
17
19
20#if DUNE_VERSION_GTE(DUNE_FUNCTIONS, 2, 11)
22#else
23#include <dune/typetree/childextraction.hh>
24#endif
25
36
37
38
39
40namespace Dune::Fufem::Forms::Impl {
41
42
43
44 // ************************************************************
45 // Implementation of compose(outerOp, innerOp)
46 // ************************************************************
47
48 template<class OuterTransform, class InnerTransform, class InnerOp,
50 auto composeImpl(const OuterTransform& outerTransform, const TransformedOperator<InnerTransform, InnerOp>& op)
51 {
52 return TransformedOperator(LocalOperators::localCompose(outerTransform, op.transformation()), op.baseOperator());
53 }
54
55 template<class OuterOp, class InnerOp,
57 auto composeImpl(const OuterOp& outerOp, const InnerOp& op)
58 {
59 return TransformedOperator(outerOp, op);
60 }
61
62 template<class OuterOp, class... InnerOps>
63 auto composeImpl(const OuterOp& outerOp, const Dune::Fufem::Forms::SumOperator<InnerOps...>& innerOps)
64 {
65 if constexpr(SumOperator<InnerOps...>::arity==0)
66 return TransformedOperator(outerOp, innerOps);
67 else
68 return std::apply([&](const auto&...op_i) {
69 return Dune::Fufem::Forms::SumOperator(composeImpl(outerOp, op_i) ...);
70 }, innerOps.operators());
71 }
72
73
74
75 // ************************************************************
76 // Implementation of sum(l,r).
77 // ************************************************************
78
79 // This has four special cases to collapse nested sums
80 // and two for the case that one argument is a constant.
81
82 template<class L, class R,
83 std::enable_if_t<isOperator_v<L> and isOperator_v<R>, int> = 0>
84 auto sum(const L& l, const R& r)
85 {
86 return SumOperator<L, R>(l, r);
87 }
88
89 template<class L, class... Ri,
91 auto sum(const L& l, const SumOperator<Ri...>& r)
92 {
93 return std::apply([&](const auto&... ri) {
94 return SumOperator<L, Ri...>(l, ri...);
95 }, r.operators());
96 }
97
98 template<class... Li, class R,
100 auto sum(const SumOperator<Li...>& l, const R& r)
101 {
102 return std::apply([&](const auto&... li) {
103 return SumOperator<Li..., R>(li..., r);
104 }, l.operators());
105 }
106
107 template<class... Li, class... Rj>
108 auto sum(const SumOperator<Li...>& l, const SumOperator<Rj...>& r)
109 {
110 return std::apply([&](const auto&...li) {
111 return std::apply([&](const auto&...rj) {
112 return SumOperator<Li..., Rj...>(li..., rj...);
113 }, r.operators());
114 }, l.operators());
115 }
116
117 // Overload for for the case that R is a constant
118 template<class L, class R,
119 std::enable_if_t<isOperatorOrSumOperator_v<L> and not isOperatorOrSumOperator_v<R>, int> = 0>
120 auto sum(const L& l, const R& r)
121 {
122 return Impl::composeImpl([r](auto&& l_value) {
124 }, l);
125 }
126
127 // Overload for for the case that L is a constant
128 template<class L, class R,
129 std::enable_if_t<not isOperatorOrSumOperator_v<L> and isOperatorOrSumOperator_v<R>, int> = 0>
130 auto sum(const L& l, const R& r)
131 {
132 return Impl::composeImpl([l](auto&& r_value) {
134 }, r);
135 }
136
137
138
139 // ************************************************************
140 // Implementation of product(p, left, right)
141 // ************************************************************
142
143 // The following are the generic functions for producing
144 // product operators from a binary operator and two other
145 // terms. At least one of those terms should be a operator.
146
147 // Overload for two plain operators
148 template<class Op, class L, class R,
149 std::enable_if_t<isOperator_v<L> and isOperator_v<R>, int> = 0,
150 std::enable_if_t<Dune::IsCallable<Op(typename L::Range, typename R::Range)>::value, int> = 0>
151 auto productImpl(const Op& op, const L& l, const R& r)
152 {
153 static_assert(L::arity+R::arity<=2, "Trying to construct multi-linear operator with arity>2");
154
155 if constexpr((L::arity==1) and (L::arity==1))
156 {
157 if constexpr(L::argIndex==1)
158 return ProductOperator(LocalOperators::TransposedBinaryOp(op), r, l);
159 else
160 return ProductOperator(op, l, r);
161 }
162 else
163 return ProductOperator(op, l, r);
164 }
165
166 // Overload for one raw value and one operator
167 // This will wrap the raw value into a operator.
168 template<class Op, class L, class R,
169 std::enable_if_t<(not isOperator_v<L>) and isOperator_v<R>, int> = 0,
170 std::enable_if_t<Dune::IsCallable<Op(L, typename R::Range)>::value, int> = 0>
171 auto productImpl(const Op& op, const L& l, const R& r)
172 {
173 using namespace std::placeholders;
174 return composeImpl(std::bind(op, l, _1), r);
175 }
176
177 // Overload for one operator and one raw value
178 // This will wrap the raw value into a operator.
179 template<class Op, class L, class R,
180 std::enable_if_t<isOperator_v<L> and (not isOperator_v<R>), int> = 0,
181 std::enable_if_t<Dune::IsCallable<Op(typename L::Range, R)>::value, int> = 0>
182 auto productImpl(const Op& op, const L& l, const R& r)
183 {
184 using namespace std::placeholders;
185 return composeImpl(std::bind(op, _1, r), l);
186 }
187
188 // Overload for one sum-operator and one plain term
189 // This will multiply out the product for the sum-operator.
190 template<class Op, class... Li, class R,
192 auto productImpl(const Op& op, const SumOperator<Li...>& l, const R& r)
193 {
194 return std::apply([&](const auto&... li) {
195 return (productImpl(op, li, r) + ...);
196 }, l.operators());
197 }
198
199 // Overload for one plain term and one sum-operator
200 // This will multiply out the product for the sum-operator.
201 template<class Op, class L, class... Ri,
203 auto productImpl(const Op& op, const L& l, const SumOperator<Ri...>& r)
204 {
205 return std::apply([&](const auto&...ri) {
206 return (productImpl(op, l, ri) + ...);
207 }, r.operators());
208 }
209
210 // Overload for two sum-operators
211 // This will multiply out the product for both sum-operators.
212 template<class Op, class... Li, class... Rj,
213 class = std::void_t<decltype((productImpl(std::declval<Op>(), std::declval<Li>(), std::declval<SumOperator<Rj...>>()),...))>>
214 auto productImpl(const Op& op, const SumOperator<Li...>& l, const SumOperator<Rj...>& r)
215 {
216 return std::apply([&](const auto&...li) {
217 return (productImpl(op, li, r) + ...);
218 }, l.operators());
219 }
220
221
222
223 // ************************************************************
224 // Implementation of dot(l, r).
225 // ************************************************************
226
227 // These specializations only exist for optimization of special cases.
228
229 // This is the default implementation.
230 template<class L, class R,
231 std::enable_if_t<isOperatorOrSumOperator_v<L> or isOperatorOrSumOperator_v<R>, int> = 0,
232 class = std::void_t<decltype(productImpl(std::declval<LocalOperators::DotOp>(), std::declval<L>(), std::declval<R>()))>>
233 auto dotImpl(const L& l, const R& r)
234 {
235 return productImpl(Dune::Fufem::Forms::LocalOperators::DotOp(), l, r);
236 }
237
238 template<class B, class TP, std::size_t argIndex_L, std::size_t argIndex_R>
239 auto dotImpl(const FEFunctionOperator<B,TP,argIndex_L>& l, const FEFunctionOperator<B,TP,argIndex_R>& r);
240
241 template<class B, class TP, std::size_t argIndex_L, std::size_t argIndex_R>
242 auto dotImpl(const FEFunctionJacobianOperator<B,TP,argIndex_L>& l, const FEFunctionJacobianOperator<B,TP,argIndex_R>& r);
243
244 template<class InnerOp>
245 using TransposedOperator = TransformedOperator<Dune::Fufem::Forms::LocalOperators::TransposeOp, InnerOp>;
246
247 template<class L, class R>
248 auto dotImpl(const Impl::TransposedOperator<L>& l, const Impl::TransposedOperator<R>& r)
249 {
250 using namespace Dune::Indices;
251 return Dune::Fufem::Forms::Impl::dotImpl(l.baseOperator(), r.baseOperator());
252 }
253
254 template<class B, class TP, std::size_t argIndex_L, std::size_t argIndex_R>
255 auto dotImpl(const FEFunctionOperator<B,TP,argIndex_L>& l, const FEFunctionOperator<B,TP,argIndex_R>& r)
256 {
258 if constexpr (Dune::Fufem::Impl::Concept::UniformInnerTreeNode<Node>)
259 {
261 [&](auto... i) {
262 return (Dune::Fufem::Forms::Impl::dotImpl(l.childOperator(i), r.childOperator(i)) + ...);
263 },
264 std::make_index_sequence<Node::degree()>{});
265 }
266 else
267 return productImpl(Dune::Fufem::Forms::LocalOperators::DotOp(), l, r);
268 }
269
270 template<class B, class TP, std::size_t argIndex_L, std::size_t argIndex_R>
271 auto dotImpl(const FEFunctionJacobianOperator<B,TP,argIndex_L>& l, const FEFunctionJacobianOperator<B,TP,argIndex_R>& r)
272 {
274 if constexpr (Dune::Fufem::Impl::Concept::UniformInnerTreeNode<Node>)
275 {
277 [&](auto... i) {
278 return (Dune::Fufem::Forms::Impl::dotImpl(l.childOperator(i), r.childOperator(i)) + ...);
279 },
280 std::make_index_sequence<Node::degree()>{});
281 }
282 else
283 return productImpl(Dune::Fufem::Forms::LocalOperators::DotOp(), l, r);
284 }
285
286
287
288} // namespace Dune::Fufem::Forms::Impl
289
290
291
292namespace Dune::Fufem::Forms {
293
294
295
296 // ************************************************************
297 // Linear combination of operators of the same arity
298 // ************************************************************
299
315#ifdef DOXYGEN
316 template<class L, class R>
317 auto operator+ (const L& l, const R& r);
318#else
319 // Overload for two operators of the same arity
320 template<class L, class R,
321 std::enable_if_t<isOperatorOrSumOperator_v<L> or isOperatorOrSumOperator_v<R>, int> = 0>
322 auto operator+ (const L& l, const R& r)
323 {
324 if constexpr (isOperatorOrSumOperator_v<L> and isOperatorOrSumOperator_v<R>)
325 static_assert(L::arity==R::arity, "The operators passed to operator+ do not have the same arity");
326 else if constexpr (isOperatorOrSumOperator_v<R>)
327 static_assert(R::arity==0, "Plain values can only be added to 0-linear operators");
328 else if constexpr (isOperatorOrSumOperator_v<L>)
329 static_assert(L::arity==0, "Plain values can only be added to 0-linear operators");
330 return Impl::sum(l, r);
331 }
332#endif
333
343 template<class Op,
345 auto operator- (const Op& op)
346 {
347 if constexpr (requires(typename Op::Range x) { -x; })
348 return Impl::composeImpl(std::negate(), op);
349 else if constexpr (requires(typename Op::Range x) { -1*x; })
350 return Impl::composeImpl([](auto&& x) { return -1*x;}, op);
351 }
352
366#ifdef DOXYGEN
367 template<class L, class R>
368 auto operator- (const L& l, const R& r);
369#else
370 template<class L, class R,
371 std::enable_if_t<isOperatorOrSumOperator_v<L> or isOperatorOrSumOperator_v<R>, int> = 0>
372 auto operator- (const L& l, const R& r)
373 {
374 if constexpr (isOperatorOrSumOperator_v<L> and isOperatorOrSumOperator_v<R>)
375 static_assert(L::arity==R::arity, "The operators passed to operator- do not have the same arity");
376 else if constexpr (isOperatorOrSumOperator_v<R>)
377 static_assert(R::arity==0, "Differences with plain values can only be used with 0-linear operators");
378 else if constexpr (isOperatorOrSumOperator_v<L>)
379 static_assert(L::arity==0, "Differences with plain values can only be used with 0-linear operators");
380 return Impl::sum(l, -r);
381 }
382#endif
383
384
385
386 // ************************************************************
387 // Bilinear combination of operators
388 // ************************************************************
389
406 template<class Op, class L, class R,
407 std::enable_if_t<isOperatorOrSumOperator_v<L> or isOperatorOrSumOperator_v<R>, int> = 0,
408 class = std::void_t<decltype(Impl::productImpl(std::declval<Op>(), std::declval<L>(), std::declval<R>()))>>
409 auto product(const Op& op, const L& l, const R& r)
410 {
411 return Impl::productImpl(op, l, r);
412 }
413
429 template<class L, class R,
430 std::enable_if_t<isOperatorOrSumOperator_v<L> or isOperatorOrSumOperator_v<R>, int> = 0,
431 class = std::void_t<decltype(product(std::declval<LocalOperators::MultOp>(), std::declval<L>(), std::declval<R>()))>>
432 auto operator* (const L& l, const R& r)
433 {
434 // This overload is recursively constrained to cases where `operator*` makes sense.
435 // Otherwise Dune::dot(a,b) may be activated for operators because it relies on availability
436 // of a*b. This is a problem, because it leads to ambiguity with Forms::dot(a,b).
437 return product(LocalOperators::MultOp{}, l, r);
438 }
439
455 template<class L, class R,
456 std::enable_if_t<isOperatorOrSumOperator_v<L> or isOperatorOrSumOperator_v<R>, int> = 0,
457 class = std::void_t<decltype(product(std::declval<LocalOperators::DotOp>(), std::declval<L>(), std::declval<R>()))>>
458 auto dot(const L& l, const R& r)
459 {
460 return Impl::dotImpl(l, r);
461 }
462
463
464
465 // ************************************************************
466 // Utilities for range transformations
467 // ************************************************************
468
480 template<class OuterOp, class InnerOp,
482 std::enable_if_t<Dune::IsCallable<OuterOp(typename InnerOp::Range)>::value, int> = 0>
483 auto compose(const OuterOp& outerOp, const InnerOp& innerOp)
484 {
485 return Impl::composeImpl(outerOp, innerOp);
486 }
487
488
489
508 template<class OuterOp>
510 {
511 public:
512 RangeOperator(const OuterOp& outerOp) : outerOp_(outerOp) {}
513
514 template<class Op, class... Args,
516 auto operator()(Op&& baseOperator, Args... args) const
517 {
518 using namespace std::placeholders;
519 return compose(std::bind(outerOp_, _1, args...), std::forward<Op>(baseOperator));
520 }
521
522 template<class Op,
524 auto operator()(Op&& baseOperator) const
525 {
526 return compose(outerOp_, std::forward<Op>(baseOperator));
527 }
528
529 template<class Arg0, class... Args,
531 auto operator()(Arg0&& arg0, Args&&... args) const
532 {
533 return outerOp_(std::forward<Arg0>(arg0), std::forward<Args>(args)...);
534 }
535
536 private:
537 OuterOp outerOp_;
538 };
539
540
541
542 // ************************************************************
543 // Predefined linear range transformations
544 // ************************************************************
545
558 template<class Op>
559 auto transpose(const Op& op)
560 {
562 }
563
576 template<class Op>
577 auto symmetrize(const Op& op)
578 {
580 }
581
594 template<class Op>
595 auto trace(const Op& op)
596 {
598 }
599
600
601
602 // ************************************************************
603 // Predefined non-linear range transformations
604 // ************************************************************
605
620 template<class Op>
621 auto inv(const Op& op)
622 {
623 if constexpr(isOperatorOrSumOperator_v<Op>)
624 static_assert(Op::arity==0, "inv(op) can only be applied to 0-linear operators");
626 }
627
645 template<class L, class R,
646 std::enable_if_t<isOperatorOrSumOperator_v<L> or isOperatorOrSumOperator_v<R>, int> = 0,
647 class = std::void_t<decltype(product(std::declval<LocalOperators::MultOp>(), std::declval<L>(), inv(std::declval<R>())))>>
648 auto operator/ (const L& l, const R& r)
649 {
650 // Since inv() does not exist if R is a non-nullary operator,
651 // we don't need to guard this further here.
652 return product(LocalOperators::MultOp{}, l, inv(r));
653 }
654
655
656
657 // ************************************************************
658 // Convenience functions for creating operators
659 // ************************************************************
660
678
693 template<class Basis>
694 auto testFunction(const Basis& basis)
695 {
696 using RootBasis = std::decay_t<decltype(basis.rootBasis())>;
697 return FEFunctionOperator<RootBasis, typename Basis::PrefixPath, 0>(basis.rootBasis(), basis.prefixPath());
698 }
699
716 template<class Basis>
717 auto testFunction(const Basis& basis, NonAffineFamily tag)
718 {
719 using RootBasis = std::decay_t<decltype(basis.rootBasis())>;
720 return FEFunctionOperator<RootBasis, typename Basis::PrefixPath, 0>(basis.rootBasis(), basis.prefixPath(), false);
721 }
722
741 template<class Basis, class... Args, std::enable_if_t<(sizeof...(Args)>0), int> = 0>
742 auto testFunction(const Basis& basis, Args&&... args)
743 {
744 using LastArg = typename Dune::Functions::LastType<std::decay_t<Args>...>::type;
746 {
747 return Dune::applyPartial([&](auto&&... treePathArgs){
748 return testFunction(Dune::Functions::subspaceBasis(basis, treePathArgs...), NonAffineFamily{});
749 },
751 std::make_index_sequence<sizeof...(Args)-1>{}
752 );
753 }
754 else
755 return testFunction(Dune::Functions::subspaceBasis(basis, args...));
756 }
757
772 template<class Basis>
773 auto trialFunction(const Basis& basis)
774 {
775 using RootBasis = std::decay_t<decltype(basis.rootBasis())>;
776 return FEFunctionOperator<RootBasis, typename Basis::PrefixPath, 1>(basis.rootBasis(), basis.prefixPath());
777 }
778
795 template<class Basis>
796 auto trialFunction(const Basis& basis, NonAffineFamily tag)
797 {
798 using RootBasis = std::decay_t<decltype(basis.rootBasis())>;
799 return FEFunctionOperator<RootBasis, typename Basis::PrefixPath, 1>(basis.rootBasis(), basis.prefixPath(), false);
800 }
801
820 template<class Basis, class... Args, std::enable_if_t<(sizeof...(Args)>0), int> = 0>
821 auto trialFunction(const Basis& basis, Args&&... args)
822 {
823 using LastArg = typename Dune::Functions::LastType<std::decay_t<Args>...>::type;
825 {
826 return Dune::applyPartial([&](auto&&... treePathArgs){
827 return trialFunction(Dune::Functions::subspaceBasis(basis, treePathArgs...), NonAffineFamily{});
828 },
830 std::make_index_sequence<sizeof...(Args)-1>{}
831 );
832 }
833 else
834 return trialFunction(Dune::Functions::subspaceBasis(basis, args...));
835 }
836
860 template<class Op,
861 std::enable_if_t<isOperatorOrSumOperator_v<Op> and (Op::arity<=1), int> = 0>
862 auto outside(const Op& op)
863 {
864 if constexpr (isOperator_v<Op>)
865 return OutsideOperator(op);
866 if constexpr (isSumOperator_v<Op>)
867 return std::apply([&](const auto&...op_i) {
869 }, op.operators());
870 }
871
885 template<class Op,
886 std::enable_if_t<isOperatorOrSumOperator_v<Op> and (Op::arity<=1), int> = 0>
887 auto avg(const Op& op)
888 {
889 return 0.5*(op+outside(op));
890 }
891
908 template<class Op,
909 std::enable_if_t<isOperatorOrSumOperator_v<Op> and (Op::arity<=1), int> = 0>
910 auto jump(const Op& op)
911 {
912 return op-outside(op);
913 }
914
928 template<class GridView>
929 auto meshSize(const GridView& gridView)
930 {
931 return MeshSizeOperator(gridView);
932 }
933
946 template<class GridView>
947 auto meshSize()
948 {
950 }
951
964 template<class GridView>
965 auto faceNormal(const GridView& gridView)
966 {
967 return FaceNormalOperator(gridView);
968 }
969
981 template<class GridView>
983 {
985 }
986
1006 template<class Op, class V,
1008 auto bindToCoefficients(const Op& op, V&& vector)
1009 {
1010 using Basis = std::decay_t<decltype(std::get<0>(op.basis()))>;
1011 // Small helper functions to wrap vectors using istlVectorBackend
1012 // if they do not already satisfy the VectorBackend interface.
1013 auto toConstVectorBackend = [&](auto&& v) -> decltype(auto) {
1014 if constexpr (models<Dune::Functions::Concept::ConstVectorBackend<Basis>, decltype(v)>()) {
1015 return std::forward<decltype(v)>(v);
1016 } else {
1018 }
1019 };
1020 return BoundUnaryOperator(op, toConstVectorBackend(std::forward<V>(vector)));
1021 }
1022
1023
1024
1039 template<class Op, class V,
1042 auto operator|(const Op& op, V&& v)
1043 {
1044 return bindToCoefficients(op, std::forward<V>(v));
1045 }
1046
1047
1048
1049 // ************************************************************
1050 // Differential operators
1051 // ************************************************************
1052
1053 // Overloads for elementary operators
1054
1062 template<class B, class TP, std::size_t argIndex>
1067
1075 template<class B, class TP, std::size_t argIndex>
1080
1090 template<class B, class TP, std::size_t argIndex>
1097
1098 // Overloads for sums of operators
1099
1107 template<class... Ops>
1108 requires requires(const Ops&... ops) { SumOperator(jacobian(ops)...); }
1110 {
1111 return std::apply([&](const auto&...op) {
1112 return SumOperator(jacobian(op) ...);
1113 }, op.operators());
1114 }
1115
1123 template<class... Ops>
1124 requires requires(const Ops&... ops) { SumOperator(jacobian(ops)...); }
1126 {
1127 return std::apply([&](const auto&...op) {
1128 return SumOperator(divergence(op) ...);
1129 }, op.operators());
1130 }
1131
1141 template<class... Ops>
1142 requires requires(const Ops&... ops) { SumOperator(curl(ops)...); }
1144 {
1145 return std::apply([&](const auto&...op) {
1146 return SumOperator(curl(op) ...);
1147 }, op.operators());
1148 }
1149
1150 // Other operators that are essetially shot cuts to the others
1151
1165 template<class Op>
1166 auto gradient(const Op& op)
1167 requires requires {Fufem::Forms::transpose(jacobian(op));}
1168 {
1170 }
1171
1185 template<class Op>
1186 auto grad(const Op& op)
1187 requires requires {Fufem::Forms::transpose(jacobian(op));}
1188 {
1190 }
1191
1199 template<class Op>
1200 auto div(const Op& op)
1201 requires requires {divergence(op);}
1202 {
1203 return divergence(op);
1204 }
1205
1215 template<class Op>
1216 auto rot(const Op& op)
1217 requires requires {curl(op);}
1218 {
1219 return curl(op);
1220 }
1221
1233 template<class Op>
1234 auto D(const Op& op, std::size_t k)
1235 requires requires {grad(op);}
1236 {
1237 return compose([k](auto&& g) { return g[k]; }, grad(op));
1238 }
1239
1240
1241
1242} // namespace Dune::Fufem::Forms
1243
1244
1245#endif // DUNE_FUFEM_FORMS_USERFUNCTIONS_HH
auto istlVectorBackend(Vector &v)
auto subspaceBasis(const RootBasis &rootBasis, const TypeTree::TreePath< PrefixTreeIndices... > &prefixPath)
This header provides fallback implementations for dune-typetree<2.11.
decltype(auto) applyPartial(F &&f, ArgTuple &&args, std::integer_sequence< I, i... >)
decltype(auto) constexpr unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
size_type dim() const
auto outside(const Op &op)
Construct outside version of a given operator.
Definition userfunctions.hh:862
auto testFunction(const Basis &basis)
Create unary identity operator on test function space.
Definition userfunctions.hh:694
auto operator|(const Op &op, V &&v)
Bind a linear operator to a coefficient vector.
Definition userfunctions.hh:1042
auto trialFunction(const Basis &basis)
Create unary identity operator on trial function space.
Definition userfunctions.hh:773
auto meshSize()
Construct mesh size operator.
Definition userfunctions.hh:947
auto avg(const Op &op)
Construct intersection average of a given operator.
Definition userfunctions.hh:887
auto jump(const Op &op)
Construct intersection jump of a given operator.
Definition userfunctions.hh:910
auto bindToCoefficients(const Op &op, V &&vector)
Bind a linear operator to a coefficient vector.
Definition userfunctions.hh:1008
auto faceNormal()
Construct operator representing the face normals.
Definition userfunctions.hh:982
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 div(const Op &op)
Obtain the divergence of an operator.
Definition userfunctions.hh:1200
auto curl(const FEFunctionOperator< B, TP, argIndex > &op)
Obtain the curl of an operator.
Definition userfunctions.hh:1091
auto D(const Op &op, std::size_t k)
Obtain the i-th partial derivative of an operator.
Definition userfunctions.hh:1234
auto grad(const Op &op)
Obtain the gradient of an operator.
Definition userfunctions.hh:1186
auto rot(const Op &op)
Obtain the curl of an operator.
Definition userfunctions.hh:1216
auto dot(const L &l, const R &r)
Exterior product of two multilinear operators based on pointwise dot-product.
Definition userfunctions.hh:458
auto product(const Op &op, const L &l, const R &r)
Generic exterior product of two multilinear operators.
Definition userfunctions.hh:409
auto operator-(const Op &op)
Negate an operator.
Definition userfunctions.hh:345
auto trace(const Op &op)
Transform an operator by pointwise computation of the matrix trace.
Definition userfunctions.hh:595
auto transpose(const Op &op)
Transform an operator by pointwise matrix transposition.
Definition userfunctions.hh:559
auto compose(const OuterOp &outerOp, const InnerOp &innerOp)
Generic composition of a multilinear operators with a pointwise outer operator.
Definition userfunctions.hh:483
auto symmetrize(const Op &op)
Transform an operator by pointwise matrix symmetrization.
Definition userfunctions.hh:577
auto inv(const Op &op)
Transform an operator by pointwise computation of the matrix inverse.
Definition userfunctions.hh:621
STL namespace.
Definition baseclass.hh:22
auto localCompose(const OuterOp &outerOp, const InnerOp &innerOp)
Definition localoperators.hh:432
Sum of several multilinear operators.
Definition sumoperator.hh:38
auto & operators()
Definition sumoperator.hh:172
Wrapper binding a linear operator to a coefficient vector.
Definition boundunaryoperator.hh:65
Operator representing the normal field on intersection.
Definition geometryoperators.hh:41
Operator representing the mesh size of entities.
Definition geometryoperators.hh:179
Definition localoperators.hh:36
Definition localoperators.hh:188
Definition localoperators.hh:268
Definition localoperators.hh:302
Definition localoperators.hh:329
Definition localoperators.hh:339
Definition localoperators.hh:353
Operator for switching to the outside entity.
Definition outsideoperator.hh:58
auto basis() const
Definition unaryoperators.hh:179
auto treePath() const
Definition unaryoperators.hh:184
bool isAffine() const
Definition unaryoperators.hh:189
Linear map representing the elements of an FE-space.
Definition unaryoperators.hh:212
Linear map representing the jacobians of the elements of an FE-space.
Definition unaryoperators.hh:325
Linear map representing the divergenc of the elements of an FE-space.
Definition unaryoperators.hh:441
Adaptor for making a callback compatible with Dune::Fufem::Forms.
Definition userfunctions.hh:510
auto operator()(Op &&baseOperator, Args... args) const
Definition userfunctions.hh:516
RangeOperator(const OuterOp &outerOp)
Definition userfunctions.hh:512
auto operator()(Arg0 &&arg0, Args &&... args) const
Definition userfunctions.hh:531
auto operator()(Op &&baseOperator) const
Definition userfunctions.hh:524
Tag type to classify non-affine finite element families.
Definition userfunctions.hh:677
T apply(T... args)
T bind(T... args)
T declval(T... args)
T forward_as_tuple(T... args)
T forward(T... args)