Довідник Оновлено у липні 2026 · Фізичний довідник

Шпаргалка з чисельних методів

Набір чисельних інструментів, на якому базується кожна симуляція в реальному часі на цьому сайті: інтегратори ОДР, пошук коренів, розв'язання лінійних систем, інтерполяція та основи ШПФ. Кожен запис містить формулу, порядок похибки, примітку щодо стійкості та готовий JavaScript-код.

🎯 Навіщо потрібні чисельні методи

Кожна фізична симуляція — стрибучий м'яч, шматок тканини, планета на орбіті — описується диференціальними рівняннями, які майже ніколи не мають замкнутого аналітичного розв'язку, щойно з'являються зіткнення, нелінійні сили або багато взаємодіючих тіл. Чисельні методи перетворюють неперервні рівняння на дискретні правила оновлення, які комп'ютер може виконувати щокадру, обмінюючи точність на швидкість і контрольовану похибку.

Вибір правильного методу — це компроміс між трьома осями: точністю (наскільки близько до справжньої траєкторії), стійкістю (чи не вибухає похибка з часом) і вартістю (кількість обчислень функції на крок). Ця сторінка збирає методи, які реально використовуються в симуляціях на цьому сайті, з практичними порадами, які підручники часто оминають.

🌀 Інтегратори ОДР

Стан симуляції (позиція, швидкість) розвивається за диференціальним рівнянням першого порядку $\dot{\mathbf{y}} = f(t, \mathbf{y})$. Інтегратор просуває $\mathbf{y}$ від $t$ до $t+h$, використовуючи обчислення $f$.

Явний (прямий) метод Ейлера

Формула оновлення — порядок 1 $$\mathbf{y}_{n+1} = \mathbf{y}_n + h\, f(t_n, \mathbf{y}_n)$$

Найпростіший інтегратор: одне обчислення функції на крок, тривіальний у реалізації, але систематично накопичує енергію в осцилюючих системах (маятник, змодельований методом Ейлера, повільно розкручується назовні). Локальна похибка $O(h^2)$, глобальна — $O(h)$.

function eulerStep(state, force, h) {
  // state = { x, v }, force(x, v) повертає прискорення
  const a = force(state.x, state.v);
  state.x += h * state.v;
  state.v += h * a;
  return state;
}

Напівнеявний (симплектичний) метод Ейлера

Формула оновлення — порядок 1, симплектичний $$\mathbf{v}_{n+1} = \mathbf{v}_n + h\, a(\mathbf{x}_n) \qquad \mathbf{x}_{n+1} = \mathbf{x}_n + h\, \mathbf{v}_{n+1}$$

Поміняйте порядок — спершу оновіть швидкість, а потім використайте нову швидкість для оновлення позиції. Та сама вартість, що й у прямого Ейлера, все ще лише перший порядок точності, але метод симплектичний: енергія коливається навколо істинного значення замість того, щоб дрейфувати геть. Це стандартний інтегратор майже у кожному ігровому фізичному рушії реального часу (Box2D, Cannon-es, Rapier).

function symplecticEulerStep(state, force, h) {
  const a = force(state.x, state.v);
  state.v += h * a;        // спершу швидкість
  state.x += h * state.v;  // потім позиція, з новою v
  return state;
}

Швидкісний метод Верле (Velocity Verlet)

Формула оновлення — порядок 2, симплектичний, оборотний у часі $$\mathbf{x}_{n+1} = \mathbf{x}_n + h\mathbf{v}_n + \tfrac{1}{2}h^2 a(\mathbf{x}_n)$$ $$\mathbf{v}_{n+1} = \mathbf{v}_n + \tfrac{1}{2}h\left[a(\mathbf{x}_n) + a(\mathbf{x}_{n+1})\right]$$

Робочий кінь для систем частинок, молекулярної динаміки та розв'язувачів тканини/канатів. Точність другого порядку, симплектичний (обмежена похибка енергії) та оборотний у часі. Коштує два обчислення прискорення на крок, коли прискорення залежить від швидкості; дешевше — коли ні.

function verletStep(state, accel, h) {
  const a0 = accel(state.x);
  state.x += h * state.v + 0.5 * h * h * a0;
  const a1 = accel(state.x);
  state.v += 0.5 * h * (a0 + a1);
  return state;
}

Рунге-Кутта 4-го порядку (RK4)

