calphy 1.3.13__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,67 +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
- #we have to clean the data, so as just the last block is selected
727
+ # we have to clean the data, so as just the last block is selected
602
728
  lx, ly, lz, lxpc = np.loadtxt(file, usecols=(1, 2, 3, 4), unpack=True)
603
- lx = lx[-ncount+1:]
604
- ly = ly[-ncount+1:]
605
- lz = lx[-ncount+1:]
606
- lxpc = lxpc[-ncount+1:]
729
+ lx = lx[-ncount + 1 :]
730
+ ly = ly[-ncount + 1 :]
731
+ lz = lx[-ncount + 1 :]
732
+ lxpc = lxpc[-ncount + 1 :]
607
733
  mean = np.mean(lxpc)
608
734
  std = np.std(lxpc)
609
- volatom = np.mean((lx*ly*lz)/self.natoms)
735
+ volatom = np.mean((lx * ly * lz) / self.natoms)
610
736
  return mean, std, volatom
611
737
 
612
- def finalise_pressure(self,):
738
+ def finalise_pressure(
739
+ self,
740
+ ):
613
741
  if self.calc.script_mode:
614
- ncount = int(self.calc.n_equilibration_steps)//int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)
615
- else:
616
- 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
+ )
617
749
 
618
750
  file = os.path.join(self.simfolder, "avg.dat")
619
- lx, ly, lz, lxpc = np.loadtxt(file, usecols=(1, 2, 3, 4), unpack=True)
620
- lx = lx[-ncount+1:]
621
- ly = ly[-ncount+1:]
622
- lz = lx[-ncount+1:]
623
- lxpc = lxpc[-ncount+1:]
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 :]
624
756
 
625
757
  mean = np.mean(lxpc)
626
758
  std = np.std(lxpc)
627
- volatom = np.mean((lx*ly*lz)/self.natoms)
759
+ volatom = np.mean((lx * ly * lz) / self.natoms)
628
760
 
629
761
  self.calc._pressure = mean
630
762
  self.lx = np.round(np.mean(lx), decimals=3)
631
763
  self.ly = np.round(np.mean(ly), decimals=3)
632
764
  self.lz = np.round(np.mean(lz), decimals=3)
633
765
  self.volatom = volatom
634
- self.vol = self.lx*self.ly*self.lz
635
- self.rho = self.natoms/(self.lx*self.ly*self.lz)
636
- self.logger.info("finalized vol/atom %f at pressure %f"%(self.volatom, mean))
637
- self.logger.info("Avg box dimensions x: %f, y: %f, z:%f"%(self.lx, self.ly, self.lz))
638
-
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
+ )
639
772
 
640
773
  def run_minimal_constrained_pressure_convergence(self, lmp):
641
- """
642
- """
643
- lmp.command("velocity all create %f %d"%(self.calc._temperature, np.random.randint(1, 10000)))
644
- 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
+ )
645
787
  lmp.command("thermo_style custom step pe press vol etotal temp lx ly lz")
646
788
  lmp.command("thermo 10")
647
-
648
- #this is when the averaging routine starts
649
- 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),
650
- int(self.calc.md.n_repeat_steps), int(self.calc.md.n_every_steps*self.calc.md.n_repeat_steps)))
651
789
 
652
- lmp.command("run %d"%int(self.calc.md.n_small_steps))
653
- 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))
654
802
 
655
803
  lmp.command("unfix 1")
656
804
  lmp.command("unfix 2")
