The "optimal" plant layout flooded on its own ground — GPU flood simulation, OpenUSD and Omniverse Kit in a generative-design loop
In short
- A generative-design (GA) tool picked a water-treatment-plant layout 6.3 % cheaper than the current plan. It got there by cutting the whole plant into a basin 1.3–3.4 m below original ground. Its flood map could not see that, because the map was run over the original ground.
- I re-ran rain and inflow over the ground each layout creates with a 2D shallow-water solver in NVIDIA Warp (GPU, 4.7 s per plan). The optimum flooded at 3 facilities, and after repair it lost its lead. The result agreed with HEC-RAS 2D (flooded-area IoU 0.94, danger verdicts 14/14).
- OpenUSD is the source of truth: the plans are variants of one file and the design numbers are attributes (150 checked, 0 mismatches). Review happens in Omniverse Kit. Four AI surrogates were tested; none was safe enough to judge, so AI only suggests evaluation order.
Site, terrain and unit costs are synthetic or assumed; no real client or site data.

What it looks like in Omniverse

This is the GA's optimum, plan C, in Omniverse Kit (RTX). The water surface is the Warp result stored as 54 time samples in an OpenUSD file. Red marks facilities whose USD attribute wtp:flood:danger_R0 is True.
Water collects in the cut basin, surrounds the sludge basin, and reaches the clearwell edge at about 45 minutes. The clearwell is the tank that stores treated drinking water. The rest of this post explains how this frame was produced, and what it changed.
1. A design tool where hydraulics is the source of truth
The layout tool does real design calculation before any optimization:
- Sizing and compartments based on Korean design standard KDS 57: sedimentation, filters, ozone, GAC and clearwell.
- Pipe routing between actual connection points: 17 pipe systems that avoid structures.
- A hydraulic profile from inlet to clearwell (total head 7.38 m), with an evidence grade on every value.
- Side systems (backwash, recycle, sludge) solved in the same function as the main water levels.
- Optimization with a relative-layout GA, scoring 20-year life-cycle cost (LCC): earthwork, piping and pumping power.
The GA evaluated 1,702 plans. It picked plan C at 1.688 bn KRW against 1.802 bn for the current plan A. Its trick was to lower the inlet level by 2.95 m, which saves raw-water pumping cost. The price was a stepped basin cut into the slope.
The tool's flood check used one map, computed once per site over the original ground with no plant on it. A map like that cannot show whether a basin cut into the ground collects water.
2. Three ways to see the same flood

| Method | What it is | Plan C, clearwell apron |
|---|---|---|
| Original-terrain flood map | What the design tool used | 0 m |
| Depression fill (Planchon–Darboux) | Static "how deep could water pond" on the finished terrain | 0.14 m |
| Warp 2D on finished terrain | Cut, fill and structure walls on a 2 m grid; rain plus upstream inflow; local-inertial shallow water on the GPU | 0.35 m |
On the finished terrain, plan C had 3 dangerous facilities: the clearwell (0.35 m), the sludge basin (0.68 m), and an overtopped washwater basin. The "danger" threshold was fixed before running: apron depth ≥ 0.30 m or overtopping.
The check also exposed two defects in the design tool:
- Ancillary tanks had no flood constraint at all.
- One rule placed the washwater basin's wall top 2 m below the surrounding grade.
3. Feed it back — the ranking flips
The simulated water surface goes back into the design tool as a constraint. The tool re-solves the inlet level and finished grades, and the plan is simulated again until no facility is in danger. I call this deterministic repair GDR.

Plan C needed its inlet level raised by 0.95 m, and its LCC rose to 1.821 bn KRW. The current plan A (1.802 bn) is ahead again.
I then ran the GA again with flooding inside the objective. It found plan D (1.7998 bn, no dangers): the same arrangement as C, moved 27 m upslope.

The unit costs are assumed and the gaps are 0.1–1 %, so "A wins" or "D wins" would be overclaiming. The honest conclusion is that C's advantage existed only before the flood check.
4. Can a home-made solver be trusted? HEC-RAS cross-check
I rebuilt the same case in US Army Corps of Engineers HEC-RAS 7.0.2 2D, using the same terrain, rain, inflow and 2 m cells. The project files were written directly and run from the command line, with no GUI.

- Flooded-area IoU 0.94 (pre-set threshold 0.70).
- Danger verdicts agree at 14/14 facilities. Clearwell 0.348 vs 0.361 m; sludge basin 0.680 vs 0.688 m.
- One miss by the strict criterion: at one shallow apron (GAC, 0.12 vs 0.28 m), the difference exceeded the pre-set tolerance. The cause is not yet identified.
- Run time: HEC-RAS took 4 min on CPU; Warp took 4.7 s on an NVIDIA GB10.
Verification also caught a bug in my own solver. Kit's bundled Warp (1.14) at first gave answers up to 2.2 m different from Warp 1.18 outside Kit. Loading Kit's Warp package outside Kit showed the two versions were bit-identical, so the version was not the cause.
The real cause was a time step at its stability limit next to vertical walls: the same plan gave different answers alone than in a batch. With CFL reduced to 0.5, the solver matched a float64 reference within 0.001 m and converged under further refinement. Every stage was then re-run. A solver verified on terrain without walls is not verified for terrain with walls.
5. OpenUSD as the source of truth, Omniverse Kit as the review stage

