Julia. DifferentialEquations.jl. Callback functions
Использование обратного вызова функций в пакете DifferentialEquations.jl.
Содержание
1 Типы обратных вызовов
ContinuousCallback
(непрерывный): срабатывает, когда непрерывная функция условия достигает нуля. В других средствах реализуется как событие (event).DiscreteCallback
(дискретный): срабатывает, когда функция условия истинна.VectorContinuousCallback
(векторный): эквивалентен вектору непрерывных обратных вызовов. Позволяет указать, когда вызывается какой обратный вызов.
1.1 Непрерывный обратный вызов
1ContinuousCallback(condition,affect!,affect_neg!;
2 initialize = INITIALIZE_DEFAULT,
3 idxs = nothing,
4 rootfind=true,
5 save_positions=(true,true),
6 interp_points=10,
7 abstol=10eps(),reltol=0)
1.2 Дискретный обратный вызов
1DiscreteCallback(condition,affect!;
2 initialize = INITIALIZE_DEFAULT,
3 save_positions=(true,true))
condition
- функцияcondition(u,t,integrator)
, определяющая, когда следует использовать обратный вызов. Обратный вызов инициируется, если условие истинно (true
).affect!
- функцияaffect!(integrator)
, которая может изменять текущее состояние интегратора.save_positions
- логический кортеж для сохранения до или послеaffect!
. Это сохранение может происходить непосредственно до, после события, во время события. Оно не зависит от таких параметров, какsaveat
,save_everystep
и т.д. (например, еслиsaveat = [1.0,2.0,3.0]
, то можно добавить точку сохранения в2.1
, если условие верно). Чтобы прерывистые изменения обрабатывались правильно (без ошибок), необходимо установитьsave_positions = (true, true)
.initialize
- функцияfunction(c,u,t,integrator)
, которая может использоваться для инициализации состояния обратного вызоваc
.
1.3 Векторный непрерывный обратный вызов
1VectorContinuousCallback(condition,affect!,affect_neg!,len;
2 initialize = INITIALIZE_DEFAULT,
3 idxs = nothing,
4 rootfind=true,
5 save_positions=(true,true),
6 interp_points=10,
7 abstol=10eps(),reltol=0)
1VectorContinuousCallback(condition,affect!,len;
2 initialize = INITIALIZE_DEFAULT,
3 idxs = nothing,
4 rootfind=true,
5 save_positions=(true,true),
6 affect_neg! = affect!,
7 interp_points=10,
8 abstol=10eps(),reltol=0)
1.4 Набор обратных вызовов
- Несколько обратных вызовов можно объединить в один набор:
1CallbackSet(cb1,cb2,cb3)
- Можно передать столько угодно обратных вызовов. Когда решатели обнаруживают несколько обратных вызовов, применяются следующие правила:
ContinuousCallbacks
иVectorContinuousCallbacks
применяются передDiscreteCallbacks
(потому, что они часто реализуют обнаружение событий, которое возвращает временной шаг на величину, меньшему, чемdt
).- Для
ContinuousCallbacks
иVectorContinuousCallbacks
применяется только первый из них (шаг времени рассчитывается только по первому). - Затем по порядку применяются
DiscreteCallbacks
. Порядок имеет значение только для условий: если предыдущий обратный вызов изменяет функция таким образом, что следующий обратный вызов больше не считает условие истинным, он не будет применяться.
2 Применение обратных вызовов
- Обратный вызов передаётся решателю:
1sol = solve(prob,alg,callback=cb)
- Когда используется обратный вызов, режим сохранения по умолчанию отключён. Это потому, что в противном случае события дважды сохраняли бы одно из значений. Чтобы снова включить стандартное поведение при сохранении, необходимо, чтобы первое значение
save_positions
было истинным хотя бы для одного обратного вызова. - Общая проблема обратных вызовов заключается в том, что они вызывают большие изменения шага, поэтому после такого изменения может быть разумным уменьшить
dt
. Например,set_proposed_dt!
используется для установки следующего шага иterminate!
используется для остановки моделирования.