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