calphy 1.3.11__py3-none-any.whl → 1.4.2__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/phase.py CHANGED
@@ -6,14 +6,14 @@ calphy: a Python library and command line interface for automated free
6
6
  energy calculations.
7
7
 
8
8
  Copyright 2021 (c) Sarath Menon^1, Yury Lysogorskiy^2, Ralf Drautz^2
9
- ^1: Max Planck Institut für Eisenforschung, Dusseldorf, Germany
9
+ ^1: Max Planck Institut für Eisenforschung, Dusseldorf, Germany
10
10
  ^2: Ruhr-University Bochum, Bochum, Germany
11
11
 
12
- calphy is published and distributed under the Academic Software License v1.0 (ASL).
13
- calphy is distributed in the hope that it will be useful for non-commercial academic research,
14
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
+ calphy is published and distributed under the Academic Software License v1.0 (ASL).
13
+ calphy is distributed in the hope that it will be useful for non-commercial academic research,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
15
  calphy API is published and distributed under the BSD 3-Clause "New" or "Revised" License
16
- See the LICENSE FILE for more details.
16
+ See the LICENSE FILE for more details.
17
17
 
18
18
  More information about the program can be found in:
19
19
  Menon, Sarath, Yury Lysogorskiy, Jutta Rogal, and Ralf Drautz.
@@ -37,6 +37,7 @@ import calphy.helpers as ph
37
37
  from calphy.errors import *
38
38
  from calphy.input import generate_metadata
39
39
 
40
+
40
41
  class Phase:
41
42
  """
42
43
  Class for free energy calculation.
@@ -45,74 +46,85 @@ class Phase:
45
46
  ----------
46
47
  input : Calculation class
47
48
  input options
48
-
49
+
49
50
  simfolder : string
50
51
  base folder for running calculations
51
52
 
52
53
  """
54
+
53
55
  def __init__(self, calculation=None, simfolder=None, log_to_screen=False):
54
56
 
55
57
  self.calc = copy.deepcopy(calculation)
56
-
57
- #serialise input
58
+
59
+ # serialise input
58
60
  indict = {"calculations": [self.calc.dict()]}
59
- with open(os.path.join(simfolder, 'input_file.yaml'), 'w') as fout:
61
+ with open(os.path.join(simfolder, "input_file.yaml"), "w") as fout:
60
62
  yaml.safe_dump(indict, fout)
61
63
 
62
- #serialise input configuration
63
- shutil.copy(self.calc.lattice, os.path.join(simfolder, 'input_configuration.data'))
64
-
65
- #write simple metadata
66
- with open(os.path.join(simfolder, 'metadata.yaml'), 'w') as fout:
67
- yaml.safe_dump(generate_metadata(), fout)
68
-
69
-
70
64
  self.simfolder = simfolder
71
65
  self.log_to_screen = log_to_screen
72
-
66
+ self.publications = []
67
+
73
68
  logfile = os.path.join(self.simfolder, "calphy.log")
74
69
  self.logger = ph.prepare_log(logfile, screen=log_to_screen)
75
70
 
76
71
  if self.calc._pressure is None:
77
72
  pressure_string = "None"
78
73
  else:
79
- pressure_string = "%f"%self.calc._pressure
74
+ pressure_string = "%f" % self.calc._pressure
80
75
 
81
- self.logger.info("Temperature start: %f K, temperature stop: %f K, pressure: %s bar"%(self.calc._temperature,
82
- self.calc._temperature_stop, pressure_string))
76
+ self.logger.info(
77
+ "Temperature start: %f K, temperature stop: %f K, pressure: %s bar"
78
+ % (self.calc._temperature, self.calc._temperature_stop, pressure_string)
79
+ )
83
80
 
84
81
  if self.calc._iso:
85
82
  self.iso = "iso"
86
83
  else:
87
84
  self.iso = "aniso"
88
- self.logger.info("Pressure adjusted in %s"%self.iso)
89
-
85
+ self.logger.info("Pressure adjusted in %s" % self.iso)
90
86
 
91
- self.logger.info("Reference phase is %s"%self.calc.reference_phase)
92
- if self.calc.reference_phase == 'liquid':
87
+ self.logger.info("Reference phase is %s" % self.calc.reference_phase)
88
+ if self.calc.reference_phase == "liquid":
93
89
  if self.calc.melting_cycle:
94
- self.logger.info("Melting cycle will run, this can be turned off using the keyword melting_cycle")
90
+ self.logger.info(
91
+ "Melting cycle will run, this can be turned off using the keyword melting_cycle"
92
+ )
95
93
  else:
96
94
  self.logger.info("Melting cycle is turned off")
97
95
 
98
- #now thermostat and barostat damping process
96
+ # now thermostat and barostat damping process
99
97
  if self.calc.equilibration_control is None:
100
- self.logger.info("Thermostat/Barostat combo for equilibration cycle is not explicitely specified")
101
- self.logger.info("Thermostat/Barostat combo for equilibration cycle can be specified using keyword equilibration_control")
102
- if self.calc.reference_phase == 'liquid':
103
- self.logger.info("Reference phase is liquid, setting Nose-Hoover thermostat for equilibration")
104
- self.calc.equilibration_control = "nose-hoover"
105
- else:
106
- self.logger.info("Reference phase is solid, setting Nose-Hoover thermostat for equilibration")
107
- self.calc.equilibration_control = "nose-hoover"
98
+ self.logger.info(
99
+ "Thermostat/Barostat combo for equilibration cycle is not explicitely specified"
100
+ )
101
+ self.logger.info(
102
+ "Thermostat/Barostat combo for equilibration cycle can be specified using keyword equilibration_control"
103
+ )
104
+ self.calc.equilibration_control = "nose-hoover"
108
105
  else:
109
- self.logger.info("Equilibration stage is done using %s barostat/thermostat"%self.calc.equilibration_control)
106
+ self.logger.info(
107
+ "Equilibration stage is done using %s barostat/thermostat"
108
+ % self.calc.equilibration_control
109
+ )
110
110
 
111
111
  if self.calc.equilibration_control == "nose-hoover":
112
- self.logger.info("Nose-Hoover thermostat damping is %f"%self.calc.nose_hoover.thermostat_damping)
113
- self.calc.md.thermostat_damping = [self.calc.nose_hoover.thermostat_damping, self.calc.md.thermostat_damping]
114
- self.logger.info("Nose-Hoover barostat damping is %f"%self.calc.nose_hoover.barostat_damping)
115
- self.calc.md.barostat_damping = [self.calc.nose_hoover.barostat_damping, self.calc.md.barostat_damping]
112
+ self.logger.info(
113
+ "Nose-Hoover thermostat damping is %f"
114
+ % self.calc.nose_hoover.thermostat_damping
115
+ )
116
+ self.calc.md.thermostat_damping = [
117
+ self.calc.nose_hoover.thermostat_damping,
118
+ self.calc.md.thermostat_damping,
119
+ ]
120
+ self.logger.info(
121
+ "Nose-Hoover barostat damping is %f"
122
+ % self.calc.nose_hoover.barostat_damping
123
+ )
124
+ self.calc.md.barostat_damping = [
125
+ self.calc.nose_hoover.barostat_damping,
126
+ self.calc.md.barostat_damping,
127
+ ]
116
128
  self.logger.info("These values can be tuned by adding in the input file:")
117
129
  self.logger.info("nose_hoover:")
118
130
  self.logger.info(" thermostat_damping: <float>")
@@ -122,10 +134,22 @@ class Phase:
122
134
  if self.calc.md.barostat_damping[0] > 10.0:
123
135
  self.logger.warning("Equil. Nose-Hoover barostat damping is high!")
124
136
  else:
125
- self.logger.info("Berendsen thermostat damping is %f"%self.calc.berendsen.thermostat_damping)
126
- self.calc.md.thermostat_damping = [self.calc.berendsen.thermostat_damping, self.calc.md.thermostat_damping]
127
- self.logger.info("Berendsen barostat damping is %f"%self.calc.berendsen.barostat_damping)
128
- self.calc.md.barostat_damping = [self.calc.berendsen.barostat_damping, self.calc.md.barostat_damping]
137
+ self.logger.info(
138
+ "Berendsen thermostat damping is %f"
139
+ % self.calc.berendsen.thermostat_damping
140
+ )
141
+ self.calc.md.thermostat_damping = [
142
+ self.calc.berendsen.thermostat_damping,
143
+ self.calc.md.thermostat_damping,
144
+ ]
145
+ self.logger.info(
146
+ "Berendsen barostat damping is %f"
147
+ % self.calc.berendsen.barostat_damping
148
+ )
149
+ self.calc.md.barostat_damping = [
150
+ self.calc.berendsen.barostat_damping,
151
+ self.calc.md.barostat_damping,
152
+ ]
129
153
  self.logger.info("These values can be tuned by adding in the input file:")
130
154
  self.logger.info("berendsen:")
131
155
  self.logger.info(" thermostat_damping: <float>")
@@ -135,28 +159,37 @@ class Phase:
135
159
  if self.calc.md.barostat_damping[0] < 1.0:
136
160
  self.logger.warning("Equil. Berendsen barostat damping is high!")
137
161
 
138
- self.logger.info("Integration stage is done using Nose-Hoover thermostat and barostat when needed")
139
- self.logger.info("Thermostat damping is %f"%(self.calc.md.thermostat_damping[1]))
140
- self.logger.info("Barostat damping is %f"%(self.calc.md.barostat_damping[1]))
162
+ self.logger.info(
163
+ "Integration stage is done using Nose-Hoover thermostat and barostat when needed"
164
+ )
165
+ self.logger.info(
166
+ "Thermostat damping is %f" % (self.calc.md.thermostat_damping[1])
167
+ )
168
+ self.logger.info("Barostat damping is %f" % (self.calc.md.barostat_damping[1]))
141
169
 
142
170
  if self.calc._fix_lattice:
143
- self.logger.info("Lattice is fixed, pressure convergence criteria is 50*tolerance.pressure; change if needed!")
171
+ self.logger.info(
172
+ "Lattice is fixed, pressure convergence criteria is 50*tolerance.pressure; change if needed!"
173
+ )
144
174
 
