Source code for aiida_castep.data
"""
Module for additional Data classes
"""
from aiida.common import MultipleObjectsError, NotExistent
from aiida.orm import Group
from aiida.orm.nodes.data.upf import UpfData
from .otfg import OTFGData
from .usp import UspData
[docs]def get_pseudos_from_structure(structure, family_name):
"""
Given a family name (of UpfData or OTFGData) and a AiiDA
structure, return a dictionary associating each kind name with its
pseduopotential object.
:raise MultipleObjectsError: if more than one UPF for the same element is
found in the group.
:raise NotExistent: if no UPF for an element in the group is
found in the group.
:returns: A dictionary maps kind to the psueodpotential node
"""
# Try to get the pseudopotentials that are managed by aiida-pseudo
result = _get_pseudos_from_aiida_pseudo(structure, family_name)
if result:
return result
family_pseudos = {}
try:
family_upf = [UpfData.get_upf_group(family_name)]
except NotExistent:
family_upf = []
try:
family_otfg = [OTFGData.get_otfg_group(family_name)]
except NotExistent:
family_otfg = []
all_families = family_otfg + family_upf
if len(all_families) == 0:
raise NotExistent(
"Cannot find matching group among UspData, UpfData and OTFGData"
)
if len(all_families) > 1:
raise MultipleObjectsError(f"Multiple groups with label {family_name} detected")
family = all_families[0]
# Checking uniqueness for each element
for node in family.nodes:
if isinstance(node, (UpfData, UspData, OTFGData)):
if node.element in family_pseudos:
raise MultipleObjectsError(
"More than one pseudo for element {} found in "
"family {}".format(node.element, family_name)
)
family_pseudos[node.element] = node
pseudo_list = {}
for kind in structure.kinds:
symbol = kind.symbol
if symbol in family_pseudos:
pseudo_list[kind.name] = family_pseudos[symbol]
elif "LIBRARY" in family_pseudos:
pseudo_list[kind.name] = family_pseudos["LIBRARY"]
else:
raise NotExistent(
"No pseudo for element {} found in family {}".format(
symbol, family_pseudos
)
)
return pseudo_list
[docs]def _get_pseudos_from_aiida_pseudo(structure, label):
"""
Attempt to get pseudopotentials that are managed by the `aiida-pseudo` package
:param structure: A ``StructureData`` for which the pseudopotentials needs to be selected.
:param label: The name of the pseudopotential family
:returns: A dictionary of each element and its pseudopotential.
"""
try:
group = Group.objects.get(label=label, type_string={"like": "pseudo.family%"})
except NotExistent:
return []
# Make sure the group is a group from aiida-pseudo
if not group._type_string.startswith( # pylint: disable=protected-access
"pseudo.family"
):
return []
if group.pseudo_type != "pseudo.upf":
raise ValueError(
f"Pseudopotential type {group.pseudo_type} is not supported - only UPF can be used."
)
return group.get_pseudos(structure=structure)