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.
- peclet_cu13-0.7.0/.gitignore +11 -0
- peclet_cu13-0.7.0/LICENSE +21 -0
- peclet_cu13-0.7.0/PKG-INFO +142 -0
- peclet_cu13-0.7.0/README.md +121 -0
- peclet_cu13-0.7.0/benchmarks/README.md +50 -0
- peclet_cu13-0.7.0/containers/README.md +101 -0
- peclet_cu13-0.7.0/pyproject.toml +57 -0
|
@@ -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
|
+
[](https://pypi.org/project/peclet/)
|
|
25
|
+
[](https://pypi.org/project/peclet/)
|
|
26
|
+
[](LICENSE)
|
|
27
|
+
[](https://computational-chemical-engineering.github.io/peclet/)
|
|
28
|
+
[](https://github.com/computational-chemical-engineering/peclet/actions/workflows/site.yml)
|
|
29
|
+
[](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
|
+
[](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
|
+
[](https://pypi.org/project/peclet/)
|
|
4
|
+
[](https://pypi.org/project/peclet/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://computational-chemical-engineering.github.io/peclet/)
|
|
7
|
+
[](https://github.com/computational-chemical-engineering/peclet/actions/workflows/site.yml)
|
|
8
|
+
[](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
|
+
[](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"]
|