145
175
  self.l = self.calc.lattice
146
176
  self.alat = self.calc.lattice_constant
147
177
  self.vol = None
148
178
 
149
- #other properties
179
+ # other properties
150
180
  self.cores = self.calc.queue.cores
151
181
  self.ncells = np.prod(self.calc.repeat)
152
- self.natoms = self.calc._natoms
153
- self.logger.info("%d atoms in %d cells on %d cores"%(self.natoms, self.ncells, self.cores))
182
+ self.natoms = self.calc._natoms
183
+ self.logger.info(
184
+ "%d atoms in %d cells on %d cores" % (self.natoms, self.ncells, self.cores)
185
+ )
154
186
 
155
- #reference system props; may not be always used
156
- #TODO : Add option to customize UFM parameters
157
- self.eps = self.calc._temperature*50.0*kb
187
+ # reference system props; may not be always used
188
+ # TODO : Add option to customize UFM parameters
189
+ self.eps = self.calc._temperature * self.calc.uhlenbeck_ford_model.p * kb
190
+ self.ufm_cutoff = 5 * self.calc.uhlenbeck_ford_model.sigma
158
191
 
159
- #properties that will be calculated later
192
+ # properties that will be calculated later
160
193
  self.volatom = None
161
194
  self.k = None
162
195
  self.rho = None
@@ -166,31 +199,32 @@ class Phase:
166
199
  self.feinstein = 0
167
200
  self.fcm = 0
168
201
  self.fideal = 0
169
-
202
+
170
203
  self.w = 0
171
204
  self.pv = 0
172
205
  self.fe = 0
173
206
 
174
- #box dimensions that need to be stored
207
+ # box dimensions that need to be stored
175
208
  self.lx = None
176
209
  self.ly = None
177
210
  self.lz = None
178
211
 
179
-
180
- #now manually tune pair styles
212
+ # now manually tune pair styles
181
213
  if self.calc.pair_style is not None:
182
- self.logger.info("pair_style: %s"%self.calc._pair_style_with_options[0])
183
- self.logger.info("pair_coeff: %s"%self.calc.pair_coeff[0])
184
-
185
- #log second pair style
186
- if len(self.calc.pair_style)>1:
187
- self.logger.info("second pair_style: %s"%self.calc._pair_style_with_options[1])
188
- self.logger.info("second pair_coeff: %s"%self.calc.pair_coeff[1])
214
+ self.logger.info("pair_style: %s" % self.calc._pair_style_with_options[0])
215
+ self.logger.info("pair_coeff: %s" % self.calc.pair_coeff[0])
216
+
217
+ # log second pair style
218
+ if len(self.calc.pair_style) > 1:
219
+ self.logger.info(
220
+ "second pair_style: %s" % self.calc._pair_style_with_options[1]
221
+ )
222
+ self.logger.info("second pair_coeff: %s" % self.calc.pair_coeff[1])
189
223
  else:
190
224
  self.logger.info("pair_style or pair_coeff not provided")
191
225
  if self.calc.potential_file is not None:
192
226
  self.logger.info("potential is being loaded from file instead")
193
-
227
+
194
228
  def __repr__(self):
195
229
  """
196
230
  String of the class
@@ -205,18 +239,19 @@ class Phase:
205
239
  org_dict[key] = {}
206
240
  self._from_dict(org_dict[key], val)
207
241
  else:
208
- org_dict[key] = val
209
-
242
+ org_dict[key] = val
243
+
210
244
  def dump_current_snapshot(self, lmp, filename):
211
- """
212
- """
213
- lmp.command("dump 2 all custom 1 %s id type mass x y z vx vy vz"%(filename))
245
+ """ """
246
+ lmp.command(
247
+ "dump 2 all custom 1 %s id type mass x y z vx vy vz"
248
+ % (filename)
249
+ )
214
250
  lmp.command("run 0")
215
251
  lmp.command("undump 2")
216
252
 
217
253
  def get_structures(self, stage="fe", direction="forward", n_iteration=1):
218
- """
219
- """
254
+ """ """
220
255
  species = self.calc.element
221
256
  filename = None
222
257
 
@@ -224,9 +259,13 @@ class Phase:
224
259
  filename = os.path.join(self.simfolder, "conf.equilibration.data")
225
260
  elif stage == "ts":
226
261
  if direction == "forward":
227
- filename = os.path.join(self.simfolder, "traj.ts.forward_%d.dat"%n_iteration)
262
+ filename = os.path.join(
263
+ self.simfolder, "traj.ts.forward_%d.dat" % n_iteration
264
+ )
228
265
  elif direction == "backward":
229
- filename = os.path.join(self.simfolder, "traj.ts.backward_%d.dat"%n_iteration)
266
+ filename = os.path.join(
267
+ self.simfolder, "traj.ts.backward_%d.dat" % n_iteration
268
+ )
230
269
 
231
270
  structures = None
232
271
  if filename is not None:
@@ -235,24 +274,31 @@ class Phase:
235
274
  return structures
236
275
 
237
276
  def check_if_melted(self, lmp, filename):
238
- """
239
- """
277
+ """ """
240
278
  solids = ph.find_solid_fraction(os.path.join(self.simfolder, filename))
241
- if (solids/lmp.natoms < self.calc.tolerance.solid_fraction):
279
+ if solids / lmp.natoms < self.calc.tolerance.solid_fraction:
242
280
  lmp.close()
243
- raise MeltedError("System melted, increase size or reduce temp!\n Solid detection algorithm only works with BCC/FCC/HCP/SC/DIA. Detection algorithm can be turned off by setting:\n tolerance.solid_fraction: 0")
281
+ raise MeltedError(
282
+ "System melted, increase size or reduce temp!\n Solid detection algorithm only works with BCC/FCC/HCP/SC/DIA. Detection algorithm can be turned off by setting:\n tolerance.solid_fraction: 0"
283
+ )
244
284
 
245
285
  def check_if_solidfied(self, lmp, filename):
246
- """
247
- """
286
+ """ """
248
287
  solids = ph.find_solid_fraction(os.path.join(self.simfolder, filename))
249
- if (solids/lmp.natoms > self.calc.tolerance.liquid_fraction):
288
+ if solids / lmp.natoms > self.calc.tolerance.liquid_fraction:
250
289
  lmp.close()
251
- raise SolidifiedError('System solidified, increase temperature')
252
-
253
- def fix_nose_hoover(self, lmp, temp_start_factor=1.0, temp_end_factor=1.0,
254
- press_start_factor=1.0, press_end_factor=1.0,
255
- stage=0, ensemble="npt"):
290
+ raise SolidifiedError("System solidified, increase temperature")
291
+
292
+ def fix_nose_hoover(
293
+ self,
294
+ lmp,
295
+ temp_start_factor=1.0,
296
+ temp_end_factor=1.0,
297
+ press_start_factor=1.0,
298
+ press_end_factor=1.0,
299
+ stage=0,
300
+ ensemble="npt",
301
+ ):
256
302
  """
257
303
  Fix Nose-Hoover thermostat and barostat
258
304
 
@@ -264,14 +310,29 @@ class Phase:
264
310
  -------
265
311
  None
266
312
  """
267
- lmp.command("fix nh1 all npt temp %f %f %f %s %f %f %f"%(temp_start_factor*self.calc._temperature,
268
- temp_end_factor*self.calc._temperature, self.calc.md.thermostat_damping[stage],
269
- self.iso, press_start_factor*self.calc._pressure, press_end_factor*self.calc._pressure, self.calc.md.barostat_damping[stage]))
270
-
271
-
272
- def fix_berendsen(self, lmp, temp_start_factor=1.0, temp_end_factor=1.0,
273
- press_start_factor=1.0, press_end_factor=1.0,
274
- stage=0, ensemble="npt"):
313
+ lmp.command(
314
+ "fix nh1 all npt temp %f %f %f %s %f %f %f"
315
+ % (
316
+ temp_start_factor * self.calc._temperature,
317
+ temp_end_factor * self.calc._temperature,
318
+ self.calc.md.thermostat_damping[stage],
319
+ self.iso,
320
+ press_start_factor * self.calc._pressure,
321
+ press_end_factor * self.calc._pressure,
322
+ self.calc.md.barostat_damping[stage],
323
+ )
324
+ )
325
+
326
+ def fix_berendsen(
327
+ self,
328
+ lmp,
329
+ temp_start_factor=1.0,
330
+ temp_end_factor=1.0,
331
+ press_start_factor=1.0,
332
+ press_end_factor=1.0,
333
+ stage=0,
334
+ ensemble="npt",
335
+ ):
275
336
  """
276
337
  Fix Nose-Hoover thermostat and barostat
277
338
 
@@ -284,8 +345,23 @@ class Phase:
284
345
  None
285
346
  """
286
347
  lmp.command("fix b1a all nve")
287
- lmp.command("fix b1b all temp/berendsen %f %f %f"%(temp_start_factor*self.calc._temperature, temp_end_factor*self.calc._temperature, self.calc.md.thermostat_damping[stage]))
288
- lmp.command("fix b1c all press/berendsen %s %f %f %f"%(self.iso, press_start_factor*self.calc._pressure, press_end_factor*self.calc._pressure, self.calc.md.barostat_damping[stage]))
348
+ lmp.command(
349
+ "fix b1b all temp/berendsen %f %f %f"
350
+ % (
351
+ temp_start_factor * self.calc._temperature,
352
+ temp_end_factor * self.calc._temperature,
353
+ self.calc.md.thermostat_damping[stage],
354
+ )
355
+ )
356
+ lmp.command(
357
+ "fix b1c all press/berendsen %s %f %f %f"
358
+ % (
359
+ self.iso,
360
+ press_start_factor * self.calc._pressure,
361
+ press_end_factor * self.calc._pressure,
362
+ self.calc.md.barostat_damping[stage],
363
+ )
364
+ )
289
365
 
290
366
  def unfix_nose_hoover(self, lmp):
291
367
  """
