#!/usr/bin/env python3 """Assemble reports/gallery.html: the figure set with reading notes, PNGs embedded as data URIs.""" import base64, json from pathlib import Path FIG = Path("reports/figures") def img(name): return "data:image/png;base64," + base64.b64encode((FIG / name).read_bytes()).decode() scan = json.load(open("runs/scan_pilot/scan_summary.json")) n_ok = sum(r["M_total_drift"] < 1e-2 for r in scan) PLATES = [ ("fig1_outcome_map.png", "Карта исходов пилотного скана", "Оси каждой панели: начальная компактность ν = 2M/R и относительная тангенциальная скорость L_rms. Панели различаются плоскостью профиля и скоростью распада Γ·t_dyn. Цвет кружка — исход, число внутри — максимум 2m/r, достигнутый за 5 t_dyn. Крестик означает, что ADM-масса за прогон уплыла больше чем на 1 %, и точке верить нельзя.", f"Тёплые облака (L_rms = 0.5) при ν ≤ 0.15 отскакивают, распад снижает максимум компактности в 2–3 раза. Плоские компактные профили (ν = 0.3, flatness 3) доходят до 2m/r ≈ 0.99 при любых L и Γ. Все холодные точки с L = 0 либо недостоверны, либо пограничны: холодная пыль сходится в каустику, которую 300 ячеек не разрешают. Достоверных точек {n_ok} из {len(scan)}.", "Исход «BH_approach» — не найденный apparent horizon. Это достижение порога 2m/r = 0.99 при коллапсе лапса, после которого полярно-ареальная калибровка не продолжается."), ("fig2_timeseries.png", "Четыре сценария во времени", "Слева вверху — максимум компактности 2m/r по радиусу; штриховая линия 0.99 — порог срыва калибровки. Справа вверху — минимальный лапс e^μ: темп собственного времени в самой глубокой точке относительно далёкого наблюдателя. Внизу — масса Мизнера–Шарпа внутри расчётной области и число макрочастиц.", "Отскок (синий): компактность растёт до 0.33 и спадает, лапс почти не меняется. Плоский профиль (оранжевый): компактность выходит на 0.99, лапс падает на пять порядков — далёкий наблюдатель видит «замерзание». Холодная пыль (красный): тот же порог, но масса внутри области растёт до 1.28 — это численный артефакт каустики, а не физика. Распад (зелёный): число частиц скачет из-за рождения и вылета дочерних пар.", None), ("fig3_spacetime.png", "Пространственно-временные диаграммы", "По горизонтали радиус в единицах начального R, по вертикали время в динамических временах t_dyn = √(R³/M). Цвет — 2m(r)/r; светлая полоса — область, где метрика близка к горизонту. Голубые кривые — мировые линии 25 макрочастиц X.", "Отскок: линии сходятся к центру, пересекаются и расходятся обратно, компактность остаётся тёмной. Плоский профиль: все линии стягиваются к r ≈ 0.3R и там останавливаются в координатном времени — светлая вертикальная полоса и есть «замороженная» область у порога горизонта. Холодная пыль: линии сходятся в точку r → 0 около t ≈ 1.5 t_dyn, дальше расчёт недостоверен.", None), ("fig4_phase_space.png", "Фазовое пространство (r, w)", "Каждая точка — макрочастица X: радиус и радиальный импульс w = p^r̂ в ортонормированном репере статичного наблюдателя. Цвет — √L/R, то есть доля тангенциального движения. Верхний ряд — холодная пыль, нижний — тёплое облако с L_rms = 0.5.", "Холодная пыль остаётся однопоточной линией, пока не дойдёт до центра при t ≈ 1.5 t_dyn; после этого w у центра уходит к −25, что и разрушает расчёт. Тёплое облако с t ≈ 2.5 t_dyn имеет два и более значения w при одном r — это пересечение потоков, которое гидродинамика пыли описать не может, а решатель Власова описывает штатно. К t = 5 t_dyn видна спиральная структура фазового перемешивания.", None), ("fig5_profiles.png", "Радиальные профили при приближении к горизонту", "Шесть моментов времени для плоского профиля ν = 0.3. Плотность энергии ρ(r), масса Мизнера–Шарпа m(r), компактность 2m/r и лапс e^μ.", "Масса стягивается внутрь r ≈ 0.3R, плотность вырастает на два порядка, 2m/r касается единицы (штрих) на радиусе ≈ 0.3R, а лапс внутри этого радиуса падает к нулю. Снаружи профиль m(r) и лапс не меняются — по теореме Биркгофа внешний наблюдатель видит ту же массу.", "Максимум 2m/r останавливается на 0.99 не потому что горизонт не образуется, а потому что расчёт остановлен по порогу калибровки."), ("fig6_decay.png", "Распад X и дочернее излучение", "Сценарий тёплого облака с Γ·t_dyn = 0.3. Вверху слева — нераспавшаяся масса X против exp(−Γt); вверху справа — баланс ADM-массы: масса внутри области плюс энергия Киллинга, унесённая через границу. Внизу — число макрочастиц по видам и фазовое пространство X и безмассовых дочерних частиц.", "Масса X убывает медленнее exp(−Γt) там, где лапс меньше единицы и частицы движутся: распад идёт по собственному времени. Чёрная линия ADM-баланса горизонтальна — энергия распада не теряется, а переходит в дочерние пары и уходит через границу. Дочерние частицы (оранжевые) заполняют w ≈ +0.5: это релятивистские кванты, летящие наружу.", "Дочерняя компонента здесь бесстолкновительная. Предел тесно связанной радиационной жидкости ещё не реализован, поэтому давление излучения на X не учитывается."), ("fig7_validation.png", "Валидация на аналитических решениях", "Слева: коллапс пылевого шара, каждая оболочка сравнивается с точной геодезикой Леметра–Толмана–Бонди в своём собственном времени. В центре: радиальное падение пробной частицы в метрике Шварцшильда, координатное время расходится у r = 2M. Справа: сходимость ошибок по числу ячеек.", "Точки решателя лежат на аналитических кривых; ошибки метрики и орбиты убывают как K⁻², что подтверждает второй порядок схемы. Это выполненные пункты обязательных тестов спецификации: вакуумная регрессия, однородный пылевой коллапс, сходимость.", None), ("fig8_resources.png", "Что упирается в текущий VPS", "Время одного шага RK4 и пиковая память в зависимости от числа макрочастиц; измерено на 2 vCPU / 3.7 GB.", "Время линейно, 3.8 мкс на частицу и шаг. Память — около 280 байт на частицу, и при 2·10⁷ частиц процесс убит OOM-killer'ом. Один сходящийся прогон на 10⁶ частиц здесь стоит около 39 часов, скан с конвергенцией — порядка 100 дней; на CCX43 около двух недель.", None), ] def plate(i, fn, title, how, what, caveat): cav = f'
Оговорка

{caveat}

' if caveat else "" return f'''
Рис. {i}

{title}

{title}
Как читать

{how}

Что видно

{what}

{cav}
''' toc = "".join(f'{i}{t}' for i, (_, t, *_) in enumerate(PLATES, 1)) body = "".join(plate(i, *p) for i, p in enumerate(PLATES, 1)) html = f'''Сферический коллапс X
pbhgr · Stage A · шаг 1 · 13.09.2026

Сферический коллапс холодного сектора X

Восемь рисунков, по которым видно, что делает решатель Einstein–Vlasov с распадом: где облако отскакивает, где стягивается к порогу горизонта, как пересекаются потоки и куда уходит энергия распада. Единицы G = c = 1, масса облака M = 1, время в t_dyn = √(R³/M).

BH_approach — 2m/r дошло до 0.99bounce — максимум компактности пройденunresolved — исход не определён за 5 t_dyn
2m(r)/r
компактность: отношение удвоенной массы Мизнера–Шарпа внутри радиуса r к этому радиусу. Единица означает горизонт.
e^μ (лапс)
во сколько раз медленнее идёт собственное время на радиусе r по сравнению с далёким наблюдателем.
w = p^r̂, L
радиальный импульс и квадрат углового момента макрочастицы в репере статичного наблюдателя.
ν, L_rms, Γ·t_dyn
оси скана: начальная компактность, тангенциальная скорость в единицах √(M/R), число распадов за динамическое время.
{body}
''' Path("reports/gallery.html").write_text(html, encoding="utf-8") print("gallery.html", len(html) // 1024, "KB")