qsym2/target/determinant/
determinant_projection.rs

1//! Implementation of symmetry projection for Slater determinants.
2
3use anyhow::{self, format_err};
4use duplicate::duplicate_item;
5use ndarray::Array1;
6use num::{Complex, ToPrimitive};
7
8use crate::analysis::Orbit;
9use crate::angmom::spinor_rotation_3d::{SpinConstraint, SpinOrbitCoupled};
10use crate::chartab::chartab_symbols::LinearSpaceSymbol;
11use crate::projection::Projectable;
12use crate::symmetry::symmetry_group::SymmetryGroupProperties;
13use crate::target::noci::basis::OrbitBasis;
14use crate::target::noci::multideterminant::MultiDeterminant;
15
16use super::SlaterDeterminant;
17use super::determinant_analysis::SlaterDeterminantSymmetryOrbit;
18
19#[duplicate_item(
20    [
21        dtype_  [ f64 ]
22        sctype_ [ SpinConstraint ]
23        coeffs_ [
24            let coeffs = self
25                .generate_orbit_algebra_terms(row)
26                .map(|item_res| item_res.and_then(|(chr, _)| {
27                    let chr_complex = chr.complex_conjugate().complex_value();
28                    if chr_complex.im > self.origin().threshold() {
29                        Err(format_err!("Complex characters encountered. Slater determinant projection fails over the reals."))
30                    } else {
31                        Ok(dim_f64 / group_order * chr_complex.re)
32                    }
33                }))
34                .collect::<Result<Vec<_>, _>>()?
35        ]
36    ]
37    [
38        dtype_  [ Complex<f64> ]
39        sctype_ [ SpinConstraint ]
40        coeffs_ [
41            let coeffs = self
42                .generate_orbit_algebra_terms(row)
43                .map(|item_res| {
44                    item_res
45                        .map(|(chr, _)| dim_f64 / group_order * chr.complex_conjugate().complex_value())
46                })
47                .collect::<Result<Vec<_>, _>>()?
48        ]
49    ]
50    [
51        dtype_  [ Complex<f64> ]
52        sctype_ [ SpinOrbitCoupled ]
53        coeffs_ [
54            let coeffs = self
55                .generate_orbit_algebra_terms(row)
56                .map(|item_res| {
57                    item_res
58                        .map(|(chr, _)| dim_f64 / group_order * chr.complex_conjugate().complex_value())
59                })
60                .collect::<Result<Vec<_>, _>>()?
61        ]
62    ]
63)]
64impl<'a, G> Projectable<G, SlaterDeterminant<'a, dtype_, sctype_>>
65    for SlaterDeterminantSymmetryOrbit<'a, G, dtype_, sctype_>
66where
67    G: SymmetryGroupProperties + Clone,
68{
69    type Projected<'p>
70        = Result<
71        MultiDeterminant<
72            'p,
73            dtype_,
74            OrbitBasis<'p, G, SlaterDeterminant<'p, dtype_, sctype_>>,
75            sctype_,
76        >,
77        anyhow::Error,
78    >
79    where
80        Self: 'p;
81
82    fn project_onto(&self, row: &G::RowSymbol) -> Self::Projected<'_> {
83        let group_order = self
84            .group()
85            .order()
86            .to_f64()
87            .ok_or_else(|| format_err!("Unable to convert the group order to `f64`."))?;
88        let dim_f64 = row
89            .dimensionality()
90            .to_f64()
91            .ok_or_else(|| format_err!("Unable to convert the degeneracy to `f64`."))?;
92
93        let orbit_basis = OrbitBasis::builder()
94            .origins(vec![self.origin().clone()])
95            .group(self.group())
96            .action(self.action())
97            .prefactors(None)
98            .build()
99            .map_err(|err| format_err!(err))?;
100
101        coeffs_;
102
103        MultiDeterminant::builder()
104            .basis(orbit_basis)
105            .coefficients(Array1::from_vec(coeffs))
106            .threshold(self.origin().threshold())
107            .build()
108            .map_err(|err| format_err!(err))
109    }
110}