@@ -670,24 +818,30 @@ class Phase:
670
818
  """
671
819
  report = {}
672
820
 
673
- #input quantities
821
+ # input quantities
674
822
  report["input"] = {}
675
823
  report["input"]["temperature"] = int(self.calc._temperature)
676
824
  report["input"]["pressure"] = float(self.calc._pressure)
677
825
  report["input"]["lattice"] = str(self.calc._original_lattice)
678
826
  report["input"]["element"] = " ".join(np.array(self.calc.element).astype(str))
679
- 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
+ )
680
832
 
681
- #average quantities
833
+ # average quantities
682
834
  report["average"] = {}
683
835
  report["average"]["vol_atom"] = float(self.volatom)
684
-
836
+
685
837
  if self.k is not None:
686
- 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
+ )
687
841
  if self.rho is not None:
688
842
  report["average"]["density"] = float(self.rho)
689
843
 
690
- #results
844
+ # results
691
845
  report["results"] = {}
692
846
  report["results"]["free_energy"] = float(self.fe)
693
847
  report["results"]["error"] = float(self.ferr)
@@ -704,21 +858,25 @@ class Phase:
704
858
  self.report = report
705
859
 
706
860
  reportfile = os.path.join(self.simfolder, "report.yaml")
707
- with open(reportfile, 'w') as f:
861
+ with open(reportfile, "w") as f:
708
862
  yaml.dump(report, f)
709
863
 
710
- self.logger.info("Report written in %s"%reportfile)
864
+ self.logger.info("Report written in %s" % reportfile)
711
865
 
712
- #now we have to write out the results
866
+ # now we have to write out the results
713
867
  self.logger.info("Please cite the following publications:")
714
868
  self.logger.info("- 10.1103/PhysRevMaterials.5.103801")
869
+ self.publications.append("10.1103/PhysRevMaterials.5.103801")
715
870
 
716
871
  if self.calc.mode == "fe":
717
872
  if self.calc.reference_phase == "solid":
718
873
  self.logger.info("- 10.1016/j.commatsci.2015.10.050")
874
+ self.publications.append("10.1016/j.commatsci.2015.10.050")
719
875
  else:
720
876
  self.logger.info("- 10.1016/j.commatsci.2018.12.029")
721
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")
722
880
 
723
881
  def reversible_scaling(self, iteration=1):
724
882
  """
@@ -733,117 +891,213 @@ class Phase:
733
891
  -------
734
892
  None
