Skip to content

Commit ed80c87

Browse files
DanielYang59shyuep
andauthored
Add missing parenthesis to electronic_structure.boltztrap.BoltztrapAnalyzer.get_extreme.is_isotropic (#4271)
* add missing parenthesis * minor cleanup of type, comment and var name --------- Co-authored-by: Shyue Ping Ong <[email protected]>
1 parent 90a1ef7 commit ed80c87

File tree

2 files changed

+50
-48
lines changed

2 files changed

+50
-48
lines changed

src/pymatgen/electronic_structure/boltztrap.py

Lines changed: 49 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
from pymatgen.symmetry.bandstructure import HighSymmKpath
4242

4343
if TYPE_CHECKING:
44-
from typing import Literal
44+
from typing import Any, Literal
4545

4646
from numpy.typing import ArrayLike
4747
from typing_extensions import Self
@@ -1426,96 +1426,98 @@ def get_complexity_factor(
14261426

14271427
def get_extreme(
14281428
self,
1429-
target_prop,
1430-
maximize=True,
1431-
min_temp=None,
1432-
max_temp=None,
1433-
min_doping=None,
1434-
max_doping=None,
1435-
isotropy_tolerance=0.05,
1436-
use_average=True,
1437-
):
1429+
target_prop: Literal["seebeck", "power factor", "conductivity", "kappa", "zt"],
1430+
maximize: bool = True,
1431+
min_temp: float | None = None,
1432+
max_temp: float | None = None,
1433+
min_doping: float | None = None,
1434+
max_doping: float | None = None,
1435+
isotropy_tolerance: float = 0.05,
1436+
use_average: bool = True,
1437+
) -> dict[Literal["p", "n", "best"], dict[str, Any]]:
14381438
"""Use eigenvalues over a range of carriers, temperatures, and doping levels, to estimate the "best"
14391439
value that can be achieved for the given target_property. Note that
14401440
this method searches the doping dict only, not the full mu dict.
14411441
14421442
Args:
1443-
target_prop: target property, i.e. "seebeck", "power factor", "conductivity", "kappa", or "zt"
1444-
maximize: True to maximize, False to minimize (e.g. kappa)
1445-
min_temp: minimum temperature allowed
1446-
max_temp: maximum temperature allowed
1447-
min_doping: minimum doping allowed (e.g., 1E18)
1448-
max_doping: maximum doping allowed (e.g., 1E20)
1449-
isotropy_tolerance: tolerance for isotropic (0.05 = 5%)
1450-
use_average: True for avg of eigenval, False for max eigenval
1443+
target_prop ("seebeck", "power factor", "conductivity", "kappa", "zt"): target property.
1444+
maximize (bool): True to maximize, False to minimize (e.g. kappa)
1445+
min_temp (float): minimum temperature allowed
1446+
max_temp (float): maximum temperature allowed
1447+
min_doping (float): minimum doping allowed (e.g., 1E18)
1448+
max_doping (float): maximum doping allowed (e.g., 1E20)
1449+
isotropy_tolerance (float): tolerance for isotropic (0.05 = 5%)
1450+
use_average (bool): True for average of eigenval, False for max eigenval.
14511451
14521452
Returns:
1453-
A dictionary with keys {"p", "n", "best"} with sub-keys:
1454-
{"value", "temperature", "doping", "isotropic"}
1453+
A dictionary with the following keys: {"p", "n", "best"}.
1454+
Each key maps to a sub-dictionary with the following keys:
1455+
{"value", "temperature", "doping", "isotropic", "carrier_type"}.
14551456
"""
14561457

1457-
def is_isotropic(x, isotropy_tolerance) -> bool:
1458-
"""Internal method to tell you if 3-vector "x" is isotropic.
1458+
def is_isotropic(x, isotropy_tolerance: float) -> bool:
1459+
"""Helper function to determine if 3D vector is isotropic.
14591460
14601461
Args:
14611462
x: the vector to determine isotropy for
1462-
isotropy_tolerance: tolerance, e.g. 0.05 is 5%
1463+
isotropy_tolerance (float): tolerance, e.g. 0.05 is 5%
14631464
"""
14641465
if len(x) != 3:
1465-
raise ValueError("Invalid input to is_isotropic!")
1466+
raise ValueError("Invalid vector length to is_isotropic!")
14661467

14671468
st = sorted(x)
1469+
14681470
return bool(
14691471
all([st[0], st[1], st[2]])
14701472
and (abs((st[1] - st[0]) / st[1]) <= isotropy_tolerance)
1471-
and (abs(st[2] - st[0]) / st[2] <= isotropy_tolerance)
1473+
and (abs((st[2] - st[0]) / st[2]) <= isotropy_tolerance)
14721474
and (abs((st[2] - st[1]) / st[2]) <= isotropy_tolerance)
14731475
)
14741476

14751477
if target_prop.lower() == "seebeck":
1476-
d = self.get_seebeck(output="eigs", doping_levels=True)
1478+
dct = self.get_seebeck(output="eigs", doping_levels=True)
14771479

14781480
elif target_prop.lower() == "power factor":
1479-
d = self.get_power_factor(output="eigs", doping_levels=True)
1481+
dct = self.get_power_factor(output="eigs", doping_levels=True)
14801482

14811483
elif target_prop.lower() == "conductivity":
1482-
d = self.get_conductivity(output="eigs", doping_levels=True)
1484+
dct = self.get_conductivity(output="eigs", doping_levels=True)
14831485

14841486
elif target_prop.lower() == "kappa":
1485-
d = self.get_thermal_conductivity(output="eigs", doping_levels=True)
1487+
dct = self.get_thermal_conductivity(output="eigs", doping_levels=True)
14861488
elif target_prop.lower() == "zt":
1487-
d = self.get_zt(output="eigs", doping_levels=True)
1489+
dct = self.get_zt(output="eigs", doping_levels=True)
14881490

14891491
else:
14901492
raise ValueError(f"Unrecognized {target_prop=}")
14911493

1492-
abs_val = True # take the absolute value of properties
1494+
abs_val: bool = True # take the absolute value of properties
14931495

14941496
x_val = x_temp = x_doping = x_isotropic = None
1495-
output = {}
1497+
output: dict[Literal["p", "n", "best"], dict[str, Any]] = {}
14961498

14971499
min_temp = min_temp or 0
14981500
max_temp = max_temp or float("inf")
14991501
min_doping = min_doping or 0
15001502
max_doping = max_doping or float("inf")
15011503

1502-
for pn in ("p", "n"):
1503-
for t in d[pn]: # temperatures
1504-
if min_temp <= float(t) <= max_temp:
1505-
for didx, evs in enumerate(d[pn][t]):
1506-
doping_lvl = self.doping[pn][didx]
1504+
for pn_type in ("p", "n"):
1505+
for temperature in dct[pn_type]:
1506+
if min_temp <= float(temperature) <= max_temp:
1507+
for idx, eig_vals in enumerate(dct[pn_type][temperature]):
1508+
doping_lvl = self.doping[pn_type][idx]
15071509
if min_doping <= doping_lvl <= max_doping:
1508-
isotropic = is_isotropic(evs, isotropy_tolerance)
1510+
isotropic: bool = is_isotropic(eig_vals, isotropy_tolerance)
15091511
if abs_val:
1510-
evs = [abs(x) for x in evs]
1511-
val = float(sum(evs)) / len(evs) if use_average else max(evs)
1512+
eig_vals = [abs(x) for x in eig_vals]
1513+
val = float(sum(eig_vals)) / len(eig_vals) if use_average else max(eig_vals)
15121514
if x_val is None or (val > x_val and maximize) or (val < x_val and not maximize):
15131515
x_val = val
1514-
x_temp = t
1516+
x_temp = temperature
15151517
x_doping = doping_lvl
15161518
x_isotropic = isotropic
15171519

1518-
output[pn] = {
1520+
output[pn_type] = {
15191521
"value": x_val,
15201522
"temperature": x_temp,
15211523
"doping": x_doping,
@@ -1524,7 +1526,7 @@ def is_isotropic(x, isotropy_tolerance) -> bool:
15241526
x_val = None
15251527

15261528
if maximize:
1527-
max_type = "p" if output["p"]["value"] >= output["n"]["value"] else "n"
1529+
max_type: Literal["p", "n"] = "p" if output["p"]["value"] >= output["n"]["value"] else "n"
15281530
else:
15291531
max_type = "p" if output["p"]["value"] <= output["n"]["value"] else "n"
15301532

@@ -1589,10 +1591,10 @@ def get_complete_dos(self, structure: Structure, analyzer_for_second_spin=None):
15891591
Example of use in case of spin polarized case:
15901592
15911593
BoltztrapRunner(bs=bs,nelec=10,run_type="DOS",spin=1).run(path_dir='dos_up/')
1592-
an_up=BoltztrapAnalyzer.from_files("dos_up/boltztrap/",dos_spin=1)
1594+
an_up=BoltztrapAnalyzer.from_files("dos_up/boltztrap/", dos_spin=1)
15931595
15941596
BoltztrapRunner(bs=bs,nelec=10,run_type="DOS",spin=-1).run(path_dir='dos_dw/')
1595-
an_dw=BoltztrapAnalyzer.from_files("dos_dw/boltztrap/",dos_spin=-1)
1597+
an_dw=BoltztrapAnalyzer.from_files("dos_dw/boltztrap/", dos_spin=-1)
15961598
15971599
cdos=an_up.get_complete_dos(bs.structure,an_dw)
15981600
"""
@@ -1602,10 +1604,10 @@ def get_complete_dos(self, structure: Structure, analyzer_for_second_spin=None):
16021604

16031605
if analyzer_for_second_spin:
16041606
if not np.all(self.dos.energies == analyzer_for_second_spin.dos.energies):
1605-
raise BoltztrapError("Dos merging error: energies of the two dos are different")
1607+
raise BoltztrapError("DOS merging error: energies of the two DOS are different")
16061608

16071609
if spin_1 == spin_2:
1608-
raise BoltztrapError("Dos merging error: spin component are the same")
1610+
raise BoltztrapError("DOS merging error: spin component are the same")
16091611

16101612
for s in self._dos_partial:
16111613
idx = int(s)

tests/electronic_structure/test_boltztrap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ def test_extreme(self):
242242
extreme = self.bz.get_extreme("seebeck")
243243
assert extreme["best"]["carrier_type"] == "n"
244244
assert extreme["p"]["value"] == approx(1255.365, abs=1e-2)
245-
assert extreme["n"]["isotropic"]
245+
assert extreme["n"]["isotropic"] is False
246246
assert extreme["n"]["temperature"] == 600
247247

248248
extreme = self.bz.get_extreme("kappa", maximize=False, min_temp=400, min_doping=1e20)

0 commit comments

Comments
 (0)