mlatom.interfaces.sparrow_interface 源代码

#!/usr/bin/env python3
'''
.. code-block::

  !---------------------------------------------------------------------------! 
  ! sparrow: interface to the Sparrow program                                 ! 
  ! Implementations by: Pavlo O. Dral & Peikun Zheng                          !
  !---------------------------------------------------------------------------! 

  '''

import os
import numpy as np
from .. import constants, simulations, models
from ..decorators import doc_inherit 

[文档] class sparrow_methods(models.OMP_model, metaclass=models.meta_method): ''' Sparrow interface Arguments: method (str): method to use read_keywords_from_file (str): keywords used in Sparrow save_files_in_current_directory (bool): whether to keep input and output files, default ``'False'`` working_directory (str): path to the directory where the program output files and other tempory files are saved, default ``'None'`` .. note:: Methods supported: Energy: DFTB0, DFTB2, DFTB3 MNDO, MNDO/d, AM1, PM3, PM6, RM1, OM2, OM3, ODM2*, ODM3* AIQM1 Gradients: DFTB0, DFTB2, DFTB3 MNDO, MNDO/d, AM1, PM3, PM6, RM1 ''' availability_of_gradients_for_methods = { 'DFTB0': True, 'DFTB2': True, 'DFTB3': True, 'MNDO': True, 'MNDO/d': True, 'AM1': True, 'RM1': True, 'PM3': True, 'PM6': True, 'OM2': False, 'OM3': False, 'ODM2*': False, 'ODM3*': False, 'AIQM1': False} def __init__(self, method='ODM2*', read_keywords_from_file='', save_files_in_current_directory=False, working_directory=None, **kwargs): self.method = method self.read_keywords_from_file = read_keywords_from_file self.save_files_in_current_directory = save_files_in_current_directory self.working_directory = working_directory try: self.sparrowbin = os.environ['sparrowbin'] except: msg = 'Cannot find the Sparrow program, please set the environment variable: export sparrowbin=...' raise ValueError(msg)
[文档] @doc_inherit def predict(self, molecular_database=None, molecule=None, calculate_energy=True, calculate_energy_gradients=False, calculate_hessian=False, **kwargs): molDB = super().predict(molecular_database=molecular_database, molecule=molecule) # Not very good method naming in Sparrow... # ODM2 is not implemented, ODM2 is just ODM2*, same for ODM3/ODM3* if self.method == 'ODM2*': method_to_pass = 'ODM2' elif self.method == 'ODM3*': method_to_pass = 'ODM3' else: method_to_pass = self.method additional_sparrow_keywords = [] if self.read_keywords_from_file != '': kw_file = self.read_keywords_from_file with open(kw_file, 'r') as fkw: for line in fkw: additional_sparrow_keywords = line.split() imol = -1 for mol in molDB.molecules: imol += 1 jmol = imol if len(additional_sparrow_keywords) < imol+1: jmol = -1 mol.additional_sparrow_keywords = additional_sparrow_keywords[jmol] import tempfile, subprocess ii = 0 for mol in molDB.molecules: with tempfile.TemporaryDirectory() as tmpdirname: if self.save_files_in_current_directory: tmpdirname = '.' if self.working_directory is not None: tmpdirname = self.working_directory if not os.path.exists(tmpdirname): os.makedirs(tmpdirname) tmpdirname = os.path.abspath(tmpdirname) ii += 1 xyzfilename = f'{tmpdirname}/predict{ii}.xyz' mol.write_file_with_xyz_coordinates(filename = xyzfilename) sparrowargs = [self.sparrowbin, '-x', xyzfilename, '-c', '%d' % mol.charge, '-s','%d' % mol.multiplicity, '-M', method_to_pass, '-o'] sparrowargs += additional_sparrow_keywords if calculate_energy_gradients and self.availability_of_gradients_for_methods[self.method]: sparrowargs += ['-G'] if calculate_hessian and self.availability_of_gradients_for_methods[self.method]: sparrowargs += ['-H'] #cmd = ' '.join(sparrowargs) proc = subprocess.Popen(sparrowargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=tmpdirname, universal_newlines=True) #proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=tmpdirname, universal_newlines=True, shell=True) #proc.wait() outs,errs = proc.communicate() #os.system(cmd + " &> sparrow.out") mol.sparrow_scf_successful = False # for readable in proc.stdout: # if 'SCF converged!' in readable: # mol.sparrow_scf_successful = True if 'SCF converged!' in outs+errs: mol.sparrow_scf_successful = True if not mol.sparrow_scf_successful: return if calculate_energy: mol.energy = np.loadtxt(f'{tmpdirname}/energy.dat', comments='#').tolist() if calculate_energy_gradients: if self.availability_of_gradients_for_methods[self.method]: mol.energy_gradients = np.loadtxt(f'{tmpdirname}/gradients.dat', comments='#') / constants.Bohr2Angstrom else: save_files_in_current_directory = self.save_files_in_current_directory self.save_files_in_current_directory = False _ = simulations.numerical_gradients(mol, self, 1e-5, model_kwargs = {'calculate_energy_gradients': False, 'calculate_hessian': False}) self.save_files_in_current_directory = save_files_in_current_directory if calculate_hessian: if self.availability_of_gradients_for_methods[self.method]: mol.hessian = np.loadtxt(f'{tmpdirname}/hessian.dat', comments='#') / (constants.Bohr2Angstrom**2) else: save_files_in_current_directory = self.save_files_in_current_directory self.save_files_in_current_directory = False _ = simulations.numerical_hessian(mol, self, 5.29167e-4, 1e-5, model_kwargs = {'calculate_energy_gradients': False, 'calculate_hessian': False}) self.save_files_in_current_directory = save_files_in_current_directory
if __name__ == '__main__': pass