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}