# Validation Report — Petrel Flow Accumulation Layer v0.3 Global (DEM-derived) ## Validation status: quantitative at reference gauges v0.3 is validated against **published upstream drainage areas at nine reference gauges on eight continents' major rivers**, including three closed (endorheic) basins. This is a direct test of the quantity the Layer computes: if the model routes water correctly, the contributing area it reports at a gauge must match the area hydrologists have measured for that gauge. It is **not** a cell-wise benchmark against an independent hydrography, and it is not a discharge validation. See *What v0.3 does not establish*. ## Method For each gauge, the maximum contributing area within **±0.10°** of the published gauge coordinates is compared to the published upstream area. The window is deliberately tight: a wide window finds the river further downstream and biases the result high. Any basin reading **above 110%** is treated as proof of a specific defect and blocks the build; the checks below were each found that way. ## Results | Gauge | published upstream area | v0.1 | v0.3 | |---|---|---|---| | Amazon @ Óbidos | 4,680,000 km² | 5.6% | **99.8%** | | Congo @ Kinshasa | 3,475,000 km² | 19.3% | **97.3%** | | Mississippi @ Vicksburg | 2,964,000 km² | 8.9% | **99.4%** | | Nile @ Aswan | 2,900,000 km² | 2.5% | **96.6%** | | Volga @ Volgograd | 1,360,000 km² | — | **100.4%** | | Ganges @ Hardinge Bridge | 950,000 km² | 3.0% | **100.3%** | | Danube @ Ceatal Izmail | 807,000 km² | 14.2% | **98.2%** | | Amu Darya @ Kerki | 309,000 km² | — | **94.3%** | | Ural @ Atyrau | 231,000 km² | — | **90.0%** | v0.1 derived flow per 10° tile, so any catchment crossing a tile boundary was truncated; it captured 2.5–19.3% of true drainage. v0.3 reconciles the tiles. ## Defects this validation caught **1. Drainage was counted in cells across latitude seams.** A grid cell is a different area at every latitude, and exporting a cell count across a north–south tile boundary re-counted it at the neighbour's cell size. The Mississippi read **108.6%** (it flows south, into larger cells) and the Nile **90.0%** (north, into smaller cells). Both had looked like acceptable noise for a week; the over-count is what named the defect. Drainage is now carried in area units across every seam, and both gauges moved to 99.4% and 96.6%. **2. A reservoir severed the Volga.** The Volga/Kama confluence lies inside the Kuybyshev Reservoir on a tile seam, and flat water gives the DEM no gradient to route by, so the mainstem was sent east across the seam. Volgograd read **15.5%**. With the eight Volga/Kama reservoirs treated as flow nodes it reads 100.4%. **3. The global version of that treatment was rejected on measurement.** Applying reservoir nodes to all 2,775 lakes ≥ 50 km² fixed the Volga (89.6% at that stage) and **broke four other basins** at floodplain lakes the carve could not place an exit for: Amazon 36.4%, Mississippi 24.3%, Nile 34.1%, Danube 0.6%. It is not shipped. Nodes are applied only where the DEM provably mis-routes a river. **4. Reservoirs read as "no river" until the previews were inspected.** The promote audit passed the bundle — 12 assets, 0 warnings — while the Volga corridor rendered as a bright band meaning *up to 3 km from the nearest river* along the river itself: a reservoir's cells are pits in the propagation, so they fell below the channel threshold. Rybinsk centre read 0 m before and 8,393 m after. Each reservoir is now filled with the contributing area passing through it, checked against its independent HydroLAKES watershed: | body | through-flow assigned | independent watershed | |---|---|---| | Rybinsk Reservoir | 155,766 km² | 150,074 km² | | Volgograd dam reach | 1,364,951 km² | 1,360,000 km² (gauge) | ## The 50 km cap, and exactly where it binds `distance_to_drainage` is encoded in uint16 at 0.763 m per count, so 50 km is the top of the range — one step below the NoData value. Values are clipped there, and the clip **is** reached. Counted at native resolution over the whole raster, not on a decimated sample: | | cells | area | |---|---|---| | at the 50 km cap | **1,683** | **118 km²** | | 49.5–49.95 km | 25 | | | 47.5–49.5 km | 63 | | | 45–47.5 km | 321 | | | scored land | 2,462,761,039 | | The cap holds 67× the bin below it — a pile-up, not a tail — but it censors **0.00007% of scored land**. **What is censored is not deserts.** Sampled locations are the Coral Sea cays, the Bahamas, the north-west Hawaiian atolls, the Marianas and Persian Gulf islands. Each is an isolated patch of **1–4 km²**: 12 to 50 valid cells within 25 km, every one reading exactly 50,000 m. They are islands too small to contain a single cell with 1 km² of contributing area, so **no channel exists anywhere on them** and the distance transform saturates across the whole island. By contrast the Amazon control has 32,761 cells within 25 km and a minimum of 0 m. ### The cap also bled into the ocean in the overviews Because 50 km encodes to 65534 and NoData is 65535, and the cells that reach the cap are 1–4 km² islands surrounded by ocean, **bilinear overview building blended the two**: each coarser level drove the blend toward 65535 and landed on 65534, which on this band is a legitimate 50,000 m. Measured on this product before the fix: | overview | spurious near-cap pixels | share of valid | |---|---|---| | ×16 | 1,391 | 0.014% | | ×32 | 1,135 | 0.044% | | ×64 | 908 | 0.133% | Every sampled one was NoData at native resolution — Coral Sea, Gulf of Mexico, Arctic Ocean. The share grows with level because each pass re-blends the previous one. It mattered beyond bookkeeping: previews and the API's tile server both read overviews, so zoomed-out views of a *distance-to-land-drainage* layer carried scattered bright dots over open sea. Bilinear was also inventing valid pixels generally, not just capped ones: 4.2% of the ×16 valid count was ocean blended into data. The distance band now builds **nearest** overviews (`overview_resampling: nearest`). After the change: 3 near-cap pixels at ×16, 0 at ×32 and ×64 — and all three are real one-to-three-cell islands, verified against their native cells. TWI keeps bilinear: its capped cells are inland, and it measures 0 near-cap at every level. So on a small island the value means *"no modelled channel on this land"*, not *"50 km to the nearest river"*. Deserts are not affected: organised drainage exists within 50 km almost everywhere in the Sahara, Arabia and the Australian interior. Setting such islands to NoData instead of the cap is a candidate for the next vintage. ## Automated product integrity (promote audit) The promote audit machine-checks every bundle: encoding tags (`PETREL_SCALE`, `PETREL_COAST_CLIP`), overview pyramids, required documentation, value ranges (distance ≤ 50 km, TWI ≤ 35), and mask correctness (Antarctica, open ocean and closed-basin sinks NoData; coastal land resolves to data). These are integrity checks on the shipped rasters. As finding 4 above shows, **a passing audit is not evidence of hydrological correctness** — the gauge measurement and the preview inspection are. ## What v0.3 does NOT establish - **No cell-wise benchmark against an independent hydrography.** Channel-overlap and distance-to-drainage correlation against HydroSHEDS v2 (CC BY 4.0, Americas-only) is the next validation step. - **No discharge / gauge-flow validation** against observed river flow. - **No DEM-artefact audit.** GEDTM30 voids, residual urban bias and water-body flattening propagate into flow paths and were not systematically assessed. - **No validation of lakes outside the Volga/Kama cascade.** Every other lake keeps DEM routing: drainage entering a lake is conserved, but where it leaves may differ from the true outlet. ## Known limitations 1. **Two basins under-count.** The Ural reads 90.0% at Atyrau and the Amu Darya 94.3% at Kerki: DEM routing through flat steppe and irrigated delta terrain loses tributary area at a few points. Not corrected in v0.3. 2. **Residual unsettled tiles.** A drainage divide along a tile boundary can make two tiles feed each other; a handful of island tiles creep by under 0.1% of their inflow per round and the build accepts that residual. The structural fix is a boundary-cell DAG. 3. **Lakes other than the Volga/Kama cascade keep DEM routing** (see above). 4. **Distance far-tail cap.** Distance-to-drainage is capped at **50 km**, the top of its uint16 encoding. The cap binds on 1,683 cells (118 km², 0.00007% of land), all of them small islands and cays carrying no 1 km² channel — read those as "no modelled channel here", not as a distance. See the section above. 5. **TWI saturates, and the v0.1 low bias is retired.** v0.1 read 1.2–2.6 units low on major basins, because TWI is a logarithm of an under-counted area. With v0.3's capture the residual implied by the same arithmetic is **under 0.11 units** at the worst tested basin (Ural) and under 0.04 on the Amazon, Congo, Ganges, Danube and Mississippi. Separately, TWI is capped at **35** and that ceiling is reached: measured across five basin windows (91.5 M cells), 0.130% of land cells and **12.9% of cells carrying more than 1000 km²** sit at the cap — Amazon 2.5%, Mississippi 2.2%, Ganges 0.7%, Congo 0.7%, Volga 22.9%. The Volga is the outlier because 98.8% of its capped cells are reservoir surfaces, where flat water carrying the whole river makes `ln(area / tan slope)` saturate by construction. Where the magnitude of drainage matters, read contributing area rather than TWI. 6. **278 m native resolution.** Channels below the 1 km² threshold are unresolved; not for reach-scale hydraulic work. 7. **Coverage:** global land 60° S – 84° N. Ocean is NoData (GSHHG-f coast clip, `all_touched`); Antarctica is excluded by Petrel standard. ## How to validate locally 1. Overlay the derived channel network on satellite imagery or a national hydrography and check the channels track real river lines — including through lakes and reservoirs. 2. Compare distance-to-drainage against a local river-distance layer if you have one. 3. If your region contains a large lake or reservoir outside the Volga/Kama cascade, check where the river leaves it before relying on downstream drainage there. 4. Report systematic artefacts to layers@petreldata.io. ## References - Bartos, M. (2020). pysheds: simple and fast watershed delineation in Python. https://doi.org/10.5281/zenodo.3822494 - Barnes, R. (2017). Parallel non-divergent flow accumulation for trillion cell digital elevation models on desktops or clusters. *Environmental Modelling & Software*, 92, 202–212. https://doi.org/10.1016/j.envsoft.2017.02.022 - Ho, Y.-F., Hengl, T., et al. (2025). GEDTM30: global ensemble digital terrain model at 30 m. *PeerJ* 13:e19673. https://doi.org/10.7717/peerj.19673 - Messager, M. L., et al. (2016). Estimating the volume and age of water stored in global lakes. *Nature Communications* 7: 13603. https://doi.org/10.1038/ncomms13603 - Wessel, P., & Smith, W. H. F. (1996). A global, self-consistent, hierarchical, high-resolution shoreline database. *JGR*, 101(B4), 8741–8743.