peclet-dem 0.1.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_dem-0.1.0/.github/workflows/ci.yml +73 -0
- peclet_dem-0.1.0/.github/workflows/docs.yml +51 -0
- peclet_dem-0.1.0/.github/workflows/quality.yml +26 -0
- peclet_dem-0.1.0/.github/workflows/release.yml +53 -0
- peclet_dem-0.1.0/.gitignore +40 -0
- peclet_dem-0.1.0/.vscode/launch.json +57 -0
- peclet_dem-0.1.0/CMakeLists.txt +65 -0
- peclet_dem-0.1.0/LICENSE +21 -0
- peclet_dem-0.1.0/PKG-INFO +133 -0
- peclet_dem-0.1.0/README.md +119 -0
- peclet_dem-0.1.0/activate_env.sh +18 -0
- peclet_dem-0.1.0/cmake/PecletDeps.cmake +123 -0
- peclet_dem-0.1.0/debug_two_particles.py +60 -0
- peclet_dem-0.1.0/debug_vtp.py +40 -0
- peclet_dem-0.1.0/diag_cube_stick_slip.py +62 -0
- peclet_dem-0.1.0/diag_incline_roll.py +53 -0
- peclet_dem-0.1.0/docs/Doxyfile +66 -0
- peclet_dem-0.1.0/docs/packing_investigation.md +351 -0
- peclet_dem-0.1.0/docs/solver_details.md +204 -0
- peclet_dem-0.1.0/docs/velocity_solver_algorithm.md +57 -0
- peclet_dem-0.1.0/docs/visualization.md +79 -0
- peclet_dem-0.1.0/generate_particles.py +79 -0
- peclet_dem-0.1.0/mpi/CMakeLists.txt +39 -0
- peclet_dem-0.1.0/mpi/README.md +119 -0
- peclet_dem-0.1.0/mpi/bench_step.py +54 -0
- peclet_dem-0.1.0/mpi/driver_distributed.py +112 -0
- peclet_dem-0.1.0/mpi/multi_gpu_testing.md +188 -0
- peclet_dem-0.1.0/mpi/test_dem_scheme_b.cpp +203 -0
- peclet_dem-0.1.0/mpi/test_dem_scheme_c.cpp +194 -0
- peclet_dem-0.1.0/mpi/test_dem_step.cpp +198 -0
- peclet_dem-0.1.0/mpi/test_device_halo.cu +132 -0
- peclet_dem-0.1.0/mpi/test_particle_migration.cpp +152 -0
- peclet_dem-0.1.0/mpi/validate_exact.py +102 -0
- peclet_dem-0.1.0/mpi/validate_periodic.py +236 -0
- peclet_dem-0.1.0/mpi/verify_distributed.py +184 -0
- peclet_dem-0.1.0/notebooks/packing_analysis.ipynb +383 -0
- peclet_dem-0.1.0/pack.py +219 -0
- peclet_dem-0.1.0/pack_meter.py +119 -0
- peclet_dem-0.1.0/packaging/dem_init.py +16 -0
- peclet_dem-0.1.0/phase0_sphere_repro.py +70 -0
- peclet_dem-0.1.0/phase1_protocol_spheres.py +96 -0
- peclet_dem-0.1.0/phase2_protocol_fixed.py +150 -0
- peclet_dem-0.1.0/pyproject.toml +63 -0
- peclet_dem-0.1.0/python/export_vtp.py +88 -0
- peclet_dem-0.1.0/python/run_packing.py +43 -0
- peclet_dem-0.1.0/python/shapes/gen_hollow_cylinder.py +70 -0
- peclet_dem-0.1.0/python/simulation_script.py +13 -0
- peclet_dem-0.1.0/python/visualizer.py +7 -0
- peclet_dem-0.1.0/requirements.txt +4 -0
- peclet_dem-0.1.0/src/broadphase_arborx.hpp +95 -0
- peclet_dem-0.1.0/src/contact_preprocessing.hpp +186 -0
- peclet_dem-0.1.0/src/dem_bindings.cpp +249 -0
- peclet_dem-0.1.0/src/dem_portable.hpp +100 -0
- peclet_dem-0.1.0/src/integration.hpp +237 -0
- peclet_dem-0.1.0/src/io.hpp +91 -0
- peclet_dem-0.1.0/src/mpi_halo.hpp +415 -0
- peclet_dem-0.1.0/src/narrowphase.hpp +197 -0
- peclet_dem-0.1.0/src/output_sdf.hpp +116 -0
- peclet_dem-0.1.0/src/particles.hpp +87 -0
- peclet_dem-0.1.0/src/periodicity.hpp +69 -0
- peclet_dem-0.1.0/src/shapes_portable.hpp +113 -0
- peclet_dem-0.1.0/src/sim.hpp +610 -0
- peclet_dem-0.1.0/src/solver_friction.hpp +175 -0
- peclet_dem-0.1.0/src/solver_position.hpp +129 -0
- peclet_dem-0.1.0/src/solver_velocity.hpp +139 -0
- peclet_dem-0.1.0/stacking_test.vtp +20 -0
- peclet_dem-0.1.0/test.vtp +24 -0
- peclet_dem-0.1.0/test_bounce.py +68 -0
- peclet_dem-0.1.0/test_bounce_gravity.py +53 -0
- peclet_dem-0.1.0/tests/arborx/CMakeLists.txt +30 -0
- peclet_dem-0.1.0/tests/arborx/test_broadphase_arborx.cpp +106 -0
- peclet_dem-0.1.0/tests/arborx/test_pipeline.cpp +139 -0
- peclet_dem-0.1.0/tests/convergence_test.py +132 -0
- peclet_dem-0.1.0/tests/debug_2_particles.py +53 -0
- peclet_dem-0.1.0/tests/debug_crash.py +43 -0
- peclet_dem-0.1.0/tests/debug_fundamental.py +129 -0
- peclet_dem-0.1.0/tests/generate_dense_packing.py +0 -0
- peclet_dem-0.1.0/tests/generate_packing_cylinders.py +90 -0
- peclet_dem-0.1.0/tests/generate_packing_sdf.py +83 -0
- peclet_dem-0.1.0/tests/generate_periodic_packing.py +95 -0
- peclet_dem-0.1.0/tests/inspect_vti.py +0 -0
- peclet_dem-0.1.0/tests/kokkos/CMakeLists.txt +56 -0
- peclet_dem-0.1.0/tests/kokkos/test_contact_preprocessing.cpp +136 -0
- peclet_dem-0.1.0/tests/kokkos/test_integration.cpp +138 -0
- peclet_dem-0.1.0/tests/kokkos/test_narrowphase.cpp +206 -0
- peclet_dem-0.1.0/tests/kokkos/test_periodicity.cpp +107 -0
- peclet_dem-0.1.0/tests/kokkos/test_solver_friction.cpp +138 -0
- peclet_dem-0.1.0/tests/kokkos/test_solver_position.cpp +146 -0
- peclet_dem-0.1.0/tests/kokkos/test_solver_velocity.cpp +155 -0
- peclet_dem-0.1.0/tests/kokkos/test_thermostat.cpp +69 -0
- peclet_dem-0.1.0/tests/kokkos_mpi/CMakeLists.txt +44 -0
- peclet_dem-0.1.0/tests/kokkos_mpi/test_demstep_mpi.cpp +233 -0
- peclet_dem-0.1.0/tests/kokkos_mpi/test_rebalance_mpi.cpp +225 -0
- peclet_dem-0.1.0/tests/study_sphere_packing.py +114 -0
- peclet_dem-0.1.0/tests/test_hollow_cylinder_overlap.py +139 -0
- peclet_dem-0.1.0/tests/test_hollow_cylinder_overlap_2.py +139 -0
- peclet_dem-0.1.0/tests/test_periodicity_corner.cpp +104 -0
- peclet_dem-0.1.0/tests/test_physics.py +163 -0
- peclet_dem-0.1.0/tests/verify_cylinders.py +81 -0
- peclet_dem-0.1.0/tests/verify_flexible.py +204 -0
- peclet_dem-0.1.0/tests/verify_restitution.py +132 -0
- peclet_dem-0.1.0/tests/verify_sdf_cylinder.py +62 -0
- peclet_dem-0.1.0/tests/verify_sdf_cylinder_highres.py +55 -0
- peclet_dem-0.1.0/tests/verify_sdf_sphere.py +43 -0
- peclet_dem-0.1.0/tests/verify_vti_periodic.py +68 -0
- peclet_dem-0.1.0/verify_collision_hollow_cylinders.py +249 -0
- peclet_dem-0.1.0/verify_collision_spheres.py +103 -0
- peclet_dem-0.1.0/verify_output.txt +56079 -0
- peclet_dem-0.1.0/verify_packing_hollow_cylinders.py +207 -0
- peclet_dem-0.1.0/verify_packing_hollow_cylinders_test.py +206 -0
- peclet_dem-0.1.0/verify_packing_spheres.py +101 -0
- peclet_dem-0.1.0/verify_precession.py +127 -0
- peclet_dem-0.1.0/verify_stacking.py +70 -0
- peclet_dem-0.1.0/verify_stacking_inelastic.py +163 -0
- peclet_dem-0.1.0/verify_stacking_nofric.py +61 -0
- peclet_dem-0.1.0/verify_thermostat.py +109 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# Build the Kokkos (OpenMP/Serial) backend + ArborX from source, then build the dem Python module and
|
|
4
|
+
# smoke-import it. The GPU (CUDA/HIP) backends and the multi-rank MPI step (DEM_MPI, needs the
|
|
5
|
+
# core sibling) are NOT exercisable on free GitHub runners (no GPU); this CI covers the
|
|
6
|
+
# portable host build, which catches the bulk of regressions. The single-rank module depends only on
|
|
7
|
+
# Kokkos + ArborX + pybind11 (the distributed step is gated behind DEM_MPI).
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
branches: [main, "**"]
|
|
12
|
+
pull_request:
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
env:
|
|
16
|
+
KOKKOS_TAG: "5.1.1" # keep in lockstep with ../tools/bootstrap_deps.sh
|
|
17
|
+
ARBORX_TAG: "v2.1"
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
build-test:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Install toolchain
|
|
26
|
+
run: |
|
|
27
|
+
sudo apt-get update
|
|
28
|
+
sudo apt-get install -y cmake ninja-build libomp-dev python3-dev python3-pip
|
|
29
|
+
python3 -m pip install --upgrade pip pybind11 numpy
|
|
30
|
+
|
|
31
|
+
- name: Cache Kokkos + ArborX install
|
|
32
|
+
id: deps-cache
|
|
33
|
+
uses: actions/cache@v4
|
|
34
|
+
with:
|
|
35
|
+
path: ${{ github.workspace }}/deps-install
|
|
36
|
+
key: kokkos-${{ env.KOKKOS_TAG }}-arborx-${{ env.ARBORX_TAG }}-openmp-${{ runner.os }}
|
|
37
|
+
|
|
38
|
+
- name: Build Kokkos (OpenMP + Serial) + ArborX
|
|
39
|
+
if: steps.deps-cache.outputs.cache-hit != 'true'
|
|
40
|
+
run: |
|
|
41
|
+
PREFIX="$GITHUB_WORKSPACE/deps-install"
|
|
42
|
+
git clone --depth 1 --branch "$KOKKOS_TAG" https://github.com/kokkos/kokkos.git /tmp/kokkos
|
|
43
|
+
cmake -S /tmp/kokkos -B /tmp/kokkos/build -G Ninja \
|
|
44
|
+
-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 \
|
|
45
|
+
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
|
|
46
|
+
-DKokkos_ENABLE_OPENMP=ON -DKokkos_ENABLE_SERIAL=ON \
|
|
47
|
+
-DCMAKE_INSTALL_PREFIX="$PREFIX"
|
|
48
|
+
cmake --build /tmp/kokkos/build -j && cmake --install /tmp/kokkos/build
|
|
49
|
+
# ArborX is header-only; it just needs to find the Kokkos we built.
|
|
50
|
+
git clone --depth 1 --branch "$ARBORX_TAG" https://github.com/arborx/ArborX.git /tmp/arborx
|
|
51
|
+
cmake -S /tmp/arborx -B /tmp/arborx/build -G Ninja \
|
|
52
|
+
-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 \
|
|
53
|
+
-DCMAKE_PREFIX_PATH="$PREFIX" -DCMAKE_INSTALL_PREFIX="$PREFIX"
|
|
54
|
+
cmake --install /tmp/arborx/build
|
|
55
|
+
|
|
56
|
+
- name: Build dem module
|
|
57
|
+
run: |
|
|
58
|
+
cmake -S . -B build \
|
|
59
|
+
-DCMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/deps-install;$(python3 -m pybind11 --cmakedir)"
|
|
60
|
+
cmake --build build -j
|
|
61
|
+
|
|
62
|
+
- name: Import smoke test
|
|
63
|
+
run: PYTHONPATH=$PWD/build python3 -c "import dem; print('dem import OK')"
|
|
64
|
+
|
|
65
|
+
- name: Build + run Kokkos kernel unit tests (tests/kokkos)
|
|
66
|
+
run: |
|
|
67
|
+
# Kokkos-only unit suite (no ArborX / MPI): contact preprocessing, narrow-phase, the
|
|
68
|
+
# velocity/position/friction XPBD solves, integration, periodicity and the thermostat,
|
|
69
|
+
# each validated in isolation against a serial reference.
|
|
70
|
+
cmake -S tests/kokkos -B build_kokkos \
|
|
71
|
+
-DCMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/deps-install"
|
|
72
|
+
cmake --build build_kokkos -j
|
|
73
|
+
ctest --test-dir build_kokkos --output-on-failure
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
# Build the Doxygen API docs (Kokkos + ArborX C++ in src/ & mpi/) and publish them to GitHub Pages.
|
|
4
|
+
# Requires Pages to be enabled for the repository with "Source: GitHub Actions" (Settings -> Pages).
|
|
5
|
+
# Runs on every push to main; can also be triggered manually. Doxygen only parses the sources (no
|
|
6
|
+
# Kokkos/ArborX toolchain needed), so this runs on a plain ubuntu runner.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
branches: [main]
|
|
11
|
+
paths:
|
|
12
|
+
- 'src/**'
|
|
13
|
+
- 'mpi/**'
|
|
14
|
+
- 'docs/**'
|
|
15
|
+
- 'README.md'
|
|
16
|
+
- '.github/workflows/docs.yml'
|
|
17
|
+
workflow_dispatch:
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
pages: write
|
|
22
|
+
id-token: write
|
|
23
|
+
|
|
24
|
+
concurrency:
|
|
25
|
+
group: pages
|
|
26
|
+
cancel-in-progress: true
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
build:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
- name: Install Doxygen + Graphviz
|
|
34
|
+
run: sudo apt-get update && sudo apt-get install -y doxygen graphviz
|
|
35
|
+
- name: Build documentation
|
|
36
|
+
run: doxygen docs/Doxyfile
|
|
37
|
+
- name: Upload Pages artifact
|
|
38
|
+
uses: actions/upload-pages-artifact@v3
|
|
39
|
+
with:
|
|
40
|
+
path: docs/html
|
|
41
|
+
|
|
42
|
+
deploy:
|
|
43
|
+
needs: build
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
environment:
|
|
46
|
+
name: github-pages
|
|
47
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
48
|
+
steps:
|
|
49
|
+
- name: Deploy to GitHub Pages
|
|
50
|
+
id: deployment
|
|
51
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Quality
|
|
2
|
+
|
|
3
|
+
# Lightweight, non-breaking code-quality gates. The Python job hard-fails on *critical* errors only
|
|
4
|
+
# (syntax errors, undefined names, bad string formatting / comparisons — the classic stop-the-build
|
|
5
|
+
# set), so it catches real bugs without drowning research scripts in style nits.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main, "**"]
|
|
10
|
+
pull_request:
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
python-lint:
|
|
15
|
+
name: ruff (critical errors)
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
- run: pip install ruff
|
|
23
|
+
- name: Ruff critical-error check
|
|
24
|
+
run: |
|
|
25
|
+
ruff check . --select E9,F63,F7,F82 \
|
|
26
|
+
--exclude ".venv,venv,build,build_*,__pycache__,_deps,extern,legacy,notebooks"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Build the sdist + self-contained OpenMP CPU wheels and publish to PyPI (peclet-dem) on a version tag.
|
|
4
|
+
# Uses PyPI Trusted Publishing (OIDC) — configure the publisher on PyPI first; no API token secret needed.
|
|
5
|
+
# The wheels FetchContent-build Kokkos (OpenMP+Serial) + the core headers inside each build
|
|
6
|
+
# (PECLET_VENDOR_DEPS=ON, from pyproject's [tool.cibuildwheel]); GPU/HIP + MPI are the source (sdist) path.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags: ["v*"]
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
sdist:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
- run: pip install build
|
|
22
|
+
- run: python -m build --sdist
|
|
23
|
+
- uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: sdist
|
|
26
|
+
path: dist/*.tar.gz
|
|
27
|
+
|
|
28
|
+
wheels:
|
|
29
|
+
name: wheels (manylinux_2_28 x86_64)
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
# cibuildwheel reads [tool.cibuildwheel] from pyproject.toml (PECLET_VENDOR_DEPS=ON): each wheel
|
|
34
|
+
# compiles Kokkos as a subproject, so builds are slow but self-contained.
|
|
35
|
+
- uses: pypa/cibuildwheel@v2.21
|
|
36
|
+
- uses: actions/upload-artifact@v4
|
|
37
|
+
with:
|
|
38
|
+
name: wheels-linux
|
|
39
|
+
path: wheelhouse/*.whl
|
|
40
|
+
|
|
41
|
+
publish:
|
|
42
|
+
needs: [sdist, wheels]
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
45
|
+
environment: pypi
|
|
46
|
+
permissions:
|
|
47
|
+
id-token: write # required for trusted publishing
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/download-artifact@v4
|
|
50
|
+
with:
|
|
51
|
+
path: dist
|
|
52
|
+
merge-multiple: true
|
|
53
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Build directories + logs
|
|
2
|
+
build/
|
|
3
|
+
build_*/
|
|
4
|
+
build_log*.txt
|
|
5
|
+
*.log
|
|
6
|
+
cmake-build-debug/
|
|
7
|
+
cmake-build-release/
|
|
8
|
+
bin/
|
|
9
|
+
lib/
|
|
10
|
+
*.so
|
|
11
|
+
*.a
|
|
12
|
+
*.o
|
|
13
|
+
|
|
14
|
+
# Python
|
|
15
|
+
__pycache__/
|
|
16
|
+
*.pyc
|
|
17
|
+
*.pyo
|
|
18
|
+
*.pyd
|
|
19
|
+
.Python
|
|
20
|
+
env/
|
|
21
|
+
venv/
|
|
22
|
+
.env
|
|
23
|
+
.venv
|
|
24
|
+
|
|
25
|
+
# IDEs
|
|
26
|
+
# .vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
*.swp
|
|
29
|
+
*~
|
|
30
|
+
.DS_Store
|
|
31
|
+
|
|
32
|
+
# Generated artifacts (if any not in build)
|
|
33
|
+
*.egg-info/
|
|
34
|
+
dist/
|
|
35
|
+
.cache/
|
|
36
|
+
output/
|
|
37
|
+
|
|
38
|
+
# Generated Doxygen output (built in CI, published to Pages)
|
|
39
|
+
docs/html/
|
|
40
|
+
docs/latex/
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"name": "(gdb) Launch Python Script (C++ Only)",
|
|
6
|
+
"type": "cppdbg",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"program": "${workspaceFolder}/.venv/bin/python",
|
|
9
|
+
"args": [
|
|
10
|
+
"${workspaceFolder}/verify_packing_hollow_cylinders_test.py"
|
|
11
|
+
],
|
|
12
|
+
"stopAtEntry": false,
|
|
13
|
+
"cwd": "${workspaceFolder}",
|
|
14
|
+
"environment": [
|
|
15
|
+
{
|
|
16
|
+
"name": "PYTHONPATH",
|
|
17
|
+
"value": "${workspaceFolder}/build:${env:PYTHONPATH}"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"externalConsole": false,
|
|
21
|
+
"MIMode": "gdb",
|
|
22
|
+
"setupCommands": [
|
|
23
|
+
{
|
|
24
|
+
"description": "Enable pretty-printing for gdb",
|
|
25
|
+
"text": "-enable-pretty-printing",
|
|
26
|
+
"ignoreFailures": true
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "Python: Current File",
|
|
32
|
+
"type": "python",
|
|
33
|
+
"request": "launch",
|
|
34
|
+
"program": "${file}",
|
|
35
|
+
"console": "integratedTerminal",
|
|
36
|
+
"justMyCode": false,
|
|
37
|
+
"env": {
|
|
38
|
+
"PYTHONPATH": "${workspaceFolder}/build:${env:PYTHONPATH}"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "(gdb) Attach to Python Process",
|
|
43
|
+
"type": "cppdbg",
|
|
44
|
+
"request": "attach",
|
|
45
|
+
"program": "${workspaceFolder}/.venv/bin/python",
|
|
46
|
+
"processId": "${command:pickProcess}",
|
|
47
|
+
"MIMode": "gdb",
|
|
48
|
+
"setupCommands": [
|
|
49
|
+
{
|
|
50
|
+
"description": "Enable pretty-printing for gdb",
|
|
51
|
+
"text": "-enable-pretty-printing",
|
|
52
|
+
"ignoreFailures": true
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.24)
|
|
2
|
+
project(dem LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
# Canonical packing-gpu build: the Kokkos + ArborX `dem` XPBD DEM module (CUDA / HIP / OpenMP backends,
|
|
5
|
+
# selected by the install prefix). Kokkos, ArborX and pybind11 are found via find_package against the
|
|
6
|
+
# bootstrapped install prefix (../extern/install/<backend>, built once by ../tools/bootstrap_deps.sh -- a
|
|
7
|
+
# HARD build dependency). With nvcc, put it on PATH (export PATH=/usr/local/cuda-13.2/bin:$PATH).
|
|
8
|
+
#
|
|
9
|
+
# Build (single-rank Python module); nanobind is found via the active interpreter (SuiteNanobind):
|
|
10
|
+
# cmake -S . -B build -DCMAKE_PREFIX_PATH="$PWD/../extern/install/nvidia-cuda"
|
|
11
|
+
# cmake --build build -j -> build/dem.*.so
|
|
12
|
+
#
|
|
13
|
+
# Multi-rank: -DDEM_MPI=ON links MPI + exposes init_mpi/enable_mpi_step/step_mpi in the module; the
|
|
14
|
+
# distributed step is also covered by the tests/kokkos_mpi ctests (run under mpirun).
|
|
15
|
+
|
|
16
|
+
set(CMAKE_CXX_STANDARD 20)
|
|
17
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
18
|
+
if(NOT CMAKE_BUILD_TYPE)
|
|
19
|
+
set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
|
|
20
|
+
endif()
|
|
21
|
+
|
|
22
|
+
option(PECLET_DEM_MPI "Build the dem module with the distributed (MPI) step exposed" OFF)
|
|
23
|
+
|
|
24
|
+
# Dependencies via the vendored PecletDeps helper: installed Kokkos+ArborX prefix + sibling checkout for
|
|
25
|
+
# the dev/suite build, or FetchContent-built Kokkos+ArborX + fetched core headers for a
|
|
26
|
+
# self-contained sdist/wheel (cibuildwheel). See cmake/PecletDeps.cmake.
|
|
27
|
+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|
28
|
+
include(PecletDeps)
|
|
29
|
+
peclet_require_kokkos()
|
|
30
|
+
peclet_require_arborx()
|
|
31
|
+
peclet_require_nanobind() # nanobind + core's View<->ndarray zero-copy bridge
|
|
32
|
+
peclet_sibling_include(peclet-core "${PECLET_TPX_TAG}" "../core" TPX_INCLUDE)
|
|
33
|
+
|
|
34
|
+
# NB_STATIC: bundle nanobind's runtime into the module; the Kokkos device path is routed by the
|
|
35
|
+
# launch compiler regardless. NOMINSIZE: nanobind's default -Os is rejected by nvcc ("'s': expected a
|
|
36
|
+
# number") since Kokkos device sources compile as CXX through the launch compiler.
|
|
37
|
+
nanobind_add_module(dem NB_STATIC NOMINSIZE src/dem_bindings.cpp)
|
|
38
|
+
# -> peclet.dem._dem (NB_MODULE(_dem)), re-exported by peclet/dem/__init__.py. The __init__ is kept as a
|
|
39
|
+
# plain file under packaging/ (OUTSIDE any importable peclet/ dir, so an incomplete source package can
|
|
40
|
+
# never shadow the installed one) and staged into <build>/peclet/dem so `PYTHONPATH=<build> python …`
|
|
41
|
+
# (`import peclet.dem`) works in the dev loop too.
|
|
42
|
+
set_target_properties(dem PROPERTIES OUTPUT_NAME _dem
|
|
43
|
+
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/peclet/dem")
|
|
44
|
+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packaging/dem_init.py
|
|
45
|
+
${CMAKE_CURRENT_BINARY_DIR}/peclet/dem/__init__.py COPYONLY)
|
|
46
|
+
target_include_directories(dem PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${TPX_INCLUDE})
|
|
47
|
+
target_link_libraries(dem PRIVATE ArborX::ArborX Kokkos::kokkos)
|
|
48
|
+
|
|
49
|
+
if(PECLET_DEM_MPI)
|
|
50
|
+
find_package(MPI REQUIRED COMPONENTS CXX)
|
|
51
|
+
target_compile_definitions(dem PRIVATE PECLET_DEM_MPI=1)
|
|
52
|
+
target_link_libraries(dem PRIVATE MPI::MPI_CXX)
|
|
53
|
+
message(STATUS "dem: distributed step ENABLED (MPI)")
|
|
54
|
+
endif()
|
|
55
|
+
|
|
56
|
+
# --- pip / scikit-build-core install rule -------------------------------------------------------
|
|
57
|
+
# `pip install .` (driven by pyproject.toml) builds against a Kokkos+ArborX prefix on
|
|
58
|
+
# CMAKE_PREFIX_PATH and installs the extension as a top-level `dem` module. The rule is inert for a
|
|
59
|
+
# plain `cmake --build` (no `cmake --install`), so the developer workflow is unchanged. SKBUILD is set
|
|
60
|
+
# by scikit-build-core; SKBUILD_PROJECT_NAME-style guards keep it from interfering elsewhere.
|
|
61
|
+
if(DEFINED SKBUILD)
|
|
62
|
+
install(TARGETS dem LIBRARY DESTINATION peclet/dem COMPONENT python)
|
|
63
|
+
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/dem_init.py
|
|
64
|
+
DESTINATION peclet/dem RENAME __init__.py COMPONENT python)
|
|
65
|
+
endif()
|
peclet_dem-0.1.0/LICENSE
ADDED
|
@@ -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,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: peclet-dem
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: peclet.dem — performance-portable XPBD Discrete Element Method (Kokkos + ArborX)
|
|
5
|
+
Author-Email: Frank Peters <e.a.j.f.peters@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Project-URL: Homepage, https://github.com/computational-chemical-engineering/peclet
|
|
9
|
+
Project-URL: Documentation, https://github.com/computational-chemical-engineering/peclet
|
|
10
|
+
Project-URL: Source, https://github.com/computational-chemical-engineering/peclet-dem
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Requires-Dist: numpy>=1.20
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# peclet-dem (`peclet.dem`)
|
|
16
|
+
|
|
17
|
+
Performance-portable Discrete Element Method (DEM) particle simulation: an XPBD solver with SDF-based point-shell collision detection. Built on **Kokkos + ArborX**, so the same source runs on **CUDA, HIP (AMD/LUMI), and OpenMP** backends (selected at build time by the install prefix). Optional MPI for domain partitioning, with **nanobind** Python bindings (zero-copy, via scikit-build-core) for scripting and visualization.
|
|
18
|
+
|
|
19
|
+
> The CUDA implementation was retired (2026-06): the Kokkos `peclet.dem` module was validated against it before the CUDA sources were removed. Restore point: git tag `pre-cuda-retirement`.
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **Hybrid XPBD Solver**: Two-pass velocity/position solver for stable high-density packing.
|
|
24
|
+
- **SDF Collision**: Point-shell collision detection using Signed Distance Fields (supports analytic shapes like hollow cylinders).
|
|
25
|
+
- **Periodicity**: Full periodic boundary conditions (Ghost Particles).
|
|
26
|
+
- **Python Bindings**: Control simulation logic, data initialization, and export entirely from Python.
|
|
27
|
+
- **MPI Support**: Optional Multi-GPU/Node support via domain decomposition.
|
|
28
|
+
|
|
29
|
+
## Folder Structure
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
├── CMakeLists.txt # Build configuration (find_package Kokkos + ArborX)
|
|
33
|
+
├── src # Kokkos sources (header-only, namespace peclet::dem)
|
|
34
|
+
│ ├── dem_bindings.cpp # nanobind module entry point (the `peclet.dem` module)
|
|
35
|
+
│ ├── sim.hpp # Simulation facade + the demStep XPBD substep
|
|
36
|
+
│ ├── integration.hpp # Time integration & prediction
|
|
37
|
+
│ ├── broadphase_arborx.hpp # ArborX BVH broad-phase
|
|
38
|
+
│ ├── narrowphase.hpp # Narrow-phase point-shell-vs-SDF collision
|
|
39
|
+
│ ├── solver_velocity.hpp # Velocity solver kernels
|
|
40
|
+
│ ├── solver_position.hpp # Position solver kernels (XPBD overlap removal)
|
|
41
|
+
│ ├── solver_friction.hpp # Coulomb friction cluster
|
|
42
|
+
│ ├── output_sdf.hpp # SDF/VTI grid generation (Eikonal)
|
|
43
|
+
│ ├── shapes_portable.hpp # Analytic shapes (sphere / hollow cylinder / box)
|
|
44
|
+
│ ├── io.hpp # LAMMPS-dump + SDF-VTI export
|
|
45
|
+
│ └── mpi_halo.hpp # Distributed particle halo (core), gated PECLET_DEM_MPI
|
|
46
|
+
├── tests # C++ unit tests: kokkos/ (kernels), arborx/, kokkos_mpi/
|
|
47
|
+
├── docs # Documentation
|
|
48
|
+
└── *.py # Python verification/example scripts (verify_*.py)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Prerequisites
|
|
52
|
+
|
|
53
|
+
- **Linux**
|
|
54
|
+
- **CMake** >= 3.24
|
|
55
|
+
- **Kokkos 5.x + ArborX** (C++20) — provisioned by `../tools/bootstrap_deps.sh` into
|
|
56
|
+
`../extern/install/<backend>` (`nvidia-cuda` / `host-openmp` / `lumi-hip`). A **hard build dependency**.
|
|
57
|
+
- **nanobind** + **scikit-build-core** (found via the active Python interpreter; see `pyproject.toml`)
|
|
58
|
+
- a backend compiler: **nvcc** (CUDA) on `PATH`, **hipcc** (ROCm), or just a host C++ compiler (OpenMP)
|
|
59
|
+
- **Python** >= 3.10
|
|
60
|
+
- **MPI** (optional, `-DDEM_MPI=ON`) — OpenMPI or MPICH
|
|
61
|
+
|
|
62
|
+
## Build Instructions
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
python -m venv .venv && source .venv/bin/activate && pip install nanobind numpy
|
|
66
|
+
export PATH=/usr/local/cuda-13.2/bin:$PATH # if building the CUDA backend
|
|
67
|
+
|
|
68
|
+
# Canonical: build + install the module via scikit-build-core
|
|
69
|
+
CMAKE_PREFIX_PATH="$PWD/../extern/install/nvidia-cuda" pip install .
|
|
70
|
+
|
|
71
|
+
# Or a dev cmake build (nanobind is found via the active interpreter, no cmakedir needed):
|
|
72
|
+
cmake -B build -S . -DCMAKE_PREFIX_PATH="$PWD/../extern/install/nvidia-cuda"
|
|
73
|
+
cmake --build build -j$(nproc)
|
|
74
|
+
```
|
|
75
|
+
*Swap the prefix to `../extern/install/host-openmp` for the OpenMP backend. `-DDEM_MPI=ON` links MPI
|
|
76
|
+
and exposes the distributed step (`init_mpi` / `enable_mpi_step` / `step_mpi`), including dynamic load
|
|
77
|
+
balancing — `enable_mpi_step(..., rebalance_every=N)` or an explicit `rebalance()` re-decomposes by
|
|
78
|
+
particle count (weighted ORB) and migrates ownership so each rank keeps a near-equal share.*
|
|
79
|
+
|
|
80
|
+
The compiled `peclet.dem` extension is placed in `build/peclet/dem/`; run scripts with `build/` on `PYTHONPATH` (`import peclet.dem`).
|
|
81
|
+
|
|
82
|
+
## Running Simulations
|
|
83
|
+
|
|
84
|
+
Example scripts are provided in the root directory:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Add build artifact to python path if needed (or symlink it)
|
|
88
|
+
export PYTHONPATH=$PYTHONPATH:$(pwd)/build
|
|
89
|
+
|
|
90
|
+
# Run a verification script
|
|
91
|
+
python verify_packing_hollow_cylinders.py
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Output & Visualization
|
|
95
|
+
|
|
96
|
+
The simulation supports two primary output formats:
|
|
97
|
+
|
|
98
|
+
### 1. LAMMPS + STL (Ovito)
|
|
99
|
+
|
|
100
|
+
For particle visualization (especially non-spherical shapes), we use the LAMMPS dump format combined with an STL mesh.
|
|
101
|
+
|
|
102
|
+
1. **Generate Output**: The simulation writes `dump.custom.*` files.
|
|
103
|
+
2. **Generate Shape**: Run `python generate_particles.py` to create `particle_shape.stl`.
|
|
104
|
+
3. **Visualize**:
|
|
105
|
+
- Open **Ovito**.
|
|
106
|
+
- Load the `dump.custom.*` sequence.
|
|
107
|
+
- Add a **Particle Types** modifier.
|
|
108
|
+
- Set the shape visualization to **Mesh/User-defined** and load `particle_shape.stl`.
|
|
109
|
+
- Ovito will automatically scale the mesh by the particle radius.
|
|
110
|
+
|
|
111
|
+
*See `docs/visualization.md` for a detailed guide.*
|
|
112
|
+
|
|
113
|
+
### 2. VTI (ParaView)
|
|
114
|
+
|
|
115
|
+
For visualizing fields (like the Signed Distance Field or occupancy grids), the simulation exports VTI files (`.vti`).
|
|
116
|
+
|
|
117
|
+
1. **Generate Output**: Use `Simulation.export_sdf("filename.vti", resolution=...)`.
|
|
118
|
+
2. **Visualize**:
|
|
119
|
+
- Open **ParaView**.
|
|
120
|
+
- Load the `.vti` file.
|
|
121
|
+
- Use "Volume" representation or "Slice" filter to inspect the field.
|
|
122
|
+
|
|
123
|
+
## Status
|
|
124
|
+
|
|
125
|
+
The single-GPU engine is complete and validated: it reaches stable high-density (random close)
|
|
126
|
+
packing, and energy is conserved to ~0.3% (see `docs/packing_investigation.md`). Friction is
|
|
127
|
+
stabilized for spheres; body-body tangential friction is a known follow-up (currently weaker than
|
|
128
|
+
ideal). Active work is at-scale multi-GPU/MPI tuning.
|
|
129
|
+
|
|
130
|
+
> [!NOTE]
|
|
131
|
+
> The distributed (MPI) step is validated against the single-rank result (`tests/kokkos_mpi`,
|
|
132
|
+
> np=1,2,4 on OpenMP + CUDA) and supports dynamic load rebalancing; remaining MPI work is at-scale
|
|
133
|
+
> multi-GPU tuning.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# peclet-dem (`peclet.dem`)
|
|
2
|
+
|
|
3
|
+
Performance-portable Discrete Element Method (DEM) particle simulation: an XPBD solver with SDF-based point-shell collision detection. Built on **Kokkos + ArborX**, so the same source runs on **CUDA, HIP (AMD/LUMI), and OpenMP** backends (selected at build time by the install prefix). Optional MPI for domain partitioning, with **nanobind** Python bindings (zero-copy, via scikit-build-core) for scripting and visualization.
|
|
4
|
+
|
|
5
|
+
> The CUDA implementation was retired (2026-06): the Kokkos `peclet.dem` module was validated against it before the CUDA sources were removed. Restore point: git tag `pre-cuda-retirement`.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Hybrid XPBD Solver**: Two-pass velocity/position solver for stable high-density packing.
|
|
10
|
+
- **SDF Collision**: Point-shell collision detection using Signed Distance Fields (supports analytic shapes like hollow cylinders).
|
|
11
|
+
- **Periodicity**: Full periodic boundary conditions (Ghost Particles).
|
|
12
|
+
- **Python Bindings**: Control simulation logic, data initialization, and export entirely from Python.
|
|
13
|
+
- **MPI Support**: Optional Multi-GPU/Node support via domain decomposition.
|
|
14
|
+
|
|
15
|
+
## Folder Structure
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
├── CMakeLists.txt # Build configuration (find_package Kokkos + ArborX)
|
|
19
|
+
├── src # Kokkos sources (header-only, namespace peclet::dem)
|
|
20
|
+
│ ├── dem_bindings.cpp # nanobind module entry point (the `peclet.dem` module)
|
|
21
|
+
│ ├── sim.hpp # Simulation facade + the demStep XPBD substep
|
|
22
|
+
│ ├── integration.hpp # Time integration & prediction
|
|
23
|
+
│ ├── broadphase_arborx.hpp # ArborX BVH broad-phase
|
|
24
|
+
│ ├── narrowphase.hpp # Narrow-phase point-shell-vs-SDF collision
|
|
25
|
+
│ ├── solver_velocity.hpp # Velocity solver kernels
|
|
26
|
+
│ ├── solver_position.hpp # Position solver kernels (XPBD overlap removal)
|
|
27
|
+
│ ├── solver_friction.hpp # Coulomb friction cluster
|
|
28
|
+
│ ├── output_sdf.hpp # SDF/VTI grid generation (Eikonal)
|
|
29
|
+
│ ├── shapes_portable.hpp # Analytic shapes (sphere / hollow cylinder / box)
|
|
30
|
+
│ ├── io.hpp # LAMMPS-dump + SDF-VTI export
|
|
31
|
+
│ └── mpi_halo.hpp # Distributed particle halo (core), gated PECLET_DEM_MPI
|
|
32
|
+
├── tests # C++ unit tests: kokkos/ (kernels), arborx/, kokkos_mpi/
|
|
33
|
+
├── docs # Documentation
|
|
34
|
+
└── *.py # Python verification/example scripts (verify_*.py)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Prerequisites
|
|
38
|
+
|
|
39
|
+
- **Linux**
|
|
40
|
+
- **CMake** >= 3.24
|
|
41
|
+
- **Kokkos 5.x + ArborX** (C++20) — provisioned by `../tools/bootstrap_deps.sh` into
|
|
42
|
+
`../extern/install/<backend>` (`nvidia-cuda` / `host-openmp` / `lumi-hip`). A **hard build dependency**.
|
|
43
|
+
- **nanobind** + **scikit-build-core** (found via the active Python interpreter; see `pyproject.toml`)
|
|
44
|
+
- a backend compiler: **nvcc** (CUDA) on `PATH`, **hipcc** (ROCm), or just a host C++ compiler (OpenMP)
|
|
45
|
+
- **Python** >= 3.10
|
|
46
|
+
- **MPI** (optional, `-DDEM_MPI=ON`) — OpenMPI or MPICH
|
|
47
|
+
|
|
48
|
+
## Build Instructions
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
python -m venv .venv && source .venv/bin/activate && pip install nanobind numpy
|
|
52
|
+
export PATH=/usr/local/cuda-13.2/bin:$PATH # if building the CUDA backend
|
|
53
|
+
|
|
54
|
+
# Canonical: build + install the module via scikit-build-core
|
|
55
|
+
CMAKE_PREFIX_PATH="$PWD/../extern/install/nvidia-cuda" pip install .
|
|
56
|
+
|
|
57
|
+
# Or a dev cmake build (nanobind is found via the active interpreter, no cmakedir needed):
|
|
58
|
+
cmake -B build -S . -DCMAKE_PREFIX_PATH="$PWD/../extern/install/nvidia-cuda"
|
|
59
|
+
cmake --build build -j$(nproc)
|
|
60
|
+
```
|
|
61
|
+
*Swap the prefix to `../extern/install/host-openmp` for the OpenMP backend. `-DDEM_MPI=ON` links MPI
|
|
62
|
+
and exposes the distributed step (`init_mpi` / `enable_mpi_step` / `step_mpi`), including dynamic load
|
|
63
|
+
balancing — `enable_mpi_step(..., rebalance_every=N)` or an explicit `rebalance()` re-decomposes by
|
|
64
|
+
particle count (weighted ORB) and migrates ownership so each rank keeps a near-equal share.*
|
|
65
|
+
|
|
66
|
+
The compiled `peclet.dem` extension is placed in `build/peclet/dem/`; run scripts with `build/` on `PYTHONPATH` (`import peclet.dem`).
|
|
67
|
+
|
|
68
|
+
## Running Simulations
|
|
69
|
+
|
|
70
|
+
Example scripts are provided in the root directory:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Add build artifact to python path if needed (or symlink it)
|
|
74
|
+
export PYTHONPATH=$PYTHONPATH:$(pwd)/build
|
|
75
|
+
|
|
76
|
+
# Run a verification script
|
|
77
|
+
python verify_packing_hollow_cylinders.py
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Output & Visualization
|
|
81
|
+
|
|
82
|
+
The simulation supports two primary output formats:
|
|
83
|
+
|
|
84
|
+
### 1. LAMMPS + STL (Ovito)
|
|
85
|
+
|
|
86
|
+
For particle visualization (especially non-spherical shapes), we use the LAMMPS dump format combined with an STL mesh.
|
|
87
|
+
|
|
88
|
+
1. **Generate Output**: The simulation writes `dump.custom.*` files.
|
|
89
|
+
2. **Generate Shape**: Run `python generate_particles.py` to create `particle_shape.stl`.
|
|
90
|
+
3. **Visualize**:
|
|
91
|
+
- Open **Ovito**.
|
|
92
|
+
- Load the `dump.custom.*` sequence.
|
|
93
|
+
- Add a **Particle Types** modifier.
|
|
94
|
+
- Set the shape visualization to **Mesh/User-defined** and load `particle_shape.stl`.
|
|
95
|
+
- Ovito will automatically scale the mesh by the particle radius.
|
|
96
|
+
|
|
97
|
+
*See `docs/visualization.md` for a detailed guide.*
|
|
98
|
+
|
|
99
|
+
### 2. VTI (ParaView)
|
|
100
|
+
|
|
101
|
+
For visualizing fields (like the Signed Distance Field or occupancy grids), the simulation exports VTI files (`.vti`).
|
|
102
|
+
|
|
103
|
+
1. **Generate Output**: Use `Simulation.export_sdf("filename.vti", resolution=...)`.
|
|
104
|
+
2. **Visualize**:
|
|
105
|
+
- Open **ParaView**.
|
|
106
|
+
- Load the `.vti` file.
|
|
107
|
+
- Use "Volume" representation or "Slice" filter to inspect the field.
|
|
108
|
+
|
|
109
|
+
## Status
|
|
110
|
+
|
|
111
|
+
The single-GPU engine is complete and validated: it reaches stable high-density (random close)
|
|
112
|
+
packing, and energy is conserved to ~0.3% (see `docs/packing_investigation.md`). Friction is
|
|
113
|
+
stabilized for spheres; body-body tangential friction is a known follow-up (currently weaker than
|
|
114
|
+
ideal). Active work is at-scale multi-GPU/MPI tuning.
|
|
115
|
+
|
|
116
|
+
> [!NOTE]
|
|
117
|
+
> The distributed (MPI) step is validated against the single-rank result (`tests/kokkos_mpi`,
|
|
118
|
+
> np=1,2,4 on OpenMP + CUDA) and supports dynamic load rebalancing; remaining MPI work is at-scale
|
|
119
|
+
> multi-GPU tuning.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Source this script to set up the development environment
|
|
3
|
+
# Usage: source activate_env.sh
|
|
4
|
+
|
|
5
|
+
# Get the absolute path of the script directory
|
|
6
|
+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
7
|
+
BUILD_DIR="$SCRIPT_DIR/build"
|
|
8
|
+
|
|
9
|
+
if [ ! -d "$BUILD_DIR" ]; then
|
|
10
|
+
echo "Warning: Build directory '$BUILD_DIR' does not exist yet."
|
|
11
|
+
echo "Make sure to run: mkdir build && cd build && cmake .. && make"
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
# Add build directory to PYTHONPATH
|
|
15
|
+
export PYTHONPATH="$BUILD_DIR:$PYTHONPATH"
|
|
16
|
+
|
|
17
|
+
echo "Environment configured."
|
|
18
|
+
echo "PYTHONPATH includes: $BUILD_DIR"
|