Mod:Hunt Research Group/dipole moment

From wiki
Jump to navigation Jump to search

code to calculate the dipole moment

What the program does?
1. Calculate the dipole moment using CHELPG charges and check against the gaussian dipole moment.
2. Calculate the dipole moment using other charge schemes.
3. Calculate the dipole moment relative to the centre of positive nuclear charge (CoP) vs. the centre of mass (CoM).
  • The dipole moment (μ) wrt the CoP and the μ wrt the CoM is the same for neutral molecules but differs for charged molecules.
  • Only the lowest non-vanishing multipole moment remains unchanged with the choice of the origin.
  • preparing the input file
  1. the first line of the input file must specify in the following order separated by whitespaces: the number of atoms, the total charge(with a decimal point), the gaussian calculated dipole moment and its component (ux,uy,uz), then leave a blank line
  2. next lines must contain the atomic number and the corresponding XYZ coordinates
  3. leave a blank line
  4. the next line must specify the type of charge as, NBO, CHELPG, or AIM
  5. the following lines must include the atomic number and the corresponding charge
  6. leave a blank line after the first set of charges
  7. do steps 4-6 for the next type of charges
  • sample input file
    • for a positively charged molecule (emim+): Media:emim.log
    • for water molecule is below
3	0.0	2.1993 	0.0000     0.0000    -2.1993

8  -0.000000   0.000000   0.114720
1   0.000000   0.754031  -0.458881
1  -0.000000  -0.754031  -0.458881

NBO
8	-0.95658
1	 0.47829
1	 0.47829

CHELPG
8	-0.798274
1	 0.399137
1	 0.399137

AIM
8	-1.18105730290000
1	 0.59052792621000
1	 0.59052707781000

running the python script

  • if the names of your script and input file are dipole_moment.py and water.inp, respectively, and if you want to save the output as a .txt file, run the script by typing, python dipole_moment.py water.inp txt
#!/usr/bin/env python3
#
#dipole_moment.py

import sys, re, os

dir=os.getcwd()
if len(sys.argv) < 3:
    print('to run the script please type: python dipole_moment.py inp_name (with extension) output_file_extension')
    sys.exit()
else:
    inp=str(sys.argv[1])
    split_inp=inp.split('.')
    base=split_inp[0]
    out_ext=str(sys.argv[2])
    out=base+'.'+out_ext
    s='directory is '
    print('{0:}{1:}'.format(s,dir))
    c=open(out,"w")
    c.write('{0:}{1:} \n'.format(s,dir))
    s='input file is '
    print('{0:}{1:}'.format(s,inp))
    c.write('{0:}{1:} \n'.format(s,inp))
    s='output file is '
    print('{0:}{1:} \n'.format(s,out))
    c.write('{0:}{1:}\n \n'.format(s,out))

f=open(inp,'r')
line=f.readline()
a1,b1,c1,d1,e1,f1=line.rstrip().split()
Natoms=int(a1)
tQ=float(b1)
count=0
dipole=[]
mux=[]
muy=[]
muz=[]
dipole.append(float(c1))
mux.append(float(d1))
muy.append(float(e1))
muz.append(float(f1))
count=count+1

s='total charge is '
print('{0:}{1:}'.format(s,tQ))
c.write('{0:}{1:} \n'.format(s,tQ))
s='dipole moment, u from gaussian is '
print('{0:}{1:}'.format(s,dipole[0]))
c.write('{0:}{1:} \n'.format(s,dipole[0]))
s='ux from gaussian is '
print('{0:}{1:}'.format(s,mux[0]))
c.write('{0:}{1:} \n'.format(s,mux[0]))
s='uy from gaussian is '
print('{0:}{1:}'.format(s,muy[0]))
c.write('{0:}{1:} \n'.format(s,muy[0]))
s='uz from gaussian is '
print('{0:}{1:}\n'.format(s,muz[0]))
c.write('{0:}{1:}\n \n'.format(s,muz[0]))

