计算电导G时积分费米-狄拉克导数与传输函数出现TypeError错误求助
计算电导G时积分费米-狄拉克导数与传输函数出现TypeError错误求助
嘿,我来帮你捋捋这个问题!你碰到的TypeError: only size-1 arrays can be converted to Python scalars错误,核心原因是**scipy.integrate.quad是专门处理标量函数积分的工具**,但你的代码给它喂了向量化的输入,还把预生成的整个E数组塞进了参数里,导致quad完全没法正确处理。
咱们一步步来修正:
错误原因拆解
quad要求被积分的函数,必须针对单个输入的E值返回一个标量结果,但你的fermi_integral函数里用了预生成的向量E,返回的是数组,完全不符合quad的要求。- 你把整个E数组作为
args传给了quad,但E应该是quad自动遍历的积分变量,根本不需要手动传入。
修正方案
我们需要调整函数逻辑,让它能接收单个E值,计算对应的费米导数和传输函数值,再用quad完成积分。另外,如果你想得到每个传输通道(对应不同的n)的电导贡献,再求和得到总电导,也可以分开计算每个通道的积分。
修正后的代码
import numpy as np import scipy.constants as phys import scipy.integrate as integrate import math # 定义固定参数 fermi = 2.5 kT = 0.2 n_range = np.arange(0, 6) # 传输通道的n范围 def fermi_derivative(E_val, fermi, kT): """计算费米-狄拉克函数的导数df/dE""" exp_term = np.exp((E_val - fermi)/kT) return exp_term / ((exp_term + 1)**2) / kT def transmission_single_n(E_val, n): """单个n对应的传输函数项""" return 1/(1 + np.exp(-2*np.pi * (E_val - (n - 0.5)*3))) def total_transmission(E_val, n_range): """所有n对应的传输函数求和结果""" return sum(transmission_single_n(E_val, n) for n in n_range) def integrand(E_val, fermi, kT, n_range): """被积分的核心函数:df/dE * t(E)""" return fermi_derivative(E_val, fermi, kT) * total_transmission(E_val, n_range) # 执行积分:积分变量为E,范围0到无穷大 result, error = integrate.quad(integrand, 0, np.inf, args=(fermi, kT, n_range)) # 计算总电导G(修正物理常数:用hbar更符合电导公式惯例) G = -(2 * phys.e**2 / phys.hbar) * result print(f"积分结果(含误差): {result} ± {error}") print(f"总电导G: {G}") # 可选:计算每个n对应的单独电导贡献 individual_contributions = [] for n in n_range: def single_channel_integrand(E_val): return fermi_derivative(E_val, fermi, kT) * transmission_single_n(E_val, n) res, err = integrate.quad(single_channel_integrand, 0, np.inf) individual_contributions.append(res) print(f"通道n={n}的积分贡献: {res} ± {err}") total_G_from_individual = -(2 * phys.e**2 / phys.hbar) * sum(individual_contributions) print(f"单个通道求和得到的总电导G: {total_G_from_individual}")
关键改动说明
- 拆分函数:把费米导数、单个通道传输函数、总传输函数拆成独立函数,逻辑更清晰,也方便quad处理单个E值。
- 移除预生成E数组:quad会自动选择最优的积分点,不需要手动生成E序列。
- 参数传递修正:给quad的
args只传固定参数(fermi, kT, n_range),积分变量E由quad自动传入。 - 物理常数修正:电导公式里通常用约化普朗克常数
hbar(phys.hbar),而不是完整的phys.Planck,这个细节也帮你调整了。
这样调整后,代码就能正常运行,得到积分结果和总电导了。如果需要每个传输通道的单独贡献,也可以通过循环计算每个n的积分来验证总电导。
备注:内容来源于stack exchange,提问作者jimmymac
相关产品推荐
相关产品推荐

