scipy 在python中使用odeint时,如何对变量执行离散时间相关更新?

egmofgnx  于 2022-11-09  发布在  Python
关注(0)|答案(1)|浏览(211)

我尝试模拟一个ODEs系统,在这样做的时候,我需要在odeint运行的特定时间点将某些变量的当前值增加一些因子。
我试着做了下面的事情。但是我注意到时间值是浮点数。这使得我很难指定一个if条件来添加一个特定的值到输入中,这些输入将在过程中进一步集成。
下面是问题案例。请帮助我解决这个问题。

def myfunc(s,t):

# whenever the time is an even day, increase the variable by 2

  if t%2==0:
  addition = 2
  else:
  addition = 0

  dsdt = (2s+8)+addition
  return dsdt

问题:函数中的传入时间(t)是一个浮点数。这使我无法对特定的离散偶数值't'应用if条件

详细说明:

(a)I定义一个时间跨度向量,Tspan = np·linspace(1,100,100),初始条件s 0 = [3]。
(b)当我运行“odeint(myfunc,s 0,Tspan)“时,我需要在特定的时间点(比如t = 25,50,75)用某个因子更新传入的”s“变量。
(c)但是对于我来说,如果我把print(t)放在“myfunc(s,t)"里面,我可以注意到传入的”t“是浮点类型的。
(d)需要注意的一点是,# myfunc在Tspan向量中被称为〉#Timesteps,这就是为什么运行时't'是浮点数。
(e)如果我尝试执行“if ceil”(t)%25==0或round”对于接下来的4到5个函数调用返回相同的int(这是因为在两个后续时间点之间发生的函数调用数量很少),因此,如果我尝试在ceiled上使用if条件更新传入的“s”(t),则对“s”的更新是针对4到5个后续函数调用执行的,而不是在特定时间点执行一次,并且应当避免这种情况。
我希望我的问题是清楚的。请帮助我,如果你可以的话,在某种程度上。谢谢乡亲!

ggazkfy8

ggazkfy81#

所有“专业”解算器都使用内部自适应步长。输出步长对此没有影响或影响很小。每个方法步骤都使用ODE函数的多次求值。根据输出采样频率,每个输出步骤可以有多个内部步骤,或者从同一个内部步骤插入多个输出步骤。
你所描述的期望机制与你的示例代码不同。你的示例代码改变了ODE的一个参数。描述相当于状态改变。虽然第一个可以在步长控制器上以有害但可恢复的影响来完成,但第二个需要一个具有状态改变动作的事件-动作机制。这在任何一个脚本解算器中都没有实现。
最好的方法是求解变化之间的段,在每个段结束时执行状态变化,然后用新的状态重新开始积分。在时间段和值段上使用数组连接,以获得大型解函数表。

t1=np.linspace(0,25,25+1); 
u10=u0
u1=odeint(fun,u10,t1); 

t2=t1+25; # or a more specific construction for non-equal interval lengths
u20 = 3*u1[-1] # or some other change of the last state u1[-1]
u2=odeint(fun,u20,t2); 

t3=t2+25; 
u30 = u2[-1].copy();
u30[0] -=5; # or what the actual state change was supposed to be
u3=odeint(fun,u30,t3); 

# combine the segments for plotting, gives vertical lines at the event locations

t=np.concatenate([t1,t2,t3]); 
u=np.concatenate([u1,u2,u3]);

对于更多的段,最好将其组织在循环中,特别是如果状态在事件位置处通过取决于几个参数的统一过程而改变。

相关问题