Полу-неявный Эйлер: одно изменение, огромный эффект

Поменяй местами две строки кода — и нестабильный интегратор станет надёжным. Это не магия, а симплектичность.

Полу-неявный (симплектический) метод Эйлера — вариант Эйлера, где координата обновляется по уже пересчитанной скорости; он не сохраняет энергию точно, но и не накапливает её систематически.

В чём отличие

Явный Эйлер сначала двигал координату по старой скорости, потом обновлял скорость. Полу-неявный делает наоборот: сначала обновляет скорость, а координату двигает уже по новой:

$$v_{n+1} = v_n + a_n \, \Delta t, \qquad x_{n+1} = x_n + v_{n+1} \, \Delta t.$$

Разница в одну строку, но последствия колоссальны. Этот метод относится к классу симплектических — сохраняющих особую геометрическую структуру механики. Практически это значит, что энергия не уходит в бесконечность и не затухает в ноль, а слегка колеблется вокруг истинного значения. Для игр это решающее свойство: маятник качается стабильно часами, планета летает по орбите без раскрутки.

Сравним энергию

Тот же осциллятор $a = -x$, тот же шаг $\Delta t = 0.1$, но новый порядок строк. Сравните энергию с прошлым уроком.

x, v, dt = 1.0, 0.0, 0.1
for n in range(11):
    E = 0.5*v*v + 0.5*x*x
    if n % 2 == 0:
        print(f"n={n:2d}  x={x:6.3f}  v={v:6.3f}  E={E:.4f}")
    a = -x
    v = v + a*dt    # сначала скорость
    x = x + v*dt    # потом координата по НОВОЙ скорости

Вывод:

n= 0  x= 1.000  v= 0.000  E=0.5000
n= 2  x= 0.970  v=-0.199  E=0.4903
n= 4  x= 0.901  v=-0.390  E=0.4824
n= 6  x= 0.797  v=-0.566  E=0.4775
n= 8  x= 0.661  v=-0.718  E=0.4763
n=10  x= 0.498  v=-0.843  E=0.4790

Энергия теперь не убегает: она колеблется около $0.48$ и не растёт. Если прогнать симуляцию на пять полных периодов, у явного Эйлера энергия раздувается в $\approx 22.7$ раза, а у полу-неявного остаётся $\approx 1.0003$ от исходной — практически идеально. Один и тот же шаг, одна переставленная строка — и разница между «взрывом» и стабильностью.

Как работает под капотом

Интуиция такая: явный Эйлер всегда использует устаревшую скорость и систематически промахивается в одну сторону. Полу-неявный «подсматривает» обновлённую скорость, и его ошибки на разных фазах колебания частично компенсируют друг друга — энергия не дрейфует, а осциллирует. Строго это доказывается через теорию симплектических отображений: метод сохраняет площадь в фазовом пространстве $(x, v)$, и потому траектория не может бесконечно раскручиваться или сжиматься.

Важная оговорка: симплектический метод сохраняет не саму энергию, а близкую к ней величину («теневую» энергию). Поэтому реальная энергия слегка колеблется, но остаётся ограниченной на сколь угодно долгом интервале. Для подавляющего большинства игр и интерактивных симуляций полу-неявный Эйлер — золотой стандарт: дёшев, как явный, но стабилен.

Частые ошибки

  • Случайно вернуться к явному порядку. При рефакторинге легко переставить строки обратно и получить «взрывающийся» маятник. Порядок «сначала $v$, потом $x$» — это контракт.
  • Ждать точного сохранения энергии. Энергия колеблется — это нормально; важно, что она не дрейфует.
  • Применять для жёстких систем без оглядки. При слишком большом шаге даже симплектический метод теряет устойчивость; шаг всё равно надо выбирать с умом.

Итог

  • Полу-неявный Эйлер: сначала $v_{n+1}=v_n+a_n\Delta t$, затем $x_{n+1}=x_n+v_{n+1}\Delta t$.
  • Он симплектический: энергия колеблется, но не дрейфует — система стабильна надолго.
  • На пяти периодах явный Эйлер раздувает энергию в $\sim 22$ раза, полу-неявный — почти не меняет.
  • Цена та же, что у явного, поэтому это стандартный выбор для игр.
Проверьте себя
1. Чем полу-неявный Эйлер отличается от явного?
AИспользует Δt² вместо Δt
BКоордината обновляется по уже пересчитанной (новой) скорости
CСчитает ускорение дважды
DНе использует ускорение
2. Что значит, что метод «симплектический»?
AОн точно сохраняет энергию
BОн сохраняет структуру фазового пространства, энергия не дрейфует, а колеблется
CОн работает только для пружин
DОн второго порядка точности
3. Почему полу-неявный Эйлер предпочтителен в играх?
AОн самый точный из всех методов
BОн стоит как явный, но стабилен для долгих колебаний и орбит
CОн не требует знать ускорение
DОн не накапливает ошибку округления