diff --git a/src/nomad_simulations/schema_packages/basis_set.py b/src/nomad_simulations/schema_packages/basis_set.py index 65a79093..4d1820c2 100644 --- a/src/nomad_simulations/schema_packages/basis_set.py +++ b/src/nomad_simulations/schema_packages/basis_set.py @@ -84,8 +84,11 @@ def cutoff_radius(self) -> pint.Quantity: """ Compute the cutoff radius for the plane-wave basis set, expressed in reciprocal coordinates. """ + if self.cutoff_energy is None: + return None m_e = const.m_e * ureg(const.unit('electron mass')) - return np.sqrt(2 * m_e * self.cutoff_energy) + h = const.h * ureg(const.unit('Planck constant')) + return np.sqrt(2 * m_e * self.cutoff_energy) / h def normalize(self, archive: EntryArchive, logger: BoundLogger) -> None: super(BasisSet, self).normalize(archive, logger) @@ -113,16 +116,14 @@ def set_cutoff_fractional(self, mt_r_min: pint.Quantity, logger: BoundLogger) -> Compute the fractional cutoff parameter for the interstitial plane waves in the LAPW family. This parameter is defined wrt the smallest muffin-tin region. """ - try: - self.cutoff_fractional = self.cutoff_radius / mt_r_min # unitless - except AttributeError: - logger.warning('`MuffinTin.cutoff_energy` must be defined.') - except ZeroDivisionError: - logger.warning('`MuffinTin.radius` cannot be zero.') - except TypeError: - logger.warning( - '`MuffinTin.radius` and `MuffinTin.cutoff_energy` must be defined.' - ) + reference_unit = 'angstrom' + if self.cutoff_fractional is not None: + logger.info('`APWPlaneWaveBasisSet.cutoff_fractional` already defined. Will not overwrite.') #! extend implementation + return + elif self.cutoff_energy is None or mt_r_min is None: + logger.warning('`APWPlaneWaveBasisSet.cutoff_energy` and `APWPlaneWaveBasisSet.radius` must both be defined. Aborting normalization step.') + return + self.cutoff_fractional = self.cutoff_radius.to(f'1 / {reference_unit}') * mt_r_min.to(reference_unit) class AtomCenteredFunction(ArchiveSection): diff --git a/tests/test_basis_set.py b/tests/test_basis_set.py new file mode 100644 index 00000000..9796de51 --- /dev/null +++ b/tests/test_basis_set.py @@ -0,0 +1,33 @@ +from nomad.units import ureg +import numpy as np +from . import logger + +from nomad_simulations.schema_packages.basis_set import APWPlaneWaveBasisSet + + +def test_cutoff(): + """Test the quantitative results when computing certain plane-wave cutoffs.""" + p_unit = '1 / angstrom' + ref_cutoff_radius = 1.823 * ureg(p_unit) + pw = APWPlaneWaveBasisSet(cutoff_energy=500 * ureg('eV')) + assert np.isclose(pw.cutoff_radius.to(p_unit).magnitude, ref_cutoff_radius.magnitude, atol=1e-3) # reference computed by ChatGPT 4o + + pw.set_cutoff_fractional(1 / ref_cutoff_radius, logger) + assert np.isclose(pw.cutoff_fractional, 1, rtol=1e-2) + +def test_cutoff_failure(): + """Test modes where `cutoff_fractional` is not computed.""" + # missing cutoff_energy + pw = APWPlaneWaveBasisSet() + pw.set_cutoff_fractional(ureg.angstrom, logger) + assert pw.cutoff_fractional is None + + # missing mt_radius + pw = APWPlaneWaveBasisSet(cutoff_energy=500 * ureg('eV')) + pw.set_cutoff_fractional(None, logger) + assert pw.cutoff_fractional is None + + # cutoff_fractional already set + pw = APWPlaneWaveBasisSet(cutoff_energy=500 * ureg('eV'), cutoff_fractional=1) + pw.set_cutoff_fractional(ureg.angstrom, logger) + assert pw.cutoff_fractional == 1