积分报错:integrand()缺失DOS_E参数及量子电容计算问题
量子电容计算报错修复方案
错误分析与修复要点
1. TypeError: integrand()缺少参数DOS_E
- 问题根源:
scipy.integrate.quad调用被积函数时仅传入积分变量E,但你定义的integrand要求两个参数,且DOS_E完全冗余——你已经通过interpolate(E)获取对应能量的DOS值,无需额外传入。 - 修复:删除
integrand的DOS_E参数,直接在函数内调用interpolate(E)获取DOS值。
2. RuntimeWarning: cosh溢出
- 问题根源:你的
E数据单位是电子伏特(eV),但kb*T的单位是焦耳(J),直接计算E/(2*kb*T)会得到极大数值(如18eV对应约2e21),导致np.cosh计算溢出。 - 修复:将玻尔兹曼常数转换为eV/K单位(
kb_eV = kb / e),使kb_eV*T与E、mu单位一致,计算时数值保持在合理范围。
3. 核心公式错误
- 问题根源:量子电容的被积函数应为
DOS(E) * sech²((E - mu)/(2*kb*T)),你原代码错误写成(interpolate(E)-mu)*sech_func(E)*DOS_E,完全偏离正确公式。 - 修复:修正被积函数为正确形式,同时
sech函数需传入(E - mu)而非E,匹配费米分布导数的形式。
完整修复代码
import openpyxl from scipy.integrate import quad import numpy as np # 读取Excel数据 wb = openpyxl.load_workbook(filename='DOS.xlsx', data_only=True) o_sheet = wb["Sheet1"] # 提取E和DOS数据,跳过表头 E_data = [cell.value for col in o_sheet.iter_cols(min_col=1, max_col=1) for cell in col][1:] DOS_data = [cell.value for col in o_sheet.iter_cols(min_col=2, max_col=2) for cell in col][1:] # 转换为numpy数组并指定类型 E_data = np.array(E_data, dtype=np.float64) DOS_data = np.array(DOS_data, dtype=np.float64) # 物理常数 e = 1.602e-19 # 元电荷 (C) kb = 1.381e-23 # 玻尔兹曼常数 (J/K) kb_eV = kb / e # 转换为eV/K单位 T = 300 # 温度 (K) mu = 0.5 # 化学势 (eV) E_min = E_data.min() E_max = E_data.max() # 定义sech平方函数,使用eV单位避免溢出 def sech_squared(E): x = (E - mu) / (2 * kb_eV * T) return 1 / np.cosh(x)**2 # 插值获取任意能量下的DOS值 def interpolate_dos(E): return np.interp(E, E_data, DOS_data) # 正确的被积函数 def integrand(E): dos = interpolate_dos(E) return dos * sech_squared(E) # 计算量子电容 # 公式:Cq = (e² / (4 * kb * T)) * ∫ DOS(E) * sech²((E-mu)/(2kbT)) dE prefactor = (e ** 2) / (4 * kb * T) integral_result, _ = quad(integrand, E_min, E_max) Cq = prefactor * integral_result print(f"Quantum capacitance: {Cq:.3e} F/m^2")
额外优化说明
- 移除了未使用的
convolve和重复导入的quad。 - 简化数据提取逻辑,通过切片直接跳过表头,无需单独删除元素。
- 将
sech_func重命名为sech_squared,更贴合实际计算的函数形式。 - 保留
quad返回的误差项(_),如需分析积分精度可直接调用。
内容的提问来源于stack exchange,提问作者Loknath Basak
相关产品推荐
相关产品推荐

