# Stage 3: CFD Closed-Loop Validation

Validates PySR formulas or PPO baselines in closed-loop CFD. Final judge is DTW similarity (not one-step R2).

## Usage

```bash
# PySR formula validation
conda run -n pycuda_3_10 python stage_3_validate.py \
    --scene karman_re100 --device 2 --mode pysr \
    --formula-front results/formulas/karman_joint_front.json \
    --formula-top results/formulas/karman_joint_top.json

# PPO baseline
conda run -n pycuda_3_10 python stage_3_validate.py --scene illusion_1L --device 2 --mode ppo

# Batch generalization
conda run -n pycuda_3_10 python stage_3_validate.py \
    --group illusion_generalization --device 2 --mode pysr \
    --formula-front results/formulas/illusion_joint_front.json \
    --formula-top results/formulas/illusion_joint_top.json
```

## Modes

- **pysr**: Deploy PySR formula in closed-loop CFD (v23: front no-bias, rear shared-head)
- **ppo**: Run trained PPO model as baseline
- **uncontrolled**: Zero-action baseline

## Steps

Auto-calculated from sample interval: SI=400→320, SI=600→214, SI=800→160.

## Output

`results/validations/{scene_name}.json`: similarity score, mode, n_steps.

## v23 Structure

- Front: α_F = f_front(x), no bias — should be ~0 when features ~0
- Top: α_T = f_rear(x), with bias
- Bottom: α_B = -f_rear(G[x]) — shared-head via G-mirror

G-mirror: [aF,aT,aB]→[-aF,-aB,-aT], sensors swap top↔bottom with v sign flip.

## Similarity Interpretation

- > 0.90: Excellent (cloak/illusion effective)
- 0.70-0.90: Partial control
- < 0.50: Poor

Tail similarity isolates the far-wake portion.
