qsym2/target/orbital/
orbital_projection.rs1use 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}