Как избежать обнаружения событий начальных условий в scipy solve_ivp

#python #scipy #ode

Вопрос:

Я работаю над моделированием нейронных цепей. Схема состоит из восьми сегментов, и я решаю активность каждого сегмента с помощью дифференциальных уравнений. Дифференциальное уравнение является

dE[i]/dt = f(b[i] * E[i]) (i = 0, 1, ... 7)

и b[i] изменяется при E[i] снижении порога снизу вверх. Чтобы реализовать это, я создал следующий код, используя scipy’s solve_ivp .

 seg_number = 8
t0 = 0
tend = 2e5
x0 = [0]*seg_number

def gen_event(i):    
    def event(t, x):
        return x[i] - threshold
    event.terminal = True
    event.direction = 1
    return event

events = [gen_event(i) for i in range(seg_number)]


def func(t, x): #differential equation
    dx = []
    for i in range(seg_number):
    ・・・
    return(dx)


while True:
    orbit = solve_ivp(func, (t0, tend), x0, events = events)
    if orbit.status == 1:
        ・・・  # update b[i]

        t0 = orbit.t[-1]
        x0 = orbit.y[:, -1].copy()

    else:
        break
 

Однако в этом коде при b[i] изменении начальных условий и повторном решении дифференциальных уравнений начальное условие определяется как событие, вызывающее бесконечный цикл. Если я добавлю небольшую сумму к начальным условиям, решение продолжится, но я не думаю, что это хорошее решение.

 x0 = orbit.y[:, -1].copy()   1e-12
 

Комментарии:

1. Я смутно помню аналогичный вопрос, где проблема заключалась в том, что размер начального шага был слишком мал. Таким образом, вы можете попытаться установить начальный размер шага для следующего запуска orbit.t[-1]-orbit.t[-2])/2 . // Другая идея состоит в том , чтобы конкретно x0[i]=threshold 1e-16 указать , что интерполированное последнее состояние может быть округлено в компоненте i в меньшую сторону, так что добавление 1 ulp или около x0[i] =2.5e-16*abs(x0[i]) того решит эту проблему без ущерба для решения.