计算化学公社

 找回密码 Forget password
 注册 Register
Views: 9163|回复 Reply: 1
打印 Print 上一主题 Last thread 下一主题 Next thread

[ORCA] 一个方便用于orca批处理的python模块

[复制链接 Copy URL]

433

帖子

8

威望

4317

eV
积分
4910

Level 6 (一方通行)

石墨

跳转到指定楼层 Go to specific reply
楼主
本帖最后由 Graphite 于 2018-11-15 18:08 编辑

CAUTION: This page is written in Chinese, If you read it via Google Translate, the code below will LOSE ITS FORMAT, so DO NOT copy and paste the code in translated page.

本模块(ChOrca)主要用于解决以下问题:
1.治好用惯了gview的人要用ORCA时, 粘来粘去的毛病
2.节省反复编写输入文件和建文件夹浪费的时间
3.简单调用cclib对输出文件进行解析

环境需求:
1.cclib -- 一个用于解析量化软件输出的库
2.需要自定义settings.json(下文提到)

注意:
本模块仅在windows下测试, linux理论可用.
By the way,  笔者用win10+GView+ORCA+本模块+VisualStudio Code集成终端用的很爽...虚拟机已删...

例: 本文件夹下有数个.gjf文件, 现在想要调用ORCA提取其中的坐标进行计算, 编写如下脚本:
  1. import ChOrca
  2. for gjf in ['a.gjf', 'b.gjf', 'c.gjf', ]:
  3.     name = gjf.split('.')[0]
  4.     calc = ChOrca.Calculation(name)
  5.     calc.set_input_from_template('rank_1_opt', 'mem_1000mb', 0, 1, gjf)
  6.     calc.run_orca()
复制代码

这里的'rank_1_opt', 'mem_1000mb'是我们在settings.json里的键, 实际调用其对应的值, 相当于设置了别名. settings.json最好与此脚本放在同一目录下.
  1. {
  2.     "orca_path": "D:\\ProgramFiles\\orca\\orca.exe",
  3.     "template_keyword_excls": {
  4.         "rank_1_opt": "!pal4 blyp def2-svp def2/j d3 miniprint"
  5.     },
  6.     "template_keyword_prcts": {
  7.         "mem_1000mb": "%maxcore 1000"
  8.     }
  9. }
复制代码