@@ -315,7 +391,7 @@ class Phase:
315
391
  """
316
392
  lmp.command("unfix b1a")
317
393
  lmp.command("unfix b1b")
318
- lmp.command("unfix b1c")
394
+ lmp.command("unfix b1c")
319
395
 
320
396
  def run_zero_pressure_equilibration(self, lmp):
321
397
  """
@@ -331,31 +407,32 @@ class Phase:
331
407
 
332
408
  Notes
333
409
  -----
334
- Each method should close all the fixes. Run a small eqbr routine to achieve zero pressure
410
+ Each method should close all the fixes. Run a small eqbr routine to achieve zero pressure
335
411
  """
336
- #set velocity
337
- lmp.command("velocity all create %f %d"%(self.calc._temperature, np.random.randint(1, 10000)))
338
-
339
- #apply fixes depending on thermostat/barostat
412
+ # set velocity
413
+ lmp.command(
414
+ "velocity all create %f %d"
415
+ % (self.calc._temperature, np.random.randint(1, 10000))
416
+ )
417
+
418
+ # apply fixes depending on thermostat/barostat
340
419
  if self.calc.equilibration_control == "nose-hoover":
341
420
  self.fix_nose_hoover(lmp)
342
421
  else:
343
422
  self.fix_berendsen(lmp)
344
- #start thermo logging
423
+ # start thermo logging
345
424
  lmp.command("thermo_style custom step pe press vol etotal temp lx ly lz")
346
425
  lmp.command("thermo 10")
347
-
348
- #run MD
349
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
350
-
351
- #remove fixes
426
+
427
+ # run MD
428
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
429
+
430
+ # remove fixes
352
431
  if self.calc.equilibration_control == "nose-hoover":
353
432
  self.unfix_nose_hoover(lmp)
354
433
  else:
355
434
  self.unfix_berendsen(lmp)
356
435
 
357
-
358
-
359
436
  def run_finite_pressure_equilibration(self, lmp):
360
437
  """
361
438
  Run a finite pressure equilibration
@@ -367,52 +444,55 @@ class Phase:
367
444
  Returns
368
445
  -------
369
446
  None
370
-
447
+
371
448
  Notes
372
449
  -----
373
450
  Each method should close all the fixes. Run a equilibration routine to reach the given finite pressure.
374
- The pressure is implemented in one fix, while temperature is gradually ramped.
451
+ The pressure is implemented in one fix, while temperature is gradually ramped.
375
452
  The thermostat can work faster than barostat, which means that the structure will melt before the pressure is scaled, this ramping
376
- can prevent the issue.
453
+ can prevent the issue.
377
454
  """
378
- #create velocity
379
- lmp.command("velocity all create %f %d"%(0.25*self.calc._temperature, np.random.randint(1, 10000)))
455
+ # create velocity
456
+ lmp.command(
457
+ "velocity all create %f %d"
458
+ % (0.25 * self.calc._temperature, np.random.randint(1, 10000))
459
+ )
380
460
 
381
- #for Nose-Hoover thermo/baro combination
461
+ # for Nose-Hoover thermo/baro combination
382
462
  if self.calc.equilibration_control == "nose-hoover":
383
- #Cycle 1: 0.25-0.5 temperature, full pressure
463
+ # Cycle 1: 0.25-0.5 temperature, full pressure
384
464
  self.fix_nose_hoover(lmp, temp_start_factor=0.25, temp_end_factor=0.5)
385
465
  lmp.command("thermo_style custom step pe press vol etotal temp")
386
466
  lmp.command("thermo 10")
387
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
467
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
388
468
  self.unfix_nose_hoover(lmp)
389
469
 
390
- #Cycle 2: 0.5-1.0 temperature, full pressure
470
+ # Cycle 2: 0.5-1.0 temperature, full pressure
391
471
  self.fix_nose_hoover(lmp, temp_start_factor=0.5, temp_end_factor=1.0)
392
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
472
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
393
473
  self.unfix_nose_hoover(lmp)
394
474
 
395
- #Cycle 3: full temperature, full pressure
475
+ # Cycle 3: full temperature, full pressure
396
476
  self.fix_nose_hoover(lmp)
397
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
477
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
398
478
  self.unfix_nose_hoover(lmp)
399
-
479
+
400
480
  else:
401
- #Cycle 1: 0.25-0.5 temperature, full pressure
481
+ # Cycle 1: 0.25-0.5 temperature, full pressure
402
482
  self.fix_berendsen(lmp, temp_start_factor=0.25, temp_end_factor=0.5)
403
483
  lmp.command("thermo_style custom step pe press vol etotal temp")
404
484
  lmp.command("thermo 10")
405
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
485
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
406
486
  self.unfix_berendsen(lmp)
407
487
 
408
- #Cycle 2: 0.5-1.0 temperature, full pressure
488
+ # Cycle 2: 0.5-1.0 temperature, full pressure
409
489
  self.fix_berendsen(lmp, temp_start_factor=0.5, temp_end_factor=1.0)
410
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
490
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
411
491
  self.unfix_berendsen(lmp)
412
492
 
413
- #Cycle 3: full temperature, full pressure
493
+ # Cycle 3: full temperature, full pressure
414
494
  self.fix_berendsen(lmp)
415
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
495
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
416
496
  self.unfix_berendsen(lmp)
417
497
 
418
498
  def run_pressure_convergence(self, lmp):
@@ -455,53 +535,70 @@ class Phase:
455
535
  The cycle is stopped when the average pressure is within the given cutoff of the target pressure.
456
536
  """
457
537
 
458
- #apply fixes
538
+ # apply fixes
459
539
  if self.calc.equilibration_control == "nose-hoover":
460
540
  self.fix_nose_hoover(lmp)
461
541
  else:
462
542
  self.fix_berendsen(lmp)
463
543
 
544
+ lmp.command(
545
+ "fix 2 all ave/time %d %d %d v_mlx v_mly v_mlz v_mpress file avg.dat"
546
+ % (
547
+ int(self.calc.md.n_every_steps),
548
+ int(self.calc.md.n_repeat_steps),
549
+ int(self.calc.md.n_every_steps * self.calc.md.n_repeat_steps),
550
+ )
551
+ )
464
552
 
465
- lmp.command("fix 2 all ave/time %d %d %d v_mlx v_mly v_mlz v_mpress file avg.dat"%(int(self.calc.md.n_every_steps),
466
- int(self.calc.md.n_repeat_steps), int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)))
467
-
468
553
  laststd = 0.00
469
554
  converged = False
470
555
 
471
556
  for i in range(int(self.calc.md.n_cycles)):
472
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
473
- ncount = int(self.calc.md.n_small_steps)//int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)
474
- #now we can check if it converted
557
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
558
+ ncount = int(self.calc.md.n_small_steps) // int(
559
+ self.calc.md.n_every_steps * self.calc.md.n_repeat_steps
560
+ )
561
+ # now we can check if it converted
475
562
  file = os.path.join(self.simfolder, "avg.dat")
476
563
  lx, ly, lz, ipress = np.loadtxt(file, usecols=(1, 2, 3, 4), unpack=True)
477
-
564
+
478
565
  lxpc = ipress
479
566
  mean = np.mean(lxpc)
480
567
  std = np.std(lxpc)
481
- volatom = np.mean((lx*ly*lz)/self.natoms)
482
- self.logger.info("At count %d mean pressure is %f with %f vol/atom"%(i+1, mean, volatom))
483
-
568
+ volatom = np.mean((lx * ly * lz) / self.natoms)
569
+ self.logger.info(
570
+ "At count %d mean pressure is %f with %f vol/atom"
571
+ % (i + 1, mean, volatom)
572
+ )
573
+
484
574
  if (np.abs(mean - self.calc._pressure)) < self.calc.tolerance.pressure:
485
575
 
486
- #process other means
487
- self.lx = np.round(np.mean(lx[-ncount+1:]), decimals=3)
488
- self.ly = np.round(np.mean(ly[-ncount+1:]), decimals=3)
489
- self.lz = np.round(np.mean(lz[-ncount+1:]), decimals=3)
576
+ # process other means
577
+ self.lx = np.round(np.mean(lx[-ncount + 1 :]), decimals=3)
578
+ self.ly = np.round(np.mean(ly[-ncount + 1 :]), decimals=3)
579
+ self.lz = np.round(np.mean(lz[-ncount + 1 :]), decimals=3)
490
580
  self.volatom = volatom
491
- self.vol = self.lx*self.ly*self.lz
492
- self.rho = self.natoms/(self.lx*self.ly*self.lz)
493
-
494
- self.logger.info("finalized vol/atom %f at pressure %f"%(self.volatom, mean))
495
- self.logger.info("Avg box dimensions x: %f, y: %f, z:%f"%(self.lx, self.ly, self.lz))
581
+ self.vol = self.lx * self.ly * self.lz
582
+ self.rho = self.natoms / (self.lx * self.ly * self.lz)
583
+
584
+ self.logger.info(
585
+ "finalized vol/atom %f at pressure %f" % (self.volatom, mean)
586
+ )
587
+ self.logger.info(
588
+ "Avg box dimensions x: %f, y: %f, z:%f"
589
+ % (self.lx, self.ly, self.lz)
590
+ )
496
591
  converged = True
497
592
  break
498
593
  laststd = std
499
-
594
+
500
595
  if not converged:
501
596
  lmp.close()
502
- raise ValueError("Pressure did not converge after MD runs, maybe change lattice_constant and try?")
597
+ raise ValueError(
598
+ "Pressure did not converge after MD runs, maybe change lattice_constant and try?"
599
+ )
503
600
 
504
- #unfix thermostat and barostat
601
+ # unfix thermostat and barostat
505
602
  if self.calc.equilibration_control == "nose-hoover":
506
603
  self.unfix_nose_hoover(lmp)
507
604
  else:
@@ -527,20 +624,25 @@ class Phase:
527
624
  The cycle is stopped when the average pressure is within the given cutoff of the target pressure.