735
893
  """
736
- self.logger.info(f'Starting temperature sweep cycle: {iteration}')
894
+ self.logger.info(f"Starting temperature sweep cycle: {iteration}")
737
895
  solid = False
738
- if self.calc.reference_phase == 'solid':
896
+ if self.calc.reference_phase == "solid":
739
897
  solid = True
740
898
 
741
899
  t0 = self.calc._temperature
742
900
  tf = self.calc._temperature_stop
743
901
  li = 1
744
- lf = t0/tf
902
+ lf = t0 / tf
745
903
  pi = self.calc._pressure
746
- pf = lf*pi
904
+ pf = lf * pi
747
905
 
748
- #create lammps object
749
- lmp = ph.create_object(self.cores, self.simfolder, self.calc.md.timestep,
750
- 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
+ )
751
914
 
752
915
  lmp.command("echo log")
753
- lmp.command("variable li equal %f"%li)
754
- lmp.command("variable lf equal %f"%lf)
916
+ lmp.command("variable li equal %f" % li)
917
+ lmp.command("variable lf equal %f" % lf)
755
918
 
756
- 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]}")
757
920
 
758
- #read in conf file
759
- #conf = os.path.join(self.simfolder, "conf.equilibration.dump")
921
+ # read in conf file
922
+ # conf = os.path.join(self.simfolder, "conf.equilibration.dump")
760
923
  conf = os.path.join(self.simfolder, "conf.equilibration.data")
761
924
  lmp = ph.read_data(lmp, conf)
762
925
 
763
- #set up potential
764
- 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]}")
765
928
  lmp = ph.set_mass(lmp, self.calc)
766
929
 
767
- #remap the box to get the correct pressure
930
+ # remap the box to get the correct pressure
768
931
  lmp = ph.remap_box(lmp, self.lx, self.ly, self.lz)
769
932
 
770
- #set thermostat and run equilibrium
933
+ # set thermostat and run equilibrium
771
934
  if self.calc.npt:
772
- lmp.command("fix f1 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
773
- 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
+ )
774
947
  else:
775
- lmp.command("fix f1 all nvt temp %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1]))
776
-
777
- self.logger.info(f'Starting equilibration: {iteration}')
778
- lmp.command("run %d"%self.calc.n_equilibration_steps)
779
- 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}")
780
956
 
781
957
  lmp.command("unfix f1")
782
958
 
783
- #now fix com
959
+ # now fix com
784
960
  lmp.command("variable xcm equal xcm(all,x)")
785
961
  lmp.command("variable ycm equal xcm(all,y)")
786
962
  lmp.command("variable zcm equal xcm(all,z)")
787
963
 
788
964
  if self.calc.npt:
789
- 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],
790
- 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
+ )
791
977
  else:
792
- 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
+ )
793
982
 
794
- #compute com and modify fix
983
+ # compute com and modify fix
795
984
  lmp.command("compute tcm all temp/com")
796
985
  lmp.command("fix_modify f1 temp tcm")
797
986
 
798
987
  lmp.command("variable step equal step")
799
- lmp.command("variable dU equal c_thermo_pe/atoms")
988
+ lmp.command("variable dU equal c_thermo_pe/atoms")
800
989
  lmp.command("thermo_style custom step pe c_tcm press vol")
801
990
  lmp.command("thermo 10000")
802
991
 
803
- #create velocity and equilibriate
804
- 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}")
805
1001
 
806
- self.logger.info(f'Starting equilibration with constrained com: {iteration}')
807
- lmp.command("run %d"%self.calc.n_equilibration_steps)
808
- self.logger.info(f'Finished equilibration with constrained com: {iteration}')
809
-
810
1002
  lmp.command("variable flambda equal ramp(${li},${lf})")
811
1003
  lmp.command("variable blambda equal ramp(${lf},${li})")
812
1004
  lmp.command("variable fscale equal v_flambda-1.0")
813
1005
  lmp.command("variable bscale equal v_blambda-1.0")
814
1006
  lmp.command("variable one equal 1.0")
815
-
816
- #set up potential
817
- 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]
818
1016
  pcraw = pc.split()
819
- pcnew1 = " ".join([*pcraw[:2], *[self.calc._pair_style_names[0],], "1", *pcraw[2:]])
820
- 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
+ )
821
1075
 
822
- 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]))
823
- lmp.command("pair_coeff %s"%pcnew1)
824
- 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
+ )
825
1081
 
826
- 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}")
827
1085
 
828
- if self.calc.n_print_steps > 0:
829
- 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,
830
- iteration))
831
-
832
- self.logger.info(f'Started forward sweep: {iteration}')
833
- lmp.command("run %d"%self.calc._n_sweep_steps)
834
- self.logger.info(f'Finished forward sweep: {iteration}')
835
-
836
- #unfix
1086
+ if self.calc.monte_carlo.n_swaps > 0:
1087
+ lmp.command("unfix swap")
1088
+ lmp.command("unfix swap2")
1089
+
1090
+ # unfix
837
1091
  lmp.command("unfix f3")
838
- #lmp.command("unfix f1")
1092
+ # lmp.command("unfix f1")
839
1093
 
840
1094
  if self.calc.n_print_steps > 0:
841
1095
  lmp.command("undump d1")
842
1096
 
843
- #switch potential
844
- lmp.command("run %d"%self.calc.n_equilibration_steps)
1097
+ # switch potential
1098
+ lmp.command("run %d" % self.calc.n_equilibration_steps)
845
1099
 
846
- #check melting or freezing
1100
+ # check melting or freezing
847
1101
  if not self.calc.script_mode:
848
1102
  self.dump_current_snapshot(lmp, "traj.temp.dat")
849
1103
  if solid:
@@ -853,41 +1107,87 @@ class Phase:
853
1107
 
854
1108
  lmp = ph.set_potential(lmp, self.calc)
855
1109
 
856
- #reverse scaling
1110
+ # reverse scaling
857
1111
  lmp.command("variable flambda equal ramp(${li},${lf})")
858
1112
  lmp.command("variable blambda equal ramp(${lf},${li})")
859
1113
  lmp.command("variable fscale equal v_flambda-1.0")
860
1114
  lmp.command("variable bscale equal v_blambda-1.0")
861
1115
  lmp.command("variable one equal 1.0")
862
-
863
- 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]))
864
- lmp.command("pair_coeff %s"%pcnew1)
865
- lmp.command("pair_coeff %s"%pcnew2)
866
-
867
- #apply fix and perform switching
868
- 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
+ )
869
1138
 
870
1139
  if self.calc.n_print_steps > 0:
871
- 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,
872
- 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")
873
1175
 
874
- self.logger.info(f'Started backward sweep: {iteration}')
875
- lmp.command("run %d"%self.calc._n_sweep_steps)
876
- self.logger.info(f'Finished backward sweep: {iteration}')
877
-
878
1176
  lmp.command("unfix f3")
879
1177
 
880
1178
  if self.calc.n_print_steps > 0:
881
1179
  lmp.command("undump d1")
882
-
883
- #close the object
1180
+
1181
+ # close the object
884
1182
  lmp.close()
885
1183
 
886
1184
  self.logger.info("Please cite the following publications:")
887
1185
  if self.calc.mode == "mts":
888
1186
  self.logger.info("- 10.1063/1.1420486")
1187
+ self.publications.append("10.1063/1.1420486")
889
1188
  else:
890
1189
  self.logger.info("- 10.1103/PhysRevLett.83.3973")
1190
+ self.publications.append("10.1103/PhysRevLett.83.3973")
891
1191
 
892
1192
  def integrate_reversible_scaling(self, scale_energy=True, return_values=False):
893
1193
  """