Формула оновлення — порядок 4, чотири обчислення $$k_1 = f(t_n, y_n)\qquad k_2 = f(t_n+\tfrac{h}{2}, y_n+\tfrac{h}{2}k_1)$$ $$k_3 = f(t_n+\tfrac{h}{2}, y_n+\tfrac{h}{2}k_2)\qquad k_4 = f(t_n+h, y_n+hk_3)$$ $$y_{n+1} = y_n + \tfrac{h}{6}(k_1 + 2k_2 + 2k_3 + k_4)$$

Чотири обчислення функції на крок дають точність четвертого порядку — глобальна похибка $O(h^4)$ проти $O(h)$ у Ейлера. Чудово підходить для гладкої, неколізійної динаміки (орбітальна механіка, траєкторії камери), де потрібна висока точність при більшому кроці. RK4 не симплектичний: за дуже довгих інтегрувань (мільйони орбіт) енергія все одно може дрейфувати, лише набагато повільніше, ніж у методі Ейлера.

function rk4Step(y, t, h, f) {
  const k1 = f(t, y);
  const k2 = f(t + h / 2, add(y, scale(k1, h / 2)));
  const k3 = f(t + h / 2, add(y, scale(k2, h / 2)));
  const k4 = f(t + h, add(y, scale(k3, h)));
  return add(y, scale(
    add(add(k1, scale(k2, 2)), add(scale(k3, 2), k4)),
    h / 6
  ));
}
Інтегратор Порядок Обчислень/крок Симплектичний Найкраще для
Прямий Ейлер O(h) 1 Ні Лише для навчання — уникати в продакшені
Симплектичний Ейлер O(h) 1 Так Ігрова фізика, системи частинок
Швидкісний Верле O(h²) 1–2 Так Тканина, канати, молекулярна динаміка
RK4 O(h⁴) 4 Ні Орбіти, гладкий неколізійний рух
Неявний (зворотний) Ейлер O(h) Безумовно стійкий Жорсткі системи (position-based dynamics, тканина)

⚖ Стійкість і крок інтегрування

Метод є стійким для заданого кроку $h$, якщо малі похибки не зростають необмежено протягом багатьох кроків. Для тестового рівняння $\dot{y} = \lambda y$ (де $\lambda$ комплексне, $\text{Re}(\lambda) \le 0$) кожен явний метод має обмежену область абсолютної стійкості у комплексній площині $h\lambda$.

Умова стійкості прямого методу Ейлера $$|1 + h\lambda| \le 1$$

Для демпфованої системи пружина-маса з жорсткістю $k$ і масою $m$ це перетворюється на практичне правило:

Межа кроку для явного інтегратора (жорстка пружина) $$h \lesssim \frac{2m}{\sqrt{km}} = \frac{2}{\omega_0}, \qquad \omega_0 = \sqrt{k/m}$$

Перевищте це — і жорстка пружина (з великим k), змодельована явним інтегратором, почне коливатися з амплітудою, що зростає, і врешті "вибухне" — класична помилка "тканина, що трясеться і вибухає". Три способи виправлення, за пріоритетом:

// Цикл з фіксованим кроком і акумулятором (відв'язує фізику від частоти рендерингу)
let accumulator = 0;
const FIXED_DT = 1 / 60;

function frame(now) {
  accumulator += (now - lastTime) / 1000;
  lastTime = now;
  while (accumulator >= FIXED_DT) {
    physicsStep(FIXED_DT);
    accumulator -= FIXED_DT;
  }
  render(accumulator / FIXED_DT); // альфа інтерполяції
  requestAnimationFrame(frame);
}
Ніколи не масштабуйте фізику лише за дельтою кадру

Множення прискорень на сирий, необмежений deltaTime робить симуляцію недетермінованою й нестійкою при просіданні частоти кадрів. Завжди обмежуйте deltaTime (наприклад, максимум 0.1с) і надавайте перевагу циклу з фіксованими підкроками для всього, що складніше за іграшкову демонстрацію.

🔍 Пошук коренів

Використовується для запитів часу зіткнення (time-of-impact), зворотної кінематики та розв'язання неявних рівнянь зв'язків $g(\mathbf{x}) = 0$.

Метод бісекції

Гарантована збіжність, лінійна швидкість $$c = \frac{a+b}{2}, \quad \text{залишити половину, де} \text{sign}(f)\text{ змінюється}$$

Вимагає, щоб $f(a)$ і $f(b)$ мали протилежні знаки. Завжди збігається, ділячи навпіл інтервал на кожній ітерації — надійно, але повільно ($O(\log_2(\epsilon^{-1}))$ ітерацій для точності $\epsilon$).

Метод Ньютона-Рафсона