528
625
  """
529
626
 
530
- #apply fixes
627
+ # apply fixes
531
628
  if self.calc.equilibration_control == "nose-hoover":
532
629
  self.fix_nose_hoover(lmp)
533
630
  else:
534
631
  self.fix_berendsen(lmp)
535
632
 
633
+ lmp.command(
634
+ "fix 2 all ave/time %d %d %d v_mlx v_mly v_mlz v_mpress file avg.dat"
635
+ % (
636
+ int(self.calc.md.n_every_steps),
637
+ int(self.calc.md.n_repeat_steps),
638
+ int(self.calc.md.n_every_steps * self.calc.md.n_repeat_steps),
639
+ )
640
+ )
536
641
 
537
- lmp.command("fix 2 all ave/time %d %d %d v_mlx v_mly v_mlz v_mpress file avg.dat"%(int(self.calc.md.n_every_steps),
538
- int(self.calc.md.n_repeat_steps), int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)))
539
-
540
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
541
- lmp.command("run %d"%int(self.calc.n_equilibration_steps))
642
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
643
+ lmp.command("run %d" % int(self.calc.n_equilibration_steps))
542
644
 
543
- #unfix thermostat and barostat
645
+ # unfix thermostat and barostat
544
646
  if self.calc.equilibration_control == "nose-hoover":
545
647
  self.unfix_nose_hoover(lmp)
546
648
  else:
@@ -555,34 +657,52 @@ class Phase:
555
657
  self.run_iterative_constrained_pressure_convergence(lmp)
556
658
 
557
659
  def run_iterative_constrained_pressure_convergence(self, lmp):
558
- """
559
- """
560
- lmp.command("velocity all create %f %d"%(self.calc._temperature, np.random.randint(1, 10000)))
561
- lmp.command("fix 1 all nvt temp %f %f %f"%(self.calc._temperature, self.calc._temperature, self.calc.md.thermostat_damping[1]))
660
+ """ """
661
+ lmp.command(
662
+ "velocity all create %f %d"
663
+ % (self.calc._temperature, np.random.randint(1, 10000))
664
+ )
665
+ lmp.command(
666
+ "fix 1 all nvt temp %f %f %f"
667
+ % (
668
+ self.calc._temperature,
669
+ self.calc._temperature,
670
+ self.calc.md.thermostat_damping[1],
671
+ )
672
+ )
562
673
  lmp.command("thermo_style custom step pe press vol etotal temp lx ly lz")
563
674
  lmp.command("thermo 10")
564
-
565
- #this is when the averaging routine starts
566
- lmp.command("fix 2 all ave/time %d %d %d v_mlx v_mly v_mlz v_mpress file avg.dat"%(int(self.calc.md.n_every_steps),
567
- int(self.calc.md.n_repeat_steps), int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)))
675
+
676
+ # this is when the averaging routine starts
677
+ lmp.command(
678
+ "fix 2 all ave/time %d %d %d v_mlx v_mly v_mlz v_mpress file avg.dat"
679
+ % (
680
+ int(self.calc.md.n_every_steps),
681
+ int(self.calc.md.n_repeat_steps),
682
+ int(self.calc.md.n_every_steps * self.calc.md.n_repeat_steps),
683
+ )
684
+ )
568
685
 
569
686
  lastmean = 100000000
570
687
  converged = False
571
688
  for i in range(int(self.calc.md.n_cycles)):
572
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
573
-
574
- #now we can check if it converted
575
- mean, std,volatom = self.process_pressure()
576
- self.logger.info("At count %d mean pressure is %f with %f vol/atom"%(i+1, mean, volatom))
577
-
578
- if (np.abs(mean - lastmean)) < 50*self.calc.tolerance.pressure:
579
- #here we actually have to set the pressure
689
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
690
+
691
+ # now we can check if it converted
692
+ mean, std, volatom = self.process_pressure()
693
+ self.logger.info(
694
+ "At count %d mean pressure is %f with %f vol/atom"
695
+ % (i + 1, mean, volatom)
696
+ )
697
+
698
+ if (np.abs(mean - lastmean)) < 50 * self.calc.tolerance.pressure:
699
+ # here we actually have to set the pressure
580
700
  self.finalise_pressure()
581
701
  converged = True
582
702
  break
583
703
 
584
704
  lastmean = mean
585
-
705
+
586
706
  lmp.command("unfix 1")
587
707
  lmp.command("unfix 2")
588
708
 
@@ -590,59 +710,95 @@ class Phase:
590
710
  lmp.close()
591
711
  raise ValueError("pressure did not converge")
592
712
 
593
- def process_pressure(self,):
713
+ def process_pressure(
714
+ self,
715
+ ):
594
716
  if self.calc.script_mode:
595
- ncount = int(self.calc.n_equilibration_steps)//int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)
596
- else:
597
- ncount = int(self.calc.md.n_small_steps)//int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)
598
-
599
- #now we can check if it converted
717
+ ncount = int(self.calc.n_equilibration_steps) // int(
718
+ self.calc.md.n_every_steps * self.calc.md.n_repeat_steps
719
+ )
720
+ else:
721
+ ncount = int(self.calc.md.n_small_steps) // int(
722
+ self.calc.md.n_every_steps * self.calc.md.n_repeat_steps
723
+ )
724
+
725
+ # now we can check if it converted
600
726
  file = os.path.join(self.simfolder, "avg.dat")
601
- lx, ly, lz, ipress = np.loadtxt(file, usecols=(1, 2, 3, 4), unpack=True)
602
- lxpc = ipress
727
+ # we have to clean the data, so as just the last block is selected
728
+ lx, ly, lz, lxpc = np.loadtxt(file, usecols=(1, 2, 3, 4), unpack=True)
729
+ lx = lx[-ncount + 1 :]
730
+ ly = ly[-ncount + 1 :]
731
+ lz = lx[-ncount + 1 :]
732
+ lxpc = lxpc[-ncount + 1 :]
603
733
  mean = np.mean(lxpc)
604
734
  std = np.std(lxpc)
605
- volatom = np.mean((lx*ly*lz)/self.natoms)
735
+ volatom = np.mean((lx * ly * lz) / self.natoms)
606
736
  return mean, std, volatom
607
737
 
608
- def finalise_pressure(self,):
738
+ def finalise_pressure(
739
+ self,
740
+ ):
609
741
  if self.calc.script_mode:
610
- ncount = int(self.calc.n_equilibration_steps)//int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)
611
- else:
612
- ncount = int(self.calc.md.n_small_steps)//int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)
742
+ ncount = int(self.calc.n_equilibration_steps) // int(
743
+ self.calc.md.n_every_steps * self.calc.md.n_repeat_steps
744
+ )
745
+ else:
746
+ ncount = int(self.calc.md.n_small_steps) // int(
747
+ self.calc.md.n_every_steps * self.calc.md.n_repeat_steps
748
+ )
613
749
 
614
750
  file = os.path.join(self.simfolder, "avg.dat")
615
- lx, ly, lz, ipress = np.loadtxt(file, usecols=(1, 2, 3, 4), unpack=True)
616
- lxpc = ipress
751
+ lx, ly, lz, lxpc = np.loadtxt(file, usecols=(1, 2, 3, 4), unpack=True)
752
+ lx = lx[-ncount + 1 :]
753
+ ly = ly[-ncount + 1 :]
754
+ lz = lx[-ncount + 1 :]
755
+ lxpc = lxpc[-ncount + 1 :]
756
+
617
757
  mean = np.mean(lxpc)
618
758
  std = np.std(lxpc)
619
- volatom = np.mean((lx*ly*lz)/self.natoms)
759
+ volatom = np.mean((lx * ly * lz) / self.natoms)
620
760
 
621
761
  self.calc._pressure = mean
622
- self.lx = np.round(np.mean(lx[-ncount+1:]), decimals=3)
623
- self.ly = np.round(np.mean(ly[-ncount+1:]), decimals=3)
624
- self.lz = np.round(np.mean(lz[-ncount+1:]), decimals=3)
762
+ self.lx = np.round(np.mean(lx), decimals=3)
763
+ self.ly = np.round(np.mean(ly), decimals=3)
764
+ self.lz = np.round(np.mean(lz), decimals=3)
625
765
  self.volatom = volatom
626
- self.vol = self.lx*self.ly*self.lz
627
- self.rho = self.natoms/(self.lx*self.ly*self.lz)
628
- self.logger.info("finalized vol/atom %f at pressure %f"%(self.volatom, mean))
629
- self.logger.info("Avg box dimensions x: %f, y: %f, z:%f"%(self.lx, self.ly, self.lz))
630
-
766
+ self.vol = self.lx * self.ly * self.lz
767
+ self.rho = self.natoms / (self.lx * self.ly * self.lz)
768
+ self.logger.info("finalized vol/atom %f at pressure %f" % (self.volatom, mean))
769
+ self.logger.info(
770
+ "Avg box dimensions x: %f, y: %f, z:%f" % (self.lx, self.ly, self.lz)
771
+ )
631
772
 
632
773
  def run_minimal_constrained_pressure_convergence(self, lmp):
633
- """
634
- """
635
- lmp.command("velocity all create %f %d"%(self.calc._temperature, np.random.randint(1, 10000)))
636
- lmp.command("fix 1 all nvt temp %f %f %f"%(self.calc._temperature, self.calc._temperature, self.calc.md.thermostat_damping[1]))
774
+ """ """
775
+ lmp.command(
776
+ "velocity all create %f %d"
777
+ % (self.calc._temperature, np.random.randint(1, 10000))
778
+ )
779
+ lmp.command(
780
+ "fix 1 all nvt temp %f %f %f"
781
+ % (
782
+ self.calc._temperature,
783
+ self.calc._temperature,
784
+ self.calc.md.thermostat_damping[1],
785
+ )
786
+ )
637
787
  lmp.command("thermo_style custom step pe press vol etotal temp lx ly lz")
638
788
  lmp.command("thermo 10")
639
-
640
- #this is when the averaging routine starts
641
- lmp.command("fix 2 all ave/time %d %d %d v_mlx v_mly v_mlz v_mpress file avg.dat"%(int(self.calc.md.n_every_steps),
642
- int(self.calc.md.n_repeat_steps), int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)))
643
789
 
644
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
645
- lmp.command("run %d"%int(self.calc.n_equilibration_steps))
790
+ # this is when the averaging routine starts
791
+ lmp.command(
792
+ "fix 2 all ave/time %d %d %d v_mlx v_mly v_mlz v_mpress file avg.dat"
793
+ % (
794
+ int(self.calc.md.n_every_steps),
795
+ int(self.calc.md.n_repeat_steps),
796
+ int(self.calc.md.n_every_steps * self.calc.md.n_repeat_steps),
797
+ )
798
+ )
799
+
800
+ lmp.command("run %d" % int(self.calc.md.n_small_steps))
801
+ lmp.command("run %d" % int(self.calc.n_equilibration_steps))
646
802
 
647
803
  lmp.command("unfix 1")
648
804
  lmp.command("unfix 2")
@@ -662,24 +818,30 @@ class Phase:
662
818
  """
