Skip to main content

qsym2/target/noci/
basis_orbit.rs

1//! Implementation of orbit behaviours for bases.
2
3use anyhow::Context;
4use derive_builder::Builder;
5
6use crate::{
7    analysis::{Orbit, OrbitIterator},
8    group::GroupProperties,
9    symmetry::{
10        symmetry_group::SymmetryGroupProperties,
11        symmetry_transformation::{SymmetryTransformable, SymmetryTransformationKind},
12    },
13    target::noci::basis::Basis,
14};
15
16// ==================
17// BasisSymmetryOrbit
18// ==================
19
20// -----------------
21// Struct definition
22// -----------------
23
24/// Structure to manage symmetry orbits (*i.e.* orbits generated by symmetry groups) of
25/// bases.
26#[derive(Builder, Clone)]
27pub struct BasisSymmetryOrbit<'a, 'g, G, B>
28where
29    G: GroupProperties,
30    B: Basis,
31{
32    /// The generating symmetry group.
33    group: &'g G,
34
35    /// The origin basis of the orbit.
36    origin: &'a B,
37
38    /// The kind of transformation determining the way the symmetry operations in `group` act on
39    /// [`Self::origin`].
40    symmetry_transformation_kind: SymmetryTransformationKind,
41}
42
43// ----------------------------
44// Struct method implementation
45// ----------------------------
46
47impl<'a, 'g, G, B> BasisSymmetryOrbit<'a, 'g, G, B>
48where
49    G: GroupProperties + Clone,
50    B: Basis + Clone,
51{
52    /// Returns a builder for constructing a new basis symmetry orbit.
53    pub fn builder() -> BasisSymmetryOrbitBuilder<'a, 'g, G, B> {
54        BasisSymmetryOrbitBuilder::default()
55    }
56
57    /// Returns the origin of the basis symmetry orbit.
58    pub fn origin(&self) -> &B {
59        self.origin
60    }
61
62    /// Returns the symmetry transformation kind.
63    pub fn symmetry_transformation_kind(&self) -> &SymmetryTransformationKind {
64        &self.symmetry_transformation_kind
65    }
66}
67
68// ---------------------
69// Trait implementations
70// ---------------------
71
72// ~~~~~
73// Orbit
74// ~~~~~
75
76impl<'a, 'g, G, B> Orbit<G, B> for BasisSymmetryOrbit<'a, 'g, G, B>
77where
78    G: SymmetryGroupProperties,
79    B: Basis + Clone + SymmetryTransformable,
80{
81    type OrbitIter = OrbitIterator<'a, G, B>;
82
83    fn group(&self) -> &G {
84        self.group
85    }
86
87    fn origin(&self) -> &B {
88        self.origin
89    }
90
91    fn iter(&self) -> Self::OrbitIter {
92        OrbitIterator::new(
93            self.group,
94            self.origin,
95            match self.symmetry_transformation_kind {
96                SymmetryTransformationKind::Spatial => |op, basis| {
97                    basis.sym_transform_spatial(op).with_context(|| {
98                        format!("Unable to apply `{op}` spatially on the origin basis")
99                    })
100                },
101                SymmetryTransformationKind::SpatialWithSpinTimeReversal => |op, basis| {
102                    basis.sym_transform_spatial_with_spintimerev(op).with_context(|| {
103                        format!("Unable to apply `{op}` spatially (with spin-including time reversal) on the origin basis")
104                    })
105                },
106                SymmetryTransformationKind::Spin => |op, basis| {
107                    basis.sym_transform_spin(op).with_context(|| {
108                        format!("Unable to apply `{op}` spin-wise on the origin basis")
109                    })
110                },
111                SymmetryTransformationKind::SpinSpatial => |op, basis| {
112                    basis.sym_transform_spin_spatial(op).with_context(|| {
113                        format!("Unable to apply `{op}` spin-spatially on the origin basis")
114                    })
115                },
116            },
117        )
118    }
119}