aegon 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aegon/__init__.py +1 -0
- aegon/atom2image.py +121 -0
- aegon/libcfg.py +79 -0
- aegon/libclustering.py +54 -0
- aegon/libcode.py +87 -0
- aegon/libcodegaussian.py +152 -0
- aegon/libcodegulp.py +204 -0
- aegon/libcodeorca.py +86 -0
- aegon/libcodevasp.py +120 -0
- aegon/libdescriptors.py +150 -0
- aegon/libdiscmbtrclusters.py +91 -0
- aegon/libdiscmbtrcrystals.py +88 -0
- aegon/libdiscusr.py +196 -0
- aegon/libgrowpal.py +174 -0
- aegon/libmlip_shapeev.py +25 -0
- aegon/libmolgen.py +377 -0
- aegon/libposcar.py +227 -0
- aegon/libpymatgen.py +33 -0
- aegon/libpyqueuing.py +53 -0
- aegon/librdkit.py +66 -0
- aegon/libstdio.py +172 -0
- aegon/libsyva.py +53 -0
- aegon/libunsupsel.py +226 -0
- aegon/libutils.py +286 -0
- aegon-0.1.0.dist-info/METADATA +15 -0
- aegon-0.1.0.dist-info/RECORD +29 -0
- aegon-0.1.0.dist-info/WHEEL +5 -0
- aegon-0.1.0.dist-info/licenses/LICENSE +674 -0
- aegon-0.1.0.dist-info/top_level.txt +1 -0
aegon/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#
|
aegon/atom2image.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
from ase.data import covalent_radii
|
|
4
|
+
from ase.data.colors import cpk_colors
|
|
5
|
+
#------------------------------------------------------------------------------------------
|
|
6
|
+
aspect_ratios_4by3 = {
|
|
7
|
+
'a': (800, 600), #SVGA
|
|
8
|
+
'b': (1024, 768), #XGA
|
|
9
|
+
'c': (1280, 960), #UXGA
|
|
10
|
+
'd': (1600, 1200),
|
|
11
|
+
'e': (2048, 1536),
|
|
12
|
+
'f': (3200, 2400),
|
|
13
|
+
'g': (6000, 4500),
|
|
14
|
+
}
|
|
15
|
+
aspect_ratios_16by9 = {
|
|
16
|
+
'a': (1280, 720), # HD
|
|
17
|
+
'b': (1920, 1080), # Full HD
|
|
18
|
+
'c': (2560, 1440), # QHD/2K
|
|
19
|
+
'd': (3840, 2160), # 4K UHD
|
|
20
|
+
'e': (7680, 4320), # 8K UHD
|
|
21
|
+
}
|
|
22
|
+
#------------------------------------------------------------------------------------------
|
|
23
|
+
bwd='0.12' # 0.15 GRUESO DE LOS ENLACES
|
|
24
|
+
dlv=0.15 # GRUESO DEL LADO DEL CUBO
|
|
25
|
+
sphere_factor=float(0.55) # 0.5 (g 1.5)
|
|
26
|
+
projection='orthographic' # 'perspective'
|
|
27
|
+
reflection='reflection 0.0'
|
|
28
|
+
reflection_model='phong 1.0' # 'specular'
|
|
29
|
+
radio_factor=float(1.30) # 1.4 1.6 #ALCANCE DE LOS ENLACES
|
|
30
|
+
tmit = 0.35 # transmit (transparencia) 0.35 0.75
|
|
31
|
+
#-----------------------------------------------------------------------------------------
|
|
32
|
+
def write_image(poscarin, basename, f=1.2, quality='f'):
|
|
33
|
+
if quality in aspect_ratios_4by3:
|
|
34
|
+
width, height = aspect_ratios_4by3[quality]
|
|
35
|
+
print(f"Width: {width}, Height: {height}")
|
|
36
|
+
else:
|
|
37
|
+
print(f"'{quality}' is not defined.")
|
|
38
|
+
poscarxx=poscarin.copy()
|
|
39
|
+
matrix=poscarxx.cell
|
|
40
|
+
a1=np.array(matrix[0,:])
|
|
41
|
+
a2=np.array(matrix[1,:])
|
|
42
|
+
a3=np.array(matrix[2,:])
|
|
43
|
+
a=np.linalg.norm(a1)
|
|
44
|
+
b=np.linalg.norm(a2)
|
|
45
|
+
c=np.linalg.norm(a3)
|
|
46
|
+
d=max([a,b,c])
|
|
47
|
+
factor=f*d
|
|
48
|
+
background1,background2,background3='2.0','2.0','2.0'
|
|
49
|
+
light11,light12,light13='1','1','1'
|
|
50
|
+
light21,light22,light23='1','1','1'
|
|
51
|
+
camara_rotate='y*0.0'
|
|
52
|
+
camara_loca1,camara_loca2,camara_loca3='0','0',str(factor)
|
|
53
|
+
camara_look1,camara_look2,camara_look3='0','0','0'
|
|
54
|
+
name_pov=basename+'.pov'
|
|
55
|
+
name_png=basename+'.png'
|
|
56
|
+
opnew = open(name_pov,'w')
|
|
57
|
+
print('global_settings { assumed_gamma 1.0 }', file=opnew)
|
|
58
|
+
#print('# include \'colors.inc\'', file=opnew)
|
|
59
|
+
print('background{color rgb<2.0, 2.0, 2.0>}\n', file=opnew)
|
|
60
|
+
print('light_source {< 10, -8, -8> color rgb <1, 1, 1>}', file=opnew)
|
|
61
|
+
print('light_source {< -8, 8, 8> color rgb <1, 1, 1>}\n', file=opnew)
|
|
62
|
+
print('camera {%s location <0, 0, %4.2f> look_at <0, 0, 0> rotate y*0.0}\n' %(projection, factor), file=opnew)
|
|
63
|
+
def primo(v1,v2):
|
|
64
|
+
print('cylinder {<%9.6f, %9.6f, %9.6f> <%9.6f, %9.6f, %9.6f>, %6.4f pigment{color rgb <0, 0, 0>} finish {%s %s}}' %(-v1[0],v1[1],v1[2],-v2[0],v2[1],v2[2],dlv,reflection_model,reflection), file=opnew)
|
|
65
|
+
#PARA QUE LA FIGURA SIEMPRE SALGA CENTRADA
|
|
66
|
+
a0=-(a1+a2+a3)/2
|
|
67
|
+
primo(a0,a0+a1)
|
|
68
|
+
primo(a0,a0+a2)
|
|
69
|
+
primo(a0,a0+a3)
|
|
70
|
+
primo(a0+a1,a0+a1+a2)
|
|
71
|
+
primo(a0+a1,a0+a1+a3)
|
|
72
|
+
primo(a0+a2,a0+a1+a2)
|
|
73
|
+
primo(a0+a2,a0+a2+a3)
|
|
74
|
+
primo(a0+a3,a0+a1+a3)
|
|
75
|
+
primo(a0+a3,a0+a2+a3)
|
|
76
|
+
primo(a0+a1+a2,a0+a1+a2+a3)
|
|
77
|
+
primo(a0+a1+a3,a0+a1+a2+a3)
|
|
78
|
+
primo(a0+a2+a3,a0+a1+a2+a3)
|
|
79
|
+
nn=len(poscarxx)
|
|
80
|
+
for ii in range(nn):
|
|
81
|
+
ni=poscarxx[ii].number
|
|
82
|
+
ri=covalent_radii[ni]
|
|
83
|
+
xxi,yyi,zzi=np.array(poscarxx[ii].position) + a0
|
|
84
|
+
for jj in range(ii+1,nn):
|
|
85
|
+
nj=poscarxx[jj].number
|
|
86
|
+
rj= covalent_radii[nj]
|
|
87
|
+
xxj,yyj,zzj=np.array(poscarxx[jj].position) + a0
|
|
88
|
+
uij=poscarxx[jj].position - poscarxx[ii].position
|
|
89
|
+
rr=np.linalg.norm(uij)
|
|
90
|
+
uijn=uij/rr
|
|
91
|
+
rt=rr/(ri+rj)
|
|
92
|
+
if rt < radio_factor:
|
|
93
|
+
xpm, ypm, zpm=(xxj+xxi)/2.0, (yyj+yyi)/2.0, (zzj+zzi)/2.0
|
|
94
|
+
cpki=cpk_colors[ni]
|
|
95
|
+
cpkj=cpk_colors[nj]
|
|
96
|
+
kolori=f"<{', '.join(f'{x:.3f}' for x in cpki)}>"
|
|
97
|
+
kolorj=f"<{', '.join(f'{x:.3f}' for x in cpkj)}>"
|
|
98
|
+
otf=float(0.95)
|
|
99
|
+
xxic=xxi+sphere_factor*otf*ri*uijn[0]
|
|
100
|
+
yyic=yyi+sphere_factor*otf*ri*uijn[1]
|
|
101
|
+
zzic=zzi+sphere_factor*otf*ri*uijn[2]
|
|
102
|
+
xxjc=xxj-sphere_factor*otf*rj*uijn[0]
|
|
103
|
+
yyjc=yyj-sphere_factor*otf*rj*uijn[1]
|
|
104
|
+
zzjc=zzj-sphere_factor*otf*rj*uijn[2]
|
|
105
|
+
print('cylinder {<%9.6f, %9.6f, %9.6f> <%9.6f, %9.6f, %9.6f> %s pigment {color rgb %s} finish {%s %s}}' %(-xxic,yyic,zzic,-xpm,ypm,zpm,bwd,kolori,reflection_model,reflection), file=opnew)
|
|
106
|
+
print('cylinder {<%9.6f, %9.6f, %9.6f> <%9.6f, %9.6f, %9.6f> %s pigment {color rgb %s} finish {%s %s}}' %(-xpm,ypm,zpm,-xxjc,yyjc,zzjc,bwd,kolorj,reflection_model,reflection), file=opnew)
|
|
107
|
+
for iatom in poscarxx:
|
|
108
|
+
cr=covalent_radii[iatom.number]
|
|
109
|
+
radii_div2=sphere_factor*cr
|
|
110
|
+
cpk=cpk_colors[iatom.number]
|
|
111
|
+
kolor=f"<{', '.join(f'{x:.3f}' for x in cpk)}>"
|
|
112
|
+
xx, yy, zz=np.array(iatom.position) + a0
|
|
113
|
+
s0='pigment {color rgb'
|
|
114
|
+
print('sphere {<%9.6f, %9.6f, %9.6f>, %6.4f pigment {color rgb %s} finish {%s %s}}' %(-xx,yy,zz,radii_div2,kolor,reflection_model,reflection), file=opnew)
|
|
115
|
+
opnew.close()
|
|
116
|
+
comp='povray +A Display=Off Output_File_Type=N All_Console=Off Width='+str(width)+' Height='+str(height)+' '+name_pov+' > /dev/null 2>&1'
|
|
117
|
+
os.system(comp)
|
|
118
|
+
print('Output= %s %s' %(name_pov, name_png))
|
|
119
|
+
doma='rm -f '+str(name_pov)
|
|
120
|
+
os.system(doma)
|
|
121
|
+
#-----------------------------------------------------------------------------------------
|
aegon/libcfg.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
from ase import Atom, Atoms
|
|
4
|
+
from ase.data import chemical_symbols
|
|
5
|
+
from aegon.libposcar import tag
|
|
6
|
+
#------------------------------------------------------------------------------------------
|
|
7
|
+
def readcfgs(filename):
|
|
8
|
+
if not os.path.isfile(filename):
|
|
9
|
+
print(f"El archivo {filename} no existe.")
|
|
10
|
+
return []
|
|
11
|
+
moleculas = []
|
|
12
|
+
singlemol = None
|
|
13
|
+
natom = 0
|
|
14
|
+
with open(filename, 'r') as contcarfile:
|
|
15
|
+
for line in contcarfile:
|
|
16
|
+
line = line.strip()
|
|
17
|
+
if line == "BEGIN_CFG":
|
|
18
|
+
if singlemol:
|
|
19
|
+
moleculas.append(singlemol)
|
|
20
|
+
singlemol = Atoms()
|
|
21
|
+
elif "Size" in line:
|
|
22
|
+
size_line = contcarfile.readline().strip()
|
|
23
|
+
natom = int(size_line)
|
|
24
|
+
elif "AtomData" in line:
|
|
25
|
+
for _ in range(natom):
|
|
26
|
+
coord_line = contcarfile.readline().strip()
|
|
27
|
+
ls = coord_line.split()
|
|
28
|
+
numero_atomico = int(5) #Escribir ls[1]
|
|
29
|
+
ss = chemical_symbols[numero_atomico]
|
|
30
|
+
xc, yc, zc = float(ls[2]), float(ls[3]), float(ls[4])
|
|
31
|
+
ai = Atom(symbol=ss, position=(xc, yc, zc))
|
|
32
|
+
singlemol.append(ai)
|
|
33
|
+
#print(f"tomo aadido: {ai}")
|
|
34
|
+
elif line == "Energy":
|
|
35
|
+
energy_line = contcarfile.readline().strip()
|
|
36
|
+
energy = float(energy_line)
|
|
37
|
+
singlemol.info['e'] = energy
|
|
38
|
+
singlemol.info['i'] = '_'
|
|
39
|
+
#print(f"Energa registrada: {energy}")
|
|
40
|
+
if singlemol:
|
|
41
|
+
moleculas.append(singlemol)
|
|
42
|
+
return moleculas
|
|
43
|
+
#------------------------------------------------------------------------------------------
|
|
44
|
+
def writecfgs(poscarlist, file, force=False):
|
|
45
|
+
if not isinstance(poscarlist, list): poscarlist = [poscarlist]
|
|
46
|
+
f=open(file,"w")
|
|
47
|
+
poscarlist=tag(poscarlist)
|
|
48
|
+
for atoms in poscarlist:
|
|
49
|
+
print("BEGIN_CFG", file=f)
|
|
50
|
+
print(" Size", file=f)
|
|
51
|
+
natoms=len(atoms)
|
|
52
|
+
print(" %d" %(natoms), file=f)
|
|
53
|
+
if np.any(atoms.pbc):
|
|
54
|
+
print(" Supercell", file=f)
|
|
55
|
+
matrix=atoms.cell
|
|
56
|
+
print(" %10.6f %10.6f %10.6f" %(matrix[0,0],matrix[0,1],matrix[0,2]), file=f)
|
|
57
|
+
print(" %10.6f %10.6f %10.6f" %(matrix[1,0],matrix[1,1],matrix[1,2]), file=f)
|
|
58
|
+
print(" %10.6f %10.6f %10.6f" %(matrix[2,0],matrix[2,1],matrix[2,2]), file=f)
|
|
59
|
+
if force:
|
|
60
|
+
print(" AtomData: id type cartes_x cartes_y cartes_z fx fy fz",file=f)
|
|
61
|
+
forces=atoms.arrays['forces']
|
|
62
|
+
for k, atom in enumerate(atoms):
|
|
63
|
+
xc, yc, zc = atom.position
|
|
64
|
+
fx, fy, fz=forces[k]
|
|
65
|
+
tipo = atom.tag
|
|
66
|
+
print(" %2d %d %10.6f %10.6f %10.6f %9.6f %9.6f %9.6f" %(k+1,tipo,xc,yc,zc,fx,fy,fz), file=f)
|
|
67
|
+
else:
|
|
68
|
+
print(" AtomData: id type cartes_x cartes_y cartes_z", file=f)
|
|
69
|
+
for k, atom in enumerate(atoms):
|
|
70
|
+
xc, yc, zc = atom.position
|
|
71
|
+
tipo = atom.tag
|
|
72
|
+
print(" %d %d %10.6f %10.6f %10.6f" %(k+1,tipo,xc,yc,zc), file=f)
|
|
73
|
+
print(" Energy", file=f)
|
|
74
|
+
energy=atoms.info['e']
|
|
75
|
+
print(" %12.8f" %(energy), file=f)
|
|
76
|
+
print(" Feature EFS_by VASP", file=f)
|
|
77
|
+
print("END_CFG\n", file=f)
|
|
78
|
+
f.close()
|
|
79
|
+
#------------------------------------------------------------------------------------------
|
aegon/libclustering.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from sklearn.cluster import KMeans, AgglomerativeClustering, HDBSCAN
|
|
2
|
+
#----------------------------------------------------------------------------------------------------------
|
|
3
|
+
|
|
4
|
+
def clustering_agg(lista, descriptors, n_clusters):
|
|
5
|
+
|
|
6
|
+
if len(descriptors) < n_clusters:
|
|
7
|
+
print("La cantidad de descriptores es menor que el número de clusters. Devolviendo la lista original.")
|
|
8
|
+
return {0: lista}
|
|
9
|
+
else:
|
|
10
|
+
model = AgglomerativeClustering(n_clusters=n_clusters)
|
|
11
|
+
labels = model.fit_predict(descriptors)
|
|
12
|
+
|
|
13
|
+
clusters = {i: [] for i in range(n_clusters)}
|
|
14
|
+
for idx, label in enumerate(labels):
|
|
15
|
+
clusters[label].append(lista[idx])
|
|
16
|
+
|
|
17
|
+
return clusters
|
|
18
|
+
#-----------------------------------------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
def clustering_kmeans (lista, descriptors, n_clusters):
|
|
21
|
+
|
|
22
|
+
if len(descriptors) < n_clusters:
|
|
23
|
+
print("La cantidad de descriptores es menor que el número de clusters. Devolviendo la lista original.")
|
|
24
|
+
return {0: lista}
|
|
25
|
+
else:
|
|
26
|
+
model = KMeans(n_clusters=n_clusters, init='k-means++', max_iter=3000, tol=1e-7)
|
|
27
|
+
model.fit(descriptors)
|
|
28
|
+
labels = model.labels_
|
|
29
|
+
|
|
30
|
+
clusters = {i: [] for i in range(n_clusters)}
|
|
31
|
+
for idx, label in enumerate(labels):
|
|
32
|
+
clusters[label].append(lista[idx])
|
|
33
|
+
|
|
34
|
+
return clusters
|
|
35
|
+
#--------------------------------------------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
def clustering_hdbscan(lista, descriptores):
|
|
38
|
+
if len(descriptores) < 100:
|
|
39
|
+
print("La cantidad de descriptores es menor a 100. Devolviendo la lista original.")
|
|
40
|
+
return {0: lista}
|
|
41
|
+
|
|
42
|
+
model = HDBSCAN(min_cluster_size = 5, cluster_selection_epsilon = 0.2, cluster_selection_method = "eom")
|
|
43
|
+
#model = DBSCAN()
|
|
44
|
+
model.fit(descriptores)
|
|
45
|
+
|
|
46
|
+
labels = model.labels_
|
|
47
|
+
n_clus = len(set(labels))
|
|
48
|
+
|
|
49
|
+
clusters = {label: [] for label in set(labels)}
|
|
50
|
+
|
|
51
|
+
for idx, label in enumerate(labels):
|
|
52
|
+
clusters[label].append(lista[idx])
|
|
53
|
+
|
|
54
|
+
return clusters, n_clus
|
aegon/libcode.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from aegon.libcodegaussian import get_geometry_gaussian, get_traj_gaussian
|
|
2
|
+
from aegon.libcodeorca import get_geometry_orca, get_traj_orca
|
|
3
|
+
from aegon.libcodevasp import get_geometry_vasp, get_traj_vasp
|
|
4
|
+
from aegon.libcodegulp import get_geometry_gulp
|
|
5
|
+
from aegon.libcfg import writecfgs
|
|
6
|
+
from aegon.libutils import writexyzs
|
|
7
|
+
from aegon.libposcar import writeposcars
|
|
8
|
+
#------------------------------------------------------------------------------------------
|
|
9
|
+
# CREATION OF CLASSES
|
|
10
|
+
class read_out:
|
|
11
|
+
|
|
12
|
+
def __init__(self):
|
|
13
|
+
self.fileout_traj = {
|
|
14
|
+
"gaussian": get_traj_gaussian,
|
|
15
|
+
"orca": get_traj_orca,
|
|
16
|
+
"vasp": get_traj_vasp
|
|
17
|
+
}
|
|
18
|
+
self.fileout_geometry = {
|
|
19
|
+
"gaussian": get_geometry_gaussian,
|
|
20
|
+
"orca": get_geometry_orca,
|
|
21
|
+
"vasp": get_geometry_vasp,
|
|
22
|
+
"gulp": get_geometry_gulp
|
|
23
|
+
}
|
|
24
|
+
def traj(self, document, file_name, force=False):
|
|
25
|
+
if document not in self.fileout_traj:
|
|
26
|
+
raise ValueError(f"This '{document}' do not exist.")
|
|
27
|
+
if not isinstance(file_name, str):
|
|
28
|
+
raise TypeError("The second argument must be a (str).")
|
|
29
|
+
if not isinstance(force, bool):
|
|
30
|
+
raise TypeError("The third argument must be a boolean (True/False).")
|
|
31
|
+
return self.fileout_traj[document](file_name, force)
|
|
32
|
+
|
|
33
|
+
def geo(self,document,name):
|
|
34
|
+
if document not in self.fileout_geometry:
|
|
35
|
+
raise ValueError(f"This '{document}' do not exist.")
|
|
36
|
+
if not isinstance(name, str):
|
|
37
|
+
raise TypeError("The second argument must be a (str).")
|
|
38
|
+
return self.fileout_geometry[document](name)
|
|
39
|
+
#------------------------------------------------------------------------------------------
|
|
40
|
+
class write:
|
|
41
|
+
@classmethod
|
|
42
|
+
def cfg(cls, data, output_file, force=False):
|
|
43
|
+
try:
|
|
44
|
+
if isinstance(data, bool) and not data:
|
|
45
|
+
raise ValueError("Data is False. Cannot execute cfg.")
|
|
46
|
+
else:
|
|
47
|
+
if not isinstance(data, list):
|
|
48
|
+
data = [data]
|
|
49
|
+
if not isinstance(output_file, str):
|
|
50
|
+
raise ValueError("The first argument must be a (str).")
|
|
51
|
+
if not isinstance(force, bool):
|
|
52
|
+
raise ValueError("The second argument must be a boolean (True/False).")
|
|
53
|
+
writecfgs(data, output_file, force)
|
|
54
|
+
print("Writing %s" %(output_file))
|
|
55
|
+
except Exception as e:
|
|
56
|
+
print(f"Error in cfg: {e}")
|
|
57
|
+
@classmethod
|
|
58
|
+
def xyz(cls, data, output_file):
|
|
59
|
+
try:
|
|
60
|
+
if isinstance(data, bool) and not data:
|
|
61
|
+
raise ValueError("Data is False. Cannot execute cfg.")
|
|
62
|
+
else:
|
|
63
|
+
if not isinstance(data, list):
|
|
64
|
+
data = [data]
|
|
65
|
+
if not isinstance(output_file, str):
|
|
66
|
+
raise ValueError("The first argument must be a (str).")
|
|
67
|
+
writexyzs(data, output_file)
|
|
68
|
+
print("Writing %s" %(output_file))
|
|
69
|
+
except Exception as e:
|
|
70
|
+
print(f"Error in xyz: {e}")
|
|
71
|
+
@classmethod
|
|
72
|
+
def poscar(cls,data, output_file, opt='D'):
|
|
73
|
+
try:
|
|
74
|
+
if isinstance(data, bool) and not data:
|
|
75
|
+
raise ValueError("Data is False. Cannot execute cfg.")
|
|
76
|
+
else:
|
|
77
|
+
if not isinstance(data, list):
|
|
78
|
+
data = [data]
|
|
79
|
+
if not isinstance(output_file, str):
|
|
80
|
+
raise ValueError("The first argument must be a (str).")
|
|
81
|
+
if not isinstance(opt, str):
|
|
82
|
+
raise ValueError("The second argument must be a (str). \tOptions:D,C or other.")
|
|
83
|
+
writeposcars(data, output_file, opt)
|
|
84
|
+
print("Writing %s" %(output_file))
|
|
85
|
+
except Exception as e:
|
|
86
|
+
print(f"Error in vasp: {e}")
|
|
87
|
+
#------------------------------------------------------------------------------------------
|
aegon/libcodegaussian.py
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
import numpy as np
|
|
3
|
+
from ase import Atom, Atoms
|
|
4
|
+
from ase.data import chemical_symbols
|
|
5
|
+
#------------------------------------------------------------------------------------------
|
|
6
|
+
hartree2eV = 27.211386245981 #NIST
|
|
7
|
+
bohr2angstrom=0.529177210544 #NIST
|
|
8
|
+
eVtokcalpermol=23.060548012069496
|
|
9
|
+
hartree2kcalmol=627.5094738898777
|
|
10
|
+
#------------------------------------------------------------------------------------------
|
|
11
|
+
def get_termination_gaussian(pathfilename):
|
|
12
|
+
if os.path.isfile(pathfilename):
|
|
13
|
+
normal=0
|
|
14
|
+
gaufile=open(pathfilename,'r')
|
|
15
|
+
for line in gaufile:
|
|
16
|
+
if "Normal termination" in line: normal=normal+1
|
|
17
|
+
gaufile.close()
|
|
18
|
+
return normal
|
|
19
|
+
else:
|
|
20
|
+
return False
|
|
21
|
+
#------------------------------------------------------------------------------------------
|
|
22
|
+
def get_energy_gaussian(filename):
|
|
23
|
+
enehartree=float(0.0)
|
|
24
|
+
gaufile=open(filename,'r')
|
|
25
|
+
for line in gaufile:
|
|
26
|
+
if "SCF Done" in line:
|
|
27
|
+
scf=line.split()
|
|
28
|
+
enehartree=float(scf[4])
|
|
29
|
+
gaufile.close()
|
|
30
|
+
#enekcalmol=enehartree*hartree2kcalmol
|
|
31
|
+
eneeV = enehartree * hartree2eV
|
|
32
|
+
return eneeV
|
|
33
|
+
#------------------------------------------------------------------------------------------
|
|
34
|
+
def get_geometry_gaussian(pathfilename):
|
|
35
|
+
nt=get_termination_gaussian(pathfilename)
|
|
36
|
+
if nt==False: return False
|
|
37
|
+
energy=get_energy_gaussian(pathfilename)
|
|
38
|
+
filename = os.path.basename(pathfilename)
|
|
39
|
+
namein=filename.split('.')[0]
|
|
40
|
+
gaufile=open(pathfilename,'r')
|
|
41
|
+
for line in gaufile:
|
|
42
|
+
if line.strip() in ("Input orientation:", "Standard orientation:"):
|
|
43
|
+
moleculeout = Atoms()
|
|
44
|
+
moleculeout.info['c'] = nt
|
|
45
|
+
moleculeout.info['e'] = energy
|
|
46
|
+
moleculeout.info['i'] = namein
|
|
47
|
+
for ii in range(4): line=gaufile.readline()
|
|
48
|
+
line=gaufile.readline()
|
|
49
|
+
while not line.startswith(" --------"):
|
|
50
|
+
ls = line.split()
|
|
51
|
+
if (len(ls) == 6 and ls[0].isdigit() and ls[1].isdigit() and ls[2].isdigit()):
|
|
52
|
+
numero_atomico=int(ls[1])
|
|
53
|
+
ss = chemical_symbols[numero_atomico]
|
|
54
|
+
xc,yc,zc = float(ls[3]), float(ls[4]), float(ls[5])
|
|
55
|
+
ai=Atom(symbol=ss, position=(xc, yc, zc))
|
|
56
|
+
moleculeout.append(ai)
|
|
57
|
+
else:
|
|
58
|
+
break
|
|
59
|
+
line=gaufile.readline()
|
|
60
|
+
ls = line.split()
|
|
61
|
+
gaufile.close()
|
|
62
|
+
return moleculeout
|
|
63
|
+
#------------------------------------------------------------------------------------------
|
|
64
|
+
def get_traj_gaussian(pathfilename, force=False):
|
|
65
|
+
nt=get_termination_gaussian(pathfilename)
|
|
66
|
+
if nt==False: return False
|
|
67
|
+
filename=os.path.basename(pathfilename)
|
|
68
|
+
namein=filename.split('.')[0]
|
|
69
|
+
start, end, ene, start_2, end_2 = [], [], [], [], []
|
|
70
|
+
openold = open(pathfilename,"r")
|
|
71
|
+
rline = openold.readlines()
|
|
72
|
+
for i in range(len(rline)):
|
|
73
|
+
if "Standard orientation:" in rline[i]:
|
|
74
|
+
start.append(i+5)
|
|
75
|
+
for j in range(i+5, len(rline)):
|
|
76
|
+
if rline[j].strip().startswith("-"):
|
|
77
|
+
end.append(j - 1)
|
|
78
|
+
break
|
|
79
|
+
if "Forces (Hartrees/Bohr)" in rline[i] and force:
|
|
80
|
+
start_2.append(i+3)
|
|
81
|
+
for j in range(i + 3, len(rline)):
|
|
82
|
+
if rline[j].strip().startswith("-"):
|
|
83
|
+
end_2.append(j - 1)
|
|
84
|
+
break
|
|
85
|
+
if "SCF Done" in rline[i]:
|
|
86
|
+
eneline = rline[i].split()
|
|
87
|
+
ene.append(eneline[4])
|
|
88
|
+
moleculeout=[]
|
|
89
|
+
for i,iStart in enumerate(start[:-1]):
|
|
90
|
+
enehartree=float(ene[i])
|
|
91
|
+
eneeV = enehartree * hartree2eV
|
|
92
|
+
singlemol = Atoms()
|
|
93
|
+
singlemol.info['e'] = eneeV
|
|
94
|
+
singlemol.info['c'] = nt
|
|
95
|
+
singlemol.info['i'] = namein+'_'+str(i+1).zfill(3)
|
|
96
|
+
for line in rline[start[i] : end[i]+1]:
|
|
97
|
+
words = line.split()
|
|
98
|
+
numero_atomico = int(words[1])
|
|
99
|
+
ss = chemical_symbols[numero_atomico]
|
|
100
|
+
xc,yc,zc = float(words[3]), float(words[4]), float(words[5])
|
|
101
|
+
ai=Atom(symbol=ss,position=(xc, yc, zc))
|
|
102
|
+
singlemol.append(ai)
|
|
103
|
+
if force:
|
|
104
|
+
forces_list_by_group = []
|
|
105
|
+
for line in rline[start_2[i] : end_2[i]+1]:
|
|
106
|
+
words = line.split()
|
|
107
|
+
fx,fy,fz = float(words[2]), float(words[3]), float(words[4])
|
|
108
|
+
fx=fx*hartree2eV/bohr2angstrom
|
|
109
|
+
fy=fy*hartree2eV/bohr2angstrom
|
|
110
|
+
fz=fz*hartree2eV/bohr2angstrom
|
|
111
|
+
#IN ev/A
|
|
112
|
+
forces_list_by_group.append([fx,fy,fz])
|
|
113
|
+
singlemol.arrays['forces'] = np.array(forces_list_by_group)
|
|
114
|
+
moleculeout.extend([singlemol])
|
|
115
|
+
openold.close()
|
|
116
|
+
return (moleculeout)
|
|
117
|
+
#------------------------------------------------------------------------------------------
|
|
118
|
+
def get_freqneg_gaussian(pathfilename):
|
|
119
|
+
gaufile=open(pathfilename,'r')
|
|
120
|
+
freq_negative=0
|
|
121
|
+
freq_neg_list=[]
|
|
122
|
+
for line in gaufile:
|
|
123
|
+
if "Frequencies" in line:
|
|
124
|
+
freq=line.split()
|
|
125
|
+
freq.pop(0)
|
|
126
|
+
freq.pop(0)
|
|
127
|
+
for ifreq in range(len(freq)):
|
|
128
|
+
if float(freq[ifreq]) < 0.0:
|
|
129
|
+
freq_negative=freq_negative+1
|
|
130
|
+
freq_neg_list.append(float(freq[ifreq]))
|
|
131
|
+
gaufile.close()
|
|
132
|
+
freq_neg_list.sort()
|
|
133
|
+
freq_sample= freq_neg_list[0] if (freq_negative > 0) else 0.0
|
|
134
|
+
return freq_negative, freq_sample
|
|
135
|
+
#------------------------------------------------------------------------------------------
|
|
136
|
+
#------------------------------------------------------------------------------------------
|
|
137
|
+
#------------------------------------------------------------------------------------------
|
|
138
|
+
def make_a_input(singlemol, level='#WB97XD def2TZVP OPT SCF=(XQC) FREQ' , folder='./'):
|
|
139
|
+
nameinp=singlemol.info['i']+'.inp'
|
|
140
|
+
fh=open(folder+nameinp,"w")
|
|
141
|
+
print("%NprocShared=13", file=fh)
|
|
142
|
+
print("%MEM=16GB", file=fh)
|
|
143
|
+
print("%s\n" %(level), file=fh)
|
|
144
|
+
print("Comment: %s\n" %(singlemol.info['i']), file=fh)
|
|
145
|
+
print("%d %d" %(singlemol.info['q'],singlemol.info['m']), file=fh)
|
|
146
|
+
for iatom in singlemol:
|
|
147
|
+
sym = iatom.symbol
|
|
148
|
+
xc, yc, zc = iatom.position
|
|
149
|
+
print ("%-2s %16.9f %16.9f %16.9f" % (sym,xc,yc,zc), file=fh)
|
|
150
|
+
fh.write("\n")
|
|
151
|
+
fh.close()
|
|
152
|
+
#------------------------------------------------------------------------------------------
|