Есть ли идиоматический способ прекратить интеграцию после n обратных вызовов в DifferentialEquations.jl - PullRequest
5 голосов
/ 09 апреля 2019

Прежде всего, я использую библиотеку DifferentialEquations.jl, что просто фантастика!Во всяком случае, мой вопрос заключается в следующем:

Скажем, например, у меня есть следующее дифференциальное уравнение:

function f(du, u, t)
    du[1] = u[3]
    du[2] = u[4]
    du[3] = -u[1] - 2 * u[1] * u[2]
    du[4] = -u[2] - u[1]^2 + u[2]^2
end

, и у меня есть обратный вызов, который срабатывает каждый раз, когда траектория пересекает ось Y:

function condition(u, t, integrator)
    u[2]
end

Однако мне нужно, чтобы интеграция завершилась ровно через 3 перехода.Мне известно, что интеграция может быть прервана с помощью эффекта:

function affect!(integrator)
    terminate!(integrator)
end

, но как правильно подсчитать количество обратных вызовов до тех пор, пока не будет достигнут критерий завершения.Кроме того, есть ли способ распространить эту методологию на n событий с n различными значениями?

В моем исследовании мне часто нужно смотреть на карты Пуанкаре, а первый, второй, третий и т. Д. Возвращаться к карте, чтобыМне нужна структура, которая позволила бы мне выполнить это прекращение подсчета.Я все еще новичок в Юлии и поэтому пытаюсь усилить хороший идиоматический код на раннем этапе.Любая помощь приветствуется и, пожалуйста, не стесняйтесь просить разъяснений.

1 Ответ

5 голосов
/ 09 апреля 2019

Для solve имеется ключевое слово userdata, которое может быть полезно для этого.Это позволяет передавать объекты интегратору.Эти объекты могут быть творчески использованы функциями обратного вызова.

Если вы передадите userdata = Dict(:my_key=>:my_value) в solve, вы можете получить к нему доступ из integrator.opts.userdata[:my_key].

Вот минимальный пример, который контролирует, сколько раз вызывался обратный вызов до того, как он действительнозавершает симуляцию:

function f(du, u, t)
    du[1] = sin(t)
end
function condition(u, t, integrator)
    u[1] 
end

function affect!(integrator)
    integrator.opts.userdata[:callback_count] +=1
    if integrator.opts.userdata[:callback_count] == integrator.opts.userdata[:max_count]
        terminate!(integrator)
    end
end


callback = ContinuousCallback(condition, affect!)

u0 = [-1.]
tspan = (0., 100.)

prob = ODEProblem(f, u0, tspan)
sol = solve(prob; callback=callback, userdata=Dict(:callback_count=>0, :max_count=>3))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...