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/__init__.py +1 -1
- calphy/alchemy.py +66 -8
- calphy/clitools.py +6 -0
- calphy/composition_transformation.py +63 -9
- calphy/helpers.py +6 -2
- calphy/input.py +478 -245
- calphy/kernel.py +3 -1
- calphy/liquid.py +199 -118
- calphy/phase.py +815 -378
- calphy/phase_diagram.py +500 -26
- calphy/postprocessing.py +274 -5
- calphy/routines.py +13 -2
- calphy/scheduler.py +2 -0
- calphy/solid.py +35 -0
- {calphy-1.3.11.dist-info → calphy-1.4.2.dist-info}/METADATA +14 -2
- calphy-1.4.2.dist-info/RECORD +25 -0
- {calphy-1.3.11.dist-info → calphy-1.4.2.dist-info}/WHEEL +1 -1
- {calphy-1.3.11.dist-info → calphy-1.4.2.dist-info}/entry_points.txt +1 -0
- calphy-1.3.11.dist-info/RECORD +0 -25
- {calphy-1.3.11.dist-info → calphy-1.4.2.dist-info/licenses}/LICENSE +0 -0
- {calphy-1.3.11.dist-info → calphy-1.4.2.dist-info}/top_level.txt +0 -0
calphy/__init__.py
CHANGED
calphy/alchemy.py
CHANGED
|
@@ -19,6 +19,10 @@ DOI: 10.1103/PhysRevMaterials.5.103801
|
|
|
19
19
|
|
|
20
20
|
For more information contact:
|
|
21
21
|
sarath.menon@ruhr-uni-bochum.de/yury.lysogorskiy@icams.rub.de
|
|
22
|
+
|
|
23
|
+
Notes
|
|
24
|
+
-----
|
|
25
|
+
- swapping is strictly only performed between types 1 and 2 at the moment; this needs to be refined further
|
|
22
26
|
"""
|
|
23
27
|
|
|
24
28
|
import numpy as np
|
|
@@ -159,6 +163,9 @@ class Alchemy(cph.Phase):
|
|
|
159
163
|
lmp.command(f'pair_coeff {self.calc.pair_coeff[0]}')
|
|
160
164
|
lmp = ph.set_mass(lmp, self.calc)
|
|
161
165
|
|
|
166
|
+
#NEW ADDED
|
|
167
|
+
lmp.command("group g1 type 1")
|
|
168
|
+
lmp.command("group g2 type 2")
|
|
162
169
|
#lmp = ph.set_double_hybrid_potential(lmp, self.options, self.calc._pressureair_style, self.calc._pressureair_coeff)
|
|
163
170
|
|
|
164
171
|
#remap the box to get the correct pressure
|
|
@@ -173,9 +180,12 @@ class Alchemy(cph.Phase):
|
|
|
173
180
|
lmp.command("fix f1 all nvt temp %f %f %f"%(self.calc._temperature, self.calc._temperature,
|
|
174
181
|
self.calc.md.thermostat_damping[1]))
|
|
175
182
|
|
|
183
|
+
|
|
176
184
|
lmp.command("thermo_style custom step pe")
|
|
177
185
|
lmp.command("thermo 1000")
|
|
178
186
|
lmp.command("run %d"%self.calc.n_equilibration_steps)
|
|
187
|
+
|
|
188
|
+
|
|
179
189
|
#equilibration run is over
|
|
180
190
|
|
|
181
191
|
#---------------------------------------------------------------
|
|
@@ -226,21 +236,41 @@ class Alchemy(cph.Phase):
|
|
|
226
236
|
lmp.command("variable dU1 equal c_c1/atoms") # Driving-force obtained from NEHI procedure.
|
|
227
237
|
lmp.command("variable dU2 equal c_c2/atoms")
|
|
228
238
|
|
|
239
|
+
#add swaps if n_swap is > 0
|
|
240
|
+
if self.calc.monte_carlo.n_swaps > 0:
|
|
241
|
+
self.logger.info(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}')
|
|
242
|
+
lmp.command("fix swap all atom/swap %d %d %d %f ke no types %d %d"%(self.calc.monte_carlo.n_steps,
|
|
243
|
+
self.calc.monte_carlo.n_swaps,
|
|
244
|
+
np.random.randint(1, 10000),
|
|
245
|
+
self.calc._temperature,
|
|
246
|
+
self.calc.monte_carlo.swap_types[0],
|
|
247
|
+
self.calc.monte_carlo.swap_types[1]))
|
|
248
|
+
lmp.command("variable a equal f_swap[1]")
|
|
249
|
+
lmp.command("variable b equal f_swap[2]")
|
|
250
|
+
lmp.command("fix swap2 all print 1 \"${a} ${b} ${flambda}\" screen no file swap.forward_%d.dat"%iteration)
|
|
251
|
+
|
|
229
252
|
# Thermo output.
|
|
230
|
-
|
|
253
|
+
if self.calc.monte_carlo.n_swaps > 0:
|
|
254
|
+
lmp.command("thermo_style custom step v_dU1 v_dU2 v_a v_b")
|
|
255
|
+
else:
|
|
256
|
+
lmp.command("thermo_style custom step v_dU1 v_dU2")
|
|
231
257
|
lmp.command("thermo 1000")
|
|
232
258
|
|
|
233
|
-
|
|
259
|
+
|
|
234
260
|
#save the necessary items to a file: first step
|
|
235
261
|
lmp.command("fix f2 all print 1 \"${dU1} ${dU2} ${flambda}\" screen no file forward_%d.dat"%iteration)
|
|
236
|
-
lmp.command("run %d"%self.calc._n_switching_steps)
|
|
237
|
-
|
|
262
|
+
lmp.command("run %d"%self.calc._n_switching_steps)
|
|
238
263
|
|
|
239
264
|
#now equilibrate at the second potential
|
|
240
265
|
lmp.command("unfix f2")
|
|
241
266
|
lmp.command("uncompute c1")
|
|
242
267
|
lmp.command("uncompute c2")
|
|
243
268
|
|
|
269
|
+
#NEW SWAP
|
|
270
|
+
if self.calc.monte_carlo.n_swaps > 0:
|
|
271
|
+
lmp.command("unfix swap")
|
|
272
|
+
lmp.command("unfix swap2")
|
|
273
|
+
|
|
244
274
|
|
|
245
275
|
lmp.command("pair_style %s"%self.calc._pair_style_with_options[1])
|
|
246
276
|
lmp.command("pair_coeff %s"%self.calc.pair_coeff[1])
|
|
@@ -248,7 +278,7 @@ class Alchemy(cph.Phase):
|
|
|
248
278
|
# Thermo output.
|
|
249
279
|
lmp.command("thermo_style custom step pe")
|
|
250
280
|
lmp.command("thermo 1000")
|
|
251
|
-
|
|
281
|
+
|
|
252
282
|
#run eqbrm run
|
|
253
283
|
lmp.command("run %d"%self.calc.n_equilibration_steps)
|
|
254
284
|
|
|
@@ -278,11 +308,39 @@ class Alchemy(cph.Phase):
|
|
|
278
308
|
lmp.command("variable dU1 equal c_c1/atoms") # Driving-force obtained from NEHI procedure.
|
|
279
309
|
lmp.command("variable dU2 equal c_c2/atoms")
|
|
280
310
|
|
|
311
|
+
#add swaps if n_swap is > 0
|
|
312
|
+
if self.calc.monte_carlo.n_swaps > 0:
|
|
313
|
+
if self.calc.monte_carlo.reverse_swap:
|
|
314
|
+
self.logger.info(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}')
|
|
315
|
+
lmp.command("fix swap all atom/swap %d %d %d %f ke no types %d %d"%(self.calc.monte_carlo.n_steps,
|
|
316
|
+
self.calc.monte_carlo.n_swaps,
|
|
317
|
+
np.random.randint(1, 10000),
|
|
318
|
+
self.calc._temperature,
|
|
319
|
+
self.calc.monte_carlo.swap_types[1],
|
|
320
|
+
self.calc.monte_carlo.swap_types[0]))
|
|
321
|
+
else:
|
|
322
|
+
self.logger.info(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}')
|
|
323
|
+
self.logger.info('note that swaps are not reversed')
|
|
324
|
+
lmp.command("fix swap all atom/swap %d %d %d %f ke no types %d %d"%(self.calc.monte_carlo.n_steps,
|
|
325
|
+
self.calc.monte_carlo.n_swaps,
|
|
326
|
+
np.random.randint(1, 10000),
|
|
327
|
+
self.calc._temperature,
|
|
328
|
+
self.calc.monte_carlo.swap_types[0],
|
|
329
|
+
self.calc.monte_carlo.swap_types[1]))
|
|
330
|
+
|
|
331
|
+
lmp.command("variable a equal f_swap[1]")
|
|
332
|
+
lmp.command("variable b equal f_swap[2]")
|
|
333
|
+
lmp.command("fix swap2 all print 1 \"${a} ${b} ${blambda}\" screen no file swap.backward_%d.dat"%iteration)
|
|
334
|
+
|
|
281
335
|
# Thermo output.
|
|
282
|
-
|
|
336
|
+
if self.calc.monte_carlo.n_swaps > 0:
|
|
337
|
+
lmp.command("thermo_style custom step v_dU1 v_dU2 v_a v_b")
|
|
338
|
+
else:
|
|
339
|
+
lmp.command("thermo_style custom step v_dU1 v_dU2")
|
|
283
340
|
lmp.command("thermo 1000")
|
|
284
341
|
|
|
285
342
|
|
|
343
|
+
|
|
286
344
|
#save the necessary items to a file: first step
|
|
287
345
|
lmp.command("fix f2 all print 1 \"${dU1} ${dU2} ${flambda}\" screen no file backward_%d.dat"%iteration)
|
|
288
346
|
lmp.command("run %d"%self.calc._n_switching_steps)
|
|
@@ -293,6 +351,8 @@ class Alchemy(cph.Phase):
|
|
|
293
351
|
lmp.command("uncompute c1")
|
|
294
352
|
lmp.command("uncompute c2")
|
|
295
353
|
|
|
354
|
+
if self.calc.monte_carlo.n_swaps > 0:
|
|
355
|
+
lmp.command("unfix swap")
|
|
296
356
|
lmp.close()
|
|
297
357
|
|
|
298
358
|
|
|
@@ -329,8 +389,6 @@ class Alchemy(cph.Phase):
|
|
|
329
389
|
return flambda_arr, w_arr, q_arr, qerr_arr
|
|
330
390
|
|
|
331
391
|
|
|
332
|
-
|
|
333
|
-
|
|
334
392
|
def mass_integration(self, flambda, ref_mass, target_masses, target_counts):
|
|
335
393
|
mcorarr, mcorsum = integrate_mass(flambda, ref_mass, target_masses, target_counts,
|
|
336
394
|
self.calc._temperature, self.natoms)
|
calphy/clitools.py
CHANGED
|
@@ -11,6 +11,7 @@ from calphy.input import read_inputfile, load_job, save_job, _convert_legacy_inp
|
|
|
11
11
|
from calphy.liquid import Liquid
|
|
12
12
|
from calphy.solid import Solid
|
|
13
13
|
from calphy.alchemy import Alchemy
|
|
14
|
+
from calphy.phase_diagram import prepare_inputs_for_phase_diagram
|
|
14
15
|
|
|
15
16
|
def _generate_job(calc, simfolder):
|
|
16
17
|
if calc.mode == "alchemy" or calc.mode == "composition_scaling":
|
|
@@ -120,3 +121,8 @@ def convert_legacy_inputfile():
|
|
|
120
121
|
yaml.safe_dump(data, fout)
|
|
121
122
|
|
|
122
123
|
|
|
124
|
+
def phase_diagram():
|
|
125
|
+
arg = ap.ArgumentParser()
|
|
126
|
+
arg.add_argument("-i", "--input", required=True, type=str,
|
|
127
|
+
help="name of the input file")
|
|
128
|
+
prepare_inputs_for_phase_diagram(args['input'])
|
|
@@ -30,6 +30,7 @@ from mendeleev import element
|
|
|
30
30
|
from ase.io import read, write
|
|
31
31
|
from ase.atoms import Atoms
|
|
32
32
|
from pyscal3.core import element_dict
|
|
33
|
+
from calphy.integrators import kb
|
|
33
34
|
|
|
34
35
|
class CompositionTransformation:
|
|
35
36
|
"""
|
|
@@ -124,6 +125,7 @@ class CompositionTransformation:
|
|
|
124
125
|
self.atom_species = None
|
|
125
126
|
self.mappings = None
|
|
126
127
|
self.unique_mappings = None
|
|
128
|
+
self.mappingdict = None
|
|
127
129
|
self.prepare_mappings()
|
|
128
130
|
|
|
129
131
|
def dict_to_string(self, inputdict):
|
|
@@ -132,8 +134,32 @@ class CompositionTransformation:
|
|
|
132
134
|
strlst.append(str(key))
|
|
133
135
|
strlst.append(str(val))
|
|
134
136
|
return "".join(strlst)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def entropy_contribution(self):
|
|
140
|
+
"""
|
|
141
|
+
Find the entropy entribution of the transformation. To get
|
|
142
|
+
free energies, multiply by -T.
|
|
143
|
+
"""
|
|
144
|
+
def _log(val):
|
|
145
|
+
if val == 0:
|
|
146
|
+
return 0
|
|
147
|
+
else:
|
|
148
|
+
return np.log(val)
|
|
149
|
+
ents = []
|
|
150
|
+
for key, val in self.output_chemical_composition.items():
|
|
151
|
+
if key in self.input_chemical_composition.keys():
|
|
152
|
+
t1 = self.input_chemical_composition[key]/self.natoms
|
|
153
|
+
t2 = self.output_chemical_composition[key]/self.natoms
|
|
154
|
+
cont = t2*_log(t2) - t1*_log(t1)
|
|
155
|
+
else:
|
|
156
|
+
t1 = 0
|
|
157
|
+
t2 = self.output_chemical_composition[key]/self.natoms
|
|
158
|
+
cont = t2*_log(t2) - 0
|
|
159
|
+
ents.append(cont)
|
|
160
|
+
entropy_term = kb*np.sum(ents)
|
|
161
|
+
return entropy_term
|
|
162
|
+
|
|
137
163
|
def convert_to_pyscal(self):
|
|
138
164
|
"""
|
|
139
165
|
Convert a given system to pyscal and give a dict of type mappings
|
|
@@ -159,7 +185,6 @@ class CompositionTransformation:
|
|
|
159
185
|
self.maxtype = self.actual_species + 1 #+ self.new_species
|
|
160
186
|
#print(self.typedict)
|
|
161
187
|
|
|
162
|
-
|
|
163
188
|
def get_composition_transformation(self):
|
|
164
189
|
"""
|
|
165
190
|
From the two given composition transformation, find the transformation dict
|
|
@@ -192,9 +217,10 @@ class CompositionTransformation:
|
|
|
192
217
|
def mark_atoms(self):
|
|
193
218
|
for i in range(self.natoms):
|
|
194
219
|
self.atom_mark.append(False)
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
220
|
+
|
|
221
|
+
self.atom_type = self.pyscal_structure.atoms.types
|
|
222
|
+
self.mappings = [f"{x}-{x}" for x in self.atom_type]
|
|
223
|
+
|
|
198
224
|
def update_mark_atoms(self):
|
|
199
225
|
self.marked_atoms = []
|
|
200
226
|
for key, val in self.to_remove.items():
|
|
@@ -281,7 +307,7 @@ class CompositionTransformation:
|
|
|
281
307
|
self.update_typedicts()
|
|
282
308
|
self.compute_possible_mappings()
|
|
283
309
|
self.update_mappings()
|
|
284
|
-
|
|
310
|
+
|
|
285
311
|
def prepare_pair_lists(self):
|
|
286
312
|
self.pair_list_old = []
|
|
287
313
|
self.pair_list_new = []
|
|
@@ -300,8 +326,12 @@ class CompositionTransformation:
|
|
|
300
326
|
def update_types(self):
|
|
301
327
|
for x in range(len(self.atom_type)):
|
|
302
328
|
self.atom_type[x] = self.mappingdict[self.mappings[x]]
|
|
303
|
-
|
|
304
|
-
|
|
329
|
+
|
|
330
|
+
#smartify these loops
|
|
331
|
+
#npyscal = len(self.pyscal_structure.atoms.types)
|
|
332
|
+
self.pyscal_structure.atoms.types = self.atom_type
|
|
333
|
+
#for count in range(npyscal)):
|
|
334
|
+
# self.pyscal_structure.atoms.types[count] = self.atom_type[count]
|
|
305
335
|
|
|
306
336
|
def iselement(self, symbol):
|
|
307
337
|
try:
|
|
@@ -331,6 +361,30 @@ class CompositionTransformation:
|
|
|
331
361
|
pc_old = " ".join([*pc_before, *self.pair_list_old, *pc_after])
|
|
332
362
|
pc_new = " ".join([*pc_before, *self.pair_list_new, *pc_after])
|
|
333
363
|
return pc_old, pc_new
|
|
364
|
+
|
|
365
|
+
def get_swap_types(self):
|
|
366
|
+
"""
|
|
367
|
+
Get swapping types
|
|
368
|
+
"""
|
|
369
|
+
swap_list = []
|
|
370
|
+
for mapping in self.unique_mappings:
|
|
371
|
+
map_split = mapping.split("-")
|
|
372
|
+
#conserved atom
|
|
373
|
+
if (map_split[0]==map_split[1]):
|
|
374
|
+
pass
|
|
375
|
+
else:
|
|
376
|
+
first_type = map_split[0]
|
|
377
|
+
second_type = map_split[1]
|
|
378
|
+
first_map = f'{first_type}-{first_type}'
|
|
379
|
+
second_map = mapping
|
|
380
|
+
|
|
381
|
+
#get the numbers from dict
|
|
382
|
+
first_swap_type = self.mappingdict[first_map]
|
|
383
|
+
second_swap_type = self.mappingdict[second_map]
|
|
384
|
+
|
|
385
|
+
swap_list.append([first_swap_type, second_swap_type])
|
|
386
|
+
return swap_list[0]
|
|
387
|
+
|
|
334
388
|
|
|
335
389
|
def write_structure(self, outfilename):
|
|
336
390
|
#create some species dict
|
calphy/helpers.py
CHANGED
|
@@ -121,8 +121,12 @@ def create_structure(lmp, calc):
|
|
|
121
121
|
|
|
122
122
|
|
|
123
123
|
def set_mass(lmp, options):
|
|
124
|
-
|
|
125
|
-
lmp.command(f'mass
|
|
124
|
+
if options.mode == 'composition_scaling':
|
|
125
|
+
lmp.command(f'mass * {options.mass[-1]}')
|
|
126
|
+
|
|
127
|
+
else:
|
|
128
|
+
for i in range(options.n_elements):
|
|
129
|
+
lmp.command(f'mass {i+1} {options.mass[i]}')
|
|
126
130
|
return lmp
|
|
127
131
|
|
|
128
132
|
|