Source code for symmetry_representation._compatibility

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# (c) 2017-2018, ETH Zurich, Institut fuer Theoretische Physik
# Author: Dominik Gresch <greschd@gmx.ch>
"""
Defines functions to determine if symmetries are compatible with a given structure.
"""

from collections.abc import Iterable
from functools import singledispatch

import numpy as np
import pymatgen as mg
from fsc.export import export

from . import SymmetryGroup, SymmetryOperation


[docs]@export def is_compatible(*, structure, symmetry): """ Checks whether a given symmetry's real space action (rotation + translation vector) is consistent with a given structure. Arguments --------- structure : pymatgen.Structure The crystal structure. symmetry : SymmetryOperation The symmetry operation that is checked for compatibility. """ analyzer = mg.symmetry.analyzer.SpacegroupAnalyzer(structure) valid_sym_ops = analyzer.get_symmetry_operations(cartesian=False) for sym_op in valid_sym_ops: if ( np. allclose(sym_op.translation_vector, symmetry.translation_vector) and np.allclose(sym_op.rotation_matrix, symmetry.rotation_matrix) ): return True return False
[docs]@export @singledispatch def filter_compatible(symmetries, *, structure): """ Returns the symmetries which are compatible with the given structure. Arguments --------- symmetries : SymmetryGroup, Iterable The symmetries which should be checked for compatibility. If a :class:`.SymmetryGroup` is given, the result is also given as a :class:`.SymmetryGroup`. structure : pymatgen.Structure The crystal structure. """ raise ValueError( "Unrecognized type '{}' for 'symmetries'".format(type(symmetries)) )
@filter_compatible.register(Iterable) def _(symmetries, *, structure): # pylint: disable=missing-function-docstring filtered_syms = [ filter_compatible(s, structure=structure) for s in symmetries ] return [s for s in filtered_syms if s is not None] @filter_compatible.register(SymmetryOperation) def _(symmetry, *, structure): # pylint: disable=missing-function-docstring if is_compatible(symmetry=symmetry, structure=structure): return symmetry else: return None @filter_compatible.register(SymmetryGroup) def _(symmetry_group, *, structure): # pylint: disable=missing-function-docstring filtered_syms = filter_compatible( symmetry_group.symmetries, structure=structure ) if filtered_syms: return SymmetryGroup( symmetries=filtered_syms, full_group=symmetry_group.full_group ) else: return None