calphy 1.3.9__py3-none-any.whl → 1.3.11__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 CHANGED
@@ -4,7 +4,7 @@ from calphy.solid import Solid
4
4
  from calphy.alchemy import Alchemy
5
5
  from calphy.routines import MeltingTemp
6
6
 
7
- __version__ = "1.3.9"
7
+ __version__ = "1.3.11"
8
8
 
9
9
  def addtest(a,b):
10
10
  return a+b
calphy/input.py CHANGED
@@ -40,19 +40,7 @@ from pyscal3.core import structure_dict, element_dict, _make_crystal
40
40
  from ase.io import read, write
41
41
  import shutil
42
42
 
43
- __version__ = "1.3.9"
44
-
45
- def read_report(folder):
46
- """
47
- Read the finished calculation report
48
- """
49
- repfile = os.path.join(folder, "report.yaml")
50
- if not os.path.exists(repfile):
51
- raise FileNotFoundError(f"file {repfile} not found")
52
-
53
- with open(repfile, 'r') as fin:
54
- data = yaml.safe_load(fin)
55
- return data
43
+ __version__ = "1.3.11"
56
44
 
57
45
  def _check_equal(val):
58
46
  if not (val[0]==val[1]==val[2]):
calphy/integrators.py CHANGED
@@ -28,19 +28,23 @@ import math
28
28
  import os
29
29
  import warnings
30
30
  from calphy.splines import splines, sum_spline1, sum_spline25, sum_spline50, sum_spline75, sum_spline100
31
- from scipy.integrate import cumtrapz
31
+ try:
32
+ from scipy.integrate import cumtrapz
33
+ except ImportError:
34
+ from scipy.integrate import cumulative_trapezoid as cumtrapz
32
35
  from tqdm import tqdm
33
36
  import pyscal3.core as pc
34
37
  from ase.io import read
35
38
 
36
39
  #Constants
37
40
  h = const.physical_constants["Planck constant in eV/Hz"][0]
41
+ hJ = const.physical_constants["Planck constant"][0]
38
42
  hbar = h/(2*np.pi)
39
43
  kb = const.physical_constants["Boltzmann constant in eV/K"][0]
40
44
  kbJ = const.physical_constants["Boltzmann constant"][0]
41
45
  Na = const.physical_constants["Avogadro constant"][0]
42
46
  eV2J = const.eV
43
-
47
+ J2eV = 6.242E18
44
48
 
45
49
  #--------------------------------------------------------------------
46
50
  # TI PATH INTEGRATION ROUTINES
@@ -466,23 +470,18 @@ def get_einstein_crystal_fe(
466
470
  calc,
467
471
  vol,
468
472
  k,
469
- cm_correction=True):
473
+ cm_correction=True,
474
+ return_contributions=False):
470
475
  """
471
476
  Get the free energy of einstein crystal
472
477
 
473
478
  Parameters
474
479
  ----------
475
- temp : temperature, float
476
- units - K
477
-
478
- natoms : int
479
- no of atoms in the system
480
-
481
- mass : float
482
- units - g/mol
480
+ calc : Calculation object
481
+ contains all input parameters
483
482
 
484
- a : lattice constant, float
485
- units - Angstrom
483
+ vol : float
484
+ converged volume per atom
486
485
 
487
486
  k : spring constant, float
488
487
  units - eV/Angstrom^2
@@ -490,40 +489,77 @@ def get_einstein_crystal_fe(
490
489
  cm_correction : bool, optional, default - True
491
490
  add the centre of mass correction to free energy
492
491
 
492
+ return_contributions: bool, optional, default - True
493
+ If True, return individual contributions to the reference free energy.
494
+
493
495
  Returns
494
496
  -------
495
- fe : float
496
- free energy of Einstein crystal
497
+ F_tot : float
498
+ total free energy of reference crystal
499
+
500
+ F_e : float
501
+ Free energy of Einstein crystal without centre of mass correction. Only if `return_contributions` is True.
502
+
503
+ F_cm : float
504
+ centre of mass correction. Only if `return_contributions` is True.
505
+
506
+ Notes
507
+ -----
508
+ The equations for free energy of Einstein crystal and centre of mass correction are from https://doi.org/10.1063/5.0044833.
497
509
 
498
510
  """
