mlatom 2.0.1__py3.7.egg
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.
- EGG-INFO/PKG-INFO +145 -0
- EGG-INFO/SOURCES.txt +40 -0
- EGG-INFO/dependency_links.txt +1 -0
- EGG-INFO/native_libs.txt +1 -0
- EGG-INFO/not-zip-safe +1 -0
- EGG-INFO/requires.txt +2 -0
- EGG-INFO/scripts/MLatomF +12 -0
- EGG-INFO/scripts/mlatom +12 -0
- EGG-INFO/top_level.txt +1 -0
- MLatom/ML_NEA.py +2697 -0
- MLatom/MLatom.py +151 -0
- MLatom/MLatomF +0 -0
- MLatom/MLtasks.py +784 -0
- MLatom/__init__.py +0 -0
- MLatom/__pycache__/ML_NEA.cpython-37.pyc +0 -0
- MLatom/__pycache__/MLatom.cpython-37.pyc +0 -0
- MLatom/__pycache__/MLtasks.cpython-37.pyc +0 -0
- MLatom/__pycache__/__init__.cpython-37.pyc +0 -0
- MLatom/__pycache__/args_class.cpython-37.pyc +0 -0
- MLatom/__pycache__/doc.cpython-37.pyc +0 -0
- MLatom/__pycache__/header.cpython-37.pyc +0 -0
- MLatom/__pycache__/interface_MLatomF.cpython-37.pyc +0 -0
- MLatom/__pycache__/sliceData.cpython-37.pyc +0 -0
- MLatom/__pycache__/stopper.cpython-37.pyc +0 -0
- MLatom/args_class.py +396 -0
- MLatom/cs.so +0 -0
- MLatom/doc.py +620 -0
- MLatom/header.py +64 -0
- MLatom/interface_MLatomF.py +87 -0
- MLatom/interfaces/DeePMDkit/DP_inference.py +20 -0
- MLatom/interfaces/DeePMDkit/__init__.py +0 -0
- MLatom/interfaces/DeePMDkit/__pycache__/DP_inference.cpython-37.pyc +0 -0
- MLatom/interfaces/DeePMDkit/__pycache__/__init__.cpython-37.pyc +0 -0
- MLatom/interfaces/DeePMDkit/__pycache__/interface_DeePMDkit.cpython-37.pyc +0 -0
- MLatom/interfaces/DeePMDkit/interface_DeePMDkit.py +327 -0
- MLatom/interfaces/DeePMDkit/template.json +70 -0
- MLatom/interfaces/GAP/__init__.py +0 -0
- MLatom/interfaces/GAP/__pycache__/__init__.cpython-37.pyc +0 -0
- MLatom/interfaces/GAP/__pycache__/interface_GAP.cpython-37.pyc +0 -0
- MLatom/interfaces/GAP/interface_GAP.py +415 -0
- MLatom/interfaces/PhysNet/PhysNet_predict.py +180 -0
- MLatom/interfaces/PhysNet/PhysNet_train.py +425 -0
- MLatom/interfaces/PhysNet/__init__.py +0 -0
- MLatom/interfaces/PhysNet/__pycache__/PhysNet_predict.cpython-37.pyc +0 -0
- MLatom/interfaces/PhysNet/__pycache__/PhysNet_train.cpython-37.pyc +0 -0
- MLatom/interfaces/PhysNet/__pycache__/__init__.cpython-37.pyc +0 -0
- MLatom/interfaces/PhysNet/__pycache__/interface_PhysNet.cpython-37.pyc +0 -0
- MLatom/interfaces/PhysNet/interface_PhysNet.py +270 -0
- MLatom/interfaces/TorchANI/TorchANI_predict.py +82 -0
- MLatom/interfaces/TorchANI/TorchANI_train.py +217 -0
- MLatom/interfaces/TorchANI/__init__.py +0 -0
- MLatom/interfaces/TorchANI/__pycache__/TorchANI_predict.cpython-37.pyc +0 -0
- MLatom/interfaces/TorchANI/__pycache__/TorchANI_train.cpython-37.pyc +0 -0
- MLatom/interfaces/TorchANI/__pycache__/__init__.cpython-37.pyc +0 -0
- MLatom/interfaces/TorchANI/__pycache__/interface_TorchANI.cpython-37.pyc +0 -0
- MLatom/interfaces/TorchANI/interface_TorchANI.py +323 -0
- MLatom/interfaces/__init__.py +0 -0
- MLatom/interfaces/__pycache__/__init__.cpython-37.pyc +0 -0
- MLatom/interfaces/sGDML/__init__.py +0 -0
- MLatom/interfaces/sGDML/__pycache__/__init__.cpython-37.pyc +0 -0
- MLatom/interfaces/sGDML/__pycache__/interface_sGDML.cpython-37.pyc +0 -0
- MLatom/interfaces/sGDML/__pycache__/sgdml_dataset_from_extxyz.cpython-37.pyc +0 -0
- MLatom/interfaces/sGDML/interface_sGDML.py +276 -0
- MLatom/interfaces/sGDML/sgdml_dataset_from_extxyz.py +199 -0
- MLatom/ref.json +23 -0
- MLatom/sliceData.py +334 -0
- MLatom/stopper.py +17 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
'''
|
|
3
|
+
!---------------------------------------------------------------------------!
|
|
4
|
+
! Interface_TorchANI: Interface between TorchANI and MLatom !
|
|
5
|
+
! Implementations by: Fuchun Ge and Max Pinheiro Jr !
|
|
6
|
+
!---------------------------------------------------------------------------!
|
|
7
|
+
'''
|
|
8
|
+
import numpy as np
|
|
9
|
+
import os, sys, subprocess, time, shutil, re, math, random
|
|
10
|
+
import stopper
|
|
11
|
+
from args_class import ArgsBase
|
|
12
|
+
|
|
13
|
+
filedir = os.path.dirname(__file__)
|
|
14
|
+
|
|
15
|
+
class Args(ArgsBase):
|
|
16
|
+
def __init__(self):
|
|
17
|
+
super().__init__()
|
|
18
|
+
self.add_default_dict_args([
|
|
19
|
+
'learningCurve'
|
|
20
|
+
],
|
|
21
|
+
bool
|
|
22
|
+
)
|
|
23
|
+
self.add_default_dict_args([
|
|
24
|
+
'xyzfile', 'yfile', 'ygradxyzfile','itrainin','itestin','isubtrainin','ivalidatein','mlmodelin','setname'
|
|
25
|
+
],
|
|
26
|
+
""
|
|
27
|
+
)
|
|
28
|
+
self.add_dict_args({
|
|
29
|
+
'mlmodeltype': 'ANI',
|
|
30
|
+
'mlmodelout': "ANIbestmodel.pt",
|
|
31
|
+
'sampling': "random",
|
|
32
|
+
'yestfile': "enest.dat",
|
|
33
|
+
'ygradxyzestfile': "gradest.dat",
|
|
34
|
+
'lcNtrains': [],
|
|
35
|
+
'natom': 0,
|
|
36
|
+
'atype': []
|
|
37
|
+
})
|
|
38
|
+
self.parse_input_content([
|
|
39
|
+
'ani.batch_size=8',
|
|
40
|
+
'ani.max_epochs=10000000',
|
|
41
|
+
'ani.early_stopping_learning_rate=0.00001',
|
|
42
|
+
'ani.force_coefficient=0.1',
|
|
43
|
+
'ani.batch_sizes=0',
|
|
44
|
+
'ani.patience=100',
|
|
45
|
+
'ani.lrfactor=0.5',
|
|
46
|
+
'ani.Rcr=5.2',
|
|
47
|
+
'ani.Rca=3.5',
|
|
48
|
+
'ani.EtaR=16',
|
|
49
|
+
'ani.ShfR=0.9,1.16875,1.4375,1.70625,1.975,2.24375,2.5125,2.78125,3.05,3.31875,3.5875,3.85625,4.125,4.39375,4.6625,4.93125',
|
|
50
|
+
'ani.Zeta=32',
|
|
51
|
+
'ani.ShfZ=0.19634954,0.58904862,0.9817477,1.3744468,1.7671459,2.1598449,2.552544,2.9452431',
|
|
52
|
+
'ani.EtaA=8',
|
|
53
|
+
'ani.ShfA=0.90,1.55,2.20,2.85',
|
|
54
|
+
'ani.Neuron_l1=160',
|
|
55
|
+
'ani.Neuron_l2=128',
|
|
56
|
+
'ani.Neuron_l3=96',
|
|
57
|
+
'ani.AF1=CELU',
|
|
58
|
+
'ani.AF2=CELU',
|
|
59
|
+
'ani.AF3=CELU'
|
|
60
|
+
])
|
|
61
|
+
|
|
62
|
+
def parse(self, argsraw):
|
|
63
|
+
self.parse_input_content(argsraw)
|
|
64
|
+
self.argProcess()
|
|
65
|
+
|
|
66
|
+
def argProcess(self):
|
|
67
|
+
for k, v in self.ani.data.items():
|
|
68
|
+
if k.lower() in ['shfr','etar','zeta','shfz','shfz','etaa','shfa']:
|
|
69
|
+
self.ani.data[k] = torch.tensor([float(i) for i in str(v).split(',')])
|
|
70
|
+
elif k.lower() in ['neuron_l1','neuron_l2','neuron_l3']:
|
|
71
|
+
self.ani.data[k] =[int(i) for i in str(v).split(',')]
|
|
72
|
+
elif k.lower() in ['af1','af2','af3']:
|
|
73
|
+
self.ani.data[k] = v.split(',')
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
with open(self.xyzfile,'r') as f:
|
|
77
|
+
self.natom = int(f.readline())
|
|
78
|
+
exec('f.readline()')
|
|
79
|
+
self.atype = [f.readline().split()[0] for i in range(self.natom)]
|
|
80
|
+
|
|
81
|
+
if not self.mlmodelin:
|
|
82
|
+
self.mlmodelin = self.mlmodelout
|
|
83
|
+
|
|
84
|
+
species_order = sorted(set(self.atype), key=lambda x: self.atype.index(x))
|
|
85
|
+
if len(self.ani.Neuron_l1) == 1: self.ani.Neuron_l1 = self.ani.Neuron_l1*len(species_order)
|
|
86
|
+
if len(self.ani.Neuron_l2) == 1: self.ani.Neuron_l2 = self.ani.Neuron_l2*len(species_order)
|
|
87
|
+
if len(self.ani.Neuron_l3) == 1: self.ani.Neuron_l3 = self.ani.Neuron_l3*len(species_order)
|
|
88
|
+
# if self.lcyonly: self.ygradxyzfile=''
|
|
89
|
+
|
|
90
|
+
if not self.ani.batch_size:
|
|
91
|
+
if self.ntrain: self.ani.batch_size = int(math.sqrt(self.ntrain))
|
|
92
|
+
else: self.ani.batch_size=8
|
|
93
|
+
|
|
94
|
+
if self.learningcurve:
|
|
95
|
+
self.lcNtrains = [int(i) for i in str(self.lcNtrains).split(',')]
|
|
96
|
+
if self.ani.batch_sizes:
|
|
97
|
+
self.ani.batch_sizes = [int(i) for i in self.lcNtrains.split(',')]
|
|
98
|
+
self.ani.batch_size = self.ani.batch_sizes[self.lcNtrains.index(self.ntrain)]
|
|
99
|
+
|
|
100
|
+
class ANICls(object):
|
|
101
|
+
dataConverted = False
|
|
102
|
+
@classmethod
|
|
103
|
+
def load(cls):
|
|
104
|
+
loaded=False
|
|
105
|
+
if not loaded:
|
|
106
|
+
|
|
107
|
+
available = True
|
|
108
|
+
try:
|
|
109
|
+
import h5py
|
|
110
|
+
import torch
|
|
111
|
+
from . import TorchANI_train
|
|
112
|
+
from . import TorchANI_predict
|
|
113
|
+
except:
|
|
114
|
+
available = False
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
globals()['available'] = available
|
|
118
|
+
globals()['h5py'] = h5py
|
|
119
|
+
globals()['torch'] = torch
|
|
120
|
+
globals()['TorchANI_train'] = TorchANI_train
|
|
121
|
+
globals()['TorchANI_predict'] = TorchANI_predict
|
|
122
|
+
|
|
123
|
+
cls.batch_size = 8
|
|
124
|
+
cls.max_epochs = 10000000
|
|
125
|
+
cls.early_stopping_learning_rate = 1.0E-5
|
|
126
|
+
cls.force_coefficient = 0.1
|
|
127
|
+
cls.batch_sizes = []
|
|
128
|
+
cls.patience = 100
|
|
129
|
+
cls.lrfactor = 0.5
|
|
130
|
+
cls.Rcr = 5.2000e+00
|
|
131
|
+
cls.Rca = 3.5000e+00
|
|
132
|
+
cls.EtaR = torch.tensor([1.6000000e+01])
|
|
133
|
+
cls.ShfR = torch.tensor([9.0000000e-01, 1.1687500e+00, 1.4375000e+00, 1.7062500e+00, 1.9750000e+00, 2.2437500e+00, 2.5125000e+00, 2.7812500e+00, 3.0500000e+00, 3.3187500e+00, 3.5875000e+00, 3.8562500e+00, 4.1250000e+00, 4.3937500e+00, 4.6625000e+00, 4.9312500e+00])
|
|
134
|
+
cls.Zeta = torch.tensor([3.2000000e+01])
|
|
135
|
+
cls.ShfZ = torch.tensor([1.9634954e-01, 5.8904862e-01, 9.8174770e-01, 1.3744468e+00, 1.7671459e+00, 2.1598449e+00, 2.5525440e+00, 2.9452431e+00])
|
|
136
|
+
cls.EtaA = torch.tensor([8.0000000e+00])
|
|
137
|
+
cls.ShfA = torch.tensor([9.0000000e-01, 1.5500000e+00, 2.2000000e+00, 2.8500000e+00])
|
|
138
|
+
cls.Neuron_l1 = [160]
|
|
139
|
+
cls.Neuron_l2 = [128]
|
|
140
|
+
cls.Neuron_l3 = [96]
|
|
141
|
+
cls.AF1 = ['CELU']
|
|
142
|
+
cls.AF2 = ['CELU']
|
|
143
|
+
cls.AF3 = ['CELU']
|
|
144
|
+
|
|
145
|
+
loaded=True
|
|
146
|
+
|
|
147
|
+
def __init__(self, argsANI = sys.argv[1:]):
|
|
148
|
+
print(' ___________________________________________________________\n\n%s' % __doc__)
|
|
149
|
+
|
|
150
|
+
@classmethod
|
|
151
|
+
def convertdata(cls, argsANI, subdatasets):
|
|
152
|
+
cls.load()
|
|
153
|
+
def convert(fileout, setname, yorgrad=False):
|
|
154
|
+
# convert data to .h5 format
|
|
155
|
+
prefix = ''
|
|
156
|
+
if args.learningcurve: prefix = '../'
|
|
157
|
+
if setname:
|
|
158
|
+
coordfile = prefix+'xyz.dat_'+setname
|
|
159
|
+
yfile = prefix+'y.dat_'+setname
|
|
160
|
+
gradfile = prefix+'grad.dat_'+setname
|
|
161
|
+
else:
|
|
162
|
+
coordfile = args.xyzfile
|
|
163
|
+
if args.yfile and yorgrad: yfile = args.yfile
|
|
164
|
+
if args.ygradxyzfile and yorgrad: gradfile = args.ygradxyzfile
|
|
165
|
+
|
|
166
|
+
with open(coordfile ,'r') as fxyz:
|
|
167
|
+
natom_max=0
|
|
168
|
+
for line in fxyz:
|
|
169
|
+
natom = int(line)
|
|
170
|
+
natom_max = max(natom_max, natom)
|
|
171
|
+
for i in range(natom+1):
|
|
172
|
+
fxyz.readline()
|
|
173
|
+
fxyz.seek(0)
|
|
174
|
+
data={}
|
|
175
|
+
# data['smiles'] = np.array([args.smiles.encode('ascii')])
|
|
176
|
+
data['species'] = np.array([i.encode('ascii') for i in args.atype])
|
|
177
|
+
data['coordinates'] = np.array([])
|
|
178
|
+
if args.yfile and yorgrad:
|
|
179
|
+
fy = open(yfile,'r')
|
|
180
|
+
data['energies'] = np.array([])
|
|
181
|
+
if args.ygradxyzfile and yorgrad:
|
|
182
|
+
fgrad = open(gradfile,'r')
|
|
183
|
+
data['forces'] = np.array([])
|
|
184
|
+
for line in fxyz:
|
|
185
|
+
natom = int(line)
|
|
186
|
+
if args.ygradxyzfile and yorgrad: fgrad.readline()
|
|
187
|
+
|
|
188
|
+
if args.yfile and yorgrad: data['energies'] =np.append(data['energies'], float(fy.readline()))
|
|
189
|
+
fxyz.readline()
|
|
190
|
+
if args.ygradxyzfile and yorgrad: fgrad.readline()
|
|
191
|
+
|
|
192
|
+
for i in range(natom):
|
|
193
|
+
data['coordinates'] = np.append(data['coordinates'], [float(i) for i in fxyz.readline().split()[-3:]])
|
|
194
|
+
if args.ygradxyzfile and yorgrad:
|
|
195
|
+
data['forces'] = np.append(data['forces'], [-1*float(i) for i in fgrad.readline().split()[-3:]])
|
|
196
|
+
for i in range(natom_max-natom):
|
|
197
|
+
data['coordinates'] = np.append(data['coordinates'], np.zeros(3))
|
|
198
|
+
if args.ygradxyzfile and yorgrad:
|
|
199
|
+
data['forces'] = np.append(data['forces'], np.zeros(3))
|
|
200
|
+
|
|
201
|
+
if args.yfile and yorgrad: fy.close()
|
|
202
|
+
if args.ygradxyzfile and yorgrad: fgrad.close()
|
|
203
|
+
data['coordinates'] = data['coordinates'].reshape(-1,natom_max,3)
|
|
204
|
+
if args.ygradxyzfile and yorgrad: data['forces'] = data['forces'].reshape(-1,natom_max,3)
|
|
205
|
+
|
|
206
|
+
hf = h5py.File(fileout, 'w')
|
|
207
|
+
grp = hf.create_group('dataset')
|
|
208
|
+
subgrp = grp.create_group('molecule')
|
|
209
|
+
for k, v in data.items():
|
|
210
|
+
subgrp[k] = v
|
|
211
|
+
|
|
212
|
+
if not available:
|
|
213
|
+
stopper.stopMLatom('Please install all Python module required for TorchANI')
|
|
214
|
+
|
|
215
|
+
args = Args()
|
|
216
|
+
args.parse(argsANI)
|
|
217
|
+
print('\n Converting data...\n\n')
|
|
218
|
+
if subdatasets:
|
|
219
|
+
if 'Subtrain' in subdatasets:
|
|
220
|
+
for i in subdatasets:
|
|
221
|
+
if i in ['Subtrain', 'Validate']: convert('ANI_'+i.lower()+'.h5', i.lower(),True)
|
|
222
|
+
else: convert('ANI_'+i.lower()+'.h5', i.lower())
|
|
223
|
+
else:
|
|
224
|
+
for i in subdatasets:
|
|
225
|
+
if i == 'Train': convert('ANI_'+i.lower()+'.h5', i.lower(),True)
|
|
226
|
+
else: convert('ANI_'+i.lower()+'.h5', i.lower())
|
|
227
|
+
else: convert('ANI.h5', '')
|
|
228
|
+
|
|
229
|
+
@classmethod
|
|
230
|
+
def createMLmodel(cls, argsANI, subdatasets):
|
|
231
|
+
cls.load()
|
|
232
|
+
args = Args()
|
|
233
|
+
args.parse(argsANI)
|
|
234
|
+
|
|
235
|
+
if not cls.dataConverted or args.learningcurve:
|
|
236
|
+
cls.convertdata(argsANI, subdatasets)
|
|
237
|
+
cls.dataConverted = True
|
|
238
|
+
|
|
239
|
+
starttime = time.time()
|
|
240
|
+
|
|
241
|
+
# if args.mlmodeltype.lower() in ['ani1x','ani1ccx','ani2x']:
|
|
242
|
+
# print('ML model already built in TorchANI')
|
|
243
|
+
if False:
|
|
244
|
+
pass
|
|
245
|
+
else:
|
|
246
|
+
TorchANI_train.train(args)
|
|
247
|
+
|
|
248
|
+
endtime = time.time()
|
|
249
|
+
wallclock = endtime - starttime
|
|
250
|
+
return wallclock
|
|
251
|
+
|
|
252
|
+
@classmethod
|
|
253
|
+
def useMLmodel(cls, argsANI, subdatasets):
|
|
254
|
+
cls.load()
|
|
255
|
+
args = Args()
|
|
256
|
+
args.parse(argsANI)
|
|
257
|
+
|
|
258
|
+
if not cls.dataConverted:
|
|
259
|
+
cls.convertdata(argsANI, subdatasets)
|
|
260
|
+
cls.dataConverted = True
|
|
261
|
+
|
|
262
|
+
starttime = time.time()
|
|
263
|
+
|
|
264
|
+
TorchANI_predict.predict(args)
|
|
265
|
+
|
|
266
|
+
endtime = time.time()
|
|
267
|
+
wallclock = endtime - starttime
|
|
268
|
+
return wallclock
|
|
269
|
+
|
|
270
|
+
def printHelp():
|
|
271
|
+
helpText = __doc__ + '''
|
|
272
|
+
To use Interface_ANI, please install TorchANI and its dependencies
|
|
273
|
+
|
|
274
|
+
Arguments with their default values:
|
|
275
|
+
MLprog=TorchANI enables this interface
|
|
276
|
+
MLmodelType=ANI requests ANI model
|
|
277
|
+
|
|
278
|
+
ani.batch_size=8 batch size
|
|
279
|
+
ani.max_epochs=10000000 max epochs
|
|
280
|
+
|
|
281
|
+
ani.early_stopping_learning_rate=0.00001
|
|
282
|
+
learning rate that triggers early-stopping
|
|
283
|
+
|
|
284
|
+
ani.force_coefficient=0.1 weight for force
|
|
285
|
+
ani.Rcr=5.2 radial cutoff radius
|
|
286
|
+
ani.Rca=3.5 angular cutoff radius
|
|
287
|
+
ani.EtaR=1.6 radial smoothness in radial part
|
|
288
|
+
|
|
289
|
+
ani.ShfR=0.9,1.16875, radial shifts in radial part
|
|
290
|
+
1.4375,1.70625,1.975,
|
|
291
|
+
2.24375,2.5125,2.78125,
|
|
292
|
+
3.05,3.31875,3.5875,
|
|
293
|
+
3.85625,4.125,4.9375,
|
|
294
|
+
4.6625,4.93125
|
|
295
|
+
|
|
296
|
+
ani.Zeta=32 angular smoothness
|
|
297
|
+
|
|
298
|
+
ani.ShfZ=0.19634954, angular shifts
|
|
299
|
+
0.58904862,0.9817477,
|
|
300
|
+
1.3744468,1.7671459,
|
|
301
|
+
2.1598449,2.552544,
|
|
302
|
+
2.9452431
|
|
303
|
+
|
|
304
|
+
ani.EtaA=8 radial smoothness in angular part
|
|
305
|
+
ani.ShfA=0.9,1.55,2.2,2.85 radial shifts in angular part
|
|
306
|
+
ani.Neuron_l1=160 number of neurons in layer 1
|
|
307
|
+
ani.Neuron_l2=128 number of neurons in layer 2
|
|
308
|
+
ani.Neuron_l3=96 number of neurons in layer 3
|
|
309
|
+
ani.AF1='CELU' acitivation function for layer 1
|
|
310
|
+
ani.AF2='CELU' acitivation function for layer 2
|
|
311
|
+
ani.AF3='CELU' acitivation function for layer 3
|
|
312
|
+
|
|
313
|
+
Cite TorchANI:
|
|
314
|
+
X. Gao, F. Ramezanghorbani, O. Isayev, J. S. Smith, A. E. Roitberg,
|
|
315
|
+
J. Chem. Inf. Model. 2020, 60, 3408
|
|
316
|
+
|
|
317
|
+
Cite ANI model:
|
|
318
|
+
J. S. Smith, O. Isayev, A. E. Roitberg, Chem. Sci. 2017, 8, 3192
|
|
319
|
+
'''
|
|
320
|
+
print(helpText)
|
|
321
|
+
|
|
322
|
+
if __name__ == '__main__':
|
|
323
|
+
ANICls()
|
|
File without changes
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
'''
|
|
3
|
+
!---------------------------------------------------------------------------!
|
|
4
|
+
! Interface_sGDML: Interface between sGDML and MLatom !
|
|
5
|
+
! Implementations by: Fuchun Ge !
|
|
6
|
+
!---------------------------------------------------------------------------!
|
|
7
|
+
'''
|
|
8
|
+
from typing import Tuple
|
|
9
|
+
import numpy as np
|
|
10
|
+
import os, sys, subprocess, time, shutil, re, math, random
|
|
11
|
+
import stopper
|
|
12
|
+
from args_class import ArgsBase
|
|
13
|
+
|
|
14
|
+
filedir = os.path.dirname(__file__)
|
|
15
|
+
|
|
16
|
+
class Args(ArgsBase):
|
|
17
|
+
def __init__(self):
|
|
18
|
+
super().__init__()
|
|
19
|
+
self.add_default_dict_args([
|
|
20
|
+
'learningCurve',
|
|
21
|
+
],
|
|
22
|
+
bool
|
|
23
|
+
)
|
|
24
|
+
self.add_default_dict_args([
|
|
25
|
+
'mlmodeltype'
|
|
26
|
+
],
|
|
27
|
+
'sgdml'
|
|
28
|
+
)
|
|
29
|
+
self.add_default_dict_args([
|
|
30
|
+
'xyzfile', 'yfile', 'ygradxyzfile','itrainin','itestin','isubtrainin','ivalidatein','mlmodelin','setname'
|
|
31
|
+
],
|
|
32
|
+
""
|
|
33
|
+
)
|
|
34
|
+
self.add_dict_args({
|
|
35
|
+
'nthreads': 1,
|
|
36
|
+
'mlmodelout': "sGDML",
|
|
37
|
+
'sampling': "random",
|
|
38
|
+
'yestfile': "enest.dat",
|
|
39
|
+
'ygradxyzestfile': "gradest.dat"
|
|
40
|
+
})
|
|
41
|
+
self.parse_input_content([
|
|
42
|
+
'sGDML.torch=false ',
|
|
43
|
+
'sGDML.gdml=false ',
|
|
44
|
+
'sGDML.cprsn=false ',
|
|
45
|
+
'sGDML.no_E=false ',
|
|
46
|
+
'sGDML.s=false'
|
|
47
|
+
])
|
|
48
|
+
|
|
49
|
+
def parse(self, argsraw):
|
|
50
|
+
self.parse_input_content(argsraw)
|
|
51
|
+
self.argProcess()
|
|
52
|
+
|
|
53
|
+
def argProcess(self):
|
|
54
|
+
with open(self.xyzfile,'r') as f:
|
|
55
|
+
sGDMLCls.natom = int(f.readline())
|
|
56
|
+
exec('f.readline()')
|
|
57
|
+
sGDMLCls.atype = [f.readline().split()[0] for i in range(sGDMLCls.natom)]
|
|
58
|
+
|
|
59
|
+
# for estAccMLmodel that MLmodelIn may not be provided
|
|
60
|
+
if self.mlmodelout[-4:] != '.npz': self.mlmodelout += '.npz'
|
|
61
|
+
if not self.mlmodelin:
|
|
62
|
+
self.mlmodelin = self.mlmodelout
|
|
63
|
+
|
|
64
|
+
if self.sGDML.s:
|
|
65
|
+
sigmas = self.sGDML.s.split(',')
|
|
66
|
+
self.sGDML.s = []
|
|
67
|
+
for i in range(len(sigmas)):
|
|
68
|
+
self.sGDML.s.append(sigmas[i])
|
|
69
|
+
self.sGDML.s.reverse()
|
|
70
|
+
if self.mlmodeltype.lower()=='gdml':
|
|
71
|
+
self.sGDML.gdml = True
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class sGDMLCls(object):
|
|
76
|
+
setname = ''
|
|
77
|
+
atype = ''
|
|
78
|
+
natom = 0
|
|
79
|
+
nsubtrain = 0
|
|
80
|
+
nvalidate = 0
|
|
81
|
+
dataConverted = False
|
|
82
|
+
@classmethod
|
|
83
|
+
def load(cls):
|
|
84
|
+
loaded=False
|
|
85
|
+
if not loaded:
|
|
86
|
+
try:
|
|
87
|
+
sGDMLbin = os.environ['sGDML']
|
|
88
|
+
from . import sgdml_dataset_from_extxyz
|
|
89
|
+
from sgdml.predict import GDMLPredict
|
|
90
|
+
from sgdml.utils import io
|
|
91
|
+
globals()['sGDMLbin'] = sGDMLbin
|
|
92
|
+
globals()['sgdml_dataset_from_extxyz'] = sgdml_dataset_from_extxyz
|
|
93
|
+
globals()['GDMLPredict'] = GDMLPredict
|
|
94
|
+
globals()['io'] = io
|
|
95
|
+
except:
|
|
96
|
+
stopper.stopMLatom('Please specify sGDML bin in $sGDML')
|
|
97
|
+
loaded=True
|
|
98
|
+
|
|
99
|
+
def __init__(self, argssGDML = sys.argv[1:]):
|
|
100
|
+
print(' ___________________________________________________________\n\n%s' % __doc__)
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def convertdata(cls, argssGDML, subdatasets):
|
|
104
|
+
cls.load()
|
|
105
|
+
def convert(fileout, setname, yorgrad=False):
|
|
106
|
+
# convert data to .exyz format
|
|
107
|
+
prefix = ''
|
|
108
|
+
if args.learningcurve: prefix = '../'
|
|
109
|
+
if setname:
|
|
110
|
+
coordfile = prefix+'xyz.dat_'+setname
|
|
111
|
+
yfile = prefix+'y.dat_'+setname
|
|
112
|
+
gradfile = prefix+'grad.dat_'+setname
|
|
113
|
+
else:
|
|
114
|
+
coordfile = args.xyzfile
|
|
115
|
+
if args.yfile and yorgrad: yfile = args.yfile
|
|
116
|
+
if args.ygradxyzfile and yorgrad: gradfile = args.ygradxyzfile
|
|
117
|
+
with open(fileout, 'w') as fo, open(coordfile ,'r') as fxyz:
|
|
118
|
+
if args.yfile and yorgrad: fy = open(yfile,'r')
|
|
119
|
+
if args.ygradxyzfile and yorgrad: fgrad = open(gradfile,'r')
|
|
120
|
+
for line in fxyz:
|
|
121
|
+
if setname == 'subtrain': cls.nsubtrain += 1
|
|
122
|
+
if setname == 'validate': cls.nvalidate += 1
|
|
123
|
+
natom = int(line)
|
|
124
|
+
fo.write(line)
|
|
125
|
+
if args.ygradxyzfile and yorgrad: fgrad.readline()
|
|
126
|
+
|
|
127
|
+
if args.yfile and yorgrad: fo.write('%s '% fy.readline()[:-1])
|
|
128
|
+
fo.write('\n')
|
|
129
|
+
fxyz.readline()
|
|
130
|
+
if args.ygradxyzfile and yorgrad: fgrad.readline()
|
|
131
|
+
|
|
132
|
+
for i in range(natom):
|
|
133
|
+
fo.write(fxyz.readline()[:-1])
|
|
134
|
+
if args.ygradxyzfile and yorgrad:
|
|
135
|
+
fo.write('%24.15f %24.15f %24.15f' % tuple(-1*float(i) for i in fgrad.readline().split()[-3:]))
|
|
136
|
+
fo.write('\n')
|
|
137
|
+
if args.yfile and yorgrad: fy.close()
|
|
138
|
+
if args.ygradxyzfile and yorgrad: fgrad.close()
|
|
139
|
+
|
|
140
|
+
if yorgrad: sgdml_dataset_from_extxyz.convert(fileout)
|
|
141
|
+
|
|
142
|
+
args = Args()
|
|
143
|
+
args.parse(argssGDML)
|
|
144
|
+
print('\n Converting data...\n\n')
|
|
145
|
+
if subdatasets:
|
|
146
|
+
if 'Subtrain' in subdatasets:
|
|
147
|
+
for i in subdatasets:
|
|
148
|
+
if i in ['Subtrain', 'Validate']: convert('sGDML_'+i.lower()+'.xyz', i.lower(),True)
|
|
149
|
+
else: convert('sGDML_'+i.lower()+'.xyz', i.lower())
|
|
150
|
+
else:
|
|
151
|
+
for i in subdatasets:
|
|
152
|
+
if i == 'Train': convert('sGDML_'+i.lower()+'.xyz', i.lower(),True)
|
|
153
|
+
else: convert('sGDML_'+i.lower()+'.xyz', i.lower())
|
|
154
|
+
else: convert('sGDML.xyz', '')
|
|
155
|
+
|
|
156
|
+
@classmethod
|
|
157
|
+
def createMLmodel(cls, argssGDML, subdatasets):
|
|
158
|
+
cls.load()
|
|
159
|
+
args = Args()
|
|
160
|
+
args.parse(argssGDML)
|
|
161
|
+
|
|
162
|
+
if not cls.dataConverted or args.learningcurve:
|
|
163
|
+
cls.convertdata(argssGDML, subdatasets)
|
|
164
|
+
cls.dataConverted = True
|
|
165
|
+
|
|
166
|
+
cmds = [
|
|
167
|
+
[sGDMLbin, 'create', '-p', str(args.nthreads), '-v', 'sGDML_validate.npz', '--task_dir', 'sGDMLtask', 'sGDML_subtrain.npz', str(cls.nsubtrain), str(cls.nvalidate)],
|
|
168
|
+
[sGDMLbin, 'train', '-p', str(args.nthreads), 'sGDMLtask'],
|
|
169
|
+
[sGDMLbin, 'validate', '-p', str(args.nthreads), 'sGDMLtask', 'sGDML_validate.npz'],
|
|
170
|
+
[sGDMLbin, 'select', '-p', str(args.nthreads), '--model_file', args.mlmodelout, 'sGDMLtask'],
|
|
171
|
+
[sGDMLbin, 'show', '-o', '-p', str(args.nthreads), args.mlmodelout]
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
if args.sGDML.E_cstr: cmds[0].insert(6, '--E_cstr')
|
|
175
|
+
if args.sGDML.no_E: cmds[0].insert(6, '--no_E')
|
|
176
|
+
if args.sGDML.cprsn: cmds[0].insert(6, '--cprsn')
|
|
177
|
+
if args.sGDML.gdml: cmds[0].insert(6, '--gdml')
|
|
178
|
+
if args.sGDML.s:
|
|
179
|
+
for i in args.sGDML.s:
|
|
180
|
+
cmds[0].insert(6, i)
|
|
181
|
+
cmds[0].insert(6, '-s')
|
|
182
|
+
if args.sGDML.torch:
|
|
183
|
+
cmds[0].insert(4, '--torch')
|
|
184
|
+
cmds[1].insert(4, '--torch')
|
|
185
|
+
cmds[2].insert(4, '--torch')
|
|
186
|
+
cmds[3].insert(4, '--torch')
|
|
187
|
+
|
|
188
|
+
cls.nsubtrain = 0
|
|
189
|
+
cls.nvalidate = 0
|
|
190
|
+
|
|
191
|
+
FNULL = open(os.devnull, 'w')
|
|
192
|
+
|
|
193
|
+
starttime = time.time()
|
|
194
|
+
|
|
195
|
+
for cmd in cmds:
|
|
196
|
+
print('> sgdml '+' '.join(cmd[1:]))
|
|
197
|
+
sys.stdout.flush()
|
|
198
|
+
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE ,stderr=subprocess.PIPE)
|
|
199
|
+
for line in iter(proc.stdout.readline, b''):
|
|
200
|
+
print(line.decode('ascii').replace('\n',''))
|
|
201
|
+
sys.stdout.flush()
|
|
202
|
+
proc.stdout.close()
|
|
203
|
+
FNULL.close()
|
|
204
|
+
|
|
205
|
+
endtime = time.time()
|
|
206
|
+
wallclock = endtime - starttime
|
|
207
|
+
return wallclock
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
@classmethod
|
|
211
|
+
def useMLmodel(cls, argssGDML, subdatasets):
|
|
212
|
+
cls.load()
|
|
213
|
+
args = Args()
|
|
214
|
+
args.parse(argssGDML)
|
|
215
|
+
|
|
216
|
+
if not cls.dataConverted:
|
|
217
|
+
cls.convertdata(argssGDML, subdatasets)
|
|
218
|
+
cls.dataConverted = True
|
|
219
|
+
|
|
220
|
+
if args.setname: args.setname='_'+args.setname
|
|
221
|
+
|
|
222
|
+
starttime = time.time()
|
|
223
|
+
|
|
224
|
+
model = np.load(args.mlmodelin)
|
|
225
|
+
gdml = GDMLPredict(model)
|
|
226
|
+
|
|
227
|
+
r,_ = io.read_xyz('sGDML'+args.setname+'.xyz') # 9 atoms
|
|
228
|
+
e,f = gdml.predict(r)
|
|
229
|
+
|
|
230
|
+
line="%d\n\n" % int(cls.natom)
|
|
231
|
+
with open(args.yestfile,'wb') as ff:
|
|
232
|
+
np.savetxt(ff, e, fmt='%12.6f', delimiter=" ")
|
|
233
|
+
with open(args.ygradxyzestfile,'wb') as ff:
|
|
234
|
+
for force in f:
|
|
235
|
+
ff.write(line.encode('utf-8'))
|
|
236
|
+
np.savetxt(ff, -1*force.reshape(-1,3), fmt='%12.6f', delimiter=" ")
|
|
237
|
+
|
|
238
|
+
endtime = time.time()
|
|
239
|
+
wallclock = endtime - starttime
|
|
240
|
+
return wallclock
|
|
241
|
+
def printHelp():
|
|
242
|
+
helpText = __doc__ + '''
|
|
243
|
+
To use Interface_sGDML, please set enviromental variable $sGDML
|
|
244
|
+
to the path of the sGDML executable
|
|
245
|
+
|
|
246
|
+
Arguments with their default values:
|
|
247
|
+
MLprog=sGDML enables this interface
|
|
248
|
+
MLmodelType=S requests model S
|
|
249
|
+
sGDML [defaut]
|
|
250
|
+
GDML
|
|
251
|
+
sgdml.gdml=False use GDML instead of sGDML
|
|
252
|
+
sgdml.cprsn=False compress kernel matrix along symmetric
|
|
253
|
+
degrees of freedom
|
|
254
|
+
sgdml.no_E=False do not predict energies
|
|
255
|
+
sgdml.E_cstr=False include the energy constraints in the
|
|
256
|
+
kernel
|
|
257
|
+
sgdml.s=<s1>[,<s2>[,...]] set hyperparameter sigma
|
|
258
|
+
=<start>:[<step>:]<stop>
|
|
259
|
+
|
|
260
|
+
Cite sGDML program:
|
|
261
|
+
S. Chmiela, H. E. Sauceda, I. Poltavsky, K.-R. Müller, A. Tkatchenko,
|
|
262
|
+
Comput. Phys. Commun. 2019, 240, 38
|
|
263
|
+
|
|
264
|
+
Cite GDML method, if you use it:
|
|
265
|
+
S. Chmiela, A. Tkatchenko, H. E. Sauceda, I. Poltavsky, K. T. Schütt,
|
|
266
|
+
K.-R. Müller, Sci. Adv. 2017, 3, e1603015
|
|
267
|
+
|
|
268
|
+
Cite sGDML method, if you use it:
|
|
269
|
+
S. Chmiela, H. E. Sauceda, K.-R. Müller, A. Tkatchenko,
|
|
270
|
+
Nat. Commun. 2018, 9, 3887
|
|
271
|
+
|
|
272
|
+
'''
|
|
273
|
+
print(helpText)
|
|
274
|
+
|
|
275
|
+
if __name__ == '__main__':
|
|
276
|
+
sGDMLCls()
|