def get_energy(self,coords,multiplicity,state,runtype=None): if self.hasRanForCurrentCoords==False or (coords != self.currentCoords).any(): self.currentCoords = coords.copy() geom = manage_xyz.np_to_xyz(self.geom,self.currentCoords) self.runall(geom,runtype) Energy = self.Energies[(multiplicity,state)] if Energy.unit=="Hartree": return Energy.value*units.KCAL_MOL_PER_AU elif Energy.unit=='kcal/mol': return Energy.value elif Energy.unit==None: return Energy.value
def get_coupling(self,coords,multiplicity,state1,state2,frozen_atoms=None): if self.hasRanForCurrentCoords==False or (coords != self.currentCoords).any(): self.currentCoords = coords.copy() geom = manage_xyz.np_to_xyz(self.geom,self.currentCoords) self.runall(geom) Coupling = self.Couplings[(state1,state2)] if Coupling.value is not None: if frozen_atoms is not None: for a in [3*i for i in frozen_atoms]: Coupling.value[a:a+3,0]=0. if Coupling.unit=="Hartree/Bohr": return Coupling.value *units.ANGSTROM_TO_AU #Ha/bohr*bohr/ang=Ha/ang else: raise NotImplementedError else: return None
def get_gradient(self,coords,multiplicity,state,frozen_atoms=None): if self.hasRanForCurrentCoords==False or (coords != self.currentCoords).any(): self.currentCoords = coords.copy() geom = manage_xyz.np_to_xyz(self.geom,self.currentCoords) self.runall(geom) Gradient = self.Gradients[(multiplicity,state)] if Gradient.value is not None: if frozen_atoms is not None: for a in frozen_atoms: Gradient.value[a, :]= 0. if Gradient.unit=="Hartree/Bohr": return Gradient.value *units.ANGSTROM_TO_AU #Ha/bohr*bohr/ang=Ha/ang elif Gradient.unit=="kcal/mol/Angstrom": return Gradient.value *units.KCAL_MOL_TO_AU #kcalmol/A*Ha/kcalmol=Ha/ang else: raise NotImplementedError else: return None
def eckart_frame( geom, masses, ): """ Moves the molecule to the Eckart frame Params: geom ((natoms,4) np.ndarray) - Contains atom symbol and xyz coordinates masses ((natoms) np.ndarray) - Atom masses Returns: COM ((3), np.ndarray) - Molecule center of mess L ((3), np.ndarray) - Principal moments O ((3,3), np.ndarray)- Principle axes of inertial tensor geom2 ((natoms,4 np.ndarray) - Contains new geometry (atom symbol and xyz coordinates) """ # Center of mass COM = np.sum(manage_xyz.xyz_to_np(geom) * np.outer(masses, [1.0] * 3), 0) / np.sum(masses) # Inertial tensor I = np.zeros((3, 3)) for atom, mass in zip(geom, masses): I[0, 0] += mass * (atom[1] - COM[0]) * (atom[1] - COM[0]) I[0, 1] += mass * (atom[1] - COM[0]) * (atom[2] - COM[1]) I[0, 2] += mass * (atom[1] - COM[0]) * (atom[3] - COM[2]) I[1, 0] += mass * (atom[2] - COM[1]) * (atom[1] - COM[0]) I[1, 1] += mass * (atom[2] - COM[1]) * (atom[2] - COM[1]) I[1, 2] += mass * (atom[2] - COM[1]) * (atom[3] - COM[2]) I[2, 0] += mass * (atom[3] - COM[2]) * (atom[1] - COM[0]) I[2, 1] += mass * (atom[3] - COM[2]) * (atom[2] - COM[1]) I[2, 2] += mass * (atom[3] - COM[2]) * (atom[3] - COM[2]) I /= np.sum(masses) # Principal moments/Principle axes of inertial tensor L, O = np.linalg.eigh(I) # Eckart geometry geom2 = manage_xyz.np_to_xyz( geom, np.dot((manage_xyz.xyz_to_np(geom) - np.outer(np.ones( (len(masses), )), COM)), O)) return COM, L, O, geom2
def copy_from_options(MoleculeA, xyz=None, fnm=None, new_node_id=1, copy_wavefunction=True): """Create a copy of MoleculeA""" print(" Copying from MoleculA {}".format(MoleculeA.node_id)) PES = type(MoleculeA.PES).create_pes_from( PES=MoleculeA.PES, options={'node_id': new_node_id}) if xyz is not None: new_geom = manage_xyz.np_to_xyz(MoleculeA.geometry, xyz) coord_obj = type(MoleculeA.coord_obj)( MoleculeA.coord_obj.options.copy().set_values({"xyz": xyz})) elif fnm is not None: new_geom = manage_xyz.read_xyz(fnm, scale=1.) xyz = manage_xyz.xyz_to_np(new_geom) coord_obj = type(MoleculeA.coord_obj)( MoleculeA.coord_obj.options.copy().set_values({"xyz": xyz})) else: new_geom = MoleculeA.geometry coord_obj = type(MoleculeA.coord_obj)( MoleculeA.coord_obj.options.copy()) return Molecule(MoleculeA.Data.copy().set_values({ 'PES': PES, 'coord_obj': coord_obj, 'geom': new_geom, 'node_id': new_node_id, 'copy_wavefunction': copy_wavefunction, }))