No file loaded

Drop an .fds file here to visualize geometry in 3D.

WASD Move QE Up/Down Rotate 16 Views R Reset
Selected Object
Clip
X
Y
Z

Load an .fds file to view mesh resolution and parallel setup.

Load an .fds file to view fire & combustion properties.

Load an .fds file to view the full source code.

FDS Viewer — User Guide

A browser-based viewer for Fire Dynamics Simulator inputs and outputs.

Quick start

  1. Drop an .fds file on the welcome screen, click Open File, or click Load Sample to try the bundled example.
  2. The model appears on the 3D Geometry tab. Drag with the mouse to orbit, scroll to zoom, right-click drag to pan.
  3. Other tabs come alive once a file is loaded — switch between them to inspect mesh resolution, fire setup, source code, and simulation results.

Use the sidebar on the left of this page to jump to any topic.

3D Geometry

The default tab. Shows the geometry parsed from the .fds file: meshes, obstructions (OBST), vents, holes, devices, geometries (GEOM), HVAC, zones, slice planes (&SLCF), fire sources, and the cell grid.

Left sidebar

  • Layers — toggle visibility of each FDS entity type. Show all / Hide all buttons batch-toggle. Show OBST edges draws a black outline on every obstruction, useful for authoring. Grayscale desaturates the scene.
  • Opacity — ghost the geometry to peek inside.
  • Camera Views — jump to Front, Back, Left, Right, Top, Bottom, Iso. Reset re-fits the model.
  • Background — six preset colours. The theme toggle in the top-right also flips the background between dark blue and light grey.

Clip bar (bottom)

Six sliders (one min/max per axis) clip the scene to a sub-volume. Drag the handles, type a value, or use the ▲/▼ step buttons. Click Reset to clear the clip.

Click-to-inspect

Click any visible OBST, VENT, HOLE, DEVC, GEOM, HVAC, ZONE, INIT or fire source to highlight it and open a floating info panel with its parameters and raw FDS namelist.

Walk Mode (FPS)

First-person navigation through the model — useful for understanding scale and seeing how rooms connect from inside.

  1. Click Enter walk mode in the sidebar.
  2. Click anywhere on a floor or top surface to teleport there at eye height (1.7 m default, adjustable).
  3. Use WASD to walk, the mouse to look around. Shift sprints, Space jumps, Esc exits walk mode.

The walker is gravity-bound and collides with OBST/GEOM surfaces. Eye height and walk speed sliders let you tune the feel. The same control is also available on the Output tab.

Mesh

Parallel-friendly mesh diagnostics:

  • Per-mesh cell sizes and total cell counts
  • Cell aspect ratios — flags meshes where dx/dy/dz are unbalanced
  • MPI process breakdown if MPI_PROCESS is set
  • D*/dx resolution analysis for fire sources, comparing the modelled cell size against published guidance for the peak HRR

Fire & Combustion

Pulls everything fire-related into one view:

  • Combustion Reaction — fuel species, heat of combustion, soot/CO/CO₂ yields, radiative fraction, and a rendered combustion equation for simple hydrocarbons.
  • Fire Sources — every SURF with HRRPUA or MLRPUA, its growth (t² / exponential / explicit ramp / steady), vent area, and peak HRR.
  • HRR Preview — tiny inline charts of each fire's heat release curve.
  • Materials — SURFs that reference MATL layers, with burn indicators and thicknesses.

Code

Full source of the loaded .fds file with line numbers, comment/namelist syntax highlighting and a search bar.

  • Copy all — copy the whole file to clipboard.
  • Save annotated — export a copy with ! ⚠ … comments inline for every static-linter finding (helpful for sharing reviews).
  • Edit — switch the source pane to a text editor, edit, then click Apply & reload to re-parse the modified file in place.

Output

Visualises FDS simulation results in 3D, overlaid on the geometry. Three independent data modes — switch via the Soot / Slice / Boundary buttons at the top of the right sidebar.

Soot — 3D smoke (volume ray-march)

Click Open simulation folder and pick the directory of the FDS run (must contain the .smv file and at least one .s3d file). The viewer parses .smv to detect what's available, lists it under Detected Smoke3D, then waits for you to commit to loading the heavy binary frames.

