Commit 68f3a587 authored by Lauri Himanen's avatar Lauri Himanen
Browse files

Re-added metainfo and parsing for normalized bands.

parent 63874e7c
Pipeline #73788 passed with stages
in 20 minutes and 6 seconds
Subproject commit c0d791a470e9cd6e2836c596691d8d8a837abcd8
Subproject commit 1e26aeaf2bbb27826075d02c0a80c2b04f482d20
......@@ -2026,6 +2026,111 @@ 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
......@@ -4338,6 +4443,11 @@ class section_single_configuration_calculation(MSection):
repeats=True,
a_legacy=LegacyDefinition(name='section_energy_van_der_Waals'))
section_k_band_normalized = SubSection(
sub_section=SectionProxy('section_k_band_normalized'),
repeats=True,
a_legacy=LegacyDefinition(name='section_k_band_normalized'))
section_k_band = SubSection(
sub_section=SectionProxy('section_k_band'),
repeats=True,
......
......@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import ase
import json
import numpy as np
from typing import List
......@@ -26,8 +25,8 @@ class BandStructureNormalizer(Normalizer):
"""Normalizer with the following responsibilities:
- Calculates band gap(s) if present (section_band_gap, section_band_gap_spin_up, section_band_gap_spin_down).
- Creates labels for special points within the band path (band_path_labels).
- Determines if the path is a standard one or not (is_standard)
- TODO: Creates labels for special points within the band path (band_path_labels)
- TODO: Determines if the path is a standard one or not (is_standard)
"""
def normalize(self, logger=None) -> None:
# Setup logger
......@@ -54,8 +53,6 @@ class BandStructureNormalizer(Normalizer):
self.add_reciprocal_cell(band, system)
self.add_brillouin_zone(band)
self.add_band_gaps(band, valence_band_maximum)
self.add_path_labels(band, system)
self.add_is_standard(band)
def add_reciprocal_cell(self, band: section_k_band, system: section_system):
"""A reciprocal cell for this calculation. If the original unit cell is
......@@ -255,44 +252,3 @@ class BandStructureNormalizer(Normalizer):
band.m_add_sub_section(section_k_band.section_band_gap, gaps[0])
elif gaps[1] is not None:
band.m_add_sub_section(section_k_band.section_band_gap, gaps[1])
def add_path_labels(self, band: section_k_band, system: section_system) -> None:
"""Adds special high symmmetry point labels to the band path.
"""
try:
cell = system.lattice_vectors.magnitude
except Exception:
self.logger.info("Could not resolve path labels as lattice vectors are missing.")
return
# Find special points for this lattice
special_points = ase.dft.kpoints.get_special_points(cell)
special_point_labels = list(special_points.keys())
# Form a conctiguous array of k points for faster operations
special_k_points = np.empty((len(special_points), 3))
for i, kpt in enumerate(special_points.values()):
special_k_points[i, :] = kpt
# Determine match tolerance in 1/m
eps = config.normalize.k_space_precision
# Try to find matches for the special points. We only attempt to match
# points at the start and end of a segment.
for segment in band.section_k_band_segment:
start_point = segment.band_k_points[0]
end_point = segment.band_k_points[-1]
start_index = atomutils.find_match(start_point, special_k_points, eps)
end_index = atomutils.find_match(end_point, special_k_points, eps)
if start_index is None:
start_label = None
else:
start_label = special_point_labels[start_index]
if end_index is None:
end_label = None
else:
end_label = special_point_labels[end_index]
segment.band_path_labels = [start_label, end_label]
def add_is_standard(self, band: section_k_band) -> None:
pass
......@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
import pytest
from tests.normalizing.conftest import ( # pylint: disable=unused-import
......@@ -75,34 +74,8 @@ def test_band_gaps(bands_unpolarized_no_gap, bands_polarized_no_gap, bands_unpol
assert gap_down_ev == pytest.approx(1.230, 0.01)
def test_band_paths(band_path_fcc):
"""Tests that the path labeling works for different lattices.
"""
# FCC
scc = band_path_fcc.entry_archive.section_run[0].section_single_configuration_calculation[0]
system = scc.single_configuration_calculation_to_system_ref
space_group_number = system.section_symmetry[0].space_group_number
assert space_group_number == 227
assumed_path = np.array([
["G", "X"],
["X", "W"],
["W", "K"],
["K", "G"],
["G", "L"],
["L", "U"],
["U", "W"],
["W", "L"],
["L", "K"],
["U", "X"],
])
bs = band_path_fcc.entry_archive.section_run[0].section_single_configuration_calculation[0].section_k_band[0]
for i, segment in enumerate(bs.section_k_band_segment):
labels = segment.band_path_labels
assert np.array_equal(labels, assumed_path[i, :])
def test_phonon_band(phonon):
"""Ensures that phonon bands are not touched.
"""Ensures that band gaps are not added to phonon bands.
"""
bs = phonon.entry_archive.section_run[0].section_single_configuration_calculation[0].section_k_band[0]
assert bs.is_standard_path is None
......
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