Thank you for your interest in contributing to MOIST! We're excited to collaborate with you.
Before you start, please read the following guidelines; this will allow for faster and better collaboration.
There are many ways to contribute: writing tutorials or blog posts, improving the documentation, submitting bug reports and feature requests or writing code which can be incorporated into MOIST itself.
MOIST aims at reusable solvation models and infrastructure; contributions should follow the following principles:
- Consistent API: the API for models and components has to be well-defined and consistent.
- Separation of responsibilities: QM hosts provide electronic-structure quantities; MOIST provides solvation models and their response.
- Reusable building blocks: reusable components composed through OOP and abstraction.
- Performance-awareness: performance should be considered as part of the architecture.
- Method development: the architecture should allow for method development.
- Please open an issue first for major features, infrastructure or API changes.
- Branch off
mainand open a pull request againstmain; keep one topic per pull request. Large PRs should be split into smaller ones. - All Build workflow jobs have to pass before merging (CI).
- Contributions are licensed under the MPL-2.0, the license of the project.
- Meson is the primary build system; CMake is tested in CI as well, so changes have to work with both (use separate build directories):
- Meson:
meson setup build-meson && meson test -C build-meson --print-errorlogs - CMake:
meson subprojects download && cmake -B build-cmake -G Ninja && cmake --build build-cmake && ctest --test-dir build-cmake
- Meson:
- Python bindings and PySCF coupling: configure Meson with
-Dpython=true, then runmeson test -C build-meson --suite python(bindings and PySCF tests); when running pytest directly,MOIST_REQUIRE_PYSCF=1turns skipped PySCF tests into failures. - Long-running diagnostic tests are built with
-Ddev_tests=true(test/dev/). - CI covers GCC, ifx, classic ifort, ILP64, macOS and Windows; stick to standard Fortran 2018 without compiler extensions.
- Adhere to the verbosity level (levels in
src/moist/context.f90); warnings always print:0: silent1: quiet (main results, once per run)2: normal, the library default for host integration: settings once per run and a summary per geometry, but no output duringget_energy,get_responseorget_gradient, so nothing prints inside the host's SCF iterations3and4: more verbose (all settings and tables, solver summaries)5and6: solver traces and debug output
- Route output through the run context (
moist_context), whosemessageprocedure is gated by verbosity (debug_messageby the debug flag); avoid bareprint/writestatements. - Use
prettyprinterandprettylistprinter(seemoist_utils_prettyprintandmoist_utils_prettylistprintinsrc/moist/utils/) for printing.
- Lint with
fortitudefrom the project root:fortitude check --output-format=concise src/ app/ test/(configured infortitude.toml); the Lint workflow runs the same check on every pull request. - Use 3-space indentation and match the style of the surrounding code;
fprettify-i 3is a good start for new files, but do not run it over existing files, as it would also reformat unrelated lines. - Use
ford-compatible comment style (config inford.md, docmark!>):- One-line summary above every module, type, and procedure; an empty
!>line, then one@param[in|inout|out]line per dummy argument. - A
!>comment above every dummy declaration and type component, except theerrordummy of a test procedure whose only argument it is. - Dimensions should be indicated by e.g.
(nat, 3, 3). - Give units if appropriate.
- One-line summary above every module, type, and procedure; an empty
- Use good-practice docstring formatting:
- Keep it short and use bullet points.
- Keep units, shapes, ranges, and defaults; no filler words ("This routine", "is used to").
- ASCII-only in source and comments.
- Report failures through
error_type/fatal_errorfrommctc_envrather than silently returning defaults. - Keep code thread-safe under OpenMP (
-Dopenmp=true); avoidsaved state. - Python code (
python/moist/) supports Python 3.10 and newer.
- Expose new features consistently in all three interfaces, each with tests:
- Fortran
- C:
src/moist/api.f90andinclude/moist.h, tested intest/api/example.c - Python:
python/moist/library.pyandpython/moist/interface.py, tested inpython/tests/
- Keep the interfaces as consistent with each other as possible: the same names, argument order, units, defaults and error behavior, deviating only where a language requires it (e.g.
lambda_in Python,moist_prefixes and handles in C). - Keep the C ABI stable (see the rules in
include/moist.h): options structs only grow at the end, and enum values should never change. - New settings extend
moist_model_parameters_type(JSON/TOML input/output, validation, defaults, printing); define defaults in one place and keep the documentation in sync. - Note breaking changes (renamed arguments, changed defaults) in the release notes.
- Files marked "generated by pcmgen, do not edit" (the PCM kernels in
src/moist/model/continuum/component/pcm/kernel/and the DROP LSF kernels) are changed in the generator and regenerated; the header records the generator commit. - Vendored third-party code stays close to upstream; record it in
THIRD_PARTY_NOTICES.md.
- The code has to be well tested.
- One suite per file (module):
test/unit/test_<id>.f90defines moduletest_<id>withcollect_<id>. Register new suites intest/unit/meson.build(testslist),test/unit/main.F90, andCMakeLists.txt(moist_test_suites). - Run with
meson test -C build-meson --print-errorlogs. Suites run their tests in parallel, so avoidsaved state in test helpers. - Every new feature or bug fix comes with a test.
- Check analytic derivatives (Fock contributions, gradients, surface weights) against finite differences.
- Expected failures (rejected input, guarded misuse): one test per failing case, registered with
new_unittest(..., should_fail=.true.), which returns the library error as its test failure.
- User documentation is Sphinx in
docs/(seedocs/requirements.txt); build withsphinx-build -E -W -b html docs docs/_build/html(-Eavoids stale pages,-Wfails on warnings). - API documentation is generated by FORD from the source comments:
pip install fordandford ford.md; the HTML lands indocs/ford/index.html(ignored by git). Adjustsrc_dirinford.mdif you add a new source tree. - When adding a cavity, model, or component:
- Add or update its
.rstpage and the support tables indocs/cavities/index.rstordocs/models/components/index.rst. - Add its references to
docs/_static/references.biband tosrc/moist/output/citations.f90(printed bymoist --citation). - Add it to the feature list in
README.md.
- Add or update its
- Solvent IDs are frozen; new solvents are appended.
- Keep logos in
docs/_static/logos/and figures indocs/_static/figures/<topic>/.
- MOIST follows SemVer with an optional pre-release suffix (e.g.
1.2.1-alpha). - To bump the version, edit
VERSION, runconfig/sync-version.sh(checked in CI), and update the version string intest/api/example.cby hand. - Add an entry to
docs/changelog.rst. - Pushing a
v*tag builds the release binaries and publishes the GitHub release.