Skip to content

Commit 8e535d6

Browse files
committed
BSSN setup ready (need the constraints solver)
1 parent e8d42a1 commit 8e535d6

File tree

6 files changed

+242
-48
lines changed

6 files changed

+242
-48
lines changed

Tests/Matrix/Matrix.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ int matrix_tests() {
303303

304304
std::cout << "X = " << X(0) << " " << X(1) << " " << X(2) << " " << X(3) << "\n";
305305

306-
tensorium_RG::Metric<double> metric("kerr_schild", 1.0, 0.0);
306+
tensorium_RG::Metric<double> metric("kerr_schild", 1.0, 0.9);
307307
metric(X, g);
308308

309309
std::cout << "Metric tensor g at X = (t=0, r=10, θ=π/2, φ=0):\n";
@@ -313,7 +313,7 @@ int matrix_tests() {
313313
std::cout << "Christoffel symbols Γ^λ_{μν} at X = (t=0, r=10, θ=π/2, φ=0):\n";
314314
auto gamma = tensorium::compute_christoffel(X, 1e-5, g, g_inv, metric);
315315
gamma.print();
316-
auto R = tensorium::compute_riemann_tensor<double>(X, 1e-5, tensorium_RG::Metric<double>("kerr_schild", 1.0, 0.8));
316+
auto R = tensorium::compute_riemann_tensor<double>(X, 1e-5, tensorium_RG::Metric<double>("kerr_schild", 1.0, 0.9));
317317
tensorium::print_riemann_tensor(R);
318318
tensorium::contract_tensor<0, 1>(R);
319319
std::cout << "Riemann tensor contracted:\n";
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#pragma once
2+
3+
#include "../../Core/Tensor.hpp"
4+
#include "../../Core/Vector.hpp"
5+
#include "../Metric.hpp"
6+
#include <cassert>
7+
#include <cstddef>
8+
9+
namespace tensorium_RG {
10+
template<typename T>
11+
class ConstraintSolver {
12+
public:
13+
/**
14+
* @brief Solve the Lichnerowicz equation to enforce the Hamiltonian constraint in BSSN.
15+
*
16+
* @param Atilde The trace-free conformal extrinsic curvature tensor Ã_{ij} at each grid point.
17+
* Shape: [NX][NY][NZ][3][3]
18+
* @param g_tilde_inv The inverse conformal metric γ̃^{ij} at each grid point.
19+
* Shape: [NX][NY][NZ][3][3]
20+
* @param dx, dy, dz Grid spacings
21+
* @param max_iter Maximum number of iterations
22+
* @param tol Convergence threshold
23+
* @return psi The conformal factor ψ at each grid point. Shape: [NX][NY][NZ]
24+
*/
25+
static tensorium::Tensor<T, 3> solveLichnerowicz(
26+
const tensorium::Tensor<T, 5>& Atilde,
27+
const tensorium::Tensor<T, 5>& g_tilde_inv,
28+
T dx, T dy, T dz,
29+
int max_iter = 1000,
30+
T tol = 1e-8) {
31+
32+
const size_t NX = Atilde.shape()[0];
33+
const size_t NY = Atilde.shape()[1];
34+
const size_t NZ = Atilde.shape()[2];
35+
36+
tensorium::Tensor<T, 3> psi({NX, NY, NZ});
37+
std::fill(psi.begin(), psi.end(), T(1));;
38+
39+
const T inv_dx2 = T(1) / (dx * dx);
40+
const T inv_dy2 = T(1) / (dy * dy);
41+
const T inv_dz2 = T(1) / (dz * dz);
42+
const T factor = T(1) / (2 * (inv_dx2 + inv_dy2 + inv_dz2));
43+
44+
for (int it = 0; it < max_iter; ++it) {
45+
T max_diff = T(0);
46+
47+
#pragma omp parallel for collapse(3) reduction(max:max_diff)
48+
for (size_t i = 1; i < NX - 1; ++i) {
49+
for (size_t j = 1; j < NY - 1; ++j) {
50+
for (size_t k = 1; k < NZ - 1; ++k) {
51+
52+
T lap = inv_dx2 * (psi(i + 1, j, k) + psi(i - 1, j, k) - 2 * psi(i, j, k))
53+
+ inv_dy2 * (psi(i, j + 1, k) + psi(i, j - 1, k) - 2 * psi(i, j, k))
54+
+ inv_dz2 * (psi(i, j, k + 1) + psi(i, j, k - 1) - 2 * psi(i, j, k));
55+
56+
// Compute ò = γ̃^{ia} γ̃^{jb} Ã_{ab} Ã_{ij}
57+
T A2 = T(0);
58+
for (int a = 0; a < 3; ++a) {
59+
for (int b = 0; b < 3; ++b) {
60+
for (int c = 0; c < 3; ++c) {
61+
for (int d = 0; d < 3; ++d) {
62+
A2 += g_tilde_inv(i,j,k,a,c) * g_tilde_inv(i,j,k,b,d)
63+
* Atilde(i,j,k,c,d) * Atilde(i,j,k,a,b);
64+
}
65+
}
66+
}
67+
}
68+
69+
T psi_val = std::fmax(psi(i, j, k), T(1e-8));
70+
T rhs = (T(1.0) / 8.0) * A2 / std::pow(psi_val, 7);
71+
72+
T new_psi = psi(i, j, k) + T(0.5) * (lap - rhs) * factor;
73+
new_psi = std::fmax(new_psi, T(0.1));
74+
75+
max_diff = std::fmax(max_diff, std::abs(new_psi - psi(i, j, k)));
76+
psi(i, j, k) = new_psi;
77+
}
78+
}
79+
}
80+
81+
if (max_diff < tol)
82+
break;
83+
}
84+
85+
return psi;
86+
}
87+
88+
};
89+
90+
}

includes/Tensorium/DiffGeometry/BSSN/BSSNDerivatives.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,5 +122,23 @@ namespace tensorium_RG {
122122
gp2 = shifted(0, 0, 2 * dz);
123123
out[2] = (-gp2 + 8 * gp1 - 8 * gm1 + gm2) / (12 * dz);
124124
}
125+
126+
template <typename T>
127+
tensorium::Tensor<T, 2> compute_dt_gamma_from_beta(
128+
const tensorium::Tensor<T, 2>& gamma,
129+
const tensorium::Vector<T>& beta,
130+
const tensorium::Tensor<T, 2>& partial_beta,
131+
const tensorium::Tensor<T, 3>& christoffel) {
132+
133+
tensorium::Tensor<T, 2> dtg({3, 3});
134+
for (size_t i = 0; i < 3; ++i)
135+
for (size_t j = 0; j < 3; ++j) {
136+
T val = partial_beta(i, j) + partial_beta(j, i);
137+
for (size_t k = 0; k < 3; ++k)
138+
val -= 2.0 * christoffel(i, j, k) * beta(k);
139+
dtg(i, j) = val;
140+
}
141+
return dtg;
142+
}
125143
}
126144

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#pragma once
2+
3+
#include "../Metric.hpp"
4+
#include "../../Core/Vector.hpp"
5+
#include "../../Core/Tensor.hpp"
6+
#include "BSSNSetup.hpp"
7+
8+
namespace tensorium_RG {
9+
10+
template <typename T>
11+
inline void print_tensor2(const std::string& name, const tensorium::Tensor<T, 2>& tensor) {
12+
std::cout << "--- " << name << " ---\n";
13+
for (size_t i = 0; i < 3; ++i) {
14+
for (size_t j = 0; j < 3; ++j)
15+
std::cout << std::setw(12) << tensor(i, j) << " ";
16+
std::cout << "\n";
17+
}
18+
}
19+
20+
template <typename T>
21+
inline void print_tensor3(const std::string& name, const tensorium::Tensor<T, 3>& tensor) {
22+
std::cout << "--- " << name << " ---\n";
23+
for (size_t d = 0; d < 3; ++d) {
24+
std::cout << "∂_" << "xyz"[d] << ":\n";
25+
for (size_t i = 0; i < 3; ++i) {
26+
for (size_t j = 0; j < 3; ++j)
27+
std::cout << std::setw(12) << tensor(d, i, j) << " ";
28+
std::cout << "\n";
29+
}
30+
}
31+
}
32+
33+
template <typename T>
34+
inline void print_vector(const std::string& name, const tensorium::Vector<T>& vec) {
35+
std::cout << "--- " << name << " ---\n";
36+
for (size_t i = 0; i < vec.size(); ++i)
37+
std::cout << std::setw(12) << vec(i) << " ";
38+
std::cout << "\n";
39+
}
40+
41+
42+
43+
} // namespace tensorium_RG
44+

includes/Tensorium/DiffGeometry/BSSN/BSSNSetup.hpp

Lines changed: 86 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "BSSNAtildeTensor.hpp"
2020
#include "BSSNTildeChristoffel.hpp"
2121
#include "BSSNContractedChristoffel.hpp"
22+
#include "BSSNPrintDebug.hpp"
23+
#include "BSSNConstraintsSolver.hpp"
2224

2325
namespace tensorium_RG {
2426
/**
@@ -84,26 +86,18 @@ namespace tensorium_RG {
8486
void init_BSSN(const tensorium::Vector<T>& X,
8587
const tensorium_RG::Metric<T>& metric,
8688
T dx, T dy, T dz) {
87-
8889
T alpha;
89-
90-
// Extract metric quantities
91-
9290
tensorium::Vector<T> beta(3);
93-
tensorium::Tensor<T, 2> gammaj({3, 3});
94-
metric.BSSN(X, alpha, beta, gammaj);
95-
tensorium::Tensor<T, 3> christoffel({3, 3, 3});
96-
tensorium::Tensor<T, 2> gammaj_inv = inv_mat_tensor(gammaj);
97-
tensorium::Tensor<T, 2> dgt({3, 3});
98-
tensorium::Tensor<T, 2> partial_beta({3, 3});
99-
tensorium::Tensor<T, 2> d_beta({3, 3});
100-
T chi = metric.compute_conformal_factor(gammaj);
101-
tensorium::Tensor<T, 2> gamma_tilde = compute_conformal_metric(metric, gammaj, chi);
91+
tensorium::Tensor<T, 2> gamma_ij({3, 3});
92+
metric.BSSN(X, alpha, beta, gamma_ij);
93+
94+
tensorium::Tensor<T, 2> dgt({3, 3});
95+
tensorium::Tensor<T, 2> gamma_ij_inv = inv_mat_tensor(gamma_ij);
96+
T chi = metric.compute_conformal_factor(gamma_ij);
97+
tensorium::Tensor<T, 2> gamma_tilde = compute_conformal_metric(metric, gamma_ij, chi);
10298
tensorium::Tensor<T, 2> gamma_tilde_inv = inv_mat_tensor(gamma_tilde);
103-
tensorium::Tensor<T, 3> dgamma_tilde({3, 3, 3});
104-
tensorium_RG::ExtrinsicCurvature<T> extr;
105-
tensorium_RG::BSSNAtildeTensor<T> Aij;
10699

100+
tensorium::Tensor<T, 3> dgamma_tilde({3, 3, 3});
107101
tensorium_RG::compute_partial_derivatives_tensor2D<T>(
108102
X, dx, dy, dz,
109103
[&](const tensorium::Vector<T>& Xs, tensorium::Tensor<T, 2>& out) {
@@ -116,13 +110,18 @@ namespace tensorium_RG {
116110
},
117111
dgamma_tilde
118112
);
119-
120-
compute_christoffel_3D(gamma_tilde, dgamma_tilde, gamma_tilde_inv, christoffel);
121-
auto contracted_Gamma = tensorium_RG::BSSNContractedGamma<T>::compute(X, metric, dx, dy, dz, chi);
113+
114+
tensorium::Tensor<T, 3> christoffel_tilde({3, 3, 3});
115+
compute_christoffel_3D(gamma_tilde, dgamma_tilde, gamma_tilde_inv, christoffel_tilde);
122116

123117
tensorium::Vector<T> tilde_Gamma(3);
124-
TildeGamma<T>::compute(gamma_tilde_inv, christoffel, tilde_Gamma);
118+
TildeGamma<T>::compute(gamma_tilde_inv, christoffel_tilde, tilde_Gamma);
125119

120+
auto contracted_Gamma = tensorium_RG::BSSNContractedGamma<T>::compute(
121+
X, metric, dx, dy, dz, chi
122+
);
123+
124+
tensorium::Tensor<T, 2> d_beta({3, 3});
126125
tensorium_RG::compute_partial_derivatives_vector<T>(
127126
X, dx, dy, dz,
128127
[&](const tensorium::Vector<T>& Xs, tensorium::Vector<T>& out) {
@@ -135,31 +134,73 @@ namespace tensorium_RG {
135134
d_beta
136135
);
137136

138-
for (size_t i = 0; i < 3; ++i)
139-
for (size_t j = 0; j < 3; ++j) {
140-
T val = 0;
141-
for (size_t l = 0; l < 3; ++l)
142-
val += gammaj(j, l) * d_beta(i, l);
143-
partial_beta(i, j) = val;
144-
}
145-
146-
auto Kij = extr.compute_Kij(dgt, gammaj, beta, partial_beta, christoffel, alpha);
147-
auto AtildeTensor = Aij.compute_Atilde_tensor(Kij, gammaj_inv, gammaj, chi);
148-
149-
150-
grid.tilde_Gamma = {tilde_Gamma};
151-
grid.contracted_Gamma = {contracted_Gamma};
152-
grid.ExtrinsicTensor = {Kij};
153-
grid.A_tildeTensor = {AtildeTensor};
154-
grid.alpha = {alpha};
155-
grid.beta = {beta};
156-
grid.gamma_ij = {gammaj};
157-
grid.gamma_ij_inv = {gammaj_inv};
158-
grid.chi = {chi};
159-
grid.gamma_tilde = {gamma_tilde};
160-
grid.gamma_tilde_inv = {gamma_tilde_inv};
161-
grid.dgamma_tilde = {dgamma_tilde};
162-
grid.christoffel_tilde = {christoffel};
137+
tensorium::Tensor<T, 3> dgamma_phys({3, 3, 3});
138+
tensorium_RG::compute_partial_derivatives_tensor2D<T>(
139+
X, dx, dy, dz,
140+
[&](const tensorium::Vector<T>& Xs, tensorium::Tensor<T, 2>& out) {
141+
T a_tmp;
142+
tensorium::Vector<T> b_tmp(3);
143+
tensorium::Tensor<T, 2> g_tmp({3, 3});
144+
metric.BSSN(Xs, a_tmp, b_tmp, g_tmp);
145+
out = g_tmp;
146+
},
147+
dgamma_phys
148+
);
149+
150+
tensorium::Tensor<T, 3> christoffel_phys({3, 3, 3});
151+
compute_christoffel_3D(gamma_ij, dgamma_phys, gamma_ij_inv, christoffel_phys);
152+
153+
tensorium_RG::ExtrinsicCurvature<T> extr;
154+
auto Kij = extr.compute_Kij(dgt, gamma_ij, beta, d_beta, christoffel_phys, alpha);
155+
156+
tensorium_RG::BSSNAtildeTensor<T> Aij;
157+
auto AtildeTensor = Aij.compute_Atilde_tensor(Kij, gamma_ij_inv, gamma_ij, chi);
158+
159+
grid.alpha = {alpha};
160+
grid.beta = {beta};
161+
grid.gamma_ij = {gamma_ij};
162+
grid.gamma_ij_inv = {gamma_ij_inv};
163+
grid.chi = {chi};
164+
grid.gamma_tilde = {gamma_tilde};
165+
grid.gamma_tilde_inv = {gamma_tilde_inv};
166+
grid.dgamma_tilde = {dgamma_tilde};
167+
grid.christoffel_tilde = {christoffel_tilde};
168+
grid.tilde_Gamma = {tilde_Gamma};
169+
grid.contracted_Gamma = {contracted_Gamma};
170+
grid.ExtrinsicTensor = {Kij};
171+
grid.A_tildeTensor = {AtildeTensor};
172+
173+
std::cout << std::setprecision(6) << std::fixed;
174+
std::cout << "\n========= BSSN Quantities at X =========\n";
175+
176+
std::cout << "--- alpha ---\n" << grid.alpha[0] << "\n";
177+
print_vector("beta", grid.beta[0]);
178+
179+
std::cout << "dbeta\n";
180+
d_beta.print();
181+
182+
print_tensor2("gamma_ij", grid.gamma_ij[0]);
183+
print_tensor2("gamma_ij_inv", grid.gamma_ij_inv[0]);
184+
185+
std::cout << "--- chi ---\n" << grid.chi[0] << "\n";
186+
print_tensor2("gamma_tilde", grid.gamma_tilde[0]);
187+
print_tensor2("gamma_tilde_inv", grid.gamma_tilde_inv[0]);
188+
189+
print_tensor3("dgamma_tilde", grid.dgamma_tilde[0]);
190+
print_tensor3("christoffel_tilde", grid.christoffel_tilde[0]);
191+
print_vector("tilde_Gamma", grid.tilde_Gamma[0]);
192+
193+
print_tensor2("∂_t gamma_ij (dgt)", dgt);
194+
print_vector("contracted_Gamma", grid.contracted_Gamma[0]);
195+
196+
print_tensor3("dgamma_phys", dgamma_phys);
197+
print_tensor3("christoffel_phys", christoffel_phys);
198+
print_tensor2("Extrinsic curvature K_ij", grid.ExtrinsicTensor[0]);
199+
Kij.print();
200+
201+
print_tensor2("A_tilde_ij", grid.A_tildeTensor[0]);
202+
203+
std::cout << "========================================\n\n";
163204
}
164205
};
165206

includes/Tensorium/DiffGeometry/BSSN/BSSNextrinTensor.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,9 @@ namespace tensorium_RG {
8383
for (size_t j = 0; j < 3; ++j) {
8484
T sym_grad_beta = partial_beta(i, j) + partial_beta(j, i);
8585
T gamma_beta = T(0.0);
86+
8687
for (size_t k = 0; k < 3; ++k)
87-
gamma_beta += 2.0 * christoffel(i, j, k) * beta(k);
88+
gamma_beta += 2.0 * christoffel(k, i, j) * beta(k);
8889

8990
Kij(i, j) = -0.5 / alpha * (dgt(i, j) - (sym_grad_beta - gamma_beta));
9091
}

0 commit comments

Comments
 (0)