あるケミストの独り言(winchemwinの日記)

ケミスト(化学者)の視点で、面白そうな情報(シミュレーション関係など)を発信

Pyscfによる量子化学計算-Tkinterアプリ_10

 引き続きpyscfの計算実施用アプリについて紹介したいと思います。
 今回は計算実行部分の関数とTkinter設定部分のコードになります。
基本的なコードは以前に紹介したPsi4のアプリのコードと同様になりますがPyscf用に一部変更しています。計算用のインプットデータですが、Pyscfではxyzファイルでの入力に対応していますので、mol ファイルの場合はrdkitを利用して配座探索を行った後にxyz を作成し、インプットデータ(comp_geo)としています。もともとxyzファイルの場合はそのままインプットデータとしています(配座探索が現時点では組み込まれていないので留意が必要です)。以前のアプリと同様に変数によってはglobal定義にしないとエラーが出ましたのでここではglobal宣言をしていますが、他のやり方もあるのかもしれません。

def calc_run(self):
    global meth
    global func
    global base
    global svname
    meth=method_sv.get()
    func=function_sv.get()
    base=baseset_sv.get()
    svname=savename_sv.get()
    global chr
    global mul
    chr=charge.get()
    mul=multi.get()
    
    global mem
    global thre
    
    mem=memory.get()
    thre=threads.get()
    
    global fname
    fname=filename_sv.get()
    
    
    #  Conformer search by rdkit then make xyz file
    # 計算のgeometry file(xyz)は comp_geo で設定
    
    global comp_geo
    
    with open (fname) as f:
        if '.mol' in fname:
            mol_H=f.read()
            
            confs = AllChem.EmbedMultipleConfs(mol_H, 10, pruneRmsThresh=1)
            prop = AllChem.MMFFGetMoleculeProperties(mol_H)

            energy=[]
            for conf in confs:
                mmff = AllChem.MMFFGetMoleculeForceField(mol_H, prop,confId=conf)
                mmff.Minimize()
                energy.append((mmff.CalcEnergy(), conf))
    
                conflist = np.array(energy)
                sortconf=conflist[np.argsort(conflist[:,0]) ]

                stconfid=sortconf[0,1]
                stconfid2=int(stconfid)
                stconfgeom=mol_H.GetConformer(stconfid2)

            xyz = chr, mul
            for atom, (x,y,z) in zip(mol_H.GetAtoms(), stconfgeom.GetPositions()):
                xyz += '\n'
                xyz += '{}\t{}\t{}\t{}'.format(atom.GetSymbol(), x, y, z)
            
            with open ('geomerty_for_calc.xyz', mode='w')  as f:
                f.write(xyz)
            
            comp_geo='geomerty_for_calc.xyz'

            # 上記xyxデータをファイルとして保存  
            #  Setting input file

        elif '.xyz' in fname:
            comp_geo=fname
            
            # 計算関数内のgto(atom=###)に設定できるxyzファイルとして設定
        
    # Select calculation task
    task=task_sv.get()
    if task=='Geometry optimization':
        Geom_Opt()
        
    elif task=='Vibration analysis':
        Vib_Calc()
        
    elif task=='Geom opt + Vib analysis':
        Geom_Opt_Vib_Anal()
    
    elif task=='Molecular orbitals analysis':
        MO_anal()
        
    elif task=='UV-Vis spectrum':
        UV_VIS_Spec()
        
    elif task=='Muliken charges':
        Mul_Charge()
        
    elif task=='Dipole moment':
        Dip_Moment()
        
    elif task=='Polarizability':
        Polar()
        
    elif task=='Infrared Spectrum':
        infrared_spect()       
        
# finish program
def scry_finish():
    exit()

以下はTkinter の設定部のコードになります。
GUIのタイトルと枠(大きさの設定)、Label, Entry, Button, Comboboxなどの設定を行っていますが、選択項目の少しの変更以外はPsi4のアプリの際と大きな変更点はありません。

Tkinter main 

root = tk.Tk()
root.title("Pyscf Calculation Setup")
root.geometry('800x650')

# Select molecule file
Label1=ttk.Label(root, text=u'Molecule',font=("Times","14","bold"))
Label1.place(x=20, y=60)

filename_sv = tk.StringVar()
filenameEntry = ttk.Entry(width=60, text="", textvariable=filename_sv)
filenameEntry.place(x=20, y= 90)

