Клеточный автомат тепла и массы — общий итог (2D-разрез хребта)

Прототип по карточке docs/archive/plan/heat-ca-prototype.md. Код, запуск и смысл картинок — README.md. Хребет 500 м, крутой склон слева (до ~33°), пологий справа (до ~16°); разрез 6,4 × 3,2 км; фон почти безразличный (θ растёт на 1 К/км, т. е. T падает на ~8,8 К/км); нагрев склонов до 250 Вт/м². Счёт — GPU (RTX 4070 SUPER, CuPy + CUDA Graph, float32); в игре это будут вычислительные шейдеры Vulkan (должно работать на AMD), CuPy — только для прототипа.

Правила автомата (простыми словами)

  1. Земля греет нижнюю клетку столбца (по солнцу на склон).
  2. Поток вверх через грань ускоряется, если клетки теплее фона на своей высоте; поднятый воздух несёт свою температуру — на инверсии быстро становится холоднее соседей, подъём гаснет сам.
  3. Потоки переносят сами себя, вязкость и трение сглаживают; губка у потолка.
  4. Недостача массы в клетке «подсасывает» соседей (давление) — многосеточно (mg) или чисто локально (acoustic, «медленный звук», без глобального решателя).
  5. Масса и тепло переходят через грани парными потоками (что ушло из одной — пришло в другую) → сохранение точное; плюс теплопроводность, плюс слабое выхолаживание к фону (τ = 2 ч, явный сток).

Это конвекция Буссинеска, записанная локально: п. 2 — плавучесть относительно фона, п. 4 — уравнение Пуассона для давления (итерации «клетка смотрит на соседей» = Якоби).

Сценарии: результат против условий приёмки (клетка 50 м)

СценарийМакс. подъёмПриток у подножия (к склону +)ОпусканиеВысота подъёмаУстановлениеПриёмка
1. Солнце на крутой склон1,65 м/с над верхней третью солнечного склона (x = 2,48 км, 475 м над землёй)+0,49 м/с; вверх по склону +0,53 м/св долине слева в среднем −0,08 (до −0,23) м/с; над теневым склоном −0,02 м/с1400 м над подножием5754 шага (210 мин модели), 3,1 с GPUда (п. 1, 2, 6)
2. Оба склона2,47 м/с над гребнем (x = 3,33 км, чуть за гребнем — склоны разные)+0,48 / +0,44 м/с; вверх по склонам +0,65 / +0,81долина −0,10 м/с, по бокам столба до −0,75 м/с1800 м6302 шага, 3,4 сда (п. 1, 3, 6)
2б. Симметричный хребет2,08 м/с строго над гребнем+0,48 / +0,48 м/с−0,08 м/с1600 м6302 шага, 3,4 ссимметрия до 6·10⁻⁶ м/с
3. Ветер 3 м/с слеваполное поле 1,40 м/с (наветренный склон); тепловая добавка 0,35 м/степловая добавка к притоку +0,26 м/сза гребнем — нисходящая часть горной волны до −1,1 м/степловая добавка до 1900 м5480 шагов, 3,1 сда (п. 1, 5, 6)
4. Инверсия 1500–1800 м2,33 м/с+0,49 / +0,44 м/с−0,09 м/с1550 м (без инверсии 1800), тёплый воздух до 18005206 шагов, 2,8 сда (п. 1, 3, 4, 6)
  • Сохранение (п. 1): невязка массы ~10⁻¹¹ от массы области, тепла ~10⁻⁵ от суммарного нагрева (float32); допуск 0,1 % выполнен с запасом на порядки. Недовыравненная масса в клетке ~2·10⁻⁸ (многосеточно) или 0,1–2 % (локальный режим, ∝ 1/c²). Графики — mass_balance.png.
  • П. 2 (сценарий 1): подъём над прогретым склоном и гребнем, приток у подножия к склону, возвратный поток на 0,8–1,3 км и опускание над долиной — s1_sun_one_slope/flow.png, evolution.mp4.
  • П. 3: схождение и столб подъёма над гребнем; на несимметричном хребте столб сдвинут на ~0,5 км к пологому склону (с него приходит больше тёплого воздуха); на симметричном (s2_sym) — строго над гребнем, картина зеркальная до 10⁻⁵.
  • П. 4 (инверсия): подъём гаснет у нижней кромки инверсии (1550 м против 1800 без неё), под инверсией — растекание в стороны до 1,6 м/с и холодная «шапка» перебега; выше инверсии |w| ≤ 0,03 м/с, |θ′| ≤ 0,06 К — s4_inversion/flow.png, temp.png.
  • П. 5 (ветер): картина не разваливается; полное поле — это прежде всего обтекание хребта устойчивым воздухом (горная волна: подъём на наветренном склоне и над долиной перед ним, сильное опускание за гребнем). Тепловая часть (с нагревом минус без) — наклонённый по ветру подъём от наветренного склона через гребень (dx/dz ≈ +0,5), тёплый слой сдувается за хребет — s3_wind/flow_thermal.png, flow_no_heating.png. При 4 м/с тепловую часть почти не видно — её забивает волна (честно: при ветре 4+ м/с и такой устойчивости тепло склона — поправка ~0,3 м/с).
  • П. 6: «пилы» нет, шаг устойчивый (перенос: dt ≤ 0,35·клетка/8 м/с; теплопроводность: ≤ 0,2·клетка²/K), установление за ~200 мин модельного времени — 1,2–15 тыс. шагов по клетке.