模块包含的方法和参数, 在代码内部的docstring中都有提到. 源代码如下:
  1. #coding: utf-8
  2. """
  3. This is a python module for calculation orca jobs conviently.
  4. Import it and enjoy!

  5. Lincense:   Whatever, use it, copy it, or modify it as you like.
  6. Author:     T. H. Graphite
  7. """

  8. import json
  9. import os
  10. import re
  11. import subprocess
  12. import sys

  13. import cclib


  14. class Calculation():
  15.     """Calculate orca jobs.
  16.    
  17.     Keyword Arguments:
  18.         name {str}-- the instance name, for creating new files and dirs.
  19.         work_dir {str} -- work directory, default: the path of module.

  20.         Once a instance is created, a new directory work_dir/name will be made.
  21.         Thus, all the calcultion will be done at this directory.

  22.     Methods:
  23.         load_settings(path)
  24.         set_input(keyword_excl, keyword_prct, ncharge, nmulti, coordinates)
  25.         set_input_from_xyz(keyword_excl, keyword_prct, ncharge, nmulti, path)

  26.     Attributes:
  27.         parse_json
  28.         parse_result
  29.     """


  30.     def __init__(self, name, work_dir=sys.path[0]):
  31.         self.name = name
  32.         self.work_dir = work_dir
  33.         os.chdir(self.work_dir)
  34.         self.dir = os.path.join(self.work_dir, self.name)

  35.         self.load_settings()

  36.         if not os.path.exists(self.dir):
  37.             os.mkdir(self.dir)

  38.         self.input_path = os.path.join(self.dir, self.name + '.inp')
  39.         self.output_path = os.path.join(self.dir, self.name + '.out')

  40.     def load_settings(self, path=None):
  41.         """Load settings from path.
  42.         
  43.         Keyword Arguments:
  44.             path {str} -- the path of json settings file (default: work_dir/settings.json)
  45.         """

  46.         if path is None:
  47.             path = os.path.join(self.work_dir, 'settings.json')

  48.         try:
  49.             settings_file = open(path, 'r')
  50.             settings_dict = json.load(settings_file)
  51.             self.orca_path = settings_dict['orca_path']
  52.             self.template_keyword_excls = settings_dict['template_keyword_excls']
  53.             self.template_keyword_prcts = settings_dict['template_keyword_prcts']

  54.         except Exception:
  55.             print('No settings file or invalid format. Exit.')
  56.             exit()

  57.     def set_input(self, keyword_excl, keyword_prct, ncharge, nmulti, coordinates):
  58.         """Set input contents for calculation
  59.         
  60.         Arguments:
  61.             keyword_excl {str} -- keywords start with a !
  62.             keyword_prct {str} -- keyword start with a %, a.k.a. the 'block' in orca manual.
  63.             ncharge {str or int} -- charge of molecule
  64.             nmulti {str or int} -- multiplicity of molecule
  65.             coordinates {str} -- coordinates in format like "C 1.000 1.000 1.000\nC 2.000 2.000 2.000..." .
  66.         """

  67.         self.input_content = "{kw_excl}\n{kw_prct}\n*xyz {nchg} {nmtp}\n{coord}\n*".format(
  68.             kw_excl=keyword_excl,
  69.             kw_prct=keyword_prct,
  70.             nchg=str(ncharge),
  71.             nmtp=str(nmulti),
  72.             coord=coordinates)

  73.     def set_input_from_xyz(self, keyword_excl, keyword_prct, ncharge, nmulti, path):
  74.         """Set input contents for calculation, coordinates from a xyz-like file
  75.         (.xyz, .gjf, or any file can be filter by the regex below)
  76.         
  77.         Arguments:
  78.             keyword_excl {str} -- keywords start with a !
  79.             keyword_prct {str} -- keyword start with a %
  80.             ncharge {str or int} -- charge of molecule
  81.             nmulti {str or int} -- multiplicity of molecule
  82.             path {str} -- the path of the xyz-like file
  83.         """

  84.         regex = r'\ {0,2}[A-Z][a-z]?(\ *-?[0-9]*\.[0-9]*){3,}'
  85.         pattern = re.compile(regex)

  86.         file_object = open(path, 'r')
  87.         coordinates = str()
  88.         for line in file_object:
  89.             if pattern.match(line):
  90.                 coordinates += line
  91.         file_object.close()

  92.         self.set_input(keyword_excl, keyword_prct, ncharge, nmulti, coordinates)

  93.     def set_input_from_template(self, temp_excl, temp_prct, ncharge, nmulti, path):
  94.         """Like set_input_from_xyz, but use template names (in the settings file, see: load_settings)
  95.         
  96.         Arguments:
  97.             temp_excl {str} -- a key of template_keyword_excls
  98.             temp_prct {str} -- a key of template_keyword_prcts
  99.             ncharge {str or int} -- charge of molecule
  100.             nmulti {str or int} -- multiplicity of molecule
  101.             path {str} -- the path of the xyz-like file
  102.         """

  103.         keyword_excl = self.template_keyword_excls[temp_excl]
  104.         keyword_prct = self.template_keyword_prcts[temp_prct]

  105.         self.set_input_from_xyz(keyword_excl, keyword_prct, ncharge, nmulti, path)
  106.         

  107.     def run_orca(self):
  108.         """Running orca
  109.         
  110.         Returns:
  111.             Boolean -- whether the calculation is terminated normally or not.
  112.         """

  113.         if not os.path.exists(self.orca_path):
  114.             raise(EnvironmentError)

  115.         input_file = open(self.input_path, 'w')
  116.         input_file.write(self.input_content)
  117.         input_file.close()

  118.         run_command = self.orca_path + ' ' + self.input_path + ' > ' + self.output_path
  119.         try:
  120.             subprocess.check_call(run_command, shell=True)
  121.             return True

  122.         except subprocess.CalledProcessError:
  123.             return False

  124.     @property
  125.     def parse_json(self):
  126.         """Parse the output file using cclib.
  127.         
  128.         Returns:
  129.             str -- a json string, including lots of interesting infos
  130.         """

  131.         parse_target = cclib.ccopen(self.output_path)
  132.         if parse_target is not None:
  133.             try:
  134.                 print(parse_target)
  135.                 parse_result = parse_target.parse()
  136.                 json = cclib.ccwrite(
  137.                     parse_result, outputtype='json', returnstr=True)
  138.                 return json

  139.             except Exception:
  140.                 return None

  141.     @property
  142.     def parse_result(self):
  143.         """The dictionary version of parse_json.
  144.         
  145.         Returns:
  146.             dict -- a flattened dict
  147.         """

  148.         def walk(dictionary):
  149.             for key, value in dictionary.items():
  150.                 if isinstance(value, dict):
  151.                     for tup in walk(value):
  152.                         yield (key, ) + tup

  153.                 else:
  154.                     yield key, value

  155.         result = dict()
  156.         for tup in walk(json.loads(self.parse_json)):
  157.             result.setdefault('/'.join(tup[:-1]), tup[-1])

  158.         return result


  159. if __name__ == '__main__':
  160.     print(__doc__)

复制代码







评分 Rate

参与人数
Participants 5
eV +25 收起 理由
Reason
zsu007 + 5 赞!
wangyj + 5 谢谢分享
sobereva + 5
卡开发发 + 5 你太可爱
ChrisZheng + 5 谢谢

查看全部评分 View all ratings

自在飞花轻似梦,无边丝雨细如愁。

全自动反应动力学(ReaxFF、AIMD、NEP等)后处理工具网页版:http://cc-portal.xyz/reax_tools

126

帖子

0

威望

1万

eV
积分
11550

Level 6 (一方通行)

2#
发表于 Post on 2018-3-19 18:56:32 | 只看该作者 Only view this author
代码粘过来全部乱码了 看起来很厉害的样子 战略马克

评分 Rate

参与人数
Participants 1
eV +1 收起 理由
Reason
Graphite + 1 已改, 编辑器自带样式表混入了...

查看全部评分 View all ratings

本版积分规则 Credits rule

手机版 Mobile version|北京科音自然科学研究中心 Beijing Kein Research Center for Natural Sciences|京公网安备 11010502035419号|计算化学公社 — 北京科音旗下高水平计算化学交流论坛 ( 京ICP备14038949号-1 )|网站地图

GMT+8, 2026-2-23 15:11 , Processed in 2.829508 second(s), 21 queries , Gzip On.

快速回复 返回顶部 返回列表 Return to list