chemrust_core/systems/crystal_model/
mod.rs1use nalgebra::{Matrix3, Rotation3};
2
3use crate::data::{atom::CoreAtomData, geom::coordinates::CoordData, lattice::UnitCellParameters};
4
5pub fn frac_to_cart_coords<T: UnitCellParameters, U: CoreAtomData>(
11 lattice_parameters: T,
12 atoms_data: U,
13) -> Option<Vec<CoordData>> {
14 let cell_tensor = lattice_parameters.lattice_bases();
15 let all_is_frac = atoms_data
16 .coords_repr()
17 .iter()
18 .all(|coord| coord.is_fractional());
19 if !all_is_frac {
20 None
21 } else {
22 Some(
23 atoms_data
24 .coords_repr()
25 .iter()
26 .map(|coord| CoordData::Fractional(cell_tensor * coord.raw_data()))
27 .collect(),
28 )
29 }
30}
31
32pub fn rotated_lattice_tensor<T: UnitCellParameters>(
33 lattice_parameters: &T,
34 rotation: Rotation3<f64>,
35) -> Matrix3<f64> {
36 rotation.matrix() * lattice_parameters.lattice_bases()
37}
38
39#[cfg(test)]
40mod test {
41 use std::f64::consts::FRAC_PI_4;
42
43 use nalgebra::{Matrix3, Point3, Rotation3, Vector3};
44
45 use crate::data::{
46 geom::coordinates::CoordData,
47 lattice::{LatticeVectors, UnitCellParameters},
48 };
49
50 #[test]
51 fn test_rotation_of_frac_coord() {
52 let p = CoordData::Fractional(Point3::new(
53 0.0756034347004260,
54 0.0756034355668187,
55 0.5000000004346841,
56 ));
57 #[allow(clippy::excessive_precision)]
58 let lattice_vector = LatticeVectors::new(Matrix3::from_columns(&[
59 Vector3::new(
60 18.931530020488704480_f64,
61 -0.000000000000003553_f64,
62 0.000000000000000000_f64,
63 ),
64 Vector3::new(
65 -9.465765010246645517_f64,
66 16.395185930251127360_f64,
67 0.000000000000000000_f64,
68 ),
69 Vector3::new(
70 0.000000000000000000_f64,
71 0.000000000000000000_f64,
72 9.999213039981000861_f64,
73 ),
74 ]));
75 let rotation = Rotation3::from_axis_angle(&Vector3::z_axis(), FRAC_PI_4);
76 let cart_p = lattice_vector.lattice_bases() * p.raw_data();
77 let rot_cart_p = rotation.matrix() * cart_p;
78 let back_to_frac_p = lattice_vector.lattice_bases().try_inverse().unwrap() * rot_cart_p;
79 let rot = lattice_vector.lattice_bases().try_inverse().unwrap()
80 * rotation.matrix()
81 * lattice_vector.lattice_bases();
82 let rot_frac_p = rot * p.raw_data();
83 println!(
84 "Direct rotate frac_p: {:.3}, cart rotate back to frac_p: {:.3}",
85 rot_frac_p, back_to_frac_p
86 );
87 }
88}