499
- #convert mass first for single particle in kg
500
- mass = np.array([calc._element_dict[x]['mass'] for x in calc.element])
501
- mass = (mass/Na)*1E-3
502
- natoms = np.sum([calc._element_dict[x]['count'] for x in calc.element])
503
- concentration = np.array([calc._element_dict[x]['composition'] for x in calc.element])
511
+ #temperature
512
+ temp = calc._temperature
504
513
 
505
- #convert k from ev/A2 to J/m2
506
- k = np.array(k)*(eV2J/1E-20)
507
- omega = np.sqrt(k/mass)
514
+ #natoms
515
+ natoms = np.sum([calc._element_dict[x]['count'] for x in calc.element])
508
516
 
509
517
  #convert a to m3
510
518
  vol = vol*1E-30
511
519
 
512
- F_harm = 0
513
- F_cm = 0
520
+ #whats the beta
521
+ beta = (1/(kbJ*temp))
514
522
 
515
- for count, om in enumerate(omega):
516
- if concentration[count] > 0:
517
- F_harm += concentration[count]*np.log((hbar*om)/(kb*calc._temperature))
518
- if cm_correction:
519
- F_cm += np.log((natoms*concentration[count]/vol)*(2*np.pi*kbJ*calc._temperature/(natoms*concentration[count]*k[count]))**1.5)
520
- #F_cm = 0
521
- F_harm = 3*kb*calc._temperature*F_harm
522
- F_cm = (kb*calc._temperature/natoms)*F_cm
523
-
524
- F_harm = F_harm + F_cm
523
+ #create an array of mass
524
+ mass = []
525
+ for x in calc.element:
526
+ for count in range(calc._element_dict[x]['count']):
527
+ mass.append(calc._element_dict[x]['mass'])
528
+ mass = np.array(mass)
529
+
530
+ #convert mass to kg
531
+ mass = (mass/Na)*1E-3
525
532
 
526
- return F_harm
533
+ #create an array of k as well
534
+ karr = []
535
+ for c, x in enumerate(calc.element):
536
+ for count in range(calc._element_dict[x]['count']):
537
+ karr.append(k[c])
538
+ k = np.array(karr)
539
+ #convert k from ev/A2 to J/m2
540
+ k = k*(eV2J/1E-20)
541
+
542
+ #fe of Einstein crystal
543
+ Z_e = ((beta**2*k*hJ**2)/(4*np.pi**2*mass))**1.5
544
+ F_e = np.log(Z_e)
545
+ F_e = kb*temp*np.sum(F_e)/natoms #*J2eV #convert back to eV
546
+
547
+ #now get the cm correction
548
+ if cm_correction:
549
+ mass_sum = np.sum(mass)
550
+ mu = mass/mass_sum
551
+ mu2_over_k = mu**2/k
552
+ mu2_over_k_sum = np.sum(mu2_over_k)
553
+ prefactor = vol
554
+ F_cm = np.log(prefactor*(beta/(2*np.pi*mu2_over_k_sum))**1.5)
555
+ F_cm = kb*temp*F_cm/natoms #convert to eV
556
+ else:
557
+ F_cm = 0
558
+
559
+ F_tot = F_e - F_cm
560
+ if return_contributions:
561
+ return F_e, -F_cm
562
+ return F_tot
527
563
 
528
564
  #--------------------------------------------------------------------
529
565
  # REF. STATE ROUTINES: LIQUID
calphy/phase.py CHANGED
@@ -163,6 +163,8 @@ class Phase:
163
163
 
164
164
  self.ferr = 0
165
165
  self.fref = 0
166
+ self.feinstein = 0
167
+ self.fcm = 0
166
168
  self.fideal = 0
167
169
 
168
170
  self.w = 0
@@ -682,6 +684,8 @@ class Phase:
682
684
  report["results"]["free_energy"] = float(self.fe)