Квадратична збіжність поблизу кореня $$x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}$$

Збігається набагато швидше за бісекцію, коли взагалі збігається, але може розходитись або циклити, якщо початкове наближення далеко від кореня або $f'(x_n) \approx 0$. Активно використовується у неперервному виявленні зіткнень для уточнення точного часу удару.

function newtonRaphson(f, fPrime, x0, tol = 1e-6, maxIter = 50) {
  let x = x0;
  for (let i = 0; i < maxIter; i++) {
    const fx = f(x);
    if (Math.abs(fx) < tol) return x;
    const dfx = fPrime(x);
    if (Math.abs(dfx) < 1e-12) break; // похідна занадто плоска, вихід
    x -= fx / dfx;
  }
  return x; // найкраще наближення — виклик повинен перевірити результат
}

Бісекція проти Ньютона — коли що використовувати

Метод Збіжність Потребує похідну Гарантована збіжність
Бісекція Лінійна Ні Так (якщо в дужках)
Ньютон-Рафсон Квадратична Так (аналітична або чисельна) Ні
Метод січних Надлінійна (~1.618) Ні (наближає її) Ні

🔢 Лінійні системи

Розв'язання $A\mathbf{x} = \mathbf{b}$ трапляється по всій симуляції: розв'язувачі зв'язків (контакти твердих тіл, канати), неявне інтегрування та якобіани зворотної кінематики.

Ітерація Гаусса-Зейделя

Використовується більшістю розв'язувачів зв'язків реального часу $$x_i^{(k+1)} = \frac{1}{a_{ii}}\left(b_i - \sum_{j<i} a_{ij}x_j^{(k+1)} - \sum_{j>i} a_{ij}x_j^{(k)}\right)$$

Фізичні рушії (Box2D, Bullet, Cannon-es) розв'язують контактні та шарнірні зв'язки жменькою ітерацій Гаусса-Зейделя (або проєктивного Гаусса-Зейделя для нерівностей, наприклад, неперетину) на кадр замість точного розв'язку — кілька ітерацій наближеної відповіді щокадру кращі, ніж один точний розв'язок, що не встигає в дедлайн.

// N проходів Гаусса-Зейделя по розрідженій системі зв'язків
function solveConstraints(constraints, iterations = 10) {
  for (let iter = 0; iter < iterations; iter++) {
    for (const c of constraints) {
      c.solve(); // оновлює швидкості на місці, використовує останні значення
    }
  }
}

LU-розклад (щільний, прямий)

