"""
CharacterPG manages point-group character table.
"""
import sympy as sp
from gcoreutils.convert_util import text_to_sympy
from multipie.tag.tag_group import TagGroup
from multipie.tag.tag_irrep import TagIrrep
from multipie.tag.tag_symmetry_operation import TagSymmetryOperation
from multipie.tag.tag_list import TagList
from multipie.data.data_character_table import _data_character
from multipie.data.data_product_decomp import _data_product_decomp
from multipie.data.data_compatibility_relation import _data_compatibility_relation
# ==================================================
[docs]
class CharacterPG(dict): # dict of (irrep, characters), {TagIrrep: [sympy]}.
"""
point-group character table.
Attributes:
tag (TagGroup): point-group tag.
"""
#
# __irrep (list): irrep., [TagIrrep].
# __symmetry_operation (list): symmetry operations of conjugacy class, [TagSymmetryOperation].
# __so_number (list): number of SOs in each conjugacy class, [int].
# __character_symbol (dict): character table in symbolic form, {TagIrrep:[sympy]}.
# __parity_conv (dict): parity conversion, {TagIrrep: TagIrrep}.
# __product_decomp_s (dict): symmetric product decomposition, {(TagIrrep,TagIrrep):[(int,TagIrrep)]}.
# __product_decomp_a (dict): anti-symmetric product decomposition, {TagIrrep:[(int,TagIrrep)]}.
#
# ==================================================
def __init__(self, pg_tag):
"""
initialize the class.
Args:
pg_tag (TagGroup or str): point-group tag.
"""
pg_tag = TagGroup(str(pg_tag))
# set tag.
self.tag = pg_tag
"""point-group tag."""
so, so_n, ct_dict = _data_character[str(pg_tag)]
s, a = _data_product_decomp[str(pg_tag)]
# set irrep.
self.__irrep = TagList.from_str(TagIrrep, ct_dict.keys())
# symmetry operation
self.__symmetry_operation = TagList.from_str(TagSymmetryOperation, so)
self.__so_number = so_n
# set character table.
w = sp.symbols(r"\omega \omega^*")
wpv = text_to_sympy("-1/2+sqrt(3)*I/2")
wmv = text_to_sympy("-1/2-sqrt(3)*I/2")
self.__character_symbol = {}
for irrep, ct in ct_dict.items():
self[TagIrrep(irrep)] = text_to_sympy(ct, local={"wp": wpv, "wm": wmv})
self.__character_symbol[TagIrrep(irrep)] = text_to_sympy(ct, local={"wp": w[0], "wm": w[1]})
# set parity conversion.
cr = TagList.from_str(TagIrrep, _data_compatibility_relation[str(pg_tag)])
n = len(cr) // 2
cr_conv = cr[n:] + cr[:n]
self.__parity_conv = {i: j for i, j in zip(cr, cr_conv)}
# set product decomposition.
self.__product_decomp_s = {}
for ir1, p in zip(self.__irrep, s):
for ir2, v in zip(self.__irrep, p):
v = [(n, TagIrrep(ir)) for n, ir in v]
self.__product_decomp_s[(ir1, ir2)] = v
self.__product_decomp_a = {}
for ir, v in zip(self.__irrep, a):
v = [(n, TagIrrep(ir)) for n, ir in v]
self.__product_decomp_a[ir] = v
# ==================================================
def __str__(self):
return str(self.tag)
# ==================================================
def __repr__(self):
return repr(self.tag)
# ==================================================
def latex(self):
return self.tag.latex()
# ==================================================
def __getitem__(self, tag):
if type(tag) == str:
return self.get(TagIrrep(tag))
else:
return self.get(tag)
# ==================================================
def key_list(self):
return TagList(self.keys())
# ==================================================
@property
def irrep_list(self):
"""
list of irreps.
Returns:
[TagIrrep]: list of irreps.
Notes:
- first element is identity irrep.
"""
return self.__irrep
# ==================================================
[docs]
def character(self, irrep=None, all_so=False, explicit=False):
"""
character table.
Args:
irrep (str or TagIrrep, optional): irrep. tag ("" = identity irrep.).
all_so (bool, optional): return characters for all symmetry operations ?
explicit (bool, optional): use explicit expression of character ?
Returns:
- [sympy]: character table (symbol) for given irrep.
or
- {TagIrrep:[sympy]}: all irreps.
"""
if irrep == "":
irrep = self.irrep_list[0]
ctbl = self if explicit else self.__character_symbol
if irrep is None:
if all_so:
return {i: self._to_all(c) for i, c in ctbl.items()}
else:
return ctbl
else:
if type(irrep) == str:
lst = list(map(str, self.irrep_list))
assert irrep in lst, f"{irrep} is not find in {lst}"
irrep = TagIrrep(irrep)
if all_so:
return self._to_all(ctbl[irrep])
else:
return ctbl[irrep]
# ==================================================
def _to_all(self, ch_cc):
"""
convert character table for all symmetry operations.
Args:
ch_cc ([sympy]): characters for cc operations.
Returns:
[sympy]: characters for all symmetry operations.
"""
ch = []
for chi, n in zip(ch_cc, self.__so_number):
ch.extend([chi] * n)
return ch
# ==================================================
[docs]
def symmetry_operation(self, ret_num=False):
"""
representative symmetry operations in conjugacy class.
Args:
ret_num (bool, optional): return with the number of cc operations ?
Returns:
- [TagSymmetryOperation]: symmetry operation.
or
- [TagSymmetryOperation]: symmetry operations.
- [int]: the number of symmetry operations in conjugacy class.
"""
if ret_num:
return self.__symmetry_operation, self.__so_number
else:
return self.__symmetry_operation
# ==================================================
[docs]
def compatibility_relation(self, pg_tag):
"""
compatibility_relation from the present point group to a given one.
Args:
pg_tag (TagGroup or str): point-group tag to obtain compatibility relation.
Returns:
{TagIrrep: [TagIrrep]}: compatibility relation from self to other.
"""
if type(pg_tag) == str:
other = TagGroup(pg_tag)
else:
other = pg_tag
assert self.tag.subgroup == other.subgroup, "diffrent subgroup is given."
p = self.irrep_list
c = TagList.from_str(TagIrrep, _data_compatibility_relation[str(other)])
return {i: j for i, j in zip(p, c)}
# ==================================================
[docs]
def parity_conversion(self):
"""
parity conversion.
Returns:
{TagIrrep: TagIrrep: correspondence from self to converted one.
"""
return self.__parity_conv
# ==================================================
[docs]
def symmetric_product_decomposition(self, irrep_pair, ret_ex=False):
"""
symmetric product irreducible decomposition.
Args:
irrep_pair ((TagIrrep or str, TagIrrep or str)): a pair of irreps.
ret_ex (bool, optional): return as an expression ?
Returns:
- [(int,TagIrrep)]: (the number of appearances, irrep.).
or
- sympy: decomposed expression.
"""
ir1, ir2 = irrep_pair
if type(ir1) == str:
ir1 = TagIrrep(ir1)
if type(ir2) == str:
ir2 = TagIrrep(ir2)
val = self.__product_decomp_s[(ir1, ir2)]
if ret_ex:
ex = 0
for n, v in val:
ex += n * v.symbol()
val = ex
return val
# ==================================================
[docs]
def anti_symmetric_product_decomposition(self, irrep, ret_ex=False):
"""
anti-symmetric product irreducible decomposition.
Args:
irrep (TagIrrep or str): irrep. tag.
ret_ex (bool, optional): return as an expression ?
Returns:
- [(int,TagIrrep)]: (the number of appearances, irrep.).
or
- sympy: decomposed expression.
"""
if type(irrep) == str:
irrep = TagIrrep(irrep)
val = self.__product_decomp_a[irrep]
if ret_ex:
ex = 0
for n, v in val:
ex += n * v.symbol()
val = ex
return val
# ==================================================
[docs]
def irrep_decomposition(self, char):
"""
irreducible decomposition.
Args:
char ([sympy]): characters to be decomposed for symmetry operations in conjugacy class, .
Returns:
[(int,TagIrrep)]: (the number of appearances, irrep.).
"""
decomp = []
g = sum(self.__so_number)
for irrep, ir_char in self.items():
s = 0
for c, ic, d in zip(char, ir_char, self.__so_number):
s += d * sp.conjugate(c) * ic
n = sp.simplify(s) / g
if n != 0:
decomp.append((n, irrep))
return decomp