Похоже ли на слова пилота. Да по всем трём пунктам карточки: подъём у прогретого склона и над гребнем (максимум — над верхней частью склона, 0,4–0,7 км над землёй), приток снизу к подножию (~0,5 м/с, вверх по склону ~0,5–0,8 м/с — склоновый ветер), потолок на инверсии (столб останавливается у её нижней кромки и растекается). Опускание над долиной слабое и широкое (−0,1…−0,2 м/с), рядом со столбом — сильнее (до −0,75 м/с). Числа порядка настоящих склоновых циркуляций; сила зависит от вязкости/теплопроводности (30 м²/с — грубое «перемешивание»).

Сходимость по клетке и время (сценарий 1)

Сходимость по клетке и время на GPU (NVIDIA GeForce RTX 4070 SUPER, CuPy + CUDA Graph, float32; сценарий 1; выравнивание массы — многосеточный Пуассон, 2 V-цикла на шаг)

КлеткаСетка (воздушных)dt, сШагов до установленияВремя до установления, смс/шагПамять GPU, МБМакс. подъём, м/с (где)Приток у подножия, м/сВверх по склону, м/сОпускание в долине (ср.), м/сВысота подъёма, м
200 м32×16 (489)8.751242 (181 мин)0.610.4910.21.21 (2.30 км, 500 м)+0.71+0.02-0.0911400
100 м64×32 (1948)4.382740 (200 мин)1.370.5000.71.42 (2.45 км, 450 м)+0.55+0.47-0.0821400
50 м128×64 (7792)2.195754 (210 мин)3.060.5322.91.65 (2.48 км, 475 м)+0.49+0.53-0.0751400
25 м256×128 (31168)1.0912078 (220 мин)7.050.58313.31.81 (2.51 км, 488 м)+0.44+0.61-0.0721425
12.5 м512×256 (124672)0.5524134 (220 мин)18.220.75553.91.90 (2.53 км, 481 м)+0.41+0.65-0.0711425
6.25 м1024×512 (498688)0.2650688 (220 мин)72.411.428216.11.95 (2.55 км, 472 м)+0.40+0.67-0.0701425
3.125 м (только замер скорости)2048×10246.034864

Оценка для 3D (квадрат 40×40 км × 32 уровня, та же физика, тот же GPU): мс/шаг = max(0.49 мс — пол накладных расходов, 2.88 нс на клетку·шаг по самой большой 2D-сетке × 1.5 за 3D); шагов — как в 2D при той же клетке; память — 432 байт на клетку × 1,3.

КлеткаЯчеек 3Dмс/шаг (оценка)ШаговДо установления, с (оценка)Память как в прототипе, МБПамять компактно (~64 байт/клетка), МБ
200 м1.28 млн5.51242768678
100 м5.12 млн22.12740612744312
50 м20.48 млн88.45754509109741250
25 м81.92 млн353.5120784270438985000

Прототип держит в пуле CuPy все временные массивы шага (CUDA Graph) — отсюда ~430 байт на клетку; в вычислительном шейдере нужно ~12–16 чисел float32 на клетку (u, v, w, m, H, p, правая часть, невязка, уровни многосеточного) ≈ 64 байт.

Сходимость по клетке и время на GPU (NVIDIA GeForce RTX 4070 SUPER, CuPy + CUDA Graph, float32; сценарий 1; выравнивание массы — чисто локально («медленный звук» 60 м/с))

