From f64b3f8da15f2413f144efc7215385d12bc1b49e Mon Sep 17 00:00:00 2001 From: HugoFara Date: Thu, 13 Aug 2026 00:10:37 +0200 Subject: [PATCH 1/3] docs(rtd): document the pip install path The documentation site had no mention of pip, pypi or wheels -- `grep -rni 'pip\|pypi\|wheel' docs/source` returned nothing -- while the README's headline instruction is `pip install forefire`. Every reader arriving at the site was sent to build from source. - installation.rst leads with pip: platforms, what the wheel contains, and the three options wheels turn off (MPI, -march=native, ANN_test), then the source build as before. - The NetCDF prerequisite said 'Verify which one is actually required by the current CMake setup', leaving the reader to answer the documentation's own question. CMakeLists.txt looks for netcdf_c++4 / netcdf-cxx4 / netcdf-cxx and its failure message already lists the package per distribution; that table is now in the page, along with the note that libnetcdf-cxx-legacy-dev is a different API. - The FOREFIRE_* build options are documented, with their real defaults. - quickstart.rst offered Docker only, calling it 'the quickest way'. A pip route comes first now; the Docker walkthrough is unchanged. - conf.py hard-coded release = '2.0.0', so the site advertised 2.0.0 while the code was v2.5.0. It parses src/include/Version.h, as CMake and scikit-build-core do. Sphinx builds clean: the only warnings are the eleven doxygenclass lookups that need the Doxygen XML RTD generates in its pre_build step. --- docs/source/conf.py | 15 +- docs/source/getting_started/installation.rst | 268 ++++++++++++++----- docs/source/getting_started/quickstart.rst | 53 +++- docs/source/index.rst | 1 + 4 files changed, 271 insertions(+), 66 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 57574fa3..b87f841e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -6,10 +6,23 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +import pathlib +import re + project = 'ForeFire' copyright = '2014 - 2025, J-B Filippi' author = 'Filippi, Jean Baptiste' -release = '2.0.0' + +# Single source of truth for the version, the same file CMake and +# scikit-build-core read. Hard-coding it here left the site advertising 2.0.0 +# for three releases. +_version_header = pathlib.Path(__file__).resolve().parents[2] / 'src' / 'include' / 'Version.h' +_match = re.search(r'ff_version\s*=\s*"v?([0-9]+\.[0-9]+\.[0-9]+)"', + _version_header.read_text(encoding='utf-8')) +if not _match: + raise RuntimeError(f'could not parse ff_version from {_version_header}') +release = _match.group(1) +version = release # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/docs/source/getting_started/installation.rst b/docs/source/getting_started/installation.rst index 0238a01d..ebe60466 100644 --- a/docs/source/getting_started/installation.rst +++ b/docs/source/getting_started/installation.rst @@ -1,32 +1,137 @@ -Installation: Build from Source -================================ +Installation +============ -This guide explains how to install ForeFire by compiling it directly on your Linux/Unix-like system. This gives you a native build, but requires managing dependencies. -There are two main ways to build from source: +There are three ways to install ForeFire. Which one you want depends on what +you intend to do with it: -- Option 1: Using the provided install script (easiest for Debian/Ubuntu) -- Option 2: Following manual steps (for all systems or finer control). +.. list-table:: + :header-rows: 1 + :widths: 20 45 35 -Prerequisites -------------- + * - Method + - Use it when + - Section + * - **pip** + - You want to run simulations or drive ForeFire from Python. + - :ref:`install-pip` + * - **Docker** + - You are on Windows, or you want the web console with no setup. + - :doc:`quickstart` + * - **From source** + - You need MPI coupling with Meso-NH, a CPU-tuned build, or you are + working on ForeFire itself. + - :ref:`install-source` + +.. _install-pip: + +Install with pip +---------------- + +This is the fastest route, and it needs no compiler, no CMake and no NetCDF +installation of your own — NetCDF is bundled inside the wheel. + +.. code-block:: bash + + pip install forefire + +Requirements +~~~~~~~~~~~~ + +- **CPython 3.9 to 3.14.** The free-threaded builds (``cp314t``) are + deliberately not published: the C++ core still keeps mutable global state, so + a wheel advertising free-threading would silently re-enable the GIL on + import. +- **Linux** on ``x86_64`` or ``aarch64`` (``manylinux_2_28`` or newer), or + **macOS 14+ on Apple Silicon**. + +There is no wheel for Intel macOS, musl-based Linux (Alpine), 32-bit targets, +Windows or PyPy. On those platforms pip falls back to the source distribution, +which needs the build prerequisites in :ref:`install-source`. Windows users are +better served by Docker — see :doc:`quickstart`. + +What you get +~~~~~~~~~~~~ + +Both interfaces, from the one package: + +.. code-block:: bash + + forefire -v + +.. code-block:: python + + import pyforefire as forefire -If you choose the **manual build steps** (Option 2), or if you simply want to understand what tools are needed, you must ensure the following are installed on your system: + ff = forefire.ForeFire() + ff.execute("FireDomain[sw=(0,0,0);ne=(10000,10000,0);t=0]") + ff.addLayer("propagation", "Iso", "propagationModel") + ff.execute("startFire[loc=(5000,5000,0.0)]") + ff.execute("step[dt=1000]") + print(ff.execute("print[]")) -- **C++ Compiler:** A modern C++ compiler (like `g++`). Package typically called `build-essential` or similar. -- **CMake:** Build system generator (`cmake`). -- **Make:** Build tool (`make`). -- **NetCDF Libraries:** ForeFire requires NetCDF support. The specific package needed is the C++ interface. +.. note:: - - On **Debian/Ubuntu**, the install script uses `libnetcdf-c++4-dev`. - - On other systems, find the equivalent package (e.g., `netcdf-cxx-devel`, `netcdf-cxx4`). - - *Note: Ensure this is the correct/intended library. Older docs might mention `libnetcdf-cxx-legacy-dev`. Verify which one is actually required by the current CMake setup.* + The distribution on PyPI is called ``forefire``; the importable module keeps + its historical name, ``pyforefire``. -Build Options -------------- +What you do not get +~~~~~~~~~~~~~~~~~~~ -**Option 1: Using the Install Script (Recommended for Debian/Ubuntu)** +Published wheels are built with three options turned off, so a few things are +only available in a source build: -The repository provides a convenience script (`install-forefire.sh`) that automates the process on Debian-based systems like Ubuntu. +- **MPI coupling.** Fire-atmosphere runs with Meso-NH need + ``FOREFIRE_ENABLE_MPI``, so they need a source build. +- **CPU tuning.** Wheels are built without ``-march=native``, so that they run + on any machine of the right architecture. A source build with + ``FOREFIRE_NATIVE_ARCH=ON`` will be faster on the machine that built it. +- **The** ``ANN_test`` **helper**, built by ``FOREFIRE_BUILD_TOOLS``. + +.. _install-source: + +Build from source +----------------- + +A native build, in exchange for managing the dependencies yourself. Two routes: +the install script (Debian/Ubuntu only), or manual steps (any Unix-like +system). + +Prerequisites +~~~~~~~~~~~~~ + +- **A C++ compiler**, such as ``g++``. On Debian/Ubuntu this comes with + ``build-essential``. +- **CMake** 3.15 or newer, and **Make**. +- **NetCDF — both the C library and the legacy C++4 API.** The C++4 API is a + separate package from the C library on every distribution, and it is the one + people usually miss. + + .. list-table:: + :header-rows: 1 + :widths: 25 75 + + * - System + - Packages + * - Debian/Ubuntu + - ``apt install libnetcdf-dev libnetcdf-c++4-dev`` + * - Fedora/RHEL + - ``dnf install netcdf-devel netcdf-cxx4-devel`` + * - macOS (Homebrew) + - ``brew install netcdf netcdf-cxx`` + + The library is named ``netcdf_c++4`` everywhere except Homebrew, which calls + it ``netcdf-cxx4`` (``netcdf-cxx`` in older bottles); CMake looks for all + three. The older ``libnetcdf-cxx-legacy-dev`` package is a *different*, + pre-C++4 API and will not work. + + If NetCDF is installed somewhere CMake does not search, point at it with + ``-DNETCDF_HOME=/path/to/netcdf`` (and ``-DNETCDF_CXX_HOME=...`` if the C++ + API lives elsewhere). + +Option 1: the install script (Debian/Ubuntu) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``install-forefire.sh`` automates the process on Debian-based systems. 1. **Clone the repository:** @@ -39,27 +144,33 @@ The repository provides a convenience script (`install-forefire.sh`) that automa .. warning:: - This script requires `sudo` privileges to install system packages using `apt`. Review the script if you have concerns. + This script requires ``sudo`` privileges to install system packages using + ``apt``. Review the script if you have concerns. .. code-block:: bash sudo bash install-forefire.sh -**What the Install Script Does:** +**What the install script does:** -- **Updates Package Lists and Installs Dependencies:** Runs `apt-get update` and installs prerequisites listed above -- **Builds ForeFire:** using CMake and Make. -- **Reports Install Location:** Prints the location of the built binaries (usually `$PROJECT_ROOT/bin`). -- **(Optional) Updates PATH:** +- **Installs dependencies:** runs ``apt-get update`` and installs the + prerequisites listed above. +- **Builds ForeFire** using CMake and Make. +- **Reports the install location:** usually ``$PROJECT_ROOT/bin``. +- **(Optional) updates PATH:** - - Prompts the user if they want to add the ForeFire `bin` directory to their PATH permanently. - - If 'yes', it appends `export PATH=` and `export FOREFIREHOME=` lines to the user's `~/.bashrc` file. - - It tries to detect the correct user's home directory even when run with `sudo` (using `$SUDO_USER`). - - **Note:** This only modifies `.bashrc`. If you use a different shell (like `zsh` or `fish`), you will need to configure the PATH manually (see below). + - Prompts you before doing anything, and only if you agree appends + ``export PATH=`` and ``export FOREFIREHOME=`` lines to ``~/.bashrc``. + - It detects the invoking user's home directory even under ``sudo``, via + ``$SUDO_USER``. + - **Note:** this only modifies ``.bashrc``. For ``zsh`` or ``fish``, + configure the PATH manually (see below). -**Option 2: Manual Build Steps (All Linux/Unix-like Systems)** +Option 2: manual build (any Linux/Unix-like system) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use this method if you are not on Debian/Ubuntu, prefer manual control, or don't want to use the install script. +Use this if you are not on Debian/Ubuntu, prefer manual control, or do not +want to run the install script. 1. **Clone the repository:** @@ -68,55 +179,88 @@ Use this method if you are not on Debian/Ubuntu, prefer manual control, or don't git clone https://github.com/forefireAPI/forefire.git cd forefire -2. **Install Prerequisites Manually:** +2. **Install the prerequisites** for your system, from the table above. + +3. **Configure and build:** - Use your system's package manager to install `cmake`, `make`, a C++ compiler (`build-essential` or equivalent), and the required NetCDF C++ development library (e.g., `libnetcdf-c++4-dev`, `netcdf-cxx-devel`, etc.). - Example for Debian/Ubuntu (if not using the script): - .. code-block:: bash - sudo apt update - sudo apt install build-essential cmake libnetcdf-c++4-dev # Verify package name! + cmake -S . -B build + cmake --build build -j -3. **Create a build directory and run CMake & Make:** + The executable lands in ``bin/forefire``. Check it with: .. code-block:: bash - mkdir build - cd build - cmake .. - make + ./bin/forefire -v -The main executable `forefire` will be located at `../bin/forefire` (relative to the `build` directory). Check installation with - - .. code-block:: bash +Build options +~~~~~~~~~~~~~ - cd .. # Go back to the root of the repository - ./bin/forefire -v +The build is driven by ``FOREFIRE_*`` CMake options; pass them at configure +time, for example ``cmake -S . -B build -DFOREFIRE_ENABLE_MPI=OFF``. -4. **Making ForeFire Executable System-Wide (Manual PATH setup)** +.. list-table:: + :header-rows: 1 + :widths: 30 15 55 - If you built from source (manually or via the script but declined the automatic PATH update, or use a shell other than bash), the `forefire` executable is in the `bin` directory within the repository. To run it easily from any location, add this directory to your system's PATH environment variable. + * - Option + - Default + - Effect + * - ``FOREFIRE_ENABLE_MPI`` + - ON + - Fire-atmosphere coupling with Meso-NH, when MPI is found. Replaces the + compiler with the MPI wrapper. + * - ``FOREFIRE_NATIVE_ARCH`` + - ON + - ``-march=native``. Turn it off for a binary you intend to move to + another machine. + * - ``FOREFIRE_BUILD_PYTHON`` + - OFF + - Build the ``pyforefire`` extension module. + * - ``FOREFIRE_STATIC_CORE`` + - OFF + - Link the core statically. + * - ``FOREFIRE_BUILD_TOOLS`` + - ON + - Build the ``ANN_test`` helper, needed by ``tests/runANN``. + * - ``FOREFIRE_CHECK_LFS`` + - ON + - Fail early if the Git LFS test fixtures were not pulled. - **For the current terminal session:** +Wheel builds flip all six: MPI, native-arch, tools and the LFS check off, +Python and the static core on. That is what makes a wheel run on a machine +other than the one that built it. - .. code-block:: bash +Making ForeFire available system-wide +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Execute this from the root of the forefire repository - export PATH=$PATH:`pwd`/bin +After a source build, ``forefire`` lives in the repository's ``bin`` +directory. To run it from anywhere, add that directory to your PATH. - **Permanently:** +**For the current terminal session:** - Add the following line to your shell's configuration file (e.g., `~/.bashrc`, `~/.zshrc`, `~/.profile`, or `~/.config/fish/config.fish`). Replace `/path/to/forefire` with the actual absolute path to the cloned repository. +.. code-block:: bash - .. code-block:: bash + # Execute this from the root of the forefire repository + export PATH=$PATH:`pwd`/bin - export PATH="/path/to/forefire/bin:$PATH" +**Permanently:** - *Optional:* The install script also sets `export FOREFIREHOME="/path/to/forefire"`. You may want to add this line as well, as some scripts or components might potentially use it. +Add the following to your shell's configuration file (``~/.bashrc``, +``~/.zshrc``, ``~/.profile``, or ``~/.config/fish/config.fish``), replacing +``/path/to/forefire`` with the absolute path to the cloned repository. - .. code-block:: bash +.. code-block:: bash + + export PATH="/path/to/forefire/bin:$PATH" + +*Optional:* the install script also sets ``FOREFIREHOME``, which some scripts +and components use to locate the repository. + +.. code-block:: bash - export FOREFIREHOME="/path/to/forefire" + export FOREFIREHOME="/path/to/forefire" - After editing your configuration file, either restart your terminal or reload the configuration (e.g., `source ~/.bashrc`). \ No newline at end of file +Then restart your terminal or reload the configuration, for example with +``source ~/.bashrc``. diff --git a/docs/source/getting_started/quickstart.rst b/docs/source/getting_started/quickstart.rst index 2a575b13..e4b5dfcd 100644 --- a/docs/source/getting_started/quickstart.rst +++ b/docs/source/getting_started/quickstart.rst @@ -1,15 +1,62 @@ Quick Start =========== -This guide shows the quickest way to get the standard **ForeFire example simulation running** using its interactive web console, powered by Docker. This method bundles all dependencies, so you don't need to install them on your host system, and is the only way to run ForeFire on Windows. +Your first simulation, two ways: from a pip install in about a minute, or in +Docker with the interactive web console. + +.. _quickstart-pip: + +The one-minute version, with pip +-------------------------------- + +On Linux or macOS on Apple Silicon, nothing needs to be compiled and no +dependencies need to be installed on your system: + +.. code-block:: bash + + pip install forefire + +Then run a simulation from Python: + +.. code-block:: python + + import pyforefire as forefire + + ff = forefire.ForeFire() + ff.execute("FireDomain[sw=(0,0,0);ne=(10000,10000,0);t=0]") + ff.addLayer("propagation", "Iso", "propagationModel") + ff.execute("startFire[loc=(5000,5000,0.0)]") + ff.execute("step[dt=1000]") + print(ff.execute("print[]")) + +``print[]`` returns the state of the simulation as text — one ``FireNode`` +entry per node of the front, each with its location, velocity and time. The +same commands work in the interactive interpreter, which the same install +provides: + +.. code-block:: bash + + forefire + +See :doc:`installation` for which platforms have wheels, and +:doc:`/user_guide/forefire_script` for what these commands mean. + +.. _quickstart-docker: + +The full example, with Docker +----------------------------- + +This runs the standard **ForeFire example simulation** in its interactive web +console. It bundles all dependencies, so nothing is installed on your host +system, and it is the only way to run ForeFire on Windows. Prerequisites -------------- +~~~~~~~~~~~~~ - Docker installed and running on your system. - Git installed (for cloning the repository). Steps ------ +~~~~~ 1. **Clone the ForeFire repository:** Open your terminal and run: diff --git a/docs/source/index.rst b/docs/source/index.rst index 33ba48c6..84ac7a8c 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -6,6 +6,7 @@ Welcome to the official documentation for ForeFire — the open-source wildfire **Key Links:** - `GitHub Repository `_ +- `ForeFire on PyPI `_ — ``pip install forefire`` - `Online Demo Simulator `_ .. toctree:: From e9fba2a378f04306eb1b8a5e4a0dff580a88650e Mon Sep 17 00:00:00 2001 From: HugoFara Date: Thu, 13 Aug 2026 00:12:44 +0200 Subject: [PATCH 2/3] docs(tests): correct the test READMEs against the tree Nearly every specific claim in tests/README.md was wrong: - `idealized_wind.py` and `rothermel.fann` do not exist; the files are `idealizedwind.py` and `Rothermel.ffann`. - runANN was listed as needing `tensorflow` (or `torch`). It needs neither. It runs `bin/ANN_test`, built from tools/runANN/ANNTest.cpp, and ForeFire reads the .ffann network itself. - runANN was described as comparing against reference outputs. It diffs against result.txt.ref, which is not in the repository, so the suite fails on its second line every time -- now stated, with a pointer to #163. - percolation.py runs four fires, not three: one per entry in k_coeffs. - idealizedwind.py writes no NetCDF, only 360wind.png, and by way of ForeFire's plot[] command rather than matplotlib. - runff has two entry points that do different things. run.bash runs three scenarios and checks the artefacts exist; ff-run.bash runs two and compares KML and NetCDF against references. CI calls the second, so only the second can catch physics drift. The old text described neither accurately. tests/python/README.md documented only farsite_flat.py, the one script that cannot run as checked out, and did not say so. It now covers all four files, keeps the download URL for flatland.lcp, and marks test_wheel.py as belonging to cibuildwheel rather than to this suite. --- tests/README.md | 150 ++++++++++++++++++++++++++--------------- tests/python/README.md | 49 ++++++++++++-- 2 files changed, 138 insertions(+), 61 deletions(-) diff --git a/tests/README.md b/tests/README.md index 31844cd9..34ef8285 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,93 +1,131 @@ +# ForeFire test suite -# *FireFront* Test Suite +Five sets of tests, one per directory, covering the different interfaces and +use-cases of ForeFire. -This directory contains **five** sets of tests that showcase the different interfaces and use-cases of *ForeFire*. +| Directory | What it covers | Needs | +| --- | --- | --- | +| `mnh_ideal` | ForeFire / **Meso-NH** coupling on an idealised atmospheric case | `SRC_MESONH` set; Meso-NH compiled with the ForeFire library in its `exe` directory | +| `mnh_real_nested` | ForeFire / **Meso-NH** coupling on a real nested case | Same as above | +| `python` | The Python bindings, through two example simulations | `PYTHONEXE` set to a Python interpreter that can `import pyforefire` | +| `runANN` | The built-in feed-forward network evaluator, on a network fitted to Rothermel | `bin/ANN_test`, built by default (`-DFOREFIRE_BUILD_TOOLS=ON`) | +| `runff` | The command-line interpreter: run a case, save and reload state, export KML and GeoJSON | ForeFire only | -| Folder / script | Purpose of the test | Specific dependencies | -| --------------- | ------------------ | --------------------- | -| `mnh_ideal` | *ForeFire* / **Meso-NH** coupling on an idealised atmospheric case | `SRC_MESONH` must be set; Meso-NH compiled with the *ForeFire* library placed in its `exe` directory | -| `mnh_real_nested` | *ForeFire* / **Meso-NH** coupling on a real nested case | Same requirements as above | -| `python` | Usage examples via the Python API:
• `idealized_wind.py` (360° rotating wind)
• `percolation.py` (propagation through fuels of random density) | Python bindings must be set and PYTHONEXE set to the python eneble binary | -| `runANN` | Activation of a serialised ANN graph (`rothermel.fann`) that reproduces the Rothermel model | `tensorflow` (or `torch` if a PyTorch graph is supplied) | -| `runff` | Using the *ForeFire* command-line interpreter to:
1. launch a real simulation;
2. save/load a state;
3. convert outputs (FF, KML, GeoJSON) | *ForeFire* only | +`TESTING.md` at the repository root describes `runff` — the suite CI actually +gates on — in more detail. ---- +## Prerequisites -## 1. General prerequisites +* **ForeFire built**, with the binaries in `bin/`. -* **ForeFire** compiled and available in the `bin` dir. +* The test fixtures are stored in **Git LFS**. `git lfs pull` if the `.nc` + files look like short text stubs. -* *(optional)* **Meso-NH** – required only for the `mnh_*` tests. -```bash +* *(optional)* **Meso-NH**, for the `mnh_*` tests only: + + ```bash export SRC_MESONH=/path/to/your/mesonh -``` + ``` -* *(optional)* **Python bindings** – required for the `python` folder +* *(optional)* **A Python interpreter with the bindings available**, for the + `python` tests only. This is either a build with + `-DFOREFIRE_BUILD_PYTHON=ON`, or an environment where `pip install forefire` + has been run: -```bash - export PYTHONEXE=/path/to/your/python_forefire_enabled -``` + ```bash + export PYTHONEXE=/path/to/your/python + ``` ---- +* The verification scripts under `runff` import `lxml`, `xarray` and + `netCDF4`: -## 2. Running the tests + ```bash + pip install lxml xarray netCDF4 + ``` + +## Running them ```bash - make test +cd tests +bash run.bash # or: make test ``` ---- +`run.bash` skips the `mnh_*` tests when `SRC_MESONH` is unset and the `python` +tests when `PYTHONEXE` is unset, runs `runff` and `runANN` unconditionally, and +prints a pass/fail summary. It exits non-zero if any suite failed. -## 3. Cleaning up +To clean up the outputs (ForeFire dumps, figures, NetCDF files): ```bash -make clean +bash clean.bash # or: make clean ``` -Removes intermediate files (ForeFire outputs, figures, NetCDF files, …) generated by all tests. +## What each set does + +### `mnh_ideal` + +Validates the coupling on a simplified atmospheric profile. Expect a fire front +consistent with the prescribed wind, plus NetCDF and KML outputs. + +### `mnh_real_nested` + +Reproduces a real fire scenario across two nested Meso-NH domains (real forcing +plus a high-resolution nest). It also exercises high-frequency output and the +HTTP web interface, which needs `FOREFIREHOME` set. ---- +### `python` -## 4. Test set details +`run.bash` runs two scripts with `$PYTHONEXE`: -### 4.1 `mnh_ideal` +| Script | What it does | Output | +| --- | --- | --- | +| `percolation.py` | Four fires, each in a band of randomly filled fuel at a different density | `percolation.nc` | +| `idealizedwind.py` | Wind rotating from 0° to 360°, giving a circular front | `360wind.png`, written by ForeFire's own `plot[]` command | -* **Goal** – validate the coupling on a simplified atmospheric profile. -* **Expected outcome** – a fire front consistent with the prescribed wind, plus NetCDF and KML outputs. +The only assertion is that `360wind.png` was produced and is not empty — these +are demonstrations of the API rather than tests of the physics. -### 4.2 `mnh_real_nested` +`farsite_flat.py` is in this directory but is **not** run by `run.bash`. It +compares ForeFire against a FARSITE case, and needs `flatland.lcp`, which is +not in the repository — `python/README.md` has the download URL. -* **Goal** – reproduce a real fire scenario with nested Meso-NH domains. -* **Features** +`test_wheel.py` is not part of this suite either. It is the smoke test +cibuildwheel runs against a built wheel, and is meant to be run against an +installed `forefire`, never from the source tree. - * two domains (real forcing + high-resolution nest); - * performance and stability check. - * high frequency outputs and http web interface (requires FOREFIREHOME environment variable set) - +### `runANN` -### 4.3 `python` +Loads `Rothermel.ffann` — a small network fitted to the Rothermel propagation +model — evaluates it over the fuel, slope and wind combinations in +`modelrun.csv`, and checks the result. -| Script | Description | Expected artefacts | -| ------------------- | -------------------------------------------------------------------- | --------------------------- | -| `idealized_wind.py` | Wind rotating from 0° to 360°; circular fire front (regression test) | `360wind.png`, NetCDF files | -| `percolation.py` | Three fires propagating through randomly heterogeneous fuels | `percolation.nc` | +It needs no machine-learning framework. `ANN_test` is a ForeFire tool built +from `tools/runANN/ANNTest.cpp`, and the `.ffann` format is read by ForeFire's +own evaluator. -### 4.4 `runANN` +> **This suite currently fails.** `run.bash` diffs its output against +> `result.txt.ref`, which is not in the repository, so it exits non-zero on the +> second line every time. See +> [issue #163](https://github.com/forefireAPI/forefire/issues/163). -* **Goal** – verify *ForeFire*’s internal feed-forward routine on an ANN graph trained to approximate the Rothermel formula. -* **Steps** +### `runff` - 1. Load `rothermel.fann`. - 2. Activate on various *fuel / slope / wind* combinations. - 3. Compare with reference outputs. +Exercises the command-line interpreter. There are two entry points, and they do +different things: -### 4.5 `runff` -* **Goal** – verify *ForeFire*’s command line intrerpreter. +* **`run.bash`** — what `tests/run.bash` calls. Three successive scenarios: -Three successive scenarios: + 1. `real_case.ff` — run a real case, write NetCDF output and a `to_reload.ff` + state file; + 2. `reload_case.ff` — reload that state and export KML; + 3. `rungeojson.ff` — load, simulate, export GeoJSON, clear memory, reload the + GeoJSON to verify it. -1. **`realcase.ff`** – start a real case, save the state in FF format. -2. **`reload_case.ff`** Reload the state and export KML. -3. **`rungeojson.ff`** Single-run variant – load ► simulate ► export GeoJSON, clear memory, reload GeoJSON for verification. + It then checks that the expected artefacts exist and are not implausibly + small. ---- +* **`ff-run.bash`** — what CI calls, from `main.yml`, `macos.yml` and + `docker.yml`. It runs the first two scenarios and then compares the KML and + NetCDF against `real_case.kml.ref` and `ForeFire.0.nc.ref` with a numerical + tolerance, using `compare_kml.py` and `compare_nc.py`. This is the one that + can detect physics drift. diff --git a/tests/python/README.md b/tests/python/README.md index 49d433d8..a2748af8 100644 --- a/tests/python/README.md +++ b/tests/python/README.md @@ -1,7 +1,46 @@ -# *Python-basesd* Test Suite +# Python examples and tests -## 1. farsite_flat.py -It runs a simulation based in Farsite software for a north-wind of 3mph. +Everything here needs the `pyforefire` module: either a build configured with +`-DFOREFIRE_BUILD_PYTHON=ON`, or `pip install forefire`. -Required the input .lcp file can be downloaded from: -https://github.com/mbedward/farsite/raw/refs/heads/master/examples/flatland/Inputs/a_lcpFiles/flatland.lcp +`../run.bash` runs only the first two, through `$PYTHONEXE`. + +## `percolation.py` + +Four fires side by side, each in an 80×60 band of fuel filled at random to a +different density (`k_coeffs = [.10, .3, .4, .5]`), so the bands sit either +side of the percolation threshold. Writes `percolation.nc`. A demonstration of +building a heterogeneous fuel map in numpy and handing it to ForeFire with +`addIndexLayer`. + +## `idealizedwind.py` + +One fire under a wind rotating from 0° to 360°, which should trace a circular +front. Writes `360wind.png` through ForeFire's own `plot[]` command — the one +artefact `../run.bash` checks for. + +## `farsite_flat.py` + +Reproduces a FARSITE benchmark case: flat terrain, a 3 mph north wind, seven +hours of spread, compared against the FARSITE result. + +**It cannot run as checked out.** It reads `flatland.lcp`, a landscape file +that is not in this repository. Download it first: + +```bash +curl -LO https://github.com/mbedward/farsite/raw/refs/heads/master/examples/flatland/Inputs/a_lcpFiles/flatland.lcp +``` + +The weather it uses, `flatland_3mph0deg7hr.raws`, *is* in this directory. + +## `test_wheel.py` + +Not part of this suite. It is the smoke test `cibuildwheel` runs against a +built wheel — it checks that the module imports, that its vendored NetCDF +resolves, that the propagation models registered, and that a trivial +simulation advances. Run it against an *installed* `forefire`, never from the +source tree: + +```bash +python tests/python/test_wheel.py +``` From 1ba998b0bbf60d742bded1caf142d1d2c5b756b3 Mon Sep 17 00:00:00 2001 From: HugoFara Date: Thu, 13 Aug 2026 00:15:45 +0200 Subject: [PATCH 3/3] docs(commands): document emit, and de-duplicate clear `emit` has been in Command::makeCmds since it was added, but in neither app/forefire/commands.md nor the command reference. That file is not prose: AdvancedLineEditor.cpp parses it into getCommandMan(), which drives Tab completion, the help text and the syntax colouring. A command missing from it is invisible to the console -- typing `emit` was rendered uncoloured, exactly like a typo, while `save` beside it came out green. commands.md also carried two '## clear' blocks. getCommandMan() assigns cmdMan[key] as it walks the file, so the second silently replaced the first and the longer entry was dead text. They are merged into one that matches what Command::clear does: free the domain, cancel scheduled events, keep the parameters. Both files now cover all 22 registered commands, with no duplicates. Verified: rebuilt and piped `emit`, `clear` and a nonsense word into the console. The first two now colour green as recognised commands, the third does not. Sphinx builds with no new warnings. --- app/forefire/commands.md | 23 +++++++----- docs/source/reference/commands.rst | 58 +++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/app/forefire/commands.md b/app/forefire/commands.md index 1c473ff1..3cf6d191 100644 --- a/app/forefire/commands.md +++ b/app/forefire/commands.md @@ -77,6 +77,17 @@ std::string commandHelp = R"( - 'vel': Velocity vector (vx,vy,vz) associated with the trigger - 't': Time at which the trigger is activated; +## emit + emit[layer=;loc=(x,y,z);radius=;duration=;flux=] + Injects a flux into an existing flux layer, over an area, for a time span starting at the current domain time + Example: emit[layer=heatFlux;loc=(5000,5000,0);radius=50;duration=600;frp=120] + Arguments: + - 'layer': Name of the flux layer to emit into, as given to addLayer. 'name' is accepted as an alias + - 'loc': Centre of the emission in domain coordinates. Alternatives: 'lonlat' in WGS84, or a 'sw'/'ne' box, or a 'swlonlat'/'nelonlat' box + - 'radius': Radius in metres, giving a disc of area pi*r^2. Alternatives: 'surface' or 'area' in m2, or the area of the sw/ne box + - 'duration': Length of the emission in seconds, required. It starts at the current domain time + - 'flux': The emitted quantity per square metre per second, in the layer's own units. Alternatives, any one of: 'frp' in MW, converted using the FRPToWatts parameter and divided by the area; 'value' or 'val', a power divided by the area; 'total', an energy divided by area and duration; + ## goTo goTo[t=seconds] Advances the simulation to the specified time @@ -179,11 +190,9 @@ std::string commandHelp = R"( - 'filename.ff': Filename containing simulation commands to execute ## clear - clear - Clears all simulation data - Example: clear - Arguments: - - Clears the simulation data to reset the state + clear[] + Frees the fire domain and cancels every scheduled event. Parameters are kept, so a new FireDomain can be created without setting them again + Example: clear[] ## systemExec systemExec[command=] @@ -200,10 +209,6 @@ std::string commandHelp = R"( - 'host': Hostname or IP address for the server - 'port': Port number on which the server will listen; -## clear - clear[] - clears-up memory except parameters, no more schedueled events or fire domain. - ## quit quit[] Terminates the simulation diff --git a/docs/source/reference/commands.rst b/docs/source/reference/commands.rst index 7910f1e1..d52eec46 100644 --- a/docs/source/reference/commands.rst +++ b/docs/source/reference/commands.rst @@ -336,6 +336,62 @@ Triggers a change in simulation data at a specific time and location. Can be use trigger[fuelType=wind;vel=(5.0,2.0,0.0);t=1800] # Trigger new wind at t=1800s +.. _cmd-emit: + +``emit`` +~~~~~~~~ + +.. code-block:: none + + emit[layer=;loc=(x,y,z);radius=;duration=;flux=] + +Injects a flux into an existing flux layer, over an area, for a time span +starting at the domain's current time. The layer must already exist — create it +with :ref:`addLayer ` first. + +It lets a source that is not the simulated fire front contribute to a flux +layer. The ``frp`` form takes fire radiative power in megawatts, the unit +satellite products report. + +**Arguments:** + +* ``layer=``: Name of the flux layer to emit into, as given to ``addLayer``. ``name=`` is accepted as an alias. **Required.** +* ``duration=``: Length of the emission, in seconds, starting at the domain's current time. **Required.** + +*Where* — give exactly one of: + +* ``loc=(x,y,z)``: Centre, in domain coordinates. +* ``lonlat=(lon,lat,z)``: Centre, in WGS84. +* ``sw=(x,y,z)`` with ``ne=(x,y,z)``: A box, in domain coordinates. Its centre and area are used. +* ``swlonlat=(lon,lat,z)`` with ``nelonlat=(lon,lat,z)``: The same, in WGS84. + +*Over what area* — from the box if one was given, otherwise: + +* ``radius=``: A disc, of area ``pi * r²``. +* ``surface=`` or ``area=``: The area directly. + +*How much* — give exactly one of: + +* ``flux=``: The emitted quantity per square metre per second, in the layer's own units — W/m² for a heat flux layer. +* ``frp=``: Fire radiative power in megawatts, converted to watts through the ``FRPToWatts`` parameter (1e7 if it is not set) and divided by the area. +* ``value=`` or ``val=``: A total power, divided by the area. +* ``total=``: A total energy, divided by the area and the duration. + +**Example:** + +.. code-block:: none + + addLayer[name=heatFlux;type=flux;modelName=heatFluxBasic] + emit[layer=heatFlux;lonlat=(9.05,41.95,0);radius=50;duration=600;frp=120] + +.. note:: + + Every failure is reported on standard output and the command returns an + error: no active ``FireDomain``, an unknown layer name, a missing + ``duration``, a missing location, or a magnitude given as ``frp``/``value``/ + ``total`` with no usable area. + + .. _cmd-print: ``print`` @@ -486,7 +542,7 @@ Executes ForeFire commands contained within the specified script file. The filen clear[] -Clears all simulation data (domain, fronts, nodes, loaded data) and scheduled events, resetting the simulation state. Parameters are generally kept. +Frees the fire domain — with its fronts, nodes and loaded data — and cancels every scheduled event. Parameters are kept, so a new ``FireDomain`` can be created without setting them again. **Example:**