PyDSTool求解ODE系统时积分步长设置报错求助
PyDSTool求解ODE系统的积分步长参数错误解决方法
问题回顾
你尝试用PyDSTool求解自定义ODE系统,但在构造Generator时遇到了参数错误,报错提示Invalid keyword arguments for this class,你的代码和报错信息如下:
原代码
import PyDSTool as ds from PyDSTool import Par, Var import time from PyDSTool import * import math # 注意:原代码漏了导入math,需要补上! # 声明(符号)参数的名称和初始值 varepsilon = pow(10, -2) j = 2.5*pow(10, -5) e = 3.0 y8 = lambda y1,y5,y7: 1 / (1 - 2 / y1) * math.sqrt(y5 ** 2 + (1 - 2 / y1) * (1 + y1 ** 2 * y7 ** 2)) E0 = lambda y1,y8: (1 - 2 / y1) * y8 Phi0 = lambda y1,y7: y1 ** 2 * y7 # 根据参数计算非平凡边界平衡初始条件(推导见参考文献) u0 = -math.sqrt(-1 + math.sqrt(varepsilon ** 2 + 12) / varepsilon) * math.sqrt(2) / 6 v0 = 1 / (1 - 2 / e) * math.sqrt(j ** 2 + (1 - 2 / e) * (e ** 2 * u0 ** 2 + 1)) y08 = y8(y1=e, y5=j, y7=u0); E = E0(y1=e, y8=y08); Phi = Phi0(y1=e, y7=u0) z01, z03, z04, z05, z07, z08 = e, 0.0, 0.0, j, u0, v0 # 声明符号变量 z1, z3, z4, z5, z7, z8 = Var('z1'), Var('z3'), Var('z4'), Var('z5'), Var('z7'), Var('z8') # 创建符号量对象用于定义 p1 = -z1*z5/(z1 - 2); p3 = -z1**2 *z7; p4 = z8*(1 - 2/z1); Q1 = -z5**2/(z1*(z1 - 2)) + (z8**2/z1**3 - z7**2)*(z1 - 2); Q3 = 2*z5*z7/z1; Q4 = 2*z5*z8/(z1*(z1 - 2)); c1 = z1*z7*varepsilon; c3 = -z1*z5*varepsilon; C = z7*varepsilon/z1 - z8*(1 - 2/z1); d1 = -z1*z8*varepsilon; d3 = z1*z5*varepsilon; B = z1**2*z7 - z8*varepsilon*(1 - 2/z1); Omega = 1/(c1*d3*p3+c3*d1*p4-c3*d3*p1); # 微分方程 z1dot = z5; z3dot = z7; z4dot = z8; z5dot = Omega*(-Q1*c1*d3*p3 - Q1*c3*d1*p4 + Q1*c3*d3*p1 + B*c3*p4 + C*d3*p3 + E*d3*p3 - Phi*c3*p4); z7dot = -Omega*(Q3*c1*d3*p3 + Q3*c3*d1*p4 - Q3*c3*d3*p1 + B*c1*p4 - C*d1*p4 + C*d3*p1 - E*d1*p4 + E*d3*p1 - Phi*c1*p4); z8dot = Omega*(-Q4*c1*d3*p3 - Q4*c3*d1*p4 + Q4*c3*d3*p1 + B*c1*p3 - B*c3*p1 - C*d1*p3 - E*d1*p3 - Phi*c1*p3 + Phi*c3*p1); # 构建生成器 DSargs = args(name='Sining particle') #print(dir(DSargs)) #DSargs.pars = [varepsilon, j, e] DSargs.MaxNumPoints = 450 DSargs.MaxStepSize = 2e-2 DSargs.MinStepSize = 1e-5 DSargs.StepSize = e-2 DSargs.tdata = [0.0, 0.1] DSargs.varspecs = args(z1=z1dot, z3=z3dot, z4=z4dot, z5=z5dot, z7=z7dot, z8=z8dot) # 使用eval方法从参数值的符号定义中获取浮点值 DSargs.ics = args(z1=z01, z3=z03, z4=z04, z5=z05, z7=z07, z8=z08) ode = Generator.Vode_ODEsystem(DSargs) t = time.time() result = ode.compute('test') print("time for integration: %f" %(time.time() - t)) pts = result.sample() plt.plot(pts['t'], pts['z7'], label='x') plt.legend() plt.xlabel('t') plt.show()
报错信息
Traceback (most recent call last): File "C:\Users\mykola\Downloads\pydstool.py", line 65, in <module> ode = Generator.Vode_ODEsystem(DSargs) File "C:\Users\mykola\AppData\Local\Programs\Python\Python36-32\lib\site-packages\PyDSTool\Generator\Vode_ODEsystem.py", line 47, in __init__ ODEsystem.__init__(self, kw) File "C:\Users\mykola\AppData\Local\Programs\Python\Python36-32\lib\site-packages\PyDSTool\Generator\ODEsystem.py", line 61, in __init__ self.checkArgs(kw) File "C:\Users\mykola\AppData\Local\Programs\Python\Python36-32\lib\site-packages\PyDSTool\Generator\baseclasses.py", line 1069, in checkArgs raise PyDSTool_KeyError('Invalid keyword arguments for this class') PyDSTool.errors.PyDSTool_KeyError: 'Invalid keyword arguments for this class'
错误原因
你犯了几个关键错误:
- 积分步长参数的位置错误:PyDSTool的
Vode_ODEsystem不接受MaxStepSize、MinStepSize、StepSize这些参数作为顶层键,这些属于VODE求解器的算法配置参数,必须放在algparams字典中。 - 参数名称不匹配:PyDSTool对VODE的参数名有特定要求,比如你用的
StepSize应该是initial_step,MaxStepSize对应max_step,MinStepSize对应min_step。 - 额外问题:原代码漏了导入
math模块,会导致运行时报错;另外MaxNumPoints不是VODE的参数,如果你需要固定输出点数,应该在采样时设置。
修正后的代码
下面是修改后的完整代码,重点标注了修改部分:
import PyDSTool as ds from PyDSTool import Par, Var import time from PyDSTool import * import math # 补上缺失的math导入 # 声明(符号)参数的名称和初始值 varepsilon = pow(10, -2) j = 2.5*pow(10, -5) e = 3.0 y8 = lambda y1,y5,y7: 1 / (1 - 2 / y1) * math.sqrt(y5 ** 2 + (1 - 2 / y1) * (1 + y1 ** 2 * y7 ** 2)) E0 = lambda y1,y8: (1 - 2 / y1) * y8 Phi0 = lambda y1,y7: y1 ** 2 * y7 # 根据参数计算非平凡边界平衡初始条件(推导见参考文献) u0 = -math.sqrt(-1 + math.sqrt(varepsilon ** 2 + 12) / varepsilon) * math.sqrt(2) / 6 v0 = 1 / (1 - 2 / e) * math.sqrt(j ** 2 + (1 - 2 / e) * (e ** 2 * u0 ** 2 + 1)) y08 = y8(y1=e, y5=j, y7=u0); E = E0(y1=e, y8=y08); Phi = Phi0(y1=e, y7=u0) z01, z03, z04, z05, z07, z08 = e, 0.0, 0.0, j, u0, v0 # 声明符号变量 z1, z3, z4, z5, z7, z8 = Var('z1'), Var('z3'), Var('z4'), Var('z5'), Var('z7'), Var('z8') # 创建符号量对象用于定义 p1 = -z1*z5/(z1 - 2); p3 = -z1**2 *z7; p4 = z8*(1 - 2/z1); Q1 = -z5**2/(z1*(z1 - 2)) + (z8**2/z1**3 - z7**2)*(z1 - 2); Q3 = 2*z5*z7/z1; Q4 = 2*z5*z8/(z1*(z1 - 2)); c1 = z1*z7*varepsilon; c3 = -z1*z5*varepsilon; C = z7*varepsilon/z1 - z8*(1 - 2/z1); d1 = -z1*z8*varepsilon; d3 = z1*z5*varepsilon; B = z1**2*z7 - z8*varepsilon*(1 - 2/z1); Omega = 1/(c1*d3*p3+c3*d1*p4-c3*d3*p1); # 微分方程 z1dot = z5; z3dot = z7; z4dot = z8; z5dot = Omega*(-Q1*c1*d3*p3 - Q1*c3*d1*p4 + Q1*c3*d3*p1 + B*c3*p4 + C*d3*p3 + E*d3*p3 - Phi*c3*p4); z7dot = -Omega*(Q3*c1*d3*p3 + Q3*c3*d1*p4 - Q3*c3*d3*p1 + B*c1*p4 - C*d1*p4 + C*d3*p1 - E*d1*p4 + E*d3*p1 - Phi*c1*p4); z8dot = Omega*(-Q4*c1*d3*p3 - Q4*c3*d1*p4 + Q4*c3*d3*p1 + B*c1*p3 - B*c3*p1 - C*d1*p3 - E*d1*p3 - Phi*c1*p3 + Phi*c3*p1); # 构建生成器 DSargs = args(name='Sining particle') DSargs.tdata = [0.0, 0.1] DSargs.varspecs = args(z1=z1dot, z3=z3dot, z4=z4dot, z5=z5dot, z7=z7dot, z8=z8dot) DSargs.ics = args(z1=z01, z3=z03, z4=z04, z5=z05, z7=z07, z8=z08) # 关键修改:将积分步长参数放入algparams字典,使用正确的参数名 DSargs.algparams = { 'max_step': 2e-2, # 对应原来的MaxStepSize 'min_step': 1e-5, # 对应原来的MinStepSize 'initial_step': 1e-2 # 对应原来的StepSize,这里我改成了1e-2,如果需要e-2=1.0可以替换回去 } ode = Generator.Vode_ODEsystem(DSargs) t = time.time() result = ode.compute('test') print("time for integration: %f" %(time.time() - t)) # 关键修改:用numpts参数控制输出点数,替代原来的MaxNumPoints pts = result.sample(numpts=450) plt.plot(pts['t'], pts['z7'], label='x') plt.legend() plt.xlabel('t') plt.show()
关键修改说明
- 参数位置调整:所有与积分步长相关的配置都移到了
algparams字典中,这是PyDSTool中VODE求解器要求的参数结构。 - 参数名称修正:使用VODE求解器认可的参数名:
max_step、min_step、initial_step,而非自定义的名称。 - 输出点数控制:通过
result.sample(numpts=450)来生成固定数量的采样点,替代原来无效的MaxNumPoints参数。 - 补全依赖:添加了
import math,避免运行时出现NameError。
内容的提问来源于stack exchange,提问作者Mykola Fenyk
相关产品推荐
相关产品推荐

