Tatooine
differentiated_field.h
Go to the documentation of this file.
1#ifndef TATOOINE_DIFFERENTIATED_FIELD_H
2#define TATOOINE_DIFFERENTIATED_FIELD_H
3//==============================================================================
4#include <tatooine/field.h>
7#include <tatooine/available_libraries.h>
9#include <tatooine/utility.h>
10//==============================================================================
11namespace tatooine {
12//==============================================================================
13template <field_concept InternalField>
15 : field<numerically_differentiated_field<InternalField>,
16 field_real_type<InternalField>, field_num_dimensions<InternalField>,
17 tensor_add_dimension_right<field_num_dimensions<InternalField>,
18 field_tensor_type<InternalField>>> {
20 std::decay_t<std::remove_pointer_t<InternalField>>;
21 static constexpr auto holds_field_pointer = is_pointer<InternalField>;
22
25 this_type, typename raw_internal_field_t::real_type,
26 raw_internal_field_t::num_dimensions(),
27 tensor_add_dimension_right<raw_internal_field_t::num_dimensions(),
28 typename raw_internal_field_t::tensor_type>>;
29 static constexpr auto num_dimensions() -> std::size_t {
31 }
32 using typename parent_type::pos_type;
33 using typename parent_type::real_type;
35 using typename parent_type::tensor_type;
36 //============================================================================
37 private:
38 InternalField m_internal_field;
40 //============================================================================
41 public:
42 template <convertible_to<InternalField> Field_, arithmetic Eps>
44 : m_internal_field{std::forward<Field_>(f)}, m_eps{tag::fill{eps}} {}
45 //----------------------------------------------------------------------------
47 vec_type const& eps = vec_type::ones() *
48 1e-7) requires holds_field_pointer
49 : m_internal_field{nullptr},
50 m_eps{eps} {}
51 //----------------------------------------------------------------------------
52 template <convertible_to<InternalField> Field_>
54 : m_internal_field{std::forward<Field_>(f)}, m_eps{eps} {}
55 //----------------------------------------------------------------------------
56 template <convertible_to<InternalField> Field_, arithmetic Real>
58 vec<Real, num_dimensions()> const& eps)
59 : m_internal_field{std::forward<Field_>(f)}, m_eps{eps} {}
60 //----------------------------------------------------------------------------
61 constexpr auto evaluate(pos_type const& x, real_type const t) const
62 -> tensor_type {
63 auto derivative = tensor_type{};
64 auto offset = pos_type{};
65 for (std::size_t i = 0; i < num_dimensions(); ++i) {
66 offset(i) = m_eps(i);
67 auto x0 = x - offset;
68 auto x1 = x + offset;
69 auto dx = 2 * m_eps(i);
70 auto y0 = internal_field()(x0, t);
71 auto y1 = internal_field()(x1, t);
72 if (y0.isnan()) {
73 x0 = x;
74 dx = m_eps(i);
75 y0 = internal_field()(x0, t);
76 }
77 if (y1.isnan()) {
78 x1 = x;
79 dx = m_eps(i);
80 y1 = internal_field()(x1, t);
81 }
82 constexpr std::size_t slice_dim = tensor_type::rank() - 1;
83 derivative.template slice<slice_dim>(i) = (y1 - y0) / dx;
84 offset(i) = 0;
85 }
86
87 return derivative;
88 }
89 //----------------------------------------------------------------------------
90 auto set_eps(vec_type const& eps) { m_eps = eps; }
91 auto set_eps(vec_type&& eps) { m_eps = std::move(eps); }
93 auto eps() -> auto& { return m_eps; }
94 auto eps() const -> auto const& { return m_eps; }
95 auto eps(std::size_t i) -> auto& { return m_eps(i); }
96 auto eps(std::size_t i) const { return m_eps(i); }
97 //----------------------------------------------------------------------------
98 auto internal_field() const -> auto const& {
99 if constexpr (holds_field_pointer) {
100 return *m_internal_field;
101 } else {
102 return m_internal_field;
103 }
104 }
105 //----------------------------------------------------------------------------
106 auto set_internal_field(InternalField f)
107 -> void requires(holds_field_pointer) {
109 }
110};
111//==============================================================================
112// deduction guides
113//==============================================================================
114template <typename Field, arithmetic Eps>
117//----------------------------------------------------------------------------
118template <typename Field, arithmetic Eps>
119numerically_differentiated_field(Field const &, Eps const)
121//----------------------------------------------------------------------------
122template <typename Field, arithmetic Eps>
125//----------------------------------------------------------------------------
126template <typename Field, arithmetic Eps>
128 vec<Eps, field_num_dimensions<Field>> const &)
130//----------------------------------------------------------------------------
131template <typename Field, arithmetic Eps>
133 vec<Eps, field_num_dimensions<Field>> const &)
135//----------------------------------------------------------------------------
136template <typename Field, arithmetic Eps>
138 vec<Eps, field_num_dimensions<Field>> const &)
140//==============================================================================
142 return numerically_differentiated_field{std::forward<decltype(field)>(field)};
143}
144//------------------------------------------------------------------------------
146 arithmetic auto const epsilon) {
147 return numerically_differentiated_field{std::forward<decltype(field)>(field),
148 epsilon};
149}
150//------------------------------------------------------------------------------
151auto diff(field_concept auto&& field, arithmetic auto const epsilon) {
152 return diff(std::forward<decltype(field)>(field), tag::numerical, epsilon);
153}
154//------------------------------------------------------------------------------
155auto diff(
156 field_concept auto&& field, tag::numerical_t /*tag*/,
157 fixed_size_real_vec<std::decay_t<decltype(field)>::num_dimensions()> auto&&
158 epsilon) {
160 std::forward<decltype(field)>(field),
161 std::forward<decltype(epsilon)>(epsilon)};
162}
163//------------------------------------------------------------------------------
164auto diff(
165 field_concept auto&& field,
166 fixed_size_real_vec<std::decay_t<decltype(field)>::num_dimensions()> auto&&
167 epsilon) {
168 return diff(std::forward<decltype(field)>(field), tag::numerical,
169 std::forward<decltype(epsilon)>(epsilon));
170}
171//==============================================================================
172template <typename InternalField>
176};
177//==============================================================================
178// deduction guides
179//==============================================================================
180template <typename Field, arithmetic Eps>
182//----------------------------------------------------------------------------
183template <typename Field, arithmetic Eps>
184differentiated_field(Field const &, Eps const)
186//----------------------------------------------------------------------------
187template <typename Field, arithmetic Eps>
189//----------------------------------------------------------------------------
190template <typename Field, arithmetic Eps>
191differentiated_field(Field &&f, vec<Eps, field_num_dimensions<Field>> const &)
193//----------------------------------------------------------------------------
194template <typename Field, arithmetic Eps>
195differentiated_field(Field const &f,
196 vec<Eps, field_num_dimensions<Field>> const &)
198//----------------------------------------------------------------------------
199template <typename Field, arithmetic Eps>
200differentiated_field(Field &f, vec<Eps, field_num_dimensions<Field>> const &)
202//==============================================================================
204 return differentiated_field{std::forward<decltype(field)>(field), 1e-10};
205}
206//==============================================================================
207template <typename InternalField>
209 : field<time_differentiated_field<InternalField>,
210 typename std::decay_t<InternalField>::real_type,
211 std::decay_t<InternalField>::num_dimensions(),
212 typename std::decay_t<InternalField>::tensor_type> {
216 std::decay_t<InternalField>::num_dimensions(),
217 typename std::decay_t<InternalField>::tensor_type>;
219 using typename parent_type::pos_type;
220 using typename parent_type::real_type;
222 using typename parent_type::tensor_type;
223 static constexpr auto holds_field_pointer = is_pointer<InternalField>;
224
225 //============================================================================
226 private:
227 InternalField m_internal_field;
229 //============================================================================
230 public:
231 template <typename Field_, arithmetic Eps>
232 time_differentiated_field(Field_&& f, Eps const eps)
233 : m_internal_field{std::forward<Field_>(f)},
234 m_eps{static_cast<real_type>(eps)} {}
235 //----------------------------------------------------------------------------
236 constexpr auto evaluate(pos_type const& x, real_type const t) const
237 -> tensor_type {
238 auto t0 = t - m_eps;
239 auto t1 = t + m_eps;
240 auto dt = 2 * m_eps;
241 auto x0 = internal_field()(x, t0);
242 auto x1 = internal_field()(x, t1);
243 if (x0.is_nan) {
244 t0 = t;
245 dt = m_eps;
246 x0 = internal_field()(x, t0);
247 }
248 if (x1) {
249 t1 = t;
250 dt = m_eps;
251 x1 = internal_field()(x, t1);
252 }
253 return (x1 - x0) / dt;
254 }
255 //----------------------------------------------------------------------------
257 auto eps() -> auto& { return m_eps; }
258 auto eps() const -> auto const& { return m_eps; }
259 //----------------------------------------------------------------------------
260 auto internal_field() const -> auto const& {
261 if constexpr (holds_field_pointer) {
262 return *m_internal_field;
263 } else {
264 return m_internal_field;
265 }
266 }
267};
268//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
269template <typename Field, typename Real, std::size_t NumDimensions,
270 typename Tensor>
272 Real const eps) {
274}
275// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
276template <typename Field, typename Real, std::size_t NumDimensions,
277 typename Tensor>
280}
281// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
282template <typename Field, typename Real, std::size_t NumDimensions,
283 typename Tensor>
285 return time_differentiated_field<Field>{std::move(f.as_derived()), eps};
286}
287// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
288template <typename Real, std::size_t NumDimensions, typename Tensor>
290 Real const eps) {
293}
294//==============================================================================
295} // namespace tatooine
296//==============================================================================
297#endif
Definition: concepts.h:33
Definition: field_concept.h:16
Definition: tensor_concepts.h:36
static constexpr numerical_t numerical
Definition: tags.h:93
Definition: algorithm.h:6
auto diff_time(field< Field, Real, NumDimensions, Tensor > const &f, Real const eps)
Definition: differentiated_field.h:271
tensor< real_number, Dimensions... > Tensor
Definition: tensor.h:184
constexpr auto diff(polynomial< Real, Degree > const &f)
Definition: polynomial.h:179
typename tensor_add_dimension_right_impl< NewRightDim, Tensor >::type tensor_add_dimension_right
Definition: tensor_type_operations.h:14
static constexpr forward_tag forward
Definition: tags.h:9
Definition: differentiated_field.h:173
Definition: field.h:134
Real real_type
Definition: field.h:17
vec< real_type, NumDimensions > pos_type
Definition: field.h:20
Tensor tensor_type
Definition: field.h:18
auto as_derived() -> auto &
Definition: field.h:161
auto num_dimensions() const -> std::size_t
Definition: hdf5.h:764
Definition: differentiated_field.h:18
std::decay_t< std::remove_pointer_t< InternalField > > raw_internal_field_t
Definition: differentiated_field.h:20
auto eps() const -> auto const &
Definition: differentiated_field.h:94
auto eps(std::size_t i) -> auto &
Definition: differentiated_field.h:95
InternalField m_internal_field
Definition: differentiated_field.h:38
static constexpr auto num_dimensions() -> std::size_t
Definition: differentiated_field.h:29
auto internal_field() const -> auto const &
Definition: differentiated_field.h:98
auto set_internal_field(InternalField f) -> void requires(holds_field_pointer)
Definition: differentiated_field.h:106
auto eps() -> auto &
Definition: differentiated_field.h:93
numerically_differentiated_field(Field_ &&f, vec_type const &eps)
Definition: differentiated_field.h:53
numerically_differentiated_field(vec_type const &eps=vec_type::ones() *1e-7)
Definition: differentiated_field.h:46
auto eps(std::size_t i) const
Definition: differentiated_field.h:96
numerically_differentiated_field< InternalField > this_type
Definition: differentiated_field.h:23
auto set_eps(vec_type &&eps)
Definition: differentiated_field.h:91
numerically_differentiated_field(Field_ &&f, Eps const eps)
Definition: differentiated_field.h:43
static constexpr auto holds_field_pointer
Definition: differentiated_field.h:21
auto set_eps(real_type eps)
Definition: differentiated_field.h:92
vec_type m_eps
Definition: differentiated_field.h:39
numerically_differentiated_field(Field_ &&f, vec< Real, num_dimensions()> const &eps)
Definition: differentiated_field.h:57
constexpr auto evaluate(pos_type const &x, real_type const t) const -> tensor_type
Definition: differentiated_field.h:61
auto set_eps(vec_type const &eps)
Definition: differentiated_field.h:90
Definition: field.h:13
static constexpr auto num_dimensions() -> std::size_t
Definition: field.h:38
Definition: tags.h:96
Definition: tags.h:92
Definition: differentiated_field.h:212
InternalField m_internal_field
Definition: differentiated_field.h:227
static constexpr auto holds_field_pointer
Definition: differentiated_field.h:223
constexpr auto evaluate(pos_type const &x, real_type const t) const -> tensor_type
Definition: differentiated_field.h:236
auto eps() -> auto &
Definition: differentiated_field.h:257
auto internal_field() const -> auto const &
Definition: differentiated_field.h:260
real_type m_eps
Definition: differentiated_field.h:228
auto set_eps(real_type eps)
Definition: differentiated_field.h:256
time_differentiated_field(Field_ &&f, Eps const eps)
Definition: differentiated_field.h:232
auto eps() const -> auto const &
Definition: differentiated_field.h:258
static auto constexpr ones()
Definition: vec.h:28