lwONIOM
July 31, 2026 · View on GitHub
This repository contains a standalone implementation of a light-weight ONIOM interface.
The default CMake and meson builds compile a static library that can be linked into other projects.
The library contains implementations for partitioning of a molecular system into the individual ONIOM fragments, including saturation of bonds with hydrogen linking atoms, and the reconstruction of respective energies, gradients and Hessian matrices. Multi-centered (MC-)ONIOM setups with several non-overlapping fragments per layer and arbitrary layer depth are supported.
Adhering to the eponymous light-weight aspect, no potentials are implemented in the library itself as it is intended for the use in other codes.
A complete example of the TOML input format (a 5-center, 3-layer MC-ONIOM setup) is provided in example/.
lwONIOM is a pure Fortran library: it requires no BLAS/LAPACK and no OpenMP. The only (optional) dependency is toml-f, which provides the TOML input parser.
Library usage
Host codes interact with the library through the lwoniom_interface module, at
one of two levels:
-
Manual: set up the model once (
lwoniom_parse_inputfile+lwoniom_new_calculator, orlwoniom_initializewith plain arrays), then per geometry: update the fragments, run your own calculations for each of them, write the results into the fragment data, and calllwoniom_singlepoint/lwoniom_gethessfor the ONIOM totals. -
Driver layer: extend the abstract type
lwoniom_calculatorwith anengradimplementation for a single model system, and let the library orchestrate everything else — including the finite-difference ONIOM Hessian:call lwoniom_engrad_driver(dat, mycalc, nat, xyz, energy, gradient, iostat=io) call lwoniom_numhess_driver(dat, mycalc, nat, xyz, hessian, iostat=io)The list of required calculations (fragment, high/low level, associated
layerleveltheory id) is available separately vialwoniom_get_jobs, e.g. for setting up the host-side calculators.
For non-Fortran hosts, a C API (include/lwoniom_c.h, implemented in
src/lwoniom_capi.F90) exposes the same job-loop workflow through an opaque
handle: init → update → per job get geometry / place result → singlepoint,
plus the Hessian counterparts.
Python / ASE
python/ contains a ctypes-based Python package on top of the C API, with
an ASE calculator where the individual
potentials are ordinary ASE calculators (one instance per ONIOM job, so
stateful backends persist across geometry steps):
from ase.calculators.emt import EMT
from lwoniom.ase_calc import ONIOM
atoms.calc = ONIOM(layers=[[1, 2, 6, 7, 8]], # embedded region (0-based)
calculators={1: EMT, 2: EMT}) # theory id -> factory
atoms.get_potential_energy()
Installation from the source tree compiles and bundles the shared library automatically (needs a Fortran compiler; meson/ninja are fetched by pip):
pip install . # from the repository root
Multi-center setups use fragments= (atom index lists) plus a fragment-wise
layers= assignment, mirroring the TOML input. Two runnable showcases live
in example/: ase_oniom.py (2-layer, job table, geometry optimization) and
ase_oniom_mc.py (3-layer MC-ONIOM with four centers on the 58-atom example
system). The raw lwoniom.LWONIOM class exposes the job-loop API directly
(atomic units) for hosts other than ASE.
For development, use an editable install instead — it skips the bundling and finds the library in the checkout:
meson setup _build -Ddefault_library=shared && ninja -C _build
pip install -e .
python -m pytest python/tests
Building the Project
Make sure you have the following dependencies installed:
- CMake and
make, or meson and ninja build systems - A Fortran compiler (
gfortran,ifx, orifort)
Check out the submodules (toml-f, and test-drive for the unit tests)
before the first build:
git submodule update --init --recursive
Instructions
Follow these steps to build the project:
-
Set up the build directory with your chosen build system:
- using meson:
FC=gfortran meson setup _build - using CMake:
FC=gfortran cmake -B _build
For the Intel toolchain, source the oneAPI environment first and use one of the machine files in
config/(meson), or setFC(CMake):source /opt/intel/oneapi/setvars.sh meson setup _build --native-file config/intel-llvm.ini # ifx FC=ifx cmake -B _build - using meson:
-
Build the project. If you have multiple cores/processors, you can speed up the build process by specifying the number of cores to use with the
-joption:- With meson/
ninja:ninja -C _build -j4 - With CMake/
make:cmake --build _build -j4
- With meson/
-
Run the unit tests:
meson test -C _build # or: ctest --test-dir _build
Build options
| meson | CMake | default | description |
|---|---|---|---|
-Dtoml-f=auto/enabled/disabled | -DWITH_TOMLF=ON/OFF | on | TOML input parser via toml-f |
-Dtests=true/false | -DWITH_TESTS=ON/OFF | on | unit tests (test/, uses test-drive) |
-Dstatic=true/false | — | off | attempt a fully static binary |
Cleaning the Build
To clean the build files, simply delete the build directory:
rm -rf _build
Use as a subproject
lwONIOM is built as a subproject of crest.
Both build systems detect that situation and then build only the library: the
unit tests and the license install are skipped, and no -static link flags are
injected — the parent project owns the final link step.
-
meson — the exported dependency variable is
lwoniom_dep, as declared in crest'ssubprojects/lwoniom.wrap:lwoniom_dep = dependency('lwoniom', fallback: ['lwoniom', 'lwoniom_dep'])The
toml-fandstaticoptions areyield-ed and named exactly like crest's, so they are inherited from the parent automatically, and the parent's already resolved toml-f subproject is reused instead of configuring a second copy. -
CMake —
add_subdirectory()provides thelwoniomtarget, which crest'sFindlwoniom.cmakewraps into the imported targetlwoniom::lwoniom.WITH_TOMLF/WITH_TESTSare named like crest's cache entries, and toml-f is only searched for when the parent has not already providedtoml-f::toml-f.