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, G, T, SC> SymmetryTransformable
143 for MultiDeterminant<'a, T, OrbitBasis<'go, G, SlaterDeterminant<'a, T, SC>>, SC>
144where
145 T: ComplexFloat + Lapack,
146 G: GroupProperties<GroupElement = SymmetryOperation> + Clone,
147 SC: StructureConstraint + Hash + Eq + Clone + fmt::Display,
148 SlaterDeterminant<'a, T, SC>: SymmetryTransformable,
149 Self: TimeReversalTransformable,
150 OrbitBasis<'go, G, SlaterDeterminant<'a, T, SC>>: TimeReversalTransformable,
151{
152 fn sym_permute_sites_spatial(
153 &self,
154 symop: &SymmetryOperation,
155 ) -> Result<Permutation<usize>, TransformationError> {
156 self.basis.sym_permute_sites_spatial(symop)
157 }
158
159 fn sym_transform_spatial_mut(
163 &mut self,
164 symop: &SymmetryOperation,
165 ) -> Result<&mut Self, TransformationError> {
166 self.basis.sym_transform_spatial_mut(symop)?;
167 if symop.contains_time_reversal() {
168 self.coefficients.iter_mut().for_each(|v| *v = v.conj());
169 self.complex_conjugated = !self.complex_conjugated;
170 }
171 Ok(self)
172 }
173
174 fn sym_transform_spatial_with_spintimerev_mut(
175 &mut self,
176 symop: &SymmetryOperation,
177 ) -> Result<&mut Self, TransformationError> {
178 self.basis
179 .sym_transform_spatial_with_spintimerev_mut(symop)?;
180 if symop.contains_time_reversal() {
181 self.coefficients.iter_mut().for_each(|v| *v = v.conj());
182 self.complex_conjugated = !self.complex_conjugated;
183 }
184 Ok(self)
185 }
186
187 fn sym_transform_spin_mut(
188 &mut self,
189 symop: &SymmetryOperation,
190 ) -> Result<&mut Self, TransformationError> {
191 self.basis.sym_transform_spin_mut(symop)?;
192 if symop.contains_time_reversal() {
193 self.coefficients.iter_mut().for_each(|v| *v = v.conj());
194 self.complex_conjugated = !self.complex_conjugated;
195 }
196 Ok(self)
197 }
198
199 fn sym_transform_spin_spatial_mut(
200 &mut self,
201 symop: &SymmetryOperation,
202 ) -> Result<&mut Self, TransformationError> {
203 self.basis.sym_transform_spin_spatial_mut(symop)?;
204 if symop.contains_time_reversal() {
205 self.coefficients.iter_mut().for_each(|v| *v = v.conj());
206 self.complex_conjugated = !self.complex_conjugated;
207 }
208 Ok(self)
209 }
210}
211
212impl<'a, T, SC> SymmetryTransformable
213 for MultiDeterminant<'a, T, EagerBasis<SlaterDeterminant<'a, T, SC>>, SC>
214where
215 T: ComplexFloat + Lapack,
216 SC: StructureConstraint + Hash + Eq + Clone + fmt::Display,
217 SlaterDeterminant<'a, T, SC>: SymmetryTransformable,
218 Self: TimeReversalTransformable,
219 EagerBasis<SlaterDeterminant<'a, T, SC>>: TimeReversalTransformable,
220{
221 fn sym_permute_sites_spatial(
222 &self,
223 symop: &SymmetryOperation,
224 ) -> Result<Permutation<usize>, TransformationError> {
225 self.basis.sym_permute_sites_spatial(symop)
226 }
227}