BlidReview's picture
weights, code, eval script
bdce880 verified
|
Raw
History Blame Contribute Delete
7.52 kB
# ezflow_v2/app β€” interactive web app (turbulent-RANS GNN predictor)
A self-contained FastAPI + Three.js app that predicts steady turbulent-RANS flow
fields around a body **in milliseconds** with a choice of surrogate models, an
interactive 3D viewer, slice planes, and a point-probe tool.
> Self-contained under `ezflow_v2/`; **separate from the v1 app** (`app/`, port 8000)
> per the v1/v2 separation rule. The v2 app runs on **port 8001**.
```bash
python ezflow_v2/app/run_app.py # -> http://127.0.0.1:8001 (opens a browser)
```
First prediction lazily loads the model(s) (the ensemble loads all three, ~10–20 s);
every prediction after that runs in milliseconds. Requires the trained runs under
`ezflow_v2/gnn/_runs/` (rans_v5, hybrid, transolver) and the v2 env (torch
2.11+cu128, gmsh, trimesh, pyvista, fastapi, uvicorn).
---
## What it does (pipeline)
```
geometry (procedural shape OR uploaded STL)
β”‚
β”œβ”€ premesh: normalize to L=1 β†’ surface (true geometry if watertight, else
β”‚ voxel envelope) β†’ graded tet mesh (fine near body)
β”‚
β”œβ”€ graph: nodes = mesh points; features = geometry + (Re, yaw) ONLY
β”‚ (same features.py as training β€” no solved field is ever an input)
β”‚
β”œβ”€ model: GeoReNet / HybridFlow / Transolver / mean(G,T,H) ensemble
β”‚
└─ outputs: per-node u, v, w, p, k, Ο‰, Ξ½_t β†’ 3D viewer + slice planes + probe
```
**No CFD is run for a prediction.** Inputs are the shape and the operating condition
(`Re`, yaw) only; OpenFOAM is used solely offline to train the models.
---
## Controls & features
### Surrogate Model (dropdown)
| Option | Backed by run | Params |
|---|---|--:|
| **mean(G,T,H) ensemble** (default) | average of the three below | ~10.2M |
| HybridFlow | `_runs/hybrid` | 3.04M |
| GeoReNet | `_runs/rans_v5` | 3.28M |
| Transolver | `_runs/transolver` | 3.88M |
The ensemble averages the three models per node (in the transformed target space).
To add GINO: append `"GINO": ["gino"]` to `MODELS` in `infer_app.py`.
### Mesh Resolution (dropdown) β€” the premesher
| Preset | Surface | Near-body size | Typical nodes | Use |
|---|---|--:|--:|---|
| Coarse | voxel envelope (vox 64) | hβ‰ˆ0.12 | ~3k | fastest, smoothed |
| **Medium** (default) | **true geometry** (watertight) | hβ‰ˆ0.045 | ~10k | detail + training density |
| Fine | true geometry | hβ‰ˆ0.022 | ~25k+ | most detail (slower) |
- **Watertight, genus-0 uploads keep their true surface** (mirrors/edges survive) and
are meshed with curvature-aware near-body refinement.
- **Non-watertight / complex bodies** (e.g. DrivAer: open underbody, wheel wells) can't
be parametrized into a clean external-flow solid, so they **auto-fall-back** to a
robust voxel **envelope** (smooth shell) at the requested volume density. This is
automatic β€” a complex STL will predict (as an envelope) rather than error.
- Medium β‰ˆ the ~10k-node density the models were trained on (the sweet spot).
### Geometry input
- **Simple Shape** tab: cylinder / sphere / box / capsule / cone / torus (sliders).
- **Upload STL** tab: drag-and-drop or browse any `.stl` (auto-normalized to L=1).
Test geometries live in `C:\dev\ezflow_eval\test_stls\`.
### Physics
Inlet speed, viscosity, density sliders β†’ **Reynolds number** (the only physical knob,
`Re = ρ U∞ L / ΞΌ`), plus a **yaw** slider. Models were trained on **Re β‰ˆ 5Γ—10²–1Γ—10⁡**;
predictions far outside that range are extrapolation.
### Visualize Field (slice viewer)
All seven outputs are selectable: **|U|, u, v, w, p, k, Ο‰, Ξ½_t**. A slice plane (X/Y/Z
axis + position slider) is colored by the chosen field; optional flow vectors on the slice.
Color map is **green (low) β†’ gold β†’ red (high)**; the legend shows the range and a
non-dimensional unit label.
### Mouse controls
- **Left-drag** β€” rotate
- **Mouse-wheel scroll** β€” zoom
- **Wheel-press (middle) drag** β€” pan
- **Single left-click** β€” set the rotation pivot at that point **and** probe values there
### Point Query (probe)
Click any point in the 3D view β†’ the sidebar shows the predicted **x,y,z and all field
values** (|U|, u, v, w, p, k, Ο‰, Ξ½_t) at the nearest node (`/api/probe`).
### Display & View (right sidebar)
Body style (glass / wireframe / hidden), wind-tunnel box, slice grid lines, flow vectors,
and view presets (3D / Side / Top / Front).
---
## HTTP API
| Endpoint | Method | Purpose |
|---|---|---|
| `/` | GET | the app page |
| `/api/models` | GET | `{models, default}` |
| `/api/predict` | POST (form) | `shape_type, model_name, resolution, Re, yaw_deg`, shape params or `file`; returns coords, wall_tris, per-field `ranges`, `geom_meta` (incl. surface `method`/`n_faces`), `mesh_meta` (incl. `resolution`, `n_nodes_approx`), `model {name, params_m, members}`, bounds |
| `/api/slice` | POST (json) | `{normal_axis, position, field_type}` β†’ slice `points/faces/scalars/vectors` |
| `/api/probe` | POST (json) | `{x, y, z}` β†’ nearest-node `{point, values{...}, velocity_vec}` |
All responses are sent with `Cache-Control: no-store` so the browser always loads the
latest build (static assets are also versioned, `?v=N`).
---
## Files
- `run_app.py` β€” launcher (port 8001).
- `serve.py` β€” FastAPI: endpoints above, no-cache middleware, caches the current
`pyvista` grid for slicing/probing.
- `infer_app.py` β€” model loading (architecture rebuilt per checkpoint) + uniform
ensemble; `mesh_stl()` (premesh + read) with the auto-fallback; `predict_fields()`
(predicts on the **full mesh** β€” the models are mesh-density-robust β€” and returns
physical fields via `features.inverse_targets`).
- `premesh.py` β€” detail-preserving premesher: `prepare_surface()` (true geometry vs
voxel envelope) + `build_volume()` (graded, curvature-aware gmsh mesh); `PRESETS`.
- `shape_generator.py` β€” procedural watertight shapes (trimesh).
- `frontend/` β€” `index.html`, `app.js` (Three.js viewer, slicing, probe, colormap),
`style.css`.
Geometry meshing reuses the shared, geometry-neutral gmsh tooling in
`datasets/gen/shapenet/` (same as `infer_v5`); it carries no v1 physics.
---
## Caveats / limitations
- **Training fidelity:** the models were trained on the *smoothed envelope* geometries
(ModelNet shapes passed through the same voxel remesh). A high-detail mesh improves the
geometry/visualization and lets the model run on a faithful body, but the model **cannot
fully exploit fine features it never saw** (e.g. mirror wakes). True fine-detail
prediction on complex cars would need **retraining on high-fidelity geometry + CFD**.
- **Complex/dirty STLs** (open underbody, non-watertight) are served as a smooth envelope
(see Mesh Resolution). In-app gmsh can't make them a clean external-flow solid; the
CFD-grade route (snappyHexMesh) is out of scope for the interactive app.
- **Outputs are non-dimensional** (U∞ = 1, ρ = 1, L = 1); labels reflect this
(`p/ρU∞²`, `Ξ½_t/Ξ½`, …).
- **Out-of-distribution** geometry (e.g. ModelNet car/airplane, sharp finned bodies) and
Reynolds numbers outside ~5Γ—10²–1Γ—10⁡ are extrapolation β€” interpret with care.
## Troubleshooting
- **Page looks stale / controls unresponsive:** hard-refresh once (Ctrl+Shift+R) or open
an Incognito window. The server sends no-cache headers, so it stays fresh afterward.
- **An STL errors:** it should auto-fall-back to the envelope; if not, try Coarse
resolution (goes straight to the robust envelope).