Troubleshooting
This page covers the most common errors encountered when installing or running ANUGA, along with their causes and fixes.
MPI not available / parallel runs fall back to serial
Symptom
Running with mpiexec -np 4 produces output as if only one process is
running, or you see:
WARNING: mpi4py not available. Running in serial mode.
Cause
mpi4py is not installed, or its underlying MPI library cannot be found
at runtime.
Fix
Install mpi4py into your conda environment:
conda install -c conda-forge mpi4py
Verify the installation:
python -c "from mpi4py import MPI; print(MPI.COMM_WORLD.Get_size())"
When launched with mpiexec -np 4 the above should print 4.
If you are on an HPC cluster, make sure you load the correct MPI module
before activating your conda environment, so that mpi4py links against
the system MPI rather than a bundled one:
module load openmpi/4.1.5 # example — use your cluster's module name
conda activate anuga_env
mpiexec -np 4 python my_script.py
Check which MPI mpi4py has found:
python -c "import mpi4py; print(mpi4py.get_config())"
Parallel API when mpi4py is absent
ANUGA’s parallel functions (distribute, distribute_basic_mesh, etc.)
fall back to a serial no-op when mpi4py is not available. The same
script therefore runs serially without modification — useful for testing, but
not for production parallel runs.
OpenMP threading not activating
Symptom
Setting OMP_NUM_THREADS=8 or calling domain.set_omp_num_threads(8)
has no effect — the simulation uses only one CPU core.
Cause — build not compiled with OpenMP
ANUGA’s Cython extensions must be compiled with OpenMP support. On Linux
this requires GCC with -fopenmp; on macOS it requires a GCC or
clang+libomp toolchain. A pre-built conda-forge package should already
include OpenMP, but a manual build may not.
Check:
python -c "
import anuga
domain = anuga.rectangular_cross_domain(10, 10)
domain.set_omp_num_threads(4, verbose=True)
"
If the extension loaded correctly you will see:
Setting omp_num_threads to 4
If you instead see an ImportError referencing sw_domain_openmp_ext,
the OpenMP extension was not compiled.
Fix — conda install (recommended):
conda install -c conda-forge anuga
Fix — rebuild from source with OpenMP
On Linux:
conda activate anuga_env
pip install --no-build-isolation -v .
On macOS, install libomp first:
brew install libomp
pip install --no-build-isolation -v .
Cause — OMP_NUM_THREADS not propagated to subprocesses
When running under mpiexec, some MPI launchers do not forward
environment variables. Set the variable explicitly in the launch command:
OMP_NUM_THREADS=4 mpiexec -np 2 python my_script.py
Or set it inside the script before creating the domain:
import os
os.environ['OMP_NUM_THREADS'] = '4'
import anuga
Rank-0 memory exhaustion on large meshes
Symptom
A MemoryError or the system swap fills up when building or distributing
a large mesh, typically in distribute() or while calling
create_domain_from_regions() / rectangular_cross_domain().
Cause
The standard distribute() workflow builds the full mesh and all
quantity arrays on rank 0 before any MPI communication takes place. For a
mesh of N triangles and P ranks, rank 0 must hold O(N) data — the same
amount as a serial run — before the submeshes are sent out.
Fix — use the mesh-first workflow
distribute_basic_mesh() distributes topology only; quantities are set
per-rank after distribution, so rank 0 never holds the full quantity arrays:
from anuga.abstract_2d_finite_volumes.basic_mesh import \
rectangular_cross_basic_mesh
from anuga.parallel.parallel_api import distribute_basic_mesh
if anuga.myid == 0:
bm = rectangular_cross_basic_mesh(1000, 1000, len1=10.0, len2=10.0)
else:
bm = None
domain = distribute_basic_mesh(bm)
# Set quantities per-rank — rank 0 never allocates the full arrays
domain.set_quantity('elevation', lambda x, y: -x / 10.0)
domain.set_quantity('stage', 0.0)
For meshes where even rank-0 topology is a concern, use
distribute_basic_mesh_collaborative(), which broadcasts topology via
shared memory (one copy per node rather than one per rank).
See MPI Distribute Mesh-first parallel workflow (distribute_basic_mesh) for full details.
Fix — use ``in_place=True`` with distribute()
If you must use distribute(), pass in_place=True so that the full
domain object on rank 0 is freed as each submesh is sent:
domain = distribute(domain, in_place=True)
SWW output errors
``ValueError: cannot reshape array of size N into shape (1, M)``
This error occurs when two MPI ranks write to the same SWW file. It is
almost always caused by all ranks using the default domain name 'domain'
(i.e. domain.set_name() was never called), so every rank writes to
domain.sww and they collide.
Fix
Call domain.set_name() before the evolve loop:
domain.set_name('my_simulation')
For parallel runs Parallel_domain automatically appends
_P<nproc>_<rank> to the name, producing separate files
my_simulation_P4_0.sww, my_simulation_P4_1.sww, etc. Merge them
afterwards with:
domain.sww_merge(delete_old=True)
SWW file grows unexpectedly large
Each yieldstep adds a time slice to the SWW file. Reduce file size by:
Increasing
yieldstep(write output less frequently)Using
outputstepto decouple the yield interval from the output interval — see Setting up the Evolve loopStoring fewer quantities:
domain.set_quantities_to_be_stored({ 'stage': 2, 'elevation': 1, })
Suppressing output entirely:
domain.set_quantities_to_be_stored(None)
Boundary tag errors
``Exception: Tag “X” provided does not exist in the domain``
The tag name passed to set_boundary() does not match any tag in the
mesh. Check the exact tag names the mesh defines:
print(domain.get_boundary_tags())
Common causes:
Typo in the tag name (
'Left'vs'left')Using tags from a different mesh file
For rectangular domains the built-in tags are exactly
'left','right','top','bottom'
``Exception: ERROR (domain.py): Tag “X” has not been bound to a boundary object``
Every tag that exists in the mesh must appear in the set_boundary()
call. If a tag is present in the mesh but not in your boundary map, ANUGA
raises this error.
Fix — assign a boundary to every tag, using Reflective_boundary as a
default for any tag you do not want to treat specially:
Br = anuga.Reflective_boundary(domain)
domain.set_boundary({
'left': anuga.Dirichlet_boundary([0.5, 0.0, 0.0]),
'right': Br,
'top': Br,
'bottom': Br,
})
Mesh file errors
``IOError: File X could not be opened``
ANUGA could not read the mesh file. Common causes:
The file does not exist at the given path. Check with an absolute path:
import os print(os.path.exists('my_mesh.tsh'))
The file extension is not
.tshor.msh. Only these two extensions are recognised byimport_mesh_file/create_domain_from_file.The
.tshfile is malformed (e.g. truncated, wrong encoding). Open it in a text editor to check its structure.
``IOError: Extension .xyz is unknown``
create_domain_from_file only accepts .tsh and .msh files. To
load elevation from a raster, convert it first:
anuga.asc2dem('elevation.asc')
anuga.dem2pts('elevation.dem')
domain.set_quantity('elevation', filename='elevation.pts')
Installation and import errors
``ModuleNotFoundError: No module named ‘anuga’``
The conda environment containing ANUGA is not active, or ANUGA has not been installed. Activate the environment and verify:
conda activate anuga_env
python -c "import anuga; print(anuga.__version__)"
``ImportError`` referencing a Cython extension (e.g. ``_quantity_ext``)``
The Cython/C extensions have not been compiled, or were compiled for a different Python version. Reinstall:
pip install --no-build-isolation -v .
Slow import / ``anuga`` takes many seconds to import
This is usually caused by matplotlib being imported at module load time
on a system with a slow display backend. Set a non-interactive backend
before importing:
import matplotlib
matplotlib.use('Agg')
import anuga
Or set it in your environment:
export MPLBACKEND=Agg
Performance issues
The simulation is slower than expected
Check
OMP_NUM_THREADS. By default ANUGA uses one thread. Set it to the number of physical cores on your machine:OMP_NUM_THREADS=8 python my_script.py
Check the number of triangles per MPI rank. Below roughly 1000–2000 triangles per rank, MPI communication overhead outweighs the speedup. Use fewer ranks or a larger mesh.
Check the flow algorithm.
DE1is generally faster thanDE0for large meshes with many wet/dry transitions:domain.set_flow_algorithm('DE1')
Use
domain.print_timestepping_statistics()inside the evolve loop to see the timestep distribution — very small timesteps indicate a CFL constraint from a locally steep gradient or a very fine mesh region.
Getting further help
If your issue is not covered here:
Check the GitHub issue tracker for similar reports.
Open a new issue with a minimal reproducible example, the full traceback, your ANUGA version (
python -c "import anuga; print(anuga.__version__)"), and your platform (OS, Python version, MPI library).