Tatooine
radial_basis_functions_sampler_with_gradients.h
Go to the documentation of this file.
1#if TATOOINE_BLAS_AND_LAPACK_AVAILABLE
2#ifndef TATOOINE_DETAIL_POINTSET_RADIAL_BASIS_FUNCTIONS_SAMPLER_WITH_GRADIENTS_H
3#define TATOOINE_DETAIL_POINTSET_RADIAL_BASIS_FUNCTIONS_SAMPLER_WITH_GRADIENTS_H
4//==============================================================================
5#include <tatooine/concepts.h>
6#include <tatooine/field.h>
7#include <tatooine/pointset.h>
8#include <tatooine/tags.h>
9//==============================================================================
11//==============================================================================
12namespace rbf_gradient_kernel {
13//==============================================================================
14static constexpr auto kernel_from_squared(floating_point auto const sqr_r) {
15 return sqr_r * sqr_r * gcem::log(sqr_r) / 2;
16}
17//------------------------------------------------------------------------------
18static constexpr auto kernel_from_squared(fixed_size_real_vec<2> auto const& p1, fixed_size_real_vec<2> auto const& p2) {
19 auto const x1_m_x2 = p1(0) - p2(0);
20 auto const x1_m_x2_sqr = x1_m_x2 * x1_m_x2;
21 auto const y1_m_y2 = p1.y() - p2.y();
22 auto const y1_m_y2_sqr = y1_m_y2 * y1_m_y2;
23 return (gcem::log(y1_m_y2_sqr + x1_m_x2_sqr) * (y1_m_y2_sqr + x1_m_x2_sqr) *
24 (y1_m_y2_sqr + x1_m_x2_sqr)) /
25 2;
26}
27//------------------------------------------------------------------------------
28static constexpr auto kernel_from_squared_x1(fixed_size_real_vec<2> auto const& p1, fixed_size_real_vec<2> auto const& p2) {
29 return ((2 * p1(0) - 2 * p2(0)) * p2(1) * p2(1) +
30 (4 * p2(0) - 4 * p1(0)) * p1(1) * p2(1) +
31 (2 * p1(0) - 2 * p2(0)) * p1(1) * p1(1) -
32 2 * p2(0) * p2(0) * p2(0) + 6 * p1(0) * p2(0) * p2(0) -
33 6 * p1(0) * p1(0) * p2(0) + 2 * p1(0) * p1(0) * p1(0)) *
34 gcem::log(p2(1) * p2(1) - 2 * p1(1) * p2(1) + p1(1) * p1(1) +
35 p2(0) * p2(0) - 2 * p1(0) * p2(0) +
36 p1(0) * p1(0)) +
37 (p1(0) - p2(0)) * p2(1) * p2(1) +
38 (2 * p2(0) - 2 * p1(0)) * p1(1) * p2(1) +
39 (p1(0) - p2(0)) * p1(1) * p1(1) - p2(0) * p2(0) * p2(0) +
40 3 * p1(0) * p2(0) * p2(0) - 3 * p1(0) * p1(0) * p2(0) +
41 p1(0) * p1(0) * p1(0);
42}
43//------------------------------------------------------------------------------
44static constexpr auto kernel_from_squared_y1(fixed_size_real_vec<2> auto const& p1, fixed_size_real_vec<2> auto const& p2) {
45 return (-2 * p2(1) * p2(1) * p2(1) + 6 * p1(1) * p2(1) * p2(1) +
46 (-6 * p1(1) * p1(1) - 2 * p2(0) * p2(0) + 4 * p1(0) * p2(0) -
47 2 * p1(0) * p1(0)) *
48 p2(1) +
49 2 * p1(1) * p1(1) * p1(1) +
50 (2 * p2(0) * p2(0) - 4 * p1(0) * p2(0) + 2 * p1(0) * p1(0)) *
51 p1(1)) *
52 gcem::log(p2(1) * p2(1) - 2 * p1(1) * p2(1) + p1(1) * p1(1) +
53 p2(0) * p2(0) - 2 * p1(0) * p2(0) +
54 p1(0) * p1(0)) -
55 p2(1) * p2(1) * p2(1) + 3 * p1(1) * p2(1) * p2(1) +
56 (-3 * p1(1) * p1(1) - p2(0) * p2(0) + 2 * p1(0) * p2(0) -
57 p1(0) * p1(0)) *
58 p2(1) +
59 p1(1) * p1(1) * p1(1) +
60 (p2(0) * p2(0) - 2 * p1(0) * p2(0) + p1(0) * p1(0)) * p1(1);
61}
62//------------------------------------------------------------------------------
63static constexpr auto kernel_from_squared_x1_x2(fixed_size_real_vec<2> auto const& p1,
64 fixed_size_real_vec<2> auto const& p2) {
65 return (-2 * p2(1) * p2(1) + 4 * p1(1) * p2(1) - 2 * p1(1) * p1(1) -
66 6 * p2(0) * p2(0) + 12 * p1(0) * p2(0) - 6 * p1(0) * p1(0)) *
67 gcem::log(p2(1) * p2(1) - 2 * p1(1) * p2(1) + p1(1) * p1(1) +
68 p2(0) * p2(0) - 2 * p1(0) * p2(0) +
69 p1(0) * p1(0)) -
70 p2(1) * p2(1) + 2 * p1(1) * p2(1) - p1(1) * p1(1) -
71 7 * p2(0) * p2(0) + 14 * p1(0) * p2(0) - 7 * p1(0) * p1(0);
72}
73//------------------------------------------------------------------------------
74static constexpr auto kernel_from_squared_y1_x2(fixed_size_real_vec<2> auto const& p1,
75 fixed_size_real_vec<2> auto const& p2) {
76 return ((4 * p1(0) - 4 * p2(0)) * p2(1) +
77 (4 * p2(0) - 4 * p1(0)) * p1(1)) *
78 gcem::log(p2(1) * p2(1) - 2 * p1(1) * p2(1) + p1(1) * p1(1) +
79 p2(0) * p2(0) - 2 * p1(0) * p2(0) +
80 p1(0) * p1(0)) +
81 (6 * p1(0) - 6 * p2(0)) * p2(1) +
82 (6 * p2(0) - 6 * p1(0)) * p1(1);
83}
84//------------------------------------------------------------------------------
85static constexpr auto kernel_from_squared_y1_y2(fixed_size_real_vec<2> auto const& p1,
86 fixed_size_real_vec<2> auto const& p2) {
87 return (-6 * p2(1) * p2(1) + 12 * p1(1) * p2(1) - 6 * p1(1) * p1(1) -
88 2 * p2(0) * p2(0) + 4 * p1(0) * p2(0) - 2 * p1(0) * p1(0)) *
89 gcem::log(p2(1) * p2(1) - 2 * p1(1) * p2(1) + p1(1) * p1(1) +
90 p2(0) * p2(0) - 2 * p1(0) * p2(0) +
91 p1(0) * p1(0)) -
92 7 * p2(1) * p2(1) + 14 * p1(1) * p2(1) - 7 * p1(1) * p1(1) -
93 p2(0) * p2(0) + 2 * p1(0) * p2(0) - p1(0) * p1(0);
94}
95//==============================================================================
96} // namespace rbf_gradient_kernel
97//==============================================================================
98template <floating_point Real, std::size_t NumDimensions, typename ValueType,
99 typename GradientType>
101//==============================================================================
102template <floating_point Real, floating_point ValueType>
104 vec<ValueType, 2>>
105 : field<radial_basis_functions_sampler_with_gradients<Real, 2, ValueType,
106 vec<ValueType, 2>>,
107 Real, 2, ValueType> {
108 using value_type = ValueType;
110 using this_type =
114 using typename parent_type::pos_type;
115 using typename parent_type::real_type;
116 using typename parent_type::tensor_type;
119 template <typename S>
121 typename pointset_type::template typed_vertex_property_type<S>;
124 //==========================================================================
125 private:
129 tensor<Real> m_coefficients = {};
130 //==========================================================================
131 public:
132 auto pointset() const -> auto const& { return m_pointset; }
133 auto coefficients() const -> auto const& { return m_coefficients; }
134 auto coefficient(vertex_handle const v) const -> auto const& {
135 return m_coefficients(v.index());
136 }
137 auto coefficient(std::size_t const i) const -> auto const& {
138 return m_coefficients(i);
139 }
140 auto f() const -> auto const& { return m_f; }
141 auto f(vertex_handle const v) const -> auto const& { return m_f[v]; }
142 auto f(std::size_t const i) const -> auto const& { return m_f[i]; }
143 auto df() const -> auto const& { return m_df; }
144 auto df(vertex_handle const v) const -> auto const& { return m_df[v]; }
145 auto df(std::size_t const i) const -> auto const& { return m_df[i]; }
146
147 //==========================================================================
150 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
153 //--------------------------------------------------------------------------
156 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
159 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
161 //--------------------------------------------------------------------------
163 f_property_type const& f,
164 df_property_type const& df)
166 ps, f, df, execution_policy::sequential} {}
167 //----------------------------------------------------------------------------
168 // radial_basis_functions_sampler_with_gradients(pointset_type const& ps,
169 // f_property_type const& f,
170 // df_property_type<Df> const&
171 // df,
172 // execution_policy::parallel_t
173 // /*pol*/)
174 // : m_pointset{ps}, m_f{f}, m_df{df}, m_coefficients{} {
175 // auto const N = m_pointset.vertices().size();
176 // // construct lower part
177 // of symmetric matrix A auto A = tensor<real_type>::zeros(N, N);
178 //#pragma omp parallel for
179 // collapse(2) for (std::size_t c = 0; c < N; ++c) {
180 // for (std::size_t r = c + 1; r < N; ++r) {
181 // A(r, c) = rbf_gradient_kernel::kernel_from_squared(squared_euclidean_distance(
182 // m_pointset.vertex_at(c), m_pointset.vertex_at(r)));
183 // }
184 // }
185 // m_coefficients = [N] {
186 // return tensor<value_type>::zeros(N);
187 // }();
188 //
189 //#pragma omp parallel for
190 // for (std::size_t i = 0; i < N; ++i) {
191 // m_coefficients(i) = m_f[i];
192 // }
193 // // do not copy by moving
194 // A and m_coefficients into solver m_coefficients =
195 // *solve_symmetric_lapack(
196 // std::move(A), std::move(m_coefficients), lapack::uplo::lower);
197 // }
198 //----------------------------------------------------------------------------
200 pointset_type const& ps, f_property_type const& f_,
202 : m_pointset{ps}, m_f{f_}, m_df{df_} {
203 auto const N = pointset().vertices().size();
204 // construct lower part of
205 // symmetric matrix A
206 auto A = tensor<real_type>::zeros(N * 3 + 3, N * 3 + 3);
207 for (std::size_t c = 0; c < N; ++c) {
208 for (std::size_t r = c + 1; r < N; ++r) {
210 pointset().vertex_at(c), pointset().vertex_at(r));
211 }
212 }
213
214 // differentiated to x1
215 for (std::size_t c = 0; c < N; ++c) {
216 for (std::size_t r = N; r < N * 2; ++r) {
217 if (c == r - N) {
218 A(r, c) = 0;
219 } else {
220 auto const& p1 = pointset().vertex_at(c);
221 auto const& p2 = pointset().vertex_at(r - N);
223 }
224 }
225 }
226 // differentiated to y1
227 for (std::size_t c = 0; c < N; ++c) {
228 for (std::size_t r = N * 2; r < N * 3; ++r) {
229 if (c == r - N * 2) {
230 A(r, c) = 0;
231 } else {
232 auto const& p1 = pointset().vertex_at(c);
233 auto const& p2 = pointset().vertex_at(r - 2 * N);
235 }
236 }
237 }
238 // differentiated to x1 and x2
239 for (std::size_t c = N; c < N * 2; ++c) {
240 for (std::size_t r = c + 1; r < N * 2; ++r) {
241 auto const& p1 = pointset().vertex_at(c - N);
242 auto const& p2 = pointset().vertex_at(r - N);
244 }
245 }
246 // differentiated to y1 and x2
247 for (std::size_t c = N; c < N * 2; ++c) {
248 for (std::size_t r = N * 2; r < N * 3; ++r) {
249 if (c - N == r - N * 2) {
250 A(r, c) = 0;
251 } else {
252 auto const& p1 = pointset().vertex_at(c - N);
253 auto const& p2 = pointset().vertex_at(r - N * 2);
255 }
256 }
257 }
258 // differentiated to y1 and y2
259 for (std::size_t c = N * 2; c < N * 3; ++c) {
260 for (std::size_t r = c + 1; r < N * 3; ++r) {
261 auto const& p1 = pointset().vertex_at(c - N * 2);
262 auto const& p2 = pointset().vertex_at(r - N * 2);
264 }
265 }
266
267 // linear monomial basis constant part
268 // constant part of derivatives is already 0.
269 for (std::size_t c = 0; c < N; ++c) {
270 A(N * 3, c) = 1;
271 }
272
273 // linear monomial basis linear part x
274 for (std::size_t c = 0; c < N; ++c) {
275 A(N * 3 + 1, c) = pointset().vertex_at(c).x();
276 A(N * 3 + 2, c) = pointset().vertex_at(c).y();
277
278 A(N * 3 + 1, c + N) = 1;
279 A(N * 3 + 2, c + 2 * N) = 1;
280 }
281
282 m_coefficients = [N] { return tensor<value_type>::zeros(N * 3 + 3); }();
283
284 for (std::size_t i = 0; i < N; ++i) {
285 m_coefficients(i) = f(i);
286 }
287 for (std::size_t i = N; i < N * 2; ++i) {
288 m_coefficients(i) = df(i - N).x();
289 }
290 for (std::size_t i = N * 2; i < N * 3; ++i) {
291 m_coefficients(i) = df(i - N * 2).y();
292 }
293 // do not copy by moving A
294 // and m_coefficients into
295 // solver
296 m_coefficients = *solve_symmetric_lapack(
297 std::move(A), std::move(m_coefficients), lapack::uplo::lower);
298 }
299 //==========================================================================
300 [[nodiscard]] auto evaluate(pos_type const& q, real_type const /*t*/) const
301 -> tensor_type {
302 auto acc = value_type{};
303 auto const N = pointset().vertices().size();
304 for (auto const v : pointset().vertices()) {
305 auto const sqr_dist = squared_euclidean_distance(q, pointset()[v]);
306 if (sqr_dist == 0) {
307 return f(v);
308 }
309 acc += coefficient(v) * rbf_gradient_kernel::kernel_from_squared(sqr_dist);
310 acc -= coefficient(v + N) * rbf_gradient_kernel::kernel_from_squared_x1(q, pointset()[v]);
311 acc -= coefficient(v + N * 2) * rbf_gradient_kernel::kernel_from_squared_y1(q, pointset()[v]);
312 }
313 acc += coefficient(N * 3);
314 acc += coefficient(N * 3 + 1) * q.x();
315 acc += coefficient(N * 3 + 2) * q.y();
316 return acc;
317 }
318};
319//==============================================================================
320template <floating_point Real, floating_point ValueType>
322 mat<ValueType, 2, 2>>
323 : field<radial_basis_functions_sampler_with_gradients<Real, 2, vec<ValueType, 2>,
324 mat<ValueType, 2, 2>>,
325 Real, 2, vec<ValueType, 2>> {
328 using this_type =
332 using typename parent_type::pos_type;
333 using typename parent_type::real_type;
334 using typename parent_type::tensor_type;
337 template <typename S>
339 typename pointset_type::template typed_vertex_property_type<S>;
342 //==========================================================================
343 private:
347 tensor<Real> m_coefficients = {};
348 //==========================================================================
349 public:
350 auto pointset() const -> auto const& { return m_pointset; }
351 auto coefficients() const -> auto const& { return m_coefficients; }
352 auto coefficient(vertex_handle const v, std::size_t const j) const
353 -> auto const& {
354 return m_coefficients(v.index(), j);
355 }
356 auto coefficient(std::size_t const i, std::size_t const j) const
357 -> auto const& {
358 return m_coefficients(i, j);
359 }
360 auto f() const -> auto const& { return m_f; }
361 auto f(vertex_handle const v) const -> auto const& { return m_f[v]; }
362 auto f(std::size_t const i) const -> auto const& { return m_f[i]; }
363 auto df() const -> auto const& { return m_df; }
364 auto df(vertex_handle const v) const -> auto const& { return m_df[v]; }
365 auto df(std::size_t const i) const -> auto const& { return m_df[i]; }
366
367 //==========================================================================
370 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
373 //--------------------------------------------------------------------------
376 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
379 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
381 //--------------------------------------------------------------------------
383 f_property_type const& f,
384 df_property_type const& df)
386 ps, f, df, execution_policy::sequential} {}
387 //----------------------------------------------------------------------------
388 // radial_basis_functions_sampler_with_gradients(pointset_type const& ps,
389 // f_property_type const& f,
390 // df_property_type<Df> const&
391 // df,
392 // execution_policy::parallel_t
393 // /*pol*/)
394 // : m_pointset{ps}, m_f{f}, m_df{df}, m_coefficients{} {
395 // auto const N = m_pointset.vertices().size();
396 // // construct lower part
397 // of symmetric matrix A auto A = tensor<real_type>::zeros(N, N);
398 //#pragma omp parallel for
399 // collapse(2) for (std::size_t c = 0; c < N; ++c) {
400 // for (std::size_t r = c + 1; r < N; ++r) {
401 // A(r, c) = rbf_gradient_kernel::kernel_from_squared(squared_euclidean_distance(
402 // m_pointset.vertex_at(c), m_pointset.vertex_at(r)));
403 // }
404 // }
405 // m_coefficients = [N] {
406 // return tensor<value_type>::zeros(N);
407 // }();
408 //
409 //#pragma omp parallel for
410 // for (std::size_t i = 0; i < N; ++i) {
411 // m_coefficients(i) = m_f[i];
412 // }
413 // // do not copy by moving
414 // A and m_coefficients into solver m_coefficients =
415 // *solve_symmetric_lapack(
416 // std::move(A), std::move(m_coefficients), lapack::uplo::lower);
417 // }
418 //----------------------------------------------------------------------------
420 pointset_type const& ps, f_property_type const& f_,
422 : m_pointset{ps}, m_f{f_}, m_df{df_} {
423 auto const N = pointset().vertices().size();
424 // construct lower part of
425 // symmetric matrix A
426 auto A = tensor<real_type>::zeros(N * 3 + 3, N * 3 + 3);
427 for (std::size_t c = 0; c < N; ++c) {
428 for (std::size_t r = c + 1; r < N; ++r) {
430 pointset().vertex_at(c), pointset().vertex_at(r));
431 }
432 }
433
434 // differentiated to x1
435 for (std::size_t c = 0; c < N; ++c) {
436 for (std::size_t r = N; r < N * 2; ++r) {
437 if (c == r - N) {
438 A(r, c) = 0;
439 } else {
440 auto const& p1 = pointset().vertex_at(c);
441 auto const& p2 = pointset().vertex_at(r - N);
443 }
444 }
445 }
446 // differentiated to y1
447 for (std::size_t c = 0; c < N; ++c) {
448 for (std::size_t r = N * 2; r < N * 3; ++r) {
449 if (c == r - N * 2) {
450 A(r, c) = 0;
451 } else {
452 auto const& p1 = pointset().vertex_at(c);
453 auto const& p2 = pointset().vertex_at(r - 2 * N);
455 }
456 }
457 }
458 // differentiated to x1 and x2
459 for (std::size_t c = N; c < N * 2; ++c) {
460 for (std::size_t r = c + 1; r < N * 2; ++r) {
461 auto const& p1 = pointset().vertex_at(c - N);
462 auto const& p2 = pointset().vertex_at(r - N);
464 }
465 }
466 // differentiated to y1 and x2
467 for (std::size_t c = N; c < N * 2; ++c) {
468 for (std::size_t r = N * 2; r < N * 3; ++r) {
469 if (c - N == r - N * 2) {
470 A(r, c) = 0;
471 } else {
472 auto const& p1 = pointset().vertex_at(c - N);
473 auto const& p2 = pointset().vertex_at(r - N * 2);
475 }
476 }
477 }
478 // differentiated to y1 and y2
479 for (std::size_t c = N * 2; c < N * 3; ++c) {
480 for (std::size_t r = c + 1; r < N * 3; ++r) {
481 auto const& p1 = pointset().vertex_at(c - N * 2);
482 auto const& p2 = pointset().vertex_at(r - N * 2);
484 }
485 }
486
487 // linear monomial basis constant part
488 // constant part of derivatives is already 0.
489 for (std::size_t c = 0; c < N; ++c) {
490 A(N * 3, c) = 1;
491 }
492
493 // linear monomial basis linear part x
494 for (std::size_t c = 0; c < N; ++c) {
495 A(N * 3 + 1, c) = pointset().vertex_at(c).x();
496 A(N * 3 + 2, c) = pointset().vertex_at(c).y();
497
498 A(N * 3 + 1, c + N) = 1;
499 A(N * 3 + 2, c + 2 * N) = 1;
500 }
501
502 m_coefficients = [N] { return tensor<ValueType>::zeros(N * 3 + 3, 2); }();
503
504 for (std::size_t i = 0; i < N; ++i) {
505 for (std::size_t j = 0; j < 2; ++j) {
506 m_coefficients(i, j) = f(i)(j);
507 }
508 }
509 for (std::size_t i = N; i < N * 2; ++i) {
510 for (std::size_t j = 0; j < 2; ++j) {
511 m_coefficients(i, j) = df(i - N)(j, 0);
512 }
513 }
514 for (std::size_t i = N * 2; i < N * 3; ++i) {
515 for (std::size_t j = 0; j < 2; ++j) {
516 m_coefficients(i, j) = df(i - N*2)(j, 1);
517 }
518 }
519 // do not copy by moving A
520 // and m_coefficients into
521 // solver
522 m_coefficients = *solve_symmetric_lapack(
523 std::move(A), std::move(m_coefficients), lapack::uplo::lower);
524 }
525 //==========================================================================
526 [[nodiscard]] auto evaluate(pos_type const& q, real_type const /*t*/) const
527 -> tensor_type {
528 auto acc = value_type{};
529 auto const N = pointset().vertices().size();
530 for (std::size_t j = 0; j < 2; ++j) {
531 for (auto const v : pointset().vertices()) {
532 auto const sqr_dist = squared_euclidean_distance(q, pointset()[v]);
533 if (sqr_dist == 0) {
534 return f(v);
535 }
536 acc(j) +=
537 coefficient(v, j) * rbf_gradient_kernel::kernel_from_squared(sqr_dist);
538 acc(j) -= coefficient(v + N, j) *
540 acc(j) -= coefficient(v + N * 2, j) *
542 }
543 acc(j) += coefficient(N * 3, j);
544 acc(j) += coefficient(N * 3 + 1, j) * q.x();
545 acc(j) += coefficient(N * 3 + 2, j) * q.y();
546 }
547 return acc;
548 }
549};
550//==============================================================================
551template <floating_point Real, std::size_t NumDimensions, typename ValueType,
552 typename GradientType>
557 ValueType> const&,
560 GradientType> const&)
562 ValueType, GradientType>;
563//==============================================================================
564template <floating_point Real, std::size_t NumDimensions, typename ValueType,
565 typename GradientType>
567//==============================================================================
568template <floating_point Real, floating_point ValueType>
570 Real, 2, ValueType, vec<ValueType, 2>>
571 : field<differentiated_radial_basis_functions_sampler_with_gradients<
572 Real, 2, ValueType, vec<ValueType, 2>>,
573 Real, 2, vec<ValueType, 2>> {
574 using this_type =
576 Real, 2, ValueType, vec<ValueType, 2>>;
578 using base_type =
581 using typename parent_type::pos_type;
582 using typename parent_type::real_type;
583 using typename parent_type::tensor_type;
586
587 private:
589
590 public:
591 auto base() const -> auto const& { return m_base; }
592 auto pointset() const -> auto const& { return base().pointset(); }
593 auto coefficients() const -> auto const& { return base().coefficients(); }
594 auto coefficient(vertex_handle const v) const -> auto const& {
595 return base().coefficient(v.index());
596 }
597 auto coefficient(std::size_t const i) const -> auto const& {
598 return base().coefficient(i);
599 }
600
602 base_type const& base)
603 : m_base{base} {}
604 auto f() const -> auto const& { return base().df(); }
605 auto f(vertex_handle const v) const -> auto const& { return f()[v]; }
606 auto f(std::size_t const i) const -> auto const& { return f()[i]; }
607 //==========================================================================
608 [[nodiscard]] auto evaluate(pos_type const& q, real_type const /*t*/) const
609 -> tensor_type {
610 auto acc = vec<ValueType, 2>{};
611 auto const N = pointset().vertices().size();
612 for (auto const v : pointset().vertices()) {
613 auto const sqr_dist = squared_euclidean_distance(q, pointset()[v]);
614 if (sqr_dist == 0) {
615 return f(v);
616 }
617 acc.x() +=
619 acc.x() -= coefficient(v + N) *
621 acc.x() -= coefficient(v + N * 2) *
623
624 acc.y() +=
626 acc.y() -= coefficient(v + N) *
628 acc.y() -= coefficient(v + N * 2) *
630 }
631 acc.x() += coefficient(N * 3 + 1);
632 acc.y() += coefficient(N * 3 + 2);
633 return acc;
634 }
635};
636//==============================================================================
637template <floating_point Real, floating_point ValueType>
639 Real, 2, vec<ValueType, 2>, mat<ValueType, 2, 2>>
640 : field<differentiated_radial_basis_functions_sampler_with_gradients<
641 Real, 2, vec<ValueType, 2>, mat<ValueType, 2, 2>>,
642 Real, 2, mat<ValueType, 2, 2>> {
643 using this_type =
647 using base_type =
650 using typename parent_type::pos_type;
651 using typename parent_type::real_type;
652 using typename parent_type::tensor_type;
655
656 private:
658
659 public:
660 auto base() const -> auto const& { return m_base; }
661 auto pointset() const -> auto const& { return base().pointset(); }
662 auto coefficients() const -> auto const& { return base().coefficients(); }
663 auto coefficient(vertex_handle const v, std::size_t const j) const
664 -> auto const& {
665 return base().coefficient(v.index(), j);
666 }
667 auto coefficient(std::size_t const i, std::size_t const j) const
668 -> auto const& {
669 return base().coefficient(i, j);
670 }
671
673 base_type const& base)
674 : m_base{base} {}
675 auto f() const -> auto const& { return base().df(); }
676 auto f(vertex_handle const v) const -> auto const& { return f()[v]; }
677 auto f(std::size_t const i) const -> auto const& { return f()[i]; }
678 //==========================================================================
679 [[nodiscard]] auto evaluate(pos_type const& q, real_type const /*t*/) const
680 -> tensor_type {
681 auto acc = tensor_type{};
682 auto const N = pointset().vertices().size();
683 for (auto const v : pointset().vertices()) {
684 auto const sqr_dist = squared_euclidean_distance(q, pointset()[v]);
685 if (sqr_dist == 0) {
686 return f(v);
687 }
688 for (std::size_t j = 0; j < 2; ++j) {
689 acc(j, 0) +=
690 coefficient(v, j) *
692 acc(j, 0) -=
693 coefficient(v + N, j) *
695 acc(j, 0) -=
696 coefficient(v + N * 2, j) *
698
699 acc(j, 1) +=
700 coefficient(v, j) *
702 acc(j, 1) -=
703 coefficient(v + N, j) *
705 acc(j, 1) -=
706 coefficient(v + N * 2, j) *
708 }
709 }
710 for (std::size_t j = 0; j < 2; ++j) {
711 for (std::size_t i = 0; i < 2; ++i) {
712 acc(j, i) += coefficient(N * 3 + i + 1, j);
713 }
714 }
715 return acc;
716 }
717};
718//==============================================================================
719template <floating_point Real, std::size_t NumDimensions, typename ValueType,
720 typename GradientType>
722 Real, NumDimensions, ValueType, GradientType> const& f) {
724 Real, NumDimensions, ValueType, GradientType>{f};
725}
726//==============================================================================
727} // namespace tatooine::detail::pointset
728//==============================================================================
729#endif
730#endif
Definition: tensor_concepts.h:36
Definition: concepts.h:30
static constexpr auto kernel_from_squared(floating_point auto const sqr_r)
Definition: radial_basis_functions_sampler_with_gradients.h:14
static constexpr auto kernel_from_squared_y1(fixed_size_real_vec< 2 > auto const &p1, fixed_size_real_vec< 2 > auto const &p2)
Definition: radial_basis_functions_sampler_with_gradients.h:44
static constexpr auto kernel_from_squared_y1_y2(fixed_size_real_vec< 2 > auto const &p1, fixed_size_real_vec< 2 > auto const &p2)
Definition: radial_basis_functions_sampler_with_gradients.h:85
static constexpr auto kernel_from_squared_x1(fixed_size_real_vec< 2 > auto const &p1, fixed_size_real_vec< 2 > auto const &p2)
Definition: radial_basis_functions_sampler_with_gradients.h:28
static constexpr auto kernel_from_squared_y1_x2(fixed_size_real_vec< 2 > auto const &p1, fixed_size_real_vec< 2 > auto const &p2)
Definition: radial_basis_functions_sampler_with_gradients.h:74
static constexpr auto kernel_from_squared_x1_x2(fixed_size_real_vec< 2 > auto const &p1, fixed_size_real_vec< 2 > auto const &p2)
Definition: radial_basis_functions_sampler_with_gradients.h:63
Definition: inverse_distance_weighting_sampler.h:4
auto diff(radial_basis_functions_sampler_with_gradients< Real, NumDimensions, ValueType, GradientType > const &f)
Definition: radial_basis_functions_sampler_with_gradients.h:721
static constexpr sequential_t sequential
Definition: tags.h:63
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
auto solve_symmetric_lapack(TensorA &&A_, TensorB &&B_, lapack::uplo uplo=lapack::uplo::lower) -> std::optional< tensor< common_type< tatooine::value_type< decltype(A_)>, tatooine::value_type< decltype(B_)> > > >
Definition: solve.h:349
auto vertices(pointset< Real, NumDimensions > const &ps)
Definition: vertex_container.h:278
constexpr auto squared_euclidean_distance(base_tensor< Tensor0, T0, N > const &lhs, base_tensor< Tensor1, T1, N > const &rhs)
Definition: distance.h:11
auto coefficient(std::size_t const i, std::size_t const j) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:667
auto f(vertex_handle const v) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:676
auto f(std::size_t const i) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:677
auto coefficient(vertex_handle const v, std::size_t const j) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:663
auto evaluate(pos_type const &q, real_type const) const -> tensor_type
Definition: radial_basis_functions_sampler_with_gradients.h:679
typename pointset_type::vertex_handle vertex_handle
Definition: radial_basis_functions_sampler_with_gradients.h:654
differentiated_radial_basis_functions_sampler_with_gradients(base_type const &base)
Definition: radial_basis_functions_sampler_with_gradients.h:672
auto coefficient(std::size_t const i) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:597
auto base() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:591
differentiated_radial_basis_functions_sampler_with_gradients(base_type const &base)
Definition: radial_basis_functions_sampler_with_gradients.h:601
auto pointset() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:592
typename pointset_type::vertex_handle vertex_handle
Definition: radial_basis_functions_sampler_with_gradients.h:585
auto evaluate(pos_type const &q, real_type const) const -> tensor_type
Definition: radial_basis_functions_sampler_with_gradients.h:608
auto coefficient(vertex_handle const v) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:594
auto f(std::size_t const i) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:606
auto f() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:604
auto coefficients() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:593
auto f(vertex_handle const v) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:605
Definition: radial_basis_functions_sampler_with_gradients.h:566
auto df(std::size_t const i) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:365
auto f() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:360
typed_vertex_property_type< value_type > f_property_type
Definition: radial_basis_functions_sampler_with_gradients.h:340
auto df() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:363
typename pointset_type::vertex_handle vertex_handle
Definition: radial_basis_functions_sampler_with_gradients.h:336
auto df(vertex_handle const v) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:364
auto coefficient(std::size_t const i, std::size_t const j) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:356
auto pointset() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:350
f_property_type const & m_f
Definition: radial_basis_functions_sampler_with_gradients.h:345
typed_vertex_property_type< gradient_type > df_property_type
Definition: radial_basis_functions_sampler_with_gradients.h:341
auto coefficient(vertex_handle const v, std::size_t const j) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:352
auto f(vertex_handle const v) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:361
auto f(std::size_t const i) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:362
df_property_type const & m_df
Definition: radial_basis_functions_sampler_with_gradients.h:346
auto coefficients() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:351
auto evaluate(pos_type const &q, real_type const) const -> tensor_type
Definition: radial_basis_functions_sampler_with_gradients.h:526
pointset_type const & m_pointset
Definition: radial_basis_functions_sampler_with_gradients.h:344
radial_basis_functions_sampler_with_gradients(pointset_type const &ps, f_property_type const &f_, df_property_type const &df_, execution_policy::sequential_t)
Definition: radial_basis_functions_sampler_with_gradients.h:419
typename pointset_type::template typed_vertex_property_type< S > typed_vertex_property_type
Definition: radial_basis_functions_sampler_with_gradients.h:339
pointset_type const & m_pointset
Definition: radial_basis_functions_sampler_with_gradients.h:126
auto f() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:140
radial_basis_functions_sampler_with_gradients(radial_basis_functions_sampler_with_gradients &&) noexcept=default
auto pointset() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:132
auto f(vertex_handle const v) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:141
auto f(std::size_t const i) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:142
typed_vertex_property_type< value_type > f_property_type
Definition: radial_basis_functions_sampler_with_gradients.h:122
auto coefficients() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:133
auto coefficient(std::size_t const i) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:137
auto coefficient(vertex_handle const v) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:134
auto df() const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:143
typename pointset_type::template typed_vertex_property_type< S > typed_vertex_property_type
Definition: radial_basis_functions_sampler_with_gradients.h:121
df_property_type const & m_df
Definition: radial_basis_functions_sampler_with_gradients.h:128
typename pointset_type::vertex_handle vertex_handle
Definition: radial_basis_functions_sampler_with_gradients.h:118
f_property_type const & m_f
Definition: radial_basis_functions_sampler_with_gradients.h:127
auto df(std::size_t const i) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:145
typed_vertex_property_type< gradient_type > df_property_type
Definition: radial_basis_functions_sampler_with_gradients.h:123
radial_basis_functions_sampler_with_gradients(pointset_type const &ps, f_property_type const &f_, df_property_type const &df_, execution_policy::sequential_t)
Definition: radial_basis_functions_sampler_with_gradients.h:199
auto df(vertex_handle const v) const -> auto const &
Definition: radial_basis_functions_sampler_with_gradients.h:144
auto evaluate(pos_type const &q, real_type const) const -> tensor_type
Definition: radial_basis_functions_sampler_with_gradients.h:300
Definition: radial_basis_functions_sampler_with_gradients.h:100
Definition: field.h:134
Real real_type
Definition: field.h:17
Definition: mat.h:14
Definition: pointset.h:83
Definition: pointset.h:69
auto vertices() const
Definition: pointset.h:226
auto vertex_at(vertex_handle const v) -> auto &
Definition: pointset.h:205
static constexpr auto zeros()
Definition: tensor.h:144
Definition: property.h:66
Definition: vec.h:12