Commit f0661ffa authored by Lauri Himanen's avatar Lauri Himanen
Browse files

Removed section_k_band normalized, as it can be simply constructucted from...

Removed section_k_band normalized, as it can be simply constructucted from section_k_band with a shift stored in energy_reference_highest_occupied. Made section_encyclopedia to store references into the band structure instead of constructing own copy.
parent d2b89c93
......@@ -4,6 +4,7 @@ from nomad.metainfo import ( # pylint: disable=unused-import
MSection, MCategory, Category, Package, Quantity, Section, SubSection, SectionProxy,
Reference, MEnum
)
from elasticsearch_dsl import InnerDoc
from nomad.metainfo.legacy import LegacyDefinition
......@@ -2025,111 +2026,6 @@ class section_gaussian_basis_group(MSection):
a_legacy=LegacyDefinition(name='number_of_gaussian_basis_group_exponents'))
# class section_k_band_normalized(MSection):
# '''
# This section stores information on a normalized $k$-band (electronic band structure)
# evaluation along one-dimensional pathways in the $k$ (reciprocal) space given in
# section_k_band_segment. Eigenvalues calculated at the actual $k$-mesh used for
# energy_total evaluations, can be found in the section_eigenvalues section.
# '''
# m_def = Section(validate=False, a_legacy=LegacyDefinition(name='section_k_band_normalized'))
# k_band_path_normalized_is_standard = Quantity(
# type=bool,
# shape=[],
# description='''
# If the normalized path is along the default path defined in W. Setyawan and S.
# Curtarolo, [Comput. Mater. Sci. **49**, 299-312
# (2010)](http://dx.doi.org/10.1016/j.commatsci.2010.05.010).
# ''',
# a_legacy=LegacyDefinition(name='k_band_path_normalized_is_standard'))
# section_k_band_segment_normalized = SubSection(
# sub_section=SectionProxy('section_k_band_segment_normalized'),
# repeats=True,
# a_legacy=LegacyDefinition(name='section_k_band_segment_normalized'))
# class section_k_band_segment_normalized(MSection):
# '''
# Section collecting the information on a normalized $k$-band segment. This section
# stores band structures along a one-dimensional pathway in the $k$ (reciprocal) space.
# Eigenvalues calculated at the actual $k$-mesh used for energy_total evaluations are
# defined in section_eigenvalues and the band structures are represented as third-order
# tensors: one dimension for the spin channels, one for the sequence of $k$ points for
# the segment (given in number_of_k_points_per_segment), and one for the sequence of
# eigenvalues at a given $k$ point. The values of the $k$ points in each segment are
# stored in band_k_points. The energies and occupation for each eigenstate, at each $k$
# point, segment, and spin channel are stored in band_energies and band_occupations,
# respectively. The labels for the segment are specified in band_segm_labels.
# '''
# m_def = Section(validate=False, a_legacy=LegacyDefinition(name='section_k_band_segment_normalized'))
# band_energies_normalized = Quantity(
# type=np.dtype(np.float64),
# shape=['number_of_spin_channels', 'number_of_normalized_k_points_per_segment', 'number_of_normalized_band_segment_eigenvalues'],
# unit='joule',
# description='''
# $k$-dependent energies of the electronic band segment (electronic band structure)
# with respect to the top of the valence band. This is a third-order tensor, with
# one dimension used for the spin channels, one for the $k$ points for each segment,
# and one for the eigenvalue sequence.
# ''',
# a_legacy=LegacyDefinition(name='band_energies_normalized'))
# band_k_points_normalized = Quantity(
# type=np.dtype(np.float64),
# shape=['number_of_normalized_k_points_per_segment', 3],
# description='''
# Fractional coordinates of the $k$ points (in the basis of the reciprocal-lattice
# vectors) for which the normalized electronic energies are given.
# ''',
# a_legacy=LegacyDefinition(name='band_k_points_normalized'))
# band_occupations_normalized = Quantity(
# type=np.dtype(np.float64),
# shape=['number_of_spin_channels', 'number_of_normalized_k_points_per_segment', 'number_of_normalized_band_segment_eigenvalues'],
# description='''
# Occupation of the $k$-points along the normalized electronic band. The size of the
# dimensions of this third-order tensor are the same as for the tensor in
# band_energies.
# ''',
# a_legacy=LegacyDefinition(name='band_occupations_normalized'))
# band_segm_labels_normalized = Quantity(
# type=str,
# shape=[2],
# description='''
# Start and end labels of the points in the segment (one-dimensional pathways)
# sampled in the $k$-space, using the conventional symbols, e.g., Gamma, K, L. The
# coordinates (fractional, in the reciprocal space) of the start and end points for
# each segment are given in band_segm_start_end_normalized
# ''',
# a_legacy=LegacyDefinition(name='band_segm_labels_normalized'))
# band_segm_start_end_normalized = Quantity(
# type=np.dtype(np.float64),
# shape=[2, 3],
# description='''
# Fractional coordinates of the start and end point (in the basis of the reciprocal
# lattice vectors) of the segment sampled in the $k$ space. The conventional symbols
# (e.g., Gamma, K, L) of the same points are given in band_segm_labels
# ''',
# a_legacy=LegacyDefinition(name='band_segm_start_end_normalized'))
# number_of_normalized_k_points_per_segment = Quantity(
# type=int,
# shape=[],
# description='''
# Gives the number of $k$ points in the segment of the normalized band structure
# (see section_k_band_segment_normalized).
# ''',
# a_legacy=LegacyDefinition(name='number_of_normalized_k_points_per_segment'))
class section_k_band_segment(MSection):
'''
Section collecting the information on a $k$-band or $q$-band segment. This section
......@@ -2215,33 +2111,38 @@ class section_band_gap(MSection):
'''
This section stores information for a band gap within a band structure.
'''
m_def = Section(validate=False)
m_def = Section(validate=False, a_legacy=LegacyDefinition(name='section_band_gap'))
value = Quantity(
type=float,
unit="joule",
description="""
Band gap energy.
"""
""",
a_legacy=LegacyDefinition(name='value')
)
type = Quantity(
type=MEnum("direct", "indirect"),
description="""
Type of band gap.
"""
""",
a_legacy=LegacyDefinition(name='type')
)
conduction_band_min_energy = Quantity(
type=float,
unit="joule",
description="""
Conduction band minimum energy.
"""
""",
a_legacy=LegacyDefinition(name='conduction_band_min_energy')
)
valence_band_max_energy = Quantity(
type=float,
unit="joule",
description="""
Valence band maximum energy.
"""
""",
a_legacy=LegacyDefinition(name='valence_band_max_energy')
)
conduction_band_min_k_point = Quantity(
type=np.dtype(np.float64),
......@@ -2249,7 +2150,8 @@ class section_band_gap(MSection):
unit="1 / meter",
description="""
Coordinate of the conduction band minimum in k-space.
"""
""",
a_legacy=LegacyDefinition(name='conduction_band_min_k_point')
)
valence_band_max_k_point = Quantity(
type=np.dtype(np.float64),
......@@ -2257,7 +2159,8 @@ class section_band_gap(MSection):
unit="1 / meter",
description="""
Coordinate of the valence band minimum in k-space.
"""
""",
a_legacy=LegacyDefinition(name='valence_band_max_k_point')
)
......@@ -2279,21 +2182,14 @@ class section_k_band(MSection):
''',
a_legacy=LegacyDefinition(name='band_structure_kind'))
fermi_level = Quantity(
type=float,
unit="joule",
description="""
Fermi level reported for the band structure.
"""
)
reciprocal_cell = Quantity(
type=np.dtype(np.float64),
shape=[3, 3],
unit="1 / meter",
description="""
The reciprocal cell within which the band structure is calculated.
"""
""",
a_legacy=LegacyDefinition(name='reciprocal_cell')
)
brillouin_zone = Quantity(
......@@ -2309,14 +2205,27 @@ class section_k_band(MSection):
"vertices": [[3, 2, 1], ...]
"faces": [[0, 1, 2, 3], ...]
}
"""
""",
a_legacy=LegacyDefinition(name='brillouin_zone')
)
band_gap = SubSection(sub_section=section_band_gap.m_def, repeats=False)
section_band_gap = SubSection(
sub_section=section_band_gap.m_def,
repeats=False,
a_legacy=LegacyDefinition(name='section_band_gap')
)
band_gap_spin_up = SubSection(sub_section=section_band_gap.m_def, repeats=False)
section_band_gap_spin_up = SubSection(
sub_section=section_band_gap.m_def,
repeats=False,
a_legacy=LegacyDefinition(name='section_band_gap')
)
band_gap_spin_down = SubSection(sub_section=section_band_gap.m_def, repeats=False)
section_band_gap_spin_down = SubSection(
sub_section=section_band_gap.m_def,
repeats=False,
a_legacy=LegacyDefinition(name='section_band_gap')
)
is_standard_path = Quantity(
type=bool,
......@@ -2324,7 +2233,8 @@ class section_k_band(MSection):
Boolean indicating whether the path follows the standard path for this
cell. The AFLOW standard by Setyawan and Curtarolo is used
(https://doi.org/10.1016/j.commatsci.2010.05.010).
"""
""",
a_legacy=LegacyDefinition(name='is_standard_path')
)
section_k_band_segment = SubSection(
......
import numpy as np
from elasticsearch_dsl import InnerDoc
from nomad.metainfo import MSection, Section, SectionProxy, SubSection, Quantity, Reference, MEnum, units
from nomad.datamodel.metainfo.public import section_dos, section_k_band
class WyckoffVariables(MSection):
......@@ -408,199 +409,6 @@ class Calculation(MSection):
)
# class BandGap(MSection):
# m_def = Section(
# a_flask=dict(skip_none=True),
# a_elastic=dict(type=InnerDoc),
# description="""
# Stores information related to a band gap that has bee identified within
# the band structure.
# """
# )
# value = Quantity(
# type=float,
# unit=units.J,
# description="""
# Band gap energy.
# """
# )
# type = Quantity(
# type=MEnum("direct", "indirect"),
# description="""
# Type of band gap.
# """
# )
# conduction_band_min_energy = Quantity(
# type=float,
# unit=units.J,
# description="""
# Conduction band minimum energy.
# """
# )
# valence_band_max_energy = Quantity(
# type=float,
# unit=units.J,
# description="""
# Valence band maximum energy.
# """
# )
# conduction_band_min_k_point = Quantity(
# type=np.dtype(np.float64),
# shape=[3],
# unit=units.m**(-1),
# description="""
# Coordinate of the conduction band minimum in k-space.
# """
# )
# valence_band_max_k_point = Quantity(
# type=np.dtype(np.float64),
# shape=[3],
# unit=units.m**(-1),
# description="""
# Coordinate of the valence band minimum in k-space.
# """
# )
# class BandSegment(MSection):
# m_def = Section(
# a_flask=dict(skip_none=True),
# a_elastic=dict(type=InnerDoc),
# description="""
# Represents a continuous path segment starting from a specific k-point
# and ending in another.
# """
# )
# energies = Quantity(
# type=np.dtype(np.float64),
# shape=["1..2", "1..*", "1..*"],
# unit=units.m**(-1),
# description="""
# The energies of the bands as a 3D array with size [n_spin_channels,
# n_bands, n_k_points]. By default the spin down channel is given first
# and the spin up channel is second.
# """
# )
# k_points = Quantity(
# type=np.dtype(np.float64),
# shape=["1..*", 3],
# unit=units.m**(-1),
# description="""
# Path of the band structure in reciprocal space.
# """
# )
# labels = Quantity(
# type=np.dtype('str'),
# shape=[1],
# description="""
# The start end end labels for the k points in this segment.
# """
# )
# class ElectronicBandStructure(MSection):
# m_def = Section(
# a_flask=dict(skip_none=True),
# a_elastic=dict(type=InnerDoc),
# description="""
# Stores information related to an electronic band structure.
# """
# )
# scc_index = Quantity(
# type=int,
# description="""
# Index of the single configuration calculation that contains the band
# structure.
# """
# )
# fermi_level = Quantity(
# type=float,
# unit=units.J,
# description="""
# Fermi level reported for the band structure.
# """
# )
# reciprocal_cell = Quantity(
# type=np.dtype(np.float64),
# shape=[3, 3],
# unit=units.m**(-1),
# description="""
# The reciprocal cell within which the band structure is calculated.
# """
# )
# brillouin_zone = Quantity(
# type=str,
# description="""
# The Brillouin zone that corresponds to the reciprocal cell used in the
# band calculation. The Brillouin Zone is defined as a list of vertices
# and facets that are encoded with JSON. The vertices are 3D points in
# the reciprocal space, and facets are determined by a chain of vertice
# indices, with a right-hand ordering determining the surface normal
# direction.
# {
# "vertices": [[3, 2, 1], ...]
# "faces": [[0, 1, 2, 3], ...]
# }
# """
# )
# band_gap = SubSection(sub_section=BandGap.m_def, repeats=False)
# band_gap_spin_up = SubSection(sub_section=BandGap.m_def, repeats=False)
# band_gap_spin_down = SubSection(sub_section=BandGap.m_def, repeats=False)
# segments = SubSection(sub_section=BandSegment.m_def, repeats=True)
# is_standard_path = Quantity(
# type=bool,
# description="""
# Boolean indicating whether the path follows the standard path for this
# cell. The AFLOW standard by Setyawan and Curtarolo is used
# (https://doi.org/10.1016/j.commatsci.2010.05.010).
# """
# )
# class ElectronicDOS(MSection):
# m_def = Section(
# a_flask=dict(skip_none=True),
# a_elastic=dict(type=InnerDoc),
# description="""
# Stores the electronic density of states (DOS).
# """
# )
# scc_index = Quantity(
# type=int,
# description="""
# Index of the single configuration calculation that contains the density
# of states.
# """
# )
# fermi_level = Quantity(
# type=np.dtype(np.float64),
# unit=units.J,
# description="""
# Fermi level reported for the density of states.
# """
# )
# energies = Quantity(
# type=np.dtype(np.float64),
# 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(np.float64),
# 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. The values are
# given as states/energy.
# """
# )
class Properties(MSection):
m_def = Section(
a_flask=dict(skip_none=True),
......@@ -630,31 +438,29 @@ class Properties(MSection):
Code dependent energy values, corrected to be per formula unit.
"""
)
# electronic_band_structure = SubSection(sub_section=ElectronicBandStructure.m_def, repeats=False)
# electronic_dos = SubSection(sub_section=ElectronicDOS.m_def, repeats=False)
electronic_band_structure = Quantity(
type=Reference(SectionProxy('section_k_band')),
type=Reference(section_k_band.m_def),
shape=[],
description="""
Reference to an electronic band structure.
"""
)
electronic_dos = Quantity(
type=Reference(SectionProxy('section_dos')),
type=Reference(section_dos.m_def),
shape=[],
description="""
Reference to an electronic density of states.
"""
)
phonon_band_structure = Quantity(
type=Reference(SectionProxy('section_k_band')),
type=Reference(section_k_band.m_def),
shape=[],
description="""
Reference to a phonon band structure.
"""
)
phonon_dos = Quantity(
type=Reference(SectionProxy('section_dos')),
type=Reference(section_dos.m_def),
shape=[],
description="""
Reference to a phonon density of states.
......
......@@ -331,7 +331,7 @@ class Reference(DataType):
def resolve(self, proxy) -> 'MSection':
'''
Resolve the given proxy. The proxy is gurantied to have a context and
Resolve the given proxy. The proxy is guaranteed to have a context and
will to be not yet resolved.
'''
return proxy.m_proxy_section.m_resolve(proxy.m_proxy_url)
......
......@@ -220,6 +220,7 @@ class EncyclopediaNormalizer(Normalizer):
super().normalize(logger)
# Initialise metainfo structure
# sec_enc = self._backend.openSection("section_encyclopedia", return_section=True)
sec_enc = self.backend.entry_archive.m_create(section_encyclopedia)
material = sec_enc.m_create(Material)
method = sec_enc.m_create(Method)
......
......@@ -21,12 +21,11 @@ from nomad.metainfo.encyclopedia import (
Calculation,
Properties,
Material,
ElectronicBandStructure,
BandGap,
)
from nomad.parsing.legacy import Backend
from nomad.metainfo import Section
from nomad.normalizing.encyclopedia.context import Context
from nomad.datamodel.metainfo.public import section_k_band, section_band_gap
from nomad import atomutils
from nomad import config
......@@ -41,7 +40,7 @@ class PropertiesNormalizer():
self.backend = backend
self.logger = logger
def get_reciprocal_cell(self, band_structure: ElectronicBandStructure, prim_atoms: Atoms, orig_atoms: Atoms):
def get_reciprocal_cell(self, band_structure: section_k_band, prim_atoms: Atoms, orig_atoms: Atoms):
"""A reciprocal cell for this calculation. If the original unit cell is
not a primitive one, then we will use the one given by spglib.
......@@ -74,18 +73,21 @@ class PropertiesNormalizer():
band_structure.reciprocal_cell = recip_cell
def get_band_gaps(self, band_structure: ElectronicBandStructure, energies: np.array, path: np.array) -> None:
def get_band_gaps(self, band_structure: section_k_band, energies: np.array, path: np.array, valence_band_maximum: np.array) -> None:
"""Given the band structure and fermi level, calculates the band gap
for spin channels and also reports the total band gap as the minum gap
found.
"""
# Handle spin channels separately to find gaps for spin up and down
reciprocal_cell = band_structure.reciprocal_cell.magnitude
fermi_level = band_structure.fermi_level
n_channels = energies.shape[0]
gaps: List[BandGap] = [None, None]
gaps: List[section_band_gap] = [None, None]
for channel in range(n_channels):
if n_channels == 1:
vbm = valence_band_maximum
else:
vbm = valence_band_maximum[channel]
channel_energies = energies[channel, :, :]
lower_defined = False
upper_defined = False
......@@ -108,17 +110,17 @@ class PropertiesNormalizer():
# If any of the bands band crosses the Fermi level, there is no
# band gap
if band_min_tol <= fermi_level and band_max_tol >= fermi_level:
if band_min_tol <= vbm and band_max_tol >= vbm:
break
# Whole band below Fermi level, save the current highest
# occupied band point
elif band_min_tol <= fermi_level and band_max_tol <= fermi_level:
elif band_min_tol <= vbm and band_max_tol <= vbm:
gap_lower_energy = band_max
gap_lower_idx = band_maxima_idx[band_idx]
lower_defined = True
# Whole band above Fermi level, save the current lowest
# unoccupied band point
elif band_min_tol >= fermi_level:
elif band_min_tol >= vbm:
gap_upper_energy = band_min
gap_upper_idx = band_minima_idx[band_idx]
upper_defined = True
......@@ -136,7 +138,7 @@ class PropertiesNormalizer():
k_point_distance = self.get_k_space_distance(reciprocal_cell, k_point_lower, k_point_upper)
is_direct_gap = k_point_distance <= config.normalize.k_space_precision
gap = BandGap()
gap = section_band_gap()
gap.type = "direct" if is_direct_gap else "indirect"
gap.value = float(gap_upper_energy - gap_lower_energy)
gap.conduction_band_min_k_point = k_point_upper
......@@ -148,25 +150,25 @@ class PropertiesNormalizer():
# For unpolarized calculations we simply report the gap if it is found.
if n_channels == 1:
if gaps[0] is not None:
band_structure.m_add_sub_section(ElectronicBandStructure.band_gap, gaps[0])
band_structure.m_add_sub_section(section_k_band.section_band_gap, gaps[0])
# For polarized calculations we report the gap separately for both
# channels. Also we report the smaller gap as the the total gap for the
# calculation.
elif n_channels == 2:
if gaps[0] is not None:
band_structure.m_add_sub_section(ElectronicBandStructure.band_gap_spin_up, gaps[0])
band_structure.m_add_sub_section(section_k_band.section_band_gap_spin_up, gaps[0])
if gaps[1] is not None:
band_structure.m_add_sub_section(ElectronicBandStructure.band_gap_spin_down, gaps[1])
band_structure.m_add_sub_section(section_k_band.section_band_gap_spin_down, gaps[1])
if gaps[0] is not None and gaps[1] is not None:
if gaps[0].value <= gaps[1].value:
band_structure.m_add_sub_section(ElectronicBandStructure.band_gap, gaps[0])
band_structure.m_add_sub_section(section_k_band.section_band_gap, gaps[0])
else:
band_structure.m_add_sub_section(ElectronicBandStructure.band_gap, gaps[1])
band_structure.m_add_sub_section(section_k_band.section_band_gap, gaps[1])
else:
if gaps[0] is not None:
band_structure.m_add_sub_section(ElectronicBandStructure.band_gap, gaps[0])
band_structure.m_add_sub_section(section_k_band.section_band_gap, gaps[0])
elif gaps[1] is not None:
band_structure.m_add_sub_section(ElectronicBandStructure.band_gap, gaps[1])
band_structure.m_add_sub_section(section_k_band.section_band_gap, gaps[1])
def get_k_space_distance(self, reciprocal_cell: np.array, point1: np.array, point2: np.array) -> float:
"""Used to calculate the Euclidean dis