@@ -896,7 +1196,7 @@ class Phase:
896
1196
  Parameters
897
1197
  ----------
898
1198
  scale_energy : bool, optional
899
- If True, scale the energy during reversible scaling.
1199
+ If True, scale the energy during reversible scaling.
900
1200
 
901
1201
  return_values : bool, optional
902
1202
  If True, return integrated values
@@ -906,8 +1206,16 @@ class Phase:
906
1206
  res : list of lists of shape 1x3
907
1207
  Only returned if `return_values` is True.
908
1208
  """
909
- res = integrate_rs(self.simfolder, self.fe, self.calc._temperature, self.natoms, p=self.calc._pressure,
910
- 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
+ )
911
1219
 
912
1220
  if return_values:
913
1221
  return res
@@ -915,80 +1223,118 @@ class Phase:
915
1223
  def temperature_scaling(self, iteration=1):
916
1224
  """
917
1225
  Perform temperature scaling calculation in NPT
918
-
1226
+
919
1227
  Parameters
920
1228
  ----------
921
1229
  iteration : int, optional
922
1230
  iteration of the calculation. Default 1
923
-
1231
+
924
1232
  Returns
925
1233
  -------
926
1234
  None
927
1235
  """
928
1236
  solid = False
929
- if self.calc.reference_phase == 'solid':
1237
+ if self.calc.reference_phase == "solid":
930
1238
  solid = True
931
1239
 
932
1240
  t0 = self.calc._temperature
933
1241
  tf = self.calc._temperature_stop
934
1242
  li = 1
935
- lf = t0/tf
1243
+ lf = t0 / tf
936
1244
  p0 = self.calc._pressure
937
- pf = lf*p0
1245
+ pf = lf * p0
938
1246
 
939
- #create lammps object
940
- lmp = ph.create_object(self.cores, self.simfolder, self.calc.md.timestep,
941
- 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
+ )
942
1255
 
943
1256
  lmp.command("echo log")
944
- lmp.command("variable li equal %f"%li)
945
- lmp.command("variable lf equal %f"%lf)
1257
+ lmp.command("variable li equal %f" % li)
1258
+ lmp.command("variable lf equal %f" % lf)
946
1259
 
947
- 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]}")
948
1261
 
949
- #read in conf
950
- #conf = os.path.join(self.simfolder, "conf.equilibration.dump")
1262
+ # read in conf
1263
+ # conf = os.path.join(self.simfolder, "conf.equilibration.dump")
951
1264
  conf = os.path.join(self.simfolder, "conf.equilibration.data")
952
1265
  lmp = ph.read_data(lmp, conf)
953
1266
 
954
- #set up potential
955
- 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]}")
956
1269
  lmp = ph.set_mass(lmp, self.calc)
957
1270
 
958
- #remap the box to get the correct pressure
1271
+ # remap the box to get the correct pressure
959
1272
  lmp = ph.remap_box(lmp, self.lx, self.ly, self.lz)
960
1273
 
961
-
962
- #equilibrate first
963
- lmp.command("fix 1 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
964
- self.iso, p0, p0, self.calc.md.barostat_damping[1]))
965
- 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)
966
1288
  lmp.command("unfix 1")
967
1289
 
968
-
969
- #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
970
1291
  lmp.command("variable step equal step")
971
1292
  lmp.command("variable dU equal pe/atoms")
972
1293
  lmp.command("variable lambda equal ramp(${li},${lf})")
973
1294
 
974
- lmp.command("fix f2 all npt temp %f %f %f %s %f %f %f"%(t0, tf, self.calc.md.thermostat_damping[1],
975
- self.iso, p0, pf, self.calc.md.barostat_damping[1]))
976
- lmp.command("fix f3 all print 1 \"${dU} $(press) $(vol) ${lambda}\" screen no file ts.forward_%d.dat"%iteration)
977
- 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)
978
1312
 
979
1313
  lmp.command("unfix f2")
980
1314
  lmp.command("unfix f3")
981
1315
 
982
- lmp.command("fix 1 all npt temp %f %f %f %s %f %f %f"%(tf, tf, self.calc.md.thermostat_damping[1],
983
- self.iso, pf, pf, self.calc.md.barostat_damping[1]))
984
- 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)
985
1329
  lmp.command("unfix 1")
986
1330
 
987
- #check melting or freezing
988
- 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
+ )
989
1335
  lmp.command("run 0")
990
1336
  lmp.command("undump 2")
991
-
1337
+
992
1338
  if not self.calc.script_mode:
993
1339
  self.dump_current_snapshot(lmp, "traj.temp.dat")
994
1340
  if solid:
@@ -996,26 +1342,38 @@ class Phase:
996
1342
  else:
997
1343
  self.check_if_solidfied(lmp, "traj.temp.dat")
998
1344
 
999
- #start reverse loop
1345
+ # start reverse loop
1000
1346
  lmp.command("variable lambda equal ramp(${lf},${li})")
1001
1347
 
1002
- lmp.command("fix f2 all npt temp %f %f %f %s %f %f %f"%(tf, t0, self.calc.md.thermostat_damping[1],
1003
- self.iso, pf, p0, self.calc.md.barostat_damping[1]))
1004
- lmp.command("fix f3 all print 1 \"${dU} $(press) $(vol) ${lambda}\" screen no file ts.backward_%d.dat"%iteration)
1005
- 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)
1006
1365
 
1007
1366
  lmp.close()
1008
1367
 
1009
-
1010
1368
  def pressure_scaling(self, iteration=1):
1011
1369
  """