Controls reference
Quantity
Which smoke3D quantity to render. Soot shows particulate density (grey smoke). HRRPUV shows heat release rate per unit volume (orange/red flames). Soot + HRRPUV renders both layers blended — only available when both files are in the folder.
Load selected data
Triggers the actual decoding. Each .s3d file is RLE-decompressed frame by frame (this is the slow part — tens of seconds for a long simulation) and uploaded to the GPU as a 3D texture. After this completes the playback, sampling, and threshold controls become interactive.
Rendering
Solid-aware (default) does two render passes per frame — first the opaque scene to an off-screen depth target, then the smoke with the depth texture bound as a uniform. The ray-march stops when each sample crosses a wall: if sampleViewZ > sceneViewZ  → break Basic skips the depth pass. Faster, but the smoke ignores OBSTs (can leak through walls).
Play / time / fps
The Play button toggles automatic frame advancement (one data frame every 220 ms). The time readout shows the simulation time of the current frame. The fps readout is the actual render frame rate of the 3D viewer — not the data rate. (Data rate is typically 3–5 frames per simulation second, capped by DT_S3D in the &DUMP namelist.)
Sampling
Number of ray-march samples per pixel through the smoke volume: Full = 200  |  Balanced = 120  |  Fast = 60  |  Coarse = 24 Each step length is dt = (rayExit − rayEntry) / steps. Because the shader applies path-length opacity correction, overall brightness is preserved regardless of step count (Beer–Lambert): doubling dt doubles the opacity per sample, halves the sample count, total stays the same. What changes is fine detail — at low step counts you'll see ray-band artefacts at thin features.
Smooth motion between frames
Per-render byte interpolation between consecutive data frames: data[i] = (1 − t) · A[i] + t · B[i],  t = elapsed / 220 ms A is the current data frame, B is the next. Hides the discrete ~3 fps data rate as continuous motion. Visual fabrication — not a real simulation state. Pause detection auto-clamps t to 0 when no frame change has happened recently.
Soot threshold / HRRPUV threshold
Minimum byte value (0–255) below which a voxel contributes nothing. Uses a smooth fade band (~16/255 wide) instead of a hard cutoff to avoid blocky cell-boundary clipping: thresholdFade = smoothstep(threshold,  threshold + 16/255,  raw) The sample's alpha is multiplied by thresholdFade.

Byte ↔ kW/m³ for HRRPUV. FDS quantises the HRRPUV field to 0–255 against the HRRPUV_MINMAX range stored in the .smv file. The byte the slider drives maps back to a physical value with:

byte = round((kW − HRRPUV_MIN) / (HRRPUV_MAX − HRRPUV_MIN) × 255)

Worked example for a run with HRRPUV_MINMAX = 0, 1200 kW/m³:

  • Smokeview's default cutoff is 200 kW/m³ (HRRPUVCUT). 200/1200 × 255 ≈ byte 43 — so a slider value of ~43 matches Smokeview.
  • Slider 0 — show every cell, even tiny flickers.
  • Slider 255 — only the most intense cells (= HRRPUV_MAX).

The kW/m³ readout next to the slider does this conversion live for whatever HRRPUV_MINMAX your loaded data has. The Smokeview default (200 kW/m³) button sets the slider to whatever byte value lands at 200 kW/m³ for that range.

Soot opacity / HRRPUV opacity
Global opacity multipliers in [0, 1] for each quantity. They scale the final α before front-to-back accumulation. Useful for ghosting one layer while keeping the other strong.
Soot extinction  (default 0.20)
The constant baseline term bs in the soot alpha equation (see below). Raises opacity uniformly — smoke gets denser everywhere, including in low-data regions.
Curve exponent  (default 0.82)
The exponent es applied to the raw data value before contributing to alpha. Controls contrast:
  • es < 1 — high values dominate (high contrast, sparser look)
  • es = 1 — linear response
  • es > 1 — low values lifted (smoother gradient, less dramatic peaks)
Density gain  (default 7.20)
The multiplier gs on the data-driven term. Scales how strongly the actual smoke density drives opacity.
Fire base  (default 0.12)
Constant term bf in the fire (HRRPUV) alpha equation — baseline opacity at zero intensity. Same role as Soot extinction but for the HRRPUV channel.
Fire exponent  (default 1.10)
Exponent ef applied to the normalised intensity t. Controls how sharply flames ramp up as intensity rises (lower → brighter low-intensity glow, higher → only the hottest cells light up).
Fire gain  (default 5.40)
Multiplier gf on the data-driven term — overall fire intensity. Same role as Density gain but for the HRRPUV channel.
The soot opacity equation, all together

