Aarav Intelligence, a play on AI
A GPU-simulated wind tunnel for learning real aerodynamics, in your browser.
- Overview
- Architecture
- The solver pipeline
- Data model
- How Aarav thinks
- Solver lifecycle
- Validation philosophy
- Status
- Features
- Tech stack
- Getting started
- Project structure
- Design principles
- Roadmap
- License
Aarav is a wind tunnel that only exists in a browser tab. Adjust a rear wing, drop the ride height, deploy a rudder, and the airflow recomputes live, because it is being solved on the GPU in real time rather than pulled from a lookup table.
AARAV WIND TUNNEL, SIDE VIEW
inlet outlet
| |
v v
+-------------------------------------------------------------------------+
| > > > > |
| > > > > _______ |
| > > > > ,----' `----. |
| > > > > / `----___ |
| > > > >/ `------....... (wake) |
| > > > >---------------------------oooo------''''''.... |
| > > > > wheels |
+-------------------------------------------------------------------------+
free-slip tunnel wall, top and bottom, no boundary layer of its own
Aarav, the in-scene AI tutor, watches along with you and explains why a number moved, using the same values you are looking at on screen, not a separate script written in advance.
flowchart LR
subgraph Browser
UI["React UI\nWorkstation"]
Store["Zustand\nScene State"]
Voxel["Voxelizer\ntriangle soup to lattice flags"]
Solver["WebGPU LBM Solver\nD3Q19, TRT, Smagorinsky"]
Field["Field Texture\nvelocity and density"]
Particles["GPU Particle Field\nadvected from Field Texture"]
Readout["Readout and Accuracy Panels"]
end
Tutor["Aarav\nAnthropic API"]
UI -->|slider change| Store
Store -->|geometry changed| Voxel
Voxel -->|flag grid| Solver
Solver -->|macros buffer| Field
Field --> Particles
Solver -->|force accumulator| Readout
Readout --> UI
Particles --> UI
Store <-->|scene context| Tutor
Tutor -->|set_part, focus_camera, highlight| UI
Every simulated frame runs the same four compute kernels, in the same order, inside a single WebGPU command encoder. The order is load bearing: force integration reads the population that collision just wrote, before streaming moves it anywhere.
sequenceDiagram
participant CPU as CPU, JavaScript
participant GPU as GPU, WebGPU compute
CPU->>GPU: submit command encoder
GPU->>GPU: collide (BGK or TRT relaxation)
GPU->>GPU: clearForces
GPU->>GPU: integrateForces (momentum exchange on bounce back links)
GPU->>GPU: stream (pull scheme, halfway bounce back)
GPU->>GPU: boundary (inlet, convective outlet, free slip walls)
Note over GPU: buffers flip, this frame's output becomes next frame's input
GPU-->>CPU: readMacros, throttled every N frames
GPU-->>CPU: readForces, throttled every N frames
CPU->>CPU: ForceIntegrator computes Cd and Cl
CPU->>CPU: applyReadout updates the store
Reference area, drag, and lift are never declared. They are measured from whichever voxel flags and force accumulator the current geometry produced, every time.
classDiagram
class Vehicle {
+string id
+string name
+type: car or plane
+string baseModelPath
+number refArea
+Slot[] slots
}
class Slot {
+string slotId
+string label
+category: wing, diffuser, rideHeight, flap, rudder, aileron, elevator, aoa
+kind: toggle or range
+geometryTransform(value)
}
class SceneState {
+string vehicleId
+number windSpeedKph
+Record slotValues
+SolverTier solverTier
+computed: Cd, Cl, wakeSize, stability
}
Vehicle "1" --> "many" Slot
SceneState "1" --> "1" Vehicle
A new car or plane is added as data against this shape, not as new solver code.
Aarav is not a chatbot with the scene bolted on afterward. Every reply has access to the
current SceneState, and can act on the scene through tool calls rather than only describing
what to do.
sequenceDiagram
participant User
participant Aarav
participant Store as Zustand Store
participant Scene as 3D Scene
User->>Aarav: "why did drag go up"
Aarav->>Store: read current slotValues and computed Cd, Cl
Aarav->>Aarav: reason using the actual numbers on screen
Aarav->>Scene: focus_camera(diffuserSlot)
Aarav->>Scene: highlight(diffuserSlot)
Aarav->>User: explanation grounded in the visible change
useAaravSimulation owns the WebGPU device for the whole session. Its state machine is
simple on purpose, because a silent failure here would be worse than a visible one.
stateDiagram-v2
[*] --> initializing
initializing --> unsupported: navigator.gpu is missing
initializing --> running: device acquired, grid voxelized, solver initialized
initializing --> error: setup threw
running --> error: device lost mid session
unsupported --> [*]
error --> [*]
unsupported and error both render a status banner in the 2D UI layer. Neither state is
allowed to fail silently behind a frozen scene.
Not every check in the suite is allowed to block a build. The distinction is deliberate: a failing gate always means the code is wrong, a failing advisory check can mean reality is inconvenient, and the two must never be treated the same way.
flowchart TB
subgraph Gating["Gates the build, a failure means the code is wrong"]
Conservation[Conservation: mass, momentum, density]
Symmetry[Symmetry: mirrored geometry, mirrored inflow]
GCI[Grid convergence index, per geometry class]
Trends[Trend suite: downforce rises then stalls, never inverts]
Fuzz[Fuzz suite: degenerate geometry never crashes]
Perf[Performance budgets]
end
subgraph Advisory["Reported only, never gates"]
Anchors[Absolute anchors against published data]
Scaling[Reynolds scaling and dimensional analysis]
Golden[Golden field regression]
end
Anchors -.->|"never corrected toward"| Note["A correction multiplier here\nwould turn every trend claim false too"]
This section is not marketing copy. The project's own internal rule is that a tool which is 15 percent off and says so is more useful than one that is 5 percent off and implies it is exact, so this table follows the same standard.
| Piece | Status |
|---|---|
| App shell, UI chrome, 3D viewport | Builds and type checks |
| LBM solver and force integration | Wired to the UI, never run on a real GPU |
| Accuracy and validation harness | Written, never executed |
| Part sliders, wing, diffuser, ride height | Not wired yet |
| Airplane module | Not started |
| WebGL2 fallback tier | Not built, WebGPU only for now |
If this breaks in the console on first load, that is expected, not a regression.
|
Real flow, not animation A D3Q19 Lattice Boltzmann solver runs on WebGPU compute shaders. Streamlines, wake, and separation emerge from the physics instead of being scripted. Tunable parts Rear wing angle, diffuser, independent front and rear ride height, with flaps, rudder, and ailerons planned for the airplane module. |
Aarav, the tutor Scene aware, able to move the camera, highlight a part, and adjust a slider mid explanation instead of only describing what to try. Honesty by design A live accuracy panel reports statistical confidence, resolution, blockage ratio, and Reynolds regime. Accuracy against published data is tracked and never corrected toward. |
| Layer | Choice |
|---|---|
| UI | React, TypeScript, Tailwind CSS |
| 3D scene | React Three Fiber, Three.js |
| Simulation | WebGPU compute shaders, D3Q19 Lattice Boltzmann |
| State | Zustand |
| AI tutor | Claude, Anthropic API, backend integration pending |
npm install
npm run dev # http://localhost:5173, needs a WebGPU capable browser
npm run typecheck # tsc --noEmit
npm run build # production build into dist/src/
components/ UI chrome and 3D scene components
engine/
webgpu/ LBM compute kernels and solver class
voxel/ triangle to lattice voxelization
geometry/ geometry helpers
render/ particle field, flow texture
store/ Zustand scene state
validation/ accuracy harness, conservation, symmetry, GCI, trends
docs/ spec addenda for the turbulence model and wall functions
plans/, prompts/ the planning documents this project grew from
- No correction multipliers, ever. If an output needs to be multiplied to match a published value, the multiplier is defined by the answer it produces, not by physics.
- Trends must never invert. More wing angle must always cost more drag. A wrong trend is a bug, not a rounding error.
- Uncertainty is always stated, and the disclaimer does not shrink as the numbers improve.
- A missing citation is reported as a gap, not filled in with a plausible looking estimate.
- Absolute accuracy against real world data is a diagnostic, not a target this build gates on.
- Phase 0, render pipeline and placeholder vehicle
- Phase 1 partial, LBM solver wired to a live readout panel
- Part and slider wiring with re-voxelization
- WebGL2 fallback tier
- Airplane module, flaps, rudder, ailerons, stall behavior
- Aarav backend, real Anthropic API tool calling into the scene
Not yet chosen. Pick one before publishing this repository.