683
685
  report["results"]["error"] = float(self.ferr)
684
686
  report["results"]["reference_system"] = float(self.fref)
687
+ report["results"]["einstein_crystal"] = float(self.feinstein)
688
+ report["results"]["com_correction"] = float(self.fcm)
685
689
  report["results"]["work"] = float(self.w)
686
690
  report["results"]["pv"] = float(self.pv)
687
691
  report["results"]["unit"] = "eV/atom"
@@ -0,0 +1,148 @@
1
+ import os
2
+ import numpy as np
3
+ import yaml
4
+
5
+ def read_report(folder):
6
+ """
7
+ Read the finished calculation report
8
+
9
+ Parameters
10
+ ----------
11
+ folder: string
12
+ folder from which calculation is to be read
13
+
14
+ Returns
15
+ -------
16
+ data: dict
17
+ dictionary with results
18
+
19
+ """
20
+ repfile = os.path.join(folder, "report.yaml")
21
+ if not os.path.exists(repfile):
22
+ raise FileNotFoundError(f"file {repfile} not found")
23
+
24
+ with open(repfile, 'r') as fin:
25
+ data = yaml.safe_load(fin)
26
+ return data
27
+
28
+ def _extract_error(errfile):
29
+ error_code = None
30
+ if os.path.exists(errfile):
31
+ with open(errfile, 'r') as fin:
32
+ for line in fin:
33
+ if 'calphy.errors' in line:
34
+ break
35
+ try:
36
+ error_code = line.split(':')[0].split('.')[-1]
37
+ except:
38
+ pass
39
+ return error_code
40
+
41
+ def gather_results(mainfolder):
42
+ """
43
+ Gather results from all subfolders in a given folder into a Pandas DataFrame
44
+
45
+ Parameters
46
+ ----------
47
+ mainfolder: string
48
+ folder where calculations are stored
49
+
50
+ Returns
51
+ -------
52
+ df: pandas DataFrame
53
+ DataFrame with results
54
+ """
55
+ try:
56
+ import pandas as pd
57
+ except ImportError:
58
+ raise ImportError('Please install pandas to use this function')
59
+
60
+ datadict = {}
61
+ datadict['mode'] = []
62
+ datadict['status'] = []
63
+ datadict['temperature'] = []
64
+ datadict['pressure'] = []
65
+ datadict['free_energy'] = []
66
+ datadict['reference_phase'] = []
67
+ datadict['error_code'] = []
68
+ datadict['composition'] = []
69
+ datadict['calculation'] = []
70
+
71
+ folders = next(os.walk(mainfolder))[1]
72
+ for folder in folders:
73
+ #adjust for pyiron folder, see
74
+ if folder.split('_')[-1] == 'hdf5':
75
+ #this could be a pyiron calc
76
+ withouthdf = folder.split('_hdf5')[0]
77
+ folder = f'{folder}/{withouthdf}'
78
+
79
+ inpfile = os.path.join(mainfolder, folder, 'input_file.yaml')
80
+ #print(inpfile)
81
+ if not os.path.exists(inpfile):
82
+ continue;
83
+
84
+ #ok, valid calculation, try to parse input file to get info
85
+ with open(inpfile, 'r') as fin:
86
+ inp = yaml.safe_load(fin)
87
+ #grab the first calculation
88
+ inp = inp['calculations'][0]
89
+ #mode
90
+ mode = inp['mode']
91
+ datadict['mode'].append(mode)
92
+ datadict['temperature'].append(inp['temperature'])
93
+ datadict['pressure'].append(inp['pressure'])
94
+ datadict['reference_phase'].append(inp['reference_phase'])
95
+ datadict['composition'].append(None)
96
+ datadict['calculation'].append(folder)
97
+
98
+ #check output file
99
+ outfile = os.path.join(mainfolder, folder, 'report.yaml')
100
+ datadict['error_code'].append(None)
101
+
102
+ #print(inpfile)
103
+ if not os.path.exists(outfile):
104
+ datadict['status'].append('False')
105
+ datadict['free_energy'].append(np.NaN)
106
+ #check if error file is found
107
+ errfile = os.path.join(os.getcwd(), mainfolder, folder+'.sub.err')
108
+ datadict['error_code'][-1] = _extract_error(errfile)
109
+ continue;
110
+
111
+ if mode in ['fe', 'alchemy', 'composition_scaling']:
112
+ datadict['status'].append('True')
113
+
114
+ #ok, valid calculation, try to parse input file to get info
115
+ with open(outfile, 'r') as fin:
116
+ out = yaml.safe_load(fin)
117
+
118
+ datadict['free_energy'].append(out['results']['free_energy'])
119
+
120
+ #add normal composition
121
+ el_arr = np.array(out['input']['element'].split(' ')).astype(str)
122
+ comp_arr = np.array(out['input']['concentration'].split(' ')).astype(float)
123
+ composition = {x:y for x,y in zip(el_arr, comp_arr)}
124
+ datadict['composition'][-1] = composition
125
+
126
+ if mode == 'composition_scaling':
127
+ #we need to update composition
128
+ compdict = inp['composition_scaling']['output_chemical_composition']
129
+ maxatoms = np.sum([val for key, val in compdict.items()])
130
+ for key, val in compdict.items():
131
+ compdict[key] = val/maxatoms
132
+ datadict['composition'][-1] = compdict
133
+
134
+ #parse extra info
135
+ if mode in ['ts', 'tscale']:
136
+ datafile = os.path.join(os.getcwd(), mainfolder, folder, 'temperature_sweep.dat')
137
+ if os.path.exists(datafile):
138
+ datadict['status'].append('True')
139
+ t, f = np.loadtxt(datafile, unpack=True, usecols=(0,1))
140
+ datadict['temperature'][-1] = t
141
+ datadict['free_energy'][-1] = f
142
+ else:
143
+ datadict['status'].append('False')
144
+ errfile = os.path.join(os.getcwd(), mainfolder, folder+'.sub.err')
145
+ datadict['error_code'][-1] = _extract_error(errfile)
146
+
147
+ df = pd.DataFrame(data=datadict)
148
+ return df
calphy/scheduler.py CHANGED
@@ -90,6 +90,7 @@ class SLURM:
90
90
  """
91
91
  self.queueoptions = {"scheduler": "slurm",
92
92
  "jobname": "tis",
93
+ "queuename": None,
93
94
  "walltime": "23:59:00",
94
95
  "memory": "3GB",
95
96
  "cores": cores,
@@ -125,7 +126,8 @@ class SLURM:
125
126
  #write the main header options
126
127
  fout.write("#SBATCH --job-name=%s\n" %self.queueoptions["jobname"])
127
128
  fout.write("#SBATCH --time=%s\n" %self.queueoptions["walltime"])
128
- fout.write("#SBATCH --partition=%s\n"%self.queueoptions["queuename"])
129
+ if self.queueoptions["queuename"] is not None:
130
+ fout.write("#SBATCH --partition=%s\n"%self.queueoptions["queuename"])
129
131
  fout.write("#SBATCH --ntasks=%s\n" %str(self.queueoptions["cores"]))
130
132
  fout.write("#SBATCH --mem-per-cpu=%s\n"%self.queueoptions["memory"])
131
133
  fout.write("#SBATCH --hint=%s\n" %self.queueoptions["hint"])
calphy/solid.py CHANGED
@@ -516,17 +516,20 @@ class Solid(cph.Phase):
516
516
  Calculates the final work, energy dissipation and free energy by
517
517
  matching with Einstein crystal
518
518
  """
