Skip to content

Commit d147350

Browse files
committed
MAINT: Update chemical potential calculation defaults and error handling
- Change `chemical_potential_range` default to None to avoid mutable default arrays. - Set `electron_tol` default to 0.05 for consistency. - Exit immediately with ValueError if chemical potential cannot be found in the specified range.
1 parent e6dee2b commit d147350

File tree

1 file changed

+34
-10
lines changed

1 file changed

+34
-10
lines changed

dfttk/thermal_electronic/thermal_electronic.py

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,8 @@ def calculate_chemical_potential(
603603
energies: np.ndarray,
604604
dos: np.ndarray,
605605
temperature: float,
606-
chemical_potential_range: np.ndarray = np.array([-0.1, 0.1]),
607-
electron_tol: float = 0.5,
606+
chemical_potential_range: np.ndarray = None,
607+
electron_tol: float = 0.05,
608608
) -> float:
609609
"""
610610
Calculates the chemical potential at a given electronic DOS, temperature, and
@@ -616,9 +616,10 @@ def calculate_chemical_potential(
616616
energies: Energy values for the electron DOS.
617617
dos: Electron DOS values.
618618
temperature: Temperature in K.
619-
chemical_potential_range: Range to search for the chemical potential. Defaults to np.array([-0.1, 0.1]).
619+
chemical_potential_range: Optional range to search for the chemical potential in eV.
620+
Defaults to None, which uses [-0.1, 0.1] eV.
620621
electron_tol: Tolerance for electron number matching.
621-
Defaults to 0.5.
622+
Defaults to 0.05.
622623
623624
Raises:
624625
ValueError: If `temperature < 0 K`.
@@ -628,14 +629,22 @@ def calculate_chemical_potential(
628629
Returns: Chemical potential at the given electronic DOS, temperature, and volume.
629630
"""
630631

632+
# If temperature is negative, raise an error
631633
if temperature < 0:
632634
raise ValueError("Temperature cannot be less than 0 K")
633635
temperature = float(temperature)
636+
637+
# If chemical_potential_range is None, set it to [-0.1, 0.1] eV
638+
if chemical_potential_range is None:
639+
chemical_potential_range = np.array([-0.1, 0.1])
634640

641+
# Calculate the number of electrons at 0 K using the provided energies and DOS
635642
num_electrons_0K = ThermalElectronic.calculate_num_electrons(
636643
energies=energies, dos=dos, chemical_potential=0, temperature=0
637644
)
638645

646+
# If the number of electrons at 0 K does not match the expected number of electrons
647+
# from VASP within the specified tolerance, issue a warning
639648
if self.nelect is not None:
640649
if abs(num_electrons_0K - self.nelect) > electron_tol:
641650
warnings.warn(
@@ -645,6 +654,8 @@ def calculate_chemical_potential(
645654
UserWarning,
646655
)
647656

657+
# Try to find the chemical potential such that the number of electrons at the
658+
# given temperature matches that at 0 K within the specified tolerance
648659
num_electrons_guess = ThermalElectronic.calculate_num_electrons(
649660
energies=energies,
650661
dos=dos,
@@ -655,6 +666,8 @@ def calculate_chemical_potential(
655666
if abs(num_electrons_guess - num_electrons_0K) < electron_tol:
656667
return 0
657668

669+
# If the above guess is not within the tolerance, use the bisection method to
670+
# find the chemical potential
658671
def electron_difference(chemical_potential):
659672
num_electrons = ThermalElectronic.calculate_num_electrons(
660673
energies=energies,
@@ -671,12 +684,11 @@ def electron_difference(chemical_potential):
671684
chemical_potential_range[1],
672685
)
673686
except ValueError as e:
674-
print(
675-
f"Warning: The chemical potential could not be found within the range "
676-
f"{chemical_potential_range[0]} to {chemical_potential_range[1]} eV."
677-
" Consider increasing the chemical_potential_range."
678-
)
679-
chemical_potential = chemical_potential_range[1]
687+
raise ValueError(
688+
f"Chemical potential could not be found in range "
689+
f"{chemical_potential_range[0]} to {chemical_potential_range[1]} eV. "
690+
"Increase chemical_potential_range."
691+
) from e
680692

681693
return chemical_potential
682694

@@ -739,9 +751,12 @@ def fermi_dirac_distribution(
739751
chemical_potential = float(chemical_potential)
740752
temperature = float(temperature)
741753

754+
# If temperature is negative, raise an error
742755
if temperature < 0:
743756
raise ValueError("Temperature cannot be less than 0 K")
744757

758+
# Calculate the Fermi-Dirac distribution function at the given temperature and
759+
# chemical potential.
745760
if temperature == 0:
746761
fermi_dist = np.where(energies <= chemical_potential, 1, 0)
747762
else:
@@ -750,6 +765,8 @@ def fermi_dirac_distribution(
750765
-(energies - chemical_potential) / (BOLTZMANN_CONSTANT * temperature)
751766
)
752767

768+
# If plot is True, plot the Fermi-Dirac distribution function vs. energy for the
769+
# given temperature and chemical potential
753770
if plot:
754771
fig = ThermalElectronic.plot_fermi_dirac_distribution(
755772
energies, fermi_dist, chemical_potential, temperature
@@ -817,12 +834,17 @@ def calculate_num_electrons(
817834
chemical_potential = float(chemical_potential)
818835
temperature = float(temperature)
819836

837+
# If temperature is negative, raise an error
820838
if temperature < 0:
821839
raise ValueError("Temperature cannot be less than 0 K")
822840

841+
# Calculate the Fermi-Dirac distribution function at the given temperature and
842+
# chemical potential.
823843
fermi_dist = ThermalElectronic.fermi_dirac_distribution(
824844
energies, chemical_potential, temperature
825845
)
846+
847+
# Calculate the number of electrons by integration.
826848
integrand = dos * fermi_dist
827849
num_electrons = np.trapz(integrand, energies)
828850

@@ -921,6 +943,7 @@ def calculate_internal_energies(
921943
"plot_temperature must be provided if and only if plot is True."
922944
)
923945

946+
# If plot is True, plot the integrands vs. energy for the specified plot_temperature
924947
if plot and plot_temperature is not None:
925948
if plot_temperature not in temperatures:
926949
raise ValueError(
@@ -1236,6 +1259,7 @@ def calculate_heat_capacities(
12361259
"plot_temperature must be provided if and only if plot is True."
12371260
)
12381261

1262+
# If plot is True, plot the integrand vs. energy for the specified plot_temperature
12391263
if plot and plot_temperature is not None:
12401264
if plot_temperature not in temperatures:
12411265
raise ValueError(

0 commit comments

Comments
 (0)