如果你想坚持 Python 科学家族,你可以选择Assimulo。Assimulo 是许多 ODE 集成器的包装器,提供通用接口。如果您碰巧在 Windows 上运行,您可以在Christoph Gohlke 的页面上找到轮子。
Assimulo 允许处理状态事件以允许 ODE 的 RHS 函数中的不连续性,但您也可以使用它们在满足特定条件时停止迭代。
该过程是定义一个函数“state_events”来分析事件是否发生,第二个函数“handle_event”相应地采取行动(改变状态方程,改变变量,停止迭代,......)。
Assimulo 包中的示例是一个撞到墙上的钟摆。当它撞到墙上时,状态会发生变化,即方向应该反转并且应该损失一些能量。
我修改了 Assimulo 附带的示例,使用一个简单的指数衰减问题,我要求在物种浓度低于阈值时停止积分。请参阅下面的代码。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as N
import pylab as P
from assimulo.problem import Explicit_Problem
from assimulo.solvers.sundials import CVode
from assimulo.exception import TerminateSimulation
def run_example():
def decay(t,y):
yd_0 = -0.5*y[0]
return N.array([yd_0])
def state_events(t,y,sw):
"""
This is our function that keep track of our events, when the sign
of any of the events has changed, we have an event.
"""
return N.array([y[0]-50.0])
def handle_event(solver, event_info):
"""
Event handling. This functions is called when Assimulo finds an event as
specified by the event functions.
"""
state_info = event_info[0] #We are only interested in state events info
if state_info[0] != 0: #Check if the first event function have been triggered
raise TerminateSimulation
#Initial values
y0 = [100.0] #Initial states
t0 = 0.0 #Initial time
#Create an Assimulo Problem
mod = Explicit_Problem(decay, y0, t0)
mod.state_events = state_events #Sets the state events to the problem
mod.handle_event = handle_event #Sets the event handling to the problem
mod.name = 'Simple decay' #Sets the name of the problem
#Create an Assimulo solver (CVode)
sim = CVode(mod)
#Specifies options
sim.discr = 'BDF' #Sets the discretization method
sim.iter = 'Newton' #Sets the iteration method
sim.rtol = 1.e-8 #Sets the relative tolerance
sim.atol = 1.e-6 #Sets the absolute tolerance
#Simulation
ncp = 200 #Number of communication points
tfinal = 10.0 #Final time
t,y = sim.simulate(tfinal, ncp) #Simulate
#Print event information
sim.print_event_data()
#Plot
P.plot(t,y)
P.show()
if __name__=='__main__':
run_example()