diff -r a4137aedcb3a -r c3a4f4bb87f7 README.md --- a/README.md Thu Feb 26 09:32:12 2026 -0500 +++ b/README.md Wed Apr 22 22:32:00 2026 -0500 @@ -1,27 +1,132 @@ -# Pointsource-PDE +# Codes for “Leak localisation with a measure source convection--diffusion model” + +These are the codes for the numerical demonstrations of the manuscript +_“Leak localisation with a measure source convection--diffusion model”_ +([arXiv:????.????](https://arxiv.org/abs/????.????)) by Thi Tam Dang and Tuomo Valkonen. +It should be relatively easy to to use this package and the algorithms it provides +for other PDE-based point source localisation problems. + +## Building + +Sorry, although the core of program is written in Rust with a modern dependency management and build process, we also have legacy C++ and Python dependencies, i.e., the Fenicsx PDE library. Therefore, the build process is difficult. + +(We admit it, we made a mistake by going with the crowd and using Fenicsx. In the end it would have been less effort to write low-level PDE code in Rust.) -## Prerequisites +### Phase 1: Python and Fenics + +#### Option 1.A that avoids Conda hell, but is more work (macOS and Linux) + +##### Phase 1.A.1: C++ dependencies of Fenics + +First install C++ dependencies using [Homebrew](https://brew.sh). +Even on Linux, **use Homebrew**, or install from official sources; distribution packages are usually obsolete and buggy, often non-standard, and will cause problems (see above). + + brew install openmpi boost pugixml fmt spdlog hdf5-mpi cmake kahip slepc petsc gsl + +(Fenics recommends ParMETIS instead of Kahip, but only the latter is available from Homebrew at the time of writing this.) + +There's no guarantee that this will install compatible versions of these packages. Homebrew, while better than most Linux distributions, is also obsolete in its philosophy: it does not allow easily installing specific versions of packages. Versions known to work are: -## Installation and usage +package | version +---------|-------- +boost | 1.90.0 +cmake | 4.2.1 +fmt | 12.1.0 +hdf5-mpi | 1.14.6 +kahip | 3.22 +petsc | 3.24.3 +pugixml | 1.15 +slepc | 3.24.2 +spdlog | 1.17.0 +gsl | 2.8 + +You can get the list of installed versions with: -### Installing dependencies + brew list --versions openmpi boost pugixml fmt spdlog hdf5-mpi cmake kahip slepc petsc gsl + +##### Phase 1.A.2: Python dependencies of Fenics + +In this source directory, create and activate a virtual environment for Python, and +install Python packages: -Python dependencies are managed Conda and by the Cargo build system of [Rust]. -On some platforms, you can use alternative methods. + python3 -m venv .venv + source .venv/bin/activate + PETSC_DIR=/opt/homebrew/ SLEPC_DIR=/opt/homebrew/ pip install -r requirements.lock + +To not have to activate the virtual environment manually every time, and to not mess up your global settings, it is recommended to install [direnv](https://direnv.net) and put the following in `.envrc` in this directory: + + source .venv/bin/activate + export PYTHONPATH=$(echo .venv/lib/python*/site-packages) + export PYO3_PYTHON="$(which python)" -#### Phase 1: Python +(The last two lines are required later.) +This template is also available in `misc/_envrc`. +For changes `.envrc` to take effect, you should use + + direnv allow + +##### Phase 1.A.3: Fenicx-basix + +Install basix from according to +instructions. First do the C++ bit: -##### Most platforms: + tar xzf basix-0.10.0.post0.tar.gz + cd basix-0.10.0.post0/cpp + mkdir build + cd build + cmake .. + make + make install + +Then the Python bit. This has to be done with the `venv` created above, active. + + cd ../../python + pip install . + +##### Phase 1.A.4: Fenicx-dolfinx + +Install dolfinx from according to +instructions. First do the C++ bit: -- Fenicsx installed in Conda according to instructions -- SciFEM and SciPY (`conda install conda-forge::scifem conda-forge::scipy`) + tar xzf dolfinx-0.10.0.post5.tar.gz + cd dolfinx-0.10.0.post5/cpp + mkdir build + cd build + cmake .. + make + make install + +Skip the `source /usr/local/lib/dolfinx/dolfinx.conf` recommended at the end +of the compilation. It will likely break things. + +Then the Python bit. This has to be done with the virtual environment created above, active. + + cd ../../python + python -m scikit_build_core.build requires | python -c "import sys, json; print(' '.join(json.load(sys.stdin)))" | xargs pip install + pip install --check-build-dependencies --no-build-isolation . + +If you didn't already do these steps with `direnv` above, you should: -##### Debian/Ubuntu + export PYTHONPATH=$(echo .venv/lib/python*/site-packages) + export PYO3_PYTHON="$(which python)" + + +#### Option 1.B: Conda + +You can *try to* install Fenicsx in Conda according to instructions on the Fenics website. Additionally you need to install `scipy`: -You may br able to use the system package manager instead of Conda, but beware of obsolete versions. + conda create -n fenicsx-env + conda activate fenicsx-env + conda install -c conda-forge fenics-dolfinx=0.10.0 scipy=1.17.1 mpich + +This is, however, unlikely to not work, as Conda, despite its sandboxing separation attempts, conflicts with system packages, or Conda packages have weird ideas. You're likely to run into runtime problems with the FFCX form compiler (*bad* *bad* *bad* idea, running a C compiler runtime) failing due to something, somewhere, in the extremely fragile Conda setup, trying to load system libraries wrongly, etc. -#### Phase 2: Rust +#### Option 1.C: Debian/Ubuntu + +You may be able to use the system package manager, but beware of obsolete and modified versions. As of 2026-03-23, the packages available in Debian/Ubuntu cause massive memory leaks and eventual system crash. + +### Phase 2: Rust You will only need to install the “nightly” Rust compiler and the [GNU Scientific Library] manually. At the time of writing this README, @@ -30,24 +135,16 @@ 1. Install the [Rust] infrastructure (including Cargo) with [rustup]. 2. Install a “nightly” release of the Rust compiler. With rustup, installed in the previous step, this can be done with - ```console - rustup toolchain install nightly - ``` -3. Install [GNU Scientific Library]. On a Mac with [Homebrew] installed, - this can be done with - ```console - brew install gsl - ``` - For other operating systems, suggestions are available in the [rust-GSL] - crate documentation. If not correctly installed, you may need to pass - extra `RUSTFLAGS` options to Cargo in the following steps to locate the - library. + + rustup toolchain install nightly -4. Download [alg_tools] and unpack it under the same directory as this - package. +3. Download [alg_tools], [pointsource_algs], and [measures] and unpack them under + the same directory as this package. [rustup]: https://rustup.rs [alg_tools]: https://tuomov.iki.fi/software/alg_tools/ + [pointsource_algs]: https://tuomov.iki.fi/software/pointsource_algs/ + [measures]: https://tuomov.iki.fi/repos/measures/ [Rust]: https://www.rust-lang.org/ [GNU Scientific Library]: https://www.gnu.org/software/gsl/ [rust-GSL]: https://docs.rs/GSL/6.0.0/rgsl/ @@ -56,41 +153,61 @@ [arXiv:2502.12417]: https://arxiv.org/abs/2502.12417 [doi:10.46298/jnsao-2023-10433]: http://doi.org/10.46298/jnsao-2023-10433 -### Building and running the experiments +### Linux / further patching + +Due to both Fenics and typical Linux system being completely broken, you may need to do further patching to get things to compile: -To compile and install the program, use -```console -cargo install --path=. -``` + 1. I had to set (in my [direnv](https://direnv.net) `.envrc`) + + export PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:/usr/local/lib/pkgconfig/:/usr/lib/aarch64-linux-gnu/pkgconfig/ + export LD_LIBRARY_PATH=/home/linuxbrew/.linuxbrew/lib + + 2. Some libraries, in particular `libfmt` and `libspdlog` installed in Homebrew, may conflict with system versions, that must be removed. + Lack of proper sandboxing in legacy Linux distributions, effectively prohibits multiple versions of the same library. + 2. I had to add `Libs` in `/usr/local/lib/pkgconfig/dolfinx.pc` the bit `-L/home/linuxbrew/.linuxbrew/lib/ -lopenblas`. Nothing in the fenics stack seems to explicitly require it. Basix, that depends on openblas, is entirely missing a `pkg-config` file. + 3. Also `export export OMP_NUM_THREADS=1` (in `.envrc`). We don't do MPI. We cannot do MPI in Fenics' lame “it's all just parallel solution of PDEs, with no other computation, ever” aka “single-program multiple-data, with no controller at all” way. If you don't do this, you may have multiple threads wasting CPU just being there. We try to control the thread count in our code, but OpenMPI on Linux doesn't seem to respect it. + +## Building and running the experiments + +To compile the program, run + + cargo build --release + When doing this for the first time, several dependencies will be downloaded. -Now you can run the default set of experiments with -``` -pointsource_pde -o results -``` -The `-o results` option tells `pointsource_pde` to write results in the -`results` directory. The option is required. +Now you can run the experiments in the article with + + cargo run --release -- \ + -o results -a radon_sliding_fb -a radon_fb --max-iter 20000 + experiments/laser_and_mirrors_aux.py experiments/laser_and_mirrors_aux2.py + +The `-o results` option tells `pointsource_pde` to write results in the `results` directory. +The other options indicate the algorithms and experiments to run, as well as the maximum number +of iterations. +The double-dash separates the options for the Cargo build system and `pointsource_pde`. -Alternatively, you may build and run the program without installing with -```console -cargo run --release -- -o results -``` -The double-dash separates the options for the Cargo build system -and `pointsource_pde`. +### Visualising the results + +The results may be plotted with + + python3 ./plot.py results/laser_and_mirrors_aux/radon_sliding_fb -### Documentation +Vary the path to `laser_and_mirrors_aux2` and `radon_fb` for the alternative experiment and basic algorithm. + +The script `misc/copy_results.sh` may be generate the images and copy the results in the manuscript +to `../gasleak`. + +## Documentation Use the `--help` option to get an extensive listing of command line options to customise algorithm parameters and the experiments performed. -## Internals +### Internals If you are interested in the program internals, the integrated source code documentation may be built and opened with -```console -cargo doc # build dependency docs -misc/cargo-d --open # build and open KaTeX-aware docs for this crate -``` -The `cargo-d` script ensures that KaTeX mathematics is rendered in the -generated documentation through an ugly workaround. Unfortunately, -`rustdoc`, akin to Rust largely itself, is stuck in 80's 7-bit gringo ASCII -world, and does not support modern markdown features, such as mathematics. + + cargo doc # build dependency docs + misc/cargo-d --open # build and open KaTeX-aware docs for this crate + +The `cargo-d` script ensures that KaTeX mathematics is rendered in the generated documentation through an ugly workaround. Unfortunately, `rustdoc` is stuck in 80's 7-bit gringo ASCII world, +and does not support modern markdown features, such as mathematics.