План: модель воздуха в трёх масштабах
Состояние на 04.10.2026: модель воздуха в игре с 1.0.0 и постоянно развивается (решение пользователя 04.10: план активный); волны А–Б закрыты и лежат в docs/archive/plan/, выводы — в docs/registry/findings.md (раздел air-model); не запущены AM-11 (производительность, сеть, Windows) и AM-12 (полёт пилота, документация) — TODO.md T-02.
Исходный статус: в работе с 29.09.2026 (ветка feature/air-model, координатор К0). Заменяет docs/archive/plan/wind-field.md как главный план. Из старого плана переиспользуются разделы, на которые ниже есть ссылки: сетка и σ-уровни, клипмапы WF-14, решатель порциями на локальном RenderingDevice, экран загрузки, запасной путь и конфиг, проверки словами пилота, калибровка по схеме Professor (WF-16), F3-стрелки, трава. Основание — прототип tools/research/heat_ca/ (итог — out/summary.md, раздел «Слои как матрицы») и исследование docs/research/slope_wind.md.
Документ — для координатора агентов: модули, задачи со скоупом, файлами, приёмкой и оценкой.
Контракты систем (решение пользователя, 29.09.2026): интерфейсы на стыках задач — docs/contracts/air-model.md, контрактные тесты — tests/contracts/. Исполнители работают в рамках контракта; менять интерфейс — только через К0 (версия контракта +1, уведомление потребителей, их правка сразу же). Ход работ — docs/archive/plan/air-model-progress.md.
Идея (пользователь, 29.09.2026)
Ощущение полёта складывается из двух вещей: общая правдивость («над прогретым полем — термик, на бровке дует, за гребнем сосёт») и локальные возмущения («крыло шатает, как в жизни»). Между ними — пузыри термиков. Отсюда три масштаба:
| Масштаб | Что это для пилота | Размер / время | Чем считаем | Где считаем |
|---|---|---|---|---|
| 1. Среднее поле | где дует, где держит склон, где термики «стоят», потолок, снос | клетка 200 м по области, 100/50 м вокруг пилота; поле на игровой час | уравнения Буссинеска, установившееся решение Пикаром | GPU, при загрузке и раз в час фоном |
| 2. Термики | ядро, край, «промахнулся — провалился», жизнь пузыря | 100–500 м, минуты | нынешняя модель термиков; место, сила, потолок, снос — из поля 1 | CPU, как сейчас |
| 3. Возмущения | болтанка, порывы, удары вниз, ротор | < 50 м, секунды | статистика турбулентности (спектры), сила — из поля 1 | CPU, как сейчас |
Главный принцип связи: масштабы 2 и 3 не имеют своих подгоночных ручек для «где и насколько» — они берут это из поля 1 по физическим формулам. Свои у них только форма и жизнь (пузырь, спектр).
Решения пользователя (не обсуждаются)
Физическая корректность в заявленных пределах модели — главное требование. В документации каждого масштаба явно: какие законы учтены, какие приближения, чего модель не умеет. Отзывы пилота — ориентир для проверки, не запрет; провалы и болтанку пилоту нравятся — после изменений сверить, что остались правдоподобными.
Параметры — с физическим смыслом и из физики/измерений; «крутить под нравится» нельзя. Калибровка — по схеме Professor (WF-16 старого плана), по числовым наблюдаемым с погрешностями.
Считаем в compute-шейдерах Godot (Vulkan, RenderingDevice), переносимо на AMD (видеокарты пилотов неизвестны, AMD). Без CUDA, Rust, расширений NVIDIA.
Сеть: каждый клиент считает поле сам, небольшое расхождение допустимо; поле не входит в
world_key/world_hash.Если расчёт дольше 1 с — этап загрузки «Рассчитываем ветер» / “Computing wind”, окно не замирает.
Решения из ответов на старый план остаются в силе: клипмапы вокруг пилота (WF-14), поле включено по умолчанию, F3 — стрелки поля, трава по полю, постоянно падающие тесты удалены, устойчивость — из погоды.
Мелкая сетка мельче 25 м не нужна: всё, что меньше клетки, пилот ощущает как масштаб 3.
Калибровка (29.09.2026): показания пилота в подгонку не входят (большой разброс; с заниженной погрешностью тянули бы физику под впечатление) — только сравнение после калибровки, расхождения — в «Границы модели». Подгонка — только по количественным данным (полевые измерения, подобие из литературы) с учётом систематики сетки; подгоняются только реально неизвестные параметры, известные из литературы — фиксируются со ссылкой. Подробно — AM-09.
Структурные правки А1 (30.09.2026): Pr_t = 0,85 (Kays 1994; K_θ = K/Pr_t на всех осях) — окончательно; τ-выхолаживание — только диабатической части θ′ (
docs/archive/plan/air-model-a1.md). Цена итерации +18 % на 400 м (второй проход тепла) — известна и принята.Сходимость (А2, 30.09.2026): несходимость решения 200 м, 3 м/с с нагревом (предельный цикл K(Ri)–θ′ у выходной границы, ревью А1.3) — в А2. Цель — максимально реалистичная физика ветра, но не уровня суперкомпьютера прогноза погоды: брать наименее вычислительно затратный вариант из ревью — первый кандидат
k_relax0,5 → 0,25;heat_sweeps= 8 дороже; пересмотр условия θ′ = 0 на выходной грани — только если дёшево.Волна А2–А4 и Б (01.10.2026): запустить А2 ∥ А3 ∥ А4, затем волну Б (совместная калибровка Askervein + Perdigão — Opus; затем решение К по α в игре с записью в журнал; Моррис — только если калибровка неудовлетворительна). А2 — на новых параметрах (λ/h 0,031, α 0,235, z0 0,09), наименее затратная правка; первый шаг — матрица
run.py matrixсk_relax0,25, затемheat_sweeps8; приёмка — всеcbl-случаи обоих наборов сходятся. А3 — записка по hb/const,local_k,heat_mode(литература, без кода). А4 — случай Perdigão по образцу Askervein (рельеф своим конвейером, наблюдаемые Menke 2019), решатель не трогать. GPU — черезflock /tmp/heat_ca_gpu.lockиdp job. Слияния вfeature/air-model— только по одобрению главной сессии; релизная сборка и AM-11 — не запускать. План дня —PLAN_2026-10-01_air_model.md(главная копия, не в git).Уточнение 01.10.2026: волну Б сегодня не начинаем — доделываем только блок А (А2; А3, А4 приняты). После приёмки А2 — шлюз, отчёт главной сессии. Слияния air/a2, air/a3, air/a4 в
feature/air-model— только по одобрению. Цена итерации из замеров А2 не окончательная: GPU делил посторонний процесс.Ротор и рывки поверх поля (шлюз 01.10.2026, решение пользователя): вариант В2 + Р1 одной задачей AM-08в. Правим только поле решателя в
feature/air-model; аналитику (main, запасной путь, полоса края поля) с еёdanger_sink_per_wind/burst_per_windне трогаем. Ощущения пилота — ориентир, модель под них не подгоняем; приёмка AM-08 «±20 % от базы AM-00» пересмотрена по физике (опоры — σ_w = 0,14·ΔU, Bell & Mehta 1990, и Menke 2019), расхождение с пилотом — наблюдение в журнале, не дефект. Числа, не проходящие физически, — перепроверка исследователем с веб-поиском.Модель воздуха готова (решение пользователя 01.10.2026, после AM-08в): пики с болтанкой за гребнем (−6…−9 м/с, до 0,6–0,7·U_H) и уточнения пузыря/механической σ_w над следом дальше не подгоняем — на таком объёме данных точнее не откалибровать, выжато всё по достоверности. Дальнейшая калибровка — только при новых данных или отзывах. AM-11 и AM-12 — в TODO, без запуска. Слияние в main — главная сессия.
Цель
Заменить набор независимых формул (глобальный ветер одного направления + w_ridge + эвристики термиков по карте нагрева) на одно физическое среднее поле воздуха, из которого масштабы 2 и 3 берут свои параметры. Что должно появиться само, без отдельных правил:
- разгон на бровке, полоса подъёма по размеру горы (~2 H), «труба» в седловине ×1,5 вдоль её оси, ослабление при косом ветре, обтекание сопок сбоку (слова пилота,
docs/archive/plan/wind-field.md→ «Решения пользователя»); - приток к прогретому склону у земли, подъём над ним, опускание над долиной;
- инверсия как крышка: потолок термиков, растекание под ней;
- снос и наклон термиков ветром, взаимодействие ветра и тепла (склоновый + фоновый ветер).
Не делаем
- LES (вихреразрешающий счёт по времени на мелкой сетке) — минуты на кадр, не для игры.
- Влагу и облака на поле — следующий шаг, не в этом плане (см. «На потом»). Основание облаков пока из погодной модели, как сейчас.
- Шаги по времени автомата как основной счёт — только переход между часами (на потом, если плавности пересчёта не хватит).
- Не шлифуем: «несовершенство = реализм»; после калибровки — полёт пилота.
Масштаб 1: среднее поле (Пикар)
Физика и границы модели
- Уравнения Буссинеска: сохранение массы (∇·u = 0 точно), импульс (перенос, вязкость турбулентная — постоянная или по высоте, трение о землю, плавучесть), нелокальное давление (проекция), тепло (перенос, диффузия, нагрев от земли, выхолаживание к фону с τ).
- Фон: профиль θ̄(z) из погодной модели на час (градиент, инверсия, её высота и сила) и ветер прогноза (профиль по высоте).
- Нагрев земли: поток тепла по склонам от солнца на час — из
surface_heating.gd/ погоды (облачность уменьшает). - Ищем установившееся решение: средняя циркуляция за ~час при перемешанном воздухе.
- Не умеет: пузыри и отрыв вихрей (это масштаб 2 и 3), влага и облака, излучение кроме τ-выхолаживания, вращение Земли, сжимаемость. При сильном ветре и мелкой клетке установившегося решения может не быть (срыв за гребнем) — тогда Пикар не сходится; запасной ход — см. ниже.
Метод (как в опыте 2, tools/research/heat_ca/exp2_picard/)
Итерация Пикара: (1) импульс Озеена при замороженном переносе, псевдошаг, плавучесть полунеявно, прогонки по линиям; (2) проекция SIMPLEC: ∇·(K∇φ) = ∇·u*, один V-цикл многосеточного, сглаживание прогонками; (3) тепло, псевдошаг, прогонки. Остановка — по невязке, измеренной шагом самого уравнения. ~70 итераций в 2D; в 3D на Онгудае — 31–141 по области (400/200 м), 51–291 в окне 100 м, 141–771 в окне 50 м.
Три обязательные правки схемы (прикидка на Онгудае, tools/research/air3d/summary.md, 29.09.2026 — без них 3D не сходится):
- Турбулентная вязкость — по замыканию слоя перемешивания (профиль K(z) Троена–Марта / Холтслага–Бовилля от z_i и масштаба скорости), не постоянная: при постоянной ν = 30 м²/с в штиль с нагревом над дном долины блуждают сеточные струи.
- Плавучесть — полностью полунеявно (множитель 1, а не 0,3 как в 2D): иначе при 3 м/с раскачиваются волны в устойчивом слое.
- Границы — «жёсткие» с поглощающими слоями (губками), а не выход «снос из соседней грани»: медленная мода 0,955 за итерацию вместо 0,989.
Строительные блоки на GPU: поэлементные ядра, прогонка по линии в разделяемой памяти (линия > 1024 точек — многопроходная прогонка), V-цикл. Решатель давления старого плана (WF-02/03: σ-сетка, A = DᵀWD, прогонка по столбцам, многосеточный) — это шаг (2), переиспользуется целиком.
Сетка
- σ-сетка по рельефу, 32 уровня, первый слой ~10 м (
docs/archive/plan/wind-field.md→ «Сетка»). - Клипмапы (WF-14): уровни 800/400/200 м на всё место, 100 и 50 м — окна 64×64 вокруг пилота; решение сверху вниз, грубый даёт границы мелкому, тёплый старт мелкого от интерполяции грубого. Сдвиг окон — фоном, до готовности — грубый уровень.
- Ориентир клетки (сходимость прототипа): 200 м — нет склонового ветра; 100 м — самая грубая с правильной картиной; 50 м — подъём с ошибкой ~15 %; 25 м — ещё −10 %.
- Онгудай в 3D (13:00, южный 3 м/с; 400 → 200 → 100 → 50 м): подъём у старта 0,66 → 0,70 → 0,75 → 0,79 м/с; ветер на 50 м над стартом 2,40 → 2,61 → 2,55 → 2,76; седловина 2,50 → 3,01 → 2,84 → 2,87. Область 400 м + окна 100 м — основной вариант: 400 м занижает на 5–25 %, но окно 100 м от родителя 400 м и от родителя 200 м одинаково (≤ 0,03 м/с). Окно 50 м — вокруг пилота в полёте, фоном.
- Прикидка шла на декартовой сетке с маской «под землёй»; σ-сетка или маска — решает AM-01 (маска проще и уже сходится; σ-сетка точнее у земли на склонах).
Когда считать
| Событие | Что | Цена (оценка 4070 SUPER по прототипу) |
|---|---|---|
| Загрузка места | точное поле для часа старта, ветра и погоды полёта (с нагревом и без — для w_mech), экран «Рассчитываем ветер» | ~1,5 с на 4070 SUPER (AM-01: 400 м ≤ 1,1 с, окно 100 м ≤ 0,8 с); AMD — оценка 3–16 с |
| Игровое время идёт (в полёте) | пересчёт по текущему игровому времени каждые 15 игровых минут (air_model.recompute_game_min), фоном с тёплого старта от текущего поля (соседнее время экономит 40–70 % итераций, если хранить давление), плавная подмена; интерполяции между часами нет | фоном; при ускорении времени ×10 — раз в 1,5 мин реального времени, запас по времени счёта большой |
| Смена ветра/погоды в полёте | то же, внеочередной пересчёт | фоном |
| Сдвиг окна клипмапа | мелкий уровень в новом окне | < 1 с, фоном |
Линейности по направлению ветра («ранг-2», старый план) больше нет: уравнения нелинейны, поле пересчитывается при смене ветра. Это плата за тепло и инерцию.
Фиксированные часы старта; поле при загрузке (решения пользователя, 29.09.2026)
Старт — только в фиксированные часы: 9:00, 12:00, 15:00, 20:00 (вечерняк). Летать «именно в 10:15» смысла нет: время в полёте идёт, есть ускорение времени — пилот сам долетает до нужного часа. Слайдер времени старта заменён выбором из 4 часов (configs/world.json → time.start_hours; сделано в AM-06 часть А). На старте поле всегда точное по часу, дальше его ведёт фоновый пересчёт по игровому времени (таблица выше).
Библиотеки готовых полей нет (решение пользователя на шлюзе AM-01): замер AM-01 показал, что ближайшее поле библиотеки ошибается на 50–75 % при ветре посередине между направлениями (смесь двух ближайших — 8–15 %), погода 18 °C вместо 26 °C меняет поле на 28–44 %. Поэтому:
- при загрузке места — всегда точное поле для часа старта, ветра и погоды полёта; этап загрузки «Рассчитываем ветер» / “Computing wind” (окно не замирает); встроенные места и места с карты — одинаково; сетевая игра — каждый клиент у себя;
- в полёте — пересчёт каждые 15 игровых минут и при смене ветра/погоды, фоном с тёплого старта от текущего поля с давлением (AM-01: 0,1–0,2 с на 400 м, 0,2–0,4 с на окно 100 м), плавная подмена;
- без GPU / ошибка / таймаут — аналитика (запасной ход ниже).
- Вечер 20:00 — проверено AM-01: сходится (41–111 итераций), склоновый ветер вниз слабый (сток холодного воздуха — после заката, вне часов старта); переход 19:00 → 19:15 — 21 итерация без скачков. Утро 9:00 в штиль неподвижной точки не имеет (колебания СКО w ≈ 0,07 м/с) — берётся среднее последних итераций (поле «среднее за час»).
- AMD (оценка по пропускной способности памяти): RX 6600 / RX 580 — ×2 к времени, Radeon 780M — ×5,6, Vega 8 — ×11 → загрузка ветра до ~15 с на слабых картах.
- Справка (прикидка): интерполяция по часам дала бы 2,4 % при шаге 2 ч, 4–5 % при 3 ч, ~10 % при 4 ч — с фиксированными часами старта и фоновым пересчётом она не нужна.
Разрешение сетки: перенос 1-го порядка — граница модели (решение пользователя на шлюзе AM-01)
Перенос 1-го порядка, клипмапы 400/100/50 м без окна 25 м, без поправок. Найдено (AM-01/01а): при клетке 50 м и переносе 1-го порядка разгон у бровки занижен на 15–20 % на 20–100 м — над Каянчей 0,80 / 0,83 / 0,84 / 0,92 на 20 / 30 / 50 / 100 м от решения 25 м + 2-й порядок. Причина — численная диффузия переноса и разрешение рельефа; ошибка растёт на крутых и узких склонах и убывает с клеткой; при 12,5 м + 2-й порядок решение сходится к независимому линейному эталону и к измерениям Askervein. Это записано как граница модели (docs/guide/air-model.md). Путь исправления, если пилоты скажут «на бровке слабо»: 2-й порядок переноса в окнах 100/50 м (время ×2–3) или окно 25 м. В калибровке AM-09 это не подкручивать.
Выход для игры
Поле на CPU (WindField, docs/archive/plan/wind-field.md → «Поле на CPU»): u, v, w и θ′ в узлах, выборка трилинейно; плюс производные карты для масштабов 2 и 3 (ниже). air_velocity_at и mean_wind_at берут горизонталь и «механическую» вертикаль из поля (см. «Стык 1↔2»).
Запасной ход
- Нет GPU / headless / таймаут / ошибка → нынешняя аналитика (как
docs/archive/plan/wind-field.md→ «Запасной путь»). - Пикар не сходится (сильный ветер, мелкая клетка) → на этом уровне: (а) взять грубый уровень, (б) усилить турбулентную вязкость по физическому замыканию (не подгонкой), (в) матрицы перехода (опыт 4) как запасной решатель для окон. Решает координатор по замерам AM-01. На Онгудае при ≤ 6 м/с сошлись все 182 решения по области и 35 окон; 8 м/с не проверено.
Масштаб 2: термики
Нынешняя модель термиков (thermal_field.gd, atmo_thermal.gd: пузыри, ядро/край, жизнь, «улицы», облака над термиком) остаётся; меняется, откуда она берёт числа:
| Параметр термика | Сейчас | Станет (из поля 1) |
|---|---|---|
| Где источники | карта нагрева + сетка клеток | максимумы подъёма/схождения у земли в поле на час (с порогом), распределение по площади — от потока тепла |
| Сила | погода + нагрев | масштаб Дирдорфа w* = (g/θ · H/(ρc_p) · z_i)^(1/3) по потоку тепла H в точке и высоте слоя z_i; согласовано с потоком массы в столбе поля (см. стык) |
| Потолок | основание облаков из погоды | высота, где частица из источника теряет плавучесть по θ̄ + θ′ поля (инверсия гасит сама); не выше основания облаков из погоды |
| Снос и наклон | глобальный ветер | средний по столбцу ветер поля в источнике на момент рождения (как этап 1 WF-13 старого плана) |
| Опускание между | фон | опускание поля (компенсирующий поток) |
Сеть для масштаба 2
Поле у клиентов чуть разное, а список источников термиков должен совпадать у всех (иначе пилоты в одной зоне увидят разные термики). Рекомендация: источники на час выбирает ведущий (он уже считает ботов) и рассылает короткий список (позиция, сила, потолок, снос — десятки чисел) через сервер; в одиночной игре — локально. Альтернатива — грубое квантование (позиция до клетки 200 м, сила до 0,2 м/с, направление до 5°) с гистерезисом; решает AM-07 по замеру расхождения. Отпечаток детерминизма (atmo_fingerprint) — с выключенным полем, как в старом плане.
Масштаб 3: возмущения
Нынешние турбулентность, рывки, подветренная эвристика и ротор (atmosphere.gd, §1.3–1.4 и §1.6 docs/research/slope_wind.md) остаются формой; сила и масштабы — из поля 1 и 2 по физике пограничного слоя:
- механическая болтанка: σ_u, σ_w ∝ u* (скорость трения из сдвига ветра у земли в поле), рост у рельефа — по сдвигу поля, а не по одной высоте над землёй;
- конвективная: σ_w ∝ w* в слое перемешивания (из масштаба 2), убывает к потолку;
- за гребнем: признак отрыва из поля (опускание и сдвиг за бровкой) задаёт, где работает подветренная эвристика и её силу, вместо фиксированной линии тени 12° (линия тени — запасной ход);
- спектры: порывы с масштабами длины от высоты над землёй и z_i (модель фон Кармана/Драйдена, как в авиасимуляторах); проверить, что нынешний шум им не противоречит, и заменить, если противоречит.
- Устойчивость (N из погоды) гасит болтанку и снижает масштабы — формулы подобия Монина–Обухова в простой форме.
Ориентир пилота: «провалы чёткие», «ногами к тросам» — СКО вертикали и частота рывков в подветренной зоне сравниваются с базой AM-00 как наблюдение (решение пользователя 01.10.2026); приёмка — по физике: σ_w слоя смешения = 0,14·ΔU (ΔU — от ветра на уровне гребня), пики рывков ≤ 3σ_w, обратный поток в пузыре — Menke 2019 (макс./U100 = 0,22 ± 0,08).
Стык масштабов 1 ↔ 2 — главный вопрос
Поле Пикара уже содержит средний подъём термиков (в прототипе — столб ~1,6 м/с над склоном) и опускание между ними. Если отдать пилоту и w поля, и пузыри термиков — будет двойной счёт. Правило (проверяется в AM-01/AM-07 числами):
- горизонталь поля — пилоту всегда (приток к склону, растекание под инверсией, разгон на бровке);
- вертикаль поля делится на механическую (обтекание рельефа ветром) и конвективную (от нагрева). Разделение — вторым решением без нагрева (тот же Пикар, H = 0; холодный старт — тёплый от поля с нагревом экономит 0–30 %; считать при загрузке) или по полю θ′;
- механическая вертикаль — пилоту напрямую (склоновый подъём, подъём перед бровкой);
- конвективная — только через пузыри масштаба 2, с тем же средним потоком массы в столбе, плюс опускание между ними из поля.
Детерминизм и сеть (итог)
- Поле 1 — у каждого своё, в ключ мира не входит; расхождение — оценка сверху (GPU против эталона float64).
- Термики 2 — одинаковые у всех (ведущий или квантование).
- Возмущения 3 — локальные, как сейчас (шум уже переносится ветром и не синхронизируется).
- Боты — у ведущего, в его поле.
Задачи
Нумерация AM-xx; ссылки WF-xx — на спецификации в docs/archive/plan/wind-field.md, которые берутся с указанными изменениями.
M0. Подготовка
AM-00. База, worktree, GPU-прогон тестов (1 день, Sonnet) — как WF-00. Дополнительно в базу: СКО вертикали и частота рывков в подветренной зоне на 3 стартах, статистика термиков (сила, потолок, расстояние между) за день на 2 местах — для сравнения масштабов 2 и 3.
M1. Эталон масштаба 1
AM-01. 3D-Пикар на CuPy: эталон (3 дня, Opus; прикидка на Онгудае уже есть — tools/research/air3d/, коммиты 449f703…6a716a5: 3D сходится с тремя правками, шлюз «идёт ли в 3D» пройден)
- Скоуп: довести прикидку
tools/research/air3d/до эталона: σ-сетка или маска (решение с обоснованием: точность у земли на склоне против сложности на GPU); перенос 2-го порядка, если 1-й заметно сглаживает; фон θ̄(z) и z_i от часа и погоды (в прикидке не менялись). Синтетика: ровно; хребет Аньези (крутой/пологий); уединённая сопка; седловина; прогретый склон без ветра и с ветром; инверсия. Реальный рельеф: Онгудай (уже), плюс одно место другого типа (Аушкуль — низкий хребет). Решение «без нагрева» для разделения механической и конвективной вертикали. - Открытые вопросы прикидки — закрыть числами: ветер 8 м/с (сходится ли); почему окно 50 м сходится в 3–5 раз медленнее области (141–771 итераций); ошибка ближайшего поля / смеси двух ближайших между направлениями (45°) и силами (3↔6 м/с) против точного; насколько поле меняется между пресетами погоды (нужны ли классы погоды в библиотеке); вечер 20:00 (устойчивый слой, склоновый ветер вниз — сходимость и картина); фоновый пересчёт каждые 15 игровых минут — сколько итераций от предыдущего поля.
- Приёмка: (1) слова пилота — проверки синтетики 3–7 из
docs/archive/plan/wind-field.md→ «Проверка» (разгон, 2 H / 2,5 H, круче — сильнее, седловина 1,5 ± 0,2 и поворот к оси, косой ветер); (2) тепловые — условия приёмки прототипа (docs/archive/plan/heat-ca-prototype.md) в 3D; (3) масса ≤ 1e-6, тепло — баланс; (4) Askervein: разгон на вершине против измерений (tools/research/data/askervein/) — число и расхождение; (5) сходимость по клетке 400/200/100/50 м; (6) таблица сходимости сила ветра × клетка; (7) эталонные поля для тестов GPU — маленькие файлы; (8) ошибки ближайшего поля/смеси и классов погоды (итог — библиотеки нет, см. выше); цена фонового пересчёта по времени. Если при 8 м/с на 100 м не сходится — координатор приходит к пользователю с вариантами (грубее клетка при сильном ветре, матрицы перехода, шаги по времени).
M2. GPU
AM-02. Строительные блоки на RenderingDevice (3 дня, Opus) — локальный RD, порции ≤ 30 мс, редукции без атомиков (WF-02), прогонка по линии (включая многопроходную > 1024), V-цикл многосеточного давления на σ-сетке (WF-02 + WF-03, обязательны). Приёмка: каждый блок против CuPy-эталона ≤ 1e-5 отн.; два прогона побитно одинаковы; проверка на lavapipe/RADV, если доступно. AM-03. Пикар на GPU, один уровень (3 дня, Opus) — итерация из блоков AM-02, критерий остановки по невязке, тёплый старт. Приёмка: эталоны AM-01 ≤ 1e-3 от |u₀| и ≤ 0,05 К; Онгудай 400 м по области ≤ 1 с и 200 м ≤ 5 с на 4070 SUPER (CuPy-прикидка: 0,3–0,8 и 1,2–4,2 с; сейчас используется ~30 % пропускной способности памяти — на Vulkan можно быстрее); ни одна порция > 50 мс. AM-04. Клипмапы (4 дня, Opus) — уровни 400 м (область) + окна 100 и 50 м, без 25 м; Δτ_u по уровню (AM-01: 0,3 с/м·Δx — медленные окна были из-за псевдошага); WF-14 для Пикара: уровни, граница с грубого, сдвиг окон фоном, выборка с плавным переходом. Приёмка: как WF-14 + на стыке уровней нет скачков поля > 5 %; сдвиг окна без кадра > 100 мс; окно 100 м ≤ 1 с, 50 м ≤ 3 с на 4070 SUPER (прикидка: 0,4–2,3 и 1,8–10 с — разобрать медленную сходимость окон: граница от родителя, тёплый старт от интерполяции, число уровней V-цикла).
M3. Поле в игре
AM-05. WindField на CPU и подключение к атмосфере (3 дня, Opus) — WF-04 + WF-05: каналы u, v, w_mech, w_conv, θ′; air_velocity_at и mean_wind_at по правилу стыка; конфиг air_model с _doc; запасной путь; AtmoFingerprint — поле выключено. Приёмка: как WF-04/05; headless-тесты без изменений.
AM-06. Загрузка, часы старта, пересчёт по времени (2 дня, Sonnet) — WF-06; выбор времени старта — 4 фиксированных часа (configs/world.json → time.start_hours = [9, 12, 15, 20]) вместо слайдера в flight_setup_screen.gd (ru/en); в сетевой игре час зоны — тоже из списка; часть Б: этап загрузки «Рассчитываем ветер» (точное поле всегда, без библиотеки), пересчёт поля по игровому времени каждые recompute_game_min = 15 мин и при смене ветра/погоды — фоном с плавной подменой (новое поле во время незаконченной подмены — от снимка текущей смеси, без скачка). Приёмка: как WF-06; скриншот экрана «Полёт…» ru/en; пересчёт в полёте — без кадра > 100 мс, подмена плавная (график w в точке по времени), при ускорении времени пересчёт успевает; тесты, где задан произвольный час старта, — на ближайший из списка.
AM-06б. Библиотека полей — снята решением пользователя на шлюзе AM-01 (библиотеки нет, точное поле при загрузке).
M4. Масштаб 2
AM-07. Термики из поля (3 дня, Opus) — источники, сила (w*), потолок, снос по таблице масштаба 2; конвективная вертикаль только через пузыри с тем же потоком массы; сеть: ведущий рассылает источники на час (изменение протокола server/proto/deltaplan/v1/net.proto — согласовать с К0) или квантование — по замеру. Приёмка: над прогретым склоном и в схождении термики есть, над тенью и долиной — нет/слабее; потолок по инверсии; поток массы пузырей = конвективному потоку поля в столбе ±20 %; два клиента на одной машине — одинаковые термики; сила и потолок — в литературных диапазонах для силы дня (таблица с источниками).
M5. Масштаб 3
AM-08. Возмущения из поля (2,5 дня, Opus) — σ по u* и w*, зона отрыва по полю, спектры, устойчивость — по разделу масштаба 3. Приёмка: болтанка растёт с ветром и у бровки, падает в устойчивом воздухе; в подветренной зоне СКО и рывки — по физике (σ_w = 0,14·ΔU, пики ≤ 3σ_w; база AM-00 — наблюдение, решение 01.10.2026, см. AM-08в); спектр порывов на записи полёта — наклон в инерционном интервале около −5/3.
AM-08в. Рывки и ротор поверх поля по физике (1 день, Opus; решение пользователя 01.10.2026, вариант В2 + Р1 шлюза «опускание за гребнем», журнал) — с полем: ΔU = (U_H − |U|)·lee_f, U_H — ветер поля на уровне гребня над точкой (вместо U_out — максимума в 600 м); рывки 0,42·ΔU (= 3σ_w) вместо 1,0·ΔU, с нулевым средним, только при turbulence_enabled (часть пульсаций); обратный поток эвристики 0,22·U_H (Menke 2019) вместо 0,25·U_out и только там, где решатель пузырь не разрешает: вес 1 − smoothstep(4; 8; 2,8·превышение/dx уровня) (C4 v4, AirFieldSet.sample_dx). Аналитика не меняется. Приёмка: (1) с выключенной болтанкой w в зоне отрыва = w поля (±0,05 м/с); (2) пики рывков ≤ 0,45·ΔU, σ_w в зоне ≈ 0,14·ΔU ±20 %; (3) в окне 50 м обратный поток эвристики = 0, доля возвратных точек — как у поля; на области 400 м — эвристика 0,22·U_H; (4) повторная выгрузка сравнения Онгудая, все 6 вариантов, таблица «было/стало» (w min, доля возвратного течения, мин. продольная) — опускание у земли за гребнем при 9 м/с в пределах среднее 1–3 м/с, пики ≲ 0,5·U_H; (5) test_lee_rotor.gd и контрактные тесты C4 v4 — зелёные, остальные headless/GPU — без регрессий.
M6. Проверка, калибровка, выпуск
AM-09. Калибровка по схеме Professor (2 дня, Opus) — метод WF-16 (сетка прогонов → полиномы → минимум χ² → неопределённости и корреляции) для трёх масштабов, по правилам калибровки пользователя (ниже, «Решения пользователя»):
- наблюдаемые для подгонки — только количественные: Askervein (мачты, с погрешностями измерений); подобие конвективного слоя из литературы (скорость в термиках ~w*, потолок = z_i, шаг термиков ~1–1,5 z_i); уровень и спектры болтанки (Kaimal, Lenschow); другие полевые данные из
docs/research/calibration_data.md, если применимы. Слова пилота в χ² не входят; - систематика сетки: у наблюдаемых у бровки/на вершине при клетке 50 м и 1-м порядке — систематическая погрешность 15–20 % (известное занижение разгона, «Разрешение сетки»), либо сравнение с решением на сетке 12,5 м + 2-й порядок; иначе подгонка компенсирует численную ошибку физическими параметрами;
- параметры — только реально неизвестные (доля нагрева по типу поверхности, длина перемешивания у рельефа, порог источников термиков и т. п.); известные из литературы с хорошей точностью (коэффициент Смагоринского, коэффициенты подобия турбулентности) — фиксируются стандартными значениями со ссылкой и не подгоняются; параметров заметно меньше независимых наблюдаемых;
- результат: параметры ± погрешности, χ²/ndf, вклад наблюдаемых, устойчивость (число прогонов, степень полинома), значения в конфиге с
_doc; затем — обязательная таблица сравнения «слова пилота → что даёт модель» (разгон до ~2 H, седловина ×1,5, косой ветер 0,55–0,8, провалы за гребнем ±20 % от базы AM-00) в документации; расхождения — в «Границы модели» (docs/guide/air-model.md; пример — седловина ×1,9), модель и коэффициенты по ним не исправляются. Приёмка: как WF-16 + таблица сравнения с пилотом. AM-10. Срезы, F3, трава (2 дня, Sonnet) — WF-09 + F3 (docs/archive/plan/wind-field.md→ ответ 4) + WF-10; на срезах — θ′ и термики поверх поля. AM-11. Производительность, отказы, сеть, Windows (1,5 дня, Opus) — WF-11 + смена часа и сдвиг окон под нагрузкой.- Вход от А2 (01.10.2026, решение пользователя — в TODO): сохранять местную вязкость K в состоянии поля (тёплый старт): после
k_relax0,1 повторный расчёт того же поля стоит 20 итераций вместо 10; с сохранённой K вернётся к ~10. Меняет формат состояния (контракты C9/C2) — делать вместе с Р13, совместимость не нужна. Подробности —docs/archive/plan/air-model-a2.md. AM-12. Полёт пилота, документация, слияние (1 день, К0 + Sonnet) — WF-12;docs/guide/atmosphere.md— раздел «Модель воздуха: три масштаба» с границами каждого.
- Вход от А2 (01.10.2026, решение пользователя — в TODO): сохранять местную вязкость K в состоянии поля (тёплый старт): после
Агенты и оценка
Один координатор (К0, Opus): держит план, шлюз после AM-01, решение по сети термиков, приёмка. Не больше ~4 исполнителей одновременно.
| Задача | Модель | Дни |
|---|---|---|
| AM-00 База | Sonnet | 1 |
| AM-01 3D-эталон (прикидка есть) | Opus | 3 |
| AM-02 Блоки на GPU | Opus | 3 |
| AM-03 Пикар на GPU | Opus | 3 |
| AM-04 Клипмапы | Opus | 4 |
| AM-05 Поле в атмосфере | Opus | 3 |
| AM-06 Загрузка, часы старта, пересчёт по времени | Sonnet | 2 |
| — | 0 | |
| AM-07б Ядра термиков по Аллену | Opus | 1 |
| AM-07 Термики из поля | Opus | 3 |
| AM-08 Возмущения из поля | Opus | 2,5 |
| AM-09 Калибровка | Opus | 2 |
| AM-10 Срезы, F3, трава | Sonnet | 2 |
| AM-11 Производительность, сеть | Opus | 1,5 |
| AM-12 Пилот, слияние | К0 + Sonnet | 1 |
| Итого | 1 координатор, 14 исполнителей | ~32 |
Волны:
- AM-00, AM-01.
- AM-02, затем AM-03; параллельно AM-05 на эталонных полях AM-01.
- AM-04, AM-06, AM-07 (+ AM-07б).
- AM-08, AM-10.
- AM-09, AM-11.
- AM-12.
atmosphere.gd правит только AM-05 и AM-08 (по очереди); thermal_field.gd — только AM-07; game.gd — только AM-06; протокол сети — только AM-07 с согласия К0.
Ветка
feature/air-model, worktree ~/deltaplan-wf (создан 29.09.2026 от main 03724d9); правила — docs/archive/plan/wind-field.md → «Ветка и работа агентов».
Известные расхождения (модель готова, решение пользователя 01.10.2026; в air-model не делаем — потом отдельной задачей вне ветки)
- (а) Механическая болтанка в слое сдвига над следом за гребнем завышена в 3–4 раза. Модель: σ_w/ΔU = 0,4–0,6 (длина перемешивания × |∂U/∂z|, AM-08), пики (w − w_ср) до 0,54–0,74·U_H (−6…−9 м/с при 9 м/с). Литература: σ_w/ΔU ≈ 0,13–0,15, σ_w/U_H ≈ 0,15–0,2 при уклоне ≈ 0,6 и до ≈ 0,3 при уклоне ≳ 1,2 (Liu, Ishihara et al. 2016, JWEIA 153:1, рис. 12c, 14c; Liu, Wang, Wang, Ishihara 2020, JWEIA 201:104178, рис. 3e); слой смешения 0,14 (Bell & Mehta 1990); Perdigão над подветренным гребнем σ ≈ 0,16·U (Menke et al. 2019, ACP 19:2713, табл. 3); распределение w в следе скошено вверх (Liu 2020, рис. 7). Где в полёте: сильный ветер, подветренная сторона, 50–100 м над землёй. Трудоёмкость: 0,5–1 день (в зоне отрыва ограничить σ_w слоем смешения 0,14·ΔU или пересмотреть длину перемешивания в слое сдвига).
- (б) Пузырь отрыва эвристики на пологих склонах и низких буграх. Модель: длина 2,8·H без порога по уклону (Menke 2019, лесистые 2D-гряды), обратная скорость 0,22·U_H. Литература: отрыв с уклона ≈ 0,27 (2D) / ≈ 0,36 (3D) (Finnigan et al. 2020, BLM 177:247, с. 13); длина при уклоне 0,63 — ≈ 1,6·H (3D) и ≈ 3,5·H (2D), при 1,26 — > 5·H (Liu 2016 §4.2.1, 4.3.1; Liu 2020 рис. 3a); обратная скорость в аэротрубе −0,1…−0,2·U_L, 0,22 у Menke — максимум по пузырю, не среднее (Menke 2019 рис. 10). Для 3D-бугров длина завышена ≈ в 1,8 раза, на пологих склонах эвристика даёт пузырь, которого быть не должно; обратная скорость как средняя — в 1,5–2 раза. Где в полёте: низкие бугры (превышение ≲ 70 м, где решатель пузырь не разрешает) и пологие склоны за ними, у земли, в сильный ветер; на области 400 м — везде за гребнями вне окон. Трудоёмкость: около 0,5 дня (порог по уклону, L/H по 2D/3D и крутизне, обратная скорость 0,1–0,2·U_H).
Риски
- Пикар в 3D — прикидка на Онгудае сошлась (≤ 6 м/с, все 217 решений) с тремя правками схемы; не проверены 8 м/с и σ-сетка — AM-01.
Окна 50 м сходятся медленно— причина найдена (псевдошаг), 40–150 итераций.- Загрузка на слабой AMD без библиотеки — до ~15 с на этапе «Рассчитываем ветер» (оценка); замер — AM-11.
- Время на AMD/слабой карте: оценки — с 4070 SUPER на CUDA; Vulkan на AMD может быть в разы медленнее → клетка по области 400 м и экран загрузки дольше; окна вокруг пилота важнее.
- Двойной счёт тепла на стыке 1↔2 — правило выше, проверка потоком массы.
- Сеть термиков — изменение протокола; альтернатива — квантование.
- Ощущения пилота на стартах и в провалах сдвинутся — сравнение с базой и полёт пилота.
На потом
- Влага — ещё один переносимый скаляр в поле 1: основание облаков из поля, затем диагностика гроз (CAPE).
- Шаги по времени между часами вместо плавного перехода, если переход будет заметен.
- Адаптивное дробление по сложности рельефа (octree) вместо клипмапов по расстоянию.