Для невеликих щільних систем (наприклад, розв'язку тензора інерції 3×3 або 4×4) прямий LU-розклад дешевий і точний: факторизуйте $A = LU$ один раз, а потім розв'язуйте дві трикутні системи для кожної правої частини через пряму/зворотну підстановку — $O(n^3)$ на факторизацію, $O(n^2)$ на кожен розв'язок.

Метод Вартість Найкраще для
Гаусс-Зейдель / PGS O(k·nnz) Великі розріджені системи зв'язків, реальний час (обмежена кількість ітерацій)
Метод спряжених градієнтів O(k·nnz) Симетричні додатно визначені системи (неявна тканина/FEM)
LU-розклад O(n³) Невеликі щільні системи (тензори інерції, якобіани IK)
Правило Крамера O(n!) Ніколи в продакшені — лише 2×2/3×3 вручну

📈 Інтерполяція

Лінійна інтерполяція (lerp)

lerp(a, b, t) $$\text{lerp}(a, b, t) = a + t(b - a), \quad t \in [0,1]$$

Кубічний сплайн Ерміта / Катмулла-Рома

Гладка траєкторія через контрольні точки, неперервність C¹ $$p(t) = \tfrac{1}{2}\Big[(2p_1) + (-p_0+p_2)t + (2p_0-5p_1+4p_2-p_3)t^2 + (-p_0+3p_1-3p_2+p_3)t^3\Big]$$

Сплайн Катмулла-Рома проходить точно через кожну контрольну точку (на відміну від Безьє) і є стандартним вибором для траєкторій камери та процедурних доріг/трас у симуляціях на цьому сайті.

Сферична лінійна інтерполяція (slerp)

Стала кутова швидкість між двома обертаннями $$\text{slerp}(q_0, q_1, t) = q_0 \left(q_0^{-1}q_1\right)^t, \quad t \in [0,1]$$

На відміну від покомпонентної lerp-інтерполяції кватерніонів, slerp інтерполює вздовж дуги великого кола, тому швидкість обертання лишається сталою — це критично важливо для плавного змішування орієнтації камери та персонажа.

Метод Неперервність Проходить через точки? Типове застосування
Лінійна (lerp) C⁰ Так Просте змішування анімації, переходи кольору
Катмулл-Ром Так Траєкторії камери, процедурна генерація трас/доріг
Кубічна Безьє C¹ (на сегмент) Лише кінцеві точки Криві плавності, рух UI
Slerp Стала кутова швидкість Так (обертання) Змішування обертання камери / кістки

∫ Чисельне диференціювання та інтегрування

Центральна різниця (похідна)

Похибка O(h²) — краще за пряму різницю $$f'(x) \approx \frac{f(x+h) - f(x-h)}{2h}$$

Використовується для чисельного наближення якобіана або нормального вектора (наприклад, градієнта поля знакованої відстані), коли аналітична похідна недоступна. Центральна різниця скасовує доданок похибки першого порядку, який несе наївна пряма різниця $\frac{f(x+h)-f(x)}{h}$.

Метод трапецій (інтегрування)

Похибка O(h²) на інтервал $$\int_a^b f(x)\,dx \approx h\left[\tfrac{1}{2}f(x_0) + f(x_1) + \dots + f(x_{n-1}) + \tfrac{1}{2}f(x_n)\right]$$

Метод Сімпсона (інтегрування)

Похибка O(h⁴) — точний для кубічних функцій $$\int_a^b f(x)\,dx \approx \frac{h}{3}\Big[f(x_0) + 4f(x_1) + 2f(x_2) + 4f(x_3) + \dots + f(x_n)\Big]$$

Метод Сімпсона проводить параболу через кожні три точки і є найдешевшим значним покращенням точності порівняно з методом трапецій для гладких підінтегральних функцій — корисний під час попереднього обчислення таблиць довжини дуги для сплайнів (потрібні для руху зі сталою швидкістю вздовж траєкторії).

🌊 Основи ШПФ

Швидке перетворення Фур'є (ШПФ) перетворює сигнал з часового/ просторового домену в частотний за $O(n\log n)$ замість $O(n^2)$ наївного дискретного перетворення Фур'є (ДПФ) — основа симуляції океанських хвиль (Tessendorf/FFT ocean), аудіореактивної візуалізації та розв'язувачів рідин на GPU.

Дискретне перетворення Фур'є (визначення) $$X_k = \sum_{n=0}^{N-1} x_n\, e^{-2\pi i k n / N}, \quad k = 0, \dots, N-1$$

Алгоритм Кулі-Тьюкі рекурсивно розбиває суму на доданки з парними та непарними індексами, зменшуючи розмір задачі вдвічі на кожному рівні рекурсії — тому $N$ зазвичай має бути степенем двійки для класичної реалізації radix-2, яка використовується у більшості WebGL-шейдерів океану.

Алгоритм Вартість Обмеження
Наївне ДПФ O(n²) Немає — працює для будь-якого N
Radix-2 ШПФ Кулі-Тьюкі O(n log n) N має бути степенем 2
Змішано-радіксне ШПФ O(n log n) N розкладається на невеликі прості множники

На практиці океанські та водні симуляції на цьому сайті виконують ШПФ на compute-шейдері GPU (або через прохід ping-pong render target у WebGL), щоб перетворити спектр висотного поля на зміщення — сітка 256×256 коштує приблизно 16 проходів radix-2 "метеликів" (butterflies) на вимір.

📊 Таблиця порядків похибки

Зменшення кроку $h$ удвічі для методу порядку $p$ знижує похибку приблизно у $2^p$ разів. Використовуйте це, щоб емпірично перевірити збіжність методу (екстраполяція Річардсона): зменшіть $h$ удвічі, перезапустіть і переконайтеся, що похибка падає в очікуваному співвідношенні.

Метод Порядок глобальної похибки Зниження похибки при h/2
Прямий / зворотний Ейлер O(h)
Симплектичний Ейлер O(h)
Швидкісний Верле O(h²)
Метод трапецій O(h²)
RK4 O(h⁴) 16×
Метод Сімпсона O(h⁴) 16×

⚠ Типові пастки

Правило великого пальця

Почніть із симплектичного Ейлера з фіксованим підкроком 60 Гц для всього інтерактивного. Переходьте на Верле, коли потрібне краще збереження енергії (тканина, канати, частинки), і на RK4 лише для гладких, неколізійних траєкторій, де точність важливіша за чисту швидкість (траєкторії камери, попередній перегляд орбіт).