КлеткаСетка (воздушных)dt, сШагов до установленияВремя до установления, смс/шагПамять GPU, МБМакс. подъём, м/с (где)Приток у подножия, м/сВверх по склону, м/сОпускание в долине (ср.), м/сВысота подъёма, м
200 м32×16 (489)8.751242 (181 мин)0.450.3640.21.17 (2.30 км, 500 м)+0.74+0.01-0.1211400
100 м64×32 (1948)4.382603 (190 мин)0.910.3500.71.39 (2.45 км, 450 м)+0.57+0.50-0.0981400
50 м128×64 (7792)2.195754 (210 мин)2.060.3582.91.64 (2.48 км, 475 м)+0.51+0.54-0.0841400
25 м256×128 (31168)1.0911529 (210 мин)4.450.38613.31.80 (2.51 км, 488 м)+0.45+0.62-0.0761425
12.5 м512×256 (124672)0.5524134 (220 мин)13.500.55953.91.90 (2.53 км, 481 м)+0.42+0.65-0.0731425
6.25 м1024×512 (498688)0.2650688 (220 мин)63.511.253216.11.95 (2.55 км, 472 м)+0.40+0.67-0.0711431
3.125 м (только замер скорости)2048×10245.735864

Оценка для 3D (квадрат 40×40 км × 32 уровня, та же физика, тот же GPU): мс/шаг = max(0.35 мс — пол накладных расходов, 2.73 нс на клетку·шаг по самой большой 2D-сетке × 1.5 за 3D); шагов — как в 2D при той же клетке; память — 432 байт на клетку × 1,3.

КлеткаЯчеек 3Dмс/шаг (оценка)ШаговДо установления, с (оценка)Память как в прототипе, МБПамять компактно (~64 байт/клетка), МБ
200 м1.28 млн5.31242768678
100 м5.12 млн21.02603552744312
50 м20.48 млн84.05754483109741250
25 м81.92 млн336.0115293874438985000

Прототип держит в пуле CuPy все временные массивы шага (CUDA Graph) — отсюда ~430 байт на клетку; в вычислительном шейдере нужно ~12–16 чисел float32 на клетку (u, v, w, m, H, p, правая часть, невязка, уровни многосеточного) ≈ 64 байт.

Сходимость по клетке (out/convergence/conv_w_profile.png, conv_flow.png): картина (где подъём, приток, возвратный поток, опускание, высота подъёма 1400 м) одинакова от 200 до 6,25 м. Меняются:

  • макс. подъём растёт с измельчением (1,21 → 1,42 → 1,65 → 1,81 → 1,90 → 1,95 м/с) — сходится как первый порядок, 50 м даёт ~85 % от предела;
  • склоновый ветер вверх по склону: на 200 м его нет (+0,02 м/с — склон 2 клетками), на 100 м уже +0,47 (предел ~0,67);
  • приток у подножия на грубых сетках завышен (0,71 на 200 м против ~0,40). Рекомендация: самая грубая клетка с правильной картиной — 100 м (есть склоновый ветер, подъём в нужном месте, ~75 % силы); 200 м годится только как фон (циркуляция долины без склонового слоя). Для 3D при загрузке — 200 м по всей области и 50–100 м в окне у пилота (как WF-14).

Время. Число шагов до установления ∝ 1/клетка (шаг по времени ∝ клетке, а устанавливается ~3 часа модельного времени — медленный прогрев долины). На малых сетках GPU ждёт запуски (пол ~0,4–0,5 мс/шаг даже с CUDA Graph), на 3,125 м (2 млн клеток) — 2,9 нс на клетку·шаг. Оценка 3D 40×40 км × 32 уровня: 200 м — ~7 с, 100 м — ~1 мин, 50 м — ~8 мин, 25 м — ~1 ч (тот же GPU; на слабой AMD — в 3–10 раз дольше). Память в компактной реализации ~64 байт/клетку: 78 МБ (200 м) … 1,25 ГБ (50 м).

Выравнивание массы: сколько итераций нужно

Выравнивание массы: сколько итераций нужно (сценарий 1, клетка 50 м, GPU)