663
819
  report = {}
664
820
 
665
- #input quantities
821
+ # input quantities
666
822
  report["input"] = {}
667
823
  report["input"]["temperature"] = int(self.calc._temperature)
668
824
  report["input"]["pressure"] = float(self.calc._pressure)
669
825
  report["input"]["lattice"] = str(self.calc._original_lattice)
670
826
  report["input"]["element"] = " ".join(np.array(self.calc.element).astype(str))
671
- report["input"]["concentration"] = " ".join(np.array([val['composition'] for key, val in self.calc._element_dict.items()]).astype(str))
827
+ report["input"]["concentration"] = " ".join(
828
+ np.array(
829
+ [val["composition"] for key, val in self.calc._element_dict.items()]
830
+ ).astype(str)
831
+ )
672
832
 
673
- #average quantities
833
+ # average quantities
674
834
  report["average"] = {}
675
835
  report["average"]["vol_atom"] = float(self.volatom)
676
-
836
+
677
837
  if self.k is not None:
678
- report["average"]["spring_constant"] = " ".join(np.array(self.k).astype(str))
838
+ report["average"]["spring_constant"] = " ".join(
839
+ np.array(self.k).astype(str)
840
+ )
679
841
  if self.rho is not None:
680
842
  report["average"]["density"] = float(self.rho)
681
843
 
682
- #results
844
+ # results
683
845
  report["results"] = {}
684
846
  report["results"]["free_energy"] = float(self.fe)
685
847
  report["results"]["error"] = float(self.ferr)
@@ -696,21 +858,25 @@ class Phase:
696
858
  self.report = report
697
859
 
698
860
  reportfile = os.path.join(self.simfolder, "report.yaml")
699
- with open(reportfile, 'w') as f:
861
+ with open(reportfile, "w") as f:
700
862
  yaml.dump(report, f)
701
863
 
702
- self.logger.info("Report written in %s"%reportfile)
864
+ self.logger.info("Report written in %s" % reportfile)
703
865
 
704
- #now we have to write out the results
866
+ # now we have to write out the results
705
867
  self.logger.info("Please cite the following publications:")
706
868
  self.logger.info("- 10.1103/PhysRevMaterials.5.103801")
869
+ self.publications.append("10.1103/PhysRevMaterials.5.103801")
707
870
 
708
871
  if self.calc.mode == "fe":
709
872
  if self.calc.reference_phase == "solid":
710
873
  self.logger.info("- 10.1016/j.commatsci.2015.10.050")
874
+ self.publications.append("10.1016/j.commatsci.2015.10.050")
711
875
  else:
712
876
  self.logger.info("- 10.1016/j.commatsci.2018.12.029")
713
877
  self.logger.info("- 10.1063/1.4967775")
878
+ self.publications.append("10.1016/j.commatsci.2018.12.029")
879
+ self.publications.append("10.1063/1.4967775")
714
880
 
715
881
  def reversible_scaling(self, iteration=1):
716
882
  """
@@ -725,117 +891,213 @@ class Phase:
725
891
  -------
726
892
  None
727
893
  """
728
- self.logger.info(f'Starting temperature sweep cycle: {iteration}')
894
+ self.logger.info(f"Starting temperature sweep cycle: {iteration}")
729
895
  solid = False
730
- if self.calc.reference_phase == 'solid':
896
+ if self.calc.reference_phase == "solid":
731
897
  solid = True
732
898
 
733
899
  t0 = self.calc._temperature
734
900
  tf = self.calc._temperature_stop
735
901
  li = 1
736
- lf = t0/tf
902
+ lf = t0 / tf
737
903
  pi = self.calc._pressure
738
- pf = lf*pi
904
+ pf = lf * pi
739
905
 
740
- #create lammps object
741
- lmp = ph.create_object(self.cores, self.simfolder, self.calc.md.timestep,
742
- self.calc.md.cmdargs, self.calc.md.init_commands)
906
+ # create lammps object
907
+ lmp = ph.create_object(
908
+ self.cores,
909
+ self.simfolder,
910
+ self.calc.md.timestep,
911
+ self.calc.md.cmdargs,
912
+ self.calc.md.init_commands,
913
+ )
743
914
 
744
915
  lmp.command("echo log")
745
- lmp.command("variable li equal %f"%li)
746
- lmp.command("variable lf equal %f"%lf)
916
+ lmp.command("variable li equal %f" % li)
917
+ lmp.command("variable lf equal %f" % lf)
747
918
 
748
- lmp.command(f'pair_style {self.calc._pair_style_with_options[0]}')
919
+ lmp.command(f"pair_style {self.calc._pair_style_with_options[0]}")
749
920
 
750
- #read in conf file
751
- #conf = os.path.join(self.simfolder, "conf.equilibration.dump")
921
+ # read in conf file
922
+ # conf = os.path.join(self.simfolder, "conf.equilibration.dump")
752
923
  conf = os.path.join(self.simfolder, "conf.equilibration.data")
753
924
  lmp = ph.read_data(lmp, conf)
754
925
 
755
- #set up potential
756
- lmp.command(f'pair_coeff {self.calc.pair_coeff[0]}')
926
+ # set up potential
927
+ lmp.command(f"pair_coeff {self.calc.pair_coeff[0]}")
757
928
  lmp = ph.set_mass(lmp, self.calc)
758
929
 
759
- #remap the box to get the correct pressure
930
+ # remap the box to get the correct pressure
760
931
  lmp = ph.remap_box(lmp, self.lx, self.ly, self.lz)
761
932
 
762
- #set thermostat and run equilibrium
933
+ # set thermostat and run equilibrium
763
934
  if self.calc.npt:
764
- lmp.command("fix f1 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
765
- self.iso, pi, pi, self.calc.md.barostat_damping[1]))
935
+ lmp.command(
936
+ "fix f1 all npt temp %f %f %f %s %f %f %f"
937
+ % (
938
+ t0,
939
+ t0,
940
+ self.calc.md.thermostat_damping[1],
941
+ self.iso,
942
+ pi,
943
+ pi,
944
+ self.calc.md.barostat_damping[1],
945
+ )
946
+ )
766
947
  else:
767
- lmp.command("fix f1 all nvt temp %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1]))
768
-
769
- self.logger.info(f'Starting equilibration: {iteration}')
770
- lmp.command("run %d"%self.calc.n_equilibration_steps)
771
- self.logger.info(f'Finished equilibration: {iteration}')
948
+ lmp.command(
949
+ "fix f1 all nvt temp %f %f %f"
950
+ % (t0, t0, self.calc.md.thermostat_damping[1])
951
+ )
952
+
953
+ self.logger.info(f"Starting equilibration: {iteration}")
954
+ lmp.command("run %d" % self.calc.n_equilibration_steps)
955
+ self.logger.info(f"Finished equilibration: {iteration}")
772
956
 
773
957
  lmp.command("unfix f1")
774
958
 
775
- #now fix com
959
+ # now fix com
776
960
  lmp.command("variable xcm equal xcm(all,x)")
777
961
  lmp.command("variable ycm equal xcm(all,y)")
778
962
  lmp.command("variable zcm equal xcm(all,z)")
779
963
 
780
964
  if self.calc.npt:
781
- lmp.command("fix f1 all npt temp %f %f %f %s %f %f %f fixedpoint ${xcm} ${ycm} ${zcm}"%(t0, t0, self.calc.md.thermostat_damping[1],
782
- self.iso, pi, pi, self.calc.md.barostat_damping[1]))
965
+ lmp.command(
966
+ "fix f1 all npt temp %f %f %f %s %f %f %f fixedpoint ${xcm} ${ycm} ${zcm}"
967
+ % (
968
+ t0,
969
+ t0,
970
+ self.calc.md.thermostat_damping[1],
971
+ self.iso,
972
+ pi,
973
+ pi,
974
+ self.calc.md.barostat_damping[1],
975
+ )
976
+ )
783
977
  else:
784
- lmp.command("fix f1 all nvt temp %f %f %f fixedpoint ${xcm} ${ycm} ${zcm}"%(t0, t0, self.calc.md.thermostat_damping[1]))
978
+ lmp.command(
979
+ "fix f1 all nvt temp %f %f %f fixedpoint ${xcm} ${ycm} ${zcm}"
980
+ % (t0, t0, self.calc.md.thermostat_damping[1])
981
+ )
785
982
 
786
- #compute com and modify fix
983
+ # compute com and modify fix
787
984
  lmp.command("compute tcm all temp/com")
788
985
  lmp.command("fix_modify f1 temp tcm")
789
986
 
790
987
  lmp.command("variable step equal step")
791
- lmp.command("variable dU equal c_thermo_pe/atoms")
988
+ lmp.command("variable dU equal c_thermo_pe/atoms")
792
989
  lmp.command("thermo_style custom step pe c_tcm press vol")
793
990
  lmp.command("thermo 10000")
794
991
 
795
- #create velocity and equilibriate
796
- lmp.command("velocity all create %f %d mom yes rot yes dist gaussian"%(t0, np.random.randint(1, 10000)))
992
+ # create velocity and equilibriate
993
+ lmp.command(
994
+ "velocity all create %f %d mom yes rot yes dist gaussian"
995
+ % (t0, np.random.randint(1, 10000))
996
+ )
997
+
998
+ self.logger.info(f"Starting equilibration with constrained com: {iteration}")
999
+ lmp.command("run %d" % self.calc.n_equilibration_steps)
1000
+ self.logger.info(f"Finished equilibration with constrained com: {iteration}")
797
1001
 
798
- self.logger.info(f'Starting equilibration with constrained com: {iteration}')
799
- lmp.command("run %d"%self.calc.n_equilibration_steps)
800
- self.logger.info(f'Finished equilibration with constrained com: {iteration}')
801
-
802
1002
  lmp.command("variable flambda equal ramp(${li},${lf})")
803
1003
  lmp.command("variable blambda equal ramp(${lf},${li})")
804
1004
  lmp.command("variable fscale equal v_flambda-1.0")
805
1005
  lmp.command("variable bscale equal v_blambda-1.0")
806
1006
  lmp.command("variable one equal 1.0")
807
-
808
- #set up potential
809
- pc = self.calc.pair_coeff[0]
1007
+ lmp.command(
1008
+ f"variable ftemp equal v_blambda*{self.calc._temperature_stop}"
1009
+ )
1010
+ lmp.command(
1011
+ f"variable btemp equal v_flambda*{self.calc._temperature_stop}"
1012
+ )
1013
+
1014
+ # set up potential
1015
+ pc = self.calc.pair_coeff[0]
810
1016
  pcraw = pc.split()
811
- pcnew1 = " ".join([*pcraw[:2], *[self.calc._pair_style_names[0],], "1", *pcraw[2:]])
812
- pcnew2 = " ".join([*pcraw[:2], *[self.calc._pair_style_names[0],], "2", *pcraw[2:]])
1017
+ pcnew1 = " ".join(
1018
+ [
1019
+ *pcraw[:2],
1020
+ *[
1021
+ self.calc._pair_style_names[0],
1022
+ ],
1023
+ "1",
1024
+ *pcraw[2:],
1025
+ ]
1026
+ )
1027
+ pcnew2 = " ".join(
1028
+ [
1029
+ *pcraw[:2],
1030
+ *[
1031
+ self.calc._pair_style_names[0],
1032
+ ],
1033
+ "2",
1034
+ *pcraw[2:],
1035
+ ]
1036
+ )
1037
+
1038
+ lmp.command(
1039
+ "pair_style hybrid/scaled v_one %s v_fscale %s"
1040
+ % (
1041
+ self.calc._pair_style_with_options[0],
1042
+ self.calc._pair_style_with_options[0],
1043
+ )
1044
+ )
1045
+ lmp.command("pair_coeff %s" % pcnew1)
1046
+ lmp.command("pair_coeff %s" % pcnew2)
1047
+
1048
+ lmp.command(
1049
+ 'fix f3 all print 1 "${dU} $(press) $(vol) ${flambda}" screen no file ts.forward_%d.dat'
1050
+ % iteration
1051
+ )
1052
+
1053
+ # add swaps if n_swap is > 0
1054
+ if self.calc.monte_carlo.n_swaps > 0:
1055
+ self.logger.info(
1056
+ 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}"
1057
+ )
1058
+ lmp.command(
1059
+ "fix swap all atom/swap %d %d %d ${ftemp} ke yes types %d %d"
1060
+ % (
1061
+ self.calc.monte_carlo.n_steps,
1062
+ self.calc.monte_carlo.n_swaps,
1063
+ np.random.randint(1, 10000),
1064
+ self.calc.monte_carlo.swap_types[0],
1065
+ self.calc.monte_carlo.swap_types[1],
1066
+ )
1067
+ )
1068
+
1069
+ lmp.command("variable a equal f_swap[1]")
1070
+ lmp.command("variable b equal f_swap[2]")
1071
+ lmp.command(
1072
+ 'fix swap2 all print 1 "${a} ${b} ${ftemp}" screen no file swap.rs.forward_%d.dat'
1073
+ % iteration
1074
+ )
813
1075
 
814
- lmp.command("pair_style hybrid/scaled v_one %s v_fscale %s"%(self.calc._pair_style_with_options[0], self.calc._pair_style_with_options[0]))
815
- lmp.command("pair_coeff %s"%pcnew1)
816
- lmp.command("pair_coeff %s"%pcnew2)
1076
+ if self.calc.n_print_steps > 0:
1077
+ lmp.command(
1078
+ "dump d1 all custom %d traj.ts.forward_%d.dat id type mass x y z vx vy vz"
1079
+ % (self.calc.n_print_steps, iteration)
1080
+ )
817
1081
 
818
- lmp.command("fix f3 all print 1 \"${dU} $(press) $(vol) ${flambda}\" screen no file ts.forward_%d.dat"%iteration)
1082
+ self.logger.info(f"Started forward sweep: {iteration}")
1083
+ lmp.command("run %d" % self.calc._n_sweep_steps)
1084
+ self.logger.info(f"Finished forward sweep: {iteration}")
819
1085
 
820
- if self.calc.n_print_steps > 0:
821
- lmp.command("dump d1 all custom %d traj.ts.forward_%d.dat id type mass x y z vx vy vz"%(self.calc.n_print_steps,
822
- iteration))
823
-
824
- self.logger.info(f'Started forward sweep: {iteration}')
825
- lmp.command("run %d"%self.calc._n_sweep_steps)
826
- self.logger.info(f'Finished forward sweep: {iteration}')
827
-
828
- #unfix
1086
+ if self.calc.monte_carlo.n_swaps > 0:
1087
+ lmp.command("unfix swap")
1088
+ lmp.command("unfix swap2")
1089
+
1090
+ # unfix
829
1091
  lmp.command("unfix f3")
830
- #lmp.command("unfix f1")
1092
+ # lmp.command("unfix f1")
831
1093
 
832
1094
  if self.calc.n_print_steps > 0:
833
1095
  lmp.command("undump d1")
834
1096
 
835
- #switch potential
836
- lmp.command("run %d"%self.calc.n_equilibration_steps)
1097
+ # switch potential
1098
+ lmp.command("run %d" % self.calc.n_equilibration_steps)
837
1099
 
838
- #check melting or freezing
1100
+ # check melting or freezing
839
1101
  if not self.calc.script_mode:
840
1102
  self.dump_current_snapshot(lmp, "traj.temp.dat")
841
1103
  if solid:
@@ -845,41 +1107,87 @@ class Phase:
845
1107
 
846
1108
  lmp = ph.set_potential(lmp, self.calc)
847
1109
 
848
- #reverse scaling
1110
+ # reverse scaling
849
1111
  lmp.command("variable flambda equal ramp(${li},${lf})")
850
1112
  lmp.command("variable blambda equal ramp(${lf},${li})")
851
1113
  lmp.command("variable fscale equal v_flambda-1.0")
852
1114
  lmp.command("variable bscale equal v_blambda-1.0")
853
1115
  lmp.command("variable one equal 1.0")
854
-
855
- lmp.command("pair_style hybrid/scaled v_one %s v_bscale %s"%(self.calc._pair_style_with_options[0], self.calc._pair_style_with_options[0]))
856
- lmp.command("pair_coeff %s"%pcnew1)
857
- lmp.command("pair_coeff %s"%pcnew2)
858
-
859
- #apply fix and perform switching
860
- lmp.command("fix f3 all print 1 \"${dU} $(press) $(vol) ${blambda}\" screen no file ts.backward_%d.dat"%iteration)
1116
+ lmp.command(
1117
+ f"variable ftemp equal v_blambda*{self.calc._temperature_stop}"
1118
+ )
1119
+ lmp.command(
1120
+ f"variable btemp equal v_flambda*{self.calc._temperature_stop}"
1121
+ )
1122
+
1123
+ lmp.command(
1124
+ "pair_style hybrid/scaled v_one %s v_bscale %s"
1125
+ % (
1126
+ self.calc._pair_style_with_options[0],
1127
+ self.calc._pair_style_with_options[0],
1128
+ )
1129
+ )
1130
+ lmp.command("pair_coeff %s" % pcnew1)
1131
+ lmp.command("pair_coeff %s" % pcnew2)
1132
+
1133
+ # apply fix and perform switching
1134
+ lmp.command(
1135
+ 'fix f3 all print 1 "${dU} $(press) $(vol) ${blambda}" screen no file ts.backward_%d.dat'
1136
+ % iteration
1137
+ )
861
1138
 
862
1139
  if self.calc.n_print_steps > 0:
863
- lmp.command("dump d1 all custom %d traj.ts.backward_%d.dat id type mass x y z vx vy vz"%(self.calc.n_print_steps,
864
- iteration))
1140
+ lmp.command(
1141
+ "dump d1 all custom %d traj.ts.backward_%d.dat id type mass x y z vx vy vz"
1142
+ % (self.calc.n_print_steps, iteration)
1143
+ )
1144
+
1145
+ # add swaps if n_swap is > 0
1146
+ if self.calc.monte_carlo.n_swaps > 0:
1147
+ self.logger.info(
1148
+ 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}"
1149
+ )
1150
+ lmp.command(
1151
+ "fix swap all atom/swap %d %d %d ${btemp} ke yes types %d %d"
1152
+ % (
1153
+ self.calc.monte_carlo.n_steps,
1154
+ self.calc.monte_carlo.n_swaps,
1155
+ np.random.randint(1, 10000),
1156
+ self.calc.monte_carlo.swap_types[1],
1157
+ self.calc.monte_carlo.swap_types[0],
1158
+ )
1159
+ )
1160
+
1161
+ lmp.command("variable a equal f_swap[1]")
1162
+ lmp.command("variable b equal f_swap[2]")
1163
+ lmp.command(
1164
+ 'fix swap2 all print 1 "${a} ${b} ${btemp}" screen no file swap.rs.backward_%d.dat'
1165
+ % iteration
1166
+ )
1167
+
1168
+ self.logger.info(f"Started backward sweep: {iteration}")
1169
+ lmp.command("run %d" % self.calc._n_sweep_steps)
1170
+ self.logger.info(f"Finished backward sweep: {iteration}")
1171
+
1172
+ if self.calc.monte_carlo.n_swaps > 0:
1173
+ lmp.command("unfix swap")
1174
+ lmp.command("unfix swap2")
865
1175
 
