Egg aims to be an excellent grid generator.
A structured multi-block grid generator with a TMOP-style mesh smoother / untangler. Written as a C++23 core and a python driver. AdaptiveCpp SYCL compute for performance portable kernels from one source (OMP, ROCm, CUDA).
These instructions have been tested on archlinux and Ubuntu 24.04 LTS.
Install podman.
From the repo root, activate the devcontainer environment:
./.devcontainer/podman-run.sh
You can now run the egg desktop UI:
uv run egg-desktop --dev
The --dev argument is needed on first run to download some javascript dependencies to egg/webui/static/vendor/.
You can omit it on subsequent runs unless you delete that directory.
For more detailed instructions and GPU installs, see DEVELOPING.md to get started.
A native window front-end ("code as CAD"): a Python geometry script on the left, a live SVG render of its topology/grid on the right, with the real untangle + TMOP pipeline streaming into the view.
uv sync --group ui # once
uv run --no-sync egg-desktop # native windowegg-desktop my_geometry.py opens a script; --watch follows it on disk;
--no-docs skips the Sphinx docs refresh (help → documentation).
The same UI also runs in a browser with egg-webui (serves
http://127.0.0.1:5001); --host 0.0.0.0 exposes it on the network for a
remote or headless host, and --reload restarts on source edits.
The basics:
- file → examples… opens any script under
examples/2D/; every example draws its topology and registers a run with the CLI-default settings. file → open/save/save as is a normal file workflow (Ctrl+S saves), and file → watch file — the expected day-to-day workflow — hides the built-in editor and follows the opened file on disk: edit in your own editor, the view updates on save, run/exports keep working. - run executes the pipeline a script registered via
egg_webui.run(grid, steps)in itsif __name__ == "__egg_webui__":block (the mirror image of the__main__guard — see any example) and animates the relaxing mesh with live energy / min-det charts; stop halts at the next chunk boundary. No registration, no run: the UI never invents a pipeline. In the examples, the block'sa = dict(...)is the knob panel (sweeps, smoother, device, …). - The view switches between the smoothed grid and the block
topology (tap elements for names + constraining geometry);
file → export su2 / svg downloads the mesh (with
tag_boundarymarkers) or the picture.
Start the app (uv sync --group ui). Then the full egg documentation is
accessible through help → documentation (Sphinx is a core dependency, so
the docs build without an extra group).
STEP/BREP import and the other OCCT-backed 3D operations (egg.io.cad:
imported solid faces into trimmed egg surfaces, boolean-carved flow domains)
need build123d, which is not a core
dependency. Install the optional cad group:
uv sync --group cadOnly the CAD import path needs it: 3D work from analytic primitives (Sphere,
Plane, Line3) or hand-authored NURBS surfaces has no OCCT dependency, and
the solver never sees OCCT regardless.
A --force-reinstall C++ rebuild drops the optional groups, and re-adding one
with uv sync --group cad reverts the core to its default precision. To hold a
precision (e.g. fp32, recommended on the GPU) and the groups together, set
SKBUILD_CMAKE_DEFINE once; see
DEVELOPING.md.
The circle demos accept --device {auto,cpu,gpu} to select the SYCL device:
# CPU
uv run examples/2D/circles/good-topo.py --tmop-sweeps 40 --device cpu
uv run examples/2D/circles/untangle.py --tmop-sweeps 1000 --device cpu
# GPU
uv run examples/2D/circles/good-topo.py --tmop-sweeps 40 --device gpu
uv run examples/2D/circles/untangle.py --tmop-sweeps 1000 --device gpuCommon flags: --plot-live (PyVista animation), --plot-grid (matplotlib
wireframe), --chunk N. Without a plot flag the demo runs headless and prints
per-chunk progress.
A generic AdaptiveCpp build exposes all visible SYCL devices (the OpenMP host
and the GPU). Use ACPP_VISIBILITY_MASK to restrict which backends are loaded:
# Force CPU only
ACPP_VISIBILITY_MASK=omp uv run ...
# Force GPU only (AMD)
ACPP_VISIBILITY_MASK=hip uv run ...Set OMP_NUM_THREADS=N to control CPU parallelism.
These should be taken with a grain of salt for now. They are mostly AI generated, but have proved useful in the development so far.
# Python tests (C++-dependent tests skip if cpp_core is not built)
ACPP_VISIBILITY_MASK=omp uv run pytest tests/
# C++ unit tests (Boost.UT)
ctest --test-dir buildParity tests cross-check the C++ sweep / untangle against the NumPy sequential
solver (local_relaxation_sweep), on both CPU and GPU.