chore(repo): close out project indexes and evidence boundaries

Add a canonical src package index, synchronize cross-project status and root navigation, and ignore local generated/runtime payloads while preserving the documented solver and evidence boundaries.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Frank14f
2026-08-09 22:32:55 +08:00
co-authored by Cursor
parent 86157c6f31
commit 140eea4d25
14 changed files with 638 additions and 2789 deletions
+9 -1
View File
@@ -143,4 +143,12 @@ src/drl_pinball/train/output/*/models/*
!src/drl_pinball/train/calibrations/*/target.npy !src/drl_pinball/train/calibrations/*/target.npy
# CCD generated evidence/archive payloads remain external immutable data. # CCD generated evidence/archive payloads remain external immutable data.
src/CCD_analysis/evidence/* src/CCD_analysis/evidence/*
src/CCD_analysis/archive/* src/CCD_analysis/archive/
src/archive/
# Local/runtime residue and generated publication working trees
.runtime/
{output_dir}/
src/drl_pinball/data/reproduction_flow_plots/
src/drl_pinball/train/results/latest/tables/training_iterations.csv
src/drl_pinball/data/reproduction
+101 -254
View File
@@ -2,277 +2,149 @@
**Machine Learning meets Numerical Simulation** **Machine Learning meets Numerical Simulation**
DynamisLab is a research framework for combining machine learning techniques with numerical simulations. Built on top of [CelerisLab](https://github.com/frank14f/CelerisLab), it provides standardized environments and training pipelines for various ML + CFD/Physics projects. DynamisLab 是一个面向机器学习与数值模拟交叉研究的框架,当前主线是二维 fluidic pinball(三圆柱)主动流动控制:以 GPU 加速 Lattice Boltzmann MethodLBM)求解流场,用 PPO 等策略驱动圆柱旋转,并用 Symbolic RegressionSR)、Corrected Cross-Covariance DecompositionCCD)、Observable IdentificationOID)和稳态理论分析审查控制规律与证据边界。
## Current Projects 项目关注的科学问题是:有限的力/速度观测和三个旋转执行器,能否使下游流动接近无扰动基准(Kármán cloaking/stealth)或指定目标流动(Illusion),以及可复现证据究竟支持到“性能、控制结构、统计共变、稳态关联或机制”的哪一层。仓库不是一个已经证明普适机理的成品库;它同时保存可执行代码、当前受限结论、失败结果和历史路线。
### 🎯 FlowStealth ## 当前状态(2026-08-09
Deep Reinforcement Learning for Active Flow Control, focusing on: - **活跃(active**:现代 CelerisLab V5 的 `drl_pinball` 训练/评估工作流与保留的 compact policy bundlesLegacy Kármán SR 的受限结论;corrected Kármán CCD 的描述性 phase-coherent co-variation 结果;稳态 pinball 的 NS-first 后续验证路线。
- **Flow Stealth**: Drag reduction and flow signature minimization - **受限(bounded)**:稳态端点、有限时域瞬态和 article publication 已形成可审计证据,但机制、因果性及渐近/全局稳定性未建立;现代 V5 发布可复现训练接口和部分保留模型,不表示所有 case/seed 已按当前代码完整重训并验证;Legacy 标准化 SR 图包仍是 partial Kármán package。
- **Flow Illusion**: Manipulating flow patterns for deception and control - **历史/负结果(historical/negative**Illusion SR 已失败并关闭为科学解释路线;OID 的 2026-07 双场景研究降级为条件性历史材料;早期 reproduce、CCD/OID 分支和被替代实现均保留在各级 `archive/`
- **Methods**: DRL (PPO) + CFD (Lattice Boltzmann Method)
- **Location**: `src/flow_stealth/`
## Features 必须区分两个不同命题:**Illusion PPO 是仓库仍支持的训练与确定性评估能力**,包括现代 `train_illusion.py`、目标及 harmonics 合约;**Illusion SR 则不是有效科学结果**。长窗口 Legacy 标准化采集显示保留的 SR 动作衰减到接近 physical zero,未显示相对 zero 的有意义收益,因此不得把旧的 200/400-step target similarity 写成 Illusion SR efficacy、target tracking 或跨尺寸泛化。
- 🌊 **CFD Environments**: Gymnasium-compatible environments for flow control Kármán CCD 只支持 DRL 相对 constant-control phase template 的描述性共变及稳定 rank-3 subspace;它不是配对反事实、因果效应、响应时间、机制、explained variance,也不证明 CCD 优于 POD。稳态结果同样尚未闭合 NavierStokes 机制链;potential-circulation cancellation 已失败,有限时域关联不得升级为因果性或全局稳定性。OID 当前是 claim-free CPU method core,不承载活跃科学结论。
- 🤖 **RL Integration**: Ready-to-use with Stable-Baselines3 and other RL libraries
- 🚀 **GPU Acceleration**: Leverages CelerisLab's CUDA-accelerated LBM solver
- 📊 **Experiment Tracking**: Built-in TensorBoard integration
- 🔧 **Modular Design**: Organized by research projects
- 📦 **Standard Structure**: Follows Python packaging best practices
## Project Structure ## 五分钟阅读顺序
``` 先看 [`src/README.md`](src/README.md) 获取源码包总索引,再按项目进入权威文档。
DynamisLab/
├── src/ # Source code (organized by project)
│ └── flow_stealth/ # FlowStealth: DRL + CFD Active Control
│ ├── __init__.py
│ ├── config.py # Configuration management
│ └── environments/ # Gymnasium environments
│ ├── __init__.py
│ └── cfd_env.py # CFD flow control environment
├── scripts/ # Training and evaluation scripts
│ └── train_ppo.py # PPO training script for FlowStealth
├── configs/ # Configuration files
│ ├── config_cuda.json # CUDA settings
│ ├── config_flowfield.json # Flow field parameters
│ └── config_gym.json # Environment settings
├── CelerisLab/ # CelerisLab submodule (GPU-accelerated CFD)
├── models/ # Trained model checkpoints (gitignored)
├── output/ # Training data and results (gitignored)
├── tensorboard/ # TensorBoard logs (gitignored)
├── docs/ # Documentation
├── requirements.txt # Python dependencies
├── pyproject.toml # Package configuration
└── README.md # This file
```
## Installation 1. 本页:项目范围、状态和证据规则。
2. [`src/drl_pinball/train/README.md`](src/drl_pinball/train/README.md):现代 V5 校准、训练与保留产物。
3. [`src/drl_pinball/eval/README.md`](src/drl_pinball/eval/README.md)canonical V5 确定性评估及 fail-closed 合约。
4. [`src/SR_analysis/README.md`](src/SR_analysis/README.md)Legacy Kármán SR 主张、Illusion SR 负结果和不可变证据链。
5. [`src/CCD_analysis/README.md`](src/CCD_analysis/README.md)corrected Kármán CCD 当前唯一结果权威。
6. [`src/steady_pinball_theory/README.md`](src/steady_pinball_theory/README.md) 与 [`src/OID_analysis/README.md`](src/OID_analysis/README.md):稳态受限路线与 OID scientific reset。
### Prerequisites 继续复现实验前,再读对应 package 的 pipeline、contract、results、handoff 和 archive index;不要只依据旧图、文件名或历史 README 作结论。
- Python 3.8+ ## 包与目录地图
- NVIDIA GPU with CUDA support
- CUDA Toolkit 11.0+
### Step 1: Clone the repository - [`src/drl_pinball/`](src/drl_pinball/) — 主运行包。`train/` 是现代 2000×600 CelerisLab V5 校准/训练;`eval/` 是 V5 评估;`legacy_test/` 在 LegacyCelerisLab 上执行统一的历史角色采集;`legacy_env/``legacy_train/` 和局部 `archive/` 服务于兼容与溯源。状态:**active + bounded + historical**。
- [`src/SR_analysis/`](src/SR_analysis/) — 在冻结 PPO 轨迹上发现、拟合并于 Legacy CFD 闭环验证符号控制器。当前只保留 Kármán/cloaking 为 **active but bounded**Illusion SR 是 **historical/negative**steady 仅作幅值校准背景。
- [`src/CCD_analysis/`](src/CCD_analysis/) — corrected `karman_re100` ROI mean 与 cycle-template CCD 的精简权威入口。状态:**completed descriptive/bounded**;旧 temporal/phase 与 pre-reset 树为 **superseded historical**
- [`src/OID_analysis/`](src/OID_analysis/) — weighted snapshot POD、Schlegel LR/LE maps、配对和原子 artifact 校验。状态:**active method core, no active science claim**2026-07 两场景研究为条件性历史材料。
- [`src/steady_pinball_theory/`](src/steady_pinball_theory/) — rear-symmetric steady rotation 的分析、finite-Re 数值证据与 NS-first 验证。状态:**active investigation, bounded evidence**;尚无完成的稳态机制证明。
- [`src/pv_plot/`](src/pv_plot/) — ParaView/FFmpeg 轻量 PNG/MP4 渲染接口,不是独立服务或 pip 项目。状态:**active utility**。
- [`src/archive/`](src/archive/) — 被替代的现代 solver reproduction Track B 等仓库级历史材料;各 package 自己的 `archive/` 也属于其 provenance chain。状态:**historical, non-authoritative unless an active document explicitly cites it**。
- [`CelerisLab/`](CelerisLab/) — Git submodule,现代 GPU LBM solver。Legacy solver 及其证据依赖按各 package 文档和本地环境解析;不要把两个 solver 的结果静默合并。
## 两条 solver 证据链
**LegacyCelerisLab** 是 SR article chain、标准化 Legacy acquisition 以及 corrected CCD 输入所依赖的历史 plant。其冻结模型、normalization、动作顺序、EMA、边界条件、采样时钟和 immutable manifests 共同定义证据;可从 [`src/drl_pinball/legacy_test/README.md`](src/drl_pinball/legacy_test/README.md) 进入。
**现代 CelerisLab V5** 是当前 `drl_pinball/train``drl_pinball/eval` 的 2000×600 工作流,使用新的 Simulation API、calibration/target bundle 和 registry。仓库保留了可推理的 compact bundles 与评估基线,但这不等于当前实现已经完成全矩阵重训,也不允许用 V5 replay 自动替代 Legacy article evidence。
两条链的网格、边界实现、动作换算、force/sensor normalization、policy bundle 和指标版本必须分别报告。跨 solver 比较只能作为明确标注的 migration/reproduction 研究,不能混池统计或互相补证。
## 证据权威层级
由高到低采用以下顺序;若 package README 指定了更严格的内部顺序,以它为准:
1. **不可变原始/派生 artifact**:成功、失败或 partial run 的 manifest、SHA-256、parent identity、原始 telemetry/field 和完整 metric contract。
2. **可执行代码与测试**:能够重算或 fail closed 的 loader、analysis、runner 和 contract tests。
3. **当前 package 权威文档**active README、RESULTS/claim ledger、METHOD/PIPELINE、checkpoint;后写且明确 supersede 的文档优先。
4. **仓库根 README**:负责导航和跨包边界,不替代 package 数值权威。
5. **历史文档、计划、旧图和 archive narrative**:只说明当时意图或演进,不证明 run 完成,也不覆盖后续负结果。
6. **Working Memory/对话摘要**:仅作检索线索,不能替代仓库 artifact。
任何数字若不能解析到 scene、solver、role、realization、window、metric definition、artifact path/hash 和 evidence status,就不应写成权威结论。失败、拒绝、未完成和 partial 记录也是证据,不得覆盖或“清理”掉。
## 环境与安装
基础包声明 Python `>=3.8`,但当前 GPU 工作流以 Linux、NVIDIA GPU、CUDA 和 Python 3.10 的 `pycuda_3_10` conda 环境为准。分析任务通常在 CPU-only `pinball_math` 环境运行;具体依赖和命令以相应 package README 为准。ParaView 自带 Python 不能混入 conda Python 的 `PYTHONPATH`
```bash ```bash
git clone --recurse-submodules <your-repo-url> DynamisLab git clone --recurse-submodules https://github.com/frank14f/DynamisLab.git
cd DynamisLab cd DynamisLab
``` git submodule update --init --recursive
> **Note**: If CelerisLab is a submodule, use `--recurse-submodules` to clone it automatically. conda create -n pycuda_3_10 python=3.10 -y
conda activate pycuda_3_10
### Step 2: Install CelerisLab pip install pycuda
pip install -e CelerisLab
#### Option A: Install from submodule (recommended for development)
```bash
cd CelerisLab
pip install -e .
cd ..
```
#### Option B: Install from pip (if published)
```bash
pip install CelerisLab
```
### Step 3: Install DynamisLab dependencies
```bash
pip install -r requirements.txt
```
### Step 4: Install DynamisLab in development mode
```bash
pip install -e . pip install -e .
``` ```
## Quick Start `requirements.txt`/`pyproject.toml` 提供 NumPy、SciPy、PyTorch、Gymnasium、Stable-Baselines3、绘图和开发工具的基础声明。GPU CFD 应串行初始化;尤其 Legacy 编译会改写共享 kernel/config 文件,不要因使用不同 GPU 就并发编译不同 case。
### Training a PPO Agent ## 真实 quickstart
Train a Proximal Policy Optimization agent for flow control: 现代 V5 Kármán target calibration 与单次训练(完整参数见 [`train/README`](src/drl_pinball/train/README.md)):
```bash ```bash
python scripts/train_ppo.py \ cd src/drl_pinball/train
--run-name my_first_run \ conda run --no-capture-output -n pycuda_3_10 python -u calibrate.py \
--device-id 0 \ --case kar_re100 --device-id 0 --si 800 \
--total-timesteps 100 \ --config ../../../configs/config_lbm_karman_2000x600.json \
--n-steps 3600 \ --out-dir calibrations/kar_re100
--activation sin
conda run --no-capture-output -n pycuda_3_10 python -u train_karman.py \
--case-name kar_re100 --device-id 0 --seed 42 \
--config ../../../configs/config_lbm_karman_2000x600.json \
--calibration calibrations/kar_re100/calibration.json \
--total-episodes 500 --symmetry-prob 0
``` ```
**Arguments:** Illusion PPO 使用同一 calibration contract、`train_illusion.py``ill_*` case;这表示能力存在,不表示 Illusion SR 成功。V5 retained policy 评估:
- `--run-name`: Name for this training run (used for saving models and logs)
- `--device-id`: CUDA device ID for CFD simulation
- `--cuda-device`: CUDA device ID for PyTorch training (can be different from --device-id)
- `--total-timesteps`: Number of training iterations
- `--n-steps`: Environment steps per training iteration
- `--activation`: Activation function (`sin`, `tanh`, or `relu`)
### Monitoring Training
```bash ```bash
tensorboard --logdir tensorboard/ bash src/drl_pinball/eval/run_all.sh --case kar_re100 --seed 45
python3 src/drl_pinball/eval/infer_train.py --validate-all --output-root /tmp/v5-eval
``` ```
Then open http://localhost:6006 in your browser. CPU-only 稳态分析/测试示例(更多命令及 bounded 条件见 [`steady_pinball_theory/README`](src/steady_pinball_theory/README.md)):
### Using the Environment Programmatically
```python
from flow_stealth.environments import CFDFlowControlEnv
from flow_stealth.config import load_celeris_configs
# Load configurations
config_cuda, config_field = load_celeris_configs()
# Create environment
env = CFDFlowControlEnv(
device_id=0,
config_cuda=config_cuda,
config_field=config_field,
)
# Run episode
obs, info = env.reset()
for step in range(500):
action = env.action_space.sample() # Random action
obs, reward, terminated, truncated, info = env.step(action)
if terminated or truncated:
break
env.close()
```
## Configuration
### CFD Configuration
Edit `configs/config_flowfield.json` to change flow parameters:
```json
{
"viscosity": 0.01, # Fluid viscosity
"velocity": 0.1, # Inlet velocity
"field_dim_in_U": [400, 200, 1], # Grid dimensions
...
}
```
### CUDA Configuration
Edit `configs/config_cuda.json` for GPU settings:
```json
{
"threads_per_block": 256,
"unit_dimensions": [16, 16, 1],
...
}
```
## Advanced Usage
### Resume Training
```bash ```bash
python scripts/train_ppo.py \ PYTHONPATH="$PWD/src" conda run -n pinball_math \
--resume models/my_run_best.zip \ python -m pytest -q src/steady_pinball_theory/tests/test_core.py
--run-name my_run_continued
``` ```
### Custom Hyperparameters 绘图接口见 [`src/pv_plot/README.md`](src/pv_plot/README.md)Legacy SR acquisition 和 CCD 不适合作为首次 GPU quickstart,应先读其 immutable-input、serial execution 与 provenance 合约。
```bash ## 2026 年 28 月演进
python scripts/train_ppo.py \
--learning-rate 0.0003 \
--gamma 0.99 \
--batch-size 512 \
--n-steps 7200
```
### Multi-GPU Setup - **2 月**:仓库建立,形成 “Machine Learning + numerical simulation” 的广义框架和 fluidic pinball 主问题。
- **6 月**:集中整理早期 SR/SINDy、CCD correction-field 与 OID/POD/LR-LE 分析;同时暴露 alignment、FIFO、ROI 和证据组织问题,开始从“有图/有分数”转向 contract-first。
- **7 月上旬**:建立参数化现代 V5 Kármán/Illusion 训练、跨 Re/尺寸路线和 solver reproduction;修正 inlet/action/order 等兼容问题。
- **7 月中下旬**:冻结 Legacy SR Stage 1→2→3 article chain,加入 dual-clock CCD、OID 和轻量 `pv_plot`;闭环、hash、no-clobber 与失败保留成为基本要求。
- **8 月初**OID scientific reset 撤回 importance/causality 读法;现代 V5 training release 冻结 compact bundlessteady theory 转向 NS-firstCCD 重做为 corrected ROI mean/cycle-template 权威。
- **8 月 89 日**:统一 Legacy 长窗口角色采集并完成项目收尾。Kármán SR 保持受限活跃;Illusion SR 因接近 physical-zero 的长窗口结果关闭;steady article publication 保持 BOUNDED;根文档改为状态与证据入口。
```bash ## Archive 与 provenance 规则
# CFD simulation on GPU 0, PyTorch training on GPU 1
python scripts/train_ppo.py \
--device-id 0 \
--cuda-device 1
```
## Environment Details - run/artifact 一经发布即 immutable、no-clobber;新尝试使用新 ID,不覆盖成功、失败或 partial 目录。
- 移动/重命名前先核对 parent path、hash、manifest、symlink、外部 Optane mapping 和下游消费者。可读性不能破坏 identity。
- Git 中没有 bulk payload 不代表证据不存在;外部 archive 必须由 inventory/hash 和 package relocation 文档绑定。仅有本地文件也不等于已经 Git-preserved。
- `archive/` 默认不执行、不导入、不作为当前结论;只有 active authority 明确引用时,才按其限定用途使用。
- derived plot/report 不自动成为 acceptance evidence;必须回溯其完整输入和生成合约。
- Legacy 与 V5 的 artifact、normalization、target、metric 和 solver version 分库存放、分开引用。
### CFDFlowControlEnv ## 科学写作边界
The main environment for active flow control around a cylinder. 可以写:指定 solver、case、窗口和 comparator 下的性能;Kármán SR 在已测试 deletion window 内的 term rankingcorrected CCD 的 phase-coherent descriptive co-variation;稳态端点/有限时域的审计结果;OID 数学工具的实现与验证。
**Observation Space:** 不能写:普适 Reynolds/尺寸规律、全局最优或唯一 SR 方程、PPO 本身具有等变性、CCD/DTW lag 给出因果机制或物理延迟、稳态旋转已经闭合动量/能量机制、单 realization 给出不确定性、现代全矩阵已完整重训、OID predictive R² 等价于 importance/control authority,或 Illusion SR 已实现 tracking/generalization。
- Dimensionality: `n_sensors × 2 × 2` (velocity components, current + derivative)
- Default: 12 dimensions (3 sensors × 2 velocities × 2)
- Normalized to zero mean and unit variance
**Action Space:** 写作时应并列给出 observation、interpretation 和 mechanism 的层级,并明确 solver、场景、基线、时长、样本数和状态。论文草稿、计划和 acknowledgements 不得反向升级本地证据。
- Dimensionality: `n_control_cylinders`
- Default: 3 (three controllable cylinders)
- Range: [-1, 1] (scaled internally to physical velocities)
**Reward:** ## Citation、License 与致谢
- Drag reduction: `-cd × 0.1`
- Lift minimization: `-|cl| × 0.05`
- Flow similarity: `-similarity_distance × 0.5`
- Total reward is sum of components
**Episode:** 若使用本仓库,请引用实际采用的代码版本/commit、对应 artifact/manifest 和底层 solver;建议的软件引用为:
- Max steps: 500 (configurable)
- Simulation runs at 800 LBM steps per environment step
## Development
### Project Guidelines
- Follow PEP 8 style guide
- Use type hints for function signatures
- Document classes and functions with docstrings
- Organize projects under `src/` (e.g., `src/flow_stealth/`)
- Keep training scripts in `scripts/`
- Use `config.py` for all path and configuration management
### Adding a New Project
1. Create new project directory in `src/` (e.g., `src/my_new_project/`)
2. Add `__init__.py`, `config.py`, and project-specific modules
3. Create environments in `src/my_new_project/environments/`
4. Create corresponding training scripts in `scripts/`
### Adding a New Environment to FlowStealth
1. Create new environment class in `src/flow_stealth/environments/`
2. Inherit from `gym.Env`
3. Register in `src/flow_stealth/environments/__init__.py`
4. Create corresponding training script in `scripts/`
### Running Tests
```bash
pytest tests/
```
## Citation
If you use DynamisLab in your research, please cite:
```bibtex ```bibtex
@software{dynamis2026, @software{dynamislab2026,
author = {Frank14f}, author = {Frank14f},
title = {DynamisLab: Machine Learning for Computational Fluid Dynamics}, title = {DynamisLab: Machine Learning for Computational Fluid Dynamics},
year = {2026}, year = {2026},
@@ -280,31 +152,6 @@ If you use DynamisLab in your research, please cite:
} }
``` ```
Also cite CelerisLab: 同时按实际使用情况引用 [CelerisLab](https://github.com/frank14f/CelerisLab)、Stable-Baselines3、Gymnasium、NumPy/SciPy、PyTorch、ParaView 以及各分析方法的原始论文。代码以 [MIT License](LICENSE) 发布;外部论文、模型、数据和 solver artifact 可能有各自的引用与再分发要求。
```bibtex 感谢 CelerisLab 提供 GPU-accelerated LBM 基础,Stable-Baselines3 与 Gymnasium 提供强化学习接口,PyTorch、NumPy/SciPy、Matplotlib 和 ParaView 支撑训练、分析与可视化。欢迎通过 issue 或 pull request 讨论可复现性、证据合约和明确限定范围的改进。
@software{celerislab2026,
author = {Frank14f},
title = {CelerisLab: GPU-Accelerated Lattice Boltzmann Method Solver},
year = {2026},
url = {https://github.com/frank14f/CelerisLab}
}
```
## License
MIT License - see LICENSE file for details
## Acknowledgments
- Built on [CelerisLab](https://github.com/frank14f/CelerisLab) CFD solver
- Uses [Stable-Baselines3](https://github.com/DLR-RM/stable-baselines3) for RL
- Gymnasium API for standardized environments
## Contributing
Contributions are welcome! Please open an issue or pull request.
## Contact
For questions or issues, please open a GitHub issue or contact Frank14f.
-452
View File
@@ -1,452 +0,0 @@
# Symbolic regression of learned flow-control policies
## 1. Purpose, evidence hierarchy and scope
The deep-reinforcement-learning (DRL) controllers used for hydrodynamic cloaking and illusion are effective, but their neural-network representation does not directly expose the control mechanism. Symbolic regression (SR) is therefore used as a post hoc policy-reduction method. The fitted expressions are empirical observation-to-action surrogates on states visited by PPO; they are not governing equations and are not identified directly from the Navier--Stokes equations.
This distinction matters in closed loop. A formula can reproduce PPO actions on a recorded trajectory and still alter the state distribution after deployment, accumulate phase error, develop an action bias, or destabilize CFD. Consequently, offline regression metrics are used to discover variables and topologies, whereas finite closed-loop CFD and trajectory similarity decide whether a candidate is useful. Term deletion and coefficient scaling then assess which parts of a deployed candidate matter.
The active software has three executable stages:
1. `stage_1_infer.py` collects contract-audited PPO trajectories;
2. `stage_2_fit.py` performs symbolic discovery and fixed-topology coefficient refitting;
3. `stage_3_validate.py` deploys PPO, symbolic, constant, or uncontrolled policies in CFD.
Within Stages 2--3, model selection has five phases: per-case discovery, within-objective joint discovery, topology freezing and coefficient refit, short and standard CFD screening, and term deletion/scaling. These phases are not additional software stages.
The fitted article evidence is deliberately narrower than the complete flow-control project. It contains four periodic Kármán-street cloaking policies and three cylinder-wake illusion policies. Kármán and illusion are never pooled into one regression. The disturbance-free steady scene is used only for post-selection calibration of the Kármán law. Transient-vortex, erase, V5, and historical SINDy analyses are outside the fitted evidence considered here.
Two evidence generations must remain separate:
- the **2026-07-18 primary evidence** contains the seven training trajectories, symbolic discovery, fixed-topology refits, 40-step screening, 200-step validation, and term tests;
- the **2026-07-20 coefficient-frozen extension** contains steady calibration, per-case diagnostic refits, 400-step duration tests, CSV exports, and pointwise unseen-condition deployments.
No extension condition participated in topology selection or coefficient estimation.
## 2. Physical labels, state contract and action units
### 2.1 Reynolds-number and target-size conventions
The inlet speed is \(U_0=0.01\) in lattice units and the pinball-cylinder diameter is \(D=20\). The historical Kármán scene names use a code Reynolds label based on the reference length \(2D=40\):
\[
Re_D=\frac{U_0D}{\nu}=\frac{\texttt{re\_code}}{2}.
\]
Thus `karman_re50`, `karman_re100`, `karman_re200`, and `karman_re400` denote \(\texttt{re\_code}=50,100,200,400\), corresponding to \(Re_D=25,50,100,200\). Both conventions must be stated whenever physical Reynolds numbers are compared.
The illusion scene names `illusion_0.75L`, `illusion_1L`, and `illusion_1.5L` are legacy target-size labels. Despite the historical configuration field name `target_diameter`, its value times \(L=20\) is passed to `LegacyCelerisLab.add_cylinder` as the cylinder **radius**. The labels are retained for provenance, but they must not be described as target-cylinder diameters.
The Kármán control sampling interval is 800 lattice steps. Illusion intervals are 400, 600, and 800 steps for the 0.75L, 1L, and 1.5L labels. With the convective scale \(D/U_0=2000\) lattice steps,
\[
\Delta t_c=\frac{\mathrm{sample\ interval}}{D/U_0},
\]
so the dimensionless control intervals are 0.4 for Kármán and 0.2, 0.3, and 0.4 for the three illusion scenes.
### 2.2 Native ordering
The canonical body and action order is
\[
(\mathrm{front},\mathrm{upper},\mathrm{lower}).
\]
The six downstream sensor channels are ordered
\[
(u_U,v_U,u_C,v_C,u_L,v_L),
\]
and the six force channels are
\[
(F_{x,F},F_{y,F},F_{x,U},F_{y,U},F_{x,L},F_{y,L}).
\]
This order follows the audited LegacyCelerisLab object IDs and force slots. It is not inferred from force signs. The runtime order gate is rerun after CFD or kernel changes because a silent slot permutation would change the physical meaning of every fitted coefficient.
### 2.3 PPO normalization and SR nondimensionalization
Two different transformations must not be conflated. PPO receives a clipped normalized observation: forces are divided by `force_norm_fact`, sensor velocities are centred by `sens_deviation` and divided by `sens_norm_fact`, and the result is clipped to \([-1,1]\). Illusion appends the normalized two-component target-cylinder force. The article trajectories use frozen existing normalization rather than recomputing normalization on each rollout.
SR does not fit these clipped PPO inputs. Recorded raw lattice data are converted to physical dimensionless features:
\[
\hat u=u/U_0,\qquad \hat v=v/U_0,
\]
\[
C_d=\frac{2F_x}{\rho U_0^2D},\qquad
C_l=\frac{2F_y}{\rho U_0^2D},
\]
with \(\rho=1\). The regression target is dimensionless cylinder surface velocity
\[
\boldsymbol{\alpha}_t
=\frac{\boldsymbol{\omega}_t}{U_0}
=(\alpha_{F,t},\alpha_{U,t},\alpha_{L,t})^{\mathsf T}.
\]
A PPO-normalized command is decoded before fitting as
\[
\boldsymbol{\alpha}
=s_a\mathbf a_{\mathrm{norm}}+\mathbf b_a.
\]
The Kármán action scale and bias are \(s_a=8\) and \((0,-4,4)\); the illusion values are \(s_a=4\) and \((0,-2,2)\). Stage 1 stores the normalized command, dimensionless \(\alpha\), and lattice \(\omega=U_0\alpha\), making unit conversion auditable.
## 3. Article trajectories and causal dataset
Seven new deterministic PPO trajectories were collected:
\[
\mathcal D_K=\{\texttt{re50},\texttt{re100},\texttt{re200},\texttt{re400}\},
\]
\[
\mathcal D_I=\{0.75L,1L,1.5L\}.
\]
Each trajectory contains 200 recorded post-action states. The causal contract is
\[
x_i\longmapsto\alpha_{i+1},
\]
named `causal_post_state_to_next_action`. At state \(x_i\), action-history features may use \(\alpha_i\) and \(\alpha_{i-1}\), but never a future action. The requirement for \(\alpha_{i+1}\) removes the final state and the two-row action-history warm-up removes indices 0 and 1, leaving state indices 2--198: 197 fitted rows per trajectory.
Every trajectory is aligned and split independently before stacking. The discovery split is contiguous 60/20/20% train, validation, and blind data; temporal rows are not randomly shuffled and boundaries never cross trajectories. The blind block is not fitted during topology discovery. After a topology has been frozen, its numerical constants are refitted on all eligible aligned rows. Therefore, the blind block protects topology selection but is no longer an untouched holdout after final refitting; final scientific acceptance comes from closed-loop CFD.
The PPO model was replayed on each stored causal state using the frozen observation normalization and decoder. All seven action sequences reproduced exactly. Historical and pre-contract trajectories remain available for diagnosis but are not pooled with the article dataset.
## 4. Candidate variables and reflection symmetry
### 4.1 Feature libraries
The `raw_complete` representation contains twelve variables: six dimensionless sensor velocities and the drag/lift coefficients of the front, upper, and lower cylinders.
The `symmetry` representation contains fourteen variables:
\[
(u_s,u_a,u_c,v_s,v_a,v_c,
C_{d,F},C_{d,\mathrm{rear},s},C_{d,\mathrm{rear},a},C_{d,\mathrm{tot}},
C_{l,F},C_{l,\mathrm{rear},s},C_{l,\mathrm{rear},a},C_{l,\mathrm{tot}}).
\]
The rear and sensor coordinates use half-sums and half-differences. For example,
\[
u_s=\frac{u_U+u_L}{2},\qquad
u_a=\frac{u_U-u_L}{2},
\]
\[
C_{d,\mathrm{rear},s}=\frac{C_{d,U}+C_{d,L}}{2},\qquad
C_{d,\mathrm{rear},a}=\frac{C_{d,U}-C_{d,L}}{2},
\]
with identical conventions for \(v\) and lift. This factor of one half is part of the formula contract: omitting it would rescale the reported coefficients.
Illusion discovery compares four controlled profiles:
- `actual_only`: actual-state variables only;
- `target_only`: target \(C_d\) and \(C_l\) only;
- `actual_plus_target`: actual state plus target force coefficients;
- `actual_plus_error`: actual state plus \(C_{d,\mathrm{tot}}-C_{d,\mathrm{target}}\) and \(C_{l,\mathrm{tot}}-C_{l,\mathrm{target}}\).
The article discovery does not add trigonometric phase coordinates or a manual bias column. PySR may still create numerical constants. Cross-correlation is never used to choose a feature lag.
### 4.2 Complete reflection map
Reflection \(G\) about the centreline exchanges upper and lower positions. Streamwise velocity is even, transverse velocity is odd, drag is even, and lift is odd. Thus upper/lower sensor and force slots are exchanged with the appropriate transverse/lift sign reversal. Front drag is even and front lift is odd. Target drag is even and target lift is odd. The same map is applied to any action history.
The native action transforms as
\[
G_a(\alpha_F,\alpha_U,\alpha_L)
=(-\alpha_F,-\alpha_L,-\alpha_U).
\]
Fit augmentation and deployment architecture are separate. G augmentation adds mirrored state-action rows during fitting. The final mapped-shared deployment imposes
\[
\operatorname{odd}[h](x)=\frac{h(x)-h(Gx)}{2},
\]
\[
\alpha_F(x)=\operatorname{odd}[h_F](x),\qquad
\alpha_U(x)=h_R(x),\qquad
\alpha_L(x)=-h_R(Gx).
\]
This is a physical inductive bias imposed on the symbolic controller. It does not establish exact PPO equivariance, and symmetrization may modify as well as simplify the PPO policy. Independent three-head fits are retained only as diagnostics of PPO structure.
## 5. Discovery, refitting and safety
### 5.1 PySR discovery
The discovery grammar uses binary \(+\), \(-\), and multiplication, with `square` as the unary operator. Search is deterministic and serial, without batching. The full defaults are 30 populations, population size 33, tournament size 10, maximum expression size 15, constant complexity 2, and parsimony 0.01. The bounded article discovery configuration (`--smoke`) uses two populations, population size 16, tournament size 4, and maximum size 7. At least three deterministic seeds are run per case/profile.
Only training blocks are fitted. Up to 25 retained Pareto candidates per head are evaluated on contiguous train, validation, and blind blocks using \(R^2\), MAE, RMSE, maximum error, complexity, and used variables. Static safety is a finite-value probe over sparse points spanning observed feature ranges; because no required output interval is supplied, it is not a global action-range guarantee.
Topology selection is a manual, evidence-based scientific step. It considers recurrence across seeds and cases, held-out diagnostics, complexity, finite static evaluation, compatibility with mapped-shared deployment, and CFD viability. PySR score or \(R^2\) never automatically promotes a formula, and an average cannot hide failure in one required scene.
### 5.2 Fixed-topology refit
After selecting a recurring topology, every numerical literal is replaced by a separate optimization parameter while operators and feature occurrences remain fixed. Constants are optimized with `scipy.optimize.least_squares`. Residuals use square-root sample weights so each case has equal total mass and trajectories within a case also have equal mass. Mapped-shared refits retain G augmentation. The artifact records initial/refitted constants, optimizer status, aggregate/per-case/per-trajectory metrics, discovery-parent path and hash, dataset hashes, feature order, action units, alignment, and deployment semantics.
Offline metrics describe PPO action imitation on PPO-visited states. They cannot be ranked directly against closed-loop DTW because symbolic deployment changes the state distribution.
### 5.3 Formula and CFD safety
Formula artifacts carry separate fitted/deployment expressions and hashes. Evaluation permits only declared features and a restricted function set, rejects unsupported syntax and variables, and performs a zero-state probe when Stage 3 loads a formula pair. Static finite probing is only a pre-screen.
Closed-loop safety is decisive. The symbolic policy maintains separate online feature histories for \(x\) and \(Gx\), initialized from the scene policy action. Every action and raw CFD observation is checked for finiteness. A failure retains partial telemetry, failed-step information, hashes, and the exception instead of overwriting the run. Candidates first receive a 40-step screen, then a 200-step standard validation. The 2026-07-20 extension adds 400-step tests without changing coefficients.
### 5.4 Legacy DTW metric
The only article metric is `legacy_dtw_v1_abs_n_unclipped`, recorded under `legacy_reference_cycle_vs_last_recorded_cycle`. For Kármán, `conv_len=30`; for illusion, `conv_len=36`. Lag is selected from transverse sensor channel 1 by cross-correlating target samples `conv_len:2*conv_len` with the final controlled `conv_len` samples. The complete target sequence is circularly shifted by that lag. Absolute, normalized, unclipped DTW similarity
\[
S_j=1-\frac{d_{\mathrm{DTW}}(y^{\mathrm{target}}_j,y^{\mathrm{controlled}}_j)}{N}
\]
is then computed independently for all six sensor channels, and the reported value is their arithmetic mean. One is ideal; the metric may be negative. Lag is a metric-alignment parameter, not a physical observation or actuation delay. The scalar score compares a reference cycle with the final recorded cycle; 400-step CSV convergence files are needed to inspect its evolution over duration.
## 6. Attempt ledger and selection lessons
Broad per-case searches showed heterogeneous Kármán formulas rather than a clean two-regime partition. Joint symmetry searches repeatedly selected front rear-drag asymmetry and a rear lift-plus-constant topology. For illusion, endpoint cases selected different variable families, motivating profile-controlled joint searches instead of a hand-reduced universal library.
Two illusion front topologies remained plausible offline. Topology A combined \(C_{d,\mathrm{rear},a}\) and \(C_{l,F}\). Topology B used \(C_{d,\mathrm{rear},s}C_{l,F}-C_{l,\mathrm{tot}}\). Topology B completed 40 steps at 0.75L with similarity 0.958889 and lag 7, but both 1L and 1.5L failed with `FloatingPointError: raw observation contains non-finite values`. Its formula-pair hash is `93615f0809c76d722a9cd781e08b23e1167a2004957964807a3d661f5c98ee38`. It was rejected, and its failures were retained. This is the clearest demonstration that an offline Pareto candidate and even one successful scene cannot substitute for all-case closed-loop screening.
Older pre-force-order formulas, round-one results, SINDy paths, V5 experiments, and archived Stage 4 figures remain historical or diagnostic. They are not alternative current entrypoints and their numbers are not imported into the article evidence.
## 7. Kármán-street cloaking results
### 7.1 Joint law and offline fit
The selected fixed-topology law is
\[
\boxed{\alpha_F(x)=\operatorname{odd}\!\left[-0.381391\,C_{d,\mathrm{rear},a}\right]},
\]
\[
\boxed{\alpha_U(x)=1.307782\,C_{l,\mathrm{rear},s}-3.431209,\qquad
\alpha_L(x)=-\alpha_U(Gx)}.
\]
The formula-pair hash is `a678f2019e0da7a0e1263f0c911b377106a668a6716ba93d6efd78f58de0a3f1`; the front and rear deployment-expression hashes are `367b5b7e...d4650` and `75207940...60f7`.
Aggregate offline metrics are:
- front head: \(R^2=0.5699\), MAE 0.8872, RMSE 1.1876, maximum error 3.1129;
- rear shared head: \(R^2=0.4363\), MAE 1.6187, RMSE 2.0608, maximum error 5.6964.
The per-case contrast is scientifically informative. Front \(R^2\) is 0.2488, 0.8671, 0.6100, and 0.8893 for the four code-Re labels. Rear \(R^2\) is -0.5315, 0.5666, 0.5483, and 0.2242. Re50 therefore has poor offline rear-action imitation but excellent closed-loop similarity, whereas Re400 has a strong front offline fit and the weakest standard closed-loop score. Offline action accuracy is not the control-performance ordering.
### 7.2 Standard and duration validation
The 200-step similarities at code labels Re50, Re100, Re200, and Re400 are 0.9543, 0.9427, 0.8560, and 0.7827. The shared law is strongest at lower/intermediate conditions and degrades at Re400; it is not a universal cross-Re law.
At 400 steps, similarities are 0.952178, 0.944339, 0.863850, and 0.833365. Every telemetry channel remains finite. The Re400 limitation is therefore not delayed numerical blow-up over this tested horizon, although one 400-step realization cannot establish statistical robustness.
### 7.3 Term deletion
Forty-step deletion tests provide the following sequence over Re50/Re100/Re200/Re400:
- delete front feedback: 0.939361 / 0.912182 / 0.881434 / 0.813289;
- remove rear lift feedback but retain the constant: 0.917126 / 0.869943 / 0.825250 / 0.789535;
- remove the rear constant but retain lift feedback: 0.839344 / 0.817735 / 0.708089 / 0.647401.
Within this short ablation horizon, the supported ordering is
\[
\text{rear constant}>\text{rear lift feedback}>\text{tested front feedback}.
\]
The persistent rear counter-rotation is therefore the dominant tested controller component. Its interpretation as downstream-deficit compensation is consistent with the expected gap-flow and momentum correction, but SR alone does not observe the spatial momentum field and does not prove causality.
### 7.4 Per-case fixed-topology diagnostics
Refitting the same topology separately gives \((a,b,c)\) in \(\alpha_F=-aC_{d,\mathrm{rear},a}\), \(\alpha_U=bC_{l,\mathrm{rear},s}-c\):
- Re50: (0.5836, 0.2212, 3.5820), rear \(R^2=0.0221\);
- Re100: (0.3248, 1.3203, 4.1774), rear \(R^2=0.7131\);
- Re200: (0.5003, 1.6971, 3.4109), rear \(R^2=0.5788\);
- Re400: (0.2947, 1.0549, 2.5545), rear \(R^2=0.3285\).
The coefficients vary non-monotonically and do not support a clean low/high-Re split. These fits are offline diagnostics and were not promoted as independent closed-loop controllers.
### 7.5 Steady calibration
A disturbance-free pinball independently calibrates the order of magnitude of the rear constant. A discrete constant counter-rotation sweep \(A=0,1,\ldots,6\), with rear commands \((-A,+A)\), gives similarities 0.631830, 0.723858, 0.857286, 0.955029, 0.976376, 0.987212, and 0.978674. Thus \(A=5\) is the best **sampled** value, not a continuously optimized value.
The Kármán law in the same steady scene gives similarity 0.966494. Its final-cycle mean actions are -0.000563, -3.430589, and 3.431828 for front, upper, and lower, consistent with its analytical constant magnitude 3.431209. The fitted value is about 68.6% of the sampled \(5U_0\) optimum. This establishes scale consistency between the learned constant and useful steady compensation; it is not an equality between wake velocity deficit, momentum deficit, and cylinder surface speed.
### 7.6 Pointwise unseen-Re extension
Without coefficient retuning, 200-step deployments at code labels Re25, Re70, Re150, and Re300 give 0.988078, 0.954339, 0.907496, and 0.835758. Re70/Re150/Re300 are interpolation points within the fitted code-label range; Re25 is one low-Re extrapolation. The results show finite pointwise deployment at these sampled configurations only. There is no high-Re extrapolation above Re400, no continuous coefficient law, and no repeated-initial-condition uncertainty estimate.
## 8. Illusion results
### 8.1 Per-size discovery and selected law
Broad discovery changes systematically across legacy target-size labels. At 0.75L, \(C_{d,\mathrm{rear},a}\) and \(C_{d,\mathrm{rear},s}\) appear 15 and 10 times across audited heads. The 1L searches are mixed/transitional, led by \(C_{d,F}\) (13) and \(C_{l,\mathrm{rear},s}\) (12). At 1.5L, \(C_{l,F}\) and \(C_{l,\mathrm{rear},s}\) appear 54 and 46 times, showing a lift-contrast-dominated endpoint.
The stable joint numerical candidate is
\[
\boxed{\alpha_F(x)=\operatorname{odd}\!\left[-1.826604\,C_{d,\mathrm{rear},a}+2.064493\,C_{l,F}\right]},
\]
\[
\boxed{\alpha_U(x)=1.254440\,C_{d,\mathrm{rear},a}-1.528074\,C_{l,F},\qquad
\alpha_L(x)=-\alpha_U(Gx)}.
\]
Its formula-pair hash is `ae67ae5071065b7ee8412791ee1841011530746865528641beddb1a203c51b83`; front/rear expression hashes are `1df7c515...0487` and `485de2ca...b8e8`.
### 8.2 Offline fit versus closed-loop performance
Aggregate offline metrics are:
- front head: \(R^2=0.4851\), MAE 1.3075, RMSE 1.9726, maximum error 6.6080;
- rear shared head: \(R^2=0.3598\), MAE 1.3347, RMSE 1.5823, maximum error 5.1284.
Per-case front \(R^2\) is 0.5850, -1.7176, and 0.5054 for 0.75L, 1L, and 1.5L; rear \(R^2\) is -5.7162, -12.5115, and 0.5923. The negative values must be retained: the candidate is not a uniformly accurate PPO action surrogate.
Nevertheless, 200-step closed-loop similarities are 0.8749, 0.9217, and 0.8306. At 400 steps they are 0.854379, 0.915609, and 0.833587, with finite telemetry. Closed-loop viability despite weak offline action fit again demonstrates that the deployed controller cannot be selected by \(R^2\) alone.
### 8.3 Per-size fixed-topology diagnostics
Separate refits produce:
- 0.75L front: \(-0.2420C_{d,\mathrm{rear},a}-0.8373C_{l,F}\), \(R^2=0.8035\); rear: \(0.2486C_{d,\mathrm{rear},a}+0.0829C_{l,F}\), \(R^2=-5.4396\);
- 1L front: \(2.0438C_{d,\mathrm{rear},a}-2.2193C_{l,F}\), \(R^2=0.6060\); rear: \(0.1843C_{d,\mathrm{rear},a}-0.1588C_{l,F}\), \(R^2=-11.2480\);
- 1.5L front: \(-0.0441C_{d,\mathrm{rear},a}+2.1015C_{l,F}\), \(R^2=0.5421\); rear: \(1.5683C_{d,\mathrm{rear},a}-1.6011C_{l,F}\), \(R^2=0.5948\).
The 1.5L front is nearly pure front-lift feedback and its rear coefficients are roughly an order of magnitude larger than the poorly identified smaller-target rear fits. Sign changes and very negative smaller-target rear \(R^2\) values prevent promotion of a clean two-group coefficient mechanism. These are diagnostics of the compromise made by a shared static topology.
### 8.4 Deletion and non-uniqueness
All four one-term deletion variants completed 40 steps. For 0.75L/1L/1.5L:
- delete first front term: 0.939375 / 0.933481 / 0.885085;
- delete second front term: 0.960067 / 0.927035 / 0.836563;
- delete first rear term: 0.954488 / 0.936851 / 0.887603;
- delete second rear term: 0.954641 / 0.930454 / 0.850816.
Thirty-seven preregistered coefficient-scaling shadow variants remained finite. The \(C_{l,F}\) terms dominate action-amplitude sensitivity, while \(C_{d,\mathrm{rear},a}\) is weaker and partly replaceable. Because all one-term deletions remain stable and differences are modest over 40 steps, the four-term expression is not unique and no individual term is established as universally necessary.
Target and error variables were available but did not recur in the selected low-complexity static topology. This is negative evidence against claiming explicit target tracking; it is not proof that target information is physically irrelevant. Target phase may be aliased into PPO-visited forces, may require memory, or may enter differently across size regimes.
### 8.5 Pointwise unseen-size extension
Coefficient-frozen 200-step interpolation at 0.8L and 1.2L gives 0.884573 and 0.925530. Extrapolation at 0.5L, 0.6L, and 2L gives 0.784055, 0.821103, and 0.756880. Every sampled run completes, but degradation toward the extremes is clear. These are single pointwise realizations and do not define a universal target-size law.
The defensible illusion conclusion is therefore narrower than for Kármán: a shared symmetric numerical controller exists over the tested family, with 1.5L a structurally different boundary regime, but the present static law does not identify a unique target-dependent mechanism.
## 9. SR-to-OID/CCD handover
SR identifies actuator-side observation-to-action structure. It does not identify where the corresponding flow correction is located. The handover to OID/CCD is therefore a ranked, falsifiable target list rather than a claim that the structures have already been found.
For Kármán:
1. **Rear steady counter-rotation, strongest evidence.** OID should search for a reflection-symmetric streamwise correction generated in the rear gap and retained at the sensor station. CCD should quantify the rear-pair relation to the mean/low-frequency downstream deficit mode.
2. **Symmetric rear lift feedback, moderate evidence.** Coefficients vary from 0.22 to 1.70, so the term is a condition-dependent modulation rather than a universal gain. Seek a rear-cylinder force-correlated source and lagged downstream descendant.
3. **Rear drag asymmetry in front action, weak evidence.** Test an antisymmetric near-front structure and expect weaker downstream canonical correlation.
For illusion:
1. **Front lift, moderate evidence.** Compare front-body source structures across target-size labels and test whether descendants change wavelength or phase.
2. **Rear drag asymmetry, weak-to-moderate evidence.** Search for antisymmetric rear-gap structures, explicitly contrasting 1.5L with smaller labels.
3. **Absence of explicit target/error terms, negative evidence.** Use lagged and phase-resolved analyses because static obs--act regression can alias memory or phase into force observations.
For every element, actuator-to-source and source-to-downstream relations must be reported separately; upper/lower parity must be preserved; lag must be stated in \(D/U_0\); and spatial coincidence must not be promoted to causality without time-lagged evidence. Agreement between SR ranking and OID/CCD correlation is convergent evidence. Contradictions must be retained and used to revise the interpretation rather than forcing agreement.
## 10. Limitations and claim discipline
The analysis has the following explicit limitations.
1. There is one 200-step PPO trajectory per fitted case. PySR seed recurrence is not recurrence over independent PPO or CFD trajectories.
2. Temporal rows are correlated; 197 rows are not 197 independent flow realizations.
3. The symbolic grammar, complexity bound, population settings, and finite seed count do not establish a global symbolic optimum.
4. Exact reflection symmetry is imposed, not discovered, and may modify the original PPO.
5. The selected laws are static and instantaneous. They cannot represent explicit memory, and failure to select target variables does not show memory or target information is unnecessary.
6. All eligible rows are reused after topology freezing, so final coefficient metrics are not a fully blind estimate.
7. The standard and extension runs report one deterministic realization per condition; no repeated-initial-phase or disturbance uncertainty interval is available.
8. The DTW result depends on the selected reference/final-cycle window and lag alignment, is not a full-field metric, and cannot prove mechanism identity.
9. Generalization is pointwise over sampled Reynolds labels and target sizes. Geometry perturbations, sensor noise, actuator mismatch, altered sampling, and other disturbances are untested.
10. No preregistered scalar DTW success threshold exists. Finiteness is a hard gate, while performance language is relative and case-specific.
11. There is no transient-vortex SR evidence in the current fitted package.
12. The steady sweep does not establish a momentum-balance equality or a continuous optimum.
13. OID/CCD causal structures are future/independent evidence, not present SR results.
Accordingly, the evidence **establishes** a reproducible discovery-to-CFD workflow, the dominance of the rear constant within the tested Kármán law, secondary short-horizon value of rear lift feedback, a finite shared illusion numerical candidate, and the inadequacy of offline fit alone for controller selection. It **supports, with bounded scope**, a shared Kármán backbone over tested conditions and finite pointwise extension performance. It does **not establish** uniqueness, universality, explicit illusion target tracking, necessity of every illusion term, physical delay from DTW lag, or causal deficit compensation without field-level analysis.
## 11. Reproducibility and evidence map
### 11.1 Environments and resources
Stage 1, policy replay, and Stage 3 use conda environment `pycuda_3_10`. PySR discovery and numerical refitting use `sr_env`. CFD runs are strictly serialized on physical GPU 2. With `CUDA_VISIBLE_DEVICES=2`, scripts use logical device 0; provenance records visibility and GPU identity. Run IDs are immutable and failure telemetry is retained.
At the 2026-07-21 final-consolidation revision, the CPU contract suite is run from the repository root with:
```bash
PYTHONPATH=src conda run -n sr_env python -m pytest \
src/SR_analysis/tests tests/test_stage_3_validate.py -q
```
The expected result at the 2026-07-21 plotting-package revision is 88 passed tests. This count is revision-specific rather than a timeless scientific result.
### 11.2 Primary and extension packages
The primary evidence index is:
```text
src/SR_analysis/results/runs/article-joint-sr-final-20260718/
readable_summary.txt
evidence_manifest.json
```
The coefficient-frozen extension is indexed by:
```text
src/SR_analysis/results/runs/article2-sr-elements-20260720/
src/SR_analysis/results/runs/article2-steady-analysis-20260720/
src/SR_analysis/results/runs/article2-percase-refit-summary-20260720/
src/SR_analysis/results/runs/article2-generalization-summary-20260720/
```
Standard-duration PPO/SR/target CSVs, including wide/long tables and DTW convergence, are under `article2-timeseries-csv-20260720/`. Four-hundred-step SR/target exports are under `article2-long-timeseries-csv-20260720/`.
### 11.3 Stable identities
The archived fitting Git SHA is `ca8ee5f238ee58eaaf48027ad026c35784f76d4d`. Kármán and illusion dataset hashes are respectively
```text
dcbfdaaa48a61bd904bb540f3067760530bd69e88ce87d54110a79ecc54b79d6
50c1d9f95bd72afc14e2d06a205bf4432672224ebf7daeb442ea6c517fbd9ab7
```
Formula-pair hashes are
```text
Karman: a678f2019e0da7a0e1263f0c911b377106a668a6716ba93d6efd78f58de0a3f1
Illusion: ae67ae5071065b7ee8412791ee1841011530746865528641beddb1a203c51b83
```
Formula JSON files carry exact commands, parent hashes, feature order, expression hashes, optimizer state, environment, and offline metrics. Validation JSON files carry formula/configuration hashes, metric details, GPU identity, telemetry hash, termination, and record hash. `scene_registry.json` is not the authority for current article evidence, and integrity auditing does not automatically promote a candidate.
## 12. Final paper-level conclusion
The Kármán analysis provides the strongest mechanism-oriented SR result. A persistent rear-pair counter-rotation is the dominant tested component; rear symmetric-lift feedback gives secondary short-horizon value; the tested front correction is weak. The constant has the same physical order as independently useful steady counter-rotation, which is consistent with a wake-deficit-compensation hypothesis. Spatial momentum correction and causality remain for OID/CCD, and reduced Re400 performance prevents a universal-law claim.
The illusion analysis provides a stable shared symmetric numerical controller but not a unique target-tracking mechanism. Front-lift terms dominate action sensitivity, drag-asymmetry terms are partly replaceable, and 1.5L is a distinct boundary regime. Static target/error variables were not selected robustly, so further mechanism work should use controlled target-aware dynamic structures and independent field decomposition rather than broader unconstrained symbolic searches.
The general methodological conclusion is that SR in closed-loop flow control should be treated as hypothesis generation plus deployment testing. Formula compactness and offline fit identify candidates; CFD stability, trajectory similarity, ablation, and independent flow-field evidence determine what can be interpreted physically.
-292
View File
@@ -1,292 +0,0 @@
# OID Analysis: Correction-Field Structure Diagnosis Results
> Date: 2026-06-15
> Project: DynamisLab -- Active hydrodynamic cloaking and illusion using DRL on a fluidic pinball.
> Analysis pipeline: OID (Observable-Inferred Decomposition) on correction fields (Delta-q_ctl).
---
## Executive Summary
Four key findings from the OID analysis pipeline:
1. **Force-relevant and signature-relevant correction structures systematically separate** across control tasks. In steady cloak, they are highly related (cosine similarity = 0.763); in Karman cloak, nearly orthogonal (-0.034); in illusion, increasingly anti-correlated as target diameter grows (from -0.082 to -0.932). This is the most striking result of the analysis.
2. **OID consistently and substantially outperforms POD** for predicting both force and future sensor signature. Across all periodic scenes, OID achieves R2 = 0.315-0.750 with 2 coordinates, while POD achieves R2 = -2.4 to 0.418. The success criterion ("m<=3 OID beats m<=3 POD") is satisfied for every scene.
3. **The separation is robust.** POD rank sensitivity tests (r=6,8,10,12,16) confirm Karman and illusion 1.0L/1.5L are very stable. Karman's force-sig separation is insensitive to the choice of convective delay tau_c (overlap ranges 0.11-0.31 across 10 different delays). The one exception is illusion 0.75L, which shows rank sensitivity and needs more data.
4. **OID coordinates are not control states.** Force-OID coordinates capture only 22.5% of action variance (vs 95.6% for raw sensor observations). This is expected and appropriate: OID identifies structures most relevant to forces and signatures, not to actions. Action-related coordinates require a separate causal-PCD analysis.
---
## 1. OID: What It Is and Why
### 1.1 The Problem with POD
Standard POD (Proper Orthogonal Decomposition) ranks flow structures by their **fluctuation energy**. The highest-energy modes capture the most "energetic" features of the flow -- typically the von Karman vortex shedding pair. But the DRL controller's objective is not "maximize energy" or "minimize energy." It is to match a downstream sensor signature, which may involve flow structures that are not the most energetic.
POD provides a useful unified coordinate system, but its ranking is by energy, not by task relevance.
### 1.2 The OID Idea
OID (Observable-Inferred Decomposition, Schlegel et al. 2012) is a generalization of POD that finds flow structures most correlated with a chosen **observable** of interest (e.g., total force, sensor error). The idea is:
1. Start with a POD coordinate system (the unified basis)
2. Choose an observable Y (e.g., total lift force, delayed sensor error)
3. Compute the cross-covariance matrix between POD coefficients A and observable Y
4. Perform SVD on this cross-covariance: `C_AY = U @ Sigma @ V.T`
5. The columns of U define directions in POD space that best predict the observable
The OID coordinates are:
```
z(t) = A(t) @ U
```
This is a simple rotation of the POD subspace. The singular values in Sigma tell us how much observable-relevant information each OID direction captures. The spatial modes are linear combinations of POD modes:
```
phi_k_OID(x,y) = sum_j U_{jk} * phi_j_POD(x,y)
```
### 1.3 The Correction-Field Preprocessing
Before OID, we must separate what the controller actually changed from what the flow inherently does. For each scene we construct three fields:
- **q_in**: Incident reference field (empty channel, or vortex street only)
- **q_blk**: Fixed pinball field (pinball present, zero rotation, natural shedding)
- **q_ctl**: Controlled pinball field (DRL policy active)
The two derived difference fields are:
- **Delta_q_blk = q_blk - q_in**: What the pinball's geometry does (passive blockage)
- **Delta_q_ctl = q_ctl - q_blk**: What the controller additionally does (active correction)
OID operates on Delta_q_ctl (the active correction), NOT on the raw controlled field. This separation prevents mixing up "structures that were already there" (inherent shedding) with "structures the controller introduced."
### 1.4 The OID Pipeline
```
Full field snapshots (500 steps)
|
v
Three-field decomposition: q_in, q_blk, q_ctl
|
v
Correction field: Delta_q_ctl = q_ctl - q_blk
|
v
POD on Delta_q_ctl -> coefficients A(t), modes phi(x,y)
(rank sensitivity: r=6,8,10,12,16)
|
v
Choose observable Y:
- Force-OID: Y = total force [Fx, Fy]
- Signature-OID: Y = delayed sensor error e_s(t + tau_c)
- Suppression-OID (steady only): Y = RMS fluctuation
|
v
Cross-covariance SVD: C_AY = (1/N) A^T Y = U Sigma V^T
|
v
OID coordinates: z(t) = A(t) @ U
OID modes: psi_k = sum_j U_{jk} * phi_j
```
### 1.5 Scene Setup
| Scene | Inflow | Uncontrolled | Controlled | SI | Action bias |
|-------|--------|-------------|------------|----|-------------|
| Steady cloak | Parabolic (uniform) | Pinball natural shedding | Rear cylinders at constant +-5.1U0 | 800 | [0, -5.1, 5.1] |
| Karman cloak | Upstream vortex street | Pinball disrupts street | PPO periodic rotation (d1a3o12_re100) | 800 | [0, -4, 4] |
| Illusion 0.75L | Parabolic | Pinball natural shedding | PPO (d1a3o14_075L_2U_400S) | 400 | [0, -2, 2] |
| Illusion 1.0L | Parabolic | Pinball natural shedding | PPO (d1a3o14_1L_2U_600S) | 600 | [0, -2, 2] |
| Illusion 1.5L | Parabolic | Pinball natural shedding | PPO (d1a3o14_15L_2U) | 800 | [0, -2, 2] |
System: 2D channel flow (1280x512 grid, 3 rotating cylinders, Re=100 code = Re_D=50 physical).
All models: PPO with Sin activation, SB3, 64x64 hidden layers.
---
## 2. Core Result: Force-vs-Signature Systematic Separation
### 2.1 The Monotonic Trend
**Figure 1** (the flagship figure) shows the cosine similarity between force-OID mode 1 and signature-OID mode 1 across all five scenes:
![Figure 1](src/OID_analysis/data/derived/figures/fig1_force_sig_overlap.png)
*File: `src/OID_analysis/data/derived/figures/fig1_force_sig_overlap.png`*
**Panel (a)** shows the signed overlap. A cosine similarity of +1 means the two modes point in identical directions; 0 means orthogonal; -1 means opposite directions.
**Panel (b)** shows the absolute overlap with three interpretation zones color-coded: green (same channel, |overlap| > 0.7), orange (partial separation, 0.3-0.7), red (orthogonal/separated, < 0.3). The gray arrow highlights the monotonic trend.
The trend is remarkably clean:
| Scene | Signed overlap | Separation level |
|-------|---------------|-----------------|
| Steady cloak | **+0.763** | Same channel |
| Karman cloak | **-0.034** | Nearly orthogonal |
| Illusion 0.75L | **-0.082** | Near-orthogonal |
| Illusion 1.0L | **-0.495** | Moderate separation |
| Illusion 1.5L | **-0.932** | Strongly opposite |
**Physical interpretation**: The DRL controller does not engage the same flow structures for all tasks:
- **Steady cloak**: The goal is to suppress natural shedding. Suppressing shedding IS suppressing force, so both objectives engage the same correction structures.
- **Karman cloak**: The goal is to let the incoming vortex street pass through undisturbed. The correction structures that preserve the street are orthogonal to those that would maximally alter the force. The controller must "stay out of the way" of natural force-generating modes.
- **Illusion**: The goal is to generate a target shedding pattern different from natural pinball shedding. Force-OID finds structures that modify the natural force, while signature-OID finds structures that generate the target frequency. These are increasingly different -- and eventually opposite -- as the target deviates further from the natural scale.
This monotonic trend from +0.763 through -0.034 to -0.932 is the most compelling evidence that **force-relevant and signature-relevant correction structures are not the same, and their divergence quantifies task difficulty**.
---
## 3. Robustness of the Core Result
### 3.1 POD Rank Sensitivity
**Figure 2** shows how the force-sig overlap changes when the POD truncation rank varies from 6 to 16:
![Figure 2](src/OID_analysis/data/derived/figures/fig2_rank_sensitivity.png)
*File: `src/OID_analysis/data/derived/figures/fig2_rank_sensitivity.png`*
Each subplot is one scene. The y-axis is force-sig overlap. Stability is measured by the standard deviation across ranks.
| Scene | std | Stability | Verdict |
|-------|-----|-----------|---------|
| Steady cloak | 0.10 | Moderate | Sign consistent, magnitude varies |
| **Karman cloak** | **0.07** | **Stable** | **Always near zero** |
| Illusion 0.75L | 0.26 | **Unstable** | **Needs more data** |
| **Illusion 1.0L** | **0.03** | **Stable** | **Monotonic trend confirmed** |
| **Illusion 1.5L** | **0.02** | **Stable** | **Strongly separated across all ranks** |
Three of five scenes are very stable. The exception (0.75L, std=0.26) is flagged for future investigation with longer time series.
### 3.2 Karman tau_c Sensitivity
For Karman cloak, the signature observable requires a convective delay tau_c (the time for flow structures to travel from pinball to downstream sensors). If tau_c is wrong, the signature-OID could be misaligned.
**Figure 4** sweeps tau_c from 0 to 60 steps (the shedding period is approximately 30 steps):
![Figure 4](src/OID_analysis/data/derived/figures/fig4_tauc_sensitivity.png)
*File: `src/OID_analysis/data/derived/figures/fig4_tauc_sensitivity.png`*
**Top panel**: Force-sig overlap stays between 0.11 and 0.31 across ALL tau_c values. The overlap is always near the orthogonal threshold. **The Karman force-sig separation is not an artifact of a bad delay choice.**
**Bottom panel**: Signature-OID R2 stays between 0.26-0.33 across all delays. Force-OID R2 is constant at 0.36 (since force has no delay). The signature prediction is modest but stable.
---
## 4. OID vs POD: Quantitative Advantage
### 4.1 Prediction Performance
**Figure 3** compares OID and POD for both force prediction and signature prediction, using m=2 coordinates:
![Figure 3](src/OID_analysis/data/derived/figures/fig3_oid_vs_pod_r2.png)
*File: `src/OID_analysis/data/derived/figures/fig3_oid_vs_pod_r2.png`*
**Panel (a)**: Force prediction. OID (blue bars) strongly outperforms POD (red bars) in every scene. POD gives negative R2 for illusion 0.75L and 1.0L (meaning it is worse than predicting the mean), while OID gives positive R2.
**Panel (b)**: Signature prediction. Sig-OID (green) outperforms POD (red) in every scene. The strongest effect is at 0.75L (OID R2=0.661 vs POD R2=-0.034).
Master comparison table:
| Scene | Task | OID R2 (m=2) | POD R2 (m=2) | OID wins? |
|-------|------|:-----------:|:-----------:|:---------:|
| Karman | Force | **0.750** | 0.418 | YES |
| Illusion 0.75L | Force | **0.435** | -2.426 | YES |
| Illusion 0.75L | Signature | **0.661** | -0.034 | YES |
| Illusion 1.0L | Force | **0.671** | -0.237 | YES |
| Illusion 1.0L | Signature | **0.586** | -0.160 | YES |
| Illusion 1.5L | Force | **0.640** | 0.264 | YES |
| Illusion 1.5L | Signature | **0.315** | 0.060 | YES |
### 4.2 Correction-Field Dimensionality
**Figure 5** confirms that correction fields are inherently low-dimensional:
![Figure 5](src/OID_analysis/data/derived/figures/fig5_pod_energy.png)
*File: `src/OID_analysis/data/derived/figures/fig5_pod_energy.png`*
All scenes capture 97.9-99.9% of correction-field fluctuation energy in just 5 POD modes. This justifies the "r=10" default truncation (safety margin) and confirms that the controller operates in a very low-dimensional correction space.
---
## 5. Steady Cloak: Suppression Metrics
**Figure 6** presents the physically meaningful metrics for steady cloak (replacing the inappropriate time-series R2):
![Figure 6](src/OID_analysis/data/derived/figures/fig6_steady_metrics.png)
*File: `src/OID_analysis/data/derived/figures/fig6_steady_metrics.png`*
| Metric | Value | Interpretation |
|--------|-------|---------------|
| Full-field RMS reduction | **99.43%** | Nearly complete fluctuation suppression |
| Recirculation area collapse | **38.55%** | The mean wake bubble shrinks significantly |
| Recirculation length change | **3.24%** | The bubble length barely changes |
| Fy (lift) RMS reduction | **83.29%** | Lift fluctuations strongly suppressed |
The large area collapse with minimal length change is interesting: the controlled wake becomes **narrower** but not **shorter**. This suggests the control primarily suppresses lateral (y-direction) fluctuations rather than shortening the streamwise extent of the recirculation zone.
---
## 6. OID and the Control Law
### 6.1 White-Box Chain
**Figure 7** answers: do OID coordinates capture the full control law?
![Figure 7](src/OID_analysis/data/derived/figures/fig7_whitebox_summary.png)
*File: `src/OID_analysis/data/derived/figures/fig7_whitebox_summary.png`*
| Model | Action R2 | Meaning |
|-------|:---------:|---------|
| obs -> act | **0.956** | PPO baseline: raw sensors predict actions |
| OID coord -> act | **0.225** | Force-OID coordinates capture 22.5% of action variance |
| OID+force -> act | **0.233** | Adding force doesn't help |
This is NOT a failure. OID is designed to find structures relevant to **observables** (force, signature), not to **actions**. Force-OID coordinates are physics-interpretable coordinates (what correction structures affect force), not control-state coordinates (what the controller internally uses). An action-related coordinate would require a separate causal-PCD analysis using the action itself as the observable.
---
## 7. Open Items and Caveats
1. **Illusion 0.75L rank sensitivity** -- The force-sig overlap varies with POD rank (std=0.26). This needs investigation with a longer time series or phase-resampled data.
2. **Karman future-signal R2** -- Signature-OID gives R2 near zero for Karman. This is under investigation. Possible causes: (a) the delayed error observable has artificially low variance due to target alignment; (b) tau_c needs scene-specific estimation using cross-correlation.
3. **No mode-to-field mapping** -- OID spatial modes (psi_k) are computed but not yet visualized as flow field plots. This would answer: "where in the physical domain does the force-sig separation live?" (near-body vs downstream). CCD zone analysis already suggests the answer is zone-dependent.
4. **PCD (whitened) did not outperform simple OID** -- The more complex whitened cross-correlation did not improve results. The simple cross-covariance SVD is sufficient for the current data quality.
5. **No cross-validation** -- The current R2 values are from 70/30 split on a single rollout. Cross-validation across multiple independent rollouts would strengthen the results.
6. **Data independence** -- All scenes use the same correction-field protocol (Delta-q_ctl = q_ctl - q_blk), ensuring fair cross-scene comparison. The illusion-position q_blk was collected separately from the cloak-position q_blk (geometry is different: front_x 19 vs 30, sensor_x 30 vs 40).
---
## 8. Figures
All figures in `src/OID_analysis/data/derived/figures/`:
| Figure | File | Description |
|--------|------|-------------|
| 1 | `fig1_force_sig_overlap.png` | **Flagship**: Force-OID vs signature-OID overlap across all 5 scenes. Signed and absolute versions with monotonic trend. |
| 2 | `fig2_rank_sensitivity.png` | POD rank sensitivity (r=6,8,10,12,16) of force-sig overlap. 5 subplots, one per scene. |
| 3 | `fig3_oid_vs_pod_r2.png` | OID vs POD prediction R2. Left: force. Right: signature. All 4 periodic scenes. |
| 4 | `fig4_tauc_sensitivity.png` | Karman tau_c sensitivity. Top: overlap vs delay. Bottom: R2 vs delay. 10 delays tested. |
| 5 | `fig5_pod_energy.png` | Correction-field POD energy capture (5 modes, cumulative %). |
| 6 | `fig6_steady_metrics.png` | Steady cloak suppression metrics: RMS reduction, recirculation collapse, force reduction. |
| 7 | `fig7_whitebox_summary.png` | White-box chain: obs->act vs OID->act vs OID+force->act. Horizontal bar chart. |
---
## 9. References
- Sch12: Schlegel et al. "On least-order flow representations for aerodynamics and aeroacoustics." JFM 2012.
- Lyu23: Lyu et al. "Canonical correlation decomposition for data-driven analysis."
- Kan17b: Kantsios et al. "Body-connected near wake as primary force determinant."
- Che19, Che21b: Chen-Liu line on rotation first rewriting near-body source terms.
- Tad10: Tadmor et al. "Low-dimensional state for flow control."
Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

+28
View File
@@ -0,0 +1,28 @@
# `src/` index
This directory contains the active analysis and rendering packages for DynamisLab. Read the package authority documents before using any result; `src/analysis_knowledge.md` records cross-project contracts, while `src/analysis_notes.md` records current gates and writing status.
| Package | Current role | First documents |
|---|---|---|
| [`drl_pinball`](drl_pinball/) | Active V5 training/evaluation plus bounded Legacy reproduction and writing evidence | [`README`](drl_pinball/README.md), [`CLAIMS`](drl_pinball/CLAIMS.md), [`RESULTS`](drl_pinball/RESULTS.md) |
| [`SR_analysis`](SR_analysis/) | Bounded Legacy Kármán symbolic-regression evidence; Illusion SR is historical/negative | [`README`](SR_analysis/README.md), [`CLAIMS`](SR_analysis/CLAIMS.md), [`results/INDEX`](SR_analysis/results/INDEX.md) |
| [`CCD_analysis`](CCD_analysis/) | Closed, descriptive corrected Kármán CCD/POD comparison | [`README`](CCD_analysis/README.md), [`RESULTS_INDEX`](CCD_analysis/RESULTS_INDEX.md), [`CLAIMS`](CCD_analysis/CLAIMS.md) |
| [`OID_analysis`](OID_analysis/) | Claim-free CPU method core; old two-scene study is archived | [`README`](OID_analysis/README.md), [`SCIENTIFIC_RESET`](OID_analysis/SCIENTIFIC_RESET.md) |
| [`steady_pinball_theory`](steady_pinball_theory/) | Active NS-first steady-flow investigation with bounded evidence | [`README`](steady_pinball_theory/README.md), [`RESULTS`](steady_pinball_theory/RESULTS.md) |
| [`pv_plot`](pv_plot/) | Small ParaView/FFmpeg rendering utility | [`README`](pv_plot/README.md) |
| [`archive`](archive/) | Superseded repository-level reproduction material | package README/index files only; non-authoritative by default |
## Solver boundary
`CelerisLab/` is the modern GPU LBM submodule and is intentionally outside this repository closeout. `LegacyCelerisLab/` is tracked legacy solver source used by SR and historical reproduction. V5 and Legacy artifacts, normalization, action ordering, timing, and metrics must remain separate unless a document explicitly defines a migration comparison.
## Evidence and storage
- Compact manifests, tests, authority documents, and selected publication figures belong in Git.
- Large arrays, CFD outputs, generated plot trees, and external Optane mappings are local/external evidence and should be referenced by manifests or relocation notes rather than bulk-committed.
- `analysis_knowledge.md` is the durable cross-package contract ledger; package `README`, claims/results ledgers, and manifests are the numerical authorities.
- Working Memory is a retrieval aid, not a substitute for repository artifacts.
## Reading rule
For any claim, identify package, solver, case, role, realization/seed, time window, metric definition, artifact path or hash, and evidence status. If those fields are missing, treat the statement as navigation or historical context rather than authoritative science.
+146 -292
View File
@@ -1,357 +1,211 @@
# 主分析知识库 # 跨项目科学与认识论知识库
## 文档作用 > 状态日期:2026-08-09。本文只保存可跨项目复用的科学合同、证据边界、工作假说、失败经验与开放问题;不安排任务,不以 `.cursor` 计划或 Memory 作为科学证据。数值与状态以各当前包的权威文档、可执行合同、不可变产物及清单为准。
这份文档只负责保存当前主分析线里已经形成的**长期判断、边界条件、方法论经验和不该忘的坑**。 ## 1. 如何阅读本文
它不安排执行顺序,也不写“下一步做什么”。凡是优先级、阶段、第一轮交付物,统一写在 `analysis_notes` 本文统一使用五类状态:
这里重点保留: - **已确立合同(established contract**:定义、坐标、单位、角色、比较量、对齐方式或证据准入规则;它规定“可以比较什么”,不等同于物理机制已证明。
- **有界支持观察(bounded supported observation**:在明确场景、窗口、分辨率、比较器和实现下由当前证据支持;不得外推为普适规律、因果或稳定性。
- **工作假说(working hypothesis**:与现有观察及文献相容、可组织后续检验,但尚未由本项目建立。
- **撤回/历史(withdrawn/historical**:保留以防重复犯错或丢失出处,但不得作为当前正面结论。
- **开放问题(open question**:现有证据不能回答,且不能用解释性语言填补。
- 这一轮调研后已经比较稳的物理判断 证据优先级通常为:源代码/冻结合同与机器可检验清单 → 不可变原始或派生产物 → 当前结果与 claim ledger → 读者图表和综述。后出的严格证据可以下调旧结论,而无需改写旧产物。计划、聊天记录和 Memory 只能帮助定位材料,不能升级科学主张。
- 哪些文献对当前项目真的有用,分别用在什么层级
- 哪些解释现在可以说,哪些不要说过头
- 当前网格分辨率下,哪些分析是可信的,哪些不可信
## 一、当前最重要的认识变化 ## 2. 已确立合同
这一轮最大的变化,不是又多知道了几篇文献,而是**分析层级变了**。 ### 2.1 雷诺数、尺度与实现世代
之前最容易滑向两个方向: - **必须同时写清 `Re_code` 与 `Re_D`。** Legacy 命名中的长度基准为 `2D`,因此在现有 Legacy SR/Kármán合同中
\[
Re_D = Re_{code}/2.
\]
例如 `karman_re100` 对应单圆柱直径定义的 `Re_D=50`,不能简称“Re=100”后与现代 `Re_D=50` 数据混合。
- **Legacy 与 modern/V5 是两条证据链。** 即使名义网格、几何或 `U_0` 相同,壁面离散、动作单位、平滑、力/传感器累计与归一化、对象顺序、边界条件和 checkpoint 行为也可能不同。名义换算不构成数值奇偶性证明。
- 坐标、数组存储、绘图方向、圆柱顺序和动作符号必须由当前源码/合同及壁面点速度 oracle 绑定。现代 Celeris 连续符号约定为
\[
(U_w,V_w)=(-\Omega r_y,\Omega r_x).
\]
“顺/逆时针”“上/下圆柱”标签不能越过显式对象 ID、中心坐标与壁面速度检查。
- 跨包引用只能作为**情境三角验证**;不同 plant、边界条件、估计量或窗口的数值不能伪装成重复试验。
- 要么把机制写成 `obs -> act -> force -> signature` ### 2.2 三场分解与均值—动态分离
- 要么试图直接搬壁面涡量理论,做单圆柱边界层级别的解释
现在更稳的理解是 一般动态/差分分析先定义角色
- `q_in`:无 pinball 的入射/目标参考场;
- `q_blk`:固定 pinball 的被动阻挡场;
- `q_ctl`:受控 pinball 场。
并定义
\[ \[
\text{obs} \rightarrow \text{act} \rightarrow \text{near-body correction} \rightarrow \text{wake structure} \rightarrow \text{force / future signature} \Delta q_{blk}=q_{blk}-q_{in},\qquad
\Delta q_{ctl}=q_{ctl}-q_{blk},\qquad
\Delta q_{tot}=q_{ctl}-q_{in}=\Delta q_{blk}+\Delta q_{ctl}.
\] \]
也就是说: 解释权随定义冻结:`Δq_blk` 是几何/边界引入的被动差异,`Δq_ctl` 是相对于固定基线的控制附加差异,`Δq_tot` 是最终残差。三者不可互换;“控制抵消阻挡”至少需要在同一掩膜、单位、时间/相位和估计量上比较 `Δq_ctl``-Δq_blk`
- **force 依然重要,但更像近体区修正过程的低维投影,而不是唯一第一性机制** [Zhu15]。 均值和动态必须分开:
- **Chen Tao 线依然重要,但它提供的主要是因果方向,不是当前网格下可直接照搬的壁面分析模板** [Che19, Che21b, Ter21]。
- **当前最可信、也最值得主打的层级,是 pinball 整体尺度的 correction field**,而不是单圆柱 wall-scale 细节。
## 二、Chen Tao 这条线对本项目到底有什么用
### 1. 有用的不是“旋转会改变表面量”这句常识
真正有用的是下面这条因果链:
\[ \[
\text{rotation} \rightarrow \text{surface condition change} \rightarrow \text{near-body vorticity organization} \rightarrow \text{shear-layer bias} \rightarrow \text{wake / force / signature} q=\overline q+q',\qquad
\Delta q=\Delta\overline q+\Delta q'.
\] \]
这条线的价值在于,它逼着解释停留在“近体区结构如何被改掉”这一层,而不是直接从动作跳到力,或者从动作跳到远场 wake 平均性能改善不能自动解释相位动态;相位共变也不能自动解释均值改善。常值控制贡献、反馈增量和波动结构应使用不同估计量并验证加法闭合
### 2. 最适合当前项目的 Chen–Liu 文献分工 **steady 例外:** 当前 steady 主合同直接以 `q_ctl` 对匹配的无体 `q_in` 做全剖面性能评估;`q_blk` 是非排名参考。因此 steady 的主指标不是 `Δq_ctl=q_ctl-q_blk`,也不能因三场记号而把参考再减一次。历史半解析 scorer 的 double subtraction 正是此类合同错误。
| 论文 | 在当前项目里的角色 | ### 2.3 对齐、比较与声明
|---|---|
| [Che19] | 最重要的桥梁。告诉我们表面压力、skin friction、boundary enstrophy flux 是耦合的,因此近体区源项不是空话。|
| [Che21b] | 提醒我们这些源项不是静态量,而有时空演化,并且和 separation / attachment 及近壁相干结构相关。|
| [Che24d] | 把 boundary vorticity flux 继续拆成 orbital rotation 与 spin,适合用来升级机理语言,但不是第一轮主证据。|
| [Che24e] | 提醒 Q-criterion 类量不要解释过满,边界上的 strain / enstrophy / Q 源项是不同层次。|
| [Che26] | 这是这一支到 JFM 的理论总论,更像上层统一框架,而不是 rotating-cylinder wake 的直接分析手册。|
### 3. 当前项目里最该保留的 Chen 线结论 - 时序、状态、动作、力、传感器和场必须按实际采样时钟与语义对齐;相邻步错位可产生漂亮但错误的公式或相关结构。
- 周期场需绑定周期选择、相位原点、保留边界、bin 数和角色间配对规则。DTW 的循环位移是算法参数,不是物理响应延迟。
- 任何数字旁应能恢复:场景、plant、`Re_code/Re_D`、窗口、掩膜/ROI、单位、比较器、样本/realization 数、状态标签和产物身份。
- 预测/重构成功不等于重要性;相关不等于因果;空间先后不等于时间因果;单次 deterministic realization 不提供独立实现不确定度。
- 旋转不是直接“指定一个目标 wake”,而是先改写近体区源项和剪切层出生条件。 ## 3. 有界支持观察
- 受力不是与涡量竞争的替代机制,而更像近体区涡量组织变化后的整体积分响应。
- 若网格不支持壁面精细诊断,仍然可以保留“近体区源项先变、远场 observable 后变”这条因果顺序。
## 三、哪些部分现在不要硬做 ### 3.1 SR:当前只支持 Kármán/cloaking 正面结果
当前 CFD 中单圆柱只占十多格,这是一个非常硬的边界条件。由此带来几个必须长期保留的判断: - 当前 SR 科学范围是 **Legacy Kármán/cloaking only**;steady 只作幅值与结构显著性的情境校准。
- 冻结 mapped-shared Kármán 稀疏律在命名的 Legacy `Re_code=50,100,200,400`、有限 200/400-step 部署中保持有限并取得已记录 DTW;这支持“可复现的稀疏闭环降阶控制器”,不支持全局符号最优、渐近稳定、普适 Reynolds 定律或统计鲁棒性。
- 在已测试删除中,后圆柱持久反向旋转常数项最显著,后部升力反馈次之,前部反馈较弱。这里的“主导”只指父公式、指定窗口和已测试删除;不等于唯一充分、普遍必要或流动物理因果机制。
- SR 是 `obs → act` 的白箱接口:它说明所选闭环公式依赖哪些可观测组合,不能独立完成 `act → flow → force/signature` 的机制证明。
| 不应硬做的分析 | 原因 | ### 3.2 Illusion SR:负面/历史证据
|---|---|
| 单圆柱边界层厚度与细节 | 分辨率不够 |
| 单圆柱精确分离点、附着点 | 数值可信度不足 |
| 壁面涡量通量逐点定量值 | 网格不足以支撑 |
| 以 wall-scale 量做主机制证据 | 容易把分辨率不支持的内容写过满 |
因此,对当前项目最稳的表述是: - 旧的有限窗口 Illusion 公式与目标相似度保留为历史事实,但不是当前正面控制结论。
- 所选静态公式虽在可用特征池中可访问 target/error,却没有显式选入它们;这不证明 PPO 不使用目标信息,只证明该静态 SR 公式没有显式表达它。
- 标准化长窗口 Legacy `illusion_1L` 中,SR 与 physical zero 的 native/normalized DTW 实质相同,均值场和 phase-8 误差略差于 zero,动作趋近零。因此撤回 target tracking、相对 zero 的有效性、跨尺寸泛化、逐项必要性及机制主张。
- Illusion 运行能力可为兼容性保留;“代码能跑”与“科学主张成立”是不同状态。
- 可以引用 Chen–Liu 线来支持“壁面/近体区过程在前”; ### 3.3 corrected CCDROI 均值与 rank-3 描述共变
- 但自己的主证据必须落在 **pinball-scale near-body correction** 上。
## 四、为什么三场分解是当前最关键的方法论 - 当前 corrected Kármán 权威使用 inclusive wake ROI `34<=x/D<=54, |y/D|<=5` 和四角色 solver-fluid mask 精确交集,共 80,200 点;速度已无量纲化,不得再次除以 `U0`
- ROI mean target error 为:zero `0.4694352273`、constant mean `0.1110140739`、DRL `0.0857787860`。zero→constant 与 constant→DRL 的改善严格加法闭合;这支持**均值控制贡献很大、反馈再提供较小增量**的观察。它不是 steady 后部动作机制的证明。
- corrected CCD 使用 19 个 DRL 周期 × 10 phase bins`N=190, Q=1, M=160400`,数值 rank 3。每个 DRL 周期/bin 相对一个 19-cycle constant ensemble phase template 独立居中并作差,角色周期不配对;无 POD、whitening 或 standardization。
- 8-bin、12-bin 和 half-bin-10 的独立 retained-boundary 检查支持稳定的 rank-3 **子空间**;最不利 projector cosine 为 `0.9947903592`,最大相对奇异值变化 `0.0766020533`。单个 mode/action vector 只是该稳定子空间的一组 SVD 基表示。
- 允许的最强表述是:**phase-coherent DRL-minus-constant-template 的 rank-3 描述性共变**。不支持 paired counterfactual、因果、机制、响应时间、独立实现不确定度、解释方差/场能量、CCD 优越性或相对 POD 优越性。
这是这一轮最重要的方法收获。 ### 3.4 OID:无主张方法核心
如果直接看控制场,很容易把三种影响混在一起: - 当前 OID 包是 claim-free、CPU-only 方法核心:加权 snapshot POD、Schlegel LR/LE 线性映射与 generated-range 处理、符号不变的 mode/subspace 指标、exact/delayed pairing 和原子产物验证。
- 当前没有 active scientific result、scene runner、GPU/plotting path 或 LR/LE action 结果。
- 2026-07 两场景研究是 conditional archivesensor 高 R² 部分来自 state 域内局部速度的 self-observationforce 未过 gateaction delayed association 未隔离策略反馈。因此不存在可比较的“sensor/force/action importance”排名。
- `q_ctl-q_blk` 在 OID 语境中仍只是 paired closed-loop branch difference;预测或重构不能升级为重要性、机制、因果、控制器必要性、执行器 authority 或 controllability。
- 入射来流本身的结构 ### 3.5 steady:直接剖面性能成立,整体状态为 BOUNDED
- pinball 作为障碍物的阻挡作用
- 旋转控制额外施加的修正
因此必须至少分成三类场: - 当前 canonical steady 合同是 uniform-inlet/free-slip、`Re_D=50`、圆柱顺序 `(front,rear_y_plus,rear_y_minus)`,接受动作 `[0,+Omega,-Omega]``s=Omega R/U_inf>0`。按冻结壁面速度映射,这是 **base-bleed/gap-jet family**,不是 boat-tail。
- 主排名指标是在 `x/D=10` 整个横截面上比较 `q_ctl``q_in` 的两分量 `E_inf_vector`;显式积分 `L2` 为次要诊断,其他站位为诊断,`q_blk` 不排名。
- 在 `s={3.45,3.55,3.65}``E_inf_vector={0.0232525,0.0231671,0.0312490}`。D20 与 D30 在 `s=3.55``E_inf` 相对差约 `1.33%`;这支持当前离散设置下的稳态低残差性能与局部分辨率一致性。
- 整体发布状态是 **BOUNDED**:未建立唯一最优、全局吸引、渐近/非线性/全局稳定、跨边界条件转移或 NS 闭合机制。D10 预期欠分辨;outlet/final-window/IC 检验缺失。
- endpoint 数据支持“壁面方向—gap/outer shear—recirculation/force—downstream deficit”的有序空间共存/关联,但不是时间因果;旧 energy ledger、single switch 和 return norm 均不足以完成机制、分支切换或稳定性证明。
- 入射参考场 \(q_{in}\) ## 4. 工作假说
- 固定 pinball 场 \(q_{blk}\)
- 控制 pinball 场 \(q_{ctl}\)
然后定义两个差分场: ### 4.1 跨项目主链只能作为可检验假说
当前可用的组织框架是:
\[ \[
\Delta q_{blk} = q_{blk} - q_{in} \text{observation}\rightarrow\text{action}\rightarrow
\text{near-body correction}\rightarrow
\text{body-connected wake structures}\rightarrow
\text{force structures}\rightarrow
\text{future-signature structures}.
\] \]
\[ 这条链**不是本项目已经建立的机制**。它的用途是区分中介对象和设计可证伪检验:
\Delta q_{ctl} = q_{ctl} - q_{blk}
\]
这里最关键的不是公式本身,而是它们对应的解释权 - SR 可约束 `observation → action`,但不证明后续物理链
- difference fields 可描述 `action` 后的附加场变化,但闭环分支差异不是 intervention。
- 文献支持“旋转壁面先改变近体涡量生成/剪切层出生条件”和“body-connected wake 与瞬时力相关”的一般物理框架;它不证明本项目每个箭头。
- CCD/OID 可以寻找与 observable 共变或可重构的结构,但需要独立对齐、干预和 held-out 证据才能谈方向或 authority。
- \(\Delta q_{blk}\) 代表 **几何阻挡带来的被动破坏** ### 4.2 force-relevant 与 signature-relevant 结构应先验分开
- \(\Delta q_{ctl}\) 代表 **旋转控制额外施加的主动修正**
一旦这两个量分开,很多原本混乱的问题会立刻清楚: - **force structures** 指对瞬时/相位积分力投影强的近体或 body-connected 结构;其重要性取决于位置、符号及与 body-induced velocity 的耦合,而非仅总涡量或能量。
- **signature structures** 指对下游未来传感器、ROI 或目标相似度有预测/重构关系的结构;它们可能经对流和非线性演化后才形成。
- 两者可以重叠,但不得因同一控制器同时改善力与 signature 就假定为同一子空间。force-OID 与 signature-OID 的差异首先是待解释结果,不是算法失败;相同也仍需排除共享均值、相位和 self-observation。
- cloak 不是“什么都不产生”,而是主动修正去抵消被动破坏; ### 4.3 当前更可信的尺度是假设性的 pinball-scale correction
- illusion 不是“pinball 变成了目标物体”,而是在自身基线 wake 上叠加 target-like correction。
## 新增补充:wake-to-force 这条线为什么重要 现有网格对整体场、ROI、横截面和 pinball-scale wake 可有用,但通常不足以支持单圆柱 wall-scale 的精确边界层厚度、分离/再附点或逐点 boundary-vorticity-flux 定量。因此“低维调制 pinball-scale correction structures”是合理工作假说;不能把它写成已证实机制。
这一轮新增的第二条有效文献线,不是 another force formula,而是 **wake-to-force**。它真正补上的,是 `near-body correction -> force -> signature` 这一段的物理层次。[Noc99, Una97, Kan17b, Geh23, Gom16] ## 5. 撤回与历史边界
这条线最值得保留的结论不是“用 wake 可以算出力”,而是以下三条: - 撤回把 Illusion SR 写成 target-aware tracking、优于 physical zero、跨尺寸普适或机制解释。
- 撤回把 CCD rank-3 共变写成响应模态、因果通道、解释能量、独立不确定度或方法优越性。
- 撤回从 OID 的高 sensor R²、force/action 预测或重构推导 observable importance、必要性或 authority。
- steady 的 prescribed-circulation blockage cancellation 因符号矛盾而 **FAIL**:理论所需 `g_opt=+6.147944`,接受 CFD 的描述拟合为 `g=-12.200554`。数学上的 rear-opposite inviscid dipole 性质仍成立,失败的是其作为当前 CFD 机制的识别。
- steady composite semi-analytic 的 held-out PASS 已撤回:scorer double-subtracted reference`q_VI` 不随 `omega/branch``q_wake` 未激活,speed/direction gates 也非独立预测。该产物只能说明一次失败拟合路径。
- `[0,-Omega,+Omega]` 不是当前 accepted cloak branch;不同幅值 reverse endpoints 不能伪装成等幅因果对照。
- 历史 phase-domain CCD、旧 OID 两场景结果、旧 Illusion 文章包、failed gates 和 negative controls 应保留,但不得越过当前包的 archive boundary 回升为 authority。
### 1. 力与 wake 的关系分层成立 ## 6. 分辨率与文献的认识论边界
较早的 control-volume / momentum 公式说明,只要控制体选得合理,近尾迹速度场本身就足以恢复瞬时力的主变化。[Una97, Noc99] 这至少证明: ### 6.1 分辨率决定可声明层级
- force 不是脱离流场的黑箱量; 可以较稳地讨论:共同掩膜上的均值/相位场、ROI 或整剖面误差、pinball-scale correction、近尾迹宽度/强度、积分力及经验证的低维子空间稳定性。
- 近尾迹与力之间确实存在可重复、可计算的映射。
### 2. 真正最该关注的是 body-connected wake structure 通常不能据当前粗网格主张:逐点壁面涡量通量、精确分离点、单圆柱边界层细节、闭合压力/黏性动量或能量平衡。数值收敛只支持所测数值量,不会自动建立物理机制。
minimum-domain impulse 理论的关键判断是:对瞬时力真正直接起作用的,不必是整个成熟 far wake,而是**仍与物体动态相连的 vortical zone**;已经 detached 的紧致尾涡,其净力贡献可以视为零。[Kan17b] ### 6.2 文献只能提供框架与可比边界
这对当前 pinball 的帮助极大,因为它把“目标尾迹要几个 \(D\) 才形成”和“力的主决定层更靠前”区分开了。更稳的口径应当是: - ChenLiu/Tao 一线可支持 boundary vorticity/enstrophy/pressure/skin-friction 的一般耦合与“壁面/近体过程在前”的物理方向;不能替代本地 wall-resolved 证据。
- control-volume、impulse 和 vortex-force 文献可支持 wake 与 force 的一般映射及 body-connected vortical zone 的概念;不能证明本项目识别出的 mode 就是 causal force structure。
- Schlegel OID 与 Lyu CCD/PCD 提供 observable-conditioned 降阶与时延结构方法;方法定义不等于本地结果有效,更不等于因果。
- rotating-cylinder 文献只可在核对 Re、几何、约束、坐标与壁面方向后做定性 framing。当前 accepted steady branch 与 base-bleed/gap-jet wall sense 相容;高 Re 阈值、drag optimum 和 URANS manifold 不可转移到 `Re_D=50`
- signature 的形成需要发展距离; 原则:**文献可以提高假说的物理可理解性,不能提高本地证据的等级。**
- force-relevant mechanism 更集中在 near-body / body-connected 区域。
### 3. 同样的涡量,不同位置,对 force 的投影不同 ## 7. 跨项目耐久经验
vortex force decomposition 进一步说明,力不是简单由“总涡量大小”决定,而取决于涡结构的位置、与 body-induced velocity 的耦合方式,以及它是 body-generated、shed 还是 external。[Geh23] 1. **合同先于分析。** 冻结对象顺序、坐标、动作单位/符号、`Re_code/Re_D`、plant、边界、时钟、归一化、目标和比较器;标签与记忆不能覆盖源码 oracle。
2. **对齐是科学问题。** state→next-action、phase origin、retained boundary、角色配对和 snapshot 来源必须可审计;错一拍仍可能得到高 R² 或平滑 mode。
3. **均值与动态分离。** 先验证 mean increment、phase decomposition 和 benefit additivity,再分别解释常值贡献与反馈波动。
4. **association != causality。** correlation、OID/CCD、DTW、ordered spatial coexistence、公式变量选择和 deletion 都只在各自合同内回答有限问题。
5. **闭环接受不能由离线拟合替代。** offline R²/重构可筛结构,控制器仍需 finite、same-protocol baseline、closed-loop 和失败保留。
6. **no-clobber 是证据纪律。** 新结果写新 ID,staging 后原子发布;哈希、父产物和失败状态不可静默覆盖或“清理”。失败、rejected、partial 与 BOUNDED 都是证据。
7. **不要修饰失败。** 不通过缩短 warm-up、降低 crossing gate、换归一化、改比较器或只对 target 不对 zero 来挽救结论。
8. **Legacy 共享编译必须串行。** 多 GPU 不隔离共享生成的 PTX/config/`macros.h`;并行初始化可污染证据。采集应串行启动并保留角色级 provenance。
9. **同 rollout 采传感器与场。** phase 选择后重新初始化/补采会改变涡相位,破坏对齐。
10. **现代/Legacy 分证据链。** 只有显式 parity 测试通过后才能作受限映射;不能把现代 V5 steady/CCD 结果直接并入 Legacy SR 的接受链。
对 pinball,最可迁移的不是照抄公式,而是保留这个判断: ## 8. 方法分工
- 同一强度的局部涡量结构,若位置和耦合方式不同,对总 force 的贡献也会不同; - **SR**:解释冻结闭环公式的 `obs → act` 接口;当前正面范围仅 Kármán,steady 为情境校准,Illusion 为历史负面。
- 因此后续完全可以谈 **force-relevant structures**,而不是只谈 energetic structures - **CCD**:当前只报告 corrected Kármán ROI mean 与 rank-3 phase-coherent descriptive co-variation;不承担因果或机制
- **OID**:当前为 claim-free 方法核心;未来可严格区分 force/signature observable,但当前无 active scientific result。
- **steady**:回答接受 rear-only 恒定动作在独立 canonical steady plant 上是否形成低残差剖面;当前性能观察成立,机制与稳定性为 BOUNDED/未建立。
## 新增补充:这条线如何改写当前主链 四条线可相互约束语言和提出假说,但不能互相代替证据。
wake-to-force 与 Chen 线结合后,当前最稳的主链不应再写成 ## 9. 开放问题
\[ - Kármán SR 的稀疏律在独立 realizations、更长窗口及更高 `Re_D` 下是否保持有限、有效与同一结构?
\text{obs} \rightarrow \text{act} \rightarrow \text{force} \rightarrow \text{signature} - constant mean 占 Kármán ROI 改善的大部分,是否由后部持久旋转主导?需要 matched intervention,不能由 SR 删除或 steady 对应关系单独回答。
\] - corrected CCD rank-3 子空间与 force-relevant、signature-relevant 或纯共享相位/均值结构分别有何关系?
- 是否存在严格配对或随机化的 intervention 能把 policy response 与 commanded action 的作用分开?
- steady accepted branch 的因果 NS 通道是什么?需要共同控制体闭合、重复 switch/return、有效稳定性指标及独立 held-out 预测。
- free-slip `Re_D=50` 的 steady 性能能否转移到充分发展 `q_in`、静止 no-slip walls 和 rotating no-slip cylinders?当前没有证据。
- wall-resolved 或经网格收敛的诊断是否支持 near-body vorticity/separation 假说?当前分辨率不能预支答案。
- Legacy 与 modern 的动作、壁面速度、力/传感器语义及场统计能否建立可量化 parity?在完成前两条证据链保持分离。
也不应写成过于粗糙的 ## 10. 紧凑权威阅读表
\[ ### 当前包内权威
\text{obs} \rightarrow \text{act} \rightarrow \text{wake}
\]
而应写成: - SR 状态与边界:[SR `CLAIMS.md`](SR_analysis/CLAIMS.md)、[`HANDOFF.md`](SR_analysis/HANDOFF.md)、[`results/README.md`](SR_analysis/results/README.md)、[标准化复现图说明](drl_pinball/data/reproduction_plots_sr/README.md)。
- CCD corrected authority[CCD `README.md`](CCD_analysis/README.md)、[`FINAL_RESULTS.md`](CCD_analysis/FINAL_RESULTS.md)、[`EXECUTION_CHECKPOINT.json`](CCD_analysis/EXECUTION_CHECKPOINT.json)。
- OID reset authority[OID `README.md`](OID_analysis/README.md)、[`SCIENTIFIC_RESET.md`](OID_analysis/SCIENTIFIC_RESET.md)、[`PHYSICS_CONTRACT.md`](OID_analysis/PHYSICS_CONTRACT.md)、[`METHOD.md`](OID_analysis/METHOD.md)。
- steady authority[steady `README.md`](steady_pinball_theory/README.md)、[`RESULTS.md`](steady_pinball_theory/RESULTS.md)、[`DERIVATION.md`](steady_pinball_theory/DERIVATION.md)、[`LITERATURE.md`](steady_pinball_theory/LITERATURE.md)。
\[ ### 文献框架入口
\text{obs} \rightarrow \text{act} \rightarrow \text{near-body correction} \rightarrow \text{body-connected wake structure} \rightarrow \text{force} \rightarrow \text{future signature}
\]
其中: 优先使用各包的 source-to-claim ledger,而不是从本文二手升级主张:steady 的 [`LITERATURE.md`](steady_pinball_theory/LITERATURE.md) 记录 potential/viscous interface、rotating-cylinder 与 wake/stability 文献边界;OID 的 [`METHOD.md`](OID_analysis/METHOD.md) 记录 Schlegel LR/LE 数学;CCD 当前方法边界由 [CCD `README.md`](CCD_analysis/README.md) 给出。历史 Lyu/旧 CCD 材料仅作出处追踪,不是 current result authority。
- Chen 线负责说明为什么 `act` 的第一作用层是近体区源项与涡量组织,而不是远场结果。[Che19, Che21b, Ter21]
- wake-to-force 线负责说明为什么 force 最好理解为 body-connected near-wake organization 的低维投影,而不是与涡量竞争的另一套机制。[Kan17b, Geh23, Gom16]
- OID/CCD 线负责把这条通道压缩成少数结构坐标,并区分 force-relevant 与 signature-relevant structures。[Sch12, Lyu23]
## 五、对 cloak 与 illusion 的当前最稳表述
### cloak
现在最稳的写法是:
- fixed pinball 会在任务相关区域内产生一个 blockage wake
- DRL 旋转产生的 correction field 会尽量抵消这部分 wake;
- 合力接近 0 不是全部机制,而是这种 wake cancellation 的积分表现。
因此,如果分析成立,应看到:
\[
\Delta q_{ctl} \approx -\Delta q_{blk}
\]
至少在任务相关区域里呈现这种趋势。
### illusion
现在最稳的写法是:
- fixed pinball 先生成自身基线 wake
- 控制不是把 wake 全部“消掉”,而是做一个 target-oriented correction
- force matching 之所以有效,是因为它约束了整体节律与积分响应,但真正被操控的是 correction field。
如果分析成立,应看到:
\[
\Delta q_{ctl}
\]
接近“目标物体相对 fixed pinball 的残差结构”。
## 六、force 在当前项目中的正确位置
这是最容易说错的地方之一。
### 现在可以说的
- force 是极重要的 observable。
- force 对 DRL reward 有效,说明它确实和任务结构高度相关。
- force 很可能是近体区修正场的低维、强相关投影,因此特别适合作为控制反馈量。
- 更具体地说,当前最稳的理解不是“force 来自整个远场尾迹”,而是:force 更像 **body-connected near-wake organization** 的积分响应或低维投影。[Kan17b, Geh23, Gom16]
### 现在不要说得太满的
- “控制机制本质上就是 force tracking”
- “只要合力为 0,就自然 cloak”
- “illusion 的本质就是匹配目标力”
更稳的说法是:
- force 是 near-body correction 的一个重要投影;
- 它之所以有用,是因为它和 task-relevant structures 强相关;
- 但真正被操纵的,仍然更像是 correction field 而不是一个单独积分量。
## 七、OID / CCD / PCD 在当前主线中的正确位置
这条线现在不应再被理解成“对原始全流场做更高级模态分解”。
更稳的理解是:
- 原始全流场里混着入射结构、阻挡结构和控制结构;
- 真正需要找的是 **control-induced correction structures**
- 因此 OID / CCD / PCD 最好作用在 \(\Delta q_{ctl}\) 或其低维系数上。
### 当前最有价值的任务
| 方法 | 现在最值得做的事 |
|---|---|
| correction-field POD | 看控制修正主要落在哪几个低维方向上 |
| force-OID | 找最影响 force 的 correction structures |
| signature-OID | 找最影响 future signature 的 correction structures |
| PCD / CCD | 在显式时延下区分 source / descendant correction modes [Lyu23] |
这里需要新增一条长期保留的解释纪律:**force-OID** 与 **signature-OID** 不应先验合并。更稳的工作假设是:
- controller 首先调制一小组 force-relevant near-wake structures
- 这些结构经过若干个 \(D\) 的对流与相互作用后,才演化为 signature-relevant downstream structures。[Kan17b, Sch12, Lyu23]
因此,如果后续真的看到 force-OID 与 signature-OID 差异明显,这首先应被视为潜在机制结果,而不是算法失败。只有在 POD rank、时延、标准化和数据量都排查完后,才适合讨论该差异是否可信。
### 这条线最关键的判断
若少数 correction modes 就能:
- 解释大部分 force 变化
- 预测 future signature 的改善
- 在 cloak 与 illusion 间提供可比较结构
则说明“控制调用的是少数 pinball-scale correction structures”这一主张成立。
## 八、SR / SINDy 的正确角色
这条线现在最容易被高估,也最容易被低估。
### 它不该单独承担的事
- 不应让 `obs -> act` 一条线独自承担全部物理解释。
- 不应把高拟合度自动当成“机制已明”。
### 它现在真正该承担的事
- 作为 `obs -> act` 的白箱接口;
- 给出控制律依赖哪些低维量的证据;
- 最终和 correction field 及 OID/CCD 拼起来,形成闭环解释。
因此最合理的三段拼法是:
\[
\text{SR/SINDy}: \text{obs} \rightarrow \text{act}
\]
\[
\text{difference-field analysis}: \text{act} \rightarrow \Delta q_{ctl}
\]
\[
\text{wake-to-force / Chen}: \Delta q_{ctl} \rightarrow \text{body-connected wake structure} \rightarrow \text{force}
\]
\[
\text{OID/CCD}: \text{force-related structure} \rightarrow \text{future signature}
\]
这也意味着,当前阶段不应要求 SINDy/SR 一条线独自把全部物理机制说完。更稳的节奏是:先让 SINDy/SR 找到共享骨架与可闭环公式,再等 CCD/OID 与 wake-to-force 这边把结构中介对象做扎实之后,回头精简和改写白箱公式。
## 九、这一轮最值得长期保留的方法论经验
### 经验 1
**不要直接在原始控制场上谈“机制”。**
先拆出:
- 来流本身是什么
- 几何阻挡本身做了什么
- 控制额外改了什么
否则很容易把“本来就有的结构”误当成“控制生成的结构”。
### 经验 2
**当前问题的自然尺度不是单圆柱 wall-scale,而是 pinball-scale correction-scale。**
这意味着:
- 可以放弃一些不可信的细节分析;
- 但反而更容易得到跨场景稳定的主结论。
### 经验 3
**Chen 线最该保留的是因果顺序,不是细节模板。**
它告诉我们:
- 近体区在前,远场 observable 在后;
- 受力是近体区组织变化后的结果;
- 这就足以为 correction field 主线提供物理正当性。
### 经验 4
**Lyu / Schlegel 这条线最适合用来识别“控制额外改出来的任务相关结构”。**
不是所有 energetic 结构都重要;
真正重要的是 observable-relevant correction structures。[Sch12, Lyu23]
## 十、当前最值得长期保留的两句话
\[
\boxed{\text{当前项目最有价值的主张,不是“DRL 学会了某个力学量”,而是“DRL 学会了对 pinball 近体区修正场的低维调制”。}}
\]
同时必须保留另一句:
\[
\boxed{\text{Chen Tao 线提供的是正确的因果方向,而不是当前网格下可直接照搬的壁面分析模板。}}
\]
这两句话一起保留,最能防止后续再次滑回两个极端:
- 把全部机制压扁成 force tracking
- 把分辨率并不支持的壁面细节写得过满。
+163 -1158
View File
File diff suppressed because it is too large Load Diff
+191 -340
View File
@@ -1,399 +1,250 @@
# DynamisLab Understanding Notes # LegacyCelerisLab → CelerisLab V5 兼容与迁移账本
## 1. 网格尺寸 (Grid Dimensions) - 文档版本:`v5.0.0-ledger.2026-08-09`
- 状态日期:2026-08-09
- 适用范围:Legacy 场景复现、Legacy 策略跨求解器迁移差距研究、原生 CelerisLab V5 训练/评估
- 文档性质:工程兼容账本,不是科学结论、论文证据或当前开放路线图
### 旧版配置 > 本账本记录“什么必须保持、什么已经验证、什么不能等同”。Legacy 数值结果的最终权威是固定版本的 Legacy 原始求解器、原始环境和绑定 artifact;迁移代码与本账本只能解释兼容关系,不能替代原求解器证据。
- `config_cuda.json`: X_1U=128, Y_1U=32, Z_1U=1
- `config_flowfield.json`: field_dim_in_U=[10, 16, 1]
- 实际网格 = [128×10, 32×16, 1×1] = **[1280, 512, 1]**
### 新版配置 ## 1. 三条工作通道必须分开
- `config_lbm_pinball.json`: nx=1280, ny=512 → **完全相同**
所以网格尺寸没有变化。L0=20 是基尺度,但网格的 U 单位 = (128, 32) 是为了对齐 CUDA SM 数。 ### L1 — Legacy 原始求解器复现
--- 目的:在 `LegacyCelerisLab` 上重放历史场景、策略、归一化、控制区间和 reset 语义。
## 2. Re 数定义 - 使用原始 Legacy 动力学、对象顺序、动作插槽、观测布局、SI、FIFO、EMA 和冻结 norm。
- 当前统一入口及证据边界见 [Legacy reproduction README](drl_pinball/legacy_test/README.md)。
- 这是历史 Legacy 数值行为的首要权威;若迁移实现、旧笔记或文件名与直接 Legacy 运行冲突,以绑定源码/配置/artifact 的 Legacy 运行结果为准。
- SR 的当前科学范围和角色限制由各自包内文档决定;本账本不把历史 Illusion 或混合输出升级为当前正面科学证据。
**关键:** 用户使用了两种 Re 定义: ### L2 — 归档 Legacy 策略在现代求解器上的迁移差距研究
| 符号 | 长度尺度 | 公式 | 默认值 | 目的:把冻结 Legacy PPO 和匹配 normalizer 接到现代 `Simulation`,量化 solver/API/geometry/schema 差距。
|------|---------|------|--------|
| `Re_D` | 单个圆柱直径 D=20 | U0·D/ν | 0.01×20/0.004 = **50** |
| `Re` (代码中写) | 2×D = 40 | U0·(2D)/ν | 0.01×40/0.004 = **100** |
- Confirmation report 中的 `Re_D = 50` 对应代码中的 Re100 - 这是 compatibility experiment,不是“Legacy 已在 V5 等价复现”。
- 代码内写 re100 系列模型 → 实际物理 Re_D=50 - 必须显式使用 `legacy-policy-v1`、Legacy sensor 单位转换、匹配的 norm/VecNormalize 和 provenance。
- 上游扰流圆柱直径 = L0×1 = 20 → Re=U0×20/ν=50 (单直径) - 两套 LBM 实现的尾迹动力学可系统性不同;高 DTW 或动作相关性不证明 plant 等价。
- 归档经验与已知差距见 [REPRODUCE_KNOWLEDGE](archive/reproduce/REPRODUCE_KNOWLEDGE.md),但其中任何旧结论仍须服从当前源码和本账本的日期/版本规则。
--- ### L3 — 原生现代 V5 训练与评估
## 3. 旧 API vs 新 API 关键差异 目的:在现代 2000×600 CelerisLab contract 下校准、训练、保存和评估原生策略。
### 3.1 力的物理含义 - 训练入口、artifact 集和 resume 边界见 [V5 training README](drl_pinball/train/README.md)。
- canonical case registry、冻结 VecNormalize、确定性 360 步评估和复现 gate 见 [V5 evaluation README](drl_pinball/eval/README.md)。
- 原生 V5 使用当前 calibration/native sensor units;不得为了“像 Legacy”而隐式乘 `SENSOR_CC`
- 保留的历史模型/结果不自动证明已按当前 native-v2 contract 完整重训。
**旧 API (`FlowField.run(N, action)`)** ## 2. Legacy 不变量账本
```
obs[:] = 0
for step in range(N):
memset(obs_gpu, 0) # 每步清零 obs_gpu
step_kernel(...) # 每步 force 通过 atomicAdd 累加进 obs_gpu
obs += obs_gpu (H2D copy) # 每步读取到 host
obs /= N # 除以步数 = 每步平均力
```
→ 旧 `obs` = **每步平均力**
**新 API (`sim.run(N)` / `sim.stepper.step(N, ...)`)** ### 2.1 `Re_code` `Re_D`
```
# stepper 内部不会清零 obs
# 需要用户手动清零
sim.bodies.zero_force_segment_async(stream) # 清零力/扭矩段
sim.stepper.step(N, ..., stream)
sim.read_force(id) → 累积 N 步后的值
```
→ 新 `sim.read_force()` = **N 步累积力**(需除以 N 得到每步平均)
**对应关系:** Legacy 模型名和环境里的 `reXX` 通常是以 `2D` 为长度尺度的代码标签:
- 旧 `obs` = 新 `sim.read_force(id)` ÷ N
- 旧 `obs[i]` 的 index 顺序 = 传感器在前 + 力在后
- 新 API 分别用 `read_force(id)``read_sensor(id)` 分开读取
### 3.2 传感器的物理含义 ```text
Re_code = U0 · (2D) / ν
**旧 API** Re_D = U0 · D / ν = Re_code / 2
- Sensor 值通过 atomicAdd 累加,跟力一样每步清零、host 累积、除以步数
- 所以旧 `obs` 中的 sensor = **每步平均速度**
**新 API**
- SensorKernel 用 atomicAdd 累加 `ux, uy``obs_gpu` 的 sensor 段
- `read_sensor(id, normalize=True)` 除以 `sensor_cell_counts[body_id]` (该 sensor 覆盖的格子数)
- **但没有除以步数!**
```python
# 新 API 读取 sensor
# read_sensor(id) = (sum_{steps} sum_{cells} ux) / cell_count
# 要得到每步平均 = read_sensor(id) / N
``` ```
**所以旧 → 新转换:** `U0=0.01, D=L0=20, ν=0.004` 为例:`Re_code=100`,但单圆柱直径定义为 `Re_D=50`。因此 `d1a3o12_re100` 不能写成“Re_D=100”。任何跨目录比较必须同时记录 `Re_code``Re_D``U0``D``ν`,不能只抄文件名。
```python
# 旧环境:
# flow_field.run(SAMPLE_INTERVAL, action)
# obs = flow_field.obs # 已经是每步平均
# 新环境等效: ### 2.2 场景用途与历史参数
# sim.bodies.zero_force_segment_async(stream)
# sim.bodies.zero_sensor_segment_async(stream) - **Steady cloak**:均匀来流中的开环/上下游稳态隐身基线;`SI=800``CONV_LEN=30`scale `8`bias `[0,-5.1,+5.1]`
# sim.run(SAMPLE_INTERVAL) # 或 stepper.step(SAMPLE_INTERVAL) - **Karman cloak**:上游扰流圆柱产生涡街,控制 pinball 使下游传感器接近“有扰流圆柱、无 pinball”的目标;`SI=800``CONV_LEN=30`scale `8`bias `[0,-4,+4]`
# fx_per_step = sim.read_force(id)[0] / SAMPLE_INTERVAL - **Erase**:历史目标是把扰流尾迹向干净入口流状态“抹除”;`SI=600``CONV_LEN=36`scale `8`bias `[0,-8,+8]`。其滚动受控力历史/目标映射特殊,只有具备完整场景证据的入口才能声称支持。
# fy_per_step = sim.read_force(id)[1] / SAMPLE_INTERVAL - **Illusion**:均匀来流中控制 pinball,使下游信号模仿指定半径目标圆柱;scale `8`bias `[0,-2,+2]``CONV_LEN=36`。历史 `0.75L/1L/1.5L` 的 SI 分别为 `400/600/800`
# ux_per_step = sim.read_sensor(id)[0] / SAMPLE_INTERVAL - **Vortex Lamb/Taylor**:在保存的背景场上注入瞬态 Lamb dipole 或 Taylor vortex 后控制;`SI=800``CONV_LEN=30`scale `4`bias `[0,-4,+4]`,历史控制长度 150 区间。
# uy_per_step = sim.read_sensor(id)[1] / SAMPLE_INTERVAL - **Reduced observation**Karman 任务的 12→9→5→3→2 维观测消融,不是新的物理场景。
所有 bias/scale 先形成 Legacy 切向表面速度:
```text
surface_vel = (normalized_action × scale + bias) × U0
``` ```
### 3.3 Obs 布局对比 Illusion 的历史 FIFO 初始化可使用 `[0,-1,+1]×U0`,而策略映射 bias 为 `[0,-2,+2]×U0`;不能把两者合并。具体 artifact 的 scene config 高于通用默认值。
**旧 API obs 数组(以 cloak env 为例,7 个 objects:** ### 2.3 对象、动作、body 与观测顺序
```
obs[0:6] = sensor0_ux, sensor0_uy, sensor1_ux, sensor1_uy, sensor2_ux, sensor2_uy
obs[6:12] = cylinder0_fx, cylinder0_fy, cylinder1_fx, cylinder1_fy, cylinder2_fx, cylinder2_fy
obs[12:14] = dist_cylinder_fx, dist_cylinder_fy (扰流圆柱)
```
objects 添加顺序:传感器 → 圆柱体。obs 是先 sensor 段(6个值),后 cylinder 段(每个 cyL 2 个值)。
**新 API** 顺序是策略 contract,不是展示偏好。canonical 控制体顺序为:`front, upper(+y), lower(-y)`
- `sim.read_force(body_id)``[fx, fy]` 按 body_id 读取
- `sim.read_sensor(body_id)``[ux, uy]` 按 body_id 读取
- `sim.read_torque(body_id)``[tz]` 按 body_id 读取
### 3.4 Checkpoint/恢复 **Karman7 objects**
**旧 API** ```text
```python 添加/body 顺序:dist_cyl(0), sensor_upper(1), sensor_center(2), sensor_lower(3),
flow_field.get_ddf() # host ← gpu front(4), upper(5), lower(6)
flow_field.save_ddf() # 保存到 host 内存 Legacy raw obs [dist_fx, dist_fy, 6 sensor channels, 6 controlled-force channels]
flow_field.restore_ddf() # host 内存恢复 策略 raw sliceobs[2:14]
flow_field.apply_ddf() # host → gpu 策略归一化顺序:[front/upper/lower forces(6), sensors upper/center/lower(6)]
动作槽:action[0:3] → body 4/5/6 → front/upper/lower
``` ```
**新 API** **Illusion/Vortex6 objects**
```python
sim.snapshot() # 内存快照 ```text
sim.restore() # 恢复 添加/body 顺序:sensor_upper(0), sensor_center(1), sensor_lower(2),
# 或 front(3), upper(4), lower(5)
sim.save_checkpoint(path) # HDF5 文件 Legacy raw obs [6 sensor channels, 6 controlled-force channels]
sim.load_checkpoint(path) # 从文件恢复 策略归一化顺序:[front/upper/lower forces(6), sensors upper/center/lower(6)]
Illusion 14D:上述 12D 后追加 target_cd, target_cl
动作槽:action[0:3] → body 3/4/5 → front/upper/lower
``` ```
### 3.5 动作施加方式 `FlowField.run()` 接收按 object slot 打包的数组;sensor slot 不等于策略动作。迁移时必须用 impulse/order test 证明策略 action 0/1/2 实际驱动 front/upper/lower,不能根据变量名猜测。
**旧 API** ### 2.4 Legacy telemetry、norm、FIFO、EMA 与 reset
```python
# 全部 action 打包成一个数组,按 object 顺序排列 Legacy 控制区间内,force 和 sensor 对每个 lattice step 累加,公开 interval observation 再按步数平均。关键差别是 Legacy sensor 保留 footprint 内的 cell sum,不做现代 API 的面积平均。
action_array = np.zeros(n_objects, dtype=DATA_TYPE)
action_array[4:7] = ... # 圆柱体的 omega 值 历史 norm 公式:
flow_field.run(N, action_array)
# 内部有指数平滑:action_pinned = (1-weight)*action_pinned + weight*action_target ```text
force_norm_fact = 6 × max(abs(controlled forces))
sens_deviation[i] = mean(sensor_i)
sens_norm_fact[i] = 5 × max(abs(sensor_i - sens_deviation[i]))
``` ```
**新 API** 完整初始化/reset contract
```python
sim.set_body(body_id, omega=value) # 每个圆柱体单独设置 1. 稳定背景/场景,在定义的边界保存 DDF 状态。
sim.run(N) 2. 以零动作采集 `FIFO_LEN=150` 个控制区间并计算诊断 norm。
# 没有内置动作平滑(通过 ActionSmoother 可以实现) 3. 恢复保存状态;按场景 FIFO init action 采集保存 FIFO。
4. 历史策略推理使用训练时冻结 norm;重新计算 norm 只用于诊断和 reset FIFO,不能替换冻结 norm。
5. `FlowField.run()` 内部动作 EMA 为 `pinned = 0.9*pinned + 0.1*target`。当前 Legacy reproduction adapter 在每个公开 interval 前将 host action seed 清零,以复现 pre-persistence driver contract,同时保留 interval 内 EMA;不得再叠加第二个外部 EMA。
6. reset 必须同时恢复 DDF、保存 FIFO、策略可见初始 observation(当前 reproduction contract 为精确零)以及场景规定的动作/时钟状态。
若研究需要可重复的中途分支,而非普通 episode reset,仅保存一个 DDF 不够。Legacy 的 `full_state_checkpoint()`/`restore_full_state()` 会绑定双 ping-pong DDF、action、last effective action、raw/boundary observation 和 solver clocks;证据入口见 [Legacy driver](../LegacyCelerisLab/driver.py)。
### 2.5 `uni_test.ipynb` 的历史角色
`uni_test.ipynb` 曾是连续视频/演示编排器:加载模型和 DummyEnv,录制 steady、Karman、Illusion、Lamb/Taylor 目标,采集各场景 norm/FIFO,恢复 DDF,确定性推理,动作渐入/淡出,保存 Tecplot 场并合成视频。
它的价值是保存历史执行顺序和场景切换知识;它不是现代 V5 的 canonical 训练入口、评估 manifest 或科学权威。现代 V5 应使用 train/eval README 所声明的入口与 artifact contract。
### 2.6 Illusion “2U” 更正与 SI 差异
`2U` 表示 `S_DIM=14` 中额外的两个目标力维度 `target_cd,target_cl`,**不表示入口速度是 2×U0**。这些模型仍使用 `U0=0.01`
- `..._075L_2U_400S``SI=400`
- `..._1L_2U_600S``SI=600`
- `..._15L_2U`:无 S 后缀,历史默认 `SI=800`
现代 V5 registry 的 SI 不相同:当前 `ill_075L=1100``ill_1L/ill_15L/ill_2L=1200`。因此现代 native Illusion 与 Legacy Illusion 即使 case 名相似,也不是相同 interval contract。
## 3. 当前 CelerisLab V5 contract
### 3.1 telemetry:已纠正的当前语义
`Simulation.run(steps, zero_obs=True)` 默认在该批次前清零 force/torque/sensor 累积区并重置内部累计步数;`zero_obs=False` 可跨多次 run 累积。完成下载并同步后:
- `read_force(id, normalize=True)`:GPU 累积力除以自上次清零以来累计的 lattice steps,返回**每步平均力**。
- `read_sensor(id, normalize=True)`:先除 sensor footprint cell count,再除累计 lattice steps,返回**每步、面积平均速度**。
- 所以使用默认 `normalize=True` 时,**禁止再除以 `SAMPLE_INTERVAL/SI`**;再次除法会引入错误的 `1/SI`
- 为构造 Legacy-equivalent sensor,可在几何和 cell-count 已验证时使用 `legacy_sensor ≈ modern_sensor × sensor_cell_count`;历史半径 5 footprint 曾验证为 78 cells,不能把 `78` 当作任意几何/版本常数。
`normalize=False` 的当前源码意图是:force 返回未做时间归一化的 GPU 累积和;sensor 仍会做面积归一化,但不做时间归一化。**迁移研究不得仅凭该描述推断跨版本 raw 等价**:每个目标 commit/config/GPU 路径都应通过 `raw == normalized × accumulated_steps`sensor 在相同 area convention 下)及清零/跨-run 累积测试显式验证。特别是低层 `bodies.read_*`、自定义 `zero_obs`、异步下载路径不能默认继承高层调用时序。
当前实现与测试证据:
- [ObjectManager telemetry implementation](../CelerisLab/src/CelerisLab/body/manager.py)
- [Unified observation integration tests](../CelerisLab/tests/integration/test_unified_obs.py)
- [CelerisLab public API](../CelerisLab/README.md)
### 3.2 动作单位:表面速度与角速度
Legacy action 是圆柱表面切向速度,现代 `set_body(id, omega=...)` 是角速度。两者都采用 lower-origin、y-up 坐标:
```text
Legacy: Uw = -surface_vel × ry/R, Vw = surface_vel × rx/R
Modern: Uw = -omega × ry, Vw = omega × rx
因此:omega = surface_vel/R
``` ```
### 3.6 数值错误检测 `omega` 为逆时针;该方程对照下**不需要额外负号**。完整映射为:
**旧 API** ```text
```python omega = ((action_norm × scale + bias) × U0) / R
flow_field.has_numeric_error()
flow_field.last_error_flag
``` ```
**新 API** 例如 `R=10, U0=0.01` 时,Karman bias `[0,-4,+4]` 映射为 `[0,-0.004,+0.004]`。任何出现 `omega = -surface_vel/R` 的迁移实现都必须先用 wall-point velocity 和直接 solver test 重新证明,不能沿用旧的符号猜测。
需要手动实现检查。
--- ### 3.3 原生 V5 calibration、policy 与 eval
## 4. 五种场景详解 高层 contract 如下,细节以 [training README](drl_pinball/train/README.md) 和 [evaluation README](drl_pinball/eval/README.md) 为准:
### 4.1 Karman Cloak (模型名: d1a3o12_re系列) - 训练 target 是匹配的 `calibration.json + target.npy`Illusion 还需要匹配 harmonicsJSON 单独存在不构成完整 target。
- 物理层先使用 CelerisLab area/time telemetry;环境再应用 `FORCE_SCALE/SENS_SCALE`SB3 `VecNormalize` 是第三层在线 running statistics。
- `native-v2` 不插入 Legacy `SENSOR_CC``legacy-policy-v1` 仅用于冻结历史模型的兼容加载。
- best policy 必须与同一 best-selection 点的 best normalizer 配对。独立 eval 对 artifact 文件名有显式、fail-closed 的 case 规则。
- eval 冻结 `VecNormalize(training=False, norm_reward=False)`,策略确定性运行 360 步,以后 180 步计分;GPU replay 不承诺 bitwise 一致。
- resume 仅是 policy + matching normalizer continuation,不是 optimizer、RNG、CFD、wrapper 和 trajectory 的精确进程重放。
**目标:** 上游 2D 扰流圆柱产生涡街,控制 pinball 使下游传感器信号跟无 pinball 时一致 ## 4. 已验证等价与已知不等价
**几何布局:** ### 4.1 已验证或可机械证明的局部等价
```
上游扰流圆柱:x=10*L0, y=中心, r=L0 (=200, 240, 20)
Pinball前: x=30*L0, y=中心, r=L0/2 (=600, 240, 10)
Pinball下: x=31.3*L0, y=中心-0.75*L0, r=L0/2 (=626, 225, 10)
Pinball上: x=31.3*L0, y=中心+0.75*L0, r=L0/2 (=626, 255, 10)
Sensor上: x=40*L0, y=中心+2*L0, r=L0/4 (=800, 280, 5)
Sensor中: x=40*L0, y=中心, r=L0/4 (=800, 240, 5)
Sensor下: x=40*L0, y=中心-2*L0, r=L0/4 (=800, 200, 5)
```
**目标信号:** 只有上游扰流圆柱(无 pinball)时,sensor 的时间序列 - `Re_D = Re_code/2`:在相同 `U0,D,ν` 定义下成立。
**观测:** `forces[6]+sens[6]` = 6 个 force 值 + 6 个 sensor 值 = 12 维 - 当前 modern `normalize=True` force 与 Legacy interval force 都具有“每 lattice step 平均”层次;数值本身仍可能因 solver/geometry 不同而不等价。
**动作缩放:** `action×8U₀ + [0, -4U₀, 4U₀]` (=0,0 代表 -4,4 的偏置动作) - Legacy/modern 旋转壁面方程给出 `omega=surface_vel/R`,同号、正值逆时针。
**Reward:** `min(0.3×exp(-|Cd×20|) + 0.4×exp(-|Cl×80|) + 0.3×exp(-10×|sim-1|), 1.0)` - 固定 footprint 下,Legacy sensor cell-sum/step 与 modern area/time average 的单位桥为乘实际 cell count;半径 5 的历史配置曾测得 78。
**SAMPLE_INTERVAL:** 800 - canonical 控制顺序是 front/upper/lower,且 Karman body IDs 4/5/6、Illusion body IDs 3/4/5 已有 order tests。
**CONV_LEN:** 30 - modern in-memory `snapshot/restore` 当前覆盖场、solver step、body state/control、action 和 telemetrybody topology 必须不变。
**检查点流程:**
1. 初始化只有扰流圆柱+3传感器的环境 → 运行稳定 → 记录150步目标信号
2. 添加 pinball → 稳定 → 保存 DDF(无控制状态)
3. 用零动作运行 150 步 → 记录 obs 到 fifo → 计算 norm
4. 用预设动作(-4,4)运行 150 步 → 记录 obs → 保存 save_states
5. reset=恢复DDF + 恢复fifo
### 4.2 Erase (模型名: d1a3o12_250729_250326_erase系列) ### 4.2 已知非等价
**目标:** 跟 Karman Cloak 场景基本一致,但目标是让下游流场恢复到"入口流状态"(干净来流),即抹除扰流圆柱尾迹 - Legacy 与 modern 是不同 LBM 实现;迁移策略下的尾迹、力方差、相位和闭环轨迹不保证相同。
- Legacy 常用 1280×512 网格;native V5 是 2000×600。Karman/Illusion 的绝对位置、中心线(现代 `y=299.5`)、入口/壁面/出口配置也可能改变。
- Legacy sensor 是 cell-sum/stepmodern sensor 是 area-average/step。
- Legacy action 输入是 surface velocitymodern action输入是 angular velocity。
- Legacy interval EMA/host-action seed contract 与 modern 用户态 smoother 不天然相同。
- Legacy Illusion SI `400/600/800` 与当前 native V5 `1100/1200/1200/1200` 不同。
- Legacy frozen norm 与 native calibration/VecNormalize 不是同一个统计对象。
- 同名 target size 仍可能有半径/直径命名陷阱:现代 `target_diam` 历史上实际作为 `radius = target_diam×L0` 传入。
- DDF snapshot 相等不代表完整 RL 状态相等;FIFO、外部 EMA、reward EMA、target phase、current step、VecNormalize、policy/optimizer/RNG 都可能在求解器外。
**关键区别:** ## 5. checkpoint 与 full-state 要求
- 目标信号 = 入口均匀流的均值(基本为零方差)
- Reward 主要看传感器与均值的偏差
- **这是未完全实现的部分**
- 动作缩放: `×8U₀ + [0, -8U₀, 8U₀]`
### 4.3 Illusion (模型名: d1a3o14_250525_imit系列) 按用途分级保存,禁止把较低级别称为“精确恢复”:
**目标:** 上游干净来流,控制 pinball 使其下游流场跟指定直径的单个圆柱一致 1. **场恢复**:双 DDF/ping-pong 状态、flags、solver step 与完全匹配的 config/precision/topology。
2. **环境 reset**:场恢复 + body action/control + telemetry accumulator + FIFO/save_states + action smoother + reward EMA + target phase/current step。
3. **策略推理复现**:环境 reset + policy + 同点 normalizer + calibration/target/harmonics + case registry/provenance + deterministic flags。
4. **训练精确续跑**:再加 optimizer、scheduler、所有 RNG、rollout buffer、wrapper/process state;当前 V5 README 明确不承诺这一层。
**几何差异:** modern `snapshot/restore` 适合内存内环境 reset,但外部 Python 状态仍须由 env 同步保存。HDF5 `save_checkpoint/load_checkpoint` 当前保存 DDF、temp、flags、step、config metadata 和 object states;在把它称为完整 RL/full-state checkpoint 前,必须额外证明 action buffer、telemetry accumulator、FIFO/EMA/normalizer 等均被恢复。
- 没有上游扰流圆柱
- 目标圆柱位置不同(x=20*L0 或 x=31*L0,取决于场景)
- Sensor 位置可能调整(x=30*L0 而不是 40×L0,为了贴近目标圆柱等效距离)
- 目标信号通过 harmonics 分析(FFT 提取频域特征)进行重构
**观测:** 12 维 (forces) + 2 维 (target_cd, target_cl) = 14 维 ## 6. 几何、版本与证据 caveat
**Reward:** `min(0.3×exp(-|(Cd-Cd_target)×10|) + 0.3×exp(-|(Cl-Cl_target)×10|) + 0.4×exp(-10×|sim-1|), 1.0)`
- 力的比较是和目标圆柱的谐波重构值比较
**IMPORTANT CORRECTION (2026-06-12):** "2U" in model name means S_DIM=14 (2 extra target force dimensions), NOT 2x velocity. ALL models train with u0=0.01. SAMPLE_INTERVAL varies by diameter: - 每次运行记录:git commit、solver version、CUDA/GPU、config SHA256、geometry/body ledger、object IDs、`U0/ν/L0/R``Re_code/Re_D`、SI、cell count、动作公式、obs 切片、normalizer/target/model hashes。
- 0.75L: `..._075L_2U_400S` → S=400 - grid size 相同只说明数组尺寸相同,不证明几何、边界条件、碰撞模型、streaming、DDF shifting、精度或动力学相同。
- 1.0L: `..._1L_2U_600S` → S=600 - body center/radius、upper/lower 符号和动作数组必须在运行前打印;文件名、图例和记忆不能覆盖直接 source equation 或 reversal CFD。
- 1.5L: `..._15L_2U` → no S suffix = default S=800 - `SENSOR_CC=78` 只对已验证 footprint 成立;几何、离散化或版本改变后重测。
- nu=0.004 for all (no Vis suffix = default) — confirmed via sweep - `normalize=False`、异步路径和 checkpoint compatibility 均按目标 commit 重新验证,不能由旧 API 文档外推。
### 4.4 Vortex (模型名: vortex_lamb / vortex_taylor) 推荐的测试/证据路径:
**目标:** 在初始流场中加入涡量(Lamb dipole 或 Taylor vortex),控制 pinball 使下游信号跟无 pinball 时一致 - Legacy contract 与 reset/order[`drl_pinball/legacy_test/tests/`](drl_pinball/legacy_test/tests/)
- SR Legacy order/Re/SI[`SR_analysis/tests/test_legacy_contracts.py`](SR_analysis/tests/test_legacy_contracts.py)
- modern telemetry[`../CelerisLab/tests/integration/test_unified_obs.py`](../CelerisLab/tests/integration/test_unified_obs.py)
- modern body sync[`../CelerisLab/tests/integration/test_body_sync_e2e.py`](../CelerisLab/tests/integration/test_body_sync_e2e.py)
- native normalization schema[`drl_pinball/train/tests/test_normalization_schema.py`](drl_pinball/train/tests/test_normalization_schema.py)
- eval compatibility[`../tests/test_drl_pinball_infer_train.py`](../tests/test_drl_pinball_infer_train.py)
- Legacy→modern 归档比较器:[`drl_pinball/eval/archive/compare_legacy_v5.py`](drl_pinball/eval/archive/compare_legacy_v5.py)
**关键特征:** ## 7. 最后验证与来源权威规则
- 要正确使用 `add_vortex` 进行初始化
- Dipole (Lamb) 强度较大 (0.5*U0)Monopole (Taylor) 强度较小 (0.03*U0)
- Vortex 在保存 DDF 之后添加,随流场演化
- 有 `MAX_STEPS=150` 的终止条件(因为是 transient 事件)
- 动作缩放: `×4U₀ + [0, -4U₀, 4U₀]`
- Reward: `min(0.2×exp(-|Cd×20|) + 0.3×exp(-|Cl×80|) + 0.5×exp(-10×|sim-1|), 1.0)`
### 4.5 Reduced Obs (模型名: d1a3o12_250421系列) 发生冲突时按以下顺序裁决,并记录裁决日期:
**目标:** 同 Karman Cloak,但逐步减少观测维度 1. 目标 commit 上的直接 kernel/source equation 与最小可重复 runtime test。
**观测:** 从 12 → 9 → 5 → 3 → 2 递减,观察模型是否能适应 2. 与该 commit/config/artifact hash 绑定的集成测试和生成 provenance。
3. scene registry、训练/评估 README 与设计决策文档。
4. 本账本和归档迁移报告。
5. notebook、文件名、图例、口头记忆。
--- “最后验证”必须说明验证了哪个 commit、哪个 config、哪个 GPU 路径和哪一种 normalize/reset 调用;只写日期不够。未验证项应 fail closed,不得用看似合理的转换自动补全。
## 5. Norm 采集过程(关键!) ## 8. 历史重写提案状态
**所有旧环境共有的模式:** 旧版“未来重写 base_env、逐场景继承、复制模型、再做等价验证”的提案已于 V5 train/eval 与 compatibility lanes 建立后作为**已完成的历史设计阶段**关闭。它不是当前开放 roadmap,也不授权继续把 Legacy 迁移结果包装成原生 V5 科学结果。后续变更应分别进入 L1、L2 或 L3,并遵守各 lane 的证据边界。
```python
# 环境初始化最后阶段:
# Step 1: 用零动作运行 FIFO_LEN 步,记录 obs
for i in range(FIFO_LEN):
flow_field.run(SAMPLE_INTERVAL, zero_action)
fifo_states.append(flow_field.obs[sensor_select])
# Step 2: 从 fifo 计算 norm
temp_states = np.array(fifo_states)
force_norm_fact = 6 * max(|forces|) # 力归一化因子
for i in range(6):
sens_deviation[i] = mean(sensor[i]) # 均值
sens_norm_fact[i] = 5 * max(|sensor[i] - mean|) # 波动范围×5
# Step 3: 恢复 DDF,用预设动作运行 FIFO_LEN 步
flow_field.apply_ddf()
for i in range(FIFO_LEN):
flow_field.run(SAMPLE_INTERVAL, init_action)
fifo_states.append(...)
save_states = fifo_states.copy()
```
这个 norm 值是**模型训练时就固化**的,**推理时也必须使用完全相同的值**。旧版环境在初始化时自动计算,新环境需要为每个场景预计算和存储这些 norm 值。
---
## 6. uni_test.ipynb 流程解析 (最重要参考)
这个 notebook 是一个连续的、视频式展示,包含以下序列:
### Phase 0: 初始化和元数据采集
1. 加载所有模型
2. 创建 DummyEnv 用于加载模型(只是一个匹配 obs/action space 的空壳)
3. 设置 CUDA context,创建 `FlowField`
4. 设置 `meta_*` 对象存储 norm 值
### Phase 1: 目标信号录制
1. **Steady 目标**3 sensors × 150步 → 记录时序均值(干净来流)
2. **Dipole (Lamb)** 目标:restore DDF → add_vortex Lamb → 150步 → 记录
3. **Monopole (Taylor)** 目标:restore DDF → add_vortex Taylor → 150步 → 记录
4. **Illusion 目标**1.0L 圆柱):新 FlowField → 单圆柱 x=31*L0, r=1*L0 → 3 sensors → 150步 × 800 采样 → 记录 8 维 obs + harmonics 分析
5. **Illusion 目标**0.75L 圆柱):类似,SAMPLE_INTERVAL=400
6. **Illusion 目标**1.5L 圆柱):类似,SAMPLE_INTERVAL=800
7. **Karman 目标信号**:pinball 恢复 + 扰流圆柱 → 3 sensors → 150步 × 800 采样 → 记录 sensor+force obs
### Phase 2: Pinball + Norm 采集
- 创建 pinball → 运行到稳定 → save DDF
- 零动作 150步 → 计算 norm
- 预设动作 150步 → 记录 save_states
### Phase 3: Norm 采集(各个场景)
- 跟 Phase 2 类似,但针对各个特定场景恢复 DDF 后分别采集 norm
### Phase 4: 推理运行(控制演示序列)
1. **No Control (nc)** 基线:加载 pinball DDF → 零动作 100步 × 1000采样 → 保存场
2. **Steady Cloaking**: 从 nc 继续 → 逐步切换到 cloak 动作(75步渐入+保持)
3. **Dipole Cloaking**: restore DDF → add Lamb vortex → 用 cloak_lamb 模型推理 → 25步渐入/25步淡出 → 保存场
4. **Monopole Cloaking**: restore DDF → add Taylor vortex → 用 cloak_taylor 模型推理 → 类似渐入淡出
5. **Illusion (1L)**: restore DDF → 用 illusion_1L 模型推理 → 10步渐入 → 200步保持
6. **Illusion (0.75L)**: 类似
7. **Illusion (1.5L)**: 类似
8. **Karman NC + Cloak**: restore Karman场景DDF → 200步无控制 → 切换到 cloak_re100 模型推理
9. **Frame 合成 → ffmpeg 视频**
关键点:
- **场景间过渡**通过 `restore/apply DDF` 实现
- **动作渐入/淡出**用 `linear interpolation in action space`
- 场数据存在 `.dat` 文件(Tecplot格式),用 `save_field()` 保存
- 所有推理都用 `deterministic=True`
---
## 7. 旧 API 动作数组的索引规则
`FlowField.run()``action_target` 数组按 object 添加顺序排列:
```
| Sensors 的 action slot | Cylinders 的 action slot |
| sensor0, sensor1, ... | cylinder0, cylinder1, ... |
```
每个 object 的 action slot 有 3×DIM 个值(DIM=2 时=6),但 LBM 中 sensor 只用第一个值(实际上被忽略),cylinder 用最后一个值(omega)。
```
action[0] = sensor0 (ignored)
action[1] = sensor0 (ignored)
action[2] = sensor0 (ignored)
action[3] = sensor1 (ignored)
action[4] = sensor1 (ignored) ← 对于 cloak env,这里放 cylinder0 的 omega
action[5] = sensor1 (ignored)
action[6] = cylinder0 omega (disturbance cylinder for cloak)
action[7] = cylinder1 omega (front pinball) ← 注意!对象索引顺序取决于添加顺序
```
实际各环境设置 action 的方式:
```python
# cloak env (7 objects: 3 sensors + 1 dist_cyl + 3 pinball):
temp = np.zeros(7, dtype=DATA_TYPE)
temp[4:7] = (action*8 + [0,-4,4]) * U0 # action[4]=front omega, [5]=bottom, [6]=top
# erase env:
temp[4:7] = (action*8 + [0,-8,8]) * U0
# imit env (6 objects: 3 sensors + 3 pinball):
temp[3:6] = (action*8 + [0,-2,2]) * U0
# vortex env:
temp[3:6] = (action*4 + [0,-4,4]) * U0
```
注意 `temp[4:7]` 是从 index 4 开始取 3 个值。这是因为添加顺序是:
1. sensor0 (id=0)
2. sensor1 (id=1)
3. sensor2 (id=2)
4. dist_cylinder (id=3) — 旧 env 里添加上游扰流圆柱后固定为 0
5. pinball_front (id=4)
6. pinball_bottom (id=5)
7. pinball_top (id=6)
---
## 8. 重写注意事项
### 8.1 力和传感器的归一化
因为新 API 返回的是 N 步累积值(需要除以步数),所以 norm 的物理含义需要重新标定。
### 8.2 动作缩放关系
旧环境动作缩放矩阵(从归一化 [-1,1] action 到物理 U0 倍数的 omega):
| 场景 | 公式 (θ=action) | 物理范围 |
|------|----------------|---------|
| Cloak | `action×8 + [0,-4,4]` | front: [-8,8], bottom:[-12,4], top:[-4,12] |
| Erase | `action×8 + [0,-8,8]` | front: [-8,8], bottom:[-16,0], top:[0,16] |
| Illusion | `action×8 + [0,-2,2]` | front: [-8,8], bottom:[-10,6], top:[-6,10] |
| Vortex | `action×4 + [0,-4,4]` | front: [-4,4], bottom:[-8,0], top:[0,8] |
然后乘以 U0=0.01 得到实际的晶格 omega 值。
### 8.3 边界条件
旧配置是 parabolic inlet + no-slip walls(因为 legacy solver 不支持 free-slip
新 pinball 配置是 parabolic inlet + **bounce_back** walls(即 no-slip,跟旧版一致)
注意新配置 `config_lbm_pinball.json``y_wall_bc``bounce_back`,验证配置 `run_kan99b``free_slip`,要统一。
### 8.4 重写策略
1. **base_env.py**: 封装共享逻辑(Simulation 创建、几何布局、checkpoint 管理、norm 存储、DTW 工具)
2. **每个场景继承 base_env**: 只覆盖 reward、目标信号、动作缩放
3. **train/*.py**: 跟旧版一致的 PPO 训练循环(Sin 激活、SB3 PPO、TensorBoard
4. **eval/*.py**: 推理脚本,对应 uni_test 功能,用配置文件驱动场景序列
5. **configs/**: 存储每个场景的 norm 值、几何参数、采样参数
6. **models/**: 从旧版复制训练好的 .zip 模型(在新 API 推理中使用)
### 8.5 与旧环境的数值一致性验证方法
新环境在完全实现后,必须用旧训练好的模型在新 env 上跑推理,对比:
- 传感器时序信号(旧 `obs` vs 新 `read_sensor/SAMPLE_INTERVAL`
- 力信号(旧 `obs` vs 新 `read_force/SAMPLE_INTERVAL`
- 场数据(旧 `save_field` vs 新 `get_macroscopic`