1use serde::{Deserialize, Serialize};
2use crate::symbolic::SymbolicExpr;
3use crate::TensorError;
4
5pub type MetricTensor = Vec<Vec<SymbolicExpr>>;
6pub type ChristoffelSymbols = Vec<Vec<Vec<SymbolicExpr>>>;
7pub type RiemannTensor = Vec<Vec<Vec<Vec<SymbolicExpr>>>>;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct TensorComponent {
11 pub indices: Vec<usize>,
12 pub expression: String,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct ChristoffelResult {
17 pub symbols: Vec<TensorComponent>,
18 pub dimension: usize,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct RiemannResult {
23 pub components: Vec<TensorComponent>,
24 pub dimension: usize,
25}
26
27pub fn parse_metric_tensor(metric_strings: Vec<Vec<String>>, _coords: &[String]) -> Result<MetricTensor, TensorError> {
28 let n = metric_strings.len();
29
30 for row in &metric_strings {
32 if row.len() != n {
33 return Err(TensorError::InvalidMetric("Metric tensor must be square".to_string()));
34 }
35 }
36
37 let mut metric = Vec::with_capacity(n);
38
39 for row in metric_strings {
40 let mut parsed_row = Vec::with_capacity(n);
41 for expr_str in row {
42 let expr = SymbolicExpr::parse(&expr_str)
43 .map_err(|e| TensorError::InvalidMetric(format!("Failed to parse expression '{}': {}", expr_str, e)))?;
44 parsed_row.push(expr);
45 }
46 metric.push(parsed_row);
47 }
48
49 Ok(metric)
50}
51
52pub fn calculate_christoffel_symbols(metric: &MetricTensor, coords: &[String]) -> Result<ChristoffelResult, TensorError> {
53 let n = metric.len();
54 let mut symbols = Vec::new();
55
56 let metric_inv = calculate_metric_inverse(metric)?;
58
59 for mu in 0..n {
61 for alpha in 0..n {
62 for beta in 0..n {
63 let mut christoffel_expr = SymbolicExpr::Zero;
64
65 for nu in 0..n {
66 let d_g_nu_beta_d_alpha = metric[nu][beta].derivative(&coords[alpha]);
68
69 let d_g_nu_alpha_d_beta = metric[nu][alpha].derivative(&coords[beta]);
71
72 let d_g_alpha_beta_d_nu = metric[alpha][beta].derivative(&coords[nu]);
74
75 let sum = SymbolicExpr::Subtract(
77 Box::new(SymbolicExpr::Add(
78 Box::new(d_g_nu_beta_d_alpha),
79 Box::new(d_g_nu_alpha_d_beta),
80 )),
81 Box::new(d_g_alpha_beta_d_nu),
82 );
83
84 let term = SymbolicExpr::Multiply(
86 Box::new(metric_inv[mu][nu].clone()),
87 Box::new(sum),
88 );
89
90 christoffel_expr = SymbolicExpr::Add(
91 Box::new(christoffel_expr),
92 Box::new(term),
93 );
94 }
95
96 christoffel_expr = SymbolicExpr::Multiply(
98 Box::new(SymbolicExpr::Constant(0.5)),
99 Box::new(christoffel_expr),
100 );
101
102 let simplified = christoffel_expr.simplify();
103
104 if !simplified.is_zero() {
106 symbols.push(TensorComponent {
107 indices: vec![mu, alpha, beta],
108 expression: simplified.to_string(),
109 });
110 }
111 }
112 }
113 }
114
115 Ok(ChristoffelResult {
116 symbols,
117 dimension: n,
118 })
119}
120
121pub fn calculate_riemann_tensor(metric: &MetricTensor, coords: &[String]) -> Result<RiemannResult, TensorError> {
122 let n = metric.len();
123 let mut components = Vec::new();
124
125 let christoffel_result = calculate_christoffel_symbols(metric, coords)?;
127 let christoffel = symbols_to_tensor(&christoffel_result, n);
128
129 for rho in 0..n {
131 for sigma in 0..n {
132 for mu in 0..n {
133 for nu in 0..n {
134 let mut riemann_expr = SymbolicExpr::Zero;
135
136 let d_christoffel_rho_sigma_nu_d_mu = christoffel[rho][sigma][nu].derivative(&coords[mu]);
138
139 let d_christoffel_rho_sigma_mu_d_nu = christoffel[rho][sigma][mu].derivative(&coords[nu]);
141
142 riemann_expr = SymbolicExpr::Add(
144 Box::new(riemann_expr),
145 Box::new(SymbolicExpr::Subtract(
146 Box::new(d_christoffel_rho_sigma_nu_d_mu),
147 Box::new(d_christoffel_rho_sigma_mu_d_nu),
148 )),
149 );
150
151 for lambda in 0..n {
153 let term1 = SymbolicExpr::Multiply(
154 Box::new(christoffel[rho][lambda][mu].clone()),
155 Box::new(christoffel[lambda][sigma][nu].clone()),
156 );
157
158 let term2 = SymbolicExpr::Multiply(
159 Box::new(christoffel[rho][lambda][nu].clone()),
160 Box::new(christoffel[lambda][sigma][mu].clone()),
161 );
162
163 riemann_expr = SymbolicExpr::Add(
164 Box::new(riemann_expr),
165 Box::new(SymbolicExpr::Subtract(
166 Box::new(term1),
167 Box::new(term2),
168 )),
169 );
170 }
171
172 let simplified = riemann_expr.simplify();
173
174 if !simplified.is_zero() {
176 components.push(TensorComponent {
177 indices: vec![rho, sigma, mu, nu],
178 expression: simplified.to_string(),
179 });
180 }
181 }
182 }
183 }
184 }
185
186 Ok(RiemannResult {
187 components,
188 dimension: n,
189 })
190}
191
192pub fn calculate_ricci_tensor(metric: &MetricTensor, coords: &[String]) -> Result<RiemannResult, TensorError> {
193 let n = metric.len();
194 let riemann_result = calculate_riemann_tensor(metric, coords)?;
195 let riemann = riemann_result_to_tensor(&riemann_result, n);
196
197 let mut components = Vec::new();
198
199 for mu in 0..n {
201 for nu in 0..n {
202 let mut ricci_expr = SymbolicExpr::Zero;
203
204 for rho in 0..n {
205 ricci_expr = SymbolicExpr::Add(
206 Box::new(ricci_expr),
207 Box::new(riemann[rho][mu][rho][nu].clone()),
208 );
209 }
210
211 let simplified = ricci_expr.simplify();
212
213 if !simplified.is_zero() {
214 components.push(TensorComponent {
215 indices: vec![mu, nu],
216 expression: simplified.to_string(),
217 });
218 }
219 }
220 }
221
222 Ok(RiemannResult {
223 components,
224 dimension: n,
225 })
226}
227
228pub fn calculate_ricci_scalar(metric: &MetricTensor, coords: &[String]) -> Result<TensorComponent, TensorError> {
229 let n = metric.len();
230 let ricci_result = calculate_ricci_tensor(metric, coords)?;
231 let ricci = ricci_result_to_matrix(&ricci_result, n);
232 let metric_inv = calculate_metric_inverse(metric)?;
233
234 let mut scalar_expr = SymbolicExpr::Zero;
235
236 for mu in 0..n {
238 for nu in 0..n {
239 let term = SymbolicExpr::Multiply(
240 Box::new(metric_inv[mu][nu].clone()),
241 Box::new(ricci[mu][nu].clone()),
242 );
243
244 scalar_expr = SymbolicExpr::Add(
245 Box::new(scalar_expr),
246 Box::new(term),
247 );
248 }
249 }
250
251 let simplified = scalar_expr.simplify();
252
253 Ok(TensorComponent {
254 indices: vec![],
255 expression: simplified.to_string(),
256 })
257}
258
259pub fn calculate_einstein_tensor(metric: &MetricTensor, coords: &[String]) -> Result<RiemannResult, TensorError> {
260 let n = metric.len();
261 let ricci_result = calculate_ricci_tensor(metric, coords)?;
262 let ricci = ricci_result_to_matrix(&ricci_result, n);
263 let ricci_scalar = calculate_ricci_scalar(metric, coords)?;
264 let ricci_scalar_expr = SymbolicExpr::parse(&ricci_scalar.expression)
265 .map_err(|e| TensorError::ComputationError(format!("Failed to parse Ricci scalar: {}", e)))?;
266
267 let mut components = Vec::new();
268
269 for mu in 0..n {
271 for nu in 0..n {
272 let half_metric_scalar = SymbolicExpr::Multiply(
273 Box::new(SymbolicExpr::Constant(0.5)),
274 Box::new(SymbolicExpr::Multiply(
275 Box::new(metric[mu][nu].clone()),
276 Box::new(ricci_scalar_expr.clone()),
277 )),
278 );
279
280 let einstein_expr = SymbolicExpr::Subtract(
281 Box::new(ricci[mu][nu].clone()),
282 Box::new(half_metric_scalar),
283 );
284
285 let simplified = einstein_expr.simplify();
286
287 if !simplified.is_zero() {
288 components.push(TensorComponent {
289 indices: vec![mu, nu],
290 expression: simplified.to_string(),
291 });
292 }
293 }
294 }
295
296 Ok(RiemannResult {
297 components,
298 dimension: n,
299 })
300}
301
302fn calculate_metric_inverse(metric: &MetricTensor) -> Result<MetricTensor, TensorError> {
305 let n = metric.len();
306
307 if n == 2 {
310 let det = SymbolicExpr::Subtract(
311 Box::new(SymbolicExpr::Multiply(
312 Box::new(metric[0][0].clone()),
313 Box::new(metric[1][1].clone()),
314 )),
315 Box::new(SymbolicExpr::Multiply(
316 Box::new(metric[0][1].clone()),
317 Box::new(metric[1][0].clone()),
318 )),
319 );
320
321 let inv_det = SymbolicExpr::Divide(
322 Box::new(SymbolicExpr::One),
323 Box::new(det),
324 );
325
326 Ok(vec![
327 vec![
328 SymbolicExpr::Multiply(Box::new(inv_det.clone()), Box::new(metric[1][1].clone())),
329 SymbolicExpr::Multiply(
330 Box::new(inv_det.clone()),
331 Box::new(SymbolicExpr::Subtract(
332 Box::new(SymbolicExpr::Zero),
333 Box::new(metric[0][1].clone()),
334 )),
335 ),
336 ],
337 vec![
338 SymbolicExpr::Multiply(
339 Box::new(inv_det.clone()),
340 Box::new(SymbolicExpr::Subtract(
341 Box::new(SymbolicExpr::Zero),
342 Box::new(metric[1][0].clone()),
343 )),
344 ),
345 SymbolicExpr::Multiply(Box::new(inv_det), Box::new(metric[0][0].clone())),
346 ],
347 ])
348 } else {
349 let mut identity = vec![vec![SymbolicExpr::Zero; n]; n];
352 for i in 0..n {
353 identity[i][i] = SymbolicExpr::One;
354 }
355 Ok(identity)
356 }
357}
358
359fn symbols_to_tensor(christoffel_result: &ChristoffelResult, n: usize) -> ChristoffelSymbols {
360 let mut tensor = vec![vec![vec![SymbolicExpr::Zero; n]; n]; n];
361
362 for component in &christoffel_result.symbols {
363 if component.indices.len() == 3 {
364 let i = component.indices[0];
365 let j = component.indices[1];
366 let k = component.indices[2];
367
368 if let Ok(expr) = SymbolicExpr::parse(&component.expression) {
369 tensor[i][j][k] = expr;
370 }
371 }
372 }
373
374 tensor
375}
376
377fn riemann_result_to_tensor(riemann_result: &RiemannResult, n: usize) -> RiemannTensor {
378 let mut tensor = vec![vec![vec![vec![SymbolicExpr::Zero; n]; n]; n]; n];
379
380 for component in &riemann_result.components {
381 if component.indices.len() == 4 {
382 let i = component.indices[0];
383 let j = component.indices[1];
384 let k = component.indices[2];
385 let l = component.indices[3];
386
387 if let Ok(expr) = SymbolicExpr::parse(&component.expression) {
388 tensor[i][j][k][l] = expr;
389 }
390 }
391 }
392
393 tensor
394}
395
396fn ricci_result_to_matrix(ricci_result: &RiemannResult, n: usize) -> MetricTensor {
397 let mut matrix = vec![vec![SymbolicExpr::Zero; n]; n];
398
399 for component in &ricci_result.components {
400 if component.indices.len() == 2 {
401 let i = component.indices[0];
402 let j = component.indices[1];
403
404 if let Ok(expr) = SymbolicExpr::parse(&component.expression) {
405 matrix[i][j] = expr;
406 }
407 }
408 }
409
410 matrix
411}