1#ifndef __DUNE_ACFEM_OPERATORS_FUNCTIONALS_FUNCTIONALEXPRESSION_HH__
2#define __DUNE_ACFEM_OPERATORS_FUNCTIONALS_FUNCTIONALEXPRESSION_HH__
4#include "../../common/types.hh"
5#include "../../common/literals.hh"
6#include "../../expressions/operationtraits.hh"
7#include "../../tensors/tensor.hh"
9#include "linearfunctional.hh"
10#include "functionaltraits.hh"
11#include "closuretraits.hh"
12#include "operations/inner.hh"
18 namespace LinearFunctional {
20 using namespace Literals;
22 template<
class Operation,
class T>
23 class UnaryLinearFunctionalExpression;
25 template<
class Operation,
class T0,
class T1>
26 class BinaryLinearFunctionalExpression;
31 :
public LinearFunctional<typename std::decay_t<T>::DiscreteFunctionSpaceType>
32 ,
public Expressions::Storage<OperationTraits<MinusOperation>, T>
35 using StorageType = Expressions::Storage<OperationTraits<MinusOperation>, T>;
37 using typename BaseType::DiscreteFunctionSpaceType;
38 using typename BaseType::RangeFieldType;
39 using StorageType::operand;
40 using StorageType::operation;
42 template<class TArg, std::enable_if_t<std::is_constructible<T, TArg>::value,
int> = 0>
43 UnaryLinearFunctionalExpression(TArg&& t)
44 : StorageType(std::forward<TArg>(t))
47 template<
class FieldArg,
class DiscreteFunction,
48 std::enable_if_t<std::is_constructible<RangeFieldType, FieldArg>::value,
int> = 0>
49 void coefficients(FieldArg&& s, DiscreteFunction& values)
const
51 static_assert(std::is_same<DiscreteFunctionSpaceType, typename DiscreteFunction::DiscreteFunctionSpaceType>::value,
52 "DiscreteFunctionSpaceType of functional and discrete storage has to coincide");
54 operand(0_c).coefficients(-s, values);
57 template<
class DiscreteFunction>
58 void coefficients(DiscreteFunction& values)
const
61 coefficients(1_f, values);
64 template<
class DiscreteFunction>
65 auto operator()(
const DiscreteFunction& df)
const
67 return inner(*
this, df);
70 const DiscreteFunctionSpaceType& space()
const
75 std::string name()
const
81 using StorageType::t0_;
82 constexpr auto&& arg() && {
return t0_; }
83 constexpr auto& arg() & {
return t0_; }
84 constexpr const auto& arg()
const& {
return t0_; }
88 template<
class Operation,
class T0,
class T1>
90 :
public LinearFunctional<typename std::decay_t<T1>::DiscreteFunctionSpaceType>
91 ,
public Expressions::Storage<OperationTraits<Operation>, T0, T1>
94 using StorageType = Expressions::Storage<OperationTraits<Operation>, T0, T1>;
96 using typename BaseType::DiscreteFunctionSpaceType;
97 using typename BaseType::RangeFieldType;
98 using StorageType::operand;
99 using StorageType::operation;
101 template<
class T0Arg,
class T1Arg,
102 std::enable_if_t<(std::is_constructible<T0, T0Arg>::value
103 && std::is_constructible<T1, T1Arg>::value
106 : StorageType(std::forward<T0Arg>(t0), std::forward<T1>(t1))
109 template<
class FieldArg,
class DiscreteFunction,
110 std::enable_if_t<std::is_constructible<RangeFieldType, FieldArg>::value,
int> = 0>
111 void coefficients(FieldArg&& s, DiscreteFunction& values)
const
113 static_assert(std::is_same<DiscreteFunctionSpaceType, typename DiscreteFunction::DiscreteFunctionSpaceType>::value,
114 "DiscreteFunctionSpaceType of functional and discrete storage has to coincide");
117 if constexpr (std::is_same<Operation, PlusOperation>::value) {
118 left().coefficients(s, values);
119 right().coefficients(s, values);
120 }
else if constexpr (std::is_same<Operation, MinusOperation>::value) {
121 left().coefficients(s, values);
122 right().coefficients(-s, values);
123 }
else if constexpr (std::is_same<Operation, SMultiplyOperation>::value) {
125 right().coefficients(left()*s, values);
129 template<
class DiscreteFunction>
130 void coefficients(DiscreteFunction& df)
const
132 coefficients(1_f, df);
135 template<
class DiscreteFunction>
136 auto operator()(
const DiscreteFunction& df)
const
138 return inner(*
this, df);
141 const DiscreteFunctionSpaceType& space()
const
143 return right().space();
146 std::string name()
const
148 return operationName(operation(), left().name(), right().name());
152 using StorageType::t0_;
153 using StorageType::t1_;
154 constexpr auto&& left() && {
return t0_; }
155 constexpr auto& left() & {
return t0_; }
156 constexpr const auto& left()
const& {
return t0_; }
157 constexpr auto&& right() && {
return t1_; }
158 constexpr auto& right() & {
return t1_; }
159 constexpr const auto& right()
const& {
return t1_; }
162 template<class Op, class T, std::enable_if_t<IsLinearFunctional<T>::value,
int> = 0>
165 DUNE_ACFEM_RECORD_OPTIMIZATION;
167 return UnaryLinearFunctionalExpression<Op, T>(std::forward<T>(t));
170 template<
class Op,
class T0,
class T1,
171 std::enable_if_t<((IsLinearFunctional<T0>::value || TensorTraits<T0>::rank == 0)
172 && IsLinearFunctional<T1>::value
176 DUNE_ACFEM_RECORD_OPTIMIZATION;
178 return BinaryLinearFunctionalExpression<Op, T0, T1>(std::forward<T0>(t0), std::forward<T1>(t1));
The one and only one binary expression.
Definition: functionalexpression.hh:92
Light-weight base class for all linear functionals.
Definition: linearfunctional.hh:13
OptimizeTag< 0 > DontOptimize
Bottom level is overloaded to do nothing.
Definition: optimizationbase.hh:74
std::string operationName(F &&f, const std::string &arg)
Verbose print of an operation, helper function to produce noise.
Definition: operationtraits.hh:601
auto inner(T1 &&t1, T2 &&t2)
"scalar product"
Definition: expressions.hh:154
Subtraction of two objects and unary minus.
Definition: expressionoperations.hh:43