Skip to content

Commit

Permalink
- Extend APW structure test template
Browse files Browse the repository at this point in the history
- Cover more APW cases
- Migrate and touch up `generate_apw`
  • Loading branch information
ndaelman committed Aug 16, 2024
1 parent 9b61bdf commit 862f5ee
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 125 deletions.
65 changes: 64 additions & 1 deletion src/nomad_simulations/schema_packages/basis_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
from nomad.datamodel.metainfo.annotations import ELNAnnotation
from nomad.metainfo import MEnum, Quantity, SubSection
from nomad.units import ureg
import itertools
import numpy as np
import pint
from scipy import constants as const
from structlog.stdlib import BoundLogger
from typing import TYPE_CHECKING, Union
from typing import TYPE_CHECKING, Optional, Any

if TYPE_CHECKING:
from nomad.metainfo import Context, Section
Expand Down Expand Up @@ -442,3 +443,65 @@ def normalize(self, archive: EntryArchive, logger: BoundLogger) -> None:
logger.error(
'Expected a `APWPlaneWaveBasisSet` instance, but found none.'
)


def generate_apw(
species: dict[str, dict[str, Any]], cutoff: Optional[float] = None
) -> BasisSetContainer:
"""
Generate a mock APW basis set with the following structure:
.
├── 1 x plane-wave basis set
└── n x muffin-tin regions
└── l_max x l-channels
├── orbitals
└── local orbitals
from a dictionary
{
<species_name>: {
'r': <muffin-tin radius>,
'l_max': <maximum angular momentum>,
'orb_type': [<APWOrbital.type>],
'lo_type': [<APWLocalOrbital.type>],
}
}
"""

basis_set_components: list[BasisSet] = []
if cutoff is not None:
pw = APWPlaneWaveBasisSet(cutoff_energy=cutoff)
basis_set_components.append(pw)

for sp_name, sp in species.items():
sp['r'] = sp.get('r', None)
sp['l_max'] = sp.get('l_max', 0)
sp['orb_type'] = sp.get('orb_type', [])
sp['lo_type'] = sp.get('lo_type', [])

basis_set_components.extend(
[
MuffinTinRegion(
species_scope=AtomsState(
chemical_symbol=sp_name
), # TODO: extend to search through a model_system
radius=sp['r'],
l_max=sp['l_max'],
l_channels=[
APWLChannel(
name=l,
orbitals=list(
itertools.chain(
(APWOrbital(type=orb) for orb in sp['orb_type']),
(APWLocalOrbital(type=lo) for lo in sp['lo_type']),
)
),
)
for l in range(sp['l_max'] + 1)
],
)

]
)

return BasisSetContainer(basis_set_components=basis_set_components)
181 changes: 115 additions & 66 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,69 +404,118 @@ def k_space_simulation() -> Simulation:
return generate_k_space_simulation()


apw = {
'basis_set_components': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWPlaneWaveBasisSet',
'cutoff_energy': 500.0,
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.MuffinTinRegion',
'radius': 1.823,
'l_max': 2,
'l_channels': [
{
'name': 0,
'orbitals': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'apw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'lapw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWLocalOrbital',
'type': 'lo',
},
],
},
{
'name': 1,
'orbitals': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'apw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'lapw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWLocalOrbital',
'type': 'lo',
},
],
},
{
'name': 2,
'orbitals': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'apw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'lapw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWLocalOrbital',
'type': 'lo',
},
],
},
],
},
]
}
refs_apw = [
{},
{
'basis_set_components': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWPlaneWaveBasisSet',
'cutoff_energy': 500.0,
},
]
},
{
'basis_set_components': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.MuffinTinRegion',
'radius': 1.823,
'l_max': 2,
'l_channels': [
{
'name': 0,
'orbitals': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'apw',
},
],
},
{
'name': 1,
'orbitals': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'apw',
},
],
},
{
'name': 2,
'orbitals': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'apw',
},
],
},
],
},
]
},
{
'basis_set_components': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWPlaneWaveBasisSet',
'cutoff_energy': 500.0,
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.MuffinTinRegion',
'radius': 1.823,
'l_max': 2,
'l_channels': [
{
'name': 0,
'orbitals': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'apw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'lapw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWLocalOrbital',
'type': 'lo',
},
],
},
{
'name': 1,
'orbitals': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'apw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'lapw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWLocalOrbital',
'type': 'lo',
},
],
},
{
'name': 2,
'orbitals': [
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'apw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWOrbital',
'type': 'lapw',
},
{
'm_def': 'nomad_simulations.schema_packages.basis_set.APWLocalOrbital',
'type': 'lo',
},
],
},
],
},
]
},
]
78 changes: 20 additions & 58 deletions tests/test_basis_set.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import itertools
from typing import Any, Optional

import pytest
from . import logger
from nomad.units import ureg
import numpy as np
import pytest
from typing import Optional, Any

