Python 根据解的大小,将Scipy ode积分到未知极限t

Python 根据解的大小,将Scipy ode积分到未知极限t,python,scipy,ode,numerical-integration,Python,Scipy,Ode,Numerical Integration,我正在模拟带电粒子在电磁场中的运动,并使用scipy ode。显然,这里的代码是简化的,但可以作为示例使用。我遇到的问题是,我想在限制r之后结束积分,而不是限制t。积分dx/dt,直到范数(x)>r 我不想把函数改成积分r,因为位置是t的函数。我能对无关变量做定积分吗 import numpy as np import matplotlib.pyplot as plt from scipy.integrate import odeint def RHS(state, t, Efield, q,

我正在模拟带电粒子在电磁场中的运动,并使用scipy ode。显然,这里的代码是简化的,但可以作为示例使用。我遇到的问题是,我想在限制r之后结束积分,而不是限制t。积分dx/dt,直到范数(x)>r

我不想把函数改成积分r,因为位置是t的函数。我能对无关变量做定积分吗

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint

def RHS(state, t, Efield, q, mp):

    ds0 = state[3]
    ds1 = state[4]
    ds2 = state[5]
    ds3 = q/mp * Efield*state[0]
    ds4 = q/mp * Efield*state[1]
    ds5 = q/mp * Efield*state[2]

    r = np.linalg.norm((state[0], state[1], state[2]))

    # if r > 30000 then do stop integration.....?

    # return the two state derivatives
    return [ds0, ds1, ds2, ds3, ds4, ds5]


ts = np.arange(0.0, 10.0, 0.1)
state0 = [1.0, 2.0, 3.0, 0.0, 0.0, 0.0]

Efield=1.0
q=1.0
mp=1.0

stateFinal = odeint(RHS, state0, ts, args=(Efield, q, mp))
print(np.linalg.norm(stateFinal[-1,0:2]))

您可以通过使用逐步执行集成来控制流程。例如:

from scipy.integrate import ode
t_initial = 0
dt = 0.1
t_max = 10
r = ode(RHS).set_initial_value(state0, t_initial).set_f_params(Efield, q, mp)
solution = [state0]
while r.successful() and r.t < t_max:
    new_val = r.integrate(r.t + dt)
    solution.append(new_val)
    if np.linalg.norm((new_val[0], new_val[1], new_val[2])) > 30000:
        break
print(solution)
从scipy.integrate导入ode
t_初始值=0
dt=0.1
t_max=10
r=ode(RHS)。设置初始值(state0,t_initial)。设置参数(Efield,q,mp)
解决方案=[state0]
当r.successful()和r.t
请注意,RHS的签名必须更改为
def RHS(t,state,Efield,q,mp):
对于
ode
,自变量排在第一位,与
odeint
不同


输出是以自变量的
dt
增量计算的解决方案,直到循环结束(因为达到
t_max
,或者积分器失败,或者遇到了
中断
的条件)

一种变体是搜索目标函数中的符号变化,并使用类似割线法的方法来细化根的时间,如中所做。一般的主题是“事件处理”。这实际上非常好,因为我还可以根据当前条件选择动态时间步。那是另一件让我汗流浃背的事!