atom_num=[]
x=[]
y=[]
z=[]
line=f.readline()

for i in range(0,Natoms):
    line=f.readline()
    a1,b1,c1,d1=line.rstrip().split()
    atom_num.append(int(a1))
    x.append(float(b1))
    y.append(float(c1))
    z.append(float(d1))

masses = {7:14.00674, 16:32.066, 9:18.9984032, 1:1.00794, 6:12.0107, 14:28.0855, 17:35.4527, 8:15.9994}

# Helper function to detect charge types in the input file
def detect_charge_types(inp):
    charge_types = {"CHELPG": False, "NBO": False, "AIM": False}
    with open(inp, 'r') as f:
        for line in f:
            if "CHELPG" in line:
                charge_types["CHELPG"] = True
            elif "NBO" in line:
                charge_types["NBO"] = True
            elif "AIM" in line:
                charge_types["AIM"] = True
    return charge_types

def nboread(inp):
    global charge
    global Natoms
    charge=[]
    go=False
    f=open(inp,'r')
    line=f.readline()
    while line:
        go=True
        line=f.readline()
        if "NBO" in line:
            s='NBO charges found'
            print('{0:}'.format(s))
            c.write('{0:} \n'.format(s))
            for i in range(0, Natoms):
                line=f.readline()
                a1,b1=line.rstrip().split()
                charge.append(float(b1))
        if line=='':go=False
    return charge

def chelpgread(inp):
    global charge
    charge=[]
    go=False
    f=open(inp,'r')
    line=f.readline()

    while line:
        go=True
        line=f.readline()
        if "CHELPG" in line:
            s='CHELPG charges found'
            print('{0:}'.format(s))
            c.write('{0:} \n'.format(s))
            for i in range(0, Natoms):
                line=f.readline()
                a1,b1=line.rstrip().split()
                charge.append(float(b1))
        if line=='':go=False
    return charge

def aimread(inp):
    global charge
    charge=[]
    go=False
    f=open(inp,'r')
    line=f.readline()

    while line:
        go=True
        line=f.readline()
        if "AIM" in line :
            s='AIM charges found'
            print('{0:}'.format(s))
            c.write('{0:} \n'.format(s))
            for i in range(0, Natoms):
                line=f.readline()
                a1,b1=line.rstrip().split()
                charge.append(float(b1))
        if line=='':go=False

    return charge

