Qsymm 和 kdotp_symmetry 对比
Qsymm 和 kdotp_symmetry 是目前比较成熟的两个自动化生成 kp 哈密顿量的 python 库,本文主要是通过实例来对比于这两个库。
Qsymm 文档: Generating models — Qsymm 1.4.0-dev10+gc8e0f55.dirty documentation
Kdotp_symmetry 文档:kdotp-symmetry — kdotp-symmetry 1.0.1 documentation (greschd.ch)
例子1: Hexagonal warping
这是三维拓扑绝缘体的表面哈密顿量模型。
import numpy as np import sympy import qsymm # C3 rotational symmetry - invariant under 2pi/3 C3 = qsymm.rotation(1/3, spin=1/2) # Time reversal TR = qsymm.time_reversal(2, spin=1/2) # Mirror symmetry in x Mx = qsymm.mirror([1, 0], spin=1/2) symmetries = [C3, TR, Mx] dim = 2 # Momenta along x and y total_power = 3 # Maximum power of momenta family = qsymm.continuum_hamiltonian(symmetries, dim, total_power, prettify=True) qsymm.display_family(family) ## Output ''' Matrix([[1, 0], [0, 1]]) Matrix([[0, I*k_x + k_y], [-I*k_x + k_y, 0]]) Matrix([[k_x**2 + k_y**2, 0], [0, k_x**2 + k_y**2]]) Matrix([[k_x**3 - 3*k_x*k_y**2, 0], [0, -k_x**3 + 3*k_x*k_y**2]]) Matrix([[0, I*k_x**3 + k_x**2*k_y + I*k_x*k_y**2 + k_y**3], [-I*k_x**3 + k_x**2*k_y - I*k_x*k_y**2 + k_y**3, 0]]) '''
对称操作矩阵为:

[ ## C3 PointGroupElement( R = array([[-0.4999999999999998, -0.8660254037844387], [0.8660254037844387, -0.4999999999999998]]), conjugate = False, antisymmetry = False, U = array([[0.5-0.8660254j, 0. +0.j ], [0. +0.j , 0.5+0.8660254j]])), ## TR PointGroupElement( R = array([[1, 0], [0, 1]]), conjugate = True, antisymmetry = False, U = array([[ 0.+0.j, -1.+0.j], [ 1.+0.j, 0.+0.j]])), ## Mx PointGroupElement( R = array([[-1, 0], [0, 1]]), conjugate = False, antisymmetry = False, U = array([[0.+0.j, 0.-1.j], [0.-1.j, 0.+0.j]])) ]
kdotp_symmetry程序运行:
import sympy as sp from sympy.core.numbers import I import sympy.physics.matrices as sm from sympy.physics.quantum import TensorProduct import symmetry_representation as sr import kdotp_symmetry as kp # In this project we used the basis of tensor products of Pauli matrices pauli_vec = [sp.eye(2), *(sm.msigma(i) for i in range(1, 4))] basis = pauli_vec # creating the symmetry operations C3 = sr.SymmetryOperation( rotation_matrix=sp.Matrix([[-0.5, -0.8660254037844387],[0.8660254037844387, -0.5]]), repr_matrix=sp.Matrix([[0.5-0.8660254037844387j, 0 ],[0, 0.5+0.8660254037844387j]]), repr_has_cc=False, numeric=False ) time_reversal = sr.SymmetryOperation( rotation_matrix=sp.eye(2), repr_matrix=sp.Matrix([[0, -1], [1, 0]]), repr_has_cc=True, ) Mx = sr.SymmetryOperation( rotation_matrix=sp.Matrix([[-1,0],[0,1]]), repr_matrix=sp.Matrix([[0, -1j], [-1j, 0]]), repr_has_cc=False, ) def print_result(order): """prints the basis for a given order of k""" print('Order:', order) for m in kp.symmetric_hamiltonian( C3, time_reversal, Mx, expr_basis=kp.monomial_basis(order), repr_basis=basis ): print(m) print() if __name__ == '__main__': for i in range(2): print_result(order=i)
代码出现报错,还没解决!!!,报错内容如下:

Order: 0 Traceback (most recent call last): File "D:\文档\研究生\kp-TB\kdotp_symmetry\kdotp_symmetry_Bi2Se3_surface.py", line 44, in <module> print_result(order=i) File "D:\文档\研究生\kp-TB\kdotp_symmetry\kdotp_symmetry_Bi2Se3_surface.py", line 32, in print_result for m in kp.symmetric_hamiltonian( File "C:\Users\ghzph\AppData\Roaming\Python\Python310\site-packages\kdotp_symmetry\_symmetric_hamiltonian.py", line 75, in symmetric_hamiltonian operator=matrix_to_expr_operator( File "C:\Users\ghzph\AppData\Roaming\Python\Python310\site-packages\kdotp_symmetry\_expr_utils.py", line 105, in matrix_to_expr_operator substitution = list(zip(K_VEC, k_matrix_form @ sp.Matrix(K_VEC))) File "C:\Users\ghzph\AppData\Roaming\Python\Python310\site-packages\sympy\core\decorators.py", line 106, in binary_op_wrapper return func(self, other) File "C:\Users\ghzph\AppData\Roaming\Python\Python310\site-packages\sympy\matrices\common.py", line 2740, in __matmul__ return self.__mul__(other) File "C:\Users\ghzph\AppData\Roaming\Python\Python310\site-packages\sympy\core\decorators.py", line 106, in binary_op_wrapper return func(self, other) File "C:\Users\ghzph\AppData\Roaming\Python\Python310\site-packages\sympy\matrices\common.py", line 2774, in __mul__ return self.multiply(other) File "C:\Users\ghzph\AppData\Roaming\Python\Python310\site-packages\sympy\matrices\common.py", line 2796, in multiply raise ShapeError("Matrix size mismatch: %s * %s." % ( sympy.matrices.common.ShapeError: Matrix size mismatch: (2, 2) * (3, 1).
-2021.09.04 已找到错误原因:
查看 kdotp_symmetry 源码发现,该程序只针对以 kx, ky, kz 三个 k 参数展开的基矢,对于想只操作只含 kx,ky 的哈密顿量,需要改动python 源码。
例子2: BHZ model
We reproduce the Hamiltonian for the quantum spin Hall effect derived in Science, 314, 1757 (2006).
The symmetry group is generated by spatial inversion symmetry, time-reversal symmetry and fourfold rotation symmetry.
import numpy as np import sympy import qsymm # Spatial inversion pU = np.array([ [1.0, 0.0, 0.0, 0.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, -1.0], ]) pS = qsymm.inversion(2, U=pU) # Time reversal trU = np.array([ [0.0, 0.0, -1.0, 0.0], [0.0, 0.0, 0.0, -1.0], [1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], ]) trS = qsymm.time_reversal(2, U=trU) # Rotation phi = 2.0 * np.pi / 4.0 # Impose 4-fold rotational symmetry rotU = np.array([ [np.exp(-1j*phi/2), 0.0, 0.0, 0.0], [0.0, np.exp(-1j*3*phi/2), 0.0, 0.0], [0.0, 0.0, np.exp(1j*phi/2), 0.0], [0.0, 0.0, 0.0, np.exp(1j*3*phi/2)], ]) rotS = qsymm.rotation(1/4, U=rotU) symmetries = [rotS, trS, pS] # print(symmetries) dim = 2 total_power = 2 family = qsymm.continuum_hamiltonian(symmetries, dim, total_power, prettify=True) qsymm.display_family(family) ### Output ''' Matrix([[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0]]) Matrix([[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1]]) Matrix([[0, k_x + I*k_y, 0, 0], [k_x - I*k_y, 0, 0, 0], [0, 0, 0, -k_x + I*k_y], [0, 0, -k_x - I*k_y, 0]]) Matrix([[0, I*k_x - k_y, 0, 0], [-I*k_x - k_y, 0, 0, 0], [0, 0, 0, I*k_x + k_y], [0, 0, -I*k_x + k_y, 0]]) Matrix([[k_x**2 + k_y**2, 0, 0, 0], [0, 0, 0, 0], [0, 0, k_x**2 + k_y**2, 0], [0, 0, 0, 0]]) Matrix([[0, 0, 0, 0], [0, k_x**2 + k_y**2, 0, 0], [0, 0, 0, 0], [0, 0, 0, k_x**2 + k_y**2]]) '''
表示矩阵

[ PointGroupElement( R = array([[0, -1], [1, 0]]), conjugate = False, antisymmetry = False, U = array([[ 0.70710678-0.70710678j, 0. +0.j , 0. +0.j , 0. +0.j ], [ 0. +0.j , -0.70710678-0.70710678j, 0. +0.j , 0. +0.j ], [ 0. +0.j , 0. +0.j , 0.70710678+0.70710678j, 0. +0.j ], [ 0. +0.j , 0. +0.j , 0. +0.j , -0.70710678+0.70710678j]])), PointGroupElement( R = array([[1, 0], [0, 1]]), conjugate = True, antisymmetry = False, U = array([[ 0., 0., -1., 0.], [ 0., 0., 0., -1.], [ 1., 0., 0., 0.], [ 0., 1., 0., 0.]])), PointGroupElement( R = array([[-1, 0], [0, -1]]), conjugate = False, antisymmetry = False, U = array([[ 1., 0., 0., 0.], [ 0., -1., 0., 0.], [ 0., 0., 1., 0.], [ 0., 0., 0., -1.]]))]
kdotp_symmetry:
import sympy as sp from sympy.core.numbers import I import sympy.physics.matrices as sm from sympy.physics.quantum import TensorProduct import symmetry_representation as sr import kdotp_symmetry as kp # In this project we used the basis of tensor products of Pauli matrices pauli_vec = [sp.eye(2), *(sm.msigma(i) for i in range(1, 4))] basis = [TensorProduct(p1, p2) for p1 in pauli_vec for p2 in pauli_vec] # creating the symmetry operations parity = sr.SymmetryOperation( rotation_matrix=sp.Matrix([[-1,0],[0,-1]]), repr_matrix=sp.Matrix([[1,0,0,0], [0,-1,0,0], [0,0, 1,0], [0,0,0,-1]]), repr_has_cc=False, ) time_reversal = sr.SymmetryOperation( rotation_matrix=sp.eye(2), repr_matrix=sp.Matrix([[0,0,-1,0], [0,0,0,-1], [1,0,0,0], [0,1,0,0]]), repr_has_cc=True, ) C4 = sr.SymmetryOperation( rotation_matrix=sp.Matrix([[0,-1],[1,0]]), repr_matrix=sp.Matrix([[0.7071067811865476-0.7071067811865476j,0,0,0], [0,-0.7071067811865476-0.7071067811865476j,0,0], [0,0, 0.7071067811865476+0.7071067811865476j,0], [0,0,0,-0.7071067811865476+0.7071067811865476j]]), repr_has_cc=False, # numeric=True ) def print_result(order): """prints the basis for a given order of k""" print('Order:', order) for m in kp.symmetric_hamiltonian( parity, time_reversal, C4, expr_basis=kp.monomial_basis(order), repr_basis=basis ): print(m) print() if __name__ == '__main__': # print(c2y) for i in range(3): print_result(order=i)
运行报错!!!,报错内容如下

ValueError: Input matrix is not unitary: Matrix([[0.707106781186548 - 0.707106781186548*I, 0, 0, 0], [0, -0.707106781186548 - 0.707106781186548*I, 0, 0], [0, 0, 0.707106781186548 + 0.707106781186548*I, 0], [0, 0, 0, -0.707106781186548 + 0.707106781186548*I]])
2022.09.04 发现问题原因:
实际上这个矩阵的确是 unitary 的,kdotp_symmetry 程序没有判断出来,这是该程序的一个小bug。
例子3: TaAs2
该例子是 kdotp_symmetry 给出的例子: Example code for TaAs2 — kdotp-symmetry 1.0.1 documentation (greschd.ch),之后用 Qsymm 程序来进行验证。
kdotp_symmetry 程序
import sympy as sp from sympy.core.numbers import I import sympy.physics.matrices as sm from sympy.physics.quantum import TensorProduct import symmetry_representation as sr import kdotp_symmetry as kp # In this project we used the basis of tensor products of Pauli matrices pauli_vec = [sp.eye(2), *(sm.msigma(i) for i in range(1, 4))] basis = [TensorProduct(p1, p2) for p1 in pauli_vec for p2 in pauli_vec] # creating the symmetry operations c2y = sr.SymmetryOperation( rotation_matrix=[[0, 1, 0], [1, 0, 0], [0, 0, -1]], repr_matrix=sp.diag(I, -I, I, -I), repr_has_cc=False, numeric=False ) parity = sr.SymmetryOperation( rotation_matrix=-sp.eye(3), repr_matrix=sp.diag(1, 1, -1, -1), repr_has_cc=False, ) time_reversal = sr.SymmetryOperation( rotation_matrix=sp.eye(3), repr_matrix=TensorProduct(sp.eye(2), sp.Matrix([[0, -1], [1, 0]])), repr_has_cc=True, ) def print_result(order): """prints the basis for a given order of k""" print('Order:', order) for m in kp.symmetric_hamiltonian( c2y, parity, time_reversal, expr_basis=kp.monomial_basis(order), repr_basis=basis ): print(m) print() if __name__ == '__main__': for i in range(3): print_result(order=i) ### Output ''' Order: 0 Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, -1]]) Order: 1 Matrix([[0, 0, 0, kx - ky], [0, 0, kx - ky, 0], [0, kx - ky, 0, 0], [kx - ky, 0, 0, 0]]) Matrix([[0, 0, 0, -I*kx + I*ky], [0, 0, I*kx - I*ky, 0], [0, -I*kx + I*ky, 0, 0], [I*kx - I*ky, 0, 0, 0]]) Matrix([[0, 0, kx + ky, 0], [0, 0, 0, -kx - ky], [kx + ky, 0, 0, 0], [0, -kx - ky, 0, 0]]) Matrix([[0, 0, -I*kx - I*ky, 0], [0, 0, 0, -I*kx - I*ky], [I*kx + I*ky, 0, 0, 0], [0, I*kx + I*ky, 0, 0]]) Matrix([[0, 0, 0, kz], [0, 0, kz, 0], [0, kz, 0, 0], [kz, 0, 0, 0]]) Matrix([[0, 0, 0, -I*kz], [0, 0, I*kz, 0], [0, -I*kz, 0, 0], [I*kz, 0, 0, 0]]) Order: 2 Matrix([[kx**2 + ky**2, 0, 0, 0], [0, kx**2 + ky**2, 0, 0], [0, 0, kx**2 + ky**2, 0], [0, 0, 0, kx**2 + ky**2]]) Matrix([[kx**2 + ky**2, 0, 0, 0], [0, kx**2 + ky**2, 0, 0], [0, 0, -kx**2 - ky**2, 0], [0, 0, 0, -kx**2 - ky**2]]) Matrix([[kx*ky, 0, 0, 0], [0, kx*ky, 0, 0], [0, 0, kx*ky, 0], [0, 0, 0, kx*ky]]) Matrix([[kx*ky, 0, 0, 0], [0, kx*ky, 0, 0], [0, 0, -kx*ky, 0], [0, 0, 0, -kx*ky]]) Matrix([[kx*kz - ky*kz, 0, 0, 0], [0, kx*kz - ky*kz, 0, 0], [0, 0, kx*kz - ky*kz, 0], [0, 0, 0, kx*kz - ky*kz]]) Matrix([[kx*kz - ky*kz, 0, 0, 0], [0, kx*kz - ky*kz, 0, 0], [0, 0, -kx*kz + ky*kz, 0], [0, 0, 0, -kx*kz + ky*kz]]) Matrix([[kz**2, 0, 0, 0], [0, kz**2, 0, 0], [0, 0, kz**2, 0], [0, 0, 0, kz**2]]) Matrix([[kz**2, 0, 0, 0], [0, kz**2, 0, 0], [0, 0, -kz**2, 0], [0, 0, 0, -kz**2]]) '''
Qsymm 运行该例子
import numpy as np import sympy,sys import qsymm # Rotation rotU = np.array([ [1j, 0.0, 0.0, 0.0], [0.0, -1j, 0.0, 0.0], [0.0, 0.0,1j, 0.0], [0.0, 0.0, 0.0,-1j], ]) c2yS = qsymm.rotation(1/2, axis=[0,1,0],U=rotU) # Spatial inversion pU = np.array([ [1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, -1.0, 0.0], [0.0, 0.0, 0.0, -1.0], ]) pS = qsymm.inversion(3, U=pU) # Time reversal trU = np.array([ [0.0,-1.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0,-1.0], [0.0, 0.0, 1.0, 0.0], ]) trS = qsymm.time_reversal(3, U=trU) symmetries = [c2yS, pS, trS] # print(symmetries) dim = 3 total_power = 2 family = qsymm.continuum_hamiltonian(symmetries, dim, total_power, prettify=True) qsymm.display_family(family) ### Output: ''' Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) Matrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) Matrix([[0, 0, 0, k_z], [0, 0, k_z, 0], [0, k_z, 0, 0], [k_z, 0, 0, 0]]) Matrix([[0, 0, 0, I*k_z], [0, 0, -I*k_z, 0], [0, I*k_z, 0, 0], [-I*k_z, 0, 0, 0]]) Matrix([[0, 0, 0, k_x], [0, 0, k_x, 0], [0, k_x, 0, 0], [k_x, 0, 0, 0]]) Matrix([[0, 0, 0, I*k_x], [0, 0, -I*k_x, 0], [0, I*k_x, 0, 0], [-I*k_x, 0, 0, 0]]) Matrix([[0, 0, k_y, 0], [0, 0, 0, -k_y], [k_y, 0, 0, 0], [0, -k_y, 0, 0]]) Matrix([[0, 0, I*k_y, 0], [0, 0, 0, I*k_y], [-I*k_y, 0, 0, 0], [0, -I*k_y, 0, 0]]) Matrix([[k_x**2, 0, 0, 0], [0, k_x**2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) Matrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, k_x**2, 0], [0, 0, 0, k_x**2]]) Matrix([[k_z**2, 0, 0, 0], [0, k_z**2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) Matrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, k_z**2, 0], [0, 0, 0, k_z**2]]) Matrix([[k_x*k_z, 0, 0, 0], [0, k_x*k_z, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) Matrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, k_x*k_z, 0], [0, 0, 0, k_x*k_z]]) Matrix([[k_y**2, 0, 0, 0], [0, k_y**2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) Matrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, k_y**2, 0], [0, 0, 0, k_y**2]]) '''
不难发现,这两个python库得到的结果不同,原因是 Qsymm 求得的 c2y 对称操作矩阵不是按照晶格基矢的。
验证:将 kdotp_symmetry 中的 c2y 对称操作矩阵按照 Qsymm 一样,检验二者结果是否相同!
### # creating the symmetry operations c2y = sr.SymmetryOperation( #rotation_matrix=[[0, 1, 0], [1, 0, 0], [0, 0, -1]], rotation_matrix=[[-1, 0, 0], [0, 1, 0], [0, 0, -1]], repr_matrix=sp.diag(I, -I, I, -I), repr_has_cc=False, numeric=False ) ### Order: 0 Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, -1]]) Order: 1 Matrix([[0, 0, 0, kx], [0, 0, kx, 0], [0, kx, 0, 0], [kx, 0, 0, 0]]) Matrix([[0, 0, 0, -I*kx], [0, 0, I*kx, 0], [0, -I*kx, 0, 0], [I*kx, 0, 0, 0]]) Matrix([[0, 0, ky, 0], [0, 0, 0, -ky], [ky, 0, 0, 0], [0, -ky, 0, 0]]) Matrix([[0, 0, -I*ky, 0], [0, 0, 0, -I*ky], [I*ky, 0, 0, 0], [0, I*ky, 0, 0]]) Matrix([[0, 0, 0, kz], [0, 0, kz, 0], [0, kz, 0, 0], [kz, 0, 0, 0]]) Matrix([[0, 0, 0, -I*kz], [0, 0, I*kz, 0], [0, -I*kz, 0, 0], [I*kz, 0, 0, 0]]) Order: 2 Matrix([[kx**2, 0, 0, 0], [0, kx**2, 0, 0], [0, 0, kx**2, 0], [0, 0, 0, kx**2]]) Matrix([[kx**2, 0, 0, 0], [0, kx**2, 0, 0], [0, 0, -kx**2, 0], [0, 0, 0, -kx**2]]) Matrix([[kx*kz, 0, 0, 0], [0, kx*kz, 0, 0], [0, 0, kx*kz, 0], [0, 0, 0, kx*kz]]) Matrix([[kx*kz, 0, 0, 0], [0, kx*kz, 0, 0], [0, 0, -kx*kz, 0], [0, 0, 0, -kx*kz]]) Matrix([[ky**2, 0, 0, 0], [0, ky**2, 0, 0], [0, 0, ky**2, 0], [0, 0, 0, ky**2]]) Matrix([[ky**2, 0, 0, 0], [0, ky**2, 0, 0], [0, 0, -ky**2, 0], [0, 0, 0, -ky**2]]) Matrix([[kz**2, 0, 0, 0], [0, kz**2, 0, 0], [0, 0, kz**2, 0], [0, 0, 0, kz**2]]) Matrix([[kz**2, 0, 0, 0], [0, kz**2, 0, 0], [0, 0, -kz**2, 0], [0, 0, 0, -kz**2]])
该结果和 Qsymm 得出的一致。
综上可以发现:
kdotp_symmetry python 库仍存在一些 bug,以后要谨慎使用。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现