519
- f1 = get_einstein_crystal_fe(
519
+ fe, fcm = get_einstein_crystal_fe(
520
520
  self.calc,
521
521
  self.vol,
522
- self.k)
522
+ self.k,
523
+ return_contributions=True)
523
524
 
524
525
  w, q, qerr = find_w(self.simfolder,
525
526
  self.calc,
526
527
  full=True,
527
528
  solid=True)
528
529
 
529
- self.fref = f1
530
+ self.fref = fe + fcm
531
+ self.feinstein = fe
532
+ self.fcm = fcm
530
533
  self.w = w
531
534
  self.ferr = qerr
532
535
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: calphy
3
- Version: 1.3.9
3
+ Version: 1.3.11
4
4
  Summary: free energy calculation for python
5
5
  Home-page: https://github.com/ICAMS/calphy
6
6
  Author: Sarath Menon, Yury Lysogorskiy, Ralf Drautz
@@ -0,0 +1,25 @@
1
+ calphy/__init__.py,sha256=yzftsRGAExKS7j5P49gh0fpg-c43MIsUCXKiUgGnCCg,234
2
+ calphy/alchemy.py,sha256=epv_vJoAMVbj-S1TuPSbBGr4w_a9qEr4EIxKlgwdlSo,12893
3
+ calphy/clitools.py,sha256=oDqaw0s-LJ7tAdW_Njk2SFljVx6K34Rs8sdMz48SNSI,4125
4
+ calphy/composition_transformation.py,sha256=Hh240-iVGC8ATlJ3nQK757qVZIBrE2aw7dsF46mi3oo,15353
5
+ calphy/errors.py,sha256=KN47RWTLbg1H_NZMrhCiJCbqjqJScJ1pgQAuzj1-l84,1268
6
+ calphy/helpers.py,sha256=nj8g53H6ScohQtyV7Enzms8Rv_89PRrDDY1IHjFSZdQ,8292
7
+ calphy/input.py,sha256=R-M0C-7i1ux1IWop0UzlqAKoYIre7cxVuFLspcUwsPk,29400
8
+ calphy/integrators.py,sha256=hJYmbznsgY-x-eZm7ng8gW0qsGbopERl5gGDnw5uLms,21719
9
+ calphy/kernel.py,sha256=rd_-EfCiBhQjkxcVaoLtVJB2_qDgS-g-dQ0BZBTJQ_A,6190
10
+ calphy/liquid.py,sha256=a5NTAjc3VsrPBQoEMGe9O1WXfv1vxGoB0xPguf0fOyM,13762
11
+ calphy/phase.py,sha256=FOm5_eP_8XbCYG3_UJoAToD3KKxlXcbSoEfQncZXTeA,44967
12
+ calphy/phase_diagram.py,sha256=2EwmT_qkT5BEP6Sx0_rm09kPP2RWh5JY4sogIBK_AhA,12992
13
+ calphy/postprocessing.py,sha256=hFsc5Kr1FOgfjicjm23Dy19BUbZU9GxKpbCa8_U6gbU,4947
14
+ calphy/queuekernel.py,sha256=4GMIYnjMiAPipoLNKP5noYcfeEOI_vCqm84zgokk7Xw,5321
15
+ calphy/routines.py,sha256=W6OZEPv6HEG11EYsoIbum2WVrO3Ly36i5UWsYQ4oBdQ,17473
16
+ calphy/scheduler.py,sha256=IN8ogDedpTbZZsdpOj-hYZI05gWoD4bN7mHOb1z77Vo,8579
17
+ calphy/solid.py,sha256=ZU_c4LqASoLzhjXX6eQY_8k_FNO9wjmMVTiOCKNsmis,19896
18
+ calphy/splines.py,sha256=BGwUVz_qXQxUzpUCuZo6CsELcd5JVNWzI-Ttcz22G_E,61627
19
+ calphy/utils.py,sha256=0UpsYoxjS5N-iGs-cdm0YDMkLF8IHvKO3smXDHrj3eg,3818
20
+ calphy-1.3.11.dist-info/LICENSE,sha256=XIHGB5RZLIhOjjoO1bPf0II-qDbjhP5Cv5HJMRE9v1g,16651
21
+ calphy-1.3.11.dist-info/METADATA,sha256=Pw5F6YJyyaGZlJG4kPU_MMf8UoilMH16JPa4iU7TFvY,4216
22
+ calphy-1.3.11.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
23
+ calphy-1.3.11.dist-info/entry_points.txt,sha256=W9qq254koyWnAgo1jtfQP9bO5Q7sgZrzc8BMnfo3vf4,386
24
+ calphy-1.3.11.dist-info/top_level.txt,sha256=w871dhMqPwgjjbifBWdkT9_aOnK1ek4Odrh8UnSG3PE,7
25
+ calphy-1.3.11.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.1.0)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,24 +0,0 @@
1
- calphy/__init__.py,sha256=RKi3orWUQRK_qYHCQKFzfbyTptYDonS9673vtVdelso,233
2
- calphy/alchemy.py,sha256=epv_vJoAMVbj-S1TuPSbBGr4w_a9qEr4EIxKlgwdlSo,12893
3
- calphy/clitools.py,sha256=oDqaw0s-LJ7tAdW_Njk2SFljVx6K34Rs8sdMz48SNSI,4125
4
- calphy/composition_transformation.py,sha256=Hh240-iVGC8ATlJ3nQK757qVZIBrE2aw7dsF46mi3oo,15353
5
- calphy/errors.py,sha256=KN47RWTLbg1H_NZMrhCiJCbqjqJScJ1pgQAuzj1-l84,1268
6
- calphy/helpers.py,sha256=nj8g53H6ScohQtyV7Enzms8Rv_89PRrDDY1IHjFSZdQ,8292
7
- calphy/input.py,sha256=Z8h-Y3dz5HJy6eOGYffMtUV9Q-NPall8dnPiFKkXUEw,29717
8
- calphy/integrators.py,sha256=CcK3oqIwZ3z41v3fh3IvswY_l-ZbLRluWuDNJlXCXfg,20680
9
- calphy/kernel.py,sha256=rd_-EfCiBhQjkxcVaoLtVJB2_qDgS-g-dQ0BZBTJQ_A,6190
10
- calphy/liquid.py,sha256=a5NTAjc3VsrPBQoEMGe9O1WXfv1vxGoB0xPguf0fOyM,13762
11
- calphy/phase.py,sha256=ukqad4MJ-MNGiyOsq2_jntG2s10UHbJVi2Ounpg_S2U,44787
12
- calphy/phase_diagram.py,sha256=2EwmT_qkT5BEP6Sx0_rm09kPP2RWh5JY4sogIBK_AhA,12992
13
- calphy/queuekernel.py,sha256=4GMIYnjMiAPipoLNKP5noYcfeEOI_vCqm84zgokk7Xw,5321
14
- calphy/routines.py,sha256=W6OZEPv6HEG11EYsoIbum2WVrO3Ly36i5UWsYQ4oBdQ,17473
15
- calphy/scheduler.py,sha256=9p1MdMlB2QtMV6-LmjBU9E0GOxx-fdDEvAb3LOVsRPM,8468
16
- calphy/solid.py,sha256=49gT0wNOP3h8lRDXarULP-bU09lIrnDCTUcyxE7X-UE,19795
17
- calphy/splines.py,sha256=BGwUVz_qXQxUzpUCuZo6CsELcd5JVNWzI-Ttcz22G_E,61627
18
- calphy/utils.py,sha256=0UpsYoxjS5N-iGs-cdm0YDMkLF8IHvKO3smXDHrj3eg,3818
19
- calphy-1.3.9.dist-info/LICENSE,sha256=XIHGB5RZLIhOjjoO1bPf0II-qDbjhP5Cv5HJMRE9v1g,16651
20
- calphy-1.3.9.dist-info/METADATA,sha256=OoDJsMjXCuKp1w4IxKX-RL9baeg3b4Co_BzHtaydQnc,4215
21
- calphy-1.3.9.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
22
- calphy-1.3.9.dist-info/entry_points.txt,sha256=W9qq254koyWnAgo1jtfQP9bO5Q7sgZrzc8BMnfo3vf4,386
23
- calphy-1.3.9.dist-info/top_level.txt,sha256=w871dhMqPwgjjbifBWdkT9_aOnK1ek4Odrh8UnSG3PE,7
24
- calphy-1.3.9.dist-info/RECORD,,