24
24
from pymatgen .util .plotting import add_fig_kwargs , get_ax_fig , pretty_plot
25
25
26
26
if TYPE_CHECKING :
27
- from typing import ClassVar
27
+ from collections .abc import Sequence
28
+ from typing import Any , ClassVar
28
29
29
30
import matplotlib .pyplot as plt
30
31
@@ -40,7 +41,11 @@ class EOSBase(ABC):
40
41
implementations.
41
42
"""
42
43
43
- def __init__ (self , volumes , energies ):
44
+ def __init__ (
45
+ self ,
46
+ volumes : Sequence [float ],
47
+ energies : Sequence [float ],
48
+ ) -> None :
44
49
"""
45
50
Args:
46
51
volumes (Sequence[float]): in Ang^3.
@@ -50,18 +55,28 @@ def __init__(self, volumes, energies):
50
55
self .energies = np .array (energies )
51
56
# minimum energy(e0), buk modulus(b0),
52
57
# derivative of bulk modulus w.r.t. pressure(b1), minimum volume(v0)
53
- self ._params = None
58
+ self ._params : Sequence | None = None
54
59
# the eos function parameters. It is the same as _params except for
55
60
# equation of states that uses polynomial fits(delta_factor and
56
61
# numerical_eos)
57
- self .eos_params = None
62
+ self .eos_params : Sequence | None = None
58
63
59
- def _initial_guess (self ):
64
+ def __call__ (self , volume : float ) -> float :
65
+ """
66
+ Args:
67
+ volume (float | list[float]): volume(s) in Ang^3.
68
+
69
+ Returns:
70
+ Compute EOS with this volume.
71
+ """
72
+ return self .func (volume )
73
+
74
+ def _initial_guess (self ) -> tuple [float , float , float , float ]:
60
75
"""
61
76
Quadratic fit to get an initial guess for the parameters.
62
77
63
78
Returns:
64
- tuple: 4 floats for ( e0, b0, b1, v0)
79
+ tuple[float, float, float, float]: e0, b0, b1, v0
65
80
"""
66
81
a , b , c = np .polyfit (self .volumes , self .energies , 2 )
67
82
self .eos_params = [a , b , c ]
@@ -78,7 +93,7 @@ def _initial_guess(self):
78
93
79
94
return e0 , b0 , b1 , v0
80
95
81
- def fit (self ):
96
+ def fit (self ) -> None :
82
97
"""
83
98
Do the fitting. Does least square fitting. If you want to use custom
84
99
fitting, must override this.
@@ -120,24 +135,20 @@ def func(self, volume):
120
135
"""
121
136
return self ._func (np .array (volume ), self .eos_params )
122
137
123
- def __call__ (self , volume : float ) -> float :
124
- """
125
- Args:
126
- volume (float | list[float]): volume(s) in Ang^3.
127
-
128
- Returns:
129
- Compute EOS with this volume.
130
- """
131
- return self .func (volume )
132
-
133
138
@property
134
139
def e0 (self ) -> float :
135
140
"""The min energy."""
141
+ if self ._params is None :
142
+ raise RuntimeError ("params have not be initialized." )
143
+
136
144
return self ._params [0 ]
137
145
138
146
@property
139
147
def b0 (self ) -> float :
140
148
"""The bulk modulus in units of energy/unit of volume^3."""
149
+ if self ._params is None :
150
+ raise RuntimeError ("params have not be initialized." )
151
+
141
152
return self ._params [1 ]
142
153
143
154
@property
@@ -156,11 +167,18 @@ def v0(self):
156
167
return self ._params [3 ]
157
168
158
169
@property
159
- def results (self ):
170
+ def results (self ) -> dict [ str , Any ] :
160
171
"""A summary dict."""
161
172
return {"e0" : self .e0 , "b0" : self .b0 , "b1" : self .b1 , "v0" : self .v0 }
162
173
163
- def plot (self , width = 8 , height = None , ax : plt .Axes = None , dpi = None , ** kwargs ):
174
+ def plot (
175
+ self ,
176
+ width : float = 8 ,
177
+ height : float | None = None ,
178
+ ax : plt .Axes = None ,
179
+ dpi : float | None = None ,
180
+ ** kwargs ,
181
+ ) -> plt .Axes :
164
182
"""
165
183
Plot the equation of state.
166
184
@@ -170,7 +188,7 @@ def plot(self, width=8, height=None, ax: plt.Axes = None, dpi=None, **kwargs):
170
188
golden ratio.
171
189
ax (plt.Axes): If supplied, changes will be made to the existing Axes.
172
190
Otherwise, new Axes will be created.
173
- dpi:
191
+ dpi (float): DPI.
174
192
kwargs (dict): additional args fed to pyplot.plot.
175
193
supported keys: style, color, text, label
176
194
@@ -211,16 +229,18 @@ def plot(self, width=8, height=None, ax: plt.Axes = None, dpi=None, **kwargs):
211
229
return ax
212
230
213
231
@add_fig_kwargs
214
- def plot_ax (self , ax : plt .Axes = None , fontsize = 12 , ** kwargs ):
232
+ def plot_ax (
233
+ self ,
234
+ ax : plt .Axes | None = None ,
235
+ fontsize : float = 12 ,
236
+ ** kwargs ,
237
+ ) -> plt .Figure :
215
238
"""
216
239
Plot the equation of state on axis `ax`.
217
240
218
241
Args:
219
242
ax: matplotlib Axes or None if a new figure should be created.
220
243
fontsize: Legend fontsize.
221
- color (str): plot color.
222
- label (str): Plot label
223
- text (str): Legend text (options)
224
244
225
245
Returns:
226
246
plt.Figure: matplotlib figure.
@@ -270,7 +290,7 @@ def plot_ax(self, ax: plt.Axes = None, fontsize=12, **kwargs):
270
290
class Murnaghan (EOSBase ):
271
291
"""Murnaghan EOS."""
272
292
273
- def _func (self , volume , params ):
293
+ def _func (self , volume , params : tuple [ float , float , float , float ] ):
274
294
"""From PRB 28,5480 (1983)."""
275
295
e0 , b0 , b1 , v0 = tuple (params )
276
296
return e0 + b0 * volume / b1 * (((v0 / volume ) ** b1 ) / (b1 - 1.0 ) + 1.0 ) - v0 * b0 / (b1 - 1.0 )
@@ -279,7 +299,7 @@ def _func(self, volume, params):
279
299
class Birch (EOSBase ):
280
300
"""Birch EOS."""
281
301
282
- def _func (self , volume , params ):
302
+ def _func (self , volume , params : tuple [ float , float , float , float ] ):
283
303
"""From Intermetallic compounds: Principles and Practice, Vol. I:
284
304
Principles Chapter 9 pages 195-210 by M. Mehl. B. Klein,
285
305
D. Papaconstantopoulos.
@@ -296,7 +316,7 @@ def _func(self, volume, params):
296
316
class BirchMurnaghan (EOSBase ):
297
317
"""BirchMurnaghan EOS."""
298
318
299
- def _func (self , volume , params ):
319
+ def _func (self , volume , params : tuple [ float , float , float , float ] ):
300
320
"""BirchMurnaghan equation from PRB 70, 224107."""
301
321
e0 , b0 , b1 , v0 = tuple (params )
302
322
eta = (v0 / volume ) ** (1 / 3 )
@@ -306,7 +326,7 @@ def _func(self, volume, params):
306
326
class PourierTarantola (EOSBase ):
307
327
"""Pourier-Tarantola EOS."""
308
328
309
- def _func (self , volume , params ):
329
+ def _func (self , volume , params : tuple [ float , float , float , float ] ):
310
330
"""Pourier-Tarantola equation from PRB 70, 224107."""
311
331
e0 , b0 , b1 , v0 = tuple (params )
312
332
eta = (volume / v0 ) ** (1 / 3 )
@@ -317,7 +337,7 @@ def _func(self, volume, params):
317
337
class Vinet (EOSBase ):
318
338
"""Vinet EOS."""
319
339
320
- def _func (self , volume , params ):
340
+ def _func (self , volume , params : tuple [ float , float , float , float ] ):
321
341
"""Vinet equation from PRB 70, 224107."""
322
342
e0 , b0 , b1 , v0 = tuple (params )
323
343
eta = (volume / v0 ) ** (1 / 3 )
@@ -335,7 +355,7 @@ class PolynomialEOS(EOSBase):
335
355
def _func (self , volume , params ):
336
356
return np .poly1d (list (params ))(volume )
337
357
338
- def fit (self , order ) :
358
+ def fit (self , order : int ) -> None :
339
359
"""
340
360
Do polynomial fitting and set the parameters. Uses numpy polyfit.
341
361
@@ -345,7 +365,7 @@ def fit(self, order):
345
365
self .eos_params = np .polyfit (self .volumes , self .energies , order )
346
366
self ._set_params ()
347
367
348
- def _set_params (self ):
368
+ def _set_params (self ) -> None :
349
369
"""
350
370
Use the fit polynomial to compute the parameter e0, b0, b1 and v0
351
371
and set to the _params attribute.
@@ -372,7 +392,7 @@ def _func(self, volume, params):
372
392
x = volume ** (- 2 / 3.0 )
373
393
return np .poly1d (list (params ))(x )
374
394
375
- def fit (self , order = 3 ) :
395
+ def fit (self , order : int = 3 ) -> None :
376
396
"""Overridden since this eos works with volume**(2/3) instead of volume."""
377
397
x = self .volumes ** (- 2 / 3.0 )
378
398
self .eos_params = np .polyfit (x , self .energies , order )
@@ -407,7 +427,12 @@ def _set_params(self):
407
427
class NumericalEOS (PolynomialEOS ):
408
428
"""A numerical EOS."""
409
429
410
- def fit (self , min_ndata_factor = 3 , max_poly_order_factor = 5 , min_poly_order = 2 ):
430
+ def fit (
431
+ self ,
432
+ min_ndata_factor : int = 3 ,
433
+ max_poly_order_factor : int = 5 ,
434
+ min_poly_order : int = 2 ,
435
+ ) -> None :
411
436
"""Fit the input data to the 'numerical eos', the equation of state employed
412
437
in the quasiharmonic Debye model described in the paper:
413
438
10.1103/PhysRevB.90.174107.
@@ -539,7 +564,7 @@ class EOS:
539
564
eos_fit.plot()
540
565
"""
541
566
542
- MODELS : ClassVar = {
567
+ MODELS : ClassVar [ dict [ str , Any ]] = {
543
568
"murnaghan" : Murnaghan ,
544
569
"birch" : Birch ,
545
570
"birch_murnaghan" : BirchMurnaghan ,
@@ -549,7 +574,7 @@ class EOS:
549
574
"numerical_eos" : NumericalEOS ,
550
575
}
551
576
552
- def __init__ (self , eos_name = "murnaghan" ):
577
+ def __init__ (self , eos_name : str = "murnaghan" ) -> None :
553
578
"""
554
579
Args:
555
580
eos_name (str): Type of EOS to fit.
@@ -562,7 +587,7 @@ def __init__(self, eos_name="murnaghan"):
562
587
self ._eos_name = eos_name
563
588
self .model = self .MODELS [eos_name ]
564
589
565
- def fit (self , volumes , energies ) :
590
+ def fit (self , volumes : Sequence [ float ] , energies : Sequence [ float ]) -> EOSBase :
566
591
"""Fit energies as function of volumes.
567
592
568
593
Args:
0 commit comments