1012
1370
  Perform pressure scaling calculation in NPT
1013
-
1371
+
1014
1372
  Parameters
1015
1373
  ----------
1016
1374
  iteration : int, optional
1017
1375
  iteration of the calculation. Default 1
1018
-
1376
+
1019
1377
  Returns
1020
1378
  -------
1021
1379
  None
@@ -1026,91 +1384,162 @@ class Phase:
1026
1384
  p0 = self.calc._pressure
1027
1385
  pf = self.calc._pressure_stop
1028
1386
 
1029
- #create lammps object
1030
- lmp = ph.create_object(self.cores, self.simfolder, self.calc.md.timestep,
1031
- 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
+ )
1032
1395
 
1033
1396
  lmp.command("echo log")
1034
- lmp.command("variable li equal %f"%li)
1035
- lmp.command("variable lf equal %f"%lf)
1036
- lmp.command("variable p0 equal %f"%p0)
1037
- 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)
1038
1401
 
1039
- 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]}")
1040
1403
 
1041
- #read in conf
1042
- #conf = os.path.join(self.simfolder, "conf.dump")
1404
+ # read in conf
1405
+ # conf = os.path.join(self.simfolder, "conf.dump")
1043
1406
  conf = os.path.join(self.simfolder, "conf.equilibration.data")
