1use std::vec::Vec;
6
7use na::SVector;
8#[cfg(feature = "serde-serialize")]
9use serde::{Deserialize, Serialize};
10
11use super::{
12 super::{
13 field::{EField, LinkMatrix, Su3Adjoint},
14 lattice::LatticeCyclic,
15 simulation::{
16 LatticeState, LatticeStateWithEField, LatticeStateWithEFieldNew, SimulationStateLeap,
17 SimulationStateSynchronous,
18 },
19 thread::{run_pool_parallel_vec, ThreadError},
20 CMatrix3, Real,
21 },
22 integrate_efield, integrate_link, SymplecticIntegrator,
23};
24
25#[derive(Debug, Clone, Eq, PartialEq, Hash)]
27#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
28pub enum SymplecticEulerError<Error> {
29 ThreadingError(ThreadError),
31 StateInitializationError(Error),
33}
34
35impl<Error> From<ThreadError> for SymplecticEulerError<Error> {
36 fn from(err: ThreadError) -> Self {
37 Self::ThreadingError(err)
38 }
39}
40
41impl<Error: core::fmt::Display> core::fmt::Display for SymplecticEulerError<Error> {
42 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
43 match self {
44 Self::ThreadingError(error) => write!(f, "thread error: {}", error),
45 Self::StateInitializationError(error) => write!(f, "initialization error: {}", error),
46 }
47 }
48}
49
50impl<Error: std::error::Error + 'static> std::error::Error for SymplecticEulerError<Error> {
51 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
52 match self {
53 Self::ThreadingError(error) => Some(error),
54 Self::StateInitializationError(error) => Some(error),
55 }
56 }
57}
58
59#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
66#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
67pub struct SymplecticEuler {
68 number_of_thread: usize,
69}
70
71impl SymplecticEuler {
72 getter_copy!(
73 pub const,
75 number_of_thread,
76 usize
77 );
78
79 pub const fn new(number_of_thread: usize) -> Self {
81 Self { number_of_thread }
82 }
83
84 fn link_matrix_integrate<State, const D: usize>(
85 self,
86 link_matrix: &LinkMatrix,
87 e_field: &EField<D>,
88 lattice: &LatticeCyclic<D>,
89 delta_t: Real,
90 ) -> Result<Vec<CMatrix3>, ThreadError>
91 where
92 State: LatticeStateWithEField<D>,
93 {
94 run_pool_parallel_vec(
95 lattice.get_links(),
96 &(link_matrix, e_field, lattice),
97 &|link, (link_matrix, e_field, lattice)| {
98 integrate_link::<State, D>(link, link_matrix, e_field, lattice, delta_t)
99 },
100 self.number_of_thread,
101 lattice.number_of_canonical_links_space(),
102 lattice,
103 &CMatrix3::zeros(),
104 )
105 .map_err(|err| err.into())
106 }
107
108 fn e_field_integrate<State, const D: usize>(
109 self,
110 link_matrix: &LinkMatrix,
111 e_field: &EField<D>,
112 lattice: &LatticeCyclic<D>,
113 delta_t: Real,
114 ) -> Result<Vec<SVector<Su3Adjoint, D>>, ThreadError>
115 where
116 State: LatticeStateWithEField<D>,
117 {
118 run_pool_parallel_vec(
119 lattice.get_points(),
120 &(link_matrix, e_field, lattice),
121 &|point, (link_matrix, e_field, lattice)| {
122 integrate_efield::<State, D>(point, link_matrix, e_field, lattice, delta_t)
123 },
124 self.number_of_thread,
125 lattice.number_of_points(),
126 lattice,
127 &SVector::<_, D>::from_element(Su3Adjoint::default()),
128 )
129 .map_err(|err| err.into())
130 }
131}
132
133impl Default for SymplecticEuler {
134 fn default() -> Self {
137 Self::new(rayon::current_num_threads().min(1))
138 }
139}
140
141impl std::fmt::Display for SymplecticEuler {
142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143 write!(
144 f,
145 "Euler integrator with {} thread",
146 self.number_of_thread()
147 )
148 }
149}
150
151impl<State, const D: usize> SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>
152 for SymplecticEuler
153where
154 State: SimulationStateSynchronous<D> + LatticeStateWithEField<D> + LatticeStateWithEFieldNew<D>,
155{
156 type Error = SymplecticEulerError<State::Error>;
157
158 fn integrate_sync_sync(&self, l: &State, delta_t: Real) -> Result<State, Self::Error> {
159 let link_matrix = self.link_matrix_integrate::<State, D>(
160 l.link_matrix(),
161 l.e_field(),
162 l.lattice(),
163 delta_t,
164 )?;
165 let e_field =
166 self.e_field_integrate::<State, D>(l.link_matrix(), l.e_field(), l.lattice(), delta_t)?;
167
168 State::new(
169 l.lattice().clone(),
170 l.beta(),
171 EField::new(e_field),
172 LinkMatrix::new(link_matrix),
173 l.t() + 1,
174 )
175 .map_err(SymplecticEulerError::StateInitializationError)
176 }
177
178 fn integrate_leap_leap(
179 &self,
180 l: &SimulationStateLeap<State, D>,
181 delta_t: Real,
182 ) -> Result<SimulationStateLeap<State, D>, Self::Error> {
183 let link_matrix = LinkMatrix::new(self.link_matrix_integrate::<State, D>(
184 l.link_matrix(),
185 l.e_field(),
186 l.lattice(),
187 delta_t,
188 )?);
189 let e_field = EField::new(self.e_field_integrate::<State, D>(
190 &link_matrix,
191 l.e_field(),
192 l.lattice(),
193 delta_t,
194 )?);
195 SimulationStateLeap::<State, D>::new(
196 l.lattice().clone(),
197 l.beta(),
198 e_field,
199 link_matrix,
200 l.t() + 1,
201 )
202 .map_err(SymplecticEulerError::StateInitializationError)
203 }
204
205 fn integrate_sync_leap(
206 &self,
207 l: &State,
208 delta_t: Real,
209 ) -> Result<SimulationStateLeap<State, D>, Self::Error> {
210 let e_field = self.e_field_integrate::<State, D>(
211 l.link_matrix(),
212 l.e_field(),
213 l.lattice(),
214 delta_t / 2_f64,
215 )?;
216 SimulationStateLeap::<State, D>::new(
218 l.lattice().clone(),
219 l.beta(),
220 EField::new(e_field),
221 l.link_matrix().clone(),
222 l.t(),
223 )
224 .map_err(SymplecticEulerError::StateInitializationError)
225 }
226
227 fn integrate_leap_sync(
228 &self,
229 l: &SimulationStateLeap<State, D>,
230 delta_t: Real,
231 ) -> Result<State, Self::Error> {
232 let link_matrix = LinkMatrix::new(self.link_matrix_integrate::<State, D>(
233 l.link_matrix(),
234 l.e_field(),
235 l.lattice(),
236 delta_t,
237 )?);
238 let e_field = EField::new(self.e_field_integrate::<State, D>(
240 &link_matrix,
241 l.e_field(),
242 l.lattice(),
243 delta_t / 2_f64,
244 )?);
245 State::new(
246 l.lattice().clone(),
247 l.beta(),
248 e_field,
249 link_matrix,
250 l.t() + 1,
251 )
252 .map_err(SymplecticEulerError::StateInitializationError)
253 }
254
255 fn integrate_symplectic(&self, l: &State, delta_t: Real) -> Result<State, Self::Error> {
256 let e_field_half = EField::new(self.e_field_integrate::<State, D>(
260 l.link_matrix(),
261 l.e_field(),
262 l.lattice(),
263 delta_t / 2_f64,
264 )?);
265 let link_matrix = LinkMatrix::new(self.link_matrix_integrate::<State, D>(
266 l.link_matrix(),
267 &e_field_half,
268 l.lattice(),
269 delta_t,
270 )?);
271 let e_field = EField::new(self.e_field_integrate::<State, D>(
272 &link_matrix,
273 &e_field_half,
274 l.lattice(),
275 delta_t / 2_f64,
276 )?);
277
278 State::new(
279 l.lattice().clone(),
280 l.beta(),
281 e_field,
282 link_matrix,
283 l.t() + 1,
284 )
285 .map_err(SymplecticEulerError::StateInitializationError)
286 }
287}