Python调用root_scalar求解fCf函数报math domain error错误
问题描述
程序除fCf函数相关逻辑外其余部分运行正常。整体采用双层for循环结构:外层循环中i值逐次递增,内层循环以ii遍历tau_analysis完成迭代计算,单个i值会对应多组由内层迭代生成的V_ratio、Re取值,但循环内求解fCf函数时持续触发报错。
第二层for循环实现代码如下:
for ii in tau_analysis: fLam = root_scalar(fLambda, args=(ii, C_v, Clo), method='toms748', bracket=[0.0, 10.0]) #print("lambda = ", fLam.root) Cld = 0.012 * pow(fLam.root, 0.5) * pow(ii, 1.1) #print("Cld =", Cld) V_ratio = sqrt(1 - (Cld - 0.0065 * beta * pow(Cld, 0.6)) / (fLam.root * cos(math.radians(ii)))) #print("V_ratio =", V_ratio) Fn = i/sqrt(g*pow(delta_volume, 1/3)) Re = (V_ratio*i*fLam.root*b)/visco #print("Fn =", Fn) #print("Reynolds =", Re) Cf = root_scalar(fCf, args = Re, method='toms748', bracket=[0,0.01]) print("Cf = ", Cf.root)
fCf函数定义代码如下:
def fCf(x, Re): return log10(Re*x) - 0.02/sqrt(x)
相同计算逻辑在MATLAB中运行无任何错误,Python运行时触发的完整报错回溯信息如下:
Traceback (most recent call last): File "C:\Users\27835\PycharmProjects\pythonProject\Savitsky (3).py", line 87, in <module> Cf = root_scalar(fCf, args = Re, method='toms748', bracket=[0,0.01]) File "C:\Users\27835\PycharmProjects\pythonProject\venv\lib\site-packages\scipy\optimize\_root_scalar.py", line 249, in root_scalar r, sol = methodc(f, a, b, args=args, **kwargs) File "C:\Users\27835\PycharmProjects\pythonProject\venv\lib\site-packages\scipy\optimize\_zeros_py.py", line 1373, in toms748 result = solver.solve(f, a, b, args=args, k=k, xtol=xtol, rtol=rtol, File "C:\Users\27835\PycharmProjects\pythonProject\venv\lib\site-packages\scipy\optimize\_zeros_py.py", line 1220, in solve status, xn = self.start(f, a, b, args) File "C:\Users\27835\PycharmProjects\pythonProject\venv\lib\site-packages\scipy\optimize\_zeros_py.py", line 1108, in start fa = self._callf(a) File "C:\Users\27835\PycharmProjects\pythonProject\venv\lib\site-packages\scipy\optimize\_zeros_py.py", line 1082, in _callf fx = self.f(x, *self.args) File "C:\Users\27835\PycharmProjects\pythonProject\Savitsky (3).py", line 40, in fCf return log10(Re*x) - 0.02/sqrt(x) ValueError: math domain error
报错核心为执行fCf函数内log10(Re*x) - 0.02/sqrt(x)计算时抛出ValueError: math domain error异常,需要定位问题触发原因并给出修复方案。
报错触发原因
- 求解区间左端点非法:传入
root_scalar的求解括号为[0, 0.01],toms748算法初始化时会先计算区间两个端点的函数值。当x=0时:sqrt(0)=0,0.02/sqrt(x)触发除零运算Re*0=0,实数域内log10(0)无定义,直接抛出数学域错误
- 传参格式不符合接口要求:
root_scalar的args参数要求传入可迭代的元组类型,原代码写args = Re直接传入单个数值,后续参数解包时也会触发错误,只是当前端点计算错误先抛出了异常。 - 跨平台求解逻辑差异:MATLAB的求根函数(如fzero)不会直接计算用户传入的端点0的函数值,会自动在区间内偏移取合法点计算,所以相同区间设置在MATLAB下不会报错。
修复方案
- 调整求解区间,将左端点从0替换为极小的合法正数,避开无定义点。摩擦系数Cf的物理取值范围通常在1e-5~0.01之间,可将区间设置为
[1e-8, 0.01] - 修正
args传参格式,将单个Re值包装为元组,即写为args=(Re,) - 可选优化:调用求解器前可先计算区间两端的
fCf返回值,确认两端函数值符号相反(toms748算法要求区间两端点函数值异号才能正常收敛),避免无意义报错。
修复后的求解代码如下:
Cf = root_scalar(fCf, args=(Re,), method='toms748', bracket=[1e-8, 0.01]) print("Cf = ", Cf.root)
内容的提问来源于stack exchange,提问作者david
相关产品推荐
相关产品推荐

