feat(pffdtd): add PFFDTD (Brian Hamilton) wave-equation FDTD method#11
Open
Burhanuddin98 wants to merge 1 commit into
Open
feat(pffdtd): add PFFDTD (Brian Hamilton) wave-equation FDTD method#11Burhanuddin98 wants to merge 1 commit into
Burhanuddin98 wants to merge 1 commit into
Conversation
Adds the upstream PFFDTD wave-equation FDTD solver (bsxfun/pffdtd) as a new simulation method package, following the canonical copier-template layout that DE / DG / pyroomacoustics use.
What's added:
pffdtd_method/
Dockerfile -- nvidia/cuda:12.6.0-devel base; clones bsxfun/pffdtd@aa319f6; compiles
Hamilton's c_cuda binary as a multi-arch fatbinary (sm_60..sm_90 + PTX);
sed-patches deprecated numpy aliases (np.bool8, np.complex_, np.float)
pyproject.toml -- numpy<2 pin (PFFDTD predates numpy 2.0 alias removals); transitive deps
(tqdm, psutil, memory_profiler, plotly, polyscope, trimesh, soundfile,
gmsh, numba, h5py, scipy, matplotlib, resampy)
pffdtd_interface/
__init__.py, __cli__.py, __main__.py -- canonical scaffolding (matches DE/DG)
definition.py -- SimulationMethod ABC (copied from de_method to avoid cross-package import)
PFFDTDinterface.py -- the actual wrapper; runs sim_setup -> FDTD -> postprocess; produces a
48 kHz IR in receiverResults plus per-band edt/t20/t30/c80/d50/ts/spl
example_settings/pffdtd_setting.json -- 7 user-facing knobs (c0, fmax, ppw, IR length, T, RH, GPU on/off)
methods-config.json -- adds the PFFDTD entry
Design notes:
- CPU-primary, GPU-opportunistic. The wrapper auto-detects whether the
container has GPU passthrough (i.e. whether the CHORAS executor is
configured to pass --gpus all) and only invokes Hamilton's c_cuda binary
in that case. Otherwise it falls back to the pure-Python numba CPU engine
(PFFDTD's fdtd.sim_fdtd.SimEngine). So the method works on every host
CHORAS supports today; GPU acceleration is a bonus when wired.
- No backend changes. This PR is self-contained to simulation-backend.
A companion docker-compose.yml entry (plus a submodule-pointer bump
after this PR merges) will be a follow-up PR to choras-org/CHORAS.
- No ROM. Pure pass-through over upstream PFFDTD. No surrogate model.
- Python 3.11 compat. Multiprocessing SharedMemory.close() raises
BufferError on 3.11+ when memoryview consumers still exist; PFFDTD's
voxelizer triggers this. Monkey-patched in the wrapper to swallow the
specific error (data is already on disk by the time close fires).
- Single-process voxelization. PFFDTD's voxelizer Nprocs forced to 1
to avoid the SharedMemory issue entirely on modern Python; the
voxelize step is fast enough that single-proc isn't a bottleneck.
Verified end-to-end against MeasurementRoom.obj from example_geometries/:
voxelize -> sim_setup -> SimEngine.run_all() -> postprocess (HP 10 Hz,
LP 0.9*Nyquist, resample to 48 kHz) -> IR written to receiverResults, per-
band metrics in parameters, auralization CSV written alongside JSON,
container exits 0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the upstream PFFDTD wave-equation FDTD solver (bsxfun/pffdtd, MIT) as a new simulation method package, following the canonical copier-template layout that DE / DG / pyroomacoustics use.
Goal: give CHORAS users a wave-equation FDTD option (FDTD complements DG and the diffusion equation by being a phase-coherent wave solver — the right tool for low-frequency room modes and detailed reflection patterns).
Companion PR
A separate PR will be opened against `choras-org/CHORAS` once this lands, to (a) bump the simulation-backend submodule pointer to the merge commit and (b) add the corresponding `pffdtd-method` service to `docker-compose.yml` under `profiles: sim_method`. I'll wait for this PR to merge first so the submodule bump references a SHA that actually exists in this repo.
Files added
```
pffdtd_method/
├── Dockerfile # nvidia/cuda:12.6.0-devel; clones bsxfun/pffdtd@aa319f6; compiles c_cuda
├── pyproject.toml # numpy<2; tqdm/psutil/memory_profiler/plotly/etc. transitive deps
└── pffdtd_interface/
├── init.py, cli.py, main.py # canonical scaffolding (matches DE/DG)
├── definition.py # SimulationMethod ABC (copied from de_method)
└── PFFDTDinterface.py # wrapper: sim_setup -> FDTD -> postprocess -> JSON
example_settings/pffdtd_setting.json # 7 UI knobs: c0, fmax, ppw, IR length, T, RH, GPU on/off
methods-config.json # adds the PFFDTD entry
```
Design notes (the parts a reviewer should sanity-check)
Verification
End-to-end run against `MeasurementRoom.obj` from `example_geometries/`:
Output schema
Matches the slide-10 schema with the DG-style flat IR in `receiverResults`:
```json
{
"results": [{
"percentage": 100,
"resultType": "PFFDTD",
"responses": [{
"x": ..., "y": ..., "z": ...,
"receiverResults": [...IR samples at 48 kHz...],
"receiverResultsUncorrected": [...same...],
"parameters": {
"edt": [...per band...],
"t20": [...], "t30": [...],
"c80": [...], "d50": [...],
"ts": [...], "spl_t0_freq": [...]
}
}]
}]
}
```
Test plan
Context
This PR comes from following the 2nd CHORAS Developer Workshop walkthrough (Silvin's slides on the copier template + contribution flow). Happy to address any deviation from the conventions DE/DG follow.