def main(charge):
    global DMp
    global mup
    CoM=[0,0,0]
    mass=0
    CoP=[0,0,0]
    pcharge=0
    n=0
    mu=[0,0,0]
    mup=[0,0,0]
    mum=[0,0,0]
    CoC=[0,0,0]
    COCC=0
    uCOCC=0
    DM=0
    DMp=0
    DMm=0
    total_charge=0
    charge_arm=0
    length=0
    ca_vector=[0,0,0]
    #calculates for the center of pcharge
    while n < Natoms:
        CoM[0]=CoM[0]+x[n]*masses[atom_num[n]]
        CoM[1]=CoM[1]+y[n]*masses[atom_num[n]]
        CoM[2]=CoM[2]+z[n]*masses[atom_num[n]]
        mass=mass+masses[atom_num[n]]
        CoP[0]=CoP[0]+x[n]*atom_num[n]
        CoP[1]=CoP[1]+y[n]*atom_num[n]
        CoP[2]=CoP[2]+z[n]*atom_num[n]
        pcharge=pcharge+atom_num[n]
        n=n+1
    CoM[0] = CoM[0] / mass
    CoM[1] = CoM[1] / mass
    CoM[2] = CoM[2] / mass
    s='center of mass: '
    print('{0:}{1[0]:>5.2f}, {1[1]:5.2f}, {1[2]:5.2f}'.format(s,CoM))
    c.write('{0:}{1[0]:>5.2f}, {1[1]:5.2f}, {1[2]:5.2f} \n'.format(s,CoM))

    CoP[0] = CoP[0] / pcharge
    CoP[1] = CoP[1] / pcharge
    CoP[2] = CoP[2] / pcharge
    s='center of pcharge: '
    print('{0:}{1[0]:>5.2f}, {1[1]:5.2f}, {1[2]:5.2f}'.format(s,CoP))
    c.write('{0:}{1[0]:>5.2f}, {1[1]:5.2f}, {1[2]:5.2f} \n'.format(s,CoP))

    n=0
    while n < Natoms:
        mup[0]=mup[0]+(charge[n]*(x[n]-CoP[0]))
        mup[1]=mup[1]+(charge[n]*(y[n]-CoP[1]))
        mup[2]=mup[2]+(charge[n]*(z[n]-CoP[2]))
        mum[0]=mum[0]+(charge[n]*(x[n]-CoM[0]))
        mum[1]=mum[1]+(charge[n]*(y[n]-CoM[1]))
        mum[2]=mum[2]+(charge[n]*(z[n]-CoM[2]))
        total_charge=total_charge+charge[n]
        n=n+1
    DMp = DMp + (((mup[0])**2+(mup[1])**2+(mup[2])**2)**0.5)
    DMm = DMm + (((mum[0])**2+(mum[1])**2+(mum[2])**2)**0.5)
    s='total charge: '
    c.write('{0:}{1:5.2f}\n'.format(s,total_charge))
    print('{0:} {1:5.2f}'.format(s,total_charge))
    length=((CoP[0]-CoM[0])**2+(CoP[1]-CoM[1])**2+(CoP[2]-CoM[2])**2)**0.5
    charge_arm=charge_arm + (total_charge*length)
    charge_arm=charge_arm/0.208194
    ca_vector[0]=charge_arm*(CoP[0]-CoM[0])/length
    ca_vector[1]=charge_arm*(CoP[1]-CoM[1])/length
    ca_vector[2]=charge_arm*(CoP[2]-CoM[2])/length
    DMp = DMp/0.208194
    mup[0]=mup[0]/0.208194
    mup[1]=mup[1]/0.208194
    mup[2]=mup[2]/0.208194
    s='dipole vector wrt CoP (D): '
    print('{0:}{1[0]:>5.2f}, {1[1]:5.2f}, {1[2]:5.2f}'.format(s,mup))
    c.write('{0:}{1[0]:>5.2f}, {1[1]:5.2f}, {1[2]:5.2f} \n'.format(s,mup))
    s='dipole moment wrt CoP (D): '
    print('{0:}{1:>5.2f}'.format(s,DMp))
    c.write('{0:}{1:>5.2f} \n'.format(s,DMp))

    DMm = DMm/0.208194
    mum[0]=mum[0]/0.208194
    mum[1]=mum[1]/0.208194
    mum[2]=mum[2]/0.208194
    s='dipole vector wrt CoM (D): '
    print('{0:}{1[0]:>5.2f}, {1[1]:5.2f}, {1[2]:5.2f}'.format(s,mum))
    c.write('{0:}{1[0]:>5.2f}, {1[1]:5.2f}, {1[2]:5.2f} \n'.format(s,mum))
    s='dipole moment wrt CoM (D): '
    print('{0:}{1:>5.2f}'.format(s,DMm))
    c.write('{0:}{1:>5.2f} \n'.format(s,DMm))
    s='charge arm vector (D): '
    print('{0:}{1[0]:>5.2f}, {1[1]:5.2f}, {1[2]:5.2f}'.format(s,ca_vector))
    c.write('{0:}{1[0]:>5.2f}, {1[1]:5.2f}, {1[2]:5.2f} \n'.format(s,ca_vector))
    s='charge arm (D): '
    print('{0:}{1:>5.2f}\n'.format(s,charge_arm))
    c.write('{0:}{1:>5.2f} \n\n'.format(s,charge_arm))

