-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTemperature_class.py
More file actions
353 lines (315 loc) · 13 KB
/
Copy pathTemperature_class.py
File metadata and controls
353 lines (315 loc) · 13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# -*- coding: utf-8 -*-
"""
Created on Sat Sep 17 22:44:15 2016
@author: gilles
"""
import numpy as np
import math
import re
#Boltzmann constant: KJ/(K.mol)
KB = (0.0083144621)
class Temperature:
"""Temperature class used for simulated tempering
_____________________________
Arguments to create instance:
-----------------------------
No arguments needed.
Constructor takes parameters from the ST.param file.
The parameters taken from ST.param are:
--> temp_min : the base temperature of the simulation (K)
--> temp_max : the peak temperature of the simulation (K)
--> temp_interval : difference between two neighbouring temperatures
___________
Attributes:
-----------
min (int) : base ST temperature
max (int) : peak ST temperature
interval (int) : difference between two neighbouring temperatures
current (int) : current temperature used in the ST
next (int) : next temperature to be tested for a temperature transition
conv_coef (float): velocity conversion factor used to convert a .gro files
temp_dict : Global temperature dictionary which contains a
subdictionary associated to each temperature.
Each of these subdictionaries contains:
--> beta: 1/KB*temp (KB is Boltzmann constant)
--> weight: temperature weight
--> Ep: accumulated potential energy
--> n: number of simulation runs done at this temperature
"""
def __init__(self):
self.min, \
self.max, \
self.interval, \
self.temp_dict = self.init_temperatures_from_file()
self.current = self.min
self.next = self.min + self.interval
self.conv_coef = (self.next/self.current)**0.5
def init_temperatures_from_file(self):
""" Initializes a temperature dictionary from file
__________
Arguments:
----------
No arguments. Takes parameters from ST.param file.
The parameters taken from ST.param are:
--> temp_min : the base temperature of the simulation (K)
--> temp_max : the peak temperature of the simulation (K)
--> temp_interval : difference between two neighbouring temperatures
_______
Return:
-------
Global temperature dictionary which contains a subdictionary associated
to each temperature.
Each of these subdictionaries contains:
--> beta: 1/KB*temp (KB is Boltzmann constant)
--> weight: temperature weight
--> Ep: accumulated average potential energy
--> n: number of simulation runs done at this temperature
"""
# Initialize variables with -1
min, max, interval = [-1]*3
# Get temperatures from parameters file
f_param = open('ST.par', 'r')
for line in f_param:
if line.startswith('temp_min'):
min = int(re.findall("\d+", line)[0])
elif line.startswith('temp_max'):
max = int(re.findall("\d+", line)[0])
elif line.startswith('temp_interval'):
interval = int(re.findall("\d+", line)[0])
f_param.close()
# TODO: throw exception if variables are not found in file
temp_dict = self.init_temperatures(min, max, interval)
return min, max, interval, temp_dict
def init_temperatures(self, min, max, interval):
""" Initializes a temperature dictionary from arguments
__________
Arguments:
----------
min (int) : base ST temperature
max (int) : peak ST temperature
interval (int) : difference between two neighbouring temperatures
_______
Return:
-------
Global temperature dictionary which contains a subdictionary associated
to each temperature.
Each of these subdictionaries contains:
--> beta: 1/KB*temp (KB is Boltzmann constant)
--> weight: temperature weight
--> Ep: accumulated average potential energy
--> n: number of simulation runs done at this temperature
"""
# Temperature dictionary for the starting temperature (min) :
# Dictionary containing beta, average potential energy, weight,
# and number of simulations for a given temperature (min in this case).
# Starting temperature has weight = zero
t_dict = {'beta': 1/(KB*min),
'weight': 0,
'Ep': float('NaN'),
'n': 0}
# Adding the first temperature dictionary to the global dictionary t
# that will contain the dictionaries of all temperatures
# (min to max with a given interval bewteen neighbouring temperatures).
t = {min: t_dict}
# Populating the global temperature dictionary:
for temp in xrange(min+interval, max+interval, interval):
# Dictionary containing beta, average potiential energy, weight,
# and number of simulations for a given temperature, respectively.
# Starting temperature weight was set to zero.
# The other temperature weights are set as Not a Number for now.
t_dict = {'beta': 1/(KB*temp),
'weight': 0,
'Ep': float('NaN'),
'n': 0}
t[temp] = t_dict
return t
def get_beta(self, temp):
""" Get a given temperature's beta value from the temp_dict attribute
__________
Arguments:
----------
temp (int): a temperature
_______
Return:
-------
beta value associated to given temperature (float)
"""
return self.temp_dict[temp]['beta']
def set_beta(self, temp, beta):
self.temp_dict[temp]['beta'] = beta
""" Set a given temperature's beta value in the temp_dict attribute
__________
Arguments:
----------
temp (int): a temperature
beta (float): a beta value
"""
def get_weight(self, temp):
""" Get a given temperature's weight from the temp_dict attribute
__________
Arguments:
----------
temp (int): a temperature
_______
Return:
-------
weight value associated to given temperature (float)
"""
return self.temp_dict[temp]['weight']
def set_weight(self, temp, weight):
""" Set a given temperature's weight in the temp_dict attribute
__________
Arguments:
----------
temp (int): a temperature
weight (float): temperature's weight
"""
self.temp_dict[temp]['weight'] = weight
def get_Ep(self, temp):
""" Get a given temperature's accumulated average potential energy
from the temp_dict attribute
__________
Arguments:
----------
temp (int): a temperature
_______
Return:
-------
Accumulated average potential energy associated to given temperature (float)
"""
return self.temp_dict[temp]['Ep']
def set_Ep(self, temp, Ep):
""" Set a given temperature's accumulated average potential energy
in the temp_dict attribute
__________
Arguments:
----------
temp (int): a temperature
Ep (float): temperature's accumulated average potential energy
"""
self.temp_dict[temp]['Ep'] = Ep
def get_n(self, temp):
""" Get a given temperature's number of simulation runs
__________
Arguments:
----------
temp (int): a temperature
_______
Return:
-------
number of simulation runs associated to given temperature (int)
"""
return self.temp_dict[temp]['n']
def set_n(self, temp, n):
""" Set a given temperature's number of simulation runs
in the temp_dict attribute
__________
Arguments:
----------
temp (int): a temperature
n (int): temperature's number of simulation runs
"""
self.temp_dict[temp]['n'] = n
def update_next(self, up_down):
""" Update next temperature to be tested for a temperature transition
(i.e. the 'next' attribute)
__________
Arguments:
----------
up_down (int): can be -1 or 1
if up_down = -1 --> chose neighbouring lower temperature
if up_down = 1 --> chose neighbouring upper temperature
"""
self.next = self.current + up_down*self.interval
def update_weight(self, temp2):
""" Calculate weight for a given temperature
and set new weight in the temp_dict attribute
__________
Arguments:
----------
temp2 (int) : temperature for which we want to calculate the weight
_______
Method:
-------
Finds weight of temperature n using:
---> beta of temperature n and n-1
---> accumulated average potential energy of temperature n and n-1
---> weight of temperature n-1
According to the formula (Nguyen 2013):
new_weight2 = weight1 + (b2 - b1)*(Ep2 + Ep1)/2
if temperature n does not yet have a potential energy, use:
new_weight2 = (b2 - b1)*Ep1/2
"""
# if temp is base temperature, weight is zero.
if temp2 == self.min:
self.set_weight(temp2, 0)
return
# if next temperature is withing temperature bounds:
elif self.min < temp2 <= self.max:
#continue
temp1 = temp2 - self.interval
#if stepping outside temperature bounds
else:
return
weight1 = self.get_weight(temp1)
b1 = self.get_beta(temp1)
b2 = self.get_beta(temp2)
Ep1 = self.get_Ep(temp1)
Ep2 = self.get_Ep(temp2)
#if energy for temp2 has not been calculated:
if math.isnan(Ep2):
new_weight2 = (b2 - b1)*Ep1/2
else:
new_weight2 = weight1 + (b2 - b1)*(Ep2 + Ep1)/2
self.set_weight(temp2, new_weight2)
def transition(self):
""" Applies the temperature transition.
Prepares temp_current attribute for the next md.
Also recalculates the velocity conversion vactor (conv_coef)
"""
self.conv_coef = (float(self.next)/self.current)**0.5
self.current = self.next
def test_transition(self, temp1, temp2):
""" Applies the transition test to see if we will change temperatures
for the next MD run.
Uses the transition probability.
_______
Return:
-------
(bool) True if test is successful, False if test failed.
"""
p = self.transition_proba(temp1, temp2)
return np.random.choice([True, False], 1, p=[p, 1-p])[0]
def transition_proba(self, temp1, temp2):
""" Caclculates the temperature transition probability from temp1 to temp2.
Uses:
---> beta of temperature 1 and 2
---> accumulated average potential energy of temperature 1 and 2
---> weight of temperature 1
According to the formula (Nguyen 2013):
proba = exp(-(((beta2 - beta1)*Ep1 - (weight2 - weight1))))
_______
Return:
-------
(float) temperature transition probability
"""
b1 = self.get_beta(temp1)
b2 = self.get_beta(temp2)
w1 = self.get_weight(temp1)
w2 = self.get_weight(temp2)
Ep1 = self.get_Ep(temp1)
try:
proba = math.exp(-(((b2 - b1)*Ep1 - (w2 - w1))))
print "######## transition proba: " + str(proba)
except OverflowError:
print "######## transition proba: 1"
if -(((b2 - b1)*Ep1 - (w2 - w1))) > 0:
proba = 1
else:
proba = 0
# # Write probabilites in file
# # TEST: REMOVE LATER
# f = open('proba.dat', 'a') # TEST TO BE REMOVED
# f.write(str(proba) + '\n') # TEST TO REMOVE
# f.close() # TEST TO REMOVE
return min(1, proba)