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::{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
22impl<'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
42impl<'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
61impl<'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 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
80impl<'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
91impl<'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 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}