For every ray-march sample, the contribution α is:

αsoot = 1 − exp(−(bs + rawes · gs) · opacity · pathLength)

with bs = Soot extinction, es = Curve exponent, gs = Density gain, opacity = Soot opacity, pathLength = dt × volume world size in metres along the ray, and raw ∈ [0, 1] the per-cell density normalised from byte.

The fire (HRRPUV) channel uses the same form with its own three sliders:

αfire = 1 − exp(−(bf + tef · gf) · opacity · pathLength)

with bf = Fire base, ef = Fire exponent, gf = Fire gain, and t = (raw − threshold) / (1 − threshold) the normalised intensity above the HRRPUV threshold. The defaults (0.12 / 1.10 / 5.40) reproduce the previously hardcoded flame look — tweak the sliders if your run's HRRPUV range needs more or less aggressive transfer.

Composing the final pixel

For each accumulating sample, the alpha is multiplied by every gate before being blended:

αfinal = αsoot/fire  ×  thresholdFade  ×  depthFade  ×  edgeFade

depthFade is only active in Solid-aware mode — it tapers the last ~30 cm before a wall to a soft boundary instead of a hard cut. edgeFade fades the very edges of each volume box to avoid hard texture-clamp seams between adjacent meshes. Front-to-back compositing then accumulates colour and alpha with the usual accum += (1 − accum.a) · color · α until accum.a saturates or the ray exits the box.

Slice — 2D cross-sections

Load individual .sf files or a whole simulation folder. Multi-mesh slices are auto-stitched in physical space (per-mesh duplicates at shared boundaries are de-duplicated). Pick a slice set from the dropdown, then play through frames. Colour map, range, and opacity are all adjustable.

Boundary — surface heatmaps on OBSTs

Open a folder containing .bf files. Each surface patch is rendered as a textured quad over the corresponding OBST face. Same play/colour/range controls as slices.

Keyboard shortcuts

KeyAction
16Front / Back / Left / Right / Top / Bottom view
0Iso view
RReset camera
W A S DPan (orbit mode) / walk (walk mode)
Q EPan up / down
Rotate around the target
ShiftSprint (walk mode)
SpaceJump (walk mode)
EscExit walk mode / close modal

Troubleshooting

Viewer issues

  • Smoke leaks through walls — switch Rendering from Basic to Solid-aware.
  • Smoke disappears behind OBSTs in Solid-aware — a known trade-off of single-pass volume rendering; fall back to Basic if the smoke needs to read everywhere.
  • Choppy smoke playback — tick Smooth motion between frames. The data rate is typically 3–5 frames per simulation second.
  • "Invalid Smoke3D record length" on load — the .s3d file is truncated. The viewer recovers automatically: every frame up to the corruption is shown, the rest is skipped.
  • Slice shows banded duplicates — this was fixed: multi-mesh slices are now stitched by physical position, not by stride.
  • FPS counter low — drop Sampling from Full to Coarse, or switch Rendering to Basic. Walk-mode raycasting also adds load on huge models.

FDS simulation issues

Problems with the simulation itself — .fds input syntax, mesh / cell sizing, ramp errors, missing namelists, MPI / OpenMP, run-time ERROR(NNN) messages from FDS, or unexpected physics — are FDS issues, not viewer issues. The official documentation is the right starting point:

When asking for help on the FDS community channels, attach a minimal reproducing .fds file and the relevant lines from the .out log.

Issue not listed? Want a new feature?

For issues with this viewer (rendering, UI, file parsing), report bugs and request new features on the GitHub issue tracker:

github.com/ProfRino/fds-viewer/issues

When reporting a bug, please include:

  • What you were doing and what you expected to see
  • The browser and OS you're using (Chrome 130, Windows 11, etc.)
  • A screenshot if the issue is visual
  • The .fds file or a minimal example that triggers it, if possible

Load an .fds file from the 3D Geometry page to see the geometry here in greyscale.

Then use the right panel to load slice data (.sf files).

0.000 s
Clip
X
Y
Z