The problem
Wall shear stress is the drag blood exerts on an artery wall, and where it stays persistently low is where atherosclerotic plaque forms. It cannot be measured in a patient — it has to be simulated, and a proper 3D CFD solve costs hours of CPU per geometry. That puts it in overnight-batch territory and out of reach of anything interactive.
What we built
hemoflow predicts the full wall-shear-stress field over a stenosed artery — 8,192 values on a 128×64 surface grid — in about 5 ms, served behind a FastAPI endpoint with an interactive demo you can drag.
Every vessel is reduced to a centerline and a radius field, described by twelve rotation-invariant dimensionless features built in a parallel-transport frame. A rotated artery is the same artery by construction rather than by training, which spends zero parameters on an invariance a network would otherwise have to learn from a few hundred geometries.
How we built it — the network never predicts pascals
Every feature we give the network is dimensionless. That is what makes the representation transferable across vessel calibres, but it throws absolute scale away:
$$\tau = \frac{4\mu Q}{\pi r^3}$$
The Reynolds number carries \(Q/r\); shear needs \(Q/r^3\). No combination of dimensionless features can recover the missing two powers of \(r\). So we compute the analytic Poiseuille field from the radius and flow we already know exactly, and the network predicts only the dimensionless correction on top.
The ablation is the result. Same architecture, same features, same parameter count, same data — two separately trained models differing only in whether the network predicts a ratio or absolute pascals:
| model | params | relative L2 |
|---|---|---|
| MLP, physics prior | 35,585 | 0.031 |
| Poiseuille, analytic | 0 | 0.270 |
| MLP, no physics prior | 35,585 | 0.287 |
A factor of 9.3 — and with the prior off, a fully trained network loses outright to the zero-parameter textbook formula.
We also kept a negative result: a U-Net with 13.8× the parameters is indistinguishable from the MLP on this dataset, and behind it on low-shear Dice and peak error. Our explanation is that two features already carry the upstream history a convolution would have to discover — but we have not run the ablation that would prove it, so we call it a hypothesis.
Challenges
A service test feeding a 2.5-micron vessel came back with an ordinary 2 Pa. That is what exposed the scale problem and motivated the whole design.
Circular topology was the other one: zero-padding the convolutions invents a seam at θ=0 that cuts through the Dean-flow variation the model is supposed to learn. Padding is circular around the circumference and replicated along the axis.
Both bugs produced plausible-looking wrong numbers. Both are now pinned by tests — 80 of them, property-based rather than smoke.
What we do not claim
Our targets come from a reduced-order solver, not a 3D Navier-Stokes run, so every metric measures fidelity to that reference and none of it is a clinical accuracy claim. There is no measured speedup anywhere in the repository — our own reference solver runs faster than the surrogate, because it stands in for the 3D solve that would be slow. Geometries are synthetic single-branch tubes, flow is steady, and the model reports no uncertainty.
What we would do next
Replace the reduced-order reference with real CFD targets from the Vascular Model Repository; add calibrated uncertainty so the service can say when it is out of distribution; extend the representation to bifurcations, where lesions actually concentrate.
Built With
- fastapi
- html5
- javascript
- numpy
- pytest
- python
- pytorch
- ruff
- uvicorn