Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines base-class MathFunction.
6 :
7 : #pragma once
8 :
9 : #include <cstddef>
10 : #include <memory>
11 :
12 : #include "DataStructures/Tensor/Tensor.hpp"
13 : #include "Utilities/MakeWithValue.hpp"
14 : #include "Utilities/Serialization/CharmPupable.hpp"
15 :
16 : /// \ingroup MathFunctionsGroup
17 : /// Holds classes implementing MathFunction (functions \f$R^n \to R\f$).
18 : namespace MathFunctions {}
19 :
20 : /*!
21 : * \ingroup MathFunctionsGroup
22 : * Encodes a function \f$R^n \to R\f$ where n is `VolumeDim`.
23 : */
24 : template <size_t VolumeDim, typename Fr>
25 : class MathFunction;
26 :
27 : /*!
28 : * \ingroup MathFunctionsGroup
29 : * Encodes a function \f$R^n \to R\f$ where n is `VolumeDim` and where the
30 : * function input (i.e., the spatial coordinates) is given as a rank-1 tensor.
31 : */
32 : template <size_t VolumeDim, typename Fr>
33 1 : class MathFunction : public PUP::able {
34 : public:
35 0 : constexpr static size_t volume_dim = VolumeDim;
36 0 : using frame = Fr;
37 :
38 0 : WRAPPED_PUPable_abstract(MathFunction); // NOLINT
39 0 : MathFunction() = default;
40 0 : virtual std::unique_ptr<MathFunction> get_clone() const = 0;
41 :
42 : /// @{
43 : /// Returns the value of the function at the coordinate 'x'.
44 1 : virtual Scalar<double> operator()(
45 : const tnsr::I<double, VolumeDim, Fr>& x) const = 0;
46 1 : virtual Scalar<DataVector> operator()(
47 : const tnsr::I<DataVector, VolumeDim, Fr>& x) const = 0;
48 : /// @}
49 :
50 : /// @{
51 : /// Returns the first partial derivatives of the function at 'x'.
52 1 : virtual tnsr::i<double, VolumeDim, Fr> first_deriv(
53 : const tnsr::I<double, VolumeDim, Fr>& x) const = 0;
54 1 : virtual tnsr::i<DataVector, VolumeDim, Fr> first_deriv(
55 : const tnsr::I<DataVector, VolumeDim, Fr>& x) const = 0;
56 : /// @}
57 :
58 : /// @{
59 : /// Returns the second partial derivatives of the function at 'x'.
60 1 : virtual tnsr::ii<double, VolumeDim, Fr> second_deriv(
61 : const tnsr::I<double, VolumeDim, Fr>& x) const = 0;
62 1 : virtual tnsr::ii<DataVector, VolumeDim, Fr> second_deriv(
63 : const tnsr::I<DataVector, VolumeDim, Fr>& x) const = 0;
64 : /// @}
65 :
66 : /// @{
67 : /// Returns the third partial derivatives of the function at 'x'.
68 1 : virtual tnsr::iii<double, VolumeDim, Fr> third_deriv(
69 : const tnsr::I<double, VolumeDim, Fr>& x) const = 0;
70 1 : virtual tnsr::iii<DataVector, VolumeDim, Fr> third_deriv(
71 : const tnsr::I<DataVector, VolumeDim, Fr>& x) const = 0;
72 : /// @}
73 :
74 0 : virtual bool operator==(const MathFunction<VolumeDim, Fr>& other) const = 0;
75 0 : virtual bool operator!=(const MathFunction<VolumeDim, Fr>& other) const = 0;
76 : };
77 :
78 : /*!
79 : * \ingroup MathFunctionsGroup
80 : * Partial template specialization of MathFunction which encodes a
81 : * function \f$R \to R\f$. In this 1D specialization, the input and output can
82 : * be `Tensors`, `doubles`, or `DataVectors`.
83 : */
84 : template <typename Fr>
85 1 : class MathFunction<1, Fr> : public PUP::able {
86 : public:
87 0 : constexpr static size_t volume_dim = 1;
88 0 : using frame = Fr;
89 :
90 0 : WRAPPED_PUPable_abstract(MathFunction); // NOLINT
91 0 : MathFunction() = default;
92 0 : virtual std::unique_ptr<MathFunction> get_clone() const = 0;
93 :
94 : /// Returns the function value at the coordinate 'x'
95 1 : virtual double operator()(const double& x) const = 0;
96 0 : virtual DataVector operator()(const DataVector& x) const = 0;
97 0 : Scalar<double> operator()(const tnsr::I<double, 1, Fr>& x) const {
98 : return Scalar<double>{{{operator()(get<0>(x))}}};
99 : }
100 0 : Scalar<DataVector> operator()(const tnsr::I<DataVector, 1, Fr>& x) const {
101 : return Scalar<DataVector>{{{operator()(get<0>(x))}}};
102 : }
103 :
104 : /// Returns the first derivative at 'x'
105 1 : virtual double first_deriv(const double& x) const = 0;
106 0 : virtual DataVector first_deriv(const DataVector& x) const = 0;
107 0 : tnsr::i<double, 1, Fr> first_deriv(const tnsr::I<double, 1, Fr>& x) const {
108 : auto result = make_with_value<tnsr::i<double, 1, Fr>>(get<0>(x), 0.0);
109 : get<0>(result) = first_deriv(get<0>(x));
110 : return result;
111 : }
112 0 : tnsr::i<DataVector, 1, Fr> first_deriv(
113 : const tnsr::I<DataVector, 1, Fr>& x) const {
114 : auto result = make_with_value<tnsr::i<DataVector, 1, Fr>>(get<0>(x), 0.0);
115 : get<0>(result) = first_deriv(get<0>(x));
116 : return result;
117 : }
118 :
119 : /// Returns the second derivative at 'x'
120 1 : virtual double second_deriv(const double& x) const = 0;
121 0 : virtual DataVector second_deriv(const DataVector& x) const = 0;
122 0 : tnsr::ii<double, 1, Fr> second_deriv(const tnsr::I<double, 1, Fr>& x) const {
123 : auto result = make_with_value<tnsr::ii<double, 1, Fr>>(get<0>(x), 0.0);
124 : get<0, 0>(result) = second_deriv(get<0>(x));
125 : return result;
126 : }
127 0 : tnsr::ii<DataVector, 1, Fr> second_deriv(
128 : const tnsr::I<DataVector, 1, Fr>& x) const {
129 : auto result = make_with_value<tnsr::ii<DataVector, 1, Fr>>(get<0>(x), 0.0);
130 : get<0, 0>(result) = second_deriv(get<0>(x));
131 : return result;
132 : }
133 :
134 : /// Returns the third derivative at 'x'
135 1 : virtual double third_deriv(const double& x) const = 0;
136 0 : virtual DataVector third_deriv(const DataVector& x) const = 0;
137 0 : tnsr::iii<double, 1, Fr> third_deriv(const tnsr::I<double, 1, Fr>& x) const {
138 : auto result = make_with_value<tnsr::iii<double, 1, Fr>>(get<0>(x), 0.0);
139 : get<0, 0, 0>(result) = third_deriv(get<0>(x));
140 : return result;
141 : }
142 0 : tnsr::iii<DataVector, 1, Fr> third_deriv(
143 : const tnsr::I<DataVector, 1, Fr>& x) const {
144 : auto result = make_with_value<tnsr::iii<DataVector, 1, Fr>>(get<0>(x), 0.0);
145 : get<0, 0, 0>(result) = third_deriv(get<0>(x));
146 : return result;
147 : }
148 0 : virtual bool operator==(const MathFunction<1, Fr>& other) const = 0;
149 0 : virtual bool operator!=(const MathFunction<1, Fr>& other) const = 0;
150 : };
|