castep_cell_io/param/
geometry_optimization_params.rs1use bon::Builder;
2use castep_cell_fmt::{Cell, CResult, Error, FromCellFile, ToCellFile, ToCell, FromKeyValue};
3use super::geometry_optimization::*;
4
5#[derive(Debug, Clone, Default, Builder)]
10pub struct GeometryOptimizationParams {
11 pub geom_convergence_win: Option<GeomConvergenceWin>,
12 pub geom_disp_tol: Option<GeomDispTol>,
13 pub geom_energy_tol: Option<GeomEnergyTol>,
14 pub geom_force_tol: Option<GeomForceTol>,
15 pub geom_frequency_est: Option<GeomFrequencyEst>,
16 pub geom_max_iter: Option<GeomMaxIter>,
17 pub geom_method: Option<GeomMethod>,
18 pub geom_modulus_est: Option<GeomModulusEst>,
19 pub geom_preconditioner: Option<GeomPreconditioner>,
20 pub geom_spin_fix: Option<GeomSpinFix>,
21 pub geom_stress_tol: Option<GeomStressTol>,
22}
23
24impl GeometryOptimizationParams {
25 pub fn validate(self) -> Result<Self, String> {
27 Ok(self)
29 }
30}
31
32impl FromCellFile for GeometryOptimizationParams {
33 fn from_cell_file(tokens: &[Cell<'_>]) -> CResult<Self> {
34 Self::builder()
35 .maybe_geom_convergence_win(GeomConvergenceWin::from_cells(tokens).ok().flatten())
36 .maybe_geom_disp_tol(GeomDispTol::from_cells(tokens).ok().flatten())
37 .maybe_geom_energy_tol(GeomEnergyTol::from_cells(tokens).ok().flatten())
38 .maybe_geom_force_tol(GeomForceTol::from_cells(tokens).ok().flatten())
39 .maybe_geom_frequency_est(GeomFrequencyEst::from_cells(tokens).ok().flatten())
40 .maybe_geom_max_iter(GeomMaxIter::from_cells(tokens).ok().flatten())
41 .maybe_geom_method(GeomMethod::from_cells(tokens).ok().flatten())
42 .maybe_geom_modulus_est(GeomModulusEst::from_cells(tokens).ok().flatten())
43 .maybe_geom_preconditioner(GeomPreconditioner::from_cells(tokens).ok().flatten())
44 .maybe_geom_spin_fix(GeomSpinFix::from_cells(tokens).ok().flatten())
45 .maybe_geom_stress_tol(GeomStressTol::from_cells(tokens).ok().flatten())
46 .build()
47 .validate()
48 .map_err(|e| Error::Message(e.to_string()))
49 }
50}
51
52impl ToCellFile for GeometryOptimizationParams {
53 fn to_cell_file(&self) -> Vec<Cell<'_>> {
54 let mut cells = Vec::new();
55 if let Some(v) = &self.geom_convergence_win { cells.push(v.to_cell()); }
56 if let Some(v) = &self.geom_disp_tol { cells.push(v.to_cell()); }
57 if let Some(v) = &self.geom_energy_tol { cells.push(v.to_cell()); }
58 if let Some(v) = &self.geom_force_tol { cells.push(v.to_cell()); }
59 if let Some(v) = &self.geom_frequency_est { cells.push(v.to_cell()); }
60 if let Some(v) = &self.geom_max_iter { cells.push(v.to_cell()); }
61 if let Some(v) = &self.geom_method { cells.push(v.to_cell()); }
62 if let Some(v) = &self.geom_modulus_est { cells.push(v.to_cell()); }
63 if let Some(v) = &self.geom_preconditioner { cells.push(v.to_cell()); }
64 if let Some(v) = &self.geom_spin_fix { cells.push(v.to_cell()); }
65 if let Some(v) = &self.geom_stress_tol { cells.push(v.to_cell()); }
66 cells
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn test_empty_builder() {
76 let params = GeometryOptimizationParams::builder().build();
77 assert!(params.validate().is_ok());
78 }
79
80 #[test]
81 fn test_builder_with_single_field() {
82 let params = GeometryOptimizationParams::builder()
83 .maybe_geom_max_iter(Some(GeomMaxIter(100)))
84 .build();
85 assert_eq!(params.geom_max_iter, Some(GeomMaxIter(100)));
86 assert!(params.validate().is_ok());
87 }
88
89 #[test]
90 fn test_builder_with_multiple_fields() {
91 let params = GeometryOptimizationParams::builder()
92 .maybe_geom_max_iter(Some(GeomMaxIter(100)))
93 .maybe_geom_method(Some(GeomMethod::Bfgs))
94 .build();
95 assert_eq!(params.geom_max_iter, Some(GeomMaxIter(100)));
96 assert_eq!(params.geom_method, Some(GeomMethod::Bfgs));
97 assert!(params.validate().is_ok());
98 }
99
100 #[test]
101 fn test_to_cell_file_empty() {
102 let params = GeometryOptimizationParams::builder().build();
103 let cells = params.to_cell_file();
104 assert_eq!(cells.len(), 0);
105 }
106
107 #[test]
108 fn test_to_cell_file_with_fields() {
109 let params = GeometryOptimizationParams::builder()
110 .maybe_geom_max_iter(Some(GeomMaxIter(100)))
111 .maybe_geom_method(Some(GeomMethod::Bfgs))
112 .build();
113 let cells = params.to_cell_file();
114 assert_eq!(cells.len(), 2);
115 }
116
117 #[test]
118 fn test_validate_always_succeeds() {
119 let params = GeometryOptimizationParams::builder()
120 .maybe_geom_max_iter(Some(GeomMaxIter(100)))
121 .maybe_geom_method(Some(GeomMethod::Bfgs))
122 .maybe_geom_force_tol(Some(GeomForceTol { value: 0.01, unit: None }))
123 .build();
124 assert!(params.validate().is_ok());
125 }
126}