Advertisement
Guest User

Untitled

a guest
Apr 25th, 2017
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.46 KB | None | 0 0
  1. from noodles import (gather, schedule)
  2. from qmworks import (adf, dftb, molkit, run, templates, Settings)
  3.  
  4. import numpy as np
  5.  
  6.  
  7. def main():
  8. backbone = '{}C1=CC=C(C=C1)C#CC2=CC=C({})C=C2'
  9.  
  10. # smiles of the electronDonors
  11. # electronDonors = ['N', 'P', 'S', 'CO']
  12. electronDonors = ['N']
  13. # smiles of the electronAcceptors
  14. # electronAcceptors = ['B', 'C(O)=O', 'N(=O)=O', 'C(F)(F)(F)']
  15. electronAcceptors = ['O']
  16.  
  17. # Genereate all the molecules
  18. molecules, names = create_molecules(backbone, electronDonors, electronAcceptors)
  19.  
  20. # Optimize with DFTB
  21. dftb_jobs = [dftb(templates.geometry, m, job_name='dftb_{}'.format(n)) for m, n in zip(molecules, names)]
  22.  
  23. # Schedule functions
  24. schedule_if_succesful = schedule(run_if_succesful)
  25. schedule_if_failure = schedule(run_if_failure)
  26. schedule_choose = schedule(choose_job)
  27.  
  28. # Optimize with DFT in gas phase
  29. s = create_settings_dft_gas()
  30. gas_jobs = [schedule_if_failure(adf, s, job, mol, name, prefix='adf_')
  31. for job, mol, name in zip(dftb_jobs, molecules, names)]
  32.  
  33. preoptimized_jobs = [schedule_choose(j1, j2) for j1, j2 in zip(dftb_jobs, gas_jobs)]
  34.  
  35. #Optimize with COSMO and compute frequency
  36. s = create_settings_dft_cosmo_freq()
  37. adf_cosmo_freq_jobs = [schedule_if_succesful(adf, s, job, name, prefix='solvation')
  38. for job, name in zip(preoptimized_jobs, names)]
  39.  
  40. # Filter jobs which frequencies are greater than zero
  41. schedule_check_freq = schedule(check_frequencies)
  42. candidates = [schedule_check_freq(j) for j in adf_cosmo_freq_jobs]
  43.  
  44. # Schedule a TD-DFT job with non-negative frequencies
  45. s = create_settings_TD_DFT()
  46. td_dft_jobs = [adf(s, job, job_name='td_dft_'.format(job.job_name)) for job in candidates]
  47.  
  48. schedule_getattr = schedule(extract_property)
  49. energies = [schedule_getattr(j, 'energy') for j in td_dft_jobs]
  50.  
  51. rs = run(gather(*energies), folder='biphenyl')
  52.  
  53. print(rs)
  54.  
  55. def create_molecules(backbone, electronDonors, electronAcceptors):
  56. """
  57. Create all the possible combination by changing one para substituent
  58. by an electronAcceptors and the other para position by an electronDonors
  59. """
  60. # Smiles representing the molecules to simulate
  61. smiles = [backbone.format(donor, acceptor)
  62. for donor in electronDonors for acceptor in electronAcceptors]
  63. # Plams molecules
  64. geometries = [molkit.from_smiles(s, forcefield='uff') for s in smiles]
  65.  
  66. # Name of the molecules
  67. invalid_chars = ['=', '(', ')', '[', ']', '#']
  68. names = [''.join(list(filter(lambda c: c not in invalid_chars, name))) for name in smiles]
  69.  
  70. return geometries, names
  71.  
  72.  
  73.  
  74. def adf_general_settings():
  75. """
  76. ADF settings use for the calculations
  77. """
  78. s = Settings()
  79.  
  80. # Basis
  81. s.specific.adf.basis.createoutput = None
  82.  
  83. # SCF
  84. s.specific.adf.SCF.iterations = 200
  85. s.specific.adf.SCF.convergence = '1.0e-6 1.0e-5'
  86.  
  87. # zlmfit
  88. s.specific.adf.zlmfit.quality = 'verygood'
  89.  
  90. # BeckeGrid
  91. s.specific.adf.BeckeGrid.quality = 'verygood'
  92.  
  93. # realtivistic
  94. s.specific.adf.Relativistic = 'SCALAR ZORA'
  95.  
  96. # Solvation
  97. with open('radii', 'r') as f:
  98. radii = f.read()
  99.  
  100. s.specific.adf.Solvation.div = 'ndiv=3 min=0.5 ofac=0.8'
  101. s.specific.adf.Solvation.charged = 'conv=1e-10 iter=1000 corr'
  102. s.specific.adf.Solvation.CSMRSP = ''
  103. s.specific.adf.Solvation.Radii = '\n{}'.format(radii)
  104.  
  105. return s
  106.  
  107. def create_settings_TD_DFT(basis='TZ2P'):
  108. """
  109. create input for a TD-DFT calculation
  110. """
  111. s = adf_general_settings()
  112.  
  113. # Basis
  114. s.specific.adf.basis.type = '{}'.format(basis)
  115. s.specific.adf.basis.core = 'none'
  116.  
  117.  
  118. #COSMO
  119. s.specific.adf.Solvation.solvent = 'name=Dichloromethane emp=0.0 neql=2.028'
  120.  
  121. # functional
  122. s.specific.adf.xc.hybrid = 'CAMYB3LYP'
  123. s.specific.adf.xc.xcfun = ''
  124. s.specific.adf.xc.rangesep = ''
  125.  
  126. # excitations
  127. s.specific.adf.excitations.Davidson = ''
  128. s.specific.adf.excitations.lowest = 7
  129. s.specific.adf.eprint.sfo = "eig ovl"
  130.  
  131. return s
  132.  
  133. def create_settings_dft_gas(basis='DZP'):
  134. """
  135. Create input for an optimizatiion with ADF in gas phase
  136. """
  137. s = Settings()
  138.  
  139. # Basis
  140. s.specific.adf.basis.createoutput = None
  141.  
  142. # SCF
  143. s.specific.adf.SCF.iterations = 200
  144. s.specific.adf.SCF.convergence = '1.0e-6 1.0e-5'
  145.  
  146. # zlmfit
  147. s.specific.adf.zlmfit.quality = 'good'
  148.  
  149. # BeckeGrid
  150. s.specific.adf.BeckeGrid.quality = 'good'
  151.  
  152. # realtivistic
  153. s.specific.adf.Relativistic = 'SCALAR ZORA'
  154.  
  155.  
  156. # Basis
  157. s.specific.adf.basis.type = '{}'.format(basis)
  158. s.specific.adf.basis.core = 'small'
  159.  
  160. # functional
  161. s.specific.adf.xc.gga = 'BP86'
  162.  
  163. # geometry
  164. s.specific.adf.geometry.optim = 'delocalized'
  165. s.specific.adf.geometry.iterations = 99
  166. s.specific.adf.geometry.convergence = 'e=0.00001 grad=0.0001'
  167.  
  168. # SCF
  169. s.specific.adf.SCF.mix = 0.2
  170.  
  171. return s
  172.  
  173.  
  174.  
  175. def create_settings_dft_cosmo_freq(basis='TZ2P'):
  176. """
  177. Create input for an optimization and posterior frequencies calculation with ADF
  178. """
  179. s = adf_general_settings()
  180. s.specific.adf.analyticalfreq
  181. s.specific.adf.scanfreq = '-500 100'
  182. #COSMO
  183. s.specific.adf.Solvation.solvent = 'name=Dichloromethane emp=0.0'
  184.  
  185. # Basis
  186. s.specific.adf.basis.type = '{}'.format(basis)
  187. s.specific.adf.basis.core = 'small'
  188.  
  189. # functional
  190. s.specific.adf.xc.gga = 'BP86'
  191.  
  192. # geometry
  193. s.specific.adf.geometry.optim = 'delocalized'
  194. s.specific.adf.geometry.iterations = 99
  195. s.specific.adf.geometry.convergence = 'e=0.000001 grad=0.00001'
  196.  
  197. # SCF
  198. s.specific.adf.SCF.mix = 0.2
  199.  
  200. return s
  201.  
  202. def filter_None(jobs):
  203. """
  204. Remove the non-valid jobs
  205. """
  206. return list(filter(lambda j: j is not None, jobs))
  207.  
  208.  
  209. def check_frequencies(job):
  210. """
  211. Filter the jobs which frequencies are non-negative
  212. """
  213. predicate = np.any(np.array(job.frequencies) < 0)
  214. if predicate:
  215. print("Job: ", job.job_name, " has at least a negative frequency")
  216. return None
  217. else:
  218. return job
  219.  
  220.  
  221. def extract_property(job, prop):
  222. """
  223. wrapper around getattr
  224. """
  225. if job is None:
  226. return None
  227. else:
  228. return getattr(job, prop)
  229.  
  230.  
  231. def choose_job(job1, job2):
  232. """
  233. Try to get an attribute from job1 otherwise from job2 else None
  234. """
  235. if job1 is not None and job1.status not in ['failed', 'crashed']:
  236. return job1
  237. elif job2 is not None and job2.status not in ['failed', 'crashed']:
  238. return job2
  239. else:
  240. return None
  241.  
  242.  
  243. def run_if_succesful(fun, settings, job, name, prefix='job'):
  244. """
  245. Schedule a job if its depencies finished succesfully
  246. """
  247. if job is not None and job.status not in ['failed', 'crashed']:
  248. job_name = '{}_{}'.format(prefix, name)
  249. return fun(settings, job.molecule, job_name=job_name)
  250. else:
  251. return None
  252.  
  253. def run_if_failure(fun, settings, job, mol, name, prefix='job'):
  254. """
  255. Schedule a job if its depencies finished succesfully
  256. """
  257. if job is None or job.status in ['failed', 'crashed']:
  258. job_name = '{}_{}'.format(prefix, name)
  259. return fun(settings, mol, job_name=job_name)
  260. else:
  261. return None
  262.  
  263. if __name__ == "__main__":
  264. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement