1use 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::{SpinOrbitCoupled, 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, TimeReversalTransformable,
17    TransformationError,
18};
19use crate::target::determinant::SlaterDeterminant;
20use crate::target::noci::basis::{Basis, EagerBasis, OrbitBasis};
21use crate::target::noci::multideterminant::MultiDeterminant;
22
23impl<'a, T, B, SC> SpatialUnitaryTransformable for MultiDeterminant<'a, T, B, SC>
28where
29    T: ComplexFloat + Lapack,
30    SC: StructureConstraint + Hash + Eq + Clone + fmt::Display,
31    B: Basis<SlaterDeterminant<'a, T, SC>> + SpatialUnitaryTransformable + Clone,
32{
33    fn transform_spatial_mut(
34        &mut self,
35        rmat: &Array2<f64>,
36        perm: Option<&Permutation<usize>>,
37    ) -> Result<&mut Self, TransformationError> {
38        self.basis.transform_spatial_mut(rmat, perm)?;
39        Ok(self)
40    }
41}
42
43impl<'a, T, B, SC> SpinUnitaryTransformable for MultiDeterminant<'a, T, B, SC>
48where
49    T: ComplexFloat + Lapack,
50    SC: StructureConstraint + Hash + Eq + Clone + fmt::Display,
51    B: Basis<SlaterDeterminant<'a, T, SC>> + SpinUnitaryTransformable + Clone,
52{
53    fn transform_spin_mut(
54        &mut self,
55        dmat: &Array2<Complex<f64>>,
56    ) -> Result<&mut Self, TransformationError> {
57        self.basis.transform_spin_mut(dmat)?;
58        Ok(self)
59    }
60}
61
62impl<'a, T, B, SC> ComplexConjugationTransformable for MultiDeterminant<'a, T, B, SC>
67where
68    T: ComplexFloat + Lapack,
69    SC: StructureConstraint + Hash + Eq + Clone + fmt::Display,
70    B: Basis<SlaterDeterminant<'a, T, SC>> + ComplexConjugationTransformable + Clone,
71{
72    fn transform_cc_mut(&mut self) -> Result<&mut Self, TransformationError> {
74        self.basis.transform_cc_mut()?;
75        self.coefficients.iter_mut().for_each(|v| *v = v.conj());
76        self.complex_conjugated = !self.complex_conjugated;
77        Ok(self)
78    }
79}
80
81impl<'a, T, B, SC> DefaultTimeReversalTransformable for MultiDeterminant<'a, T, B, SC>
86where
87    T: ComplexFloat + Lapack,
88    SC: StructureConstraint + Hash + Eq + Clone + fmt::Display,
89    B: Basis<SlaterDeterminant<'a, T, SC>> + DefaultTimeReversalTransformable + Clone,
90{
91}
92
93impl<'a, 'g, G> TimeReversalTransformable
101    for MultiDeterminant<
102        'a,
103        Complex<f64>,
104        OrbitBasis<'g, G, SlaterDeterminant<'a, Complex<f64>, SpinOrbitCoupled>>,
105        SpinOrbitCoupled,
106    >
107where
108    G: GroupProperties<GroupElement = SymmetryOperation> + Clone,
109{
110    fn transform_timerev_mut(&mut self) -> Result<&mut Self, TransformationError> {
111        self.basis.transform_timerev_mut()?;
112        self.coefficients.mapv_inplace(|v| v.conj());
113        self.complex_conjugated = !self.complex_conjugated;
114        Ok(self)
115    }
116}
117
118impl<'a> TimeReversalTransformable
123    for MultiDeterminant<
124        'a,
125        Complex<f64>,
126        EagerBasis<SlaterDeterminant<'a, Complex<f64>, SpinOrbitCoupled>>,
127        SpinOrbitCoupled,
128    >
129{
130    fn transform_timerev_mut(&mut self) -> Result<&mut Self, TransformationError> {
131        self.basis.transform_timerev_mut()?;
132        self.coefficients.mapv_inplace(|v| v.conj());
133        self.complex_conjugated = !self.complex_conjugated;
134        Ok(self)
135    }
136}
137
138impl<'a, 'go, T, B, SC> SymmetryTransformable for MultiDeterminant<'a, T, B, SC>
143where
144    T: ComplexFloat + Lapack,
145    B: Basis<SlaterDeterminant<'a, T, SC>> + Clone + SymmetryTransformable,
146    SC: StructureConstraint + Hash + Eq + Clone + fmt::Display,
147    SlaterDeterminant<'a, T, SC>: SymmetryTransformable,
148    Self: TimeReversalTransformable,
149{
150    fn sym_permute_sites_spatial(
151        &self,
152        symop: &SymmetryOperation,
153    ) -> Result<Permutation<usize>, TransformationError> {
154        self.basis.sym_permute_sites_spatial(symop)
155    }
156
157    fn sym_transform_spatial_mut(
161        &mut self,
162        symop: &SymmetryOperation,
163    ) -> Result<&mut Self, TransformationError> {
164        self.basis.sym_transform_spatial_mut(symop)?;
165        if symop.contains_time_reversal() {
166            self.coefficients.iter_mut().for_each(|v| *v = v.conj());
167            self.complex_conjugated = !self.complex_conjugated;
168        }
169        Ok(self)
170    }
171
172    fn sym_transform_spatial_with_spintimerev_mut(
173        &mut self,
174        symop: &SymmetryOperation,
175    ) -> Result<&mut Self, TransformationError> {
176        self.basis
177            .sym_transform_spatial_with_spintimerev_mut(symop)?;
178        if symop.contains_time_reversal() {
179            self.coefficients.iter_mut().for_each(|v| *v = v.conj());
180            self.complex_conjugated = !self.complex_conjugated;
181        }
182        Ok(self)
183    }
184
185    fn sym_transform_spin_mut(
186        &mut self,
187        symop: &SymmetryOperation,
188    ) -> Result<&mut Self, TransformationError> {
189        self.basis.sym_transform_spin_mut(symop)?;
190        if symop.contains_time_reversal() {
191            self.coefficients.iter_mut().for_each(|v| *v = v.conj());
192            self.complex_conjugated = !self.complex_conjugated;
193        }
194        Ok(self)
195    }
196
197    fn sym_transform_spin_spatial_mut(
198        &mut self,
199        symop: &SymmetryOperation,
200    ) -> Result<&mut Self, TransformationError> {
201        self.basis.sym_transform_spin_spatial_mut(symop)?;
202        if symop.contains_time_reversal() {
203            self.coefficients.iter_mut().for_each(|v| *v = v.conj());
204            self.complex_conjugated = !self.complex_conjugated;
205        }
206        Ok(self)
207    }
208}