@@ -48,6 +48,53 @@ namespace tensorium_RG {
4848 }
4949 }
5050
51+ template <typename T, typename TensorFunc>
52+ void compute_second_derivatives_tensor2D (
53+ const tensorium::Vector<T>& X,
54+ T dx, T dy, T dz,
55+ TensorFunc&& func,
56+ tensorium::Tensor<T, 4 >& out
57+ ) {
58+ out = tensorium::Tensor<T, 4 >({3 , 3 , 3 , 3 });
59+
60+ auto shifted = [&](T dx_, T dy_, T dz_) {
61+ tensorium::Vector<T> Xs = X;
62+ Xs (0 ) += dx_; Xs (1 ) += dy_; Xs (2 ) += dz_;
63+ tensorium::Tensor<T, 2 > out_tensor ({3 , 3 });
64+ func (Xs, out_tensor);
65+ return out_tensor;
66+ };
67+
68+ for (size_t a = 0 ; a < 3 ; ++a) {
69+ for (size_t b = 0 ; b < 3 ; ++b) {
70+ // ∂²/∂x²
71+ auto gm2 = shifted (-2 * dx, 0 , 0 );
72+ auto gm1 = shifted (-dx, 0 , 0 );
73+ auto g0 = shifted (0 , 0 , 0 );
74+ auto gp1 = shifted (dx, 0 , 0 );
75+ auto gp2 = shifted (2 * dx, 0 , 0 );
76+ out (0 , a, b, 0 ) = (-gp2 (a,b) + 16 *gp1 (a,b) - 30 *g0 (a,b) + 16 *gm1 (a,b) - gm2 (a,b)) / (12 * dx * dx);
77+
78+ // ∂²/∂y²
79+ gm2 = shifted (0 , -2 * dy, 0 );
80+ gm1 = shifted (0 , -dy, 0 );
81+ g0 = shifted (0 , 0 , 0 );
82+ gp1 = shifted (0 , dy, 0 );
83+ gp2 = shifted (0 , 2 * dy, 0 );
84+ out (1 , a, b, 1 ) = (-gp2 (a,b) + 16 *gp1 (a,b) - 30 *g0 (a,b) + 16 *gm1 (a,b) - gm2 (a,b)) / (12 * dy * dy);
85+
86+ // ∂²/∂z²
87+ gm2 = shifted (0 , 0 , -2 * dz);
88+ gm1 = shifted (0 , 0 , -dz);
89+ g0 = shifted (0 , 0 , 0 );
90+ gp1 = shifted (0 , 0 , dz);
91+ gp2 = shifted (0 , 0 , 2 * dz);
92+ out (2 , a, b, 2 ) = (-gp2 (a,b) + 16 *gp1 (a,b) - 30 *g0 (a,b) + 16 *gm1 (a,b) - gm2 (a,b)) / (12 * dz * dz);
93+ }
94+ }
95+ }
96+
97+
5198 template <typename T, typename VectorFunc>
5299 void compute_partial_derivatives_vector (
53100 const tensorium::Vector<T>& X,
@@ -140,5 +187,46 @@ namespace tensorium_RG {
140187 }
141188 return dtg;
142189 }
190+
191+ template <typename T>
192+ inline void compute_partial_derivatives_vector3D (
193+ const tensorium::Tensor<T, 4 >& vec_field,
194+ size_t i, size_t j, size_t k,
195+ T dx, T dy, T dz,
196+ tensorium::Tensor<T, 2 >& dvec_out
197+ ) {
198+ dvec_out.resize (3 , 3 );
199+
200+ auto get = [&](int ii, int jj, int kk, int a) -> T {
201+ return vec_field (ii, jj, kk, a);
202+ };
203+
204+ const auto & shape = vec_field.shape ();
205+ const size_t NX = shape[0 ], NY = shape[1 ], NZ = shape[2 ];
206+
207+ for (size_t a = 0 ; a < 3 ; ++a) {
208+ if (i >= 2 && i + 2 < NX)
209+ dvec_out (0 , a) = (-get (i+2 ,j,k,a) + 8 *get (i+1 ,j,k,a) - 8 *get (i-1 ,j,k,a) + get (i-2 ,j,k,a)) / (12 * dx);
210+ else if (i > 0 && i + 1 < NX)
211+ dvec_out (0 , a) = (get (i+1 ,j,k,a) - get (i-1 ,j,k,a)) / (2 * dx);
212+ else
213+ dvec_out (0 , a) = T (0 );
214+
215+ if (j >= 2 && j + 2 < NY)
216+ dvec_out (1 , a) = (-get (i,j+2 ,k,a) + 8 *get (i,j+1 ,k,a) - 8 *get (i,j-1 ,k,a) + get (i,j-2 ,k,a)) / (12 * dy);
217+ else if (j > 0 && j + 1 < NY)
218+ dvec_out (1 , a) = (get (i,j+1 ,k,a) - get (i,j-1 ,k,a)) / (2 * dy);
219+ else
220+ dvec_out (1 , a) = T (0 );
221+
222+ if (k >= 2 && k + 2 < NZ)
223+ dvec_out (2 , a) = (-get (i,j,k+2 ,a) + 8 *get (i,j,k+1 ,a) - 8 *get (i,j,k-1 ,a) + get (i,j,k-2 ,a)) / (12 * dz);
224+ else if (k > 0 && k + 1 < NZ)
225+ dvec_out (2 , a) = (get (i,j,k+1 ,a) - get (i,j,k-1 ,a)) / (2 * dz);
226+ else
227+ dvec_out (2 , a) = T (0 );
228+ }
229+ }
230+
143231}
144232
0 commit comments