| Способ | Итераций (подшагов) на шаг | Макс. |m−1| в клетке (недовыравнено) | Шагов до установления | мс/шаг | Макс. подъём, м/с | Приток у подножия, м/с | Высота подъёма, м | |—|—|—|—|—|—|—|—| | многосеточный V-цикл (Пуассон) | 1 | 5.9e-08 | 5754 | 0.392 | 1.65 | +0.49 | 1400 | | многосеточный V-цикл (Пуассон) | 2 | 2.2e-08 | 5754 | 0.530 | 1.65 | +0.49 | 1400 | | многосеточный V-цикл (Пуассон) | 4 | 2.0e-08 | 5754 | 0.812 | 1.65 | +0.49 | 1400 | | Якоби, локальные итерации давления, снимать накопленный избыток массы | 50 | расходимость: |v|max=nan на шаге 274 | | | | | | | Якоби, локальные итерации давления, без возврата накопленной массы | 50 | 3.0e-03 | 5754 | 0.297 | 1.65 | +0.49 | 1400 | | Якоби, локальные итерации давления, без возврата накопленной массы | 500 | 8.0e-04 | 5754 | 0.715 | 1.65 | +0.49 | 1400 | | локально: «медленный звук» c = 30 м/с | 3 | 2.3e-02 | 5754 | 0.288 | 1.65 | +0.50 | 1400 | | локально: «медленный звук» c = 60 м/с | 6 | 5.6e-03 | 5754 | 0.355 | 1.64 | +0.51 | 1400 | | локально: «медленный звук» c = 120 м/с | 11 | 1.3e-03 | 5754 | 0.468 | 1.63 | +0.50 | 1400 |

  • Многосеточному хватает 1 V-цикла на шаг с тёплым стартом (недостача массы 6·10⁻⁸).
  • Буквальная «клетка смотрит на соседей» (Якоби), если каждый шаг пытаться вернуть накопленную недостачу массы, разваливается (двойной счёт недостачи → раскачка); без возврата работает, но масса в клетках «плывёт» (0,1–0,3 %), и на больших сетках Якоби сходится всё медленнее (∝ N²).
  • Лучший локальный вариант — «медленный звук» (--pressure acoustic): недостача массы сама даёт давление, 3–11 подшагов по соседям на шаг, без глобального решателя; картина та же (подъём 1,63–1,65 м/с), быстрее многосеточного (0,29–0,47 против 0,39–0,53 мс/шаг), масса в клетке 0,1–2 %. Для вычислительного шейдера это самое удобное: только соседи, никаких уровней и редукций; на AMD переносимо.

Сравнение с решателем Пуассона из плана поля ветра

Выравнивание массы здесь — это то же уравнение Пуассона, что в docs/archive/plan/wind-field.md (∇·(∇λ) = −∇·u₀, те же проводимости граней, многосеточный метод). Разница в том, что поле ветра решает его один раз (диагностическое поле без инерции и плавучести: 15–30 итераций PCG), а автомат — на каждом шаге (1 V-цикл × тысячи шагов) плюс перенос тепла и импульса. То есть автомат = решатель поля ветра + плавучесть + время. Отсюда цена: при 200 м — секунды против долей секунды; при 50 м — минуты против секунды. Зато автомат даёт то, чего поле по массе не даёт в принципе (§11.2 исследования): приток к прогретому склону, столб над гребнем, возвратный поток и опускание, потолок на инверсии, наклон по ветру.

Вывод для игры

  • Идея рабочая и физически честная: локальные правила дают правильную качественную картину и правильные порядки величин; сохранение точное; счёт устойчивый.
  • Статичный прогон до установления при загрузке/смене часа реален только на грубой сетке: 3D 200 м — ~5–10 с на 4070 SUPER (на слабой AMD — до минуты), 100 м — ~1 мин (слишком долго для загрузки, можно фоном). 50 м по всей области — нет; 50 м в окне 8×8 км у пилота — ~30 с фоном.
  • Ускорители: локальный «медленный звук» вместо многосеточного (проще шейдер, быстрее); старт не с покоя, а с прошлого часа (установление не с нуля, а на ~30–60 мин модельного времени — в 3–5 раз меньше шагов); грубая сетка для фона + мелкая в окне (WF-14).
  • Что это даст пилоту поверх поля ветра по массе: склоновый ветер и приток снизу (трава/пыль тянутся к склону), широкое опускание над долиной, высоту «потолка» по инверсии, снос тепла ветром. Термики как пузыри и «провалы» — по-прежнему отдельная модель (автомат на 50–200 м их не разрешает).
  • Рекомендация: не заменять план поля ветра, а рассматривать автомат как этап 2–3 связанной системы (§11.3): тот же решатель + плавучесть от солнца на склонах, 200 м по области, раз в игровой час, фоном; начать с 2D→3D прототипа на Vulkan с локальным режимом давления.

