Skip to content

Add Python callback hook and pybind11 wrapper for PySAGES integration#1496

Draft
JaafarMehrez wants to merge 1 commit into
brucefan1983:masterfrom
JaafarMehrez:pysages-integration
Draft

Add Python callback hook and pybind11 wrapper for PySAGES integration#1496
JaafarMehrez wants to merge 1 commit into
brucefan1983:masterfrom
JaafarMehrez:pysages-integration

Conversation

@JaafarMehrez
Copy link
Copy Markdown
Contributor

@JaafarMehrez JaafarMehrez commented May 13, 2026

Summary

Add Python callback hook and pybind11 wrapper to enable enhanced-sampling integration with PySAGES. This PR adds C++ infrastructure needed to drive GPUMD from Python and receive per-step callbacks so that PySAGES can compute bias forces on the GPU and inject them back into GPUMD's MD loop.

What changed

C++ core (run.cuh / run.cu)

  • Added #ifdef USE_PYSAGES guarded members to Run:
    • std::function<void(int)> step_callback — invoked every timestep after force computation and before integrate.compute2().
    • GPU_Vector<double> external_bias_per_atom — buffer for external bias forces (N×3 doubles).
  • Added accessors (get_atom, get_box, get_time_step, get_number_of_steps, set_number_of_steps, execute_run) needed by the Python wrapper.
  • Added gpu_add_external_bias CUDA kernel that adds the bias buffer to atom.force_per_atom.
  • The new code is completely opt-in: default make gpumd does not define USE_PYSAGES, so the standard executable is unchanged and requires only the CUDA toolkit.

Python wrapper (gpumd_python.cpp, new)

  • Exposes simulation data as DLPack capsules for zero-copy exchange with JAX / CuPy / PyTorch.
    • get_positions_dlpack(), get_velocities_dlpack(), get_forces_dlpack(), get_masses_dlpack(), get_types_dlpack()
  • set_step_callback(fn) registers a Python callable that receives the current timestep.
  • run(steps) executes the deferred MD loop.
  • is_box_constant() inspects run.in to determine if the simulation box can change.
  • add_aos_bias_to_forces() accepts a DLPack tensor in AOS layout and adds it directly to GPUMD's SOA force_per_atom via a custom CUDA kernel — no intermediate copies.
  • set_external_bias() / clear_external_bias() — legacy path for backward compatibility.

CUDA kernel (gpumd_python_kernels.cu / .cuh, new)

  • gpu_add_aos_bias_to_soa_forces_kernel: single kernel, no extra device to device copies.

Build system (makefile)

  • Added pygpumd target that compiles the wrapper into gpumd.so.
    • Automatically adds -DUSE_PYSAGES to CFLAGS.
    • Handles pybind11 includes, Python config, and CUDA runtime linking.

DLPack header (dlpack.h, new — vendored)

  • Standard v0.8 DLPack header for zero-copy array exchange. Vendored because it is a single 200-line file with no dependencies (same approach used by JAX, PyTorch, TensorFlow).

gpu_vector.cuh

  • Added #ifdef __CUDACC__ guards around the __global__ gpu_fill kernel so that the file can be included when compiling the wrapper with g++.

Testing

  • make gpumd — standard executable builds successfully (no Python dependencies).
  • make pygpumd — Python module builds successfully on Linux + CUDA 11.x/12.x.

Dependency

This PR is required by the companion PySAGES backend PR .

Author

Jaafar Mehrez

@brucefan1983 brucefan1983 marked this pull request as draft May 13, 2026 05:37
@brucefan1983
Copy link
Copy Markdown
Owner

Thanks for the contribution. This is a big change and I need time to review it.

@JaafarMehrez
Copy link
Copy Markdown
Contributor Author

@brucefan1983 Thank you, If you would like to test it with PySAGES, this branch of my fork (https://github.com/JaafarMehrez/PySAGES/tree/gpumd-backend) has the required files under /pysages/backends/gpumd.py, an example is also provided under /examples/gpumd/

I look forward to your comments, and would like to know whether we can optimize the code further.

@brucefan1983
Copy link
Copy Markdown
Owner

brucefan1983 commented May 17, 2026

After careful review of this PR, I feel that it is better you release the combined code by yourself, in your github page. You can for example release a code named GPUMD-PySAGES, stating in the homepage that it depends on both GPUMD and PySAGES, citing the relevant publications (for GPUMD, it is https://doi.org/10.1002/mgea.70028).

@JaafarMehrez
Copy link
Copy Markdown
Contributor Author

@brucefan1983 Thank you for the feedback. I will proceed with creating a standalone repository and will ensure all proper citations are included. Thanks again for your time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants