xtb_model/
raw.rs

1// [[file:../xtb.note::fb6f72a1][fb6f72a1]]
2use super::*;
3
4use std::ptr::null;
5// fb6f72a1 ends here
6
7// [[file:../xtb.note::8cd490ab][8cd490ab]]
8/// XTB Calculation environment
9pub struct XtbEnvironment {
10    /// XTB Calculation environment
11    env: xtb_TEnvironment,
12}
13
14impl XtbEnvironment {
15    /// Create new xtb calculation environment object
16    pub fn new() -> Self {
17        unsafe { assert_eq!(XTB_API_VERSION, xtb_getAPIVersion() as u32) };
18
19        Self {
20            env: unsafe { xtb_newEnvironment() },
21        }
22    }
23
24    /// Check current status of calculation environment.
25    pub fn check_error(&self) -> Result<()> {
26        let ret = unsafe { xtb_checkEnvironment(self.env) };
27        if ret != 0 {
28            // Show and empty error stack
29            unsafe { xtb_showEnvironment(self.env, null()) };
30            bail!("Error occured in the API with return code {}!", ret);
31        }
32        Ok(())
33    }
34
35    /// Set verbosity of calculation output.
36    fn set_verbosity(&self, verbosity: u32) -> Result<()> {
37        unsafe {
38            xtb_setVerbosity(self.env, verbosity as i32);
39        }
40        self.check_error()?;
41        Ok(())
42    }
43
44    /// Set verbosity of calculation output to be verbose
45    pub fn set_output_verbose(&self) -> Result<()> {
46        self.set_verbosity(XTB_VERBOSITY_FULL)
47    }
48
49    /// Set verbosity of calculation output to be minimal
50    pub fn set_output_minimal(&self) -> Result<()> {
51        self.set_verbosity(XTB_VERBOSITY_MINIMAL)
52    }
53
54    /// Set verbosity of calculation output to be muted
55    pub fn set_output_muted(&self) -> Result<()> {
56        self.set_verbosity(XTB_VERBOSITY_MUTED)
57    }
58}
59// 8cd490ab ends here
60
61// [[file:../xtb.note::3bbaae4e][3bbaae4e]]
62/// Molecular structure data
63pub struct XtbMolecule {
64    mol: xtb_TMolecule,
65}
66
67impl XtbMolecule {
68    /// Create new molecular structure data (quantities in Bohr). The molecular
69    /// structure data object has a fixed number of atoms and immutable atomic
70    /// identifiers.
71    pub fn create<'a>(
72        env: &XtbEnvironment,
73        attyp: &[i32],
74        coord: &[f64],
75        charge: f64,
76        uhf: i32,
77        lattice: impl Into<Option<&'a [f64; 9]>>,
78        periodic: impl Into<Option<&'a [bool; 3]>>,
79    ) -> Result<Self> {
80        let mol = unsafe {
81            let natoms = attyp.len() as i32;
82            let env = env.env;
83            let attyp = attyp.as_ptr();
84            let coord = coord.as_ptr();
85            let lattice = lattice.into().map_or(null(), |x| x.as_ptr());
86            let periodic = periodic.into().map_or(null(), |x| x.as_ptr());
87            xtb_newMolecule(env, &natoms, attyp, coord, &charge, &uhf, lattice, periodic)
88        };
89        env.check_error()?;
90        let mol = Self { mol };
91
92        Ok(mol)
93    }
94
95    /// Update coordinates and lattice parameters (quantities in Bohr)
96    pub fn update(&self, env: &XtbEnvironment, coord: &[f64], lattice: Option<&[f64; 9]>) -> Result<()> {
97        unsafe {
98            let env = env.env;
99            let mol = self.mol;
100            let coord = coord.as_ptr();
101            let lattice = lattice.map_or(null(), |x| x.as_ptr());
102            xtb_updateMolecule(env, mol, coord, lattice);
103        }
104        env.check_error()?;
105
106        Ok(())
107    }
108}
109// 3bbaae4e ends here
110
111// [[file:../xtb.note::e737b33d][e737b33d]]
112/// Possible parametrisations for the Calculator.
113#[derive(Clone, Debug, Copy, PartialEq)]
114pub enum XtbMethod {
115    /// GFN2-xTB
116    GFN2xTB,
117    /// GFN1-xTB
118    GFN1xTB,
119    /// GFN0-xTB
120    GFN0xTB,
121    /// GFN0-FF
122    GFNFF,
123}
124
125/// XTB single point calculator
126pub struct XtbCalculator {
127    calc: xtb_TCalculator,
128}
129
130impl XtbCalculator {
131    /// Create new calculator object
132    pub fn new() -> Self {
133        Self {
134            calc: unsafe { xtb_newCalculator() },
135        }
136    }
137
138    /// Load parametrization of GFN-xTB method `method`.
139    pub fn load_parametrization(&self, mol: &XtbMolecule, env: &XtbEnvironment, method: XtbMethod) -> Result<()> {
140        unsafe {
141            let calc = self.calc;
142            let mol = mol.mol;
143            let env = env.env;
144            match method {
145                XtbMethod::GFNFF => xtb_loadGFNFF(env, mol, calc, std::ptr::null_mut()),
146                XtbMethod::GFN0xTB => xtb_loadGFN0xTB(env, mol, calc, std::ptr::null_mut()),
147                XtbMethod::GFN1xTB => xtb_loadGFN1xTB(env, mol, calc, std::ptr::null_mut()),
148                XtbMethod::GFN2xTB => xtb_loadGFN2xTB(env, mol, calc, std::ptr::null_mut()),
149                _ => unimplemented!(),
150            }
151        }
152        env.check_error()?;
153        Ok(())
154    }
155
156    /// Set maximum number of iterations for self-consistent TB calculators. Set
157    /// maximum number of iterations for self-consistent charge methods, values
158    /// smaller than one will be silently ignored by the API. Failing to
159    /// converge in a given number of cycles is not necessarily reported as an
160    /// error by the API.
161    pub fn set_max_iterations(&self, env: &XtbEnvironment, n: usize) {
162        unsafe {
163            xtb_setMaxIter(env.env, self.calc, n as i32);
164        }
165    }
166
167    /// Set electronic temperature for level filling in tight binding calculators in K
168    pub fn set_electronic_temperature(&self, env: &XtbEnvironment, temp: f64) {
169        unsafe {
170            xtb_setElectronicTemp(env.env, self.calc, temp);
171        }
172    }
173
174    /// Set numerical accuracy of calculator in the range of 1000 to 0.0001
175    pub fn set_accuracy(&self, env: &XtbEnvironment, acc: f64) {
176        unsafe {
177            xtb_setAccuracy(env.env, self.calc, acc);
178        }
179    }
180
181    /// Perform singlepoint calculation. Note that the a previous result is
182    /// overwritten by default.
183    pub fn single_point(&self, mol: &XtbMolecule, env: &XtbEnvironment) -> Result<XtbResults> {
184        let mut res = XtbResults::new();
185        unsafe {
186            let calc = self.calc;
187            let mol = mol.mol;
188            let res = res.res;
189            let env = env.env;
190            xtb_singlepoint(env, mol, calc, res);
191        }
192        env.check_error()?;
193        Ok(res)
194    }
195}
196// e737b33d ends here
197
198// [[file:../xtb.note::1e3dd6ef][1e3dd6ef]]
199/// XTB singlepoint results object
200pub struct XtbResults {
201    res: xtb_TResults,
202}
203
204impl XtbResults {
205    /// Create new singlepoint results object
206    fn new() -> Self {
207        Self {
208            res: unsafe { xtb_newResults() },
209        }
210    }
211
212    /// Get singlepoint energy in Hartree
213    pub fn get_energy(&self, env: &XtbEnvironment) -> Result<f64> {
214        let mut energy = std::f64::NAN;
215        unsafe {
216            xtb_getEnergy(env.env, self.res, &mut energy);
217        }
218        env.check_error()?;
219        Ok(energy)
220    }
221
222    /// Get dipole in e Bohr
223    pub fn get_dipole(&self, env: &XtbEnvironment) -> Result<[f64; 3]> {
224        let mut dipole = [std::f64::NAN; 3];
225        unsafe {
226            xtb_getDipole(env.env, self.res, dipole.as_mut_ptr());
227        }
228        env.check_error()?;
229        Ok(dipole)
230    }
231
232    /// Get gradient in Hartree / Bohr
233    pub fn get_gradient(&self, env: &XtbEnvironment, gradient: &mut [f64]) -> Result<()> {
234        unsafe {
235            xtb_getGradient(env.env, self.res, gradient.as_mut_ptr());
236        }
237        env.check_error()?;
238        Ok(())
239    }
240
241    /// Query singlepoint results object for bond orders
242    pub fn get_bond_orders(&self, env: &XtbEnvironment, bond_orders: &mut [f64]) -> Result<()> {
243        unsafe {
244            xtb_getBondOrders(env.env, self.res, bond_orders.as_mut_ptr());
245        }
246        env.check_error()?;
247        Ok(())
248    }
249
250    /// Query singlepoint results object for partial charges in e
251    pub fn get_charges(&self, env: &XtbEnvironment, charges: &mut [f64]) -> Result<()> {
252        unsafe {
253            xtb_getCharges(env.env, self.res, charges.as_mut_ptr());
254        }
255        env.check_error()?;
256        Ok(())
257    }
258
259    /// Query singlepoint results object for virial in Hartree
260    pub fn get_virial(&self, env: &XtbEnvironment, virial: &mut [f64]) -> Result<()> {
261        unsafe {
262            xtb_getVirial(env.env, self.res, virial.as_mut_ptr());
263        }
264        env.check_error()?;
265        Ok(())
266    }
267
268    /// Query singlepoint results object for the number of basis functions
269    pub fn get_nao(&self, env: &XtbEnvironment) -> Result<usize> {
270        let mut nao = 0;
271        unsafe {
272            xtb_getNao(env.env, self.res, &mut nao);
273        }
274        env.check_error()?;
275        Ok(nao as usize)
276    }
277
278    /// Query singlepoint results object for orbital energies in Hartree [nao]
279    pub fn get_orbital_eigenvalues(&self, env: &XtbEnvironment, emo: &mut [f64]) -> Result<()> {
280        unsafe {
281            xtb_getOrbitalEigenvalues(env.env, self.res, emo.as_mut_ptr());
282        }
283        env.check_error()?;
284        Ok(())
285    }
286
287    /// Query singlepoint results object for occupation numbers [nao]
288    pub fn get_orbital_occupations(&self, env: &XtbEnvironment, focc: &mut [f64]) -> Result<()> {
289        unsafe {
290            xtb_getOrbitalOccupations(env.env, self.res, focc.as_mut_ptr());
291        }
292        env.check_error()?;
293        Ok(())
294    }
295
296    /// Query singlepoint results object for orbital coefficients [nao][nao]
297    pub fn get_orbital_coefficients(&self, env: &XtbEnvironment, forb: &mut [f64]) -> Result<()> {
298        unsafe {
299            xtb_getOrbitalCoefficients(env.env, self.res, forb.as_mut_ptr());
300        }
301        env.check_error()?;
302        Ok(())
303    }
304}
305// 1e3dd6ef ends here
306
307// [[file:../xtb.note::7d8b4594][7d8b4594]]
308macro_rules! impl_xtb_drop {
309    ($obj:ident, $xtb_del:ident, $res:ident) => {
310        impl Drop for $obj {
311            fn drop(&mut self) {
312                if !self.$res.is_null() {
313                    unsafe { $xtb_del(&mut self.$res) }
314                }
315                assert!(self.$res.is_null());
316            }
317        }
318    };
319}
320
321impl_xtb_drop!(XtbEnvironment, xtb_delEnvironment, env);
322impl_xtb_drop!(XtbMolecule, xtb_delMolecule, mol);
323impl_xtb_drop!(XtbResults, xtb_delResults, res);
324impl_xtb_drop!(XtbCalculator, xtb_delCalculator, calc);
325// 7d8b4594 ends here