# Detect available charge types
charge_types = detect_charge_types(inp)

# Calculate dipole moments only for the detected charge types
methods = []
methods.append("Gaussian")

if charge_types["CHELPG"]:
    chelpg_charges = chelpgread(inp)
    methods.append("CHELPG")
    main(chelpg_charges)
    dipole.append(float(DMp))
    mux.append(float(mup[0]))
    muy.append(float(mup[1]))
    muz.append(float(mup[2]))
    count=count+1

if charge_types["NBO"]:
    nbo_charges = nboread(inp)
    methods.append("NBO")
    main(nbo_charges)
    dipole.append(float(DMp))
    mux.append(float(mup[0]))
    muy.append(float(mup[1]))
    muz.append(float(mup[2]))
    count=count+1

if charge_types["AIM"]:
    aim_charges = aimread(inp)
    methods.append("AIM")
    main(aim_charges)
    dipole.append(float(DMp))
    mux.append(float(mup[0]))
    muy.append(float(mup[1]))
    muz.append(float(mup[2]))
    count=count+1

m=0
s='\nsummary of dipole moments wrt to CoP:'
print('{0:}'.format(s))
c.write('{0:}'.format(s))
s='\nMethod, Dipole Moment u, ux,uy,uz\n'
print('Method, Dipole Moment u, ux,uy,uz')
c.write('{0:}'.format(s))
while m<count:
    print('{0:},{1: >05.2f} ,{2: >05.2f} ,{3: >05.2f}, {4: >05.2f}'.format(methods[m],dipole[m],mux[m],muy[m],muz[m]))
    c.write('{0:},{1: >05.2f} ,{2: >05.2f} ,{3: >05.2f}, {4: >05.2f} \n'.format(methods[m],dipole[m],mux[m],muy[m],muz[m]))
    m=m+1

quit()

sample output of the script above

directory is /nfs/home/ebardoir/bin/test
input file is water.inp
output file is water.txt

total charge is 0.0
dipole moment, u from gaussian is 2.1993
ux from gaussian is 0.0
uy from gaussian is 0.0
uz from gaussian is -2.1993

CHELPG charges found
center of mass:  0.00,  0.00,  0.05
center of pcharge:  0.00,  0.00, -0.00
total charge:   0.00
dipole vector wrt CoP (D):  0.00,  0.00, -2.20
dipole moment wrt CoP (D):  2.20
dipole vector wrt CoM (D):  0.00,  0.00, -2.20
dipole moment wrt CoM (D):  2.20
charge arm vector (D):  0.00,  0.00, -0.00
charge arm (D):  0.00

NBO charges found
center of mass:  0.00,  0.00,  0.05
center of pcharge:  0.00,  0.00, -0.00
total charge:   0.00
dipole vector wrt CoP (D):  0.00,  0.00, -2.64
dipole moment wrt CoP (D):  2.64
dipole vector wrt CoM (D):  0.00,  0.00, -2.64
dipole moment wrt CoM (D):  2.64
charge arm vector (D):  0.00,  0.00, -0.00
charge arm (D):  0.00

AIM charges found
center of mass:  0.00,  0.00,  0.05
center of pcharge:  0.00,  0.00, -0.00
total charge:  -0.00
dipole vector wrt CoP (D):  0.00,  0.00, -3.25
dipole moment wrt CoP (D):  3.25
dipole vector wrt CoM (D):  0.00,  0.00, -3.25
dipole moment wrt CoM (D):  3.25
charge arm vector (D): -0.00, -0.00,  0.00
charge arm (D): -0.00


summary of dipole moments wrt to CoP:
Method, Dipole Moment u, ux,uy,uz
Gaussian, 2.20 , 0.00 , 0.00, -2.20
CHELPG, 2.20 , 0.00 , 0.00, -2.20
NBO, 2.64 , 0.00 , 0.00, -2.64
AIM, 3.25 , 0.00 , 0.00, -3.25