1044
1407
  lmp = ph.read_data(lmp, conf)
1045
1408
 
1046
- #set up potential
1047
- 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]}")
1048
1411
  lmp = ph.set_mass(lmp, self.calc)
1049
1412
 
1050
- #remap the box to get the correct pressure
1413
+ # remap the box to get the correct pressure
1051
1414
  lmp = ph.remap_box(lmp, self.lx, self.ly, self.lz)
1052
1415
 
1053
- #equilibrate first
1054
- lmp.command("fix 1 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
1055
- self.iso, p0, p0, self.calc.md.barostat_damping[1]))
1056
- 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)
1057
1430
  lmp.command("unfix 1")
1058
1431
 
1059
-
1060
- #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
1061
1433
  lmp.command("variable step equal step")
1062
1434
  lmp.command("variable dU equal pe/atoms")
1063
1435
  lmp.command("variable lambda equal ramp(${li},${lf})")
1064
1436
  lmp.command("variable pp equal ramp(${p0},${pf})")
1065
1437
 
1066
- lmp.command("fix f2 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
1067
- self.iso, p0, pf, self.calc.md.barostat_damping[1]))
1068
- lmp.command("fix f3 all print 1 \"${dU} ${pp} $(vol) ${lambda}\" screen no file ps.forward_%d.dat"%iteration)
1069
- 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)
1070
1455
 
1071
1456
  lmp.command("unfix f2")
1072
1457
  lmp.command("unfix f3")
1073
1458
 
1074
-
1075
- lmp.command("fix 1 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
1076
- self.iso, pf, pf, self.calc.md.barostat_damping[1]))
1077
- 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)
1078
1472
  lmp.command("unfix 1")
1079
1473
 
1080
- #start reverse loop
1474
+ # start reverse loop
1081
1475
  lmp.command("variable lambda equal ramp(${lf},${li})")
1082
1476
  lmp.command("variable pp equal ramp(${pf},${p0})")
1083
1477
 
1084
- lmp.command("fix f2 all npt temp %f %f %f %s %f %f %f"%(t0, t0, self.calc.md.thermostat_damping[1],
1085
- self.iso, pf, p0, self.calc.md.barostat_damping[1]))
1086
- lmp.command("fix f3 all print 1 \"${dU} ${pp} $(vol) ${lambda}\" screen no file ps.backward_%d.dat"%iteration)
1087
- 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)
1088
1495
 
1089
1496
  lmp.close()
1090
1497
 
1091
1498
  self.logger.info("Please cite the following publications:")
1092
1499
  self.logger.info("- 10.1016/j.commatsci.2022.111275")
1093
-
1094
-
1500
+ self.publications.append("10.1016/j.commatsci.2022.111275")
1501
+
1095
1502
  def integrate_pressure_scaling(self, return_values=False):
1096
1503
  """
1097
1504
  Perform integration after reversible scaling
1098
-
1505
+
1099
1506
  Parameters
1100
1507
  ----------
1101
1508
  scale_energy : bool, optional
1102
- If True, scale the energy during reversible scaling.
1509
+ If True, scale the energy during reversible scaling.
1103
1510
  return_values : bool, optional
1104
1511
  If True, return integrated values
1105
-
1512
+
1106
1513
  Returns
1107
1514
  -------
1108
1515
  res : list of lists of shape 1x3
1109
1516
  Only returned if `return_values` is True.
1110
1517
  """
1111
- res = integrate_ps(self.simfolder, self.fe, self.natoms,
1112
- self.calc._pressure, self.calc._pressure_stop,
1113
- 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
+ )
1114
1527
 
1115
1528
  if return_values:
1116
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)