一、非简并波函数的固定规范
在之前这篇文章“SSH模型中的Wilson loop(附Python代码)”中,用到了非简并波函数的固定规范方法。这里重新提下,并给出例子。
原理:循环规范的参数,当波函数的某个指定元素为实数时,停止循环,返回波函数。
补充:除了循环查找,也可以对某个指定元素乘一个相反的相位角,达到实数化的目的,这种运算效率更高,推荐使用这种方法。
Python代码:
"""
This code is supported by the website: https://www.guanjihuan.com
The newest version of this code is on the web page: https://www.guanjihuan.com/archives/22604
"""
import numpy as np
import cmath
def find_vector_with_fixed_gauge_by_making_one_component_real(vector, precision=0.005, index=None):
vector = np.array(vector)
if index == None:
index = np.argmax(np.abs(vector))
sign_pre = np.sign(np.imag(vector[index]))
for phase in np.arange(0, 2*np.pi, precision):
sign = np.sign(np.imag(vector[index]*cmath.exp(1j*phase)))
if np.abs(np.imag(vector[index]*cmath.exp(1j*phase))) < 1e-9 or sign == -sign_pre:
break
sign_pre = sign
vector = vector*cmath.exp(1j*phase)
if np.real(vector[index]) < 0:
vector = -vector
return vector
vector_1 = np.array([np.sqrt(0.5), np.sqrt(0.5)])*cmath.exp(np.random.uniform(0, 1)*1j)
vector_2 = np.array([1, 0])*cmath.exp(np.random.uniform(0, 1)*1j)
print('随机规范的原向量:', vector_1)
angle = cmath.phase(vector_1[0])
print('固定规范后的向量(方法1):', vector_1*cmath.exp(-1j*angle))
vector_1 = find_vector_with_fixed_gauge_by_making_one_component_real(vector_1, precision=0.001)
print('固定规范后的向量(方法2):', vector_1)
print('\n随机规范的原向量:', vector_2)
angle = cmath.phase(vector_2[0])
print('固定规范后的向量(方法1):', vector_2*cmath.exp(-1j*angle))
vector_2 = find_vector_with_fixed_gauge_by_making_one_component_real(vector_2, precision=0.001)
print('固定规范后的向量(方法2):', vector_2)
运行结果:
随机规范的原向量: [0.6050246+0.36598529j 0.6050246+0.36598529j]
固定规范后的向量(方法1): [0.70710678+0.j 0.70710678+0.j]
固定规范后的向量(方法2): [0.70710672+0.00030346j 0.70710672+0.00030346j]
随机规范的原向量: [0.97845851+0.20644355j 0. +0.j ]
固定规范后的向量(方法1): [1.+0.j 0.+0.j]
固定规范后的向量(方法2): [0.99999994+0.00034615j 0. -0.j ]
二、简并波函数的固定规范
需要说明的是:这个方法涉及到三重循环查找参数,因此效率不是特别高,暂不推荐使用,仅作参考。
此外,对关键的函数可以通过Numba加速,速度会快很多,但用上Numba后运行可能会出一些警告,需要对问题一个个排除。参考:Numba加速Python的时间测试。
原理:对简并波函数进行一般性的幺正变换,当得到满足规定形式的规范时,停止参数的循环,返回波函数。
计算公式[1]:
Python代码(说明:如果需要在整个布里渊区都连续,那么需要全程固定一个indxe1和index2。这里只是作为例子,一个k值的波函数给出一个index1和index2):
"""
This code is supported by the website: https://www.guanjihuan.com
The newest version of this code is on the web page: https://www.guanjihuan.com/archives/22604
"""
import numpy as np
import math
import cmath
# from numba import jit
# @jit
def rotation_of_degenerate_vectors(vector1, vector2, index1=None, index2=None, precision=0.01, criterion=0.01, show_theta=0):
vector1 = np.array(vector1)
vector2 = np.array(vector2)
if index1 == None:
index1 = np.argmax(np.abs(vector1))
if index2 == None:
index2 = np.argmax(np.abs(vector2))
if np.abs(vector1[index2])>criterion or np.abs(vector2[index1])>criterion:
for theta in np.arange(0, 2*math.pi, precision):
if show_theta==1:
print(theta)
for phi1 in np.arange(0, 2*math.pi, precision):
for phi2 in np.arange(0, 2*math.pi, precision):
vector1_test = cmath.exp(1j*phi1)*vector1*math.cos(theta)+cmath.exp(1j*phi2)*vector2*math.sin(theta)
vector2_test = -cmath.exp(-1j*phi2)*vector1*math.sin(theta)+cmath.exp(-1j*phi1)*vector2*math.cos(theta)
if np.abs(vector1_test[index2])<criterion and np.abs(vector2_test[index1])<criterion:
vector1 = vector1_test
vector2 = vector2_test
break
if np.abs(vector1_test[index2])<criterion and np.abs(vector2_test[index1])<criterion:
break
if np.abs(vector1_test[index2])<criterion and np.abs(vector2_test[index1])<criterion:
break
return vector1, vector2
def hamiltonian_of_bbh_model(kx, ky, gamma_x=0.5, gamma_y=0.5, lambda_x=1, lambda_y=1):
# label of atoms in a unit cell
# (2) —— (0)
# | |
# (1) —— (3)
hamiltonian = np.zeros((4, 4), dtype=complex)
hamiltonian[0, 2] = gamma_x+lambda_x*cmath.exp(1j*kx)
hamiltonian[1, 3] = gamma_x+lambda_x*cmath.exp(-1j*kx)
hamiltonian[0, 3] = gamma_y+lambda_y*cmath.exp(1j*ky)
hamiltonian[1, 2] = -gamma_y-lambda_y*cmath.exp(-1j*ky)
hamiltonian[2, 0] = np.conj(hamiltonian[0, 2])
hamiltonian[3, 1] = np.conj(hamiltonian[1, 3])
hamiltonian[3, 0] = np.conj(hamiltonian[0, 3])
hamiltonian[2, 1] = np.conj(hamiltonian[1, 2])
return hamiltonian
# For kx=0
print('\nFor kx=0:\n')
eigenvalue, eigenvector = np.linalg.eigh(hamiltonian_of_bbh_model(kx=0, ky=0))
print(eigenvalue, '\n')
print(eigenvector[:, 0])
print(eigenvector[:, 1], '\n')
# For kx=0.005
print('\nFor kx=0.005:\n')
eigenvalue, eigenvector = np.linalg.eigh(hamiltonian_of_bbh_model(kx=0.005, ky=0))
print(eigenvalue, '\n')
print(eigenvector[:, 0])
print(eigenvector[:, 1], '\n\n')
# Rotaion
vector1, vector2 = rotation_of_degenerate_vectors(eigenvector[:, 0], eigenvector[:, 1], precision=0.01, criterion=0.01, show_theta=1)
print()
print(vector1)
print(vector2, '\n')
运行结果:
For kx=0:
[-2.12132034 -2.12132034 2.12132034 2.12132034]
[ 0. +0.j -0.70710678+0.j -0.5 +0.j 0.5 +0.j]
[-0.70710678+0.j 0. +0.j 0.5 +0.j 0.5 +0.j]
For kx=0.005:
[-2.1213174 -2.1213174 2.1213174 2.1213174]
[-0.1795765 +0.j -0.68392353+0.00094454j -0.35662876+0.00024463j
0.61058577+0.00094413j]
[ 0.68392418+0.j -0.17957633+0.00024801j -0.61058388+0.00178739j
-0.35662876+0.0002479j ]
0.0
0.01
0.02
0.03
0.04
0.05
0.06
0.07
0.08
0.09
0.1
0.11
0.12
0.13
0.14
0.15
0.16
0.17
0.18
0.19
0.2
0.21
0.22
0.23
0.24
0.25
[-0.00478835+0.j -0.70708989+0.00097654j -0.4966029 +0.00067923j
0.50337277+0.00097611j]
[ 0.70709057+0.00000000e+00j -0.00478834+6.61300191e-06j
-0.50337094+1.67129993e-03j -0.49660337+6.61013877e-06j]
参考资料:
[1] “An anomalous higher-order topological insulator” Supplemental material
【说明:本站主要是个人的一些笔记和代码分享,内容可能会不定期修改。为了使全网显示的始终是最新版本,这里的文章未经同意请勿转载。引用请注明出处:https://www.guanjihuan.com】
博主你好,我想问下 ,为什么当波函数的某个指定元素为实数时,这样就固定了一个规范?我不是很理解
如果是非零元素,乘任意相位exp(1j*phase)都会导致该元素为非实数,所以当为实数时是一个特殊的相位。每个波函数都这么规定,那么波函数就具有连续性,求导就不容易发散。
谢谢博主!