rssn/symbolic/
differential_geometry.rs1use crate::symbolic::calculus::{definite_integrate, differentiate};
8use crate::symbolic::core::Expr;
9use crate::symbolic::simplify_dag::simplify;
10use crate::symbolic::vector::Vector;
11use num_bigint::BigInt;
12use num_traits::Zero;
13use std::sync::Arc;
14#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct DifferentialForm {
27 pub terms: std::collections::BTreeMap<u32, Expr>,
29}
30pub fn exterior_derivative(form: &DifferentialForm, vars: &[&str]) -> DifferentialForm {
43 let mut result_terms = std::collections::BTreeMap::new();
44 for (blade, coeff) in &form.terms {
45 for (i, _item) in vars.iter().enumerate() {
46 let new_blade = (1 << i) | blade;
47 if new_blade.count_ones() != blade.count_ones() + 1 {
48 continue;
49 }
50 let d_coeff = differentiate(coeff, vars[i]);
51 let mut sign = 1i64;
52 for j in 0..i {
53 if (blade >> j) & 1 == 1 {
54 sign *= -1;
55 }
56 }
57 let signed_coeff = if sign == 1 {
58 d_coeff
59 } else {
60 simplify(&Expr::new_neg(d_coeff))
61 };
62 let entry = result_terms
63 .entry(new_blade)
64 .or_insert(Expr::BigInt(BigInt::zero()));
65 *entry = simplify(&Expr::new_add(entry.clone(), signed_coeff));
66 }
67 }
68 DifferentialForm {
69 terms: result_terms,
70 }
71}
72pub fn wedge_product(form1: &DifferentialForm, form2: &DifferentialForm) -> DifferentialForm {
84 let mut result_terms = std::collections::BTreeMap::new();
85 for (blade1, coeff1) in &form1.terms {
86 for (blade2, coeff2) in &form2.terms {
87 if (blade1 & blade2) != 0 {
88 continue;
89 }
90 let new_blade = blade1 | blade2;
91 let mut sign = 1i64;
92 let mut temp_blade2 = *blade2;
93 while temp_blade2 > 0 {
94 let i = temp_blade2.trailing_zeros();
95 let swaps = (blade1 >> (i + 1)).count_ones();
96 if swaps % 2 != 0 {
97 sign *= -1;
98 }
99 temp_blade2 &= !(1 << i);
100 }
101 let new_coeff = simplify(&Expr::new_mul(coeff1.clone(), coeff2.clone()));
102 let signed_coeff = if sign == 1 {
103 new_coeff
104 } else {
105 simplify(&Expr::new_neg(new_coeff))
106 };
107 let entry = result_terms
108 .entry(new_blade)
109 .or_insert(Expr::BigInt(BigInt::zero()));
110 *entry = simplify(&Expr::new_add(entry.clone(), signed_coeff));
111 }
112 }
113 DifferentialForm {
114 terms: result_terms,
115 }
116}
117pub fn boundary(domain: &Expr) -> Expr {
120 Expr::Boundary(Arc::new(domain.clone()))
121}
122pub fn generalized_stokes_theorem(
129 omega: &DifferentialForm,
130 manifold: &Expr,
131 vars: &[&str],
132) -> Expr {
133 let d_omega = exterior_derivative(omega, vars);
134 let integral_d_omega = Expr::Integral {
135 integrand: Arc::new(Expr::Variable(format!("{:?}", d_omega))),
136 var: Arc::new(Expr::Variable(manifold.to_string())),
137 lower_bound: Arc::new(Expr::Variable("M".to_string())),
138 upper_bound: Arc::new(Expr::BigInt(BigInt::zero())),
139 };
140 let integral_omega = Expr::Integral {
141 integrand: Arc::new(Expr::Variable(format!("{:?}", omega))),
142 var: Arc::new(Expr::Variable(manifold.to_string())),
143 lower_bound: Arc::new(boundary(manifold)),
144 upper_bound: Arc::new(Expr::BigInt(BigInt::zero())),
145 };
146 Expr::Eq(Arc::new(integral_d_omega), Arc::new(integral_omega))
147}
148pub fn gauss_theorem(vector_field: &Vector, volume: &Expr) -> Expr {
155 let div_f = super::vector::divergence(vector_field, ("x", "y", "z"));
156 let integral_div = Expr::VolumeIntegral {
157 scalar_field: Arc::new(div_f),
158 volume: Arc::new(volume.clone()),
159 };
160 let surface_integral = Expr::SurfaceIntegral {
161 vector_field: Arc::new(Expr::Variable("F".to_string())),
162 surface: Arc::new(boundary(volume)),
163 };
164 Expr::Eq(Arc::new(integral_div), Arc::new(surface_integral))
165}
166pub fn stokes_theorem(vector_field: &Vector, surface: &Expr) -> Expr {
173 let curl_f = super::vector::curl(vector_field, ("x", "y", "z"));
174 let integral_curl = Expr::SurfaceIntegral {
175 vector_field: Arc::new(curl_f.to_expr()),
176 surface: Arc::new(surface.clone()),
177 };
178 let line_integral = Expr::Integral {
179 integrand: Arc::new(Expr::Variable("F · dr".to_string())),
180 var: Arc::new(Expr::Variable("t".to_string())),
181 lower_bound: Arc::new(boundary(surface)),
182 upper_bound: Arc::new(Expr::BigInt(BigInt::zero())),
183 };
184 Expr::Eq(Arc::new(integral_curl), Arc::new(line_integral))
185}
186pub fn greens_theorem(p: &Expr, q: &Expr, domain: &Expr) -> Expr {
193 let dq_dx = differentiate(q, "x");
194 let dp_dy = differentiate(p, "y");
195 let integrand_da = simplify(&Expr::new_sub(dq_dx, dp_dy));
196 let integral_da = definite_integrate(
197 &integrand_da,
198 "A",
199 &Expr::Domain(format!("{}", domain)),
200 &Expr::BigInt(BigInt::zero()),
201 );
202 let integrand_line = Expr::new_add(
203 Expr::new_mul(p.clone(), Expr::Variable("dx".to_string())),
204 Expr::new_mul(q.clone(), Expr::Variable("dy".to_string())),
205 );
206 let line_integral = Expr::Integral {
207 integrand: Arc::new(integrand_line),
208 var: Arc::new(Expr::Variable("t".to_string())),
209 lower_bound: Arc::new(boundary(domain)),
210 upper_bound: Arc::new(Expr::BigInt(BigInt::zero())),
211 };
212 Expr::Eq(Arc::new(integral_da), Arc::new(line_integral))
213}