from tests.conftest import apw
from tests.conftest import refs_apw

from nomad_simulations.schema_packages.basis_set import (
APWBaseOrbital,
Expand All @@ -16,6 +16,7 @@
BasisSet,
BasisSetContainer,
MuffinTinRegion,
generate_apw,
)


Expand Down Expand Up @@ -50,57 +51,18 @@ def test_cutoff_failure():
assert pw.cutoff_fractional == 1


@pytest.mark.skip(reason='This function is not meant to be tested directly')
def generate_apw(
species: dict[str, dict[str, Any]], cutoff: Optional[float] = None
) -> BasisSetContainer:
"""
Generate a mock APW basis set with the following structure:
.
├── 1 x plane-wave basis set
└── n x muffin-tin regions
└── l_max x l-channels
├── orbitals
└── local orbitals
"""
basis_set_components: list[BasisSet] = []
if cutoff is not None:
pw = APWPlaneWaveBasisSet(cutoff_energy=cutoff)
basis_set_components.append(pw)

for sp_name, sp in species.items():
l_max = sp['l_max']
mt = MuffinTinRegion(
radius=sp['r'],
l_max=l_max,
l_channels=[
APWLChannel(
name=l,
orbitals=list(
itertools.chain(
(APWOrbital(type=orb) for orb in sp['orb_type']),
(APWLocalOrbital(type=lo) for lo in sp['lo_type']),
)
),
)
for l in range(l_max + 1)
],
)
basis_set_components.append(mt)

return BasisSetContainer(basis_set_components=basis_set_components)


def test_full_apw():
ref_apw = generate_apw(
{
'A': {
'r': 1.823,
'l_max': 2,
'orb_type': ['apw', 'lapw'],
'lo_type': ['lo'],
}
},
cutoff=500,
)
assert ref_apw.m_to_dict() == apw
@pytest.mark.parametrize(
'ref_index, species_def, cutoff',
[
(0, {}, None),
(1, {}, 500.0),
(2, {'H': {'r': 1, 'l_max': 2, 'orb_type': ['apw']}}, 500.0),
],
)
def test_full_apw(
ref_index: int, species_def: dict[str, dict[str, Any]], cutoff: Optional[float]
):
"""Test the composite structure of APW basis sets."""
assert (
generate_apw(species_def, cutoff=cutoff).m_to_dict() == refs_apw[ref_index]
) # TODO: add normalization?

1 comment on commit 862f5ee

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/nomad_simulations
   __init__.py4250%3–4
   _version.py11282%5–6
src/nomad_simulations/schema_packages
   __init__.py14286%53–55
   atoms_state.py1902189%31–33, 219–222, 246, 301–302, 370–371, 373, 555, 567–568, 629–633, 648–652, 659
   basis_set.py1566856%14, 86, 92–93, 155, 208–210, 270–274, 304–322, 325–327, 364–367, 370, 401–416, 422–427, 430–443
   general.py75791%29–30, 98, 162, 272–273, 283
   model_method.py2657771%28–30, 189–192, 195–202, 294–295, 315, 336–355, 371–397, 400–417, 771, 782, 824–831, 869, 888, 968, 1025, 1100, 1214
   model_system.py2612292%43–45, 520–523, 570–577, 751–752, 973–977, 983–984, 992–993, 998, 1021
   numerical_settings.py2596276%30–32, 165, 235, 237–238, 241–244, 248–249, 256–259, 268–271, 275–278, 280–283, 288–291, 297–300, 484–511, 586, 621–624, 648, 651, 696, 698–701, 705, 709, 756, 760–781, 836–837, 904
   outputs.py1151091%27–28, 247–250, 290–293, 318, 320, 357, 376
   physical_property.py102793%38–40, 220, 349–351
   variables.py651183%26–28, 116, 139, 159–160, 163, 185, 208, 228
src/nomad_simulations/schema_packages/properties
   band_gap.py51590%26–28, 153–154
   band_structure.py1112280%27–29, 249–282, 295, 302, 338–339, 342
   energies.py36975%25–27, 54, 75, 100, 121, 131, 140
   fermi_surface.py17476%25–27, 58
   forces.py22673%26–28, 55, 75, 98
   hopping_matrix.py29583%25–27, 75, 110
   permittivity.py48883%25–27, 115–123
   spectral_profile.py25612452%27–29, 75–78, 113–116, 217–318, 374–386, 411–414, 434, 439–442, 484–520, 544, 591–594, 610–611, 616–622
   thermodynamics.py751876%25–27, 53, 74, 90, 99, 108, 119, 128, 155, 165, 175, 195, 211, 236, 252, 277
src/nomad_simulations/schema_packages/utils
   utils.py681479%26–29, 79–88, 97–98, 103, 106
TOTAL224050677% 

Tests Skipped Failures Errors Time
326 0 💤 29 ❌ 0 🔥 6.347s ⏱️

Please sign in to comment.