866
- self.logger.info(f'Started backward sweep: {iteration}')
867
- lmp.command("run %d"%self.calc._n_sweep_steps)
868
- self.logger.info(f'Finished backward sweep: {iteration}')
869
-
870
1176
  lmp.command("unfix f3")
871
1177
 
872
1178
  if self.calc.n_print_steps > 0:
873
1179
  lmp.command("undump d1")
874
-
875
- #close the object
1180
+
1181
+ # close the object
876
1182
  lmp.close()
877
1183
 
878
1184
  self.logger.info("Please cite the following publications:")
879
1185
  if self.calc.mode == "mts":
880
1186
  self.logger.info("- 10.1063/1.1420486")
1187
+ self.publications.append("10.1063/1.1420486")
881
1188
  else:
882
1189
  self.logger.info("- 10.1103/PhysRevLett.83.3973")
1190
+ self.publications.append("10.1103/PhysRevLett.83.3973")
883
1191
 
884
1192
  def integrate_reversible_scaling(self, scale_energy=True, return_values=False):
885
1193
  """
@@ -888,7 +1196,7 @@ class Phase:
888
1196
  Parameters
889
1197
  ----------
890
1198
  scale_energy : bool, optional
891
- If True, scale the energy during reversible scaling.
1199
+ If True, scale the energy during reversible scaling.
892
1200
 
893
1201
  return_values : bool, optional
894
1202
  If True, return integrated values
@@ -898,8 +1206,16 @@ class Phase:
898
1206
  res : list of lists of shape 1x3
899
1207
  Only returned if `return_values` is True.
900
1208
  """
901
- res = integrate_rs(self.simfolder, self.fe, self.calc._temperature, self.natoms, p=self.calc._pressure,
902
- nsims=self.calc.n_iterations, scale_energy=scale_energy, return_values=return_values)
1209
+ res = integrate_rs(
1210
+ self.simfolder,
1211
+ self.fe,
1212
+ self.calc._temperature,
1213
+ self.natoms,
1214
+ p=self.calc._pressure,
1215
+ nsims=self.calc.n_iterations,
1216
+ scale_energy=scale_energy,
1217
+ return_values=return_values,
1218
+ )
903
1219
 
904
1220
  if return_values:
905
1221
  return res
@@ -907,80 +1223,118 @@ class Phase:
907
1223
  def temperature_scaling(self, iteration=1):
908
1224
  """
909
1225
  Perform temperature scaling calculation in NPT
910
-
1226
+
911
1227
  Parameters
912
1228
  ----------
913
1229
  iteration : int, optional
914
1230
  iteration of the calculation. Default 1
915
-
1231
+
916
1232
  Returns
917
1233
  -------
918
1234
  None
919
1235
  """
920
1236
  solid = False
921
- if self.calc.reference_phase == 'solid':
1237
+ if self.calc.reference_phase == "solid":
922
1238
  solid = True
923
1239
 
924
1240
  t0 = self.calc._temperature
925
1241
  tf = self.calc._temperature_stop
926
1242
  li = 1
927
- lf = t0/tf
1243
+ lf = t0 / tf
928
1244
  p0 = self.calc._pressure
929
- pf = lf*p0
1245
+ pf = lf * p0
930
1246
 
931
- #create lammps object
932
- lmp = ph.create_object(self.cores, self.simfolder, self.calc.md.timestep,
933
- self.calc.md.cmdargs, self.calc.md.init_commands)
1247
+ # create lammps object
1248
+ lmp = ph.create_object(
1249
+ self.cores,
1250
+ self.simfolder,
1251
+ self.calc.md.timestep,
1252
+ self.calc.md.cmdargs,
1253
+ self.calc.md.init_commands,
1254
+ )
934
1255
 
935
1256
  lmp.command("echo log")
936
- lmp.command("variable li equal %f"%li)
937
- lmp.command("variable lf equal %f"%lf)
1257
+ lmp.command("variable li equal %f" % li)
1258
+ lmp.command("variable lf equal %f" % lf)
938
1259
 
939
- lmp.command(f'pair_style {self.calc._pair_style_with_options[0]}')
1260
+ lmp.command(f"pair_style {self.calc._pair_style_with_options[0]}")
940
1261
 
941
- #read in conf
942
- #conf = os.path.join(self.simfolder, "conf.equilibration.dump")
1262
+ # read in conf
1263
+ # conf = os.path.join(self.simfolder, "conf.equilibration.dump")
943
1264
  conf = os.path.join(self.simfolder, "conf.equilibration.data")
944
1265
  lmp = ph.read_data(lmp, conf)
945
1266
 
946
- #set up potential
947
- lmp.command(f'pair_coeff {self.calc.pair_coeff[0]}')
1267
+ # set up potential
1268
+ lmp.command(f"pair_coeff {self.calc.pair_coeff[0]}")
948
1269
  lmp = ph.set_mass(lmp, self.calc)
949
1270
 
950
- #remap the box to get the correct pressure
1271
+ # remap the box to get the correct pressure
951
1272
  lmp = ph.remap_box(lmp, self.lx, self.ly, self.lz)
952
1273
 
953
-
954
- #equilibrate first
955
- lmp.command("fix 1 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
956
- self.iso, p0, p0, self.calc.md.barostat_damping[1]))
957
- lmp.command("run %d"%self.calc.n_equilibration_steps)
1274
+ # equilibrate first
1275
+ lmp.command(
1276
+ "fix 1 all npt temp %f %f %f %s %f %f %f"
1277
+ % (
1278
+ t0,
1279
+ t0,
1280
+ self.calc.md.thermostat_damping[1],
1281
+ self.iso,
1282
+ p0,
1283
+ p0,
1284
+ self.calc.md.barostat_damping[1],
1285
+ )
1286
+ )
1287
+ lmp.command("run %d" % self.calc.n_equilibration_steps)
958
1288
  lmp.command("unfix 1")
959
1289
 
960
-
961
- #now scale system to final temp, thereby recording enerfy at every step
1290
+ # now scale system to final temp, thereby recording enerfy at every step
962
1291
  lmp.command("variable step equal step")
963
1292
  lmp.command("variable dU equal pe/atoms")
964
1293
  lmp.command("variable lambda equal ramp(${li},${lf})")
965
1294
 
966
- lmp.command("fix f2 all npt temp %f %f %f %s %f %f %f"%(t0, tf, self.calc.md.thermostat_damping[1],
967
- self.iso, p0, pf, self.calc.md.barostat_damping[1]))
968
- lmp.command("fix f3 all print 1 \"${dU} $(press) $(vol) ${lambda}\" screen no file ts.forward_%d.dat"%iteration)
969
- lmp.command("run %d"%self.calc._n_sweep_steps)
1295
+ lmp.command(
1296
+ "fix f2 all npt temp %f %f %f %s %f %f %f"
1297
+ % (
1298
+ t0,
1299
+ tf,
1300
+ self.calc.md.thermostat_damping[1],
1301
+ self.iso,
1302
+ p0,
1303
+ pf,
1304
+ self.calc.md.barostat_damping[1],
1305
+ )
1306
+ )
1307
+ lmp.command(
1308
+ 'fix f3 all print 1 "${dU} $(press) $(vol) ${lambda}" screen no file ts.forward_%d.dat'
1309
+ % iteration
1310
+ )
1311
+ lmp.command("run %d" % self.calc._n_sweep_steps)
970
1312
 
971
1313
  lmp.command("unfix f2")
972
1314
  lmp.command("unfix f3")
973
1315
 
974
- lmp.command("fix 1 all npt temp %f %f %f %s %f %f %f"%(tf, tf, self.calc.md.thermostat_damping[1],
975
- self.iso, pf, pf, self.calc.md.barostat_damping[1]))
976
- lmp.command("run %d"%self.calc.n_equilibration_steps)
1316
+ lmp.command(
1317
+ "fix 1 all npt temp %f %f %f %s %f %f %f"
1318
+ % (
1319
+ tf,
1320
+ tf,
1321
+ self.calc.md.thermostat_damping[1],
1322
+ self.iso,
1323
+ pf,
1324
+ pf,
1325
+ self.calc.md.barostat_damping[1],
1326
+ )
1327
+ )
1328
+ lmp.command("run %d" % self.calc.n_equilibration_steps)
977
1329
  lmp.command("unfix 1")
978
1330
 
979
- #check melting or freezing
980
- lmp.command("dump 2 all custom 1 traj.temp.dat id type mass x y z vx vy vz")
1331
+ # check melting or freezing
1332
+ lmp.command(
1333
+ "dump 2 all custom 1 traj.temp.dat id type mass x y z vx vy vz"
1334
+ )
981
1335
  lmp.command("run 0")
982
1336
  lmp.command("undump 2")
983
-
1337
+
984
1338
  if not self.calc.script_mode:
985
1339
  self.dump_current_snapshot(lmp, "traj.temp.dat")
986
1340
  if solid:
@@ -988,26 +1342,38 @@ class Phase:
988
1342
  else:
989
1343
  self.check_if_solidfied(lmp, "traj.temp.dat")
990
1344
 
991
- #start reverse loop
1345
+ # start reverse loop
992
1346
  lmp.command("variable lambda equal ramp(${lf},${li})")
993
1347
 
