qsym2/target/orbital/
orbital_projection.rs

1//! Implementation of symmetry projection for molecular orbitals.
2
3use anyhow::{self, format_err};
4use duplicate::duplicate_item;
5use ndarray::Array1;
6use num::{Complex, ToPrimitive};
7
8use super::orbital_analysis::MolecularOrbitalSymmetryOrbit;
9use crate::analysis::Orbit;
10use crate::angmom::spinor_rotation_3d::{SpinConstraint, SpinOrbitCoupled};
11use crate::chartab::chartab_symbols::LinearSpaceSymbol;
12use crate::projection::Projectable;
13use crate::symmetry::symmetry_group::SymmetryGroupProperties;
14use crate::target::orbital::MolecularOrbital;
15
16#[duplicate_item(
17    [
18        dtype_  [ f64 ]
19        sctype_ [ SpinConstraint ]
20        coeffs_ [
21            let c_res = self.generate_orbit_algebra_terms(row).fold(
22                Ok(Array1::zeros(self.origin().coefficients().raw_dim())),
23                |acc_res, item_res| acc_res.and_then(|acc| item_res.and_then(|(chr, mo)| {
24                    let chr_complex = chr.complex_conjugate().complex_value();
25                    if chr_complex.im > self.origin().threshold() {
26                        Err(format_err!("Complex characters encountered. Density projection fails over the reals."))
27                    } else {
28                        Ok(acc + dim_f64 * chr_complex.re / group_order * mo.coefficients())
29                    }
30                })),
31            )
32        ]
33    ]
34    [
35        dtype_  [ Complex<f64> ]
36        sctype_ [ SpinConstraint ]
37        coeffs_ [
38            let c_res = self.generate_orbit_algebra_terms(row).fold(
39                Ok(Array1::zeros(self.origin().coefficients().raw_dim())),
40                |acc_res, item_res| acc_res.and_then(|acc| item_res.map(|(chr, mo)| {
41                    let chr_complex = chr.complex_conjugate().complex_value();
42                    acc + dim_f64 * chr_complex / group_order * mo.coefficients()
43                })),
44            )
45        ]
46    ]
47    [
48        dtype_  [ Complex<f64> ]
49        sctype_ [ SpinOrbitCoupled ]
50        coeffs_ [
51            let c_res = self.generate_orbit_algebra_terms(row).fold(
52                Ok(Array1::zeros(self.origin().coefficients().raw_dim())),
53                |acc_res, item_res| acc_res.and_then(|acc| item_res.map(|(chr, mo)| {
54                    let chr_complex = chr.complex_conjugate().complex_value();
55                    acc + dim_f64 * chr_complex / group_order * mo.coefficients()
56                })),
57            )
58        ]
59    ]
60)]
61impl<'a, G> Projectable<G, MolecularOrbital<'a, dtype_, sctype_>>
62    for MolecularOrbitalSymmetryOrbit<'a, G, dtype_, sctype_>
63where
64    G: SymmetryGroupProperties,
65{
66    type Projected<'p>
67        = Result<MolecularOrbital<'p, dtype_, sctype_>, anyhow::Error>
68    where
69        Self: 'p;
70
71    fn project_onto(&self, row: &G::RowSymbol) -> Self::Projected<'_> {
72        let group_order = self
73            .group()
74            .order()
75            .to_f64()
76            .ok_or_else(|| format_err!("Unable to convert the group order to `f64`."))?;
77        let dim_f64 = row
78            .dimensionality()
79            .to_f64()
80            .ok_or_else(|| format_err!("Unable to convert the degeneracy to `f64`."))?;
81        coeffs_;
82        c_res.and_then(|c| {
83            MolecularOrbital::builder()
84                .structure_constraint(self.origin().structure_constraint.clone())
85                .baos(self.origin().baos.clone())
86                .complex_symmetric(self.origin().complex_symmetric)
87                .complex_conjugated(self.origin().complex_conjugated)
88                .component_index(self.origin().component_index)
89                .mol(self.origin().mol)
90                .coefficients(c)
91                .threshold(self.origin().threshold)
92                .build()
93                .map_err(|err| format_err!(err))
94        })
95    }
96}