Слои как матрицы: итог опытов 1–6

Главный критерий — физическая корректность в заявленных границах модели. Дальше — точность против точной неподвижной точки и цена в 3D на GPU.

ПодходФизика в ответеТочность2D, 50 м3D 200 м / 100 м (4070 SUPER)Где кончается применимость
Шаги по времени (автомат; эталон)масса и тепло точно, полный импульс, нелокальное давление; есть переходные процессы—3 с (до 1 % — 7 с)7–18 с / 1–2,5 минединственный с динамикой; дорог на мелкой клетке
2. Пикар (Озеен + SIMPLEC + тепло)то же, что у автомата; подгонки нет≤ 0,5 % по u, w; ~1 % по θ′0,1–0,3 с2–5 с / 7–17 столько установившееся среднее поле (перемешанный воздух)
5. ADI-прогонкито жедо 1 % за 100–190 раундов0,3–0,4 с6–16 с / 15–40 сто же; ветер не реализован; итерация пока дорогая
4. Матрицы перехода (гармоники + Андерсон)то же1–2 % (ветер — до 14 % по w)0,1–0,5 с; повторов не больше при измельчении1–12 с / 5–48 спамять Андерсона 2,5 КБ/клетку (по области — только 200 м)
6. Ядро струимасса точно, тепло глобально; импульс только по оси; давление — проекцияключевые числа 5–30 %, поле 0,6–0,751–2 мс~20 мс / ~80 мсодна струя, без взаимодействий; с ветром грубо
1 и 3. Линейные ядра и свёрткалинеаризованный Буссинескподъём втрое слабее0,03 мс—только подъём меньше 5 см/с

Недостаток базы. Критерий установления абсолютный (0,02 м/с и 0,03 К за 10 мин), поэтому эталоны out/refs недоустановились: от точной неподвижной точки они отличаются на 3–8 % по u, w и на 10–23 % по θ′. Точные эталоны — exp2_picard/out/truth, exp4_transfer_sweeps/out/refs_long, exp5_adi/out/fixed. Критерий стоит сделать относительным или считать 8–10 ч.

Рекомендация для игры (Vulkan compute, AMD, клипмап WF-14):

  • Единая модель «воздуха» — те же уравнения Буссинеска. «Поле на час» считать Пикаром (опыт 2): 200 м по всей области за ~2–5 с, окна 50–100 м вокруг пилота фоном, с тёплым стартом от грубого поля и от прошлого часа.
  • Строительные блоки простые: поэлементные ядра, прогонки в разделяемой памяти, V-цикл. На AMD переносимо, но для линий длиннее 1024 точек нужна многопроходная прогонка.
  • Шаги по времени (локальный режим «медленный звук») — только для переходов между часами.
  • Ядро струи — начальное приближение и мгновенная оценка.
  • Матрицы перехода — запасной вариант для окон, если упрёмся в сходимость Пикара.
  • Все подходы дают только среднюю циркуляцию. Термики-пузыри и «провалы» остаются отдельной моделью.
  • Следующий шаг физики — влага как ещё один переносимый скаляр: из неё база облаков, дальше диагностика гроз (CAPE).

Как воспроизвести:

cd tools/research/heat_ca
.venv/bin/python run.py all
.venv/bin/python study.py cells [--pressure acoustic]
.venv/bin/python study.py solvers
.venv/bin/python refs.py

Команды для опытов — в README.md каждой папки exp*/. Все замеры времени — под flock /tmp/heat_ca_gpu.lock.

Картинки для статьи:

  • база: out/s1_sun_one_slope/flow.png и evolution.mp4, out/s4_inversion/flow.png и temp.png, out/s3_wind/flow_thermal.png, out/convergence/conv_w_profile.png, out/solvers/solvers_w300.png;
  • опыт 1: exp1_3_6_kernels/out/exp1_linearity_vs_strength.png;
  • опыт 6: exp1_3_6_kernels/out/exp6_jet_anatomy.png;
  • опыт 2: exp2_picard/out/fig_convergence.png;
  • опыт 4: exp4_transfer_sweeps/out/passes_explained.png, streams_s4_inversion.png;
  • опыт 5: exp5_adi/out/rounds_lines_adi.png.

Данные вне git: снимки повторов опыта 4 для 25 и 12,5 м (~140 МБ) — локально в exp4_transfer_sweeps/out/snaps/.