qsym2/target/noci/
multideterminant_transformation.rs

1//! Implementation of symmetry transformations for multi-determinantal wavefunctions.
2
3use std::fmt;
4use std::hash::Hash;
5
6use ndarray::Array2;
7use ndarray_linalg::types::Lapack;
8use num_complex::{Complex, ComplexFloat};
9
10use crate::angmom::spinor_rotation_3d::{SpinConstraint, StructureConstraint};
11use crate::group::GroupProperties;
12use crate::permutation::Permutation;
13use crate::symmetry::symmetry_element::{SpecialSymmetryTransformation, SymmetryOperation};
14use crate::symmetry::symmetry_transformation::{
15    ComplexConjugationTransformable, DefaultTimeReversalTransformable, SpatialUnitaryTransformable,
16    SpinUnitaryTransformable, SymmetryTransformable, TransformationError,
17};
18use crate::target::determinant::SlaterDeterminant;
19use crate::target::noci::basis::{Basis, EagerBasis, OrbitBasis};
20use crate::target::noci::multideterminant::MultiDeterminant;
21
22// ---------------------------
23// SpatialUnitaryTransformable
24// ---------------------------
25
26impl<'a, T, B, SC> SpatialUnitaryTransformable for MultiDeterminant<'a, T, B, SC>
27where
28    T: ComplexFloat + Lapack,
29    SC: StructureConstraint + Hash + Eq + Clone + fmt::Display,
30    B: Basis<SlaterDeterminant<'a, T, SC>> + SpatialUnitaryTransformable + Clone,
31{
32    fn transform_spatial_mut(
33        &mut self,
34        rmat: &Array2<f64>,
35        perm: Option<&Permutation<usize>>,
36    ) -> Result<&mut Self, TransformationError> {
37        self.basis.transform_spatial_mut(rmat, perm)?;
38        Ok(self)
39    }
40}
41
42// ------------------------
43// SpinUnitaryTransformable
44// ------------------------
45
46impl<'a, T, B, SC> SpinUnitaryTransformable for MultiDeterminant<'a, T, B, SC>
47where
48    T: ComplexFloat + Lapack,
49    SC: StructureConstraint + Hash + Eq + Clone + fmt::Display,
50    B: Basis<SlaterDeterminant<'a, T, SC>> + SpinUnitaryTransformable + Clone,
51{
52    fn transform_spin_mut(
53        &mut self,
54        dmat: &Array2<Complex<f64>>,
55    ) -> Result<&mut Self, TransformationError> {
56        self.basis.transform_spin_mut(dmat)?;
57        Ok(self)
58    }
59}
60
61// -------------------------------
62// ComplexConjugationTransformable
63// -------------------------------
64
65impl<'a, T, B, SC> ComplexConjugationTransformable for MultiDeterminant<'a, T, B, SC>
66where
67    T: ComplexFloat + Lapack,
68    SC: StructureConstraint + Hash + Eq + Clone + fmt::Display,
69    B: Basis<SlaterDeterminant<'a, T, SC>> + ComplexConjugationTransformable + Clone,
70{
71    /// Performs a complex conjugation in-place.
72    fn transform_cc_mut(&mut self) -> Result<&mut Self, TransformationError> {
73        self.basis.transform_cc_mut()?;
74        self.coefficients.iter_mut().for_each(|v| *v = v.conj());
75        self.complex_conjugated = !self.complex_conjugated;
76        Ok(self)
77    }
78}
79
80// --------------------------------
81// DefaultTimeReversalTransformable
82// --------------------------------
83
84impl<'a, T, B> DefaultTimeReversalTransformable for MultiDeterminant<'a, T, B, SpinConstraint>
85where
86    T: ComplexFloat + Lapack,
87    B: Basis<SlaterDeterminant<'a, T, SpinConstraint>> + DefaultTimeReversalTransformable + Clone,
88{
89}
90
91// ---------------------
92// SymmetryTransformable
93// ---------------------
94
95impl<'a, 'go, G, T> SymmetryTransformable
96    for MultiDeterminant<
97        'a,
98        T,
99        OrbitBasis<'go, G, SlaterDeterminant<'a, T, SpinConstraint>>,
100        SpinConstraint,
101    >
102where
103    T: ComplexFloat + Lapack,
104    G: GroupProperties<GroupElement = SymmetryOperation> + Clone,
105    SlaterDeterminant<'a, T, SpinConstraint>: SymmetryTransformable,
106{
107    fn sym_permute_sites_spatial(
108        &self,
109        symop: &SymmetryOperation,
110    ) -> Result<Permutation<usize>, TransformationError> {
111        self.basis.sym_permute_sites_spatial(symop)
112    }
113
114    // --------------------------
115    // Overriden provided methods
116    // --------------------------
117    fn sym_transform_spatial_mut(
118        &mut self,
119        symop: &SymmetryOperation,
120    ) -> Result<&mut Self, TransformationError> {
121        self.basis.sym_transform_spatial_mut(symop)?;
122        if symop.contains_time_reversal() {
123            self.coefficients.iter_mut().for_each(|v| *v = v.conj());
124            self.complex_conjugated = !self.complex_conjugated;
125        }
126        Ok(self)
127    }
128
129    fn sym_transform_spatial_with_spintimerev_mut(
130        &mut self,
131        symop: &SymmetryOperation,
132    ) -> Result<&mut Self, TransformationError> {
133        self.basis
134            .sym_transform_spatial_with_spintimerev_mut(symop)?;
135        if symop.contains_time_reversal() {
136            self.coefficients.iter_mut().for_each(|v| *v = v.conj());
137            self.complex_conjugated = !self.complex_conjugated;
138        }
139        Ok(self)
140    }
141
142    fn sym_transform_spin_mut(
143        &mut self,
144        symop: &SymmetryOperation,
145    ) -> Result<&mut Self, TransformationError> {
146        self.basis.sym_transform_spin_mut(symop)?;
147        if symop.contains_time_reversal() {
148            self.coefficients.iter_mut().for_each(|v| *v = v.conj());
149            self.complex_conjugated = !self.complex_conjugated;
150        }
151        Ok(self)
152    }
153
154    fn sym_transform_spin_spatial_mut(
155        &mut self,
156        symop: &SymmetryOperation,
157    ) -> Result<&mut Self, TransformationError> {
158        self.basis.sym_transform_spin_spatial_mut(symop)?;
159        if symop.contains_time_reversal() {
160            self.coefficients.iter_mut().for_each(|v| *v = v.conj());
161            self.complex_conjugated = !self.complex_conjugated;
162        }
163        Ok(self)
164    }
165}
166
167impl<'a, T> SymmetryTransformable
168    for MultiDeterminant<
169        'a,
170        T,
171        EagerBasis<SlaterDeterminant<'a, T, SpinConstraint>>,
172        SpinConstraint,
173    >
174where
175    T: ComplexFloat + Lapack,
176    SlaterDeterminant<'a, T, SpinConstraint>: SymmetryTransformable,
177{
178    fn sym_permute_sites_spatial(
179        &self,
180        symop: &SymmetryOperation,
181    ) -> Result<Permutation<usize>, TransformationError> {
182        self.basis.sym_permute_sites_spatial(symop)
183    }
184}