From cbc8c37f96993405ea98be60317dfd1d20ff54ed Mon Sep 17 00:00:00 2001 From: Antonio Leblanc Date: Wed, 11 Nov 2026 12:50:04 -0300 Subject: [PATCH 1/2] docs: second pass on claims that do not match the code Drop defaultFuelType (nothing reads it) and the Kcurv/beta columns from the WindDriven examples (it only uses vv_coeff). Fix minSpeed, relax and smoothing, document startFire[geojson=...], the mnh3d timeline, Windows/WSL and CMake 3.18 for the sdist, the wasm workflow name and ff-run.bash in CONTRIBUTING. --- CHANGELOG.md | 4 ++++ CONTRIBUTING.md | 5 ++++- README.md | 3 +-- app/forefire/commands.md | 7 +++++-- bindings/python/README.md | 7 ++++--- bindings/wasm/README.md | 4 ++-- docs/source/reference/commands.rst | 5 ++++- docs/source/reference/parameters.rst | 6 +++--- docs/source/user_guide/ensembles.rst | 3 +-- docs/source/user_guide/forefire_script.rst | 6 +++--- docs/source/user_guide/fuels_and_models.rst | 2 +- docs/source/user_guide/mesonh.rst | 5 +++-- docs/source/user_guide/python_arrays.rst | 5 ++--- 13 files changed, 37 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2389b40..2b018b06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,10 @@ history, so they summarise each release rather than list every change. The - `plot[...;filename=*.asc]` writes a valid ESRI ASCII grid: one row per y, north first, at full precision. It used to write one row per x and round values to six significant digits. +- Documentation: removed `defaultFuelType`, which nothing reads, and the + `Kcurv`/`beta` columns from the WindDriven examples, which only use + `vv_coeff`. `minSpeed`, `relax` and `smoothing` now describe what the code + does, and Windows pip users are pointed to WSL. ## [v2.6.0] — 2026-10-26 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 48a18128..cbcf6299 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,7 +70,10 @@ We welcome code contributions, from bug fixes to new features. cmake -S . -B build && cmake --build build -j ctest --test-dir build --output-on-failure - # The script-driven suites (runff, runANN) + # Regression check: compares a real case against the .ref files + cd tests/runff && bash ff-run.bash + + # Every script-driven suite your environment allows cd tests && bash run.bash ``` 7. **Record the Change:** diff --git a/README.md b/README.md index 5e33a1f6..88dc5238 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,7 @@ import pyforefire as forefire from pyforefire.helpers import printToPathe ff = forefire.ForeFire() -ff["fuelsTable"] = "Index;vv_coeff;Kcurv;beta\n1;1.0;1.0;1.0" -ff["defaultFuelType"] = 1 +ff["fuelsTable"] = "Index;vv_coeff\n1;1.0" ff["propagationModel"] = "WindDriven" ff.execute("FireDomain[sw=(0,0,0);ne=(4000,4000,0);t=0]") diff --git a/app/forefire/commands.md b/app/forefire/commands.md index 0406c803..1d8d6307 100644 --- a/app/forefire/commands.md +++ b/app/forefire/commands.md @@ -48,12 +48,15 @@ std::string commandHelp = R"( ## startFire startFire[loc=(x,y,z)|lonlat=(lon,lat,z);t=seconds|date=YYYY-MM-DDTHH:MM:SSZ] - Creates the smallest possible triangular fire front at the specified location and time + startFire[geojson=] + Creates the smallest possible triangular fire front at the specified location and time, or a front along a GeoJSON polygon Example: startFire[loc=(0.0,0.0,0.0);t=0.] + Example: startFire[geojson=ignition.geojson] Arguments: - 'loc': Starting location of the fire (coordinates x,y,z) - 'lonlat': WGS coordinates of the ignition point (lon,lat,z); all three values are required - - 't': Time when the fire is started (in seconds or as an absolute ISO GMT date); + - 't': Time when the fire is started (in seconds or as an absolute ISO GMT date) + - 'geojson': GeoJSON file or inline text (Polygon/MultiPolygon in lon,lat,z); a top-level "valid_at" date sets the time; ## step step[dt=seconds] diff --git a/bindings/python/README.md b/bindings/python/README.md index a55725b3..4cb79d0e 100644 --- a/bindings/python/README.md +++ b/bindings/python/README.md @@ -44,9 +44,10 @@ If you need either, build from source (below). ### Building from source -Any platform without a published wheel — Windows, musl-based Linux, or an -unusual architecture — falls back to compiling the sdist, which needs a C++ -compiler, CMake ≥ 3.15, and the NetCDF C and legacy C++4 libraries: +On Linux or macOS without a published wheel (musl-based Linux or an unusual +architecture), pip compiles the sdist, which needs a C++ compiler, CMake ≥ 3.18, +and the NetCDF C and legacy C++4 libraries. Native Windows is not supported; +use WSL. ```bash # Debian/Ubuntu diff --git a/bindings/wasm/README.md b/bindings/wasm/README.md index 80c528ef..4962a530 100644 --- a/bindings/wasm/README.md +++ b/bindings/wasm/README.md @@ -8,8 +8,8 @@ This is an experimental build, not a supported one yet. It answers the three questions the issue left open: does it link, does it run, how big is it. `.github/workflows/wasm.yml` builds the module and runs `smoke.mjs` on every -pull request, and `.github/workflows/wasm-pages.yml` publishes the browser -demo to GitHub Pages on every push to `dev`. The `.wasm` is built in CI rather +pull request, and the same workflow publishes the browser demo to GitHub Pages +on every push to `dev`. The `.wasm` is built in CI rather than committed: it is a megabyte of generated output, and a stale binary sitting next to live sources is worse than a two minute build. diff --git a/docs/source/reference/commands.rst b/docs/source/reference/commands.rst index 5329f18c..b29c66e2 100644 --- a/docs/source/reference/commands.rst +++ b/docs/source/reference/commands.rst @@ -123,14 +123,16 @@ startFire .. code-block:: none startFire[loc=(x,y,z)|lonlat=(lon,lat,z);t=seconds|date=YYYY-MM-DDTHH:MM:SSZ] + startFire[geojson=] -Ignites a minimal clockwise triangular fire front (3 ``FireNode`` markers) at the given location and time. +Ignites a minimal clockwise triangular fire front (3 ``FireNode`` markers) at the given location and time, or a front along a GeoJSON polygon. **Arguments:** * ``loc=(x,y,z)``: Ignition point in Cartesian domain coordinates (meters). * ``lonlat=(lon,lat,z)``: Ignition point in WGS84 coordinates (longitude, latitude, elevation). All three components are required (``lonlat=(lon,lat)`` is ignored). * ``t=seconds`` or ``date=YYYY-MM-DDTHH:MM:SSZ``: Ignition time in seconds or ISO 8601 UTC format. +* ``geojson=``: Path to a GeoJSON file, or the GeoJSON text inline between triple quotes. The ``Polygon`` or ``MultiPolygon`` coordinates are ``[lon, lat, z]``. A top-level ``"valid_at"`` date, if present, sets the ignition time. See ``tests/runff/rungeojson.ff``. **Example:** @@ -138,6 +140,7 @@ Ignites a minimal clockwise triangular fire front (3 ``FireNode`` markers) at th startFire[loc=(5000,5000,0);t=0] startFire[lonlat=(9.0,42.0,0);date=2024-07-15T10:00:00Z] + startFire[geojson=ignition.geojson] .. _cmd-step: diff --git a/docs/source/reference/parameters.rst b/docs/source/reference/parameters.rst index 0360ebbc..4e407d09 100644 --- a/docs/source/reference/parameters.rst +++ b/docs/source/reference/parameters.rst @@ -32,7 +32,7 @@ propagationSpeedAdjustmentFactor minSpeed ~~~~~~~~ -* **Description:** Minimum propagation speed floor (in m/s) enforced when advancing a ``FireNode``. +* **Description:** A ``FireNode`` whose speed (in m/s) is at or below this value stops advancing. It is a stopping threshold, not a floor on the speed. * **Default:** ``0.005`` maxSpeed @@ -111,12 +111,12 @@ curvatureScheme smoothing ~~~~~~~~~ -* **Description:** Smoothing weight applied during normal vector computation. +* **Description:** Read but not used by the current node update. * **Default:** ``1`` relax ~~~~~ -* **Description:** Relaxation factor (:math:`0\text{–}1`) used when updating node normal vectors and front depth. +* **Description:** Relaxation factor (:math:`0\text{–}1`) that blends a node's previous speed and front depth with the newly computed ones. * **Default:** ``0.5`` frontDepthComputation diff --git a/docs/source/user_guide/ensembles.rst b/docs/source/user_guide/ensembles.rst index edc9d001..0ae50c67 100644 --- a/docs/source/user_guide/ensembles.rst +++ b/docs/source/user_guide/ensembles.rst @@ -30,8 +30,7 @@ against a ``pip``-installed ForeFire. L = 4000.0 def setup(ff): - ff["fuelsTable"] = "Index;vv_coeff;Kcurv;beta\n1;1.0;1.0;1.0" - ff["defaultFuelType"] = 1. + ff["fuelsTable"] = "Index;vv_coeff\n1;1.0" ff["windReductionFactor"] = 1.0 ff["propagationModel"] = "WindDriven" ff.execute(f"FireDomain[sw=(0,0,0);ne=({L},{L},0);t=0]") diff --git a/docs/source/user_guide/forefire_script.rst b/docs/source/user_guide/forefire_script.rst index 0fe3cba0..7735352d 100644 --- a/docs/source/user_guide/forefire_script.rst +++ b/docs/source/user_guide/forefire_script.rst @@ -31,9 +31,9 @@ Grammar & Syntax Rules .. code-block:: none - setParameter[fuelsTable="""Index;vv_coeff;Kcurv;beta - 1;1.0;1.0;1.0 - 2;0.3;1.0;1.0"""] + setParameter[fuelsTable="""Index;vv_coeff + 1;1.0 + 2;0.3"""] 5. **Parameter Substitution** (``*param*``) **and Protected Values** (``!``): diff --git a/docs/source/user_guide/fuels_and_models.rst b/docs/source/user_guide/fuels_and_models.rst index 15c625ed..a6be58f5 100644 --- a/docs/source/user_guide/fuels_and_models.rst +++ b/docs/source/user_guide/fuels_and_models.rst @@ -37,7 +37,7 @@ Model Families and Their Fuel Columns * - ``Iso`` - **None.** Spreads at the constant speed given by ``setParameter[Iso.speed=0.5]`` (m/s) in all directions. * - ``WindDriven`` - - ``Index;vv_coeff;Kcurv;beta`` (idealized wind-driven model used in :doc:`python_arrays` and :doc:`ensembles`). + - ``Index;vv_coeff``: the rate of spread is ``vv_coeff × normal wind`` (idealized wind-driven model used in :doc:`python_arrays` and :doc:`ensembles`). * - ``Rothermel``, ``BalbiNov2011``, ``Balbi2020``, ``Balbi2015`` - The standard 23-column Rothermel/Balbi fuel table detailed in :ref:`rothermel-fuel-file` below. * - ``RothermelAndrews2018`` diff --git a/docs/source/user_guide/mesonh.rst b/docs/source/user_guide/mesonh.rst index ee88fc7c..4c5a2e2f 100644 --- a/docs/source/user_guide/mesonh.rst +++ b/docs/source/user_guide/mesonh.rst @@ -80,6 +80,7 @@ While it runs, open ``http://localhost:8080/mnh3d.html``. The page displays the terrain, fuel, fire perimeter, plume top and surface wind. The browser needs internet access to load its JavaScript dependencies. -This is a live view of the calculation: it does not provide a replay or -fast-forward control. Use one viewer tab at a time. For comparisons of +The page follows the run live. Once it has steps to show, a Timeline slider +lets you scrub or play them back, and opening the page after the run replays +the steps saved in ``ForeFire/Outputs`` and ``MODEL2``. Use one viewer tab at a time. For comparisons of simulation outputs, leave the viewer closed, as explained in the guide. diff --git a/docs/source/user_guide/python_arrays.rst b/docs/source/user_guide/python_arrays.rst index ee0682f2..84c11433 100644 --- a/docs/source/user_guide/python_arrays.rst +++ b/docs/source/user_guide/python_arrays.rst @@ -45,8 +45,7 @@ against a ``pip``-installed ForeFire. # Fuel table, inline — no CSV file needed. The columns depend on the # propagation model: the WindDriven model used here only needs vv_coeff # (see "Choosing a fuel table" below). - ff["fuelsTable"] = "Index;vv_coeff;Kcurv;beta\n1;1.0;1.0;1.0\n2;0.3;1.0;1.0" - ff["defaultFuelType"] = 1. + ff["fuelsTable"] = "Index;vv_coeff\n1;1.0\n2;0.3" # Solver parameters. for key, value in { @@ -122,7 +121,7 @@ The columns of ``fuelsTable`` are read by the propagation model, so they change with the model you select: * ``WindDriven`` — a minimal table with ``vv_coeff`` (the rate of spread is - ``vv_coeff × normal wind``), plus ``Kcurv`` and ``beta``. Convenient for + ``vv_coeff × normal wind``). Convenient for idealized and teaching cases. * ``Rothermel``, ``BalbiNov2011``, ``Balbi2015`` and the other physical models — the full fuel description in ``fuels.csv``. See From 6e7fe97dde8f6e55a66b1da9de429eac9d70a66d Mon Sep 17 00:00:00 2001 From: Antonio Leblanc Date: Wed, 11 Nov 2026 12:54:55 -0300 Subject: [PATCH 2/2] docs: Git LFS for runff, contributor rules, test script counts, mnh3d replay scope --- CONTRIBUTING.md | 6 +++++- TESTING.md | 4 ++++ docs/source/user_guide/mesonh.rst | 4 ++-- tests/README.md | 3 ++- tests/python/README.md | 7 ++++--- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cbcf6299..be44e2a5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,6 +62,10 @@ We welcome code contributions, from bug fixes to new features. 5. **Make Changes:** Implement your code changes, following existing coding style and conventions where possible. + * Changes to propagation or flux models and their physics start as an issue: the maintainers decide those. + * A change that moves simulation results goes in its own PR, and at the top of its CHANGELOG entry. + * Never regenerate a `.ref` file to make a test pass. + * Report security problems through [private vulnerability reporting](https://github.com/forefireAPI/forefire/security/advisories/new), never in a public issue. 6. **Add Tests (if applicable):** For new features or significant bug fixes, please add corresponding tests or update existing ones. See [TESTING.md](TESTING.md) for what each suite covers, how to run it, and which ones CI validates. Ensure all tests pass locally. @@ -94,7 +98,7 @@ We welcome code contributions, from bug fixes to new features. ``` 10. **Open a Pull Request (PR):** - Go to the `forefireAPI/forefire` repository on GitHub and open a Pull Request from your branch to the `dev` branch (or `master` if that's the target). + Go to the `forefireAPI/forefire` repository on GitHub and open a Pull Request from your branch to the `dev` branch. * Provide a clear description of the changes in the PR. * Link any relevant issues (e.g., "Fixes #123"). * Ensure the CI checks pass on your PR. The maintainers will review your code, provide feedback, and merge it once approved. diff --git a/TESTING.md b/TESTING.md index 30e259a2..0e048174 100644 --- a/TESTING.md +++ b/TESTING.md @@ -40,6 +40,10 @@ The primary physics regression test, validated in CI by `main.yml` and `macos.ym 2. Navigate to the test directory: `cd tests/runff` 3. Execute the test script: `bash ff-run.bash` +The test data and `.ref` files are stored in Git LFS. Fetch them first with +`git lfs pull --include tests/runff` (or `git lfs pull` for every case). +Configure checks the LFS files; `-DFOREFIRE_CHECK_LFS=OFF` skips that check. + **Test Logic:** The `ff-run.bash` script: diff --git a/docs/source/user_guide/mesonh.rst b/docs/source/user_guide/mesonh.rst index 4c5a2e2f..c798e746 100644 --- a/docs/source/user_guide/mesonh.rst +++ b/docs/source/user_guide/mesonh.rst @@ -81,6 +81,6 @@ the terrain, fuel, fire perimeter, plume top and surface wind. The browser needs internet access to load its JavaScript dependencies. The page follows the run live. Once it has steps to show, a Timeline slider -lets you scrub or play them back, and opening the page after the run replays -the steps saved in ``ForeFire/Outputs`` and ``MODEL2``. Use one viewer tab at a time. For comparisons of +lets you scrub or play them back. For this bundled case, opening the page +after the run replays the steps saved in ``ForeFire/Outputs`` and ``MODEL2``. Use one viewer tab at a time. For comparisons of simulation outputs, leave the viewer closed, as explained in the guide. diff --git a/tests/README.md b/tests/README.md index 855fc5b2..9ee79827 100644 --- a/tests/README.md +++ b/tests/README.md @@ -102,7 +102,8 @@ are demonstrations of the API rather than tests of the physics. compares ForeFire against a FARSITE case, and needs `flatland.lcp`, which is not in the repository — `python/README.md` has the download URL. -Three test scripts sit here too, and `run.bash` runs none of them: +Eight `test_*.py` scripts sit here too, and `run.bash` runs only +`test_validate.py`. `python/README.md` covers them all; the main ones: | File | What it checks | Where it runs | | --- | --- | --- | diff --git a/tests/python/README.md b/tests/python/README.md index 17ec1aff..2b83c629 100644 --- a/tests/python/README.md +++ b/tests/python/README.md @@ -3,7 +3,8 @@ Everything here needs the `pyforefire` module: either a build configured with `-DFOREFIRE_BUILD_PYTHON=ON`, or `pip install forefire`. -`../run.bash` runs only the first two, through `$PYTHONEXE`. +`../run.bash` runs only the first two examples and `test_validate.py`, through +`$PYTHONEXE`. ## `percolation.py` @@ -35,8 +36,8 @@ The weather it uses, `flatland_3mph0deg7hr.raws`, *is* in this directory. ## The test scripts -These four are tests rather than examples, and `../run.bash` runs none of -them. They are plain scripts, not pytest modules. `TESTING.md` covers each in +The `test_*.py` scripts are tests rather than examples, and `../run.bash` +runs only `test_validate.py`. They are plain scripts, not pytest modules. `TESTING.md` covers each in detail, including how to build the module they import. ### `test_moisture_invariants.py`