MaxInfil.One curve per storm depth, using the soil and surface settings in the left rail. Horizontal dashed lines are the TR-55 table values for the selected hydrologic soil group. The dot marks your current bowl depth and storm.
A bowl of fixed depth does not produce a fixed CN. Small storms partly fill it and look benign; large storms overtop it and the fitted CN climbs toward an asymptote set entirely by the total available storage. This is the "violent" pattern Hawkins described in asymptotic-CN fitting, and it is the opposite of the gently declining CN a deep, rate-limited soil produces.
For a storm much larger than the available storage, every loss term is exhausted and total losses approach D + dstore. Expanding the SCS equation for large P gives total losses of (1 + λ)S, so the fitted S converges on (D + dstore)/(1 + λ). That single number is the ceiling on how low the apparent CN of a compacted lawn can ever go.
The practical question runs the other way. A gauged urban catchment calibrates to a CN well above anything in the TR-55 tables. How deep would the bowl have to be to explain it?
Depths are what the current soil settings require to reproduce each CN at the selected storm depth. A dash means that CN is unreachable with these soil parameters — no bowl depth produces it.
Verified against EPA SWMM 5.2.4 compiled from source on
2026-07-27. Under MODIFIED_HORTON, any non-zero MaxInfil seals the
subcatchment: the same 3-inch Type II storm infiltrated 0.001 in whether MaxInfil was set to
0.5, 5, 50, or 500 inches, while the identical model with MaxInfil = 0 infiltrated 1.371 in
normally. The cause is visible in infil.c: line 545 clamps the state variable with
Fe = MAX(Fe, Fmax) where MIN is clearly intended, so Fe
jumps to the cap on the first wet step and the guard at line 534 returns zero from then on.
Under plain HORTON, MaxInfil behaves exactly as a volume cap.
Horton with a finite MaxInfil. This is the physical model.
The same site as a jurisdiction's CN spreadsheet would see it.
SWMM's CURVE_NUMBER infiltration is not the TR-55
event equation. It derives a soil storage capacity from CN and depletes it during the storm, with
no explicit 0.2S initial abstraction. Measured against the algebraic SCS result on a Type II
24-hour storm in SWMM 5.2.4:
So there are three answers in play, not two: what the bowl physically does, what the SCS equation says at the apparent CN, and what SWMM's CN option returns when you type that same number in. Model B above is generated for you to run against Model A and see the gap on your own parameters.
The model below is run through genuine compiled engines — EPA SWMM 5.2.2 and OpenSWMM 6.0.0-alpha.2, both as WebAssembly. Nothing here is a re-implementation. The engines are fetched on demand, so this tab needs a connection the first time and will stay offline inside a sandboxed preview; deploy the file and it works.
No runs yet.
Run an engine to read its results file.
SWMM5 comes from @fileops/swmm-wasm-web@0.0.4
(MIT), a genuine EPA 5.2.2 build with the wasm inlined. SWMM6 is the OpenSWMM engine
(MIT, Caleb Buahin 2026), loaded as the prebuilt pair published in the LocalSWMM project and
pinned to one commit so the bytes cannot change under you.
Both engines run on the page's main thread, so a large model will freeze the tab while it computes — these bowl models are 480 reporting periods and finish in well under a second. A production tool should move this into a Worker.
The two .out files share a byte layout: the same magic number, the
same element and variable counts, the same bytes per reporting period. Only the version stamp
differs, 52002 against 60000. That is what lets one parser read both, and it is why the
comparison above is a like-for-like read rather than two different readers being trusted to
agree.
Dr. Shirley Clark, Distinguished Professor of Environmental Engineering at Penn State Harrisburg, posted the observation this app is built on. Her argument, in summary: land development grades the whole site, leaving a broad compacted layer of near-zero permeability; topsoil and grass go on top after the buildings and roads are in; green infrastructure may punch through the compacted layer, but the rest of the site keeps it. The lawn is not as pervious as the plan set implies. Horton in SWMM can carry a compaction-layer storage depth. The CN method has no place to put one, and jurisdictions lean on CN. Her point about the literature — urban watersheds calibrating to CN values above the TR-55 tables — is what tabs 2 through 4 are for. She has been building the curves that link storage depth to apparent CN; this is an independent implementation of that idea, not a reproduction of her results.
The capacity curve is the volume-indexed form SWMM calls
modified Horton, which avoids the classic error of advancing along the Horton curve during
periods when rainfall is lighter than the soil could accept. The bowl is a hard cap on stored
water, matching SWMM's MaxInfil under the HORTON option. With the
leaky-bowl box ticked the bowl also drains at f∞, which is closer to what a real compaction
layer of finite conductivity does over a long storm; leave it unticked to reproduce SWMM
exactly.
The two lines at the bottom are diagnostics rather than parts of the solution. The first is what the soil could take if water were ponded on it continuously for the whole storm — the number the limiter badge compares against, and the reason a deep bowl sometimes changes nothing. It is a finite-duration expression on purpose: the T → ∞ shortcut f∞·T + (f0 − f∞)/k overstates the potential by 350% on a half-hour storm with a slow decay constant. The second comes from expanding the SCS equation for large P, which gives Q → P − (1 + λ)S, so the fitted S converges on (D + d_store)/(1 + λ). Both are evaluated in closed form.
The CN inversion is exact, not fitted. For λ = 0.2 it reduces to the familiar S = 5[P + 2Q − √(Q(4Q + 5P))]. When runoff is zero the inversion returns S = P/λ, which is an upper bound on CN rather than a fit — the app labels those points and dashes those curve segments.
EPA SWMM 5.2.4 was compiled from source and run on the exact
model this app generates: one acre, fully pervious, Type II 24-hour storm, P = 3.00 in,
f0 = 3.0 in/hr, f∞ = 0.02 in/hr, k = 4.0 /hr, depression storage 0.10 in. With
HORTON and MaxInfil stepped through 0.10, 0.25, 0.50, 0.75 and 1.00 in, SWMM's
reported infiltration equalled the cap to three decimals and its runoff depth matched this
app's to within 0.004 in — between 0.14% and 0.21% — giving apparent CNs of 98.25, 96.89,
94.47, 91.83 and 88.95 against the app's 98.28, 96.92, 94.51, 91.88 and 89.00.
The metric exports were checked the same way. Switching
to SI writes a CMS model with rainfall, infiltration parameters and
MaxInfil in millimetres, area in hectares and lengths in metres; SWMM ran those
files clean and returned runoff depths within 0.005 mm of 25.4 × the matching US run at bowl
depths of 6.35, 12.70 and 25.40 mm.
Three honest limits. First, that agreement holds while the bowl is the binding
constraint, which is the regime this app is about. When the bowl is deeper than the soil could
absorb anyway, the run becomes rate-limited and the app's volume-indexed capacity curve lands
between SWMM's two Horton options — at MaxInfil = 1.50 in on the same model, SWMM's
HORTON gave 1.836 in of runoff, its MODIFIED_HORTON gave 1.630 in, and
this app gave 1.675 in. The limiter badge on tab 1 tells you which regime you are in.
Second, this is a volume model. Runoff leaves the surface as soon as depression storage is exceeded, with no overland routing, so the app has nothing to say about peak flow or timing — only about the volume that CN is meant to predict.
Third, the Type II ordinates carry a known discrepancy at hour 11.75: the 1973 TP-149 tabulation gives 0.387 where Chow and most TR-55-era reproductions give 0.357. Both are selectable in the distribution list, because the peak intensity that follows is exactly where a rate-limited soil is most sensitive. Type I, IA and III are deliberately absent rather than transcribed from an unverified source.
Each slider has a numeric box beside it for exact entry, and the computational time step is selectable from 1 to 15 minutes — the apparent CN moves by less than 0.1 across that whole range on the default case, which is the convergence check worth running before you trust any particular setting. Copy setup link encodes the entire configuration into the URL so a specific case can be sent to someone else, and Reset returns everything to the defaults. Tabs respond to the arrow keys, Home and End.
Hovering any control shows what it does and why it matters; the same text is
wired to the control through aria-describedby, so it reaches a screen reader
whether or not the visual tooltip ever appears. Keyboard focus raises a tooltip too, and
Escape dismisses it.
The theme control offers Dark, Light and Auto. Dark is the default and what the app boots into. Auto hands the decision to your operating system's colour setting and keeps listening — change the system theme while the page is open and the app follows immediately, no reload. Whichever you pick is remembered where the browser allows it, travels in the shared link, and never touches a computed number.
The last row is the one worth sitting with. A newly graded area with no vegetation is already CN 86 on B soils. The whole premise of the "open space, good condition" line at CN 61 is that the profile beneath the grass behaves like a B soil. If the grading crew left a bowl, it does not.