Skip to content

Commit 77cfeec

Browse files
author
jrudz
committed
added missing property files by hand
1 parent 219be1e commit 77cfeec

File tree

7 files changed

+1462
-0
lines changed

7 files changed

+1462
-0
lines changed

properties/band_gap.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
#
2+
# Copyright The NOMAD Authors.
3+
#
4+
# This file is part of NOMAD. See https://nomad-lab.eu for further info.
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
import numpy as np
20+
from structlog.stdlib import BoundLogger
21+
import pint
22+
from typing import Optional
23+
24+
from nomad.metainfo import Quantity, MEnum, Section, Context
25+
26+
from nomad_simulations.physical_property import PhysicalProperty
27+
28+
29+
class ElectronicBandGap(PhysicalProperty):
30+
"""
31+
Energy difference between the highest occupied electronic state and the lowest unoccupied electronic state.
32+
"""
33+
34+
# ! implement `iri` and `rank` as part of `m_def = Section()`
35+
36+
iri = 'http://fairmat-nfdi.eu/taxonomy/ElectronicBandGap'
37+
38+
type = Quantity(
39+
type=MEnum('direct', 'indirect'),
40+
description="""
41+
Type categorization of the electronic band gap. This quantity is directly related with `momentum_transfer` as by
42+
definition, the electronic band gap is `'direct'` for zero momentum transfer (or if `momentum_transfer` is `None`) and `'indirect'`
43+
for finite momentum transfer.
44+
45+
Note: in the case of finite `variables`, this quantity refers to all of the `value` in the array.
46+
""",
47+
)
48+
49+
momentum_transfer = Quantity(
50+
type=np.float64,
51+
shape=[2, 3],
52+
description="""
53+
If the electronic band gap is `'indirect'`, the reciprocal momentum transfer for which the band gap is defined
54+
in units of the `reciprocal_lattice_vectors`. The initial and final momentum 3D vectors are given in the first
55+
and second element. Example, the momentum transfer in bulk Si2 happens between the Γ and the (approximately)
56+
X points in the Brillouin zone; thus:
57+
`momentum_transfer = [[0, 0, 0], [0.5, 0.5, 0]]`.
58+
59+
Note: this quantity only refers to scalar `value`, not to arrays of `value`.
60+
""",
61+
)
62+
63+
spin_channel = Quantity(
64+
type=np.int32,
65+
description="""
66+
Spin channel of the corresponding electronic band gap. It can take values of 0 or 1.
67+
""",
68+
)
69+
70+
value = Quantity(
71+
type=np.float64,
72+
unit='joule',
73+
description="""
74+
The value of the electronic band gap. This value has to be positive, otherwise it will
75+
prop an error and be set to None by the `normalize()` function.
76+
""",
77+
)
78+
79+
def __init__(
80+
self, m_def: Section = None, m_context: Context = None, **kwargs
81+
) -> None:
82+
super().__init__(m_def, m_context, **kwargs)
83+
self.name = self.m_def.name
84+
self.rank = []
85+
86+
def validate_values(self, logger: BoundLogger) -> Optional[pint.Quantity]:
87+
"""
88+
Validate the electronic band gap `value` by checking if they are negative and sets them to None if they are.
89+
90+
Args:
91+
logger (BoundLogger): The logger to log messages.
92+
"""
93+
value = self.value.magnitude
94+
if not isinstance(self.value.magnitude, np.ndarray): # for scalars
95+
value = np.array(
96+
[value]
97+
) # ! check this when talking with Lauri and Theodore
98+
99+
# Set the value to 0 when it is negative
100+
if (value < 0).any():
101+
logger.error('The electronic band gap cannot be defined negative.')
102+
return None
103+
104+
if not isinstance(self.value.magnitude, np.ndarray): # for scalars
105+
value = value[0]
106+
return value * self.value.u
107+
108+
def resolve_type(self, logger: BoundLogger) -> Optional[str]:
109+
"""
110+
Resolves the `type` of the electronic band gap based on the stored `momentum_transfer` values.
111+
112+
Args:
113+
logger (BoundLogger): The logger to log messages.
114+
115+
Returns:
116+
(Optional[str]): The resolved `type` of the electronic band gap.
117+
"""
118+
mtr = self.momentum_transfer if self.momentum_transfer is not None else []
119+
120+
# Check if the `momentum_transfer` is [], and return the type and a warning in the log for `indirect` band gaps
121+
if len(mtr) == 0:
122+
if self.type == 'indirect':
123+
logger.warning(
124+
'The `momentum_transfer` is not stored for an `indirect` band gap.'
125+
)
126+
return self.type
127+
128+
# Check if the `momentum_transfer` has at least two elements, and return None if it does not
129+
if len(mtr) == 1:
130+
logger.warning(
131+
'The `momentum_transfer` should have at least two elements so that the difference can be calculated and the type of electronic band gap can be resolved.'
132+
)
133+
return None
134+
135+
# Resolve `type` from the difference between the initial and final momentum transfer
136+
momentum_difference = np.diff(mtr, axis=0)
137+
if (np.isclose(momentum_difference, np.zeros(3))).all():
138+
return 'direct'
139+
else:
140+
return 'indirect'
141+
142+
def normalize(self, archive, logger) -> None:
143+
super().normalize(archive, logger)
144+
145+
# Checks if the `value` is negative and sets it to None if it is.
146+
self.value = self.validate_values(logger)
147+
if self.value is None:
148+
# ? What about deleting the class if `value` is None?
149+
logger.error('The `value` of the electronic band gap is not stored.')
150+
return
151+
152+
# Resolve the `type` of the electronic band gap from `momentum_transfer`, ONLY for scalar `value`
153+
if isinstance(self.value.magnitude, np.ndarray):
154+
logger.info(
155+
'We do not support `type` which describe individual elements in an array `value`.'
156+
)
157+
else:
158+
self.type = self.resolve_type(logger)
159+

0 commit comments

Comments
 (0)