Development Tips#
Git collaborative workflow#
The recommended workflow is:
Fork the repository.
Create a topic branch for your changes.
Rebase your branch on
masterwhen it is ready for review.Resolve any conflicts locally.
Open a merge request.
Address review comments.
Merge with a fast-forward merge.
Fortran binding#
When updating the Fortran binding, make sure that the LibrpaOptions derived
type in binding/fortran/librpa_f03.f90 matches the definition in
include/librpa_options.h.
After modifying librpa_f03.f90, run the stub-conversion script so that the
stub module stays synchronized with the main binding module.
cd binding/fortran
../../utilities/convert_fortran_module_to_stub.py librpa_f03.f90 librpa_f03_stubs.f90
Code style#
LibRPA does not enforce a strict project-wide code style. However, the repository
does provide a .clang-format file for formatting C and C++ code with
clang-format.
The goal is to avoid spending review time on personal formatting preferences,
such as whether an opening brace should be placed on a new line. The
.clang-format settings naturally encode some preferences, but the main purpose
is to make formatting mechanical and consistent.
Use clang-format for new C and C++ code. Avoid reformatting old code unless you
are making substantial changes in the same area, or unless the commit is
explicitly dedicated to formatting cleanup. This keeps functional diffs focused
and easier to review. Modern editors with language-server support should be able
to pick up the repository formatting rules automatically.
For naming, follow these general conventions:
Use
UpperCamelCasefor classes and structs.Use
snake_casefor variables, object instances, functions, and namespaces.Use
SCREAMING_SNAKE_CASEfor constants.
Source code structure of LibRPA#
.
|-- binding
| `-- fortran : Fortran bindings and binding tests
|-- cmake : CMake find modules and build helper scripts
|-- docs : Sphinx/MyST user and developer documentation
|-- driver : Command-line driver, input parsing, and data readers
| `-- tasks : Driver task implementations
|-- examples
| `-- build : Example build scripts for common platforms
|-- include : Public C and C++ API headers
|-- regression_tests : Regression suite definitions, test cases, and references
|-- src : Source code for the library target
| |-- api : Public API implementation and handler/dataset glue
| |-- core : Physics objects and algorithms: basis, RPA, EXX, GW, symmetry
| |-- elpa : ELPA eigensolver integration
| |-- gpu : Optional CUDA/HIP device and linear-algebra adapters
| |-- interface : Thin interfaces to external codes, e.g. BLAS, LAPACK, and ScaLAPACK
| |-- io : Filesystem, ELSI/GW I/O, and stream-printing helpers
| |-- math : Utilities of matrix, vector, interpolation, fitting, etc.
| |-- mpi : MPI, BLACS, and k-point/process-grid helpers
| |-- utils : Constants, errors, profiling, memory, and configured build information
| `-- test : C++ unit and MPI tests for library components
|-- thirdparty : Bundled external libraries used when not supplied by the user
`-- utilities : Standalone conversion, consistency-check, and maintenance tools
The public API path is include/librpa*.h(pp), implemented under src/api.
The driver path is driver/main.cpp with tasks implemented under driver/tasks
and input data coming from driver/read_data.cpp. Library code (src/)
should stay independent of the command-line driver (driver/).
A few C++ guidelines#
General coding guidelines:
Avoid forward declarations for concrete classes and structs; include the header that provides the necessary definition.
Prefer RAII, standard containers, references, and
constcorrectness; make ownership and mutation explicit.Treat MPI layout, rank ownership, and collectives as part of the program behavior; check both serial and representative multi-rank cases when they may be affected.
Use clear, explicit control flow for indexing, basis mappings, matrix layouts, and symmetry logic. Add a short comment when the physical or parallel assumption is not obvious from the code.
Below are a few specific guidelines for LibRPA:
Library components (non-test code under
src/) should remain host-agnostic: they must not assume that input data follows the convention of any particular host program. The host should communicate its conventions through the public API, for example viaset_basis_convention; LibRPA internals should use only the parsed convention values when interpreting input data. The standalone driver follows the same rule by reading conventions from input files and passing them through the API. For user convenience, input files may still provide producer presets, such as a program name, as shorthand for a known set of conventions.When adding code in
src/core, consider whether reusable pieces belong in utility components such assrc/math,src/mpi,src/io, orsrc/utils; implement those pieces in the appropriate place and assemble the core algorithm undersrc/core.Source files outside
src/coreshould not include headers fromsrc/core; C APIs and dataset instances insrc/apiare the exceptions.Implement public behavior in the C API first; the C++ API (
src/api/librpa.cpp) and Fortran bindings (binding/fortran) should wrap that C layer.Files in
src/interfaceshould not include internal headers outsidesrc/interface.In principle, do not read input files in library code (
src/). Restart check-point files generated by the library itself are the only exception.Use
src/io/stl_io_helper.hwhen printing STL containers.Driver code (
driver/) should not directly modify internal objects owned by aLibrpaHandler. Input parsing and output retrieval should go through public APIs. The only exception is an early task prototype; in that case, helper functions that mutate internal objects should remainstaticin the prototype task source,driver/tasks/{proto}.cpp.
Adding new runtime options#
Prefer
output_oruse_prefixes forLibrpaSwitchoptions when they describe the behavior clearly; use another verb prefix when it is more precise, such asread_sigc_mat_rf.Option with a few available values can either be an
inttype starting withoption_, or a dedicatedenumtype defined inlibrpa_enums.h.Try to keep the option name short, favorably no longer than 25 characters.
Doxygen docstrings in
driver/driver.handinclude/librpa_options.hare the source of truth for runtime-parameter documentation. Put the explanation, default value, status, version information, and deprecation note there.Add the option to the appropriate block in
docs/user_guide/runtime_parameters.yml; this controls where the generated user-guide table places the keyword.Use
utilities/check_librpa_options.pyto cross-check the consistency between the C struct, Fortran interface and high-level wrapper ofLibrpaOptions.