Commit 279eec30 authored by Lauri Himanen's avatar Lauri Himanen
Browse files

Added metainfo and normalization for DOS, compressed test files, added regtests for DOS.

parent 4daf5de5
Pipeline #70057 failed with stages
in 16 minutes and 3 seconds
......@@ -537,6 +537,41 @@ class ElectronicBandStructure(MSection):
)
class ElectronicDOS(MSection):
m_def = Section(
a_flask=dict(skip_none=True),
a_elastic=dict(type=InnerDoc),
description="""
Store the electronic density of states (DOS).
"""
)
fermi_level = Quantity(
type=float,
unit=units.J,
description="""
Fermi level reported for the density of states.
"""
)
energies = Quantity(
type=np.dtype('f8'),
shape=["1..*"],
unit=units.J,
description="""
Array containing the set of discrete energy values with respect to the
top of the valence band for the density of states (DOS).
"""
)
values = Quantity(
type=np.dtype('f8'),
shape=["1..2", "1..*"],
unit=units.J**(-1),
description="""
Values (number of states for a given energy, the set of discrete energy
values is given in dos_energies) of density of states.
"""
)
class Properties(MSection):
m_def = Section(
a_flask=dict(skip_none=True),
......@@ -566,13 +601,8 @@ class Properties(MSection):
formula unit.
"""
)
dos = Quantity(
type=str,
description="""
A JSON encoded string that contains the density of states.
"""
)
electronic_band_structure = SubSection(sub_section=ElectronicBandStructure.m_def, repeats=False)
electronic_dos = SubSection(sub_section=ElectronicDOS.m_def, repeats=False)
class Encyclopedia(MSection):
......
......@@ -26,9 +26,30 @@ import numpy as np
from matid import SymmetryAnalyzer
import matid.geometry
from nomad.normalizing.normalizer import Normalizer, s_scc, s_system, s_method, s_frame_sequence, r_frame_sequence_to_sampling, s_sampling_method, r_frame_sequence_local_frames
from nomad.normalizing.normalizer import (
Normalizer,
s_scc,
s_system,
s_method,
s_frame_sequence,
r_frame_sequence_to_sampling,
s_sampling_method,
r_frame_sequence_local_frames,
)
from nomad.metainfo.encyclopedia import (
Encyclopedia,
Material,
Method,
Properties,
RunType,
WyckoffSet,
WyckoffVariables,
ElectronicBandStructure,
ElectronicDOS,
BandGap,
BandSegment,
)
from nomad.normalizing.settingsbasisset import SettingsBasisSet
from nomad.metainfo.encyclopedia import Encyclopedia, Material, Method, Properties, RunType, WyckoffSet, WyckoffVariables, ElectronicBandStructure, BandGap, BandSegment
from nomad.normalizing import structure
from nomad.utils import hash
from nomad import config
......@@ -1682,7 +1703,27 @@ class PropertiesNormalizer():
properties.m_add_sub_section(Properties.electronic_band_structure, band_structure)
def dos(self) -> None:
pass
dos_sections = self.backend.get('section_dos')
if dos_sections:
# There should be only one section dos
dos_data = dos_sections[0]
dos_kind = dos_data.get('dos_kind', None)
# dos_kind might not be given for electronic DOS
if dos_kind is None:
self.logger.warning("dos_kind is not specified, assuming electronic DOS")
elif dos_kind == 'vibrational':
return None
# Use only normalized data
dos_energies = dos_data.get('dos_energies_normalized')
dos_values = dos_data.get('dos_values')
if dos_energies is not None and dos_values is not None:
sec_enc = self.backend.get_mi2_section(Encyclopedia.m_def)
properties = sec_enc.properties
dos = properties.m_create(ElectronicDOS)
dos.energies = dos_energies
dos.values = dos_values
def elastic_constants_matrix(self) -> None:
pass
......@@ -1752,3 +1793,4 @@ class PropertiesNormalizer():
self.context = ctx
self.band_structure()
self.energies()
self.dos()
......@@ -191,3 +191,21 @@ def bands_polarized_gap_indirect() -> LocalBackend:
backend = parse_file((parser_name, filepath))
backend = run_normalize(backend)
return backend
@pytest.fixture(scope='session')
def dos_polarized_vasp() -> LocalBackend:
parser_name = "parsers/vasp"
filepath = "tests/data/normalizers/dos/polarized_vasp/vasprun.xml.relax2.xz"
backend = parse_file((parser_name, filepath))
backend = run_normalize(backend)
return backend
@pytest.fixture(scope='session')
def dos_unpolarized_vasp() -> LocalBackend:
parser_name = "parsers/vasp"
filepath = "tests/data/normalizers/dos/unpolarized_vasp/vasprun.xml.xz"
backend = parse_file((parser_name, filepath))
backend = run_normalize(backend)
return backend
......@@ -23,7 +23,20 @@ from nomad.utils import hash
from nomad.parsing import LocalBackend
from nomad.normalizing import structure
from nomad.metainfo.encyclopedia import Encyclopedia
from tests.normalizing.conftest import run_normalize_for_structure, geometry_optimization, molecular_dynamics, phonon, two_d, bulk, bands_unpolarized_no_gap, bands_polarized_no_gap, bands_unpolarized_gap_indirect, bands_polarized_gap_indirect # pylint: disable=unused-import
from tests.normalizing.conftest import ( # pylint: disable=unused-import
run_normalize_for_structure,
geometry_optimization,
molecular_dynamics,
phonon,
two_d,
bulk,
bands_unpolarized_no_gap,
bands_polarized_no_gap,
bands_unpolarized_gap_indirect,
bands_polarized_gap_indirect,
dos_unpolarized_vasp,
dos_polarized_vasp,
)
ureg = UnitRegistry()
......@@ -508,3 +521,25 @@ def test_band_structure(bands_unpolarized_no_gap, bands_polarized_no_gap, bands_
assert gap_up_ev == gap_ev
assert gap_up_ev == pytest.approx(0.956, 0.01)
assert gap_down_ev == pytest.approx(1.230, 0.01)
def test_dos(dos_unpolarized_vasp, dos_polarized_vasp):
def test_generic(dos, n_channels):
"""Generic tests for DOS data."""
assert len(dos.energies.shape) == 1
assert len(dos.values.shape) == 2
assert dos.values.shape[1] == dos.energies.shape[0]
assert dos.values.shape[0] == n_channels
# Unpolarized
enc = dos_unpolarized_vasp.get_mi2_section(Encyclopedia.m_def)
properties = enc.properties
dos = properties.electronic_dos
test_generic(dos, n_channels=1)
# Polarized
enc = dos_polarized_vasp.get_mi2_section(Encyclopedia.m_def)
properties = enc.properties
dos = properties.electronic_dos
test_generic(dos, n_channels=2)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment