Source code for gyroid.group

# -*- coding: utf-8 -*-
"""
gyroid.group
============

"""

import numpy as np
from numpy.linalg import inv

#from .symmetry import find_symmetry_for_group
from .common import HM_ITA_TABLE1,HM_ITA_TABLE2,HM_ITA_TABLE3
from .common import GROUP_ORDER_TABLE1,GROUP_ORDER_TABLE2,GROUP_ORDER_TABLE3
from .space_group import symmetry_generator1,symmetry_generator2,symmetry_generator3

__all__ = ["Group","CayleyTable"]

[docs]class Group(object): ''' A :class:`Group` object is a representaion of a space group. All symmetries in a space group must have the same basis type, i.e. they must all be either the BRAVAIS or the CARTESIAN bases. The space group is constructed either by providing a Hermann-Mauguin Symbol (HM_symbol) or a sequential number as given in the International Tables for Crystallography, Vol. A (ITA_number) :members: dim, type, shape, symm ''' def __init__(self,dim,basis_type,shape_matrix, HM_symbol=None,ITA_number=None): ''' If both HM symbol and ITA number are provided, use HM symbol only. And the consistency of HM symbol and ITA number is checked. ''' if dim < 1 or dim > 3: raise ValueError('Only 1D, 2D, and 3D space allowed.') self.dim = dim self.type = basis_type self.shape = shape_matrix if HM_symbol: self.__create_group_by_symbol(HM_symbol) return if ITA_number is None: return self.__create_group_by_number(ITA_number) def __find_ITA_number(self,HM_symbol): if self.dim == 1 and HM_symbol in HM_ITA_TABLE1: return HM_ITA_TABLE1.index(HM_symbol) + 1 if self.dim == 2 and HM_symbol in HM_ITA_TABLE2: return HM_ITA_TABLE2.index(HM_symbol) + 1 if self.dim == 3 and HM_symbol in HM_ITA_TABLE3: return HM_ITA_TABLE3.index(HM_symbol) + 1 return 0 def __is_valid_ITA_number(self,ITA_number): if self.dim == 1 and ITA_number > 0 and ITA_number < 3: return True if self.dim == 2 and ITA_number > 0 and ITA_number < 18: return True if self.dim == 3 and ITA_number > 0 and ITA_number < 231: return True return False def __find_HM_symbol(self,ITA_number): if self.dim == 1: return HM_ITA_TABLE1[ITA_number-1] if self.dim == 2: return HM_ITA_TABLE2[ITA_number-1] if self.dim == 3: return HM_ITA_TABLE3[ITA_number-1] def __find_group_order(self,ITA_number): if self.dim == 1: return GROUP_ORDER_TABLE1[ITA_number-1] if self.dim == 2: return GROUP_ORDER_TABLE2[ITA_number-1] if self.dim == 3: return GROUP_ORDER_TABLE3[ITA_number-1] def __find_symmetry_for_group(self,ITA_number): if self.dim == 1: return symmetry_generator1(ITA_number,self.type,self.shape) if self.dim == 2: symm = symmetry_generator2(ITA_number,self.type,self.shape) if self.dim == 3: symm = symmetry_generator3(ITA_number,self.type,self.shape) # generating group symmetries using generators cayley = CayleyTable(symm) for iterate in range(20): is_group = True # Add missing inverses of existing elements to group k = len(symm) for i in range(k): isymm = symm[i].inverse() if isymm not in symm: symm.append(isymm) is_group = False # Add products of existing elements to group cayley.update(symm) k = len(symm) for (i,j) in np.ndindex(k,k): #if (cayley.index[i,j] == -1) and (cayley.table[i][j] not in symm): if cayley.table[i][j] not in symm: symm.append(cayley.table[i][j]) is_group = False # No more symmetry element is added before end of iteration. if is_group: return symm raise ValueError("Failed to create a group.") def __create_group_by_symbol(self,HM_symbol): number = self.__find_ITA_number(HM_symbol) self.__create_group_by_number(number) def __create_group_by_number(self,ITA_number): if not self.__is_valid_ITA_number(ITA_number): raise ValueError("Incorrect HM symbol or ITA number.") self.number = ITA_number self.HM_symbol = self.__find_HM_symbol(ITA_number) self.symm = self.__find_symmetry_for_group(ITA_number) self.order = len(self.symm) if self.order != self.__find_group_order(ITA_number): raise ValueError("Incorrect order for group")
[docs]class CayleyTable(object): """ Make a full Cayley table from a list of :class:`Symmetry` objects. """ def __init__(self,symm=None): # create a self.order x self.order table # NOTE: table is not an numpy ndarray! if symm is None: self.table = [[]] else: self.order = len(symm) self.table = [[symm[i]*symm[j] for i in range(self.order)] for j in range(self.order)]
[docs] def update(self,symm): ''' Update the :class:`CayleyTable` object. Currently, `len(symm)` must be larger than `self.order`. ''' l0 = self.order l1 = len(symm) if l1 <= l0: return # Extend original rows for i in range(l0): self.table[i].extend([symm[i]*symm[j] for j in range(l0,l1)]) # Add additional rows self.table.extend([[symm[i]*symm[j] for j in range(l1)] for i in range(l0,l1)]) self.order = l1

Related Topics