994
- lmp.command("fix f2 all npt temp %f %f %f %s %f %f %f"%(tf, t0, self.calc.md.thermostat_damping[1],
995
- self.iso, pf, p0, self.calc.md.barostat_damping[1]))
996
- lmp.command("fix f3 all print 1 \"${dU} $(press) $(vol) ${lambda}\" screen no file ts.backward_%d.dat"%iteration)
997
- lmp.command("run %d"%self.calc._n_sweep_steps)
1348
+ lmp.command(
1349
+ "fix f2 all npt temp %f %f %f %s %f %f %f"
1350
+ % (
1351
+ tf,
1352
+ t0,
1353
+ self.calc.md.thermostat_damping[1],
1354
+ self.iso,
1355
+ pf,
1356
+ p0,
1357
+ self.calc.md.barostat_damping[1],
1358
+ )
1359
+ )
1360
+ lmp.command(
1361
+ 'fix f3 all print 1 "${dU} $(press) $(vol) ${lambda}" screen no file ts.backward_%d.dat'
1362
+ % iteration
1363
+ )
1364
+ lmp.command("run %d" % self.calc._n_sweep_steps)
998
1365
 
999
1366
  lmp.close()
1000
1367
 
1001
-
1002
1368
  def pressure_scaling(self, iteration=1):
1003
1369
  """
1004
1370
  Perform pressure scaling calculation in NPT
1005
-
1371
+
1006
1372
  Parameters
1007
1373
  ----------
1008
1374
  iteration : int, optional
1009
1375
  iteration of the calculation. Default 1
1010
-
1376
+
1011
1377
  Returns
1012
1378
  -------
1013
1379
  None
@@ -1018,91 +1384,162 @@ class Phase:
1018
1384
  p0 = self.calc._pressure
1019
1385
  pf = self.calc._pressure_stop
1020
1386
 
1021
- #create lammps object
1022
- lmp = ph.create_object(self.cores, self.simfolder, self.calc.md.timestep,
1023
- self.calc.md.cmdargs, self.calc.md.init_commands)
1387
+ # create lammps object
1388
+ lmp = ph.create_object(
1389
+ self.cores,
1390
+ self.simfolder,
1391
+ self.calc.md.timestep,
1392
+ self.calc.md.cmdargs,
1393
+ self.calc.md.init_commands,
1394
+ )
1024
1395
 
1025
1396
  lmp.command("echo log")
1026
- lmp.command("variable li equal %f"%li)
1027
- lmp.command("variable lf equal %f"%lf)
1028
- lmp.command("variable p0 equal %f"%p0)
1029
- lmp.command("variable pf equal %f"%pf)
1397
+ lmp.command("variable li equal %f" % li)
1398
+ lmp.command("variable lf equal %f" % lf)
1399
+ lmp.command("variable p0 equal %f" % p0)
1400
+ lmp.command("variable pf equal %f" % pf)
1030
1401
 
1031
- lmp.command(f'pair_style {self.calc._pair_style_with_options[0]}')
1402
+ lmp.command(f"pair_style {self.calc._pair_style_with_options[0]}")
1032
1403
 
1033
- #read in conf
1034
- #conf = os.path.join(self.simfolder, "conf.dump")
1404
+ # read in conf
1405
+ # conf = os.path.join(self.simfolder, "conf.dump")
1035
1406
  conf = os.path.join(self.simfolder, "conf.equilibration.data")
1036
1407
  lmp = ph.read_data(lmp, conf)
1037
1408
 
1038
- #set up potential
1039
- lmp.command(f'pair_coeff {self.calc.pair_coeff[0]}')
1409
+ # set up potential
1410
+ lmp.command(f"pair_coeff {self.calc.pair_coeff[0]}")
1040
1411
  lmp = ph.set_mass(lmp, self.calc)
1041
1412
 
1042
- #remap the box to get the correct pressure
1413
+ # remap the box to get the correct pressure
1043
1414
  lmp = ph.remap_box(lmp, self.lx, self.ly, self.lz)
1044
1415
 
1045
- #equilibrate first
1046
- lmp.command("fix 1 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
1047
- self.iso, p0, p0, self.calc.md.barostat_damping[1]))
1048
- lmp.command("run %d"%self.calc.n_equilibration_steps)
1416
+ # equilibrate first
1417
+ lmp.command(
1418
+ "fix 1 all npt temp %f %f %f %s %f %f %f"
1419
+ % (
1420
+ t0,
1421
+ t0,
1422
+ self.calc.md.thermostat_damping[1],
1423
+ self.iso,
1424
+ p0,
1425
+ p0,
1426
+ self.calc.md.barostat_damping[1],
1427
+ )
1428
+ )
1429
+ lmp.command("run %d" % self.calc.n_equilibration_steps)
1049
1430
  lmp.command("unfix 1")
1050
1431
 
1051
-
1052
- #now scale system to final temp, thereby recording enerfy at every step
1432
+ # now scale system to final temp, thereby recording enerfy at every step
1053
1433
  lmp.command("variable step equal step")
1054
1434
  lmp.command("variable dU equal pe/atoms")
1055
1435
  lmp.command("variable lambda equal ramp(${li},${lf})")
1056
1436
  lmp.command("variable pp equal ramp(${p0},${pf})")
1057
1437
 
1058
- lmp.command("fix f2 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
1059
- self.iso, p0, pf, self.calc.md.barostat_damping[1]))
1060
- lmp.command("fix f3 all print 1 \"${dU} ${pp} $(vol) ${lambda}\" screen no file ps.forward_%d.dat"%iteration)
1061
- lmp.command("run %d"%self.calc._n_sweep_steps)
1438
+ lmp.command(
1439
+ "fix f2 all npt temp %f %f %f %s %f %f %f"
1440
+ % (
1441
+ t0,
1442
+ t0,
1443
+ self.calc.md.thermostat_damping[1],
1444
+ self.iso,
1445
+ p0,
1446
+ pf,
1447
+ self.calc.md.barostat_damping[1],
1448
+ )
1449
+ )
1450
+ lmp.command(
1451
+ 'fix f3 all print 1 "${dU} ${pp} $(vol) ${lambda}" screen no file ps.forward_%d.dat'
1452
+ % iteration
1453
+ )
1454
+ lmp.command("run %d" % self.calc._n_sweep_steps)
1062
1455
 
1063
1456
  lmp.command("unfix f2")
1064
1457
  lmp.command("unfix f3")
1065
1458
 
1066
-
1067
- lmp.command("fix 1 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
1068
- self.iso, pf, pf, self.calc.md.barostat_damping[1]))
1069
- lmp.command("run %d"%self.calc.n_equilibration_steps)
1459
+ lmp.command(
1460
+ "fix 1 all npt temp %f %f %f %s %f %f %f"
1461
+ % (
1462
+ t0,
1463
+ t0,
1464
+ self.calc.md.thermostat_damping[1],
1465
+ self.iso,
1466
+ pf,
1467
+ pf,
1468
+ self.calc.md.barostat_damping[1],
1469
+ )
1470
+ )
1471
+ lmp.command("run %d" % self.calc.n_equilibration_steps)
1070
1472
  lmp.command("unfix 1")
1071
1473
 
1072
- #start reverse loop
1474
+ # start reverse loop
1073
1475
  lmp.command("variable lambda equal ramp(${lf},${li})")
1074
1476
  lmp.command("variable pp equal ramp(${pf},${p0})")
1075
1477
 
1076
- lmp.command("fix f2 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
1077
- self.iso, pf, p0, self.calc.md.barostat_damping[1]))
1078
- lmp.command("fix f3 all print 1 \"${dU} ${pp} $(vol) ${lambda}\" screen no file ps.backward_%d.dat"%iteration)
1079
- lmp.command("run %d"%self.calc._n_sweep_steps)
1478
+ lmp.command(
1479
+ "fix f2 all npt temp %f %f %f %s %f %f %f"
1480
+ % (
1481
+ t0,
1482
+ t0,
1483
+ self.calc.md.thermostat_damping[1],
1484
+ self.iso,
1485
+ pf,
1486
+ p0,
1487
+ self.calc.md.barostat_damping[1],
1488
+ )
1489
+ )
1490
+ lmp.command(
1491
+ 'fix f3 all print 1 "${dU} ${pp} $(vol) ${lambda}" screen no file ps.backward_%d.dat'
1492
+ % iteration
1493
+ )
1494
+ lmp.command("run %d" % self.calc._n_sweep_steps)
1080
1495
 
1081
1496
  lmp.close()
1082
1497
 
1083
1498
  self.logger.info("Please cite the following publications:")
1084
1499
  self.logger.info("- 10.1016/j.commatsci.2022.111275")
1085
-
1086
-
1500
+ self.publications.append("10.1016/j.commatsci.2022.111275")
1501
+
1087
1502
  def integrate_pressure_scaling(self, return_values=False):
1088
1503
  """
1089
1504
  Perform integration after reversible scaling
1090
-
1505
+
1091
1506
  Parameters
1092
1507
  ----------
1093
1508
  scale_energy : bool, optional
1094
- If True, scale the energy during reversible scaling.
1509
+ If True, scale the energy during reversible scaling.
1095
1510
  return_values : bool, optional
1096
1511
  If True, return integrated values
1097
-
1512
+
1098
1513
  Returns
1099
1514
  -------
1100
1515
  res : list of lists of shape 1x3
1101
1516
  Only returned if `return_values` is True.
1102
1517
  """
1103
- res = integrate_ps(self.simfolder, self.fe, self.natoms,
1104
- self.calc._pressure, self.calc._pressure_stop,
1105
- nsims=self.calc.n_iterations, return_values=return_values)
1518
+ res = integrate_ps(
1519
+ self.simfolder,
1520
+ self.fe,
1521
+ self.natoms,
1522
+ self.calc._pressure,
1523
+ self.calc._pressure_stop,
1524
+ nsims=self.calc.n_iterations,
1525
+ return_values=return_values,
1526
+ )
1106
1527
 
1107
1528
  if return_values:
1108
1529
  return res
1530
+
1531
+ def clean_up(self):
1532
+ """
1533
+ Run a clean up job
1534
+ """
1535
+ # serialise input configuration
1536
+ shutil.copy(
1537
+ self.calc.lattice, os.path.join(self.simfolder, "input_configuration.data")
1538
+ )
1539
+
1540
+ # write simple metadata
1541
+ metadata = generate_metadata()
1542
+ metadata["publications"] = self.publications
1543
+
1544
+ with open(os.path.join(self.simfolder, "metadata.yaml"), "w") as fout:
1545
+ yaml.safe_dump(metadata, fout)