Skip to main content

sciforge_lib/physics/quantum/
wavefunctions.rs

1use crate::maths::complex::Complex;
2
3pub fn plane_wave(x: f64, k: f64, omega: f64, t: f64) -> Complex {
4    Complex::from_polar(1.0, k * x - omega * t)
5}
6
7pub fn gaussian_packet(x: f64, x0: f64, sigma: f64, k0: f64) -> Complex {
8    let norm = 1.0 / (sigma * (2.0 * std::f64::consts::PI).sqrt()).sqrt();
9    let gauss = (-(x - x0).powi(2) / (4.0 * sigma * sigma)).exp();
10    Complex::from_polar(norm * gauss, k0 * x)
11}
12
13pub fn normalize(psi: &mut [Complex], dx: f64) {
14    let norm_sq: f64 = psi.iter().map(|c| c.norm() * c.norm()).sum::<f64>() * dx;
15    let inv_norm = 1.0 / norm_sq.sqrt();
16    for c in psi.iter_mut() {
17        *c = *c * Complex::new(inv_norm, 0.0);
18    }
19}
20
21pub fn probability_density(psi: &[Complex]) -> Vec<f64> {
22    psi.iter().map(|c| c.norm() * c.norm()).collect()
23}
24
25pub fn expectation_position(psi: &[Complex], x: &[f64], dx: f64) -> f64 {
26    psi.iter()
27        .zip(x.iter())
28        .map(|(p, &xi)| p.norm() * p.norm() * xi)
29        .sum::<f64>()
30        * dx
31}
32
33pub fn expectation_momentum(psi: &[Complex], dx: f64) -> f64 {
34    use crate::constants::HBAR;
35    let n = psi.len();
36    let mut sum = 0.0;
37    for i in 1..n - 1 {
38        let dpsi = (psi[i + 1] - psi[i - 1]) * Complex::new(1.0 / (2.0 * dx), 0.0);
39        let integrand = psi[i].conj() * dpsi * Complex::new(0.0, -HBAR);
40        sum += integrand.re;
41    }
42    sum * dx
43}
44
45pub fn time_evolve_split_step(
46    psi: &mut [Complex],
47    v: &[f64],
48    dx: f64,
49    dt: f64,
50    mass: f64,
51    steps: usize,
52) {
53    use crate::constants::HBAR;
54    let n = psi.len();
55    let dk = 2.0 * std::f64::consts::PI / (n as f64 * dx);
56
57    for _ in 0..steps {
58        for i in 0..n {
59            let phase = -v[i] * dt / (2.0 * HBAR);
60            psi[i] = psi[i] * Complex::from_polar(1.0, phase);
61        }
62
63        let mut ft = vec![Complex::new(0.0, 0.0); n];
64        for (k, ftk) in ft.iter_mut().enumerate() {
65            for (j, &psij) in psi.iter().enumerate() {
66                let angle = -2.0 * std::f64::consts::PI * (k as f64) * (j as f64) / (n as f64);
67                *ftk = *ftk + psij * Complex::from_polar(1.0, angle);
68            }
69        }
70
71        for (k, ftk) in ft.iter_mut().enumerate() {
72            let kk = if k <= n / 2 {
73                k as f64 * dk
74            } else {
75                (k as f64 - n as f64) * dk
76            };
77            let phase = -HBAR * kk * kk * dt / (2.0 * mass);
78            *ftk = *ftk * Complex::from_polar(1.0, phase);
79        }
80
81        for (j, psij) in psi.iter_mut().enumerate() {
82            *psij = Complex::new(0.0, 0.0);
83            for (k, &ftk) in ft.iter().enumerate() {
84                let angle = 2.0 * std::f64::consts::PI * (k as f64) * (j as f64) / (n as f64);
85                *psij = *psij + ftk * Complex::from_polar(1.0, angle);
86            }
87            *psij = *psij * Complex::new(1.0 / n as f64, 0.0);
88        }
89
90        for i in 0..n {
91            let phase = -v[i] * dt / (2.0 * HBAR);
92            psi[i] = psi[i] * Complex::from_polar(1.0, phase);
93        }
94    }
95}
96
97pub fn inner_product(psi: &[Complex], phi: &[Complex], dx: f64) -> Complex {
98    let mut sum = Complex::new(0.0, 0.0);
99    for i in 0..psi.len() {
100        sum = sum + psi[i].conj() * phi[i];
101    }
102    sum * Complex::new(dx, 0.0)
103}
104
105pub fn transition_probability(psi_initial: &[Complex], psi_final: &[Complex], dx: f64) -> f64 {
106    let ip = inner_product(psi_final, psi_initial, dx);
107    ip.norm() * ip.norm()
108}