qsym2/interfaces/input/
mod.rs1use std::path::PathBuf;
4
5use anyhow::{self, bail, Context};
6use log;
7use serde::{Deserialize, Serialize};
8
9use crate::auxiliary::molecule::Molecule;
10use crate::drivers::molecule_symmetrisation_bootstrap::MoleculeSymmetrisationBootstrapDriver;
11use crate::drivers::representation_analysis::angular_function::AngularFunctionRepAnalysisParams;
12use crate::drivers::symmetry_group_detection::{
13 SymmetryGroupDetectionDriver, SymmetryGroupDetectionParams,
14};
15use crate::drivers::QSym2Driver;
16use crate::interfaces::input::analysis::{
17 AnalysisTarget, SlaterDeterminantSource, SlaterDeterminantSourceHandle,
18};
19#[cfg(feature = "qchem")]
20use crate::interfaces::input::analysis::{
21 VibrationalCoordinateSource, VibrationalCoordinateSourceHandle,
22};
23use crate::interfaces::InputHandle;
24use crate::io::format::qsym2_output;
25#[allow(unused_imports)]
26use crate::io::{read_qsym2_binary, QSym2FileType};
27
28pub mod analysis;
29pub mod ao_basis;
30
31#[cfg(test)]
32#[path = "input_tests.rs"]
33mod input_tests;
34
35#[derive(Clone, Serialize, Deserialize)]
46pub enum SymmetryGroupDetectionInputKind {
47 Parameters(SymmetryGroupDetectionParams),
50
51 FromFile(PathBuf),
55}
56
57impl Default for SymmetryGroupDetectionInputKind {
58 fn default() -> Self {
59 SymmetryGroupDetectionInputKind::Parameters(SymmetryGroupDetectionParams::default())
60 }
61}
62
63#[derive(Clone, Serialize, Deserialize)]
70pub struct Input {
71 pub symmetry_group_detection: SymmetryGroupDetectionInputKind,
75
76 pub analysis_targets: Vec<AnalysisTarget>,
78}
79
80impl InputHandle for Input {
81 fn handle(&self) -> Result<(), anyhow::Error> {
83 let pd_params_inp = &self.symmetry_group_detection;
84 let mut afa_params = AngularFunctionRepAnalysisParams::default();
85 self.analysis_targets.iter().map(|target| match target {
86 AnalysisTarget::MolecularSymmetry {
87 xyz,
88 symmetrisation,
89 } => {
90 qsym2_output!("");
91 log::debug!("Analysis target: Molecular symmetry");
92 let mol = Molecule::from_xyz(xyz, 1e-7);
93 if let Some(msb_params) = symmetrisation.as_ref() {
94 log::debug!("Performing molecule symmetrisation by bootstrapping...");
95 let mut msb_driver = MoleculeSymmetrisationBootstrapDriver::builder()
96 .parameters(msb_params)
97 .molecule(&mol)
98 .build()
99 .with_context(|| "Unable to construct a molecule symmetrisation by bootstrapping driver while handling molecular symmetry analysis target")?;
100 msb_driver
101 .run()
102 .with_context(|| "Unable to execute the molecule symmetrisation by bootstrapping driver successfully while handling molecular symmetry analysis target")?;
103 log::debug!("Performing molecule symmetrisation by bootstrapping... Done.");
104
105 qsym2_output!("Performing symmetry-group detection on the symmetrised system...");
106 qsym2_output!("");
107 let pd_params = match pd_params_inp {
108 SymmetryGroupDetectionInputKind::Parameters(pd_params) => pd_params,
109 SymmetryGroupDetectionInputKind::FromFile(_) => {
110 bail!(
111 "It is pointless to provide a pre-calculated symmetry-group \
112 detection result when only symmetry-group detection is required."
113 )
114 }
115 };
116 log::debug!(
117 "Molecular symmetry group will be identified based on specified parameters."
118 );
119 let symmol = &msb_driver.result()?.symmetrised_molecule;
120 let mut pd_driver = SymmetryGroupDetectionDriver::builder()
121 .parameters(pd_params)
122 .molecule(Some(symmol))
123 .build()
124 .with_context(|| "Unable to construct a symmetry-group detection driver while handling molecular symmetry analysis target")?;
125 let pd_res = pd_driver
126 .run()
127 .with_context(|| "Unable to execute the symmetry-group detection driver successfully while handling molecular symmetry analysis target");
128 qsym2_output!("Performing symmetry-group detection on the symmetrised system... Done.");
129 qsym2_output!("");
130 pd_res
131 } else {
132 log::debug!("Performing symmetry-group detection without symmetrisation...");
133 let pd_params = match pd_params_inp {
134 SymmetryGroupDetectionInputKind::Parameters(pd_params) => pd_params,
135 SymmetryGroupDetectionInputKind::FromFile(_) => {
136 bail!(
137 "It is pointless to provide a pre-calculated symmetry-group \
138 detection result when only symmetry-group detection is required."
139 )
140 }
141 };
142 log::debug!(
143 "Molecular symmetry group will be identified based on specified parameters."
144 );
145 let mut pd_driver = SymmetryGroupDetectionDriver::builder()
146 .parameters(pd_params)
147 .xyz(Some(xyz.into()))
148 .build()
149 .with_context(|| "Unable to construct a symmetry-group detection driver while handling molecular symmetry analysis target")?;
150 let pd_res = pd_driver
151 .run()
152 .with_context(|| "Unable to execute the symmetry-group detection driver successfully while handling molecular symmetry analysis target");
153 log::debug!("Performing symmetry-group detection without symmetrisation... Done.");
154 pd_res
155 }
156 }
157 AnalysisTarget::RealSlaterDeterminant(sd_control) => {
158 qsym2_output!("");
159 log::debug!("Analysis target: Slater determinant");
160 let sd_source = &sd_control.source;
161 let sda_params = &sd_control.control;
162 afa_params.linear_independence_threshold = sda_params.linear_independence_threshold;
163 afa_params.integrality_threshold = sda_params.integrality_threshold;
164 match sd_source {
165 #[cfg(feature = "qchem")]
166 SlaterDeterminantSource::QChemArchive(qchemarchive_sd_source) => {
167 log::debug!("Slater determinant source: Q-Chem archive");
168 qchemarchive_sd_source
169 .sd_source_handle(&pd_params_inp, &afa_params, &sda_params)
170 .map(|_| ())
171 }
172 SlaterDeterminantSource::Binaries(binaries_sd_source) => {
173 log::debug!("Slater determinant source: binary files");
174 binaries_sd_source
175 .sd_source_handle(&pd_params_inp, &afa_params, &sda_params)
176 .map(|_| ())
177 }
178 }
179 }
180 #[cfg(feature = "qchem")]
181 AnalysisTarget::VibrationalCoordinates(vc_control) => {
182 qsym2_output!("");
183 log::debug!("Analysis target: vibrational coordinates");
184 let vc_source = &vc_control.source;
185 let vca_params = &vc_control.control;
186 afa_params.linear_independence_threshold = vca_params.linear_independence_threshold;
187 afa_params.integrality_threshold = vca_params.integrality_threshold;
188 match vc_source {
189 VibrationalCoordinateSource::QChemArchive(qchemarchive_vc_source) => {
190 log::debug!("Vibrational coordinate source: Q-Chem archive");
191 qchemarchive_vc_source
192 .vc_source_handle(&pd_params_inp, &afa_params, &vca_params)
193 .map(|_| ())
194 }
195 }
196 }
197 }).collect::<Result<_, _>>()
198 }
199}
200
201impl Default for Input {
202 fn default() -> Self {
203 Input {
204 symmetry_group_detection: SymmetryGroupDetectionInputKind::default(),
205 analysis_targets: AnalysisTarget::all_default(),
206 }
207 }
208}