extern crate core;
use pyo3::prelude::*;
use crate::connectivity::bonds::{Bond, BondOrder};
use crate::ff::forcefield::Forcefield;
use crate::ff::uff::core::UFF;
use crate::molecule::Molecule;
use crate::utils::IsVeryClose;
mod molecule;
mod atoms;
mod connectivity;
mod ff;
mod io;
mod opt;
mod utils;
mod pairs;
mod coordinates;
mod cli;
use clap::Parser;
use crate::cli::{run, CommandLineArguments};
fn main() { run(CommandLineArguments::parse()) }
#[pymodule]
fn optrs(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PyMoleculeWrapper>()?;
Ok(())
}
#[pyclass (name="Molecule")]
struct PyMoleculeWrapper {
molecule: Molecule,
}
#[pymethods]
impl PyMoleculeWrapper {
#[staticmethod]
fn from_xyz_file(filename: &str) -> Self {
PyMoleculeWrapper { molecule: Molecule::from_xyz_file(filename) }
}
#[staticmethod]
fn from_atomic_symbols(symbols: Vec<&str>) -> Self{
let mol = Molecule::from_atomic_symbols(&symbols);
PyMoleculeWrapper { molecule: mol}
}
fn set_bond_orders(&mut self, bond_orders: Vec<f64>){
if bond_orders.len() != self.molecule.num_atoms().pow(2) {
panic!("Cannot set the bond orders. Must have a flat array with (N_atoms)^2 items in");
}
self.molecule.connectivity.clear();
let mut i = 0;
for (k, bond_order) in bond_orders.iter().enumerate(){
let j = k % self.molecule.num_atoms();
if j <= i || bond_order.is_very_close(&0.){
continue; }
let mut bond = Bond::from_atom_indices(i, j);
bond.order = BondOrder::from_value(bond_order);
self.molecule.connectivity.bonds.insert(bond);
if j == 0{
i += 1;
}
}
self.molecule.add_angles();
self.molecule.add_dihedrals();
self.molecule.add_non_bonded_pairs();
}
fn build_3d(&mut self){
if self.molecule.num_atoms() > 1 && self.molecule.bonds().len() == 0{
panic!("Cannot build a 3d structure without any bonds. \
Consider calling set_bond_orders()");
}
self.molecule.build_3d()
}
pub fn optimise(&mut self) {
self.molecule.optimise(&mut UFF::new(&self.molecule));
}
pub fn write_xyz_file(&self, filename: &str){ self.molecule.write_xyz_file(filename); }
pub fn set_coordinates(&mut self, coordinates: Vec<f64>){
if coordinates.len() != 3*self.molecule.num_atoms(){
panic!("Cannot set the coordinates. Must have a flat list with length 3xN_atoms");
}
for (i, coord) in self.molecule.coordinates.iter_mut().enumerate(){
for (k, _) in ['x', 'y', 'z'].iter().enumerate(){
coord[k] = coordinates[3*i + k].clone();
}
}
}
pub fn generate_connectivty(&mut self){
self.molecule.connectivity.clear();
self.molecule.add_bonds();
self.molecule.add_angles();
self.molecule.add_dihedrals();
self.molecule.add_non_bonded_pairs();
}
}