Source code for gyroid.group
# -*- coding: utf-8 -*-
"""
gyroid.group
============
:copyright: (c) 2012 by Yi-Xin Liu
:license: BSD, see LICENSE for more details.
"""
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 representaion of a space group.
All symmetries in a space group must have the same basis, 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)
"""
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 will not be checked.
"""
if dim < 1 or dim > 3:
raise ValueError("Error: 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
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 = CayleyTable(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):
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 group.
"""
def __init__(self,symm):
self.order = len(symm)
# create a self.order x self.order table
# NOTE: table is not an numpy ndarray!
self.table = [[symm[i]*symm[j] for i in range(self.order)]
for j in range(self.order)]
# Find index for symmetry element table(i,j) in symm
# If symmetry element (i,j) is not in symm, then index(i,j)=-1
self.index = np.zeros((self.order,self.order)) - 1
for (i,j) in np.ndindex(self.order,self.order):
if self.table[i][j] in symm:
self.index[i,j] = symm.index(self.table[i][j])