Developer Guide

This section includes information for developers who want to contribute to the project. It includes information about the project structure, how to run the tests, and how to build the documentation. It also includes information about the project’s coding style and how to contribute to the project.

Project Structure

PQ is a C++ molecular dynamics simulation engine with Python bindings, organized into a modular architecture. The project follows standard C++ project conventions with clear separation between headers, source code, applications, tests, and documentation.

Core Directory Layout

The main directories are organized as follows:

Source Code:
  • src/ - Implementation files (.cpp) containing the core functionality

  • include/ - Header files (.hpp) defining interfaces and declarations

  • apps/ - Main application executable (PQ.cpp)

Build System:
  • CMakeLists.txt - Main CMake configuration file

Testing:
  • tests/ - Unit tests for individual components

  • integration_tests/ - Integration tests using pytest

Documentation:
  • docs/ - Sphinx documentation source files and build configuration

  • README.md - Project overview and installation instructions

External Dependencies:
  • external/ - Third-party libraries (googletest, progressbar, toml++)

Utilities:
  • scripts/ - Build scripts, Singularity definition files, and utility scripts

  • examples/ - Example simulation input files

  • config/ - License headers

Core Architecture

The PQ codebase is organized into functional modules, each contained in its own directory within both src/ and include/:

Simulation Engine:
  • engine/ - Main simulation engine and orchestration

  • integrator/ - Numerical integration algorithms

  • thermostat/ - Temperature control algorithms

  • manostat/ - Pressure control algorithms

Physical Models:
  • forceField/ - MM bonded interactions

  • intraNonBonded/ - MM intramolecular non-bonded interactions

  • potential/ - MM intermolecular non-bonded interactions

  • QM/ - Interface to QM runner programs

System Setup:
  • input/ - Input and setup file parsing

  • setup/ - System initialization and configuration

  • simulationBox/ - Simulation cell, molecule and atom handling

  • connectivity/ - Molecular topology and bonding information

Data Management:
  • box/ - Simulation box geometry and periodic boundary conditions

  • physicalData/ - Physical constants and unit conversions

  • output/ - Output file generation and data writing

Computational Infrastructure:
  • linearAlgebra/ - Vector and matrix operations

  • utilities/ - General utility functions and helpers

  • kernels/ - Computational kernels and optimized routines

  • timings/ - Performance profiling and timing utilities

Advanced Features:
  • constraints/ - Constraint algorithms (SHAKE, RATTLE, etc.)

  • maxwellBoltzmann/ - Maxwell-Boltzmann velocity initialization

  • resetKinetics/ - Kinetic energy manipulation

  • virial/ - Virial stress tensor calculations

  • mpi/ - MPI parallelization support

  • python/ - Python bindings and interface

  • opt/ - Optimization algorithms

Design Patterns:
  • concepts/ - C++20 concepts for template constraints

  • exceptions/ - Custom exception classes

  • settings/ - Configuration and settings management

Build Configuration

The project uses CMake as its build system:

  • Root CMakeLists.txt configures the overall project

  • Each major directory contains its own CMakeLists.txt for modular compilation

  • External dependencies are managed through CMake’s FetchContent or find_package

  • Support for different build types (Debug, Release) and optional features (MPI support)

Software Tests

Unit Testing

Unit tests are located in the PQ/tests/ directory. After building the project, the unit tests can be run by executing the command make test from within the build directory.

Integration Testing

Integration tests are located in the PQ/integration_tests/ directory. To run these tests, ensure the following Python packages are installed:

In addition, the DFTB+ program package has to be installed. You can then run the integration tests with the command pytest PQ/integration_tests.

Performance Benchmarks

The Google Benchmark suite contains local wall-clock benchmarks for core algorithms. It is separate from the fixed-work performance checks in benchmarks/perf.

Configure and build the suite from the repository root:

$ cmake -S . -B build-benchmark -DCMAKE_BUILD_TYPE=Release -DBUILD_WITH_BENCHMARKING=ON -DBUILD_WITH_TESTS=OFF -DBUILD_WITH_ASE=OFF
$ cmake --build build-benchmark --target google_benchmarks

Run a short smoke test:

$ ctest --test-dir build-benchmark -L benchmark --output-on-failure

Run the full local suite and write JSON results to benchmark-results:

$ ./benchmarks/run_benchmarks.sh build-benchmark

