Skip to content
Snippets Groups Projects
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
Branches
Tags
4 merge requests!115V0.8.0 beta,!113V0.8.0,!103Merging Encyclopedia functionality with v0.8.0,!102First version of EncyclopediaNormalizer
Pipeline #70057 failed
Showing
with 135 additions and 116706 deletions
...@@ -537,6 +537,41 @@ class ElectronicBandStructure(MSection): ...@@ -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): class Properties(MSection):
m_def = Section( m_def = Section(
a_flask=dict(skip_none=True), a_flask=dict(skip_none=True),
...@@ -566,13 +601,8 @@ class Properties(MSection): ...@@ -566,13 +601,8 @@ class Properties(MSection):
formula unit. 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_band_structure = SubSection(sub_section=ElectronicBandStructure.m_def, repeats=False)
electronic_dos = SubSection(sub_section=ElectronicDOS.m_def, repeats=False)
class Encyclopedia(MSection): class Encyclopedia(MSection):
......
...@@ -26,9 +26,30 @@ import numpy as np ...@@ -26,9 +26,30 @@ import numpy as np
from matid import SymmetryAnalyzer from matid import SymmetryAnalyzer
import matid.geometry 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.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.normalizing import structure
from nomad.utils import hash from nomad.utils import hash
from nomad import config from nomad import config
...@@ -1682,7 +1703,27 @@ class PropertiesNormalizer(): ...@@ -1682,7 +1703,27 @@ class PropertiesNormalizer():
properties.m_add_sub_section(Properties.electronic_band_structure, band_structure) properties.m_add_sub_section(Properties.electronic_band_structure, band_structure)
def dos(self) -> None: 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: def elastic_constants_matrix(self) -> None:
pass pass
...@@ -1752,3 +1793,4 @@ class PropertiesNormalizer(): ...@@ -1752,3 +1793,4 @@ class PropertiesNormalizer():
self.context = ctx self.context = ctx
self.band_structure() self.band_structure()
self.energies() self.energies()
self.dos()
This diff is collapsed.
File added
File added
File added
File added
File added
File added
...@@ -191,3 +191,21 @@ def bands_polarized_gap_indirect() -> LocalBackend: ...@@ -191,3 +191,21 @@ def bands_polarized_gap_indirect() -> LocalBackend:
backend = parse_file((parser_name, filepath)) backend = parse_file((parser_name, filepath))
backend = run_normalize(backend) backend = run_normalize(backend)
return 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 ...@@ -23,7 +23,20 @@ from nomad.utils import hash
from nomad.parsing import LocalBackend from nomad.parsing import LocalBackend
from nomad.normalizing import structure from nomad.normalizing import structure
from nomad.metainfo.encyclopedia import Encyclopedia 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() ureg = UnitRegistry()
...@@ -508,3 +521,25 @@ def test_band_structure(bands_unpolarized_no_gap, bands_polarized_no_gap, bands_ ...@@ -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 == gap_ev
assert gap_up_ev == pytest.approx(0.956, 0.01) assert gap_up_ev == pytest.approx(0.956, 0.01)
assert gap_down_ev == pytest.approx(1.230, 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)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment