qsym2/sandbox/target/real_space_function/
real_space_function_transformation.rs

1//! Implementation of symmetry transformations for real-space functions.
2
3use itertools::Itertools;
4use nalgebra::Point3;
5use ndarray::{Array2, Axis, ShapeBuilder};
6use ndarray_linalg::types::Lapack;
7use num_complex::{Complex, ComplexFloat};
8
9use crate::permutation::Permutation;
10use crate::sandbox::target::real_space_function::RealSpaceFunction;
11use crate::symmetry::symmetry_element::SymmetryOperation;
12use crate::symmetry::symmetry_transformation::{
13    ComplexConjugationTransformable, DefaultTimeReversalTransformable, SpatialUnitaryTransformable,
14    SpinUnitaryTransformable, SymmetryTransformable, TimeReversalTransformable,
15    TransformationError,
16};
17
18// ---------------------------
19// SpatialUnitaryTransformable
20// ---------------------------
21impl<T, F> SpatialUnitaryTransformable for RealSpaceFunction<T, F>
22where
23    T: ComplexFloat + Lapack,
24    F: Clone + Fn(&Point3<f64>) -> T,
25{
26    fn transform_spatial_mut(
27        &mut self,
28        rmat: &Array2<f64>,
29        _: Option<&Permutation<usize>>,
30    ) -> Result<&mut Self, TransformationError> {
31        let rmat = rmat.select(Axis(0), &[2, 0, 1]).select(Axis(1), &[2, 0, 1]);
32        let rmatinv = rmat.t();
33        let grid_array = Array2::from_shape_vec(
34            (3, self.grid_points.len()).f(),
35            self.grid_points
36                .iter()
37                .flat_map(|pt| pt.iter().cloned())
38                .collect_vec(),
39        )
40        .map_err(|err| TransformationError(err.to_string()))?;
41        let rmatinv_grid_array = rmatinv.dot(&grid_array);
42        let rmatinv_grid_points = rmatinv_grid_array
43            .columns()
44            .into_iter()
45            .map(|col| Point3::new(col[0], col[1], col[2]))
46            .collect_vec();
47        self.grid_points = rmatinv_grid_points;
48        Ok(self)
49    }
50}
51
52// ------------------------
53// SpinUnitaryTransformable
54// ------------------------
55
56impl<T, F> SpinUnitaryTransformable for RealSpaceFunction<T, F>
57where
58    T: ComplexFloat + Lapack,
59    F: Clone + Fn(&Point3<f64>) -> T,
60{
61    /// Performs a spin transformation in-place.
62    ///
63    /// Since real-space functions are entirely spatial, spin transformations have no effect on
64    /// them. This thus simply returns `self` without modification.
65    fn transform_spin_mut(
66        &mut self,
67        _: &Array2<Complex<f64>>,
68    ) -> Result<&mut Self, TransformationError> {
69        Ok(self)
70    }
71}
72
73// -------------------------------
74// ComplexConjugationTransformable
75// -------------------------------
76
77impl<T, F> ComplexConjugationTransformable for RealSpaceFunction<T, F>
78where
79    T: ComplexFloat + Lapack,
80    F: Clone + Fn(&Point3<f64>) -> T,
81{
82    fn transform_cc_mut(&mut self) -> Result<&mut Self, TransformationError> {
83        self.complex_conjugated = !self.complex_conjugated;
84        Ok(self)
85    }
86}
87
88// --------------------------------
89// DefaultTimeReversalTransformable
90// --------------------------------
91impl<T, F> DefaultTimeReversalTransformable for RealSpaceFunction<T, F>
92where
93    T: ComplexFloat + Lapack,
94    F: Clone + Fn(&Point3<f64>) -> T,
95{
96}
97
98// ---------------------
99// SymmetryTransformable
100// ---------------------
101impl<T, F> SymmetryTransformable for RealSpaceFunction<T, F>
102where
103    T: ComplexFloat + Lapack,
104    F: Clone + Fn(&Point3<f64>) -> T,
105    RealSpaceFunction<T, F>: SpatialUnitaryTransformable + TimeReversalTransformable,
106{
107    /// Real-space functions have no local sites for permutation. This method therefore simply
108    /// returns the identity permutation on one object.
109    fn sym_permute_sites_spatial(
110        &self,
111        _: &SymmetryOperation,
112    ) -> Result<Permutation<usize>, TransformationError> {
113        Permutation::from_image(vec![0]).map_err(|err| TransformationError(err.to_string()))
114    }
115}