1use std::collections::{HashSet, VecDeque};
5
6use anyhow::format_err;
7use nalgebra::Vector3;
8use ndarray::Array2;
9use num_complex::Complex;
10
11use crate::angmom::spinor_rotation_3d::SpinOrbitCoupled;
12use crate::group::GroupProperties;
13use crate::permutation::Permutation;
14use crate::symmetry::symmetry_element::{RotationGroup, SymmetryElement, SymmetryOperation, TRROT};
15use crate::symmetry::symmetry_element_order::ElementOrder;
16use crate::symmetry::symmetry_transformation::{
17 ComplexConjugationTransformable, DefaultTimeReversalTransformable, SpatialUnitaryTransformable,
18 SpinUnitaryTransformable, SymmetryTransformable, TimeReversalTransformable,
19 TransformationError,
20};
21use crate::target::determinant::SlaterDeterminant;
22use crate::target::noci::basis::{EagerBasis, OrbitBasis};
23
24impl<'g, G, I> SpatialUnitaryTransformable for OrbitBasis<'g, G, I>
34where
35 G: GroupProperties + Clone,
36 I: SpatialUnitaryTransformable,
37{
38 fn transform_spatial_mut(
39 &mut self,
40 _: &Array2<f64>,
41 _: Option<&Permutation<usize>>,
42 ) -> Result<&mut Self, TransformationError> {
43 Err(TransformationError("Transforming an orbit basis by an arbitrary spatial transformation matrix is not supported.".to_string()))
44 }
45}
46
47impl<'g, G, I> SpinUnitaryTransformable for OrbitBasis<'g, G, I>
51where
52 G: GroupProperties + Clone,
53 I: SpinUnitaryTransformable,
54{
55 fn transform_spin_mut(
56 &mut self,
57 _: &Array2<Complex<f64>>,
58 ) -> Result<&mut Self, TransformationError> {
59 Err(TransformationError("Transforming an orbit basis by an arbitrary spin transformation matrix is not supported.".to_string()))
60 }
61}
62
63impl<'g, G, I> ComplexConjugationTransformable for OrbitBasis<'g, G, I>
68where
69 G: GroupProperties + Clone,
70 I: ComplexConjugationTransformable,
71{
72 fn transform_cc_mut(&mut self) -> Result<&mut Self, TransformationError> {
74 Err(TransformationError(
75 "Transforming an orbit basis by an explicit complex conjugation is not supported."
76 .to_string(),
77 ))
78 }
79}
80
81impl<'g, G, I> DefaultTimeReversalTransformable for OrbitBasis<'g, G, I>
85where
86 G: GroupProperties + Clone,
87 I: DefaultTimeReversalTransformable,
88{
89}
90
91impl<'a, 'g, G> TimeReversalTransformable
98 for OrbitBasis<'g, G, SlaterDeterminant<'a, Complex<f64>, SpinOrbitCoupled>>
99where
100 G: GroupProperties<GroupElement = SymmetryOperation> + Clone,
101{
102 fn transform_timerev_mut(&mut self) -> Result<&mut Self, TransformationError> {
103 let t_element = SymmetryElement::builder()
104 .threshold(1e-14)
105 .proper_order(ElementOrder::Int(1))
106 .proper_power(1)
107 .raw_axis(Vector3::new(0.0, 0.0, 1.0))
108 .kind(TRROT)
109 .rotation_group(RotationGroup::SU2(true))
110 .build()
111 .map_err(|err| TransformationError(err.to_string()))?;
112 let t = SymmetryOperation::builder()
113 .generating_element(t_element)
114 .power(1)
115 .build()
116 .map_err(|err| TransformationError(err.to_string()))?;
117 if let Some(prefactors) = self.prefactors.as_mut() {
118 prefactors.push_front((t.clone(), |g, item| {
119 item.sym_transform_spin_spatial(g)
120 .map_err(|err| format_err!(err))
121 }));
122 } else {
123 let mut v = VecDeque::<(
124 G::GroupElement,
125 fn(
126 &G::GroupElement,
127 &SlaterDeterminant<'a, Complex<f64>, SpinOrbitCoupled>,
128 )
129 -> Result<SlaterDeterminant<'a, Complex<f64>, SpinOrbitCoupled>, anyhow::Error>,
130 )>::new();
131 v.push_front((t.clone(), |g, item| {
132 item.sym_transform_spin_spatial(g)
133 .map_err(|err| format_err!(err))
134 }));
135 self.prefactors = Some(v);
136 }
137 Ok(self)
138 }
139}
140
141impl<'g, G, I> SymmetryTransformable for OrbitBasis<'g, G, I>
145where
146 G: GroupProperties<GroupElement = SymmetryOperation> + Clone,
147 I: SymmetryTransformable,
148 OrbitBasis<'g, G, I>: TimeReversalTransformable,
149{
150 fn sym_permute_sites_spatial(
151 &self,
152 symop: &SymmetryOperation,
153 ) -> Result<Permutation<usize>, TransformationError> {
154 let mut perms = self
155 .origins
156 .iter()
157 .map(|origin| origin.sym_permute_sites_spatial(symop))
158 .collect::<Result<HashSet<_>, _>>()?;
159 if perms.len() == 1 {
160 perms.drain().next().ok_or(TransformationError(
161 "Unable to retrieve the site permutation.".to_string(),
162 ))
163 } else {
164 Err(TransformationError(
165 "Mismatched site permutations across the origins.".to_string(),
166 ))
167 }
168 }
169
170 fn sym_transform_spatial_mut(
174 &mut self,
175 symop: &SymmetryOperation,
176 ) -> Result<&mut Self, TransformationError> {
177 if let Some(prefactors) = self.prefactors.as_mut() {
178 prefactors.push_front((symop.clone(), |g, item| {
179 item.sym_transform_spatial(g)
180 .map_err(|err| format_err!(err))
181 }));
182 } else {
183 let mut v = VecDeque::<(
184 G::GroupElement,
185 fn(&G::GroupElement, &I) -> Result<I, anyhow::Error>,
186 )>::new();
187 v.push_front((symop.clone(), |g, item| {
188 item.sym_transform_spatial(g)
189 .map_err(|err| format_err!(err))
190 }));
191 self.prefactors = Some(v);
192 }
193 Ok(self)
194 }
195
196 fn sym_transform_spatial_with_spintimerev_mut(
197 &mut self,
198 symop: &SymmetryOperation,
199 ) -> Result<&mut Self, TransformationError> {
200 if let Some(prefactors) = self.prefactors.as_mut() {
201 prefactors.push_front((symop.clone(), |g, item| {
202 item.sym_transform_spatial_with_spintimerev(g)
203 .map_err(|err| format_err!(err))
204 }));
205 } else {
206 let mut v = VecDeque::<(
207 G::GroupElement,
208 fn(&G::GroupElement, &I) -> Result<I, anyhow::Error>,
209 )>::new();
210 v.push_front((symop.clone(), |g, item| {
211 item.sym_transform_spatial_with_spintimerev(g)
212 .map_err(|err| format_err!(err))
213 }));
214 self.prefactors = Some(v);
215 }
216 Ok(self)
217 }
218
219 fn sym_transform_spin_mut(
220 &mut self,
221 symop: &SymmetryOperation,
222 ) -> Result<&mut Self, TransformationError> {
223 if let Some(prefactors) = self.prefactors.as_mut() {
224 prefactors.push_front((symop.clone(), |g, item| {
225 item.sym_transform_spin(g).map_err(|err| format_err!(err))
226 }));
227 } else {
228 let mut v = VecDeque::<(
229 G::GroupElement,
230 fn(&G::GroupElement, &I) -> Result<I, anyhow::Error>,
231 )>::new();
232 v.push_front((symop.clone(), |g, item| {
233 item.sym_transform_spin(g).map_err(|err| format_err!(err))
234 }));
235 self.prefactors = Some(v);
236 }
237 Ok(self)
238 }
239
240 fn sym_transform_spin_spatial_mut(
241 &mut self,
242 symop: &SymmetryOperation,
243 ) -> Result<&mut Self, TransformationError> {
244 if let Some(prefactors) = self.prefactors.as_mut() {
245 prefactors.push_front((symop.clone(), |g, item| {
246 item.sym_transform_spin_spatial(g)
247 .map_err(|err| format_err!(err))
248 }));
249 } else {
250 let mut v = VecDeque::<(
251 G::GroupElement,
252 fn(&G::GroupElement, &I) -> Result<I, anyhow::Error>,
253 )>::new();
254 v.push_front((symop.clone(), |g, item| {
255 item.sym_transform_spin_spatial(g)
256 .map_err(|err| format_err!(err))
257 }));
258 self.prefactors = Some(v);
259 }
260 Ok(self)
261 }
262}
263
264impl<I> SpatialUnitaryTransformable for EagerBasis<I>
274where
275 I: SpatialUnitaryTransformable,
276{
277 fn transform_spatial_mut(
278 &mut self,
279 rmat: &Array2<f64>,
280 perm: Option<&Permutation<usize>>,
281 ) -> Result<&mut Self, TransformationError> {
282 self.elements
283 .iter_mut()
284 .map(|origin| origin.transform_spatial_mut(rmat, perm))
285 .collect::<Result<Vec<_>, _>>()?;
286 Ok(self)
287 }
288}
289
290impl<I> SpinUnitaryTransformable for EagerBasis<I>
294where
295 I: SpinUnitaryTransformable,
296{
297 fn transform_spin_mut(
298 &mut self,
299 dmat: &Array2<Complex<f64>>,
300 ) -> Result<&mut Self, TransformationError> {
301 self.elements
302 .iter_mut()
303 .map(|origin| origin.transform_spin_mut(dmat))
304 .collect::<Result<Vec<_>, _>>()?;
305 Ok(self)
306 }
307}
308
309impl<I> ComplexConjugationTransformable for EagerBasis<I>
314where
315 I: ComplexConjugationTransformable,
316{
317 fn transform_cc_mut(&mut self) -> Result<&mut Self, TransformationError> {
319 for origin in self.elements.iter_mut() {
320 origin.transform_cc_mut()?;
321 }
322 Ok(self)
323 }
324}
325
326impl<I> DefaultTimeReversalTransformable for EagerBasis<I> where
330 I: DefaultTimeReversalTransformable + Clone
331{
332}
333
334impl<'a> TimeReversalTransformable
341 for EagerBasis<SlaterDeterminant<'a, Complex<f64>, SpinOrbitCoupled>>
342{
343 fn transform_timerev_mut(&mut self) -> Result<&mut Self, TransformationError> {
344 for det in self.elements.iter_mut() {
345 det.transform_timerev_mut()?;
346 }
347 Ok(self)
348 }
349}
350
351impl<I> SymmetryTransformable for EagerBasis<I>
355where
356 I: SymmetryTransformable,
357 EagerBasis<I>: TimeReversalTransformable,
358{
359 fn sym_permute_sites_spatial(
360 &self,
361 symop: &SymmetryOperation,
362 ) -> Result<Permutation<usize>, TransformationError> {
363 let mut perms = self
364 .elements
365 .iter()
366 .map(|origin| origin.sym_permute_sites_spatial(symop))
367 .collect::<Result<HashSet<_>, _>>()?;
368 if perms.len() == 1 {
369 perms.drain().next().ok_or(TransformationError(
370 "Unable to retrieve the site permutation.".to_string(),
371 ))
372 } else {
373 Err(TransformationError(
374 "Mismatched site permutations across the elements in the basis.".to_string(),
375 ))
376 }
377 }
378}