peclet-cu13 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ # Phase 0 toolchain artifacts
2
+ /build/
3
+ /extern/
4
+
5
+ # MkDocs site output (built in CI, published to Pages)
6
+ /site/
7
+
8
+ # The single suite-level development virtualenv (see CLAUDE.md). One venv serves every
9
+ # submodule: coupling composes flow+dem in one interpreter, pnm already borrowed flow's, and
10
+ # the per-project venvs had drifted (three nanobind copies, three numpy versions).
11
+ /.venv/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Frank Peters
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,142 @@
1
+ Metadata-Version: 2.5
2
+ Name: peclet-cu13
3
+ Version: 0.7.0
4
+ Summary: GPU-accelerated & parallel simulation of transport phenomena (CFD, DEM, Voronoi) — single-GPU CUDA family metapackage
5
+ Project-URL: Homepage, https://github.com/computational-chemical-engineering/peclet
6
+ Project-URL: Documentation, https://github.com/computational-chemical-engineering/peclet
7
+ Author-email: Frank Peters <e.a.j.f.peters@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Requires-Python: >=3.10
11
+ Requires-Dist: peclet-dem-cu13==0.5.0
12
+ Requires-Dist: peclet-flow-cu13==0.5.0
13
+ Requires-Dist: peclet-morton==0.2.1
14
+ Requires-Dist: peclet-pnm-cu13==0.1.1
15
+ Requires-Dist: peclet-voro-cu13==0.5.0
16
+ Provides-Extra: cfd-dem
17
+ Requires-Dist: peclet-coupling==0.4.0; extra == 'cfd-dem'
18
+ Provides-Extra: mpi
19
+ Requires-Dist: peclet-core==0.6.0; extra == 'mpi'
20
+ Description-Content-Type: text/markdown
21
+
22
+ # Peclet
23
+
24
+ [![PyPI version](https://img.shields.io/pypi/v/peclet.svg)](https://pypi.org/project/peclet/)
25
+ [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://pypi.org/project/peclet/)
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
27
+ [![Docs](https://img.shields.io/badge/docs-online-brightgreen.svg)](https://computational-chemical-engineering.github.io/peclet/)
28
+ [![Docs build](https://github.com/computational-chemical-engineering/peclet/actions/workflows/site.yml/badge.svg)](https://github.com/computational-chemical-engineering/peclet/actions/workflows/site.yml)
29
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21132445.svg)](https://doi.org/10.5281/zenodo.21132445)
30
+
31
+ A suite of codes for **simulation of transport phenomena** — Eulerian (CFD/Navier–Stokes), Lagrangian
32
+ (DEM/particle packing) and mixed (Voronoi) methods — sharing one MPI **block domain decomposition**
33
+ with efficient **asynchronous ghost-layer exchange**, **SDF**-described solids, a common **immersed
34
+ boundary** methodology, **GPU** support, and **Python bindings**.
35
+
36
+ The name nods to the [Péclet number](https://en.wikipedia.org/wiki/P%C3%A9clet_number) — the ratio of
37
+ advective to diffusive transport, the dimensionless heart of transport phenomena.
38
+
39
+ 📖 **Documentation site:** <https://computational-chemical-engineering.github.io/peclet/> — the suite's front
40
+ door (Python API reference, install/deployment guide, design docs, links to each code's Doxygen API).
41
+ Built from `docs/` via MkDocs ([mkdocs.yml](mkdocs.yml)).
42
+
43
+ 🧪 **Examples gallery:** <https://computational-chemical-engineering.github.io/peclet-examples/> — runnable,
44
+ validated notebooks (single-phase and two-phase flow, packings, DEM, CFD-DEM, scaling benchmarks), each
45
+ with an *Open in Colab* button.
46
+
47
+ This is an **umbrella repository**: each code is a git **submodule** (its own repo and history); this
48
+ repo pins compatible commits and holds the shared design docs.
49
+
50
+ ## Clone
51
+
52
+ ```bash
53
+ git clone --recursive git@github.com:computational-chemical-engineering/peclet.git
54
+ # or, after a plain clone:
55
+ git submodule update --init --recursive
56
+ ```
57
+
58
+ ## Layout
59
+
60
+ | Submodule | Role |
61
+ |-----------|------|
62
+ | `core/` | **Shared infrastructure** (header-only C++20 + MPI, optional Kokkos): ORB block decomposition, async grid ghost-layer exchange + Lagrangian particle migration/ghosts, SDF geometry, VTI I/O. Every method depends on it. |
63
+ | `flow/` | Eulerian **Kokkos** incompressible Navier–Stokes (porous media; staggered MAC grid + cut-cell IBM). Complete, validated, MPI-optional distributed solver on `core`. |
64
+ | `pnm/` | **Kokkos** pore-network extraction from SDF geometry (pores, watershed segmentation, throat topology). Split out of `flow`. |
65
+ | `dem/` | Lagrangian **Kokkos + ArborX** DEM/XPBD particle packing. Full XPBD step with a validated distributed `step_mpi` (core particle halo). |
66
+ | `voro/` | Mixed Lagrangian/Eulerian dynamic 3D Voronoi tessellation (**Kokkos** device tessellator; periodic & Lees–Edwards), mesh generator and Navier–Stokes on the Voronoi mesh. |
67
+ | `coupling/` | **CFD-DEM coupling** of `flow` + `dem` (Kokkos kernels + Python drivers): unresolved volume-averaged drag and resolved cut-cell coupling. |
68
+ | `morton/` | Morton/Z-order spatial-index primitive — arithmetic directly in Morton space (header-only C++17 + BMI2/AVX-512, Python). |
69
+
70
+ The compute codes are **Kokkos**-based; the same source runs on CUDA, HIP (AMD/LUMI), and OpenMP backends,
71
+ chosen by the bootstrapped install prefix (`tools/bootstrap_deps.sh`). The reusable parts of the original
72
+ `block_decomposer` prototype were extracted into `core/`.
73
+
74
+ ## Shared design docs
75
+
76
+ `docs/` is the cross-code contract every method follows:
77
+ [ARCHITECTURE](docs/ARCHITECTURE.md) · [CONVENTIONS](docs/CONVENTIONS.md) · [STYLE](docs/STYLE.md) ·
78
+ [INTERFACES](docs/INTERFACES.md) · [ROADMAP](docs/ROADMAP.md) ·
79
+ [PORTABILITY](docs/PORTABILITY.md). See `CLAUDE.md` for an agent-facing overview.
80
+
81
+ ## Install & run (Python)
82
+
83
+ Everything ships under one **`peclet` namespace** — installable parts of one family:
84
+
85
+ | PyPI package | Import | Role |
86
+ |---|---|---|
87
+ | `peclet-morton` | `peclet.morton` | Morton/Z-order spatial index |
88
+ | `peclet-flow` | `peclet.flow` | Eulerian incompressible Navier–Stokes solver |
89
+ | `peclet-pnm` | `peclet.pnm` | Pore-network extraction from SDF geometry |
90
+ | `peclet-dem` | `peclet.dem` | Lagrangian DEM/XPBD particle packing |
91
+ | `peclet-voro` | `peclet.voro` | Dynamic Voronoi tessellation + mesh generator |
92
+ | `peclet-coupling` | `peclet.coupling` | CFD-DEM coupling drivers over flow + dem — sdist only (`peclet[cfd-dem]`) |
93
+ | `peclet-core` | `peclet.core` (`.mpi`, `.amr`, `.geom`) | Shared infra (particle halo, AMR, analytic-SDF scenes) — sdist only (`peclet[mpi]`) |
94
+ | `peclet` | — | metapackage: `pip install peclet` pulls the CPU family |
95
+ | `peclet-cu13` | — | metapackage: `pip install peclet-cu13` pulls the CUDA family (`peclet-{flow,pnm,dem,voro}-cu13`) |
96
+
97
+ **Multicore CPU (OpenMP):** the compute packages ship **self-contained wheels** — `pip install peclet`
98
+ (or an individual `pip install peclet-flow`) just works and runs multi-threaded (`OMP_NUM_THREADS`).
99
+
100
+ **Single NVIDIA GPU:** `pip install peclet-cu13` — CUDA wheels of the same family (only the NVIDIA driver is
101
+ needed; not alongside `peclet` in one venv).
102
+
103
+ **AMD/HIP and multi-rank MPI:** a wheel cannot carry an MPI ABI, so you build the packages from source
104
+ against a Kokkos prefix, or use a container. Because the backend (Serial / OpenMP / CUDA / HIP) is compiled
105
+ in, you build for your hardware — [**docs/DEPLOYMENT.md**](docs/DEPLOYMENT.md) is the guide: the backend×MPI
106
+ matrix, `pip install` recipes per environment, the Snellius site install (`tools/hpc/`), and the
107
+ **Apptainer containers** (GHCR, built by CI on every release) for Snellius (CUDA) and LUMI (HIP) in
108
+ [`containers/`](containers).
109
+
110
+ ## Continuous integration & docs
111
+
112
+ Each submodule carries its own `.github/workflows/`: a **CI** workflow (build + test — `core` and `morton`
113
+ run full CPU/MPI suites; the Kokkos codes build the OpenMP host backend and run their single-rank suites),
114
+ a **Documentation** workflow that builds the Doxygen API docs and publishes them to that repo's GitHub
115
+ Pages, and a **Release** workflow that builds the sdist + CPU wheels (+ the CUDA wheel) and publishes them
116
+ to PyPI on a version tag. The umbrella adds the documentation site (`site.yml`), the metapackages
117
+ (`release.yml`) and the containers (`containers.yml`). The whole procedure is written down in
118
+ [docs/RELEASE.md](docs/RELEASE.md).
119
+
120
+ ## Contributing & community
121
+
122
+ Contributions are welcome — see **[CONTRIBUTING.md](CONTRIBUTING.md)** for the submodule dev setup,
123
+ build/test, and PR flow. Participation is governed by the [Contributor Covenant](CODE_OF_CONDUCT.md).
124
+ Report security issues privately per the [Security Policy](SECURITY.md). Release history lives in the
125
+ [CHANGELOG](CHANGELOG.md).
126
+
127
+ ## Citing
128
+
129
+ If you use Peclet in your research, please cite it. Each release is archived on Zenodo:
130
+
131
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21132445.svg)](https://doi.org/10.5281/zenodo.21132445)
132
+
133
+ - **All versions (concept DOI):** [10.5281/zenodo.21132445](https://doi.org/10.5281/zenodo.21132445) — always resolves to the latest release; use this unless you need to pin an exact version.
134
+ - **A specific version:** the Zenodo record lists a version DOI per release, and each [GitHub release](https://github.com/computational-chemical-engineering/peclet/releases) links to its own.
135
+
136
+ Machine-readable metadata is in [CITATION.cff](CITATION.cff) — use GitHub's "Cite this repository"
137
+ button for ready-made BibTeX/APA.
138
+
139
+ ## Note on submodule pins
140
+
141
+ This umbrella pins each submodule to a compatible commit on `main`. Update to the latest upstream with
142
+ `git submodule update --remote` followed by a commit here that bumps the pointers.
@@ -0,0 +1,121 @@
1
+ # Peclet
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/peclet.svg)](https://pypi.org/project/peclet/)
4
+ [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://pypi.org/project/peclet/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+ [![Docs](https://img.shields.io/badge/docs-online-brightgreen.svg)](https://computational-chemical-engineering.github.io/peclet/)
7
+ [![Docs build](https://github.com/computational-chemical-engineering/peclet/actions/workflows/site.yml/badge.svg)](https://github.com/computational-chemical-engineering/peclet/actions/workflows/site.yml)
8
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21132445.svg)](https://doi.org/10.5281/zenodo.21132445)
9
+
10
+ A suite of codes for **simulation of transport phenomena** — Eulerian (CFD/Navier–Stokes), Lagrangian
11
+ (DEM/particle packing) and mixed (Voronoi) methods — sharing one MPI **block domain decomposition**
12
+ with efficient **asynchronous ghost-layer exchange**, **SDF**-described solids, a common **immersed
13
+ boundary** methodology, **GPU** support, and **Python bindings**.
14
+
15
+ The name nods to the [Péclet number](https://en.wikipedia.org/wiki/P%C3%A9clet_number) — the ratio of
16
+ advective to diffusive transport, the dimensionless heart of transport phenomena.
17
+
18
+ 📖 **Documentation site:** <https://computational-chemical-engineering.github.io/peclet/> — the suite's front
19
+ door (Python API reference, install/deployment guide, design docs, links to each code's Doxygen API).
20
+ Built from `docs/` via MkDocs ([mkdocs.yml](mkdocs.yml)).
21
+
22
+ 🧪 **Examples gallery:** <https://computational-chemical-engineering.github.io/peclet-examples/> — runnable,
23
+ validated notebooks (single-phase and two-phase flow, packings, DEM, CFD-DEM, scaling benchmarks), each
24
+ with an *Open in Colab* button.
25
+
26
+ This is an **umbrella repository**: each code is a git **submodule** (its own repo and history); this
27
+ repo pins compatible commits and holds the shared design docs.
28
+
29
+ ## Clone
30
+
31
+ ```bash
32
+ git clone --recursive git@github.com:computational-chemical-engineering/peclet.git
33
+ # or, after a plain clone:
34
+ git submodule update --init --recursive
35
+ ```
36
+
37
+ ## Layout
38
+
39
+ | Submodule | Role |
40
+ |-----------|------|
41
+ | `core/` | **Shared infrastructure** (header-only C++20 + MPI, optional Kokkos): ORB block decomposition, async grid ghost-layer exchange + Lagrangian particle migration/ghosts, SDF geometry, VTI I/O. Every method depends on it. |
42
+ | `flow/` | Eulerian **Kokkos** incompressible Navier–Stokes (porous media; staggered MAC grid + cut-cell IBM). Complete, validated, MPI-optional distributed solver on `core`. |
43
+ | `pnm/` | **Kokkos** pore-network extraction from SDF geometry (pores, watershed segmentation, throat topology). Split out of `flow`. |
44
+ | `dem/` | Lagrangian **Kokkos + ArborX** DEM/XPBD particle packing. Full XPBD step with a validated distributed `step_mpi` (core particle halo). |
45
+ | `voro/` | Mixed Lagrangian/Eulerian dynamic 3D Voronoi tessellation (**Kokkos** device tessellator; periodic & Lees–Edwards), mesh generator and Navier–Stokes on the Voronoi mesh. |
46
+ | `coupling/` | **CFD-DEM coupling** of `flow` + `dem` (Kokkos kernels + Python drivers): unresolved volume-averaged drag and resolved cut-cell coupling. |
47
+ | `morton/` | Morton/Z-order spatial-index primitive — arithmetic directly in Morton space (header-only C++17 + BMI2/AVX-512, Python). |
48
+
49
+ The compute codes are **Kokkos**-based; the same source runs on CUDA, HIP (AMD/LUMI), and OpenMP backends,
50
+ chosen by the bootstrapped install prefix (`tools/bootstrap_deps.sh`). The reusable parts of the original
51
+ `block_decomposer` prototype were extracted into `core/`.
52
+
53
+ ## Shared design docs
54
+
55
+ `docs/` is the cross-code contract every method follows:
56
+ [ARCHITECTURE](docs/ARCHITECTURE.md) · [CONVENTIONS](docs/CONVENTIONS.md) · [STYLE](docs/STYLE.md) ·
57
+ [INTERFACES](docs/INTERFACES.md) · [ROADMAP](docs/ROADMAP.md) ·
58
+ [PORTABILITY](docs/PORTABILITY.md). See `CLAUDE.md` for an agent-facing overview.
59
+
60
+ ## Install & run (Python)
61
+
62
+ Everything ships under one **`peclet` namespace** — installable parts of one family:
63
+
64
+ | PyPI package | Import | Role |
65
+ |---|---|---|
66
+ | `peclet-morton` | `peclet.morton` | Morton/Z-order spatial index |
67
+ | `peclet-flow` | `peclet.flow` | Eulerian incompressible Navier–Stokes solver |
68
+ | `peclet-pnm` | `peclet.pnm` | Pore-network extraction from SDF geometry |
69
+ | `peclet-dem` | `peclet.dem` | Lagrangian DEM/XPBD particle packing |
70
+ | `peclet-voro` | `peclet.voro` | Dynamic Voronoi tessellation + mesh generator |
71
+ | `peclet-coupling` | `peclet.coupling` | CFD-DEM coupling drivers over flow + dem — sdist only (`peclet[cfd-dem]`) |
72
+ | `peclet-core` | `peclet.core` (`.mpi`, `.amr`, `.geom`) | Shared infra (particle halo, AMR, analytic-SDF scenes) — sdist only (`peclet[mpi]`) |
73
+ | `peclet` | — | metapackage: `pip install peclet` pulls the CPU family |
74
+ | `peclet-cu13` | — | metapackage: `pip install peclet-cu13` pulls the CUDA family (`peclet-{flow,pnm,dem,voro}-cu13`) |
75
+
76
+ **Multicore CPU (OpenMP):** the compute packages ship **self-contained wheels** — `pip install peclet`
77
+ (or an individual `pip install peclet-flow`) just works and runs multi-threaded (`OMP_NUM_THREADS`).
78
+
79
+ **Single NVIDIA GPU:** `pip install peclet-cu13` — CUDA wheels of the same family (only the NVIDIA driver is
80
+ needed; not alongside `peclet` in one venv).
81
+
82
+ **AMD/HIP and multi-rank MPI:** a wheel cannot carry an MPI ABI, so you build the packages from source
83
+ against a Kokkos prefix, or use a container. Because the backend (Serial / OpenMP / CUDA / HIP) is compiled
84
+ in, you build for your hardware — [**docs/DEPLOYMENT.md**](docs/DEPLOYMENT.md) is the guide: the backend×MPI
85
+ matrix, `pip install` recipes per environment, the Snellius site install (`tools/hpc/`), and the
86
+ **Apptainer containers** (GHCR, built by CI on every release) for Snellius (CUDA) and LUMI (HIP) in
87
+ [`containers/`](containers).
88
+
89
+ ## Continuous integration & docs
90
+
91
+ Each submodule carries its own `.github/workflows/`: a **CI** workflow (build + test — `core` and `morton`
92
+ run full CPU/MPI suites; the Kokkos codes build the OpenMP host backend and run their single-rank suites),
93
+ a **Documentation** workflow that builds the Doxygen API docs and publishes them to that repo's GitHub
94
+ Pages, and a **Release** workflow that builds the sdist + CPU wheels (+ the CUDA wheel) and publishes them
95
+ to PyPI on a version tag. The umbrella adds the documentation site (`site.yml`), the metapackages
96
+ (`release.yml`) and the containers (`containers.yml`). The whole procedure is written down in
97
+ [docs/RELEASE.md](docs/RELEASE.md).
98
+
99
+ ## Contributing & community
100
+
101
+ Contributions are welcome — see **[CONTRIBUTING.md](CONTRIBUTING.md)** for the submodule dev setup,
102
+ build/test, and PR flow. Participation is governed by the [Contributor Covenant](CODE_OF_CONDUCT.md).
103
+ Report security issues privately per the [Security Policy](SECURITY.md). Release history lives in the
104
+ [CHANGELOG](CHANGELOG.md).
105
+
106
+ ## Citing
107
+
108
+ If you use Peclet in your research, please cite it. Each release is archived on Zenodo:
109
+
110
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21132445.svg)](https://doi.org/10.5281/zenodo.21132445)
111
+
112
+ - **All versions (concept DOI):** [10.5281/zenodo.21132445](https://doi.org/10.5281/zenodo.21132445) — always resolves to the latest release; use this unless you need to pin an exact version.
113
+ - **A specific version:** the Zenodo record lists a version DOI per release, and each [GitHub release](https://github.com/computational-chemical-engineering/peclet/releases) links to its own.
114
+
115
+ Machine-readable metadata is in [CITATION.cff](CITATION.cff) — use GitHub's "Cite this repository"
116
+ button for ready-made BibTeX/APA.
117
+
118
+ ## Note on submodule pins
119
+
120
+ This umbrella pins each submodule to a compatible commit on `main`. Update to the latest upstream with
121
+ `git submodule update --remote` followed by a commit here that bumps the pointers.
@@ -0,0 +1,50 @@
1
+ # Benchmarks
2
+
3
+ ## `profile_mpi_flow.py` — distributed CFD communication-overhead (weak scaling)
4
+
5
+ Measures the **MPI communication overhead** of the distributed staggered-MAC Navier–Stokes solver
6
+ (`peclet.flow`, multi-rank) — the halo exchange plus the global pressure-solve all-reduces — using a
7
+ **weak-scaling** setup where every rank/GPU does *identical* work.
8
+
9
+ ### How it isolates communication
10
+
11
+ - The geometry is a **periodic random sphere packing** of `L³` cells (one tile).
12
+ - Tiles are **glued periodically** into the global domain: for `np` ranks it picks a balanced rank grid
13
+ `px·py·pz = np`, makes the global grid `L·px × L·py × L·pz`, and fills each rank's block from the same
14
+ periodic tile. The global field is therefore seamless and **every rank simulates the same subdomain**.
15
+ - Per-rank work is thus **constant** as `np` grows. The only things that change with `np` are the
16
+ **ghost-layer halo exchange** (every step) and the **global MG-PCG pressure solve** (couples all ranks).
17
+ So the rise in per-step wall-time = the communication tax (+ any non-weak-scalable growth in the solver,
18
+ visible as a climbing `pressure_iters`).
19
+
20
+ Ideal weak scaling ⇒ per-step time is **flat** vs `np`. **The packing generation is not timed** (only the
21
+ warm-then-timed `step()` loop is).
22
+
23
+ ### Run
24
+
25
+ ```bash
26
+ # local CPU/OpenMP sweep — compare the per-step time across np:
27
+ for n in 1 2 4 8; do mpirun -np $n python benchmarks/profile_mpi_flow.py --L 48 --steps 100 --csv wk.csv; done
28
+
29
+ # on a cluster, launch through the site bind-wrapper (multi-GPU or multi-node CPU):
30
+ srun containers/snellius-run.sh peclet-cuda_0.1.0-sm80.sif benchmarks/profile_mpi_flow.py --L 128 --steps 200 --csv wk.csv
31
+ ```
32
+
33
+ Key flags: `--L` per-rank grid (raise until a GPU is saturated, e.g. 128–192), `--steps`, `--warmup`,
34
+ `--phi` packing solid fraction, `--csv` appends one row per run.
35
+
36
+ ### Reading the output
37
+
38
+ ```
39
+ [Cuda] np=8 grid=2x2x2 global=256x256x256 per-rank=128x128x128=2097152 cells (~1900 spheres/tile)
40
+ per-step: max 12.3 ms min 12.1 ms imbalance 1.6% pressure_iters=14 170.5 Mcell/s/rank
41
+ ```
42
+
43
+ - **per-step max** vs `np` — the weak-scaling curve; the climb over the `np=1` value is the comm overhead.
44
+ - **imbalance** — should stay near 0 (identical tiles); a large value means the rank grid didn't tile evenly
45
+ (use `np` = a product of small factors, ideally powers of two).
46
+ - **pressure_iters** — if this climbs with `np`, the pressure solve is the non-`O(N)` cost, not the halo.
47
+ - **Mcell/s/rank** — per-rank throughput; on one node this should stay near the single-rank device number.
48
+
49
+ Requires `peclet.flow` built with `PECLET_FLOW_MPI=ON` (`flow.has_mpi == True`) and `mpi4py`. The GPU
50
+ containers (`peclet-cuda`, `peclet-hip`) and the CPU container are built with the flag on.
@@ -0,0 +1,101 @@
1
+ # Containers
2
+
3
+ Apptainer (Singularity) definition files that bake the toolchain + a bootstrapped Kokkos/ArborX prefix
4
+ and pip-install the full `peclet.*` family (flow, dem, voro, core, morton). Apptainer is the de-facto
5
+ container runtime on HPC (both **Snellius** and **LUMI** use it; Docker is not permitted on the compute
6
+ nodes).
7
+
8
+ | File | Backend | Target | Published image |
9
+ |------|---------|--------|-----------------|
10
+ | `cpu.def` | Kokkos OpenMP + Serial | laptops, CI, CPU HPC partitions | `peclet-cpu` |
11
+ | `cuda.def` | Kokkos CUDA | **Snellius** (A100 `sm_80`; H100 `sm_90`) | `peclet-cuda:*-sm80` / `:*-sm90` |
12
+ | `hip.def` | Kokkos HIP | **LUMI-G** (MI250X `gfx90a`) | `peclet-hip:*-gfx90a` |
13
+
14
+ ## Pre-built images (GHCR)
15
+
16
+ The [`.github/workflows/containers.yml`](../.github/workflows/containers.yml) workflow builds these on
17
+ version tags and publishes them to the GitHub Container Registry. Pull on a login node without building:
18
+
19
+ ```bash
20
+ apptainer pull oras://ghcr.io/computational-chemical-engineering/peclet-cpu:0.7.0
21
+ apptainer pull oras://ghcr.io/computational-chemical-engineering/peclet-cuda:0.7.0-sm80 # Snellius A100
22
+ apptainer pull oras://ghcr.io/computational-chemical-engineering/peclet-hip:0.7.0-gfx90a # LUMI MI250X
23
+ ```
24
+
25
+ Or build them yourself from the `.def` files below.
26
+
27
+ ## Build
28
+
29
+ Run from the **suite root** so the `%files . /opt/peclet` section copies the full source tree
30
+ (check out submodules first):
31
+
32
+ ```bash
33
+ git submodule update --init --recursive
34
+ apptainer build peclet-cpu.sif containers/cpu.def
35
+ # GPU images compile device code for a chosen arch (no GPU needed at build time):
36
+ KOKKOS_ARCH=AMPERE80 CUDA_ARCH=80 apptainer build peclet-cuda.sif containers/cuda.def # A100
37
+ apptainer build peclet-hip.sif containers/hip.def
38
+ ```
39
+
40
+ The GPU images are large and slow to build (they compile Kokkos for the device arch); build them on a
41
+ build node, or pull/convert a prebuilt image. The arch is read from the build environment — see the
42
+ header comment in each `.def`.
43
+
44
+ ## Run
45
+
46
+ ```bash
47
+ # CPU, single process:
48
+ apptainer exec peclet-cpu.sif python3 -c "import peclet.flow, peclet.dem, peclet.morton"
49
+
50
+ # CPU, 4 MPI ranks (host mpirun launches one container per rank):
51
+ mpirun -np 4 apptainer exec peclet-cpu.sif python3 your_distributed_script.py
52
+
53
+ # NVIDIA GPU (Snellius) — --nv binds the host driver:
54
+ srun apptainer exec --nv peclet-cuda.sif python3 your_script.py
55
+
56
+ # AMD GPU (LUMI) — use the Cray-MPICH launcher wrapper (see below):
57
+ module load LUMI partition/G cray-mpich rocm
58
+ srun -n8 --gpus-per-node=8 containers/lumi-run.sh peclet-hip.sif your_script.py
59
+ ```
60
+
61
+ ## LUMI / Cray-MPICH (the `hip.def` MPI model)
62
+
63
+ LUMI-G runs **Cray-MPICH** over the **Slingshot-11** interconnect (libfabric `cxi` provider), not
64
+ OpenMPI. `hip.def` therefore uses the **MPICH-ABI hybrid** model:
65
+
66
+ 1. The container is **built against vanilla MPICH** (Ubuntu's MPICH 4.0 exports `libmpi.so.12`, the
67
+ same SONAME Cray-MPICH provides), so `dem`'s distributed step links the MPICH ABI.
68
+ 2. At **runtime**, [`lumi-run.sh`](lumi-run.sh) binds the host Cray-MPICH + libfabric + GPU-transport-
69
+ layer (GTL) libraries over the container's MPICH, so the app actually talks Slingshot and does
70
+ GPU-aware transfers. It injects `CRAY_LD_LIBRARY_PATH` (which the Cray PE sets once
71
+ `cray-mpich`/`rocm` are loaded) into the container and sets `MPICH_GPU_SUPPORT_ENABLED=1`.
72
+
73
+ ```bash
74
+ module load LUMI partition/G cray-mpich rocm # populates CRAY_LD_LIBRARY_PATH
75
+ srun -n8 --gpus-per-node=8 containers/lumi-run.sh peclet-hip.sif my_run.py
76
+ # override the host-library bind list if LUMI's layout differs:
77
+ PECLET_LUMI_BIND=/opt/cray,/var/spool/slurmd,/usr/lib64/libcxi.so.1 \
78
+ srun ... containers/lumi-run.sh peclet-hip.sif my_run.py
79
+ ```
80
+
81
+ Notes / gotchas:
82
+ - **ROCm version.** Pin the `hip.def` base (`rocm/dev-ubuntu-22.04:6.2.4`) to **≤** the LUMI driver's
83
+ ROCm (`module show rocm`); a container ROCm newer than the host driver fails at load.
84
+ - **GTL vs hsa.** The GPU-transport-layer lib (`libmpi_gtl_hsa.so`) is built against the host ROCm; if
85
+ you hit hsa-symbol errors, also bind the host `/opt/rocm` ahead of the container's in
86
+ `PECLET_LUMI_BIND` / the injected `LD_LIBRARY_PATH`.
87
+ - **Simpler path.** If your project has LUMI's `singularity-bindings` (EasyBuild) module, load it
88
+ instead — it sets the bind list + `LD_LIBRARY_PATH` for you, and `lumi-run.sh` will compose with it.
89
+
90
+ ## Snellius / other HPC notes
91
+
92
+ - **MPI ABI.** Same hybrid model: `srun`/`mpirun` on the host, MPI inside the container. `cpu.def` and
93
+ `cuda.def` ship OpenMPI; if your Snellius MPI module is OpenMPI this composes directly, otherwise bind
94
+ the host MPI or rebuild against the matching ABI.
95
+ - **GPU-aware MPI (Snellius).** Use the CUDA-aware OpenMPI module + `--nv`. The codes host-stage the
96
+ halo by default and opt into GPU-aware MPI explicitly — see `core/docs/cuda-aware-mpi.md`.
97
+ - **Arch.** `cuda.def` defaults to A100 (`sm_80`); pass `KOKKOS_ARCH=HOPPER90 CUDA_ARCH=90` for H100.
98
+ `hip.def` targets MI250X (`gfx90a`).
99
+
100
+ These `.def` files have **not** been built/tested in CI (no GPU runners); treat them as a starting
101
+ point to build on the target cluster. Roadblocks/assumptions are noted in `../docs/DEPLOYMENT.md`.
@@ -0,0 +1,57 @@
1
+ # The `peclet-cu13` metapackage — the single-GPU CUDA twin of `peclet`. `pip install peclet-cu13` pulls
2
+ # the CUDA-13 builds of the compute members (`peclet-flow-cu13`, `peclet-pnm-cu13`, `peclet-dem-cu13`,
3
+ # `peclet-voro-cu13`; Kokkos-CUDA static inside each module, libcudart from the `nvidia-cuda-runtime`
4
+ # dependency wheel, only the NVIDIA driver host-provided) plus the pure-CPU `peclet-morton`. It ships NO
5
+ # code of its own (the `peclet` PEP-420 namespace is owned by the member packages) — purely a convenience
6
+ # dependency set, exactly like ../pyproject.toml.
7
+ #
8
+ # pip install peclet-cu13 # CUDA family: peclet-morton + peclet-{flow,pnm,dem,voro}-cu13
9
+ # pip install peclet-cu13[mpi] # + peclet-core (MPI particle halo / AMR — builds from sdist, needs MPI)
10
+ #
11
+ # `peclet-cu13` and `peclet` are MUTUALLY EXCLUSIVE in one environment (both install the same
12
+ # `peclet.<member>` imports; the CuPy `cupy` vs `cupy-cuda12x` model) — use one venv per backend.
13
+ # AMD/HIP and multi-GPU MPI stay source/container builds (docs/DEPLOYMENT.md).
14
+ #
15
+ # The umbrella release workflow's build-cu13 job copies this over pyproject.toml; keep the `==` pins in
16
+ # lockstep with ../pyproject.toml (tools/release/check_release_state.sh compares them).
17
+
18
+ [build-system]
19
+ requires = ["hatchling"]
20
+ build-backend = "hatchling.build"
21
+
22
+ [project]
23
+ name = "peclet-cu13"
24
+ version = "0.7.0"
25
+ description = "GPU-accelerated & parallel simulation of transport phenomena (CFD, DEM, Voronoi) — single-GPU CUDA family metapackage"
26
+ readme = "README.md"
27
+ requires-python = ">=3.10"
28
+ license = "MIT"
29
+ license-files = ["LICENSE"]
30
+ authors = [{ name = "Frank Peters", email = "e.a.j.f.peters@gmail.com" }]
31
+ dependencies = [
32
+ "peclet-morton==0.2.1",
33
+ "peclet-flow-cu13==0.5.0",
34
+ "peclet-pnm-cu13==0.1.1",
35
+ "peclet-dem-cu13==0.5.0",
36
+ "peclet-voro-cu13==0.5.0",
37
+ ]
38
+
39
+ [project.optional-dependencies]
40
+ # peclet-core is sdist-only (MPI particle halo + Kokkos AMR): installing it builds from source and needs
41
+ # an MPI toolchain (+ optional Kokkos prefix for the AMR module).
42
+ mpi = ["peclet-core==0.6.0"]
43
+ # peclet-coupling is the unresolved point-particle CFD-DEM coupling of peclet.flow + peclet.dem
44
+ # (sdist-only: builds its Kokkos kernels from source against a bootstrapped prefix).
45
+ cfd-dem = ["peclet-coupling==0.4.0"]
46
+
47
+ [project.urls]
48
+ Homepage = "https://github.com/computational-chemical-engineering/peclet"
49
+ Documentation = "https://github.com/computational-chemical-engineering/peclet"
50
+
51
+ # No Python package is built — this metapackage is dependencies only. Point hatchling at an empty target
52
+ # so it produces a valid (code-free) wheel/sdist.
53
+ [tool.hatch.build.targets.wheel]
54
+ bypass-selection = true
55
+
56
+ [tool.hatch.build.targets.sdist]
57
+ include = ["pyproject.toml", "README.md", "LICENSE"]