- One file, many plans: each plan is a variant in a
planVariantSet. Switching plans in Kit takes 1.0 s. - Design numbers as attributes: every facility's water level, grade, wall top and flood result are stored as
wtp:*attributes. - Checked on read-back: reading the file back in Kit and comparing 150 values against the pipeline gave 0 mismatches. The numbers on screen are the numbers that were computed.

The same Warp kernel inside Kit and outside differs by at most 0.0002 m, so the answer can be produced inside the review tool. Recomputing a new plan inside Kit is about 10× slower, though: 49 s against 4.7 s standalone. Time scales with step count, about 2 ms per step instead of 0.15 ms.
My working hypothesis is kernel-launch latency while Kit holds the GPU: the solver issues about 10 small launches per step. I tried render throttling, pausing the viewport, CPU affinity and fewer syncs; none helped. Bundling steps into CUDA graphs is the next thing to try.
The practical split today:
- Bulk computation runs outside Kit. All 574 plans plus repairs took 1,278 simulations, about 11 minutes.
- Review happens inside Kit, switching between computed variants.
- The USD attributes are the source of truth.
6. What AI actually did
A variant of the GD–AI Loop: the ground truth for 574 GA plans comes from Warp plus repair. 76 % of them flooded somewhere at first. Four surrogates were trained to predict the apron depth at 14 facilities from design-stage inputs, taking 3–8 ms per plan.


- Accurate on average, wrong at the threshold. Mean error was small (GBM: 0.014 m), but the misses fall near the 0.30 m threshold. No model had zero missed dangers (F1 0.875–0.965). In a safety check one miss is too many, so AI never gives the verdict; Warp re-simulation does.
- Choosing which plans to simulate: re-simulating in order of the original LCC, which is known without any simulation, found the pool's best plan in 10 runs. There was no gap for AI to close.
- Pre-screening GA children: the GA simulated only the GBM's top 20 out of 60 children per generation. It missed the pre-set criterion (≥ 0.5 % better in 2 of 3 seeds; met in 1/3) and used about 2× the simulations.
When one evaluation costs 0.5 s, simply running more simulations beats choosing cleverly. Surrogates earn their place when evaluation is expensive (1 m grids, dozens of storms), alternatives are very many, or a person is waiting for an answer in milliseconds. This task met none of those conditions, and measuring that against criteria fixed in advance is part of the result.
7. Process and tools
The design tool stays the source of truth; simulation and AI are added around it, never in place of it. Each step and the tool behind it:
| Step | Tool | What it does |
|---|---|---|
| Design | Custom Python/NumPy generative-design tool | KDS 57 sizing, hydraulic profile, A* pipe routing, relative-layout GA on 20-year LCC |
| Finished terrain | NumPy | Each layout rasterised to a 2 m grid with cut, fill and structure walls |
| Flood | NVIDIA Warp on an NVIDIA GB10 | 2D local-inertial shallow water, 4.7 s per layout; GPU depression fill as the static baseline |
| Repair (GDR) | The design tool itself | Simulated water levels fed back as constraints, re-simulated until no facility is in danger |
| Review | OpenUSD, Omniverse Kit 110.3 (RTX, headless for frames) | One file: a VariantSet per layout, wtp:* attributes, time-sampled water |
| AI | scikit-learn, PyTorch, NVIDIA PhysicsNeMo | Gradient boosting (quantile), U-Net, FNO, trained on the simulation results |
| Cross-check | HEC-RAS 7.0.2 2D, h5py | Project files written directly, run from the command line, results read from HDF5 |
| Figures | matplotlib | Every figure in this post is generated from the saved results |
Summary

Design calculation is the source of truth. Simulation matters when it changes a decision, and here it did.
- GPU (Warp): re-running water over every layout's own ground became a job of minutes.
- OpenUSD: the design numbers and the 3D model share one source of truth.
- Omniverse Kit: the place where a reviewer sees why a number is dangerous.
- AI: limited to suggesting order, at this cost scale.
Every pass/fail criterion was written to a file before running.
Open items:
- the shallow-apron difference against HEC-RAS
- CUDA graphs for recomputation inside Kit
Coming next, short technical notes: running HEC-RAS 2D without the GUI, and practical traps when running Warp inside Omniverse Kit.
댓글
댓글 쓰기