Button1 = ttk.Button(text=u'Select',width=10)
Button1.bind("<Button-1>", data_import) 
Button1.place(x=600, y=90)

# Select calculation task
Label2=ttk.Label(text=u'Task', font=("Times","14","bold"))
Label2.place(x=20, y=140)
task_sv = tk.StringVar()
task_contents=('Geometry optimization','Vibration analysis','Geom opt + Vib analysis', 'Molecular orbitals analysis', 'UV-Vis spectrum','Muliken charges','Dipole moment', 'Polarizability', 'Infrared Spectrum' )
comboBox2=ttk.Combobox(root, height=5, width=20, state='readonly', values=task_contents, textvariable=task_sv)
comboBox2.place(x=20, y=170)

# Select calculation methods
Label3=ttk.Label(text=u'Calculation Method', font=("Times","14","bold"))
Label3.place(x=20, y=220)

Label3_1=ttk.Label(root, text=u'Method',font=("Times","12"))
Label3_1.place(x=20, y=240)
method_sv = tk.StringVar()
methods=('HF','DFT', 'MP2')
comboBox3_1=ttk.Combobox(root, height=5, width=10, state='readonly', values=methods, textvariable=method_sv)
comboBox3_1.place(x=20, y=260)

Label3_2=ttk.Label(root, text=u'Function',font=("Times","12"))
Label3_2.place(x=200, y=240)
function_sv = tk.StringVar()
functions=('','b3lyp','cam-b3lyp', 'edf2','m06', 'pbe','wb97x-d')
comboBox3_2=ttk.Combobox(root, height=5, width=10, state='readonly', values=functions, textvariable=function_sv)
comboBox3_2.place(x=200, y=260)

Label3_3=ttk.Label(root, text=u'Basis set',font=("Times","12"))
Label3_3.place(x=400, y=240)
baseset_sv = tk.StringVar()
base_sets=('3-21g','6-31g', '6-31g(d)','6-311g', 'aug-cc-pvtz')
comboBox3_3=ttk.Combobox(root, height=5, width=10, state='readonly', values=base_sets, textvariable=baseset_sv)
comboBox3_3.place(x=400, y=260)

# Select options
Label4=ttk.Label(text=u'Options', font=("Times","14","bold"))
Label4.place(x=20, y=300)

Label4_1=ttk.Label(root, text=u'Tread',font=("Times","12"))
Label4_1.place(x=30, y=320)
threads=tk.IntVar(value=2)
textBox1_1=ttk.Entry(root, width=5, textvariable=threads)
textBox1_1.place(x=30, y=340)

Label4_2=ttk.Label(root, text=u'Memory/MB',font=("Times","12"))
Label4_2.place(x=130, y=320)
memory=tk.IntVar(value=500)
textBox1_2=ttk.Entry(root, width=5, textvariable=memory)
textBox1_2.place(x=130, y=340)

Label4_3=ttk.Label(root, text=u'Charge',font=("Times","12"))
Label4_3.place(x=30, y=370)
charge=tk.IntVar(value=0)
textBox2_1=ttk.Entry(root, width=5, textvariable=charge)
textBox2_1.place(x=30, y=390)

# spinのカウントは不対電子の数を数えるため通常(一重項)spin=0, ラジカルspin=1, 三重項 spin=2 

Label4_4=ttk.Label(root, text=u'Multiplicity',font=("Times","12"))
Label4_4.place(x=130, y=370)
multi=tk.IntVar(value=0)
textBox2_2=ttk.Entry(root, width=5, textvariable=multi)
textBox2_2.place(x=130, y=390)

# Input the name of calculated output files
Label5=ttk.Label(text=u'Name of output files', font=("Times","14","bold"))
Label5.place(x=20, y=470)

savename_sv = tk.StringVar()
textBox3=ttk.Entry(root, width=30, textvariable=savename_sv)
textBox3.place(x=30, y=500)

# Calculation Run
Button2=ttk.Button(text=u'Run',width=20)
Button2.bind("<Button-1>", calc_run) 
Button2.place(x=300, y=540)

Label6=ttk.Label(text=u'Finish the program')
Label6.place(x=630, y=560)
Button3 = ttk.Button(text=u'Quit',width=10, command=scry_finish)
Button3.place(x=630, y=580)

root.mainloop()

以上、今回は計算実行部分とTkinterの入力部の続きについて紹介してきました。次回は実際のアプリの入力の様子の説明を行いたいと思います。