Tensorium
Loading...
Searching...
No Matches
BSSNDerivatives.hpp
Go to the documentation of this file.
1#pragma once
2
4#include "../Metric.hpp"
6namespace tensorium_RG {
7
8template <typename T>
10 using C = std::complex<T>;
11 using FFT = tensorium::SpectralFFT<T>;
12
13 tensorium::Vector<C> field_fft(field.size());
14 for (size_t i = 0; i < field.size(); ++i)
15 field_fft(i) = field(i);
16
17 FFT::forward(field_fft);
18
19 const T L = dx * field.size();
20 for (size_t k = 0; k < field.size(); ++k) {
21 int n = (k <= field.size() / 2) ? k : (int)k - (int)field.size();
22 C factor = C(0, 2.0 * M_PI * n / L);
23 field_fft(k) *= factor;
24 }
25
26 FFT::backward(field_fft);
27 for (size_t i = 0; i < field.size(); ++i)
28 dfield(i) = field_fft(i).real();
29}
30
31template <typename T>
32void spectral_partial_scalar_3D(const tensorium::Tensor<T, 3> &scalar_field, T dx, T dy, T dz,
33 tensorium::Tensor<T, 4> &grad_out) {
34 using namespace tensorium;
35 using C = std::complex<T>;
36 using FFT = SpectralFFT<T>;
37
38 const auto &shape = scalar_field.shape();
39 const size_t NX = shape[0], NY = shape[1], NZ = shape[2];
40
41 grad_out.resize({NX, NY, NZ, 3});
42
44 for (size_t i = 0; i < NX; ++i)
45 for (size_t j = 0; j < NY; ++j)
46 for (size_t k = 0; k < NZ; ++k)
47 field_cplx(i, j, k) = C(scalar_field(i, j, k), 0.0);
48
49 FFT::forward_3D(field_cplx);
50
51 for (size_t i = 0; i < NX; ++i) {
52 int ni = (i <= NX / 2) ? int(i) : int(i) - int(NX);
53 T kx = 2.0 * M_PI * ni / (NX * dx);
54
55 for (size_t j = 0; j < NY; ++j) {
56 int nj = (j <= NY / 2) ? int(j) : int(j) - int(NY);
57 T ky = 2.0 * M_PI * nj / (NY * dy);
58
59 for (size_t k = 0; k < NZ; ++k) {
60 int nk = (k <= NZ / 2) ? int(k) : int(k) - int(NZ);
61 T kz = 2.0 * M_PI * nk / (NZ * dz);
62
63 C f_hat = field_cplx(i, j, k);
64
65 field_cplx(i, j, k) = f_hat;
66
67 grad_out(i, j, k, 0) = (f_hat * C(0, kx)).real();
68 grad_out(i, j, k, 1) = (f_hat * C(0, ky)).real();
69 grad_out(i, j, k, 2) = (f_hat * C(0, kz)).real();
70 }
71 }
72 }
73
74 for (int dim = 0; dim < 3; ++dim) {
76
77 for (size_t i = 0; i < NX; ++i)
78 for (size_t j = 0; j < NY; ++j)
79 for (size_t k = 0; k < NZ; ++k)
80 dfield_cplx(i, j, k) = C(grad_out(i, j, k, dim), 0.0);
81
82 FFT::backward_3D(dfield_cplx);
83
84 for (size_t i = 0; i < NX; ++i)
85 for (size_t j = 0; j < NY; ++j)
86 for (size_t k = 0; k < NZ; ++k)
87 grad_out(i, j, k, dim) = dfield_cplx(i, j, k).real();
88 }
89}
90
91template <typename T, typename TensorFunc>
93 TensorFunc &&func, size_t NX, size_t NY,
94 size_t NZ) {
95 using namespace tensorium;
96 using C = std::complex<T>;
97 using FFT = SpectralFFT<T>;
98
100 Tensor<T, 3> grad_gamma({3, 3, 3});
101
102 for (size_t i = 0; i < 3; ++i) {
103 for (size_t j = 0; j < 3; ++j) {
105 tensorium_RG::populate_tensor3D_component<T>(i, j, func, dx, dy, dz, NX, NY, NZ);
106
109
110 for (size_t k = 0; k < 3; ++k)
111 grad_gamma(i, j, k) = grad_tmp(NX / 2, NY / 2, NZ / 2, k);
112 }
113 }
114
115 return grad_gamma;
116}
117
118template <typename T, typename ScalarFunc>
120 ScalarFunc &&func) {
122
123 {
125 T gm2, gm1, gp1, gp2;
126 Xs(1) = X(1) - 2 * dx;
127 gm2 = func(Xs);
128 Xs(1) = X(1) - dx;
129 gm1 = func(Xs);
130 Xs(1) = X(1) + dx;
131 gp1 = func(Xs);
132 Xs(1) = X(1) + 2 * dx;
133 gp2 = func(Xs);
134 grad(0) = (-gp2 + 8 * gp1 - 8 * gm1 + gm2) / (12 * dx);
135 }
136 // dérivée selon x²
137 {
139 T gm2, gm1, gp1, gp2;
140 Xs(2) = X(2) - 2 * dy;
141 gm2 = func(Xs);
142 Xs(2) = X(2) - dy;
143 gm1 = func(Xs);
144 Xs(2) = X(2) + dy;
145 gp1 = func(Xs);
146 Xs(2) = X(2) + 2 * dy;
147 gp2 = func(Xs);
148 grad(1) = (-gp2 + 8 * gp1 - 8 * gm1 + gm2) / (12 * dy);
149 }
150 // dérivée selon x³
151 {
153 T gm2, gm1, gp1, gp2;
154 Xs(3) = X(3) - 2 * dz;
155 gm2 = func(Xs);
156 Xs(3) = X(3) - dz;
157 gm1 = func(Xs);
158 Xs(3) = X(3) + dz;
159 gp1 = func(Xs);
160 Xs(3) = X(3) + 2 * dz;
161 gp2 = func(Xs);
162 grad(2) = (-gp2 + 8 * gp1 - 8 * gm1 + gm2) / (12 * dz);
163 }
164
165 return grad;
166}
167
168template <typename T, typename VectorFunc>
170 VectorFunc &&func) {
171 tensorium::Tensor<T, 2> result({3, 3});
172 // dérivée ∂/∂x
173 {
175 tensorium::Vector<T> Vm2(3), Vm1(3), Vp1(3), Vp2(3);
176 Xs(1) = X(1) - 2 * dx;
177 Vm2 = func(Xs);
178 Xs(1) = X(1) - dx;
179 Vm1 = func(Xs);
180 Xs(1) = X(1) + dx;
181 Vp1 = func(Xs);
182 Xs(1) = X(1) + 2 * dx;
183 Vp2 = func(Xs);
184 for (int i = 0; i < 3; ++i)
185 result(i, 0) = (-Vp2(i) + 8 * Vp1(i) - 8 * Vm1(i) + Vm2(i)) / (12 * dx);
186 }
187 // dérivée ∂/∂y
188 {
190 tensorium::Vector<T> Vm2(3), Vm1(3), Vp1(3), Vp2(3);
191 Xs(2) = X(2) - 2 * dy;
192 Vm2 = func(Xs);
193 Xs(2) = X(2) - dy;
194 Vm1 = func(Xs);
195 Xs(2) = X(2) + dy;
196 Vp1 = func(Xs);
197 Xs(2) = X(2) + 2 * dy;
198 Vp2 = func(Xs);
199 for (int i = 0; i < 3; ++i)
200 result(i, 1) = (-Vp2(i) + 8 * Vp1(i) - 8 * Vm1(i) + Vm2(i)) / (12 * dy);
201 }
202 // dérivée ∂/∂z
203 {
205 tensorium::Vector<T> Vm2(3), Vm1(3), Vp1(3), Vp2(3);
206 Xs(3) = X(3) - 2 * dz;
207 Vm2 = func(Xs);
208 Xs(3) = X(3) - dz;
209 Vm1 = func(Xs);
210 Xs(3) = X(3) + dz;
211 Vp1 = func(Xs);
212 Xs(3) = X(3) + 2 * dz;
213 Vp2 = func(Xs);
214 for (int i = 0; i < 3; ++i)
215 result(i, 2) = (-Vp2(i) + 8 * Vp1(i) - 8 * Vm1(i) + Vm2(i)) / (12 * dz);
216 }
217 return result;
218}
219
220template <typename T, typename TensorFunc>
223 out.resize(3, 3, 3);
224
225 auto shifted = [&](T dx_, T dy_, T dz_) {
227 Xs(0) += dx_;
228 Xs(1) += dy_;
229 Xs(2) += dz_;
232 return out_tensor;
233 };
234
235 for (size_t a = 0; a < 3; ++a) {
236 for (size_t b = 0; b < 3; ++b) {
237 // ∂₀ = ∂/∂x
238 auto gm2 = shifted(-2 * dx, 0, 0);
239 auto gm1 = shifted(-dx, 0, 0);
240 auto gp1 = shifted(dx, 0, 0);
241 auto gp2 = shifted(2 * dx, 0, 0);
242 out(0, a, b) = (-gp2(a, b) + 8 * gp1(a, b) - 8 * gm1(a, b) + gm2(a, b)) / (12 * dx);
243
244 // ∂₁ = ∂/∂y
245 gm2 = shifted(0, -2 * dy, 0);
246 gm1 = shifted(0, -dy, 0);
247 gp1 = shifted(0, dy, 0);
248 gp2 = shifted(0, 2 * dy, 0);
249 out(1, a, b) = (-gp2(a, b) + 8 * gp1(a, b) - 8 * gm1(a, b) + gm2(a, b)) / (12 * dy);
250
251 // ∂₂ = ∂/∂z
252 gm2 = shifted(0, 0, -2 * dz);
253 gm1 = shifted(0, 0, -dz);
254 gp1 = shifted(0, 0, dz);
255 gp2 = shifted(0, 0, 2 * dz);
256 out(2, a, b) = (-gp2(a, b) + 8 * gp1(a, b) - 8 * gm1(a, b) + gm2(a, b)) / (12 * dz);
257 }
258 }
259}
260
261template <typename T, typename TensorFunc>
264 out = tensorium::Tensor<T, 4>({3, 3, 3, 3});
265
266 auto shifted = [&](T dx_, T dy_, T dz_) {
268 Xs(0) += dx_;
269 Xs(1) += dy_;
270 Xs(2) += dz_;
273 return out_tensor;
274 };
275
276 for (size_t a = 0; a < 3; ++a) {
277 for (size_t b = 0; b < 3; ++b) {
278 // ∂²/∂x²
279 auto gm2 = shifted(-2 * dx, 0, 0);
280 auto gm1 = shifted(-dx, 0, 0);
281 auto g0 = shifted(0, 0, 0);
282 auto gp1 = shifted(dx, 0, 0);
283 auto gp2 = shifted(2 * dx, 0, 0);
284 out(0, a, b, 0) =
285 (-gp2(a, b) + 16 * gp1(a, b) - 30 * g0(a, b) + 16 * gm1(a, b) - gm2(a, b)) /
286 (12 * dx * dx);
287
288 // ∂²/∂y²
289 gm2 = shifted(0, -2 * dy, 0);
290 gm1 = shifted(0, -dy, 0);
291 g0 = shifted(0, 0, 0);
292 gp1 = shifted(0, dy, 0);
293 gp2 = shifted(0, 2 * dy, 0);
294 out(1, a, b, 1) =
295 (-gp2(a, b) + 16 * gp1(a, b) - 30 * g0(a, b) + 16 * gm1(a, b) - gm2(a, b)) /
296 (12 * dy * dy);
297
298 // ∂²/∂z²
299 gm2 = shifted(0, 0, -2 * dz);
300 gm1 = shifted(0, 0, -dz);
301 g0 = shifted(0, 0, 0);
302 gp1 = shifted(0, 0, dz);
303 gp2 = shifted(0, 0, 2 * dz);
304 out(2, a, b, 2) =
305 (-gp2(a, b) + 16 * gp1(a, b) - 30 * g0(a, b) + 16 * gm1(a, b) - gm2(a, b)) /
306 (12 * dz * dz);
307 }
308 }
309}
310
311template <typename T, typename VectorFunc>
314 out.resize(3, 3);
315
316 auto shifted = [&](T dx_, T dy_, T dz_) {
318 Xs(0) += dx_;
319 Xs(1) += dy_;
320 Xs(2) += dz_;
322 func(Xs, Vout);
323 return Vout;
324 };
325
326 for (size_t i = 0; i < 3; ++i) {
327 auto gm2 = shifted(-2 * dx, 0, 0);
328 auto gm1 = shifted(-dx, 0, 0);
329 auto gp1 = shifted(dx, 0, 0);
330 auto gp2 = shifted(2 * dx, 0, 0);
331 out(0, i) = (-gp2(i) + 8 * gp1(i) - 8 * gm1(i) + gm2(i)) / (12 * dx);
332
333 gm2 = shifted(0, -2 * dy, 0);
334 gm1 = shifted(0, -dy, 0);
335 gp1 = shifted(0, dy, 0);
336 gp2 = shifted(0, 2 * dy, 0);
337 out(1, i) = (-gp2(i) + 8 * gp1(i) - 8 * gm1(i) + gm2(i)) / (12 * dy);
338
339 gm2 = shifted(0, 0, -2 * dz);
340 gm1 = shifted(0, 0, -dz);
341 gp1 = shifted(0, 0, dz);
342 gp2 = shifted(0, 0, 2 * dz);
343 out(2, i) = (-gp2(i) + 8 * gp1(i) - 8 * gm1(i) + gm2(i)) / (12 * dz);
344 }
345}
346
347template <typename T, typename ScalarFunc>
350
351 out.resize(3);
352
353 auto shifted = [&](T dx_, T dy_, T dz_) {
355 Xs(0) += dx_;
356 Xs(1) += dy_;
357 Xs(2) += dz_;
358 return func(Xs);
359 };
360
361 // ∂/∂x
362 T gm2 = shifted(-2 * dx, 0, 0);
363 T gm1 = shifted(-dx, 0, 0);
364 T gp1 = shifted(dx, 0, 0);
365 T gp2 = shifted(2 * dx, 0, 0);
366 out[0] = (-gp2 + 8 * gp1 - 8 * gm1 + gm2) / (12 * dx);
367
368 // ∂/∂y
369 gm2 = shifted(0, -2 * dy, 0);
370 gm1 = shifted(0, -dy, 0);
371 gp1 = shifted(0, dy, 0);
372 gp2 = shifted(0, 2 * dy, 0);
373 out[1] = (-gp2 + 8 * gp1 - 8 * gm1 + gm2) / (12 * dy);
374
375 // ∂/∂z
376 gm2 = shifted(0, 0, -2 * dz);
377 gm1 = shifted(0, 0, -dz);
378 gp1 = shifted(0, 0, dz);
379 gp2 = shifted(0, 0, 2 * dz);
380 out[2] = (-gp2 + 8 * gp1 - 8 * gm1 + gm2) / (12 * dz);
381}
382
383template <typename T>
388
390 for (size_t i = 0; i < 3; ++i)
391 for (size_t j = 0; j < 3; ++j) {
392 T val = partial_beta(i, j) + partial_beta(j, i);
393 for (size_t k = 0; k < 3; ++k)
394 val -= 2.0 * christoffel(i, j, k) * beta(k);
395 dtg(i, j) = val;
396 }
397 return dtg;
398}
399
400template <typename T>
402 size_t j, size_t k, T dx, T dy, T dz,
404 dvec_out.resize(3, 3);
405
406 auto get = [&](int ii, int jj, int kk, int a) -> T { return vec_field(ii, jj, kk, a); };
407
408 const auto &shape = vec_field.shape();
409 const size_t NX = shape[0], NY = shape[1], NZ = shape[2];
410
411 for (size_t a = 0; a < 3; ++a) {
412 if (i >= 2 && i + 2 < NX)
413 dvec_out(0, a) = (-get(i + 2, j, k, a) + 8 * get(i + 1, j, k, a) -
414 8 * get(i - 1, j, k, a) + get(i - 2, j, k, a)) /
415 (12 * dx);
416 else if (i > 0 && i + 1 < NX)
417 dvec_out(0, a) = (get(i + 1, j, k, a) - get(i - 1, j, k, a)) / (2 * dx);
418 else
419 dvec_out(0, a) = T(0);
420
421 if (j >= 2 && j + 2 < NY)
422 dvec_out(1, a) = (-get(i, j + 2, k, a) + 8 * get(i, j + 1, k, a) -
423 8 * get(i, j - 1, k, a) + get(i, j - 2, k, a)) /
424 (12 * dy);
425 else if (j > 0 && j + 1 < NY)
426 dvec_out(1, a) = (get(i, j + 1, k, a) - get(i, j - 1, k, a)) / (2 * dy);
427 else
428 dvec_out(1, a) = T(0);
429
430 if (k >= 2 && k + 2 < NZ)
431 dvec_out(2, a) = (-get(i, j, k + 2, a) + 8 * get(i, j, k + 1, a) -
432 8 * get(i, j, k - 1, a) + get(i, j, k - 2, a)) /
433 (12 * dz);
434 else if (k > 0 && k + 1 < NZ)
435 dvec_out(2, a) = (get(i, j, k + 1, a) - get(i, j, k - 1, a)) / (2 * dz);
436 else
437 dvec_out(2, a) = T(0);
438 }
439}
440
441template <typename T, typename ScalarFunc>
444 out.resize(3, 3);
445
446 auto shifted = [&](T dx_, T dy_, T dz_) {
448 Xs(0) += dx_;
449 Xs(1) += dy_;
450 Xs(2) += dz_;
451 return func(Xs);
452 };
453
454 // ∂²/∂x²
455 {
456 T gm2 = shifted(-2 * dx, 0, 0);
457 T gm1 = shifted(-dx, 0, 0);
458 T g0 = shifted(0, 0, 0);
459 T gp1 = shifted(dx, 0, 0);
460 T gp2 = shifted(2 * dx, 0, 0);
461 out(0, 0) = (-gp2 + 16 * gp1 - 30 * g0 + 16 * gm1 - gm2) / (12 * dx * dx);
462 }
463
464 // ∂²/∂y²
465 {
466 T gm2 = shifted(0, -2 * dy, 0);
467 T gm1 = shifted(0, -dy, 0);
468 T g0 = shifted(0, 0, 0);
469 T gp1 = shifted(0, dy, 0);
470 T gp2 = shifted(0, 2 * dy, 0);
471 out(1, 1) = (-gp2 + 16 * gp1 - 30 * g0 + 16 * gm1 - gm2) / (12 * dy * dy);
472 }
473
474 // ∂²/∂z²
475 {
476 T gm2 = shifted(0, 0, -2 * dz);
477 T gm1 = shifted(0, 0, -dz);
478 T g0 = shifted(0, 0, 0);
479 T gp1 = shifted(0, 0, dz);
480 T gp2 = shifted(0, 0, 2 * dz);
481 out(2, 2) = (-gp2 + 16 * gp1 - 30 * g0 + 16 * gm1 - gm2) / (12 * dz * dz);
482 }
483
484 // ∂²/∂x∂y
485 {
486 T pp = shifted(dx, dy, 0);
487 T pm = shifted(dx, -dy, 0);
488 T mp = shifted(-dx, dy, 0);
489 T mm = shifted(-dx, -dy, 0);
490 out(0, 1) = out(1, 0) = (pp - pm - mp + mm) / (4 * dx * dy);
491 }
492
493 // ∂²/∂x∂z
494 {
495 T pp = shifted(dx, 0, dz);
496 T pm = shifted(dx, 0, -dz);
497 T mp = shifted(-dx, 0, dz);
498 T mm = shifted(-dx, 0, -dz);
499 out(0, 2) = out(2, 0) = (pp - pm - mp + mm) / (4 * dx * dz);
500 }
501
502 // ∂²/∂y∂z
503 {
504 T pp = shifted(0, dy, dz);
505 T pm = shifted(0, dy, -dz);
506 T mp = shifted(0, -dy, dz);
507 T mm = shifted(0, -dy, -dz);
508 out(1, 2) = out(2, 1) = (pp - pm - mp + mm) / (4 * dy * dz);
509 }
510}
511
512template <typename T, typename ScalarFunc>
516 using namespace tensorium;
517
518 Vector<T> grad(3);
520
521 Tensor<T, 2> hess({3, 3});
522 compute_second_derivatives_scalar(X, dx, dy, dz, std::forward<ScalarFunc>(func), hess);
523
524 Tensor<T, 2> result({3, 3});
525 for (int i = 0; i < 3; ++i)
526 for (int j = 0; j < 3; ++j) {
527 result(i, j) = hess(i, j);
528 for (int k = 0; k < 3; ++k)
529 result(i, j) -=
530 christoffel(k, i, j) * grad(k); // D_i D_j φ = ∂_i ∂_j φ - Γ^k_{ij} ∂_k φ
531 }
532 return result;
533}
534
535template <typename T>
538 const auto &shape = scalar_field.shape();
539 const size_t NX = shape[0], NY = shape[1], NZ = shape[2];
540
541 hessian_out.resize(NX, NY, NZ, 3, 3);
542
543 auto get = [&](int i, int j, int k) -> T {
544 if (i < 0)
545 i = 0;
546 if (j < 0)
547 j = 0;
548 if (k < 0)
549 k = 0;
550 if (i >= NX)
551 i = NX - 1;
552 if (j >= NY)
553 j = NY - 1;
554 if (k >= NZ)
555 k = NZ - 1;
556 return scalar_field(i, j, k);
557 };
558
559 for (size_t i = 0; i < NX; ++i) {
560 for (size_t j = 0; j < NY; ++j) {
561 for (size_t k = 0; k < NZ; ++k) {
562
563 auto d2f_xx = (-get(i + 2, j, k) + 16 * get(i + 1, j, k) - 30 * get(i, j, k) +
564 16 * get(i - 1, j, k) - get(i - 2, j, k)) /
565 (12 * dx * dx);
566 auto d2f_yy = (-get(i, j + 2, k) + 16 * get(i, j + 1, k) - 30 * get(i, j, k) +
567 16 * get(i, j - 1, k) - get(i, j - 2, k)) /
568 (12 * dy * dy);
569 auto d2f_zz = (-get(i, j, k + 2) + 16 * get(i, j, k + 1) - 30 * get(i, j, k) +
570 16 * get(i, j, k - 1) - get(i, j, k - 2)) /
571 (12 * dz * dz);
572
573 auto d2f_xy = (get(i + 1, j + 1, k) - get(i + 1, j - 1, k) - get(i - 1, j + 1, k) +
574 get(i - 1, j - 1, k)) /
575 (4 * dx * dy);
576 auto d2f_xz = (get(i + 1, j, k + 1) - get(i + 1, j, k - 1) - get(i - 1, j, k + 1) +
577 get(i - 1, j, k - 1)) /
578 (4 * dx * dz);
579 auto d2f_yz = (get(i, j + 1, k + 1) - get(i, j + 1, k - 1) - get(i, j - 1, k + 1) +
580 get(i, j - 1, k - 1)) /
581 (4 * dy * dz);
582
583 hessian_out(i, j, k, 0, 0) = d2f_xx;
584 hessian_out(i, j, k, 1, 1) = d2f_yy;
585 hessian_out(i, j, k, 2, 2) = d2f_zz;
586
587 hessian_out(i, j, k, 0, 1) = hessian_out(i, j, k, 1, 0) = d2f_xy;
588 hessian_out(i, j, k, 0, 2) = hessian_out(i, j, k, 2, 0) = d2f_xz;
589 hessian_out(i, j, k, 1, 2) = hessian_out(i, j, k, 2, 1) = d2f_yz;
590 }
591 }
592 }
593}
594
595template <typename T>
598 T dy, T dz) {
599 const auto &shape = chi.shape();
600 const size_t NX = shape[0], NY = shape[1], NZ = shape[2];
601
602 tensorium::Tensor<T, 5> result({NX, NY, NZ, 3, 3});
603
606
607 for (size_t i = 0; i < NX; ++i)
608 for (size_t j = 0; j < NY; ++j)
609 for (size_t k = 0; k < NZ; ++k) {
610 auto func = [&](const tensorium::Vector<T> &X) -> T { return chi(i, j, k); };
611
612 compute_partial_derivatives_scalar({T(i), T(j), T(k)}, dx, dy, dz, func, grad);
613 compute_second_derivatives_scalar({T(i), T(j), T(k)}, dx, dy, dz, func, hess);
614
615 for (int a = 0; a < 3; ++a)
616 for (int b = 0; b < 3; ++b) {
617 T val = hess(a, b);
618 for (int c = 0; c < 3; ++c)
619 val -= christoffel(i, j, k, c, a, b) * grad(c);
620 result(i, j, k, a, b) = val;
621 }
622 }
623
624 return result;
625}
626
627template <typename T, typename VectorFunc>
630 auto dVi = partial_vector(X, dx, dy, dz, std::forward<VectorFunc>(func));
631
632 tensorium::Tensor<T, 2> result({3, 3});
633
634 for (int i = 0; i < 3; ++i)
635 for (int j = 0; j < 3; ++j) {
636 result(i, j) = dVi(i, j);
637 for (int k = 0; k < 3; ++k)
638 result(i, j) += Gamma(i, j, k) * func(X)(k);
639 }
640
641 return result;
642}
643
644template <typename T, typename TensorFunc>
647 auto dTij = partial_tensor2(X, dx, dy, dz, std::forward<TensorFunc>(func));
649 tensorium::Tensor<T, 3> result({3, 3, 3});
650
651 for (int i = 0; i < 3; ++i)
652 for (int j = 0; j < 3; ++j)
653 for (int k = 0; k < 3; ++k) {
654 result(i, j, k) = dTij(i, j, k);
655 for (int l = 0; l < 3; ++l)
656 result(i, j, k) += -Gamma(l, k, i) * Tij(l, j) - Gamma(l, k, j) * Tij(i, l);
657 }
658
659 return result;
660}
661
662template <typename T, typename TensorFunc>
664 TensorFunc &&func) {
665 tensorium::Tensor<T, 3> result({3, 3, 3});
666
667 for (int k = 0; k < 3; ++k) {
668 tensorium::Vector<T> dx_vec = {0, 0, 0};
669 dx_vec(k) = (k == 0) ? dx : (k == 1 ? dy : dz);
670
673
674 for (int i = 0; i < 3; ++i)
675 for (int j = 0; j < 3; ++j)
676 result(i, j, k) = (fp(i, j) - fm(i, j)) / (2 * dx_vec(k));
677 }
678
679 return result;
680}
681
682template <typename T, typename TensorFunc>
686 auto cov1 = [&](const tensorium::Vector<T> &Y) {
687 return covariant_tensor2<T>(Y, dx, dy, dz, func, Gamma);
688 };
689
690 tensorium::Tensor<T, 4> result({3, 3, 3, 3}); // ∇_i ∇_j T_{kl}
691 for (int i = 0; i < 3; ++i)
692 for (int j = 0; j < 3; ++j)
693 for (int k = 0; k < 3; ++k)
694 for (int l = 0; l < 3; ++l) {
695 // très simpliste, pas d'optimisation pour la structure de symétrie
696 T cov_minus = cov1(X - tensorium::Vector<T>::canonical(j, dx, dy, dz))(k, l, i);
697 T cov_plus = cov1(X + tensorium::Vector<T>::canonical(j, dx, dy, dz))(k, l, i);
698 T cov0 = cov1(X)(k, l, i);
699 T h = (j == 0) ? dx : (j == 1 ? dy : dz);
700 result(i, j, k, l) = (cov_plus - cov_minus) / (2 * h); // ∂_j (∇_i T_kl)
701 }
702
703 return result;
704}
705
706} // namespace tensorium_RG
static FrontendPluginRegistry::Add< TensoriumPluginAction > X("tensorium-dispatch", "Handle #pragma tensorium directives")
Register the plugin under the name "tensorium-dispatch".
Multi-dimensional tensor class with fixed rank and SIMD support.
Definition Tensor.hpp:25
void resize(const std::array< size_t, Rank > &dims)
Resize 2D tensor.
Definition Tensor.hpp:70
std::array< size_t, Rank > shape() const
Definition Tensor.hpp:62
Aligned, SIMD-optimized mathematical vector class for scientific computing.
Definition Vector.hpp:26
Definition BSSNAtildeTensor.hpp:10
tensorium::Tensor< T, 2 > compute_dt_gamma_from_beta(const tensorium::Tensor< T, 2 > &gamma, const tensorium::Vector< T > &beta, const tensorium::Tensor< T, 2 > &partial_beta, const tensorium::Tensor< T, 3 > &christoffel)
Definition BSSNDerivatives.hpp:384
tensorium::Tensor< T, 3 > spectral_partial_tensor2(const tensorium::Vector< T > &X, T dx, T dy, T dz, TensorFunc &&func, size_t NX, size_t NY, size_t NZ)
Definition BSSNDerivatives.hpp:92
void compute_second_derivatives_scalar3D(const tensorium::Tensor< T, 3 > &scalar_field, T dx, T dy, T dz, tensorium::Tensor< T, 5 > &hessian_out)
Definition BSSNDerivatives.hpp:536
tensorium::Tensor< T, 2 > partial_vector(const tensorium::Vector< T > &X, T dx, T dy, T dz, VectorFunc &&func)
Definition BSSNDerivatives.hpp:169
tensorium::Tensor< T, 2 > covariant_vector(const tensorium::Vector< T > &X, T dx, T dy, T dz, VectorFunc &&func, const tensorium::Tensor< T, 3 > &Gamma)
Definition BSSNDerivatives.hpp:628
void spectral_partial_scalar_3D(const tensorium::Tensor< T, 3 > &scalar_field, T dx, T dy, T dz, tensorium::Tensor< T, 4 > &grad_out)
Definition BSSNDerivatives.hpp:32
tensorium::Tensor< T, 2 > covariant_scalar_second(const tensorium::Vector< T > &X, T dx, T dy, T dz, ScalarFunc &&func, const tensorium::Tensor< T, 3 > &christoffel)
Definition BSSNDerivatives.hpp:513
void compute_partial_derivatives_vector(const tensorium::Vector< T > &X, T dx, T dy, T dz, VectorFunc &&func, tensorium::Tensor< T, 2 > &out)
Definition BSSNDerivatives.hpp:312
tensorium::Tensor< T, 3 > partial_tensor2(const tensorium::Vector< T > &X, T dx, T dy, T dz, TensorFunc &&func)
Definition BSSNDerivatives.hpp:663
tensorium::Vector< T > partial_scalar(const tensorium::Vector< T > &X, T dx, T dy, T dz, ScalarFunc &&func)
Definition BSSNDerivatives.hpp:119
void spectral_derivative_1D(tensorium::Vector< T > &field, tensorium::Vector< T > &dfield, T dx)
Definition BSSNDerivatives.hpp:9
void compute_partial_derivatives_vector3D(const tensorium::Tensor< T, 4 > &vec_field, size_t i, size_t j, size_t k, T dx, T dy, T dz, tensorium::Tensor< T, 2 > &dvec_out)
Definition BSSNDerivatives.hpp:401
tensorium::Tensor< T, 3 > covariant_tensor2(const tensorium::Vector< T > &X, T dx, T dy, T dz, TensorFunc &&func, const tensorium::Tensor< T, 3 > &Gamma)
Definition BSSNDerivatives.hpp:645
tensorium::Tensor< T, 5 > covariant_scalar_second_3D(const tensorium::Tensor< T, 3 > &chi, const tensorium::Tensor< T, 5 > &christoffel, T dx, T dy, T dz)
Definition BSSNDerivatives.hpp:596
tensorium::Tensor< T, 4 > covariant_tensor2_second(const tensorium::Vector< T > &X, T dx, T dy, T dz, TensorFunc &&func, const tensorium::Tensor< T, 3 > &Gamma)
Definition BSSNDerivatives.hpp:683
void compute_partial_derivatives_scalar(const tensorium::Vector< T > &X, T dx, T dy, T dz, ScalarFunc &&func, tensorium::Vector< T > &out)
Definition BSSNDerivatives.hpp:348
void compute_partial_derivatives_tensor2D(const tensorium::Vector< T > &X, T dx, T dy, T dz, TensorFunc &&func, tensorium::Tensor< T, 3 > &out)
Definition BSSNDerivatives.hpp:221
void compute_second_derivatives_tensor2D(const tensorium::Vector< T > &X, T dx, T dy, T dz, TensorFunc &&func, tensorium::Tensor< T, 4 > &out)
Definition BSSNDerivatives.hpp:262
void compute_second_derivatives_scalar(const tensorium::Vector< T > &X, T dx, T dy, T dz, ScalarFunc &&func, tensorium::Tensor< T, 2 > &out)
Definition BSSNDerivatives.hpp:442
Definition Derivate.hpp:24