calphy 1.4.5__py3-none-any.whl → 1.4.12__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.
- calphy/__init__.py +1 -1
- calphy/alchemy.py +278 -158
- calphy/composition_transformation.py +298 -136
- calphy/helpers.py +45 -29
- calphy/input.py +81 -3
- calphy/liquid.py +13 -0
- calphy/phase.py +55 -4
- calphy/phase_diagram.py +196 -53
- calphy/routines.py +6 -0
- calphy/scheduler.py +100 -105
- calphy/solid.py +243 -186
- {calphy-1.4.5.dist-info → calphy-1.4.12.dist-info}/METADATA +1 -1
- calphy-1.4.12.dist-info/RECORD +25 -0
- {calphy-1.4.5.dist-info → calphy-1.4.12.dist-info}/WHEEL +1 -1
- calphy-1.4.5.dist-info/RECORD +0 -25
- {calphy-1.4.5.dist-info → calphy-1.4.12.dist-info}/entry_points.txt +0 -0
- {calphy-1.4.5.dist-info → calphy-1.4.12.dist-info}/licenses/LICENSE +0 -0
- {calphy-1.4.5.dist-info → calphy-1.4.12.dist-info}/top_level.txt +0 -0
calphy/__init__.py
CHANGED
calphy/alchemy.py
CHANGED
|
@@ -3,14 +3,14 @@ calphy: a Python library and command line interface for automated free
|
|
|
3
3
|
energy calculations.
|
|
4
4
|
|
|
5
5
|
Copyright 2021 (c) Sarath Menon^1, Yury Lysogorskiy^2, Ralf Drautz^2
|
|
6
|
-
^1: Max Planck Institut für Eisenforschung, Dusseldorf, Germany
|
|
6
|
+
^1: Max Planck Institut für Eisenforschung, Dusseldorf, Germany
|
|
7
7
|
^2: Ruhr-University Bochum, Bochum, Germany
|
|
8
8
|
|
|
9
|
-
calphy is published and distributed under the Academic Software License v1.0 (ASL).
|
|
10
|
-
calphy is distributed in the hope that it will be useful for non-commercial academic research,
|
|
11
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
9
|
+
calphy is published and distributed under the Academic Software License v1.0 (ASL).
|
|
10
|
+
calphy is distributed in the hope that it will be useful for non-commercial academic research,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
12
12
|
calphy API is published and distributed under the BSD 3-Clause "New" or "Revised" License
|
|
13
|
-
See the LICENSE FILE for more details.
|
|
13
|
+
See the LICENSE FILE for more details.
|
|
14
14
|
|
|
15
15
|
More information about the program can be found in:
|
|
16
16
|
Menon, Sarath, Yury Lysogorskiy, Jutta Rogal, and Ralf Drautz.
|
|
@@ -27,11 +27,13 @@ Notes
|
|
|
27
27
|
|
|
28
28
|
import numpy as np
|
|
29
29
|
import yaml
|
|
30
|
+
import os
|
|
30
31
|
|
|
31
32
|
from calphy.integrators import *
|
|
32
33
|
import calphy.helpers as ph
|
|
33
34
|
import calphy.phase as cph
|
|
34
35
|
|
|
36
|
+
|
|
35
37
|
class Alchemy(cph.Phase):
|
|
36
38
|
"""
|
|
37
39
|
Class for alchemical transformations
|
|
@@ -40,7 +42,7 @@ class Alchemy(cph.Phase):
|
|
|
40
42
|
----------
|
|
41
43
|
options : dict
|
|
42
44
|
dict of input options
|
|
43
|
-
|
|
45
|
+
|
|
44
46
|
kernel : int
|
|
45
47
|
the index of the calculation that should be run from
|
|
46
48
|
the list of calculations in the input file
|
|
@@ -49,13 +51,13 @@ class Alchemy(cph.Phase):
|
|
|
49
51
|
base folder for running calculations
|
|
50
52
|
|
|
51
53
|
"""
|
|
52
|
-
def __init__(self, calculation=None, simfolder=None, log_to_screen=False):
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
super().__init__(calculation=calculation,
|
|
56
|
-
simfolder=simfolder,
|
|
57
|
-
log_to_screen=log_to_screen)
|
|
55
|
+
def __init__(self, calculation=None, simfolder=None, log_to_screen=False):
|
|
58
56
|
|
|
57
|
+
# call base class
|
|
58
|
+
super().__init__(
|
|
59
|
+
calculation=calculation, simfolder=simfolder, log_to_screen=log_to_screen
|
|
60
|
+
)
|
|
59
61
|
|
|
60
62
|
def run_averaging(self):
|
|
61
63
|
"""
|
|
@@ -76,53 +78,58 @@ class Alchemy(cph.Phase):
|
|
|
76
78
|
If pressure is specified, MD simulations are run until the pressure converges within the given
|
|
77
79
|
threshold value.
|
|
78
80
|
Fix lattice option is not implemented at present.
|
|
79
|
-
At the end of the run, the averaged box dimensions are calculated.
|
|
81
|
+
At the end of the run, the averaged box dimensions are calculated.
|
|
80
82
|
"""
|
|
81
|
-
lmp = ph.create_object(
|
|
82
|
-
self.
|
|
83
|
+
lmp = ph.create_object(
|
|
84
|
+
self.cores,
|
|
85
|
+
self.simfolder,
|
|
86
|
+
self.calc.md.timestep,
|
|
87
|
+
self.calc.md.cmdargs,
|
|
88
|
+
self.calc.md.init_commands,
|
|
89
|
+
)
|
|
83
90
|
|
|
84
|
-
lmp.command(f
|
|
91
|
+
lmp.command(f"pair_style {self.calc._pair_style_with_options[0]}")
|
|
85
92
|
|
|
86
|
-
#set up structure
|
|
93
|
+
# set up structure
|
|
87
94
|
lmp = ph.create_structure(lmp, self.calc)
|
|
88
95
|
|
|
89
|
-
#set up potential
|
|
90
|
-
lmp.command(f
|
|
96
|
+
# set up potential
|
|
97
|
+
lmp.command(f"pair_coeff {self.calc.pair_coeff[0]}")
|
|
91
98
|
lmp = ph.set_mass(lmp, self.calc)
|
|
92
99
|
|
|
93
|
-
#add some computes
|
|
100
|
+
# add some computes
|
|
94
101
|
lmp.command("variable mvol equal vol")
|
|
95
102
|
lmp.command("variable mlx equal lx")
|
|
96
103
|
lmp.command("variable mly equal ly")
|
|
97
104
|
lmp.command("variable mlz equal lz")
|
|
98
105
|
lmp.command("variable mpress equal press")
|
|
99
106
|
|
|
100
|
-
#add some computes
|
|
107
|
+
# add some computes
|
|
101
108
|
if not self.calc._fix_lattice:
|
|
102
109
|
if self.calc._pressure == 0:
|
|
103
110
|
self.run_zero_pressure_equilibration(lmp)
|
|
104
111
|
else:
|
|
105
112
|
self.run_finite_pressure_equilibration(lmp)
|
|
106
113
|
|
|
107
|
-
|
|
108
|
-
#this is when the averaging routine starts
|
|
114
|
+
# this is when the averaging routine starts
|
|
109
115
|
self.run_pressure_convergence(lmp)
|
|
110
|
-
|
|
111
|
-
#run if a constrained lattice is used
|
|
116
|
+
|
|
117
|
+
# run if a constrained lattice is used
|
|
112
118
|
else:
|
|
113
|
-
#routine in which lattice constant will not varied, but is set to a given fixed value
|
|
114
|
-
self.run_constrained_pressure_convergence(lmp)
|
|
119
|
+
# routine in which lattice constant will not varied, but is set to a given fixed value
|
|
120
|
+
self.run_constrained_pressure_convergence(lmp)
|
|
115
121
|
|
|
116
|
-
#check for melting
|
|
122
|
+
# check for melting
|
|
117
123
|
self.dump_current_snapshot(lmp, "traj.equilibration_stage2.dat")
|
|
118
124
|
self.check_if_melted(lmp, "traj.equilibration_stage2.dat")
|
|
119
125
|
|
|
120
|
-
#close object and process traj
|
|
126
|
+
# close object and process traj
|
|
121
127
|
lmp = ph.write_data(lmp, "conf.equilibration.data")
|
|
122
128
|
lmp.close()
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
# Preserve log file
|
|
130
|
+
logfile = os.path.join(self.simfolder, "log.lammps")
|
|
131
|
+
if os.path.exists(logfile):
|
|
132
|
+
os.rename(logfile, os.path.join(self.simfolder, "averaging.log.lammps"))
|
|
126
133
|
|
|
127
134
|
def run_integration(self, iteration=1):
|
|
128
135
|
"""
|
|
@@ -143,111 +150,186 @@ class Alchemy(cph.Phase):
|
|
|
143
150
|
the lambda parameter. See algorithm 4 in publication.
|
|
144
151
|
"""
|
|
145
152
|
|
|
146
|
-
#create lammps object
|
|
147
|
-
lmp = ph.create_object(
|
|
148
|
-
self.
|
|
149
|
-
|
|
153
|
+
# create lammps object
|
|
154
|
+
lmp = ph.create_object(
|
|
155
|
+
self.cores,
|
|
156
|
+
self.simfolder,
|
|
157
|
+
self.calc.md.timestep,
|
|
158
|
+
self.calc.md.cmdargs,
|
|
159
|
+
self.calc.md.init_commands,
|
|
160
|
+
)
|
|
161
|
+
|
|
150
162
|
# Adiabatic switching parameters.
|
|
151
163
|
lmp.command("variable li equal 1.0")
|
|
152
164
|
lmp.command("variable lf equal 0.0")
|
|
153
165
|
|
|
154
|
-
lmp.command(f
|
|
155
|
-
|
|
156
|
-
#read dump file
|
|
157
|
-
#conf = os.path.join(self.simfolder, "conf.equilibration.dump")
|
|
166
|
+
lmp.command(f"pair_style {self.calc._pair_style_with_options[0]}")
|
|
167
|
+
|
|
168
|
+
# read dump file
|
|
169
|
+
# conf = os.path.join(self.simfolder, "conf.equilibration.dump")
|
|
158
170
|
conf = os.path.join(self.simfolder, "conf.equilibration.data")
|
|
159
171
|
lmp = ph.read_data(lmp, conf)
|
|
160
172
|
|
|
161
|
-
#set up hybrid potential
|
|
162
|
-
#here we only need to set one potential
|
|
163
|
-
lmp.command(f
|
|
173
|
+
# set up hybrid potential
|
|
174
|
+
# here we only need to set one potential
|
|
175
|
+
lmp.command(f"pair_coeff {self.calc.pair_coeff[0]}")
|
|
164
176
|
lmp = ph.set_mass(lmp, self.calc)
|
|
165
177
|
|
|
166
|
-
#NEW ADDED
|
|
178
|
+
# NEW ADDED
|
|
167
179
|
lmp.command("group g1 type 1")
|
|
168
180
|
lmp.command("group g2 type 2")
|
|
169
|
-
#lmp = ph.set_double_hybrid_potential(lmp, self.options, self.calc._pressureair_style, self.calc._pressureair_coeff)
|
|
181
|
+
# lmp = ph.set_double_hybrid_potential(lmp, self.options, self.calc._pressureair_style, self.calc._pressureair_coeff)
|
|
170
182
|
|
|
171
|
-
#remap the box to get the correct pressure
|
|
183
|
+
# remap the box to get the correct pressure
|
|
172
184
|
lmp = ph.remap_box(lmp, self.lx, self.ly, self.lz)
|
|
173
185
|
|
|
174
|
-
lmp.command(
|
|
186
|
+
lmp.command(
|
|
187
|
+
"velocity all create %f %d mom yes rot yes dist gaussian"
|
|
188
|
+
% (self.calc._temperature, np.random.randint(1, 10000))
|
|
189
|
+
)
|
|
175
190
|
# Integrator & thermostat.
|
|
176
191
|
if self.calc.npt:
|
|
177
|
-
lmp.command(
|
|
178
|
-
|
|
192
|
+
lmp.command(
|
|
193
|
+
"fix f1 all npt temp %f %f %f %s %f %f %f"
|
|
194
|
+
% (
|
|
195
|
+
self.calc._temperature,
|
|
196
|
+
self.calc._temperature,
|
|
197
|
+
self.calc.md.thermostat_damping[1],
|
|
198
|
+
self.iso,
|
|
199
|
+
self.calc._pressure,
|
|
200
|
+
self.calc._pressure,
|
|
201
|
+
self.calc.md.barostat_damping[1],
|
|
202
|
+
)
|
|
203
|
+
)
|
|
179
204
|
else:
|
|
180
|
-
lmp.command(
|
|
181
|
-
|
|
205
|
+
lmp.command(
|
|
206
|
+
"fix f1 all nvt temp %f %f %f"
|
|
207
|
+
% (
|
|
208
|
+
self.calc._temperature,
|
|
209
|
+
self.calc._temperature,
|
|
210
|
+
self.calc.md.thermostat_damping[1],
|
|
211
|
+
)
|
|
212
|
+
)
|
|
182
213
|
|
|
183
|
-
|
|
184
214
|
lmp.command("thermo_style custom step pe")
|
|
185
215
|
lmp.command("thermo 1000")
|
|
186
|
-
lmp.command("run %d"%self.calc.n_equilibration_steps)
|
|
187
|
-
|
|
216
|
+
lmp.command("run %d" % self.calc.n_equilibration_steps)
|
|
217
|
+
|
|
218
|
+
# equilibration run is over
|
|
188
219
|
|
|
189
|
-
#
|
|
190
|
-
|
|
191
|
-
#---------------------------------------------------------------
|
|
220
|
+
# ---------------------------------------------------------------
|
|
192
221
|
# FWD cycle
|
|
193
|
-
|
|
222
|
+
# ---------------------------------------------------------------
|
|
194
223
|
lmp.command("variable flambda equal ramp(${li},${lf})")
|
|
195
224
|
lmp.command("variable blambda equal ramp(${lf},${li})")
|
|
196
|
-
|
|
197
|
-
#lmp.command("pair_style hybrid/scaled v_flambda %s v_blambda ufm 7.5"%self.options["md"]["pair_style"])
|
|
198
|
-
|
|
225
|
+
|
|
226
|
+
# lmp.command("pair_style hybrid/scaled v_flambda %s v_blambda ufm 7.5"%self.options["md"]["pair_style"])
|
|
227
|
+
|
|
199
228
|
# Compute pair definitions
|
|
200
229
|
if self.calc.pair_style[0] == self.calc.pair_style[1]:
|
|
201
|
-
pc =
|
|
230
|
+
pc = self.calc.pair_coeff[0]
|
|
202
231
|
pcraw = pc.split()
|
|
203
|
-
pc1 = " ".join(
|
|
204
|
-
|
|
232
|
+
pc1 = " ".join(
|
|
233
|
+
[
|
|
234
|
+
*pcraw[:2],
|
|
235
|
+
*[
|
|
236
|
+
self.calc._pair_style_names[0],
|
|
237
|
+
],
|
|
238
|
+
"1",
|
|
239
|
+
*pcraw[2:],
|
|
240
|
+
]
|
|
241
|
+
)
|
|
242
|
+
pc = self.calc.pair_coeff[1]
|
|
205
243
|
pcraw = pc.split()
|
|
206
|
-
pc2 = " ".join(
|
|
244
|
+
pc2 = " ".join(
|
|
245
|
+
[
|
|
246
|
+
*pcraw[:2],
|
|
247
|
+
*[
|
|
248
|
+
self.calc._pair_style_names[1],
|
|
249
|
+
],
|
|
250
|
+
"2",
|
|
251
|
+
*pcraw[2:],
|
|
252
|
+
]
|
|
253
|
+
)
|
|
207
254
|
else:
|
|
208
|
-
pc =
|
|
255
|
+
pc = self.calc.pair_coeff[0]
|
|
209
256
|
pcraw = pc.split()
|
|
210
|
-
pc1 = " ".join(
|
|
211
|
-
|
|
257
|
+
pc1 = " ".join(
|
|
258
|
+
[
|
|
259
|
+
*pcraw[:2],
|
|
260
|
+
*[
|
|
261
|
+
self.calc._pair_style_names[0],
|
|
262
|
+
],
|
|
263
|
+
*pcraw[2:],
|
|
264
|
+
]
|
|
265
|
+
)
|
|
266
|
+
pc = self.calc.pair_coeff[1]
|
|
212
267
|
pcraw = pc.split()
|
|
213
|
-
pc2 = " ".join(
|
|
214
|
-
|
|
268
|
+
pc2 = " ".join(
|
|
269
|
+
[
|
|
270
|
+
*pcraw[:2],
|
|
271
|
+
*[
|
|
272
|
+
self.calc._pair_style_names[1],
|
|
273
|
+
],
|
|
274
|
+
*pcraw[2:],
|
|
275
|
+
]
|
|
276
|
+
)
|
|
215
277
|
|
|
216
|
-
lmp.command(
|
|
217
|
-
|
|
218
|
-
|
|
278
|
+
lmp.command(
|
|
279
|
+
"pair_style hybrid/scaled v_flambda %s v_blambda %s"
|
|
280
|
+
% (
|
|
281
|
+
self.calc._pair_style_with_options[0],
|
|
282
|
+
self.calc._pair_style_with_options[1],
|
|
219
283
|
)
|
|
220
284
|
)
|
|
221
|
-
lmp.command("pair_coeff %s"%pc1)
|
|
222
|
-
lmp.command("pair_coeff %s"%pc2)
|
|
285
|
+
lmp.command("pair_coeff %s" % pc1)
|
|
286
|
+
lmp.command("pair_coeff %s" % pc2)
|
|
223
287
|
|
|
224
|
-
|
|
225
|
-
#apply pair force commands
|
|
288
|
+
# apply pair force commands
|
|
226
289
|
if self.calc._pair_style_names[0] == self.calc._pair_style_names[1]:
|
|
227
|
-
lmp.command(
|
|
228
|
-
|
|
290
|
+
lmp.command(
|
|
291
|
+
"compute c1 all pair %s 1" % self.calc._pair_style_names[0]
|
|
292
|
+
)
|
|
293
|
+
lmp.command(
|
|
294
|
+
"compute c2 all pair %s 2" % self.calc._pair_style_names[1]
|
|
295
|
+
)
|
|
229
296
|
else:
|
|
230
|
-
lmp.command(
|
|
231
|
-
|
|
232
|
-
|
|
297
|
+
lmp.command(
|
|
298
|
+
"compute c1 all pair %s" % self.calc._pair_style_names[0]
|
|
299
|
+
)
|
|
300
|
+
lmp.command(
|
|
301
|
+
"compute c2 all pair %s" % self.calc._pair_style_names[1]
|
|
302
|
+
)
|
|
233
303
|
|
|
234
304
|
# Output variables.
|
|
235
305
|
lmp.command("variable step equal step")
|
|
236
|
-
lmp.command(
|
|
306
|
+
lmp.command(
|
|
307
|
+
"variable dU1 equal c_c1/atoms"
|
|
308
|
+
) # Driving-force obtained from NEHI procedure.
|
|
237
309
|
lmp.command("variable dU2 equal c_c2/atoms")
|
|
238
310
|
|
|
239
|
-
#add swaps if n_swap is > 0
|
|
311
|
+
# add swaps if n_swap is > 0
|
|
240
312
|
if self.calc.monte_carlo.n_swaps > 0:
|
|
241
|
-
self.logger.info(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
313
|
+
self.logger.info(
|
|
314
|
+
f"{self.calc.monte_carlo.n_swaps} swap moves are performed between {self.calc.monte_carlo.swap_types[0]} and {self.calc.monte_carlo.swap_types[1]} every {self.calc.monte_carlo.n_steps}"
|
|
315
|
+
)
|
|
316
|
+
lmp.command(
|
|
317
|
+
"fix swap all atom/swap %d %d %d %f ke no types %d %d"
|
|
318
|
+
% (
|
|
319
|
+
self.calc.monte_carlo.n_steps,
|
|
320
|
+
self.calc.monte_carlo.n_swaps,
|
|
321
|
+
np.random.randint(1, 10000),
|
|
322
|
+
self.calc._temperature,
|
|
323
|
+
self.calc.monte_carlo.swap_types[0],
|
|
324
|
+
self.calc.monte_carlo.swap_types[1],
|
|
325
|
+
)
|
|
326
|
+
)
|
|
248
327
|
lmp.command("variable a equal f_swap[1]")
|
|
249
328
|
lmp.command("variable b equal f_swap[2]")
|
|
250
|
-
lmp.command(
|
|
329
|
+
lmp.command(
|
|
330
|
+
'fix swap2 all print 1 "${a} ${b} ${flambda}" screen no file swap.forward_%d.dat'
|
|
331
|
+
% iteration
|
|
332
|
+
)
|
|
251
333
|
|
|
252
334
|
# Thermo output.
|
|
253
335
|
if self.calc.monte_carlo.n_swaps > 0:
|
|
@@ -256,97 +338,126 @@ class Alchemy(cph.Phase):
|
|
|
256
338
|
lmp.command("thermo_style custom step v_dU1 v_dU2")
|
|
257
339
|
lmp.command("thermo 1000")
|
|
258
340
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
341
|
+
# save the necessary items to a file: first step
|
|
342
|
+
lmp.command(
|
|
343
|
+
'fix f2 all print 1 "${dU1} ${dU2} ${flambda}" screen no file forward_%d.dat'
|
|
344
|
+
% iteration
|
|
345
|
+
)
|
|
346
|
+
lmp.command("run %d" % self.calc._n_switching_steps)
|
|
263
347
|
|
|
264
|
-
#now equilibrate at the second potential
|
|
348
|
+
# now equilibrate at the second potential
|
|
265
349
|
lmp.command("unfix f2")
|
|
266
350
|
lmp.command("uncompute c1")
|
|
267
351
|
lmp.command("uncompute c2")
|
|
268
352
|
|
|
269
|
-
#NEW SWAP
|
|
353
|
+
# NEW SWAP
|
|
270
354
|
if self.calc.monte_carlo.n_swaps > 0:
|
|
271
355
|
lmp.command("unfix swap")
|
|
272
356
|
lmp.command("unfix swap2")
|
|
273
357
|
|
|
274
|
-
|
|
275
|
-
lmp.command("
|
|
276
|
-
lmp.command("pair_coeff %s"%self.calc.pair_coeff[1])
|
|
358
|
+
lmp.command("pair_style %s" % self.calc._pair_style_with_options[1])
|
|
359
|
+
lmp.command("pair_coeff %s" % self.calc.pair_coeff[1])
|
|
277
360
|
|
|
278
361
|
# Thermo output.
|
|
279
362
|
lmp.command("thermo_style custom step pe")
|
|
280
363
|
lmp.command("thermo 1000")
|
|
281
|
-
|
|
282
|
-
#run eqbrm run
|
|
283
|
-
lmp.command("run %d"%self.calc.n_equilibration_steps)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
#reverse switching
|
|
364
|
+
|
|
365
|
+
# run eqbrm run
|
|
366
|
+
lmp.command("run %d" % self.calc.n_equilibration_steps)
|
|
367
|
+
|
|
368
|
+
# reverse switching
|
|
287
369
|
lmp.command("variable flambda equal ramp(${lf},${li})")
|
|
288
370
|
lmp.command("variable blambda equal ramp(${li},${lf})")
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
lmp.command("pair_style hybrid/scaled v_flambda %s v_blambda %s"%(self.calc._pair_style_with_options[0],
|
|
292
|
-
self.calc._pair_style_with_options[1]))
|
|
293
|
-
lmp.command("pair_coeff %s"%pc1)
|
|
294
|
-
lmp.command("pair_coeff %s"%pc2)
|
|
295
371
|
|
|
372
|
+
lmp.command(
|
|
373
|
+
"pair_style hybrid/scaled v_flambda %s v_blambda %s"
|
|
374
|
+
% (
|
|
375
|
+
self.calc._pair_style_with_options[0],
|
|
376
|
+
self.calc._pair_style_with_options[1],
|
|
377
|
+
)
|
|
378
|
+
)
|
|
379
|
+
lmp.command("pair_coeff %s" % pc1)
|
|
380
|
+
lmp.command("pair_coeff %s" % pc2)
|
|
296
381
|
|
|
297
|
-
#apply pair force commands
|
|
382
|
+
# apply pair force commands
|
|
298
383
|
if self.calc._pair_style_names[0] == self.calc._pair_style_names[1]:
|
|
299
|
-
lmp.command(
|
|
300
|
-
|
|
384
|
+
lmp.command(
|
|
385
|
+
"compute c1 all pair %s 1" % self.calc._pair_style_names[0]
|
|
386
|
+
)
|
|
387
|
+
lmp.command(
|
|
388
|
+
"compute c2 all pair %s 2" % self.calc._pair_style_names[1]
|
|
389
|
+
)
|
|
301
390
|
else:
|
|
302
|
-
lmp.command(
|
|
303
|
-
|
|
304
|
-
|
|
391
|
+
lmp.command(
|
|
392
|
+
"compute c1 all pair %s" % self.calc._pair_style_names[0]
|
|
393
|
+
)
|
|
394
|
+
lmp.command(
|
|
395
|
+
"compute c2 all pair %s" % self.calc._pair_style_names[1]
|
|
396
|
+
)
|
|
305
397
|
|
|
306
398
|
# Output variables.
|
|
307
399
|
lmp.command("variable step equal step")
|
|
308
|
-
lmp.command(
|
|
400
|
+
lmp.command(
|
|
401
|
+
"variable dU1 equal c_c1/atoms"
|
|
402
|
+
) # Driving-force obtained from NEHI procedure.
|
|
309
403
|
lmp.command("variable dU2 equal c_c2/atoms")
|
|
310
404
|
|
|
311
|
-
#add swaps if n_swap is > 0
|
|
405
|
+
# add swaps if n_swap is > 0
|
|
312
406
|
if self.calc.monte_carlo.n_swaps > 0:
|
|
313
407
|
if self.calc.monte_carlo.reverse_swap:
|
|
314
|
-
self.logger.info(
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
408
|
+
self.logger.info(
|
|
409
|
+
f"{self.calc.monte_carlo.n_swaps} swap moves are performed between {self.calc.monte_carlo.swap_types[1]} and {self.calc.monte_carlo.swap_types[0]} every {self.calc.monte_carlo.n_steps}"
|
|
410
|
+
)
|
|
411
|
+
lmp.command(
|
|
412
|
+
"fix swap all atom/swap %d %d %d %f ke no types %d %d"
|
|
413
|
+
% (
|
|
414
|
+
self.calc.monte_carlo.n_steps,
|
|
415
|
+
self.calc.monte_carlo.n_swaps,
|
|
416
|
+
np.random.randint(1, 10000),
|
|
417
|
+
self.calc._temperature,
|
|
418
|
+
self.calc.monte_carlo.swap_types[1],
|
|
419
|
+
self.calc.monte_carlo.swap_types[0],
|
|
420
|
+
)
|
|
421
|
+
)
|
|
321
422
|
else:
|
|
322
|
-
self.logger.info(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
423
|
+
self.logger.info(
|
|
424
|
+
f"{self.calc.monte_carlo.n_swaps} swap moves are performed between {self.calc.monte_carlo.swap_types[0]} and {self.calc.monte_carlo.swap_types[1]} every {self.calc.monte_carlo.n_steps}"
|
|
425
|
+
)
|
|
426
|
+
self.logger.info("note that swaps are not reversed")
|
|
427
|
+
lmp.command(
|
|
428
|
+
"fix swap all atom/swap %d %d %d %f ke no types %d %d"
|
|
429
|
+
% (
|
|
430
|
+
self.calc.monte_carlo.n_steps,
|
|
431
|
+
self.calc.monte_carlo.n_swaps,
|
|
432
|
+
np.random.randint(1, 10000),
|
|
433
|
+
self.calc._temperature,
|
|
434
|
+
self.calc.monte_carlo.swap_types[0],
|
|
435
|
+
self.calc.monte_carlo.swap_types[1],
|
|
436
|
+
)
|
|
437
|
+
)
|
|
330
438
|
|
|
331
439
|
lmp.command("variable a equal f_swap[1]")
|
|
332
440
|
lmp.command("variable b equal f_swap[2]")
|
|
333
|
-
lmp.command(
|
|
441
|
+
lmp.command(
|
|
442
|
+
'fix swap2 all print 1 "${a} ${b} ${blambda}" screen no file swap.backward_%d.dat'
|
|
443
|
+
% iteration
|
|
444
|
+
)
|
|
334
445
|
|
|
335
446
|
# Thermo output.
|
|
336
447
|
if self.calc.monte_carlo.n_swaps > 0:
|
|
337
448
|
lmp.command("thermo_style custom step v_dU1 v_dU2 v_a v_b")
|
|
338
|
-
else:
|
|
449
|
+
else:
|
|
339
450
|
lmp.command("thermo_style custom step v_dU1 v_dU2")
|
|
340
451
|
lmp.command("thermo 1000")
|
|
341
452
|
|
|
453
|
+
# save the necessary items to a file: first step
|
|
454
|
+
lmp.command(
|
|
455
|
+
'fix f2 all print 1 "${dU1} ${dU2} ${flambda}" screen no file backward_%d.dat'
|
|
456
|
+
% iteration
|
|
457
|
+
)
|
|
458
|
+
lmp.command("run %d" % self.calc._n_switching_steps)
|
|
342
459
|
|
|
343
|
-
|
|
344
|
-
#save the necessary items to a file: first step
|
|
345
|
-
lmp.command("fix f2 all print 1 \"${dU1} ${dU2} ${flambda}\" screen no file backward_%d.dat"%iteration)
|
|
346
|
-
lmp.command("run %d"%self.calc._n_switching_steps)
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
#now equilibrate at the second potential
|
|
460
|
+
# now equilibrate at the second potential
|
|
350
461
|
lmp.command("unfix f2")
|
|
351
462
|
lmp.command("uncompute c1")
|
|
352
463
|
lmp.command("uncompute c2")
|
|
@@ -354,8 +465,10 @@ class Alchemy(cph.Phase):
|
|
|
354
465
|
if self.calc.monte_carlo.n_swaps > 0:
|
|
355
466
|
lmp.command("unfix swap")
|
|
356
467
|
lmp.close()
|
|
357
|
-
|
|
358
|
-
|
|
468
|
+
# Preserve log file
|
|
469
|
+
logfile = os.path.join(self.simfolder, "log.lammps")
|
|
470
|
+
if os.path.exists(logfile):
|
|
471
|
+
os.rename(logfile, os.path.join(self.simfolder, "integration.log.lammps"))
|
|
359
472
|
|
|
360
473
|
def thermodynamic_integration(self):
|
|
361
474
|
"""
|
|
@@ -374,24 +487,31 @@ class Alchemy(cph.Phase):
|
|
|
374
487
|
Calculates the final work, energy dissipation; In alchemical mode, there is reference system,
|
|
375
488
|
the calculated free energy is the same as the work.
|
|
376
489
|
"""
|
|
377
|
-
w, q, qerr = find_w(self.simfolder, self.calc,
|
|
378
|
-
full=True, solid=False)
|
|
490
|
+
w, q, qerr = find_w(self.simfolder, self.calc, full=True, solid=False)
|
|
379
491
|
|
|
380
492
|
self.w = w
|
|
381
493
|
self.ferr = qerr
|
|
382
494
|
self.fe = self.w
|
|
383
|
-
|
|
495
|
+
|
|
384
496
|
if self.calc.mode == "composition_scaling":
|
|
385
|
-
w_arr, q_arr, qerr_arr, flambda_arr = find_w(
|
|
386
|
-
|
|
497
|
+
w_arr, q_arr, qerr_arr, flambda_arr = find_w(
|
|
498
|
+
self.simfolder,
|
|
499
|
+
self.calc,
|
|
500
|
+
full=True,
|
|
501
|
+
solid=False,
|
|
502
|
+
composition_integration=True,
|
|
503
|
+
)
|
|
387
504
|
|
|
388
|
-
#now we need to process the comp scaling
|
|
505
|
+
# now we need to process the comp scaling
|
|
389
506
|
return flambda_arr, w_arr, q_arr, qerr_arr
|
|
390
507
|
|
|
391
|
-
|
|
392
508
|
def mass_integration(self, flambda, ref_mass, target_masses, target_counts):
|
|
393
|
-
mcorarr, mcorsum = integrate_mass(
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
509
|
+
mcorarr, mcorsum = integrate_mass(
|
|
510
|
+
flambda,
|
|
511
|
+
ref_mass,
|
|
512
|
+
target_masses,
|
|
513
|
+
target_counts,
|
|
514
|
+
self.calc._temperature,
|
|
515
|
+
self.natoms,
|
|
516
|
+
)
|
|
517
|
+
return mcorarr, mcorsum
|