30
30
31
31
from typing_extensions import Self
32
32
33
+ from pymatgen .analysis .phase_diagram import PhaseDiagram
33
34
from pymatgen .core import Structure
34
35
35
36
__author__ = "Ryan Kingsbury, Matt McDermott, Shyue Ping Ong, Anubhav Jain"
@@ -50,12 +51,12 @@ class EnergyAdjustment(MSONable):
50
51
51
52
def __init__ (
52
53
self ,
53
- value ,
54
- uncertainty = np .nan ,
55
- name = "Manual adjustment" ,
56
- cls = None ,
57
- description = "" ,
58
- ):
54
+ value : float ,
55
+ uncertainty : float = np .nan ,
56
+ name : str = "Manual adjustment" ,
57
+ cls : dict | None = None ,
58
+ description : str = "" ,
59
+ ) -> None :
59
60
"""
60
61
Args:
61
62
value (float): value of the energy adjustment in eV
@@ -69,20 +70,20 @@ def __init__(
69
70
self .cls = cls or {}
70
71
self .description = description
71
72
self ._value = value
72
- self ._uncertainty = uncertainty
73
+ self ._uncertainty = float ( uncertainty )
73
74
74
75
@property
75
- def value (self ):
76
+ def value (self ) -> float :
76
77
"""The value of the energy correction in eV."""
77
78
return self ._value
78
79
79
80
@property
80
- def uncertainty (self ):
81
+ def uncertainty (self ) -> float :
81
82
"""The uncertainty in the value of the energy adjustment in eV."""
82
83
return self ._uncertainty
83
84
84
85
@abc .abstractmethod
85
- def normalize (self , factor ) :
86
+ def normalize (self , factor : float ) -> None :
86
87
"""Scale the value of the current energy adjustment by factor in-place.
87
88
88
89
This method is utilized in ComputedEntry.normalize() to scale the energies to a formula unit basis
@@ -91,10 +92,10 @@ def normalize(self, factor):
91
92
92
93
@property
93
94
@abc .abstractmethod
94
- def explain (self ):
95
+ def explain (self ) -> str :
95
96
"""Return an explanation of how the energy adjustment is calculated."""
96
97
97
- def __repr__ (self ):
98
+ def __repr__ (self ) -> str :
98
99
name , value , uncertainty , description = (
99
100
self .name ,
100
101
float (self .value ),
@@ -115,28 +116,28 @@ class ConstantEnergyAdjustment(EnergyAdjustment):
115
116
116
117
def __init__ (
117
118
self ,
118
- value ,
119
- uncertainty = np .nan ,
120
- name = "Constant energy adjustment" ,
121
- cls = None ,
122
- description = "Constant energy adjustment" ,
123
- ):
119
+ value : float ,
120
+ uncertainty : float = np .nan ,
121
+ name : str = "Constant energy adjustment" ,
122
+ cls : dict | None = None ,
123
+ description : str = "Constant energy adjustment" ,
124
+ ) -> None :
124
125
"""
125
126
Args:
126
- value: float, value of the energy adjustment in eV
127
- uncertainty: float, uncertainty of the energy adjustment in eV. (Default: np.nan)
128
- name: str, human-readable name of the energy adjustment.
127
+ value ( float): the energy adjustment in eV
128
+ uncertainty ( float): uncertainty of the energy adjustment in eV. (Default: np.nan)
129
+ name ( str): human-readable name of the energy adjustment.
129
130
(Default: Constant energy adjustment)
130
- cls: dict, Serialized Compatibility class used to generate the energy
131
+ cls ( dict): Serialized Compatibility class used to generate the energy
131
132
adjustment. (Default: None)
132
- description: str, human-readable explanation of the energy adjustment.
133
+ description ( str): human-readable explanation of the energy adjustment.
133
134
"""
134
135
super ().__init__ (value , uncertainty , name = name , cls = cls , description = description )
135
136
self ._value = value
136
- self ._uncertainty = uncertainty
137
+ self ._uncertainty = float ( uncertainty )
137
138
138
139
@property
139
- def explain (self ):
140
+ def explain (self ) -> str :
140
141
"""An explanation of how the energy adjustment is calculated."""
141
142
return f"{ self .description } ({ self .value :.3f} eV)"
142
143
@@ -145,7 +146,7 @@ def normalize(self, factor: float) -> None:
145
146
factor.
146
147
147
148
Args:
148
- factor: factor to divide by.
149
+ factor (float) : factor to divide by.
149
150
"""
150
151
self ._value /= factor
151
152
self ._uncertainty /= factor
@@ -154,10 +155,10 @@ def normalize(self, factor: float) -> None:
154
155
class ManualEnergyAdjustment (ConstantEnergyAdjustment ):
155
156
"""A manual energy adjustment applied to a ComputedEntry."""
156
157
157
- def __init__ (self , value ) :
158
+ def __init__ (self , value : float ) -> None :
158
159
"""
159
160
Args:
160
- value: float, value of the energy adjustment in eV.
161
+ value ( float): the energy adjustment in eV.
161
162
"""
162
163
name = "Manual energy adjustment"
163
164
description = "Manual energy adjustment"
@@ -171,44 +172,44 @@ class CompositionEnergyAdjustment(EnergyAdjustment):
171
172
172
173
def __init__ (
173
174
self ,
174
- adj_per_atom ,
175
- n_atoms ,
176
- uncertainty_per_atom = np .nan ,
177
- name = "" ,
178
- cls = None ,
179
- description = "Composition-based energy adjustment" ,
180
- ):
175
+ adj_per_atom : float ,
176
+ n_atoms : float ,
177
+ uncertainty_per_atom : float = np .nan ,
178
+ name : str = "" ,
179
+ cls : dict | None = None ,
180
+ description : str = "Composition-based energy adjustment" ,
181
+ ) -> None :
181
182
"""
182
183
Args:
183
- adj_per_atom: float, energy adjustment to apply per atom, in eV/atom
184
- n_atoms: float or int, number of atoms.
185
- uncertainty_per_atom: float, uncertainty in energy adjustment to apply per atom, in eV/atom.
184
+ adj_per_atom ( float): energy adjustment to apply per atom, in eV/atom
185
+ n_atoms ( float): number of atoms.
186
+ uncertainty_per_atom ( float): uncertainty in energy adjustment to apply per atom, in eV/atom.
186
187
(Default: np.nan)
187
- name: str, human-readable name of the energy adjustment.
188
+ name ( str): human-readable name of the energy adjustment.
188
189
(Default: "")
189
- cls: dict, Serialized Compatibility class used to generate the energy
190
+ cls ( dict): Serialized Compatibility class used to generate the energy
190
191
adjustment. (Default: None)
191
- description: str, human-readable explanation of the energy adjustment.
192
+ description ( str): human-readable explanation of the energy adjustment.
192
193
"""
193
194
self ._adj_per_atom = adj_per_atom
194
- self .uncertainty_per_atom = uncertainty_per_atom
195
+ self .uncertainty_per_atom = float ( uncertainty_per_atom )
195
196
self .n_atoms = n_atoms
196
197
self .cls = cls or {}
197
198
self .name = name
198
199
self .description = description
199
200
200
201
@property
201
- def value (self ):
202
+ def value (self ) -> float :
202
203
"""The value of the energy adjustment in eV."""
203
204
return self ._adj_per_atom * self .n_atoms
204
205
205
206
@property
206
- def uncertainty (self ):
207
+ def uncertainty (self ) -> float :
207
208
"""The value of the energy adjustment in eV."""
208
209
return self .uncertainty_per_atom * self .n_atoms
209
210
210
211
@property
211
- def explain (self ):
212
+ def explain (self ) -> str :
212
213
"""An explanation of how the energy adjustment is calculated."""
213
214
return f"{ self .description } ({ self ._adj_per_atom :.3f} eV/atom x { self .n_atoms } atoms)"
214
215
@@ -229,47 +230,47 @@ class TemperatureEnergyAdjustment(EnergyAdjustment):
229
230
230
231
def __init__ (
231
232
self ,
232
- adj_per_deg ,
233
- temp ,
234
- n_atoms ,
235
- uncertainty_per_deg = np .nan ,
236
- name = "" ,
237
- cls = None ,
238
- description = "Temperature-based energy adjustment" ,
239
- ):
233
+ adj_per_deg : float ,
234
+ temp : float ,
235
+ n_atoms : float ,
236
+ uncertainty_per_deg : float = np .nan ,
237
+ name : str = "" ,
238
+ cls : dict | None = None ,
239
+ description : str = "Temperature-based energy adjustment" ,
240
+ ) -> None :
240
241
"""
241
242
Args:
242
- adj_per_deg: float, energy adjustment to apply per degree K, in eV/atom
243
- temp: float, temperature in Kelvin
244
- n_atoms: float or int, number of atoms
245
- uncertainty_per_deg: float, uncertainty in energy adjustment to apply per degree K,
243
+ adj_per_deg ( float): energy adjustment to apply per degree K, in eV/atom
244
+ temp ( float): temperature in Kelvin
245
+ n_atoms ( float): number of atoms
246
+ uncertainty_per_deg ( float): uncertainty in energy adjustment to apply per degree K,
246
247
in eV/atom. (Default: np.nan)
247
- name: str, human-readable name of the energy adjustment.
248
+ name ( str): human-readable name of the energy adjustment.
248
249
(Default: "")
249
- cls: dict, Serialized Compatibility class used to generate the energy
250
+ cls ( dict): Serialized Compatibility class used to generate the energy
250
251
adjustment. (Default: None)
251
- description: str, human-readable explanation of the energy adjustment.
252
+ description ( str): human-readable explanation of the energy adjustment.
252
253
"""
253
254
self ._adj_per_deg = adj_per_deg
254
- self .uncertainty_per_deg = uncertainty_per_deg
255
+ self .uncertainty_per_deg = float ( uncertainty_per_deg )
255
256
self .temp = temp
256
257
self .n_atoms = n_atoms
257
258
self .name = name
258
259
self .cls = cls or {}
259
260
self .description = description
260
261
261
262
@property
262
- def value (self ):
263
+ def value (self ) -> float :
263
264
"""The value of the energy correction in eV."""
264
265
return self ._adj_per_deg * self .temp * self .n_atoms
265
266
266
267
@property
267
- def uncertainty (self ):
268
+ def uncertainty (self ) -> float :
268
269
"""The value of the energy adjustment in eV."""
269
270
return self .uncertainty_per_deg * self .temp * self .n_atoms
270
271
271
272
@property
272
- def explain (self ):
273
+ def explain (self ) -> str :
273
274
"""An explanation of how the energy adjustment is calculated."""
274
275
return f"{ self .description } ({ self ._adj_per_deg :.4f} eV/K/atom x { self .temp } K x { self .n_atoms } atoms)"
275
276
@@ -298,7 +299,7 @@ def __init__(
298
299
parameters : dict | None = None ,
299
300
data : dict | None = None ,
300
301
entry_id : str | None = None ,
301
- ):
302
+ ) -> None :
302
303
"""Initialize a ComputedEntry.
303
304
304
305
Args:
@@ -322,7 +323,7 @@ def __init__(
322
323
super ().__init__ (composition , energy )
323
324
self .energy_adjustments = energy_adjustments or []
324
325
325
- if correction != 0.0 :
326
+ if not math . isclose ( correction , 0.0 ) :
326
327
if energy_adjustments :
327
328
raise ValueError (
328
329
f"Argument conflict! Setting correction = { correction :.3f} conflicts "
@@ -395,7 +396,7 @@ def correction_uncertainty(self) -> float:
395
396
for ea in self .energy_adjustments
396
397
) or ufloat (0.0 , np .nan )
397
398
398
- if unc .nominal_value != 0 and unc .std_dev == 0 :
399
+ if not math . isclose ( unc .nominal_value , 0 ) and math . isclose ( unc .std_dev , 0 ) :
399
400
return np .nan
400
401
401
402
return unc .std_dev
@@ -498,7 +499,7 @@ def from_dict(cls, dct: dict) -> Self:
498
499
# we don't pass correction explicitly because it will be calculated
499
500
# on the fly from energy_adjustments
500
501
correction = 0
501
- if dct ["correction" ] != 0 and len (energy_adj ) == 0 :
502
+ if not math . isclose ( dct ["correction" ], 0 ) and len (energy_adj ) == 0 :
502
503
# this block is for legacy ComputedEntry that were
503
504
# serialized before we had the energy_adjustments attribute.
504
505
correction = dct ["correction" ]
@@ -629,7 +630,7 @@ def from_dict(cls, dct: dict) -> Self:
629
630
"""
630
631
# the first block here is for legacy ComputedEntry that were
631
632
# serialized before we had the energy_adjustments attribute.
632
- if dct ["correction" ] != 0 and not dct .get ("energy_adjustments" ):
633
+ if not math . isclose ( dct ["correction" ], 0 ) and not dct .get ("energy_adjustments" ):
633
634
struct = MontyDecoder ().process_decoded (dct ["structure" ])
634
635
return cls (
635
636
struct ,
@@ -709,7 +710,7 @@ def __init__(
709
710
parameters : dict | None = None ,
710
711
data : dict | None = None ,
711
712
entry_id : str | None = None ,
712
- ):
713
+ ) -> None :
713
714
"""
714
715
Args:
715
716
structure (Structure): The pymatgen Structure object of an entry.
@@ -891,7 +892,12 @@ def _g_delta_sisso(vol_per_atom, reduced_mass, temp) -> float:
891
892
)
892
893
893
894
@classmethod
894
- def from_pd (cls , pd , temp = 300 , gibbs_model = "SISSO" ) -> list [Self ]:
895
+ def from_pd (
896
+ cls ,
897
+ pd : PhaseDiagram ,
898
+ temp : float = 300 ,
899
+ gibbs_model : Literal ["SISSO" ] = "SISSO" ,
900
+ ) -> list [Self ]:
895
901
"""Constructor method for initializing a list of GibbsComputedStructureEntry
896
902
objects from an existing T = 0 K phase diagram composed of
897
903
ComputedStructureEntry objects, as acquired from a thermochemical database;
@@ -900,7 +906,7 @@ def from_pd(cls, pd, temp=300, gibbs_model="SISSO") -> list[Self]:
900
906
Args:
901
907
pd (PhaseDiagram): T = 0 K phase diagram as created in pymatgen. Must
902
908
contain ComputedStructureEntry objects.
903
- temp (int ): Temperature [K] for estimating Gibbs free energy of formation.
909
+ temp (float ): Temperature [K] for estimating Gibbs free energy of formation.
904
910
gibbs_model (str): Gibbs model to use; currently the only option is "SISSO".
905
911
906
912
Returns:
@@ -925,15 +931,20 @@ def from_pd(cls, pd, temp=300, gibbs_model="SISSO") -> list[Self]:
925
931
return gibbs_entries
926
932
927
933
@classmethod
928
- def from_entries (cls , entries , temp = 300 , gibbs_model = "SISSO" ) -> list [Self ]:
934
+ def from_entries (
935
+ cls ,
936
+ entries : list ,
937
+ temp : float = 300 ,
938
+ gibbs_model : Literal ["SISSO" ] = "SISSO" ,
939
+ ) -> list [Self ]:
929
940
"""Constructor method for initializing GibbsComputedStructureEntry objects from
930
941
T = 0 K ComputedStructureEntry objects, as acquired from a thermochemical
931
942
database e.g. The Materials Project.
932
943
933
944
Args:
934
945
entries ([ComputedStructureEntry]): List of ComputedStructureEntry objects,
935
946
as downloaded from The Materials Project API.
936
- temp (int ): Temperature [K] for estimating Gibbs free energy of formation.
947
+ temp (float ): Temperature [K] for estimating Gibbs free energy of formation.
937
948
gibbs_model (str): Gibbs model to use; currently the only option is "SISSO".
938
949
939
950
Returns:
@@ -978,7 +989,7 @@ def from_dict(cls, dct: dict) -> Self:
978
989
entry_id = dct .get ("entry_id" ),
979
990
)
980
991
981
- def __repr__ (self ):
992
+ def __repr__ (self ) -> str :
982
993
return (
983
994
f"GibbsComputedStructureEntry { self .entry_id } - { self .formula } \n "
984
995
f"Gibbs Free Energy (Formation) = { self .energy :.4f} "
0 commit comments