# 物质 · 能量 · 城市

基于 `aim/00-需求.txt` 的 GPU 宏观爆炸教学原型。自行实现有限体积气体求解、统一材料块的断裂/运动，以及直接读取物理状态的光线渲染。使用 Taichi 作为 GPU 内核编译器，不使用现成物理引擎或预制爆炸效果。

最新时间要求：**30 秒，全程 1 倍真实时间，街景较短、远景较长**。先显示 2 秒初始街景，再释放能量。以行人位置压力比环境高 1,500 Pa 为到达事件，在实际测得事件的当帧切到空中，持续演化至影片结束。绝不慢放、加速、倒放或重新开始第二个视角。实际切换秒数记录于 `output/report.json`。

- 网站：http://bomb.codeloop.cn/
- 完整视频：`output/nuclear-physics.mp4`
- 运行读数：`output/report.json`
- 输出：1280 × 720、24 fps、H.264 / yuv420p、720 帧，无音轨。

## 运行

需要 NVIDIA CUDA 驱动、Python 3.12 和 RTX 3090 等 GPU；本项目使用实际 RTX 3090 测试。依赖下载和安装时间不计入视频计算时间。

```bash
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python tests/test_physics.py
.venv/bin/python src/render.py
# 网站兼容视频（另行计时，主视频不变）
.venv/bin/python scripts/web_video.py
python3 scripts/package.py
```

程序自动使用 imageio-ffmpeg 提供的编码器，未要求系统安装 ffmpeg。输出目录由程序创建；运行时间包括城市构建、GPU 编译/数值推进、渲染和编码。缓存会影响后续执行速度。最终实际时长见运行记录，不以估算替代实测。

## 结构和规则

`src/city.py`：读取用户提供的 18,036 条建筑记录。围绕经纬度 (-74.006, 40.719) 建立 3,840 米方形计算区域；裁剪后的数量另行报告。经纬度转换为局部米制平面，高度乘 0.3048。栅格化多边形及孔洞后，相交轮廓取最高高度，避免重复填充材料；不使用道路、纹理、装饰模型。忽略 `ground_elevation`，统一地面标高 0，因此不是精确地形重建。

`src/engine.py`：

1. 气体保守变量为密度、三轴动量密度、总能量密度。理想气体状态方程，γ=1.4；256 × 160 × 256 网格，15 米单元。
2. 有限体积 Rusanov 面通量、minmod 斜率重构、SSP-RK2 时间推进、三维 CFL 自适应步长。重力源项与静力平衡外推边界。开放侧边界允许物质和能量离开，不能仅凭域内总量改变就解释为守恒误差。
3. 高斯空间分布的一次热能沉积作为初始条件。没有随时间指定的火球半径、冲击壳体或蘑菇云轮廓。仅研究能量释放后的现象，不涉及核装置和核反应过程。
4. 所有可见固体（建筑和表层土壤）采用同一密度、热容、温度软化、连接失效、重力和气体阻力规则。预分割块的高度档位为 8/16/32 米，三档抽样概率相同；最后一块裁切到建筑高度。破坏解除连接，不即时凭空生成几何。上层块随下方支撑失效而脱落。
5. 气体阻力通过独立源项累积场交换动量，并扣除传给固体的动能，避免在并行内核中边读边改气体状态。固体碰撞和基础支撑为低成本近似。
6. 尘埃由破坏区域产生并由流场输送；灰体冷却降低热能。没有单独的粒子特效发射器、噪声云纹理或手绘爆炸。
7. 通过物质空间索引追踪视线，与固体包围盒求交，并积分气体消光、散射和发射。发射色来自普朗克谱的三个可见光波长。固定日光作为外部辐射边界；热气体对固体的照明由每帧物理场的辐射功率和质心近似计算。曝光/色调映射只将辐射值转换为可显示的像素。

## 明确的精度边界

这仍是**教学原型，不是高保真核爆模拟器**。不能据此给出真实伤害、工程破坏或安全结论。

- 建筑统一为粗粒度柱状块，不区分真实钢筋、墙体、玻璃；块不旋转。预分割与标量强度近似不等于真实断裂力学。地层深部为固定边界，不模拟整个地球。
- 气固耦合不是严格不可穿透边界；粗网格不能解析街道反射冲击。固体接触采用上一帧空间索引，因此密集堆叠可能有穿插或遗漏。
- 气体求解器使用保守通量，但辐射逃逸、边界通量、固体热交换和断裂耗散没有构成经过完整预算验证的封闭能量系统。不能宣称整机严格能量守恒。
- 灰体和日光单次散射近似不含全谱辐射输运、多次散射、真实空气电离与材料光谱。辐射中心照明是降阶近似。
- 没有湿度凝结、潜热和亚网格湍流模型。云形来自流动和尘埃，**不保证呈现典型清晰蘑菇云**，也不会为匹配形状补画云层。
- 数据文件的权属/公开许可未提供；源码下载包不重新分发建筑原始数据。复现时需将有使用权限的数据放到 `data/buildings.json`。仓库保留用户提供的原始输入。

## 验证

数值测试检查静置大气、热能注入的质量不变与能量误差、短时冲击密度/内能正性，以及像素是否响应热状态。最终运行逐秒检查气体有限性及密度正性，记录温度、气体总量、断裂块数和耗时。网站同时提供 VP9/WebM 兼容版本，其额外转码耗时单独记录。视频另用 FFmpeg 实际解码并核对分辨率、帧数、时间线；网站检查移动端和桌面端布局。

GPU 原子操作的归约顺序可能造成细微差异，不能承诺逐比特重现。

## 部署

`scripts/deploy.sh` 使用 `BOMB_DEPLOY_KEY` 指向已有服务器密钥。部署只写 `/var/www/bomb` 和独立 `bomb` Nginx 配置，先检查现有站点配置哈希、后上传新版本并原子切换链接。`nginx -t` 通过后 reload，结束后核对其他站点配置不变及 HTTP 响应。密钥不入库、不打包。

```bash
BOMB_DEPLOY_KEY=/path/to/key scripts/deploy.sh
```

基础方法参考：[Clawpack 的有限体积守恒律方法](https://www.clawpack.org/master/)，[NASA 的普朗克辐射定律说明](https://imagine.gsfc.nasa.gov/educators/gammaraybursts/imagine/page18.html)。这些资料解释理论，不代表对本实现精度的验证。

网站本地检查：先执行 `npm ci`、`npx playwright install chromium`，再用 `python3 -m http.server 8770 --directory website` 启动站点，在另一终端运行 `npm run test:site`。也可通过 `SITE_URL` 检查线上站点；`CHROMIUM_PATH` 可指定已有浏览器。所需浏览器系统依赖由运行环境提供。
