Source code for aiida_quantumespresso.tools.data.orbital.spinorbithydrogen
# -*- coding: utf-8 -*-
"""A module defining hydrogen-like orbitals.
The orbitals are defined in the simultaneous eigen-basis of H, J^2, L^2, S^2
and J_z operators, useful for projecting densities with spin-orbit coupling.
"""
from aiida.common.exceptions import ValidationError
from aiida.tools.data.orbital.orbital import Orbital
[docs]def validate_j(value):
"""Validate the value of the total angular momentum."""
if not isinstance(value, (int, float)):
raise ValidationError('total angular momentum (j) must be float')
if not value % 0.5 == 0.0:
raise ValidationError('total angular momentum (j) must be a half integer')
if value < 0.5 or value > 3.5:
raise ValidationError('total angular momentum (j) must be between 0.5 and 3.5')
return value
[docs]def validate_l(value):
"""Validate the value of the angular momentum."""
if not isinstance(value, int):
raise ValidationError('angular momentum (l) must be integer')
if value < 0 or value > 3:
raise ValidationError('angular momentum (l) must be between 0 and 3')
return value
[docs]def validate_mj(value):
"""Validate the value of the magnetic number."""
if not isinstance(value, (int, float)):
raise ValidationError('magnetic number (m_j) must be float')
# without knowing j we cannot validate the value of m_j. We will call an additional function
# in the validate function
return value
[docs]def validate_kind_name(value):
"""Validate the value of the kind_name."""
if value is not None and not isinstance(value, str):
raise ValidationError('kind_name must be a string')
return value
[docs]def validate_n(value):
"""Validate the value of the number of radial nodes."""
if not isinstance(value, int):
raise ValidationError('number of radial nodes (n) must be integer')
if value < 0 or value > 2:
raise ValidationError('number of radial nodes (n) must be between 0 and 2')
return value
[docs]class SpinorbitHydrogenOrbital(Orbital):
"""Orbitals for hydrogen with spin-orbit interaction.
The orbital is defined in the common basis of H, J^2, L^2, S^2, J_z
operators, indexed by the quantum numbers n, j, l, j_z.
A brief description of what is meant by each of these labels:
:param radial_nodes: the number of radial nodes (or inflections) if no radial
nodes are supplied, defaults to 0
:param angular_momentum: Angular quantum number l
:param total_angular_momentum: Total angular momentum number j
:param magnetic_number: Magnetic quantum number m_j
The total angular momentum quantum number j takes values `|l-s| <= j <=
l+s` in integer steps and the magnetic number takes values from -j to +j in
integer steps.
"""
[docs] _base_fields_required = tuple(
list(Orbital._base_fields_required) +
[('total_angular_momentum',
validate_j), ('angular_momentum', validate_l), ('magnetic_number', validate_mj), ('radial_nodes', validate_n)]
)
[docs] _base_fields_optional = tuple(list(Orbital._base_fields_optional) + [
('kind_name', validate_kind_name, None),
])
[docs] def __str__(self):
"""Printable representation of the orbital."""
orb = self.get_orbital_dict()
try:
orb_name = f"j={orb['total_angular_momentum']},l={orb['angular_momentum']},m_j={orb['magnetic_number']}"
position_string = f"{orb['position'][0]:.4f},{orb['position'][1]:.4f},{orb['position'][2]:.4f}"
orbital = f"for kind {orb['kind_name']}" if orb['kind_name'] else ''
out_string = f"r{orb['radial_nodes']} {orb_name} orbital {orbital} @ {position_string}"
except KeyError:
# Should not happen, but we want it not to crash in __str__
out_string = '(not all parameters properly set)'
return out_string
[docs] def _validate_keys(self, input_dict):
"""Validate the keys otherwise raise ValidationError.
Does basic validation from the parent followed by validations for the
quantum numbers. Raises exceptions should the input_dict fail the
valiation or if it contains any unsupported keywords. :param
input_dict: the dictionary of keys to be validated :return
validated_dict: a validated dictionary
"""
validated_dict = super()._validate_keys(input_dict)
# Validate m knowing the value of l
total_angular_momentum = validated_dict['total_angular_momentum'] # j quantum number, must be there
angular_momentum = validated_dict['angular_momentum'] # l quantum number, must be there
accepted_range = [abs(angular_momentum - 0.5), angular_momentum + 0.5]
if total_angular_momentum < min(accepted_range) or total_angular_momentum > max(accepted_range):
raise ValidationError(
f'the total angular momentum must be in the range [{min(accepted_range)}, {max(accepted_range)}]'
)
magnetic_number = validated_dict['magnetic_number'] # m quantum number, must be there
accepted_range = [-total_angular_momentum, total_angular_momentum]
if magnetic_number < min(accepted_range) or magnetic_number > max(accepted_range):
raise ValidationError(
f'the magnetic number must be in the range [{min(accepted_range)}, {max(accepted_range)}]'
)
return validated_dict