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! используется для остановки моделирования.

3 Примеры


Дмитрий Сергеевич Кулябов
Дмитрий Сергеевич Кулябов
Профессор кафедры теории вероятностей и кибербезопасности

Мои научные интересы включают физику, администрирование Unix и сетей.

Похожие