含YSR磁杂质的1D BCS超导体态密度模拟:代码问题与优化
问题排查与优化方案
一、LDOS异常的错误原因及修正
1. LDOS计算逻辑错误
BCS体系的电子局域态密度(LDOS)仅需考虑BdG本征态中电子分量的权重,你的代码错误引入了空穴分量的反向能量项,导致LDOS出现异常振荡且远隙处无法匹配BCS预期。正确的LDOS计算仅需对电子分量的洛伦兹峰叠加:
def compute_ldos(E_vals, E, psi, eta, site): """ 计算指定格点的电子局域态密度 """ # 提取当前格点的电子分量(对应BdG哈密顿量的上半部分) u1 = psi[4 * site, :] u2 = psi[4 * site + 1, :] # 仅累加电子分量的权重贡献 ldos = (np.abs(u1)**2 + np.abs(u2)**2) * (eta / np.pi) / ((E - E_vals)**2 + eta**2) return np.sum(ldos)
2. 哈密顿量边界构造错误
手动赋值的周期边界条件存在索引覆盖不全的问题,建议用循环逻辑统一处理,避免遗漏或错误:
# 处理周期边界(最后一个格点到第一个格点的hopping) last_block_start = N - 4 # 电子块 hopping H[last_block_start, 0] = -t H[last_block_start + 1, 1] = -t # 空穴块 hopping H[last_block_start + 2, 2] = t H[last_block_start + 3, 3] = t # 对称转置项 H[0, last_block_start] = -t H[1, last_block_start + 1] = -t H[2, last_block_start + 2] = t H[3, last_block_start + 3] = t
3. 维度与格点映射混淆
矩阵总维度N对应每个格点4个BdG分量,实际格点数为N//4。若site_index=250超出实际格点数范围(如N=2000时格点数为500,250是合法的),需确保杂质仅作用于目标格点,避免非预期的全局扰动。
二、大矩阵计算的性能优化
当N=8000时,全矩阵对角化时间复杂度为O(N³),效率极低,可采用以下两种方案:
1. 稀疏矩阵对角化
BdG哈密顿量是高度稀疏的,使用稀疏矩阵存储并仅求解目标能量范围的特征值,大幅减少计算量:
from scipy.sparse import lil_matrix, csr_matrix from scipy.sparse.linalg import eigsh # 用稀疏矩阵初始化哈密顿量 H_sparse = lil_matrix((N, N), dtype=complex) # 按原逻辑填充非零元(替换为稀疏矩阵赋值) # ... # 转换为CSR格式加速计算 H_sparse = H_sparse.tocsr() # 仅求解[-3,3]附近的200个特征值与特征向量 eigenvalues, eigenvectors = eigsh(H_sparse, k=200, sigma=0, which='LM')
2. 递归格林函数(RGF)方法
计算单个格点LDOS时,RGF无需对角化整个矩阵,时间复杂度为O(N),核心是通过递推计算格林函数的对角元:
def compute_ldos_rgf(E, delta, t, U, JS, eta, total_sites, target_site): # 初始化左右段格林函数 gl = np.array([[E - (U+JS), delta], [np.conj(delta), -E + (U+JS)]]) gr = gl.copy() # 递推计算中间段格林函数 for _ in range(total_sites - 1): # 构造传播子 prop = np.array([[E + t, delta], [np.conj(delta), -E + t]]) gl = np.linalg.inv(prop - np.dot(gl, np.array([[t, 0], [0, -t]]))) gr = np.linalg.inv(prop - np.dot(np.array([[t, 0], [0, -t]]), gr)) # 拼接杂质格点的格林函数 g_imp = np.linalg.inv(np.array([[E - (U+JS), delta], [np.conj(delta), -E + (U+JS)]]) - np.dot(np.array([[t, 0], [0, -t]]), np.dot(gl, np.array([[t, 0], [0, -t]])))) # 提取LDOS return -np.imag(np.trace(g_imp)) / (2 * np.pi)
该方法在大体系下可瞬间完成单个格点的LDOS计算。
内容的提问来源于stack exchange,提问作者ivana curci
相关产品推荐
相关产品推荐