The benchmarks are standalone executables in build-benchmark/benchmarks/src. For example:

$ ./build-benchmark/benchmarks/src/benchmark_forceCalculation

See benchmarks/README.md for filtering, output, and sampling-time options.

GitHub Actions

The software workflow — from building the project to running unit and integration tests — is validated by continuous integration (CI) using GitHub Actions. The corresponding workflow configuration files are located in the PQ/.github/workflows/ directory.

Coding Style

The C++ source code is formatted with clang-format using the project configuration in PQ/.clang-format. Use clang-format version 16 or newer. Older versions do not support all options used in the current configuration, and different clang-format versions can produce different formatting. When changing C++ files, format the touched files before committing them.

Documentation

Sphinx

This documentation is written as reStructuredText files .rst and converted to HTML website files by Sphinx . The respective source files are located in PQ/docs/sphinx/src/. In order to compile the files locally you need to install the following Python packages:

The project is built by running make html in the folder PQ/docs/sphinx/. The resulting website can be viewed by opening the file PQ/docs/sphinx/_build/html/index.html via your favorite browser.

Doxygen

PQ includes comprehensive API documentation generated using Doxygen. This documentation provides detailed information about all classes, functions, methods, and their usage throughout the codebase. The documentation is automatically extracted from specially formatted comments in the source code using Doxygen markup syntax. To generate the Doxygen documentation, you need to have Doxygen installed on your system. The documentation can be built as follows:

  1. Enable documentation during CMake configuration:

    $ cmake .. -DBUILD_WITH_DOC=ON
    
  2. Build the documentation:

    $ make docs
    
  3. View the documentation:

    $ <browser> build/docs/html/index.html
    

How to Contribute

For anyone willing to contribute to the project, it is important to understand the branching model used by the project. The project uses the git-flow branching model. Furthermore, git hooks for commit messages need to be enabled. In order to contribute to the project, please follow these steps:

  1. Fork the project on GitHub. (not necessary if you are a member of the project)

  2. Clone your fork locally:

    $ git clone https://github.com/MolarVerse/PQ.git
    
  3. Enable automated commit message validation by installing the provided git hook:

    $ cp .githooks/commit-msg .git/hooks/
    
  4. Initialize git-flow and use the following settings (if not specified default settings are used)

    $ git flow init
    [master] main
    [develop] dev
    [version tag prefix] v
    
  5. Create a feature branch for your contribution:

    $ git flow feature start <feature_branch_name>
    
  6. Commit your changes to your feature branch and publish your feature branch:

    $ git add <files>
    $ git commit -m "commit message"
    $ git flow feature publish <feature_branch_name>
    
  7. Add a changelog fragment describing your change (see Changelog Fragments below).

  8. Create a pull request on GitHub.

Changelog Fragments

PQ does not accumulate changelog entries by hand-editing CHANGELOG.md or DEV-CHANGELOG.md. Instead, every regular pull request adds a small Markdown file, a fragment, under PQ/changes/, and a CI check (changelog.yml) fails the pull request if none is present. At release time, scripts/update_changelog.py routes every fragment into the right changelog section, stamps a release header, and deletes the fragments it consumed.

Fragments live in one of two audience directories:

  • changes/user/ — for changes an installed-PQ user would notice: behavior, results, inputs, outputs, errors, compatibility, or runtime performance.

  • changes/developer/ — for build tooling, CI, tests, refactors, and other internal maintenance.

Within either directory, a fragment is named:

<category>.<title>.md

<category> selects the changelog section the entry is rendered under and must be one of the fixed categories for that audience (see changes/README.md for the full list, e.g. bugfix, enhancement, performance, build, ci, test, internal, documentation). <title> is a short, free-text, lowercase-with-hyphens slug identifying the change; it is only used to keep filenames unique and does not appear in the rendered changelog.

A fragment’s body is one or more Markdown bullets, one per line, with no blank lines in between. Each bullet becomes its own line in the changelog:

- Fix wrong virial mode when using atomic virial after copying physical data.
- First point about this change.
- Second, related point about the same change.

If your pull request extends a change that already has an unreleased fragment, append another bullet to that existing file instead of creating a new one. A pull request may add new fragments, append to existing ones, or both, and may touch both audiences, but it must not delete unreleased fragments or edit CHANGELOG.md / DEV-CHANGELOG.md directly.