From 89d1c5d4dc9d683282158fab3061017e1838ab41 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Sat, 17 Oct 2026 18:44:07 +0100 Subject: [PATCH] Define augmented phase space symplectic integrator --- .gitignore | 1 + src/augmented.rs | 128 +++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + 3 files changed, 131 insertions(+) create mode 100644 .gitignore create mode 100644 src/augmented.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/src/augmented.rs b/src/augmented.rs new file mode 100644 index 0000000..58afd3d --- /dev/null +++ b/src/augmented.rs @@ -0,0 +1,128 @@ +use crate::hamiltonian::*; + +use std::ops::{Add, Sub, Mul, Div, AddAssign}; + +#[derive(Clone, Copy, Debug)] +pub struct Augmented { + omega: f64, + pub a: State, + pub b: State, +} + +impl Augmented { + pub fn from(state: State, omega: f64) -> Self { + Self { + omega, + a: state, + b: state, + } + } +} + +impl Augmented +where T: Copy + Add + Mul +{ + pub fn average(&self) -> State { + (self.a + self.b) * 0.5 + } +} + +impl Augmented +where + T: Copy + Add + Sub + Mul + Div + AddAssign, + State: Hamiltonian +{ + pub fn evolve(&mut self, h: f64) { + let cbrt2 = 2.0_f64.powf(1.0 / 3.0); + let z0 = - cbrt2 / (2.0 - cbrt2); + let z1 = 1.0 / (2.0 - cbrt2); + + self.strang(z1 * h); + self.strang(z0 * h); + self.strang(z1 * h); + } + + fn strang(&mut self, h: f64) { + self.evolve_a(h / 2.0); + self.evolve_b(h / 2.0); + self.evolve_c(h); + self.evolve_b(h / 2.0); + self.evolve_a(h / 2.0); + } + + fn evolve_a(&mut self, h: f64) { + let dots = State { q: self.a.q, p: self.b.p }.dots(); + self.a.p += dots.p * h; + self.b.q += dots.q * h; + } + + fn evolve_b(&mut self, h: f64) { + let dots = State { q: self.b.q, p: self.a.p }.dots(); + self.a.q += dots.q * h; + self.b.p += dots.p * h; + } + + fn evolve_c(&mut self, h: f64) { + let alpha = 2.0 * self.omega * h; + let c = alpha.cos(); + let s = alpha.sin(); + + let diff = self.a - self.b; + let r = State { + q: diff.q * c + diff.p * s, + p: diff.p * c - diff.q * s, + }; + + let sum = self.a + self.b; + self.a = (sum + r) / 2.0; + self.b = (sum - r) / 2.0; + } +} + +impl> Add for Augmented { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self { + omega: self.omega, + a: self.a + rhs.a, + b: self.b + rhs.b, + } + } +} + +impl> Sub for Augmented { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + Self { + omega: self.omega, + a: self.a - rhs.a, + b: self.b - rhs.b, + } + } +} + +impl> Mul for Augmented { + type Output = Self; + + fn mul(self, rhs: f64) -> Self { + Self { + omega: self.omega, + a: self.a * rhs, + b: self.b * rhs, + } + } +} + +impl> Div for Augmented { + type Output = Self; + + fn div(self, rhs: f64) -> Self { + Self { + omega: self.omega, + a: self.a / rhs, + b: self.b / rhs, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 4c19035..8716395 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ pub mod hamiltonian; +pub mod augmented; pub use hamiltonian::*; +pub use augmented::*;