VOLT

Plugin Development

Build custom analysis plugins for VOLT using CoreToolkit.

Overview

VOLT plugins are standalone C++ executables that link against CoreToolkit. Each plugin reads a LAMMPS dump frame, performs an analysis algorithm, and outputs results in MessagePack format. Once compiled, a plugin can be installed on any ClusterDaemon.

Prerequisites

RequirementVersion
C++ compilerC++23 capable (GCC 14+ or Clang 17+)
CMake≥ 3.20
Conan≥ 2.0

If you don't have these, the Ecosystem Setup script can install them for you.

Project Structure

A typical plugin has this layout:

MyPlugin/
├── CMakeLists.txt
├── conanfile.py
├── src/
│   └── main.cpp
└── .github/
    └── workflows/
        └── publish-plugin-binary.yml

Step 1: CMakeLists.txt

cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
project(myplugin VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type")

find_package(coretoolkit REQUIRED)
find_package(Threads REQUIRED)

add_executable(${PROJECT_NAME} src/main.cpp)

target_link_libraries(${PROJECT_NAME} PRIVATE
    coretoolkit::coretoolkit
    Threads::Threads
)

target_compile_options(${PROJECT_NAME} PRIVATE
    $<$<AND:$<CONFIG:Release>,$<CXX_COMPILER_ID:GNU,Clang,AppleClang>>:
        -O3 -march=native
    >
)

install(TARGETS ${PROJECT_NAME} DESTINATION bin)

Step 2: conanfile.py

from conan import ConanFile
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout


class MyPluginConan(ConanFile):
    name = "myplugin"
    version = "1.0.0"
    settings = "os", "arch", "compiler", "build_type"
    requires = ("coretoolkit/1.0.0",)

    def layout(self):
        cmake_layout(self)

    def generate(self):
        CMakeToolchain(self).generate()
        CMakeDeps(self).generate()

    def build(self):
        cmake = CMake(self)
        cmake.configure()
        cmake.build()

Step 3: Plugin Source Code

Here's a minimal plugin that computes per-atom coordination numbers:

#include <volt/core/volt.h>
#include <volt/core/lammps_parser.h>
#include <volt/core/frame_adapter.h>
#include <volt/core/simulation_cell.h>
#include <volt/core/particle_property.h>
#include <volt/core/analysis_result.h>
#include <volt/analysis/cutoff_neighbor_finder.h>
#include <volt/cli/common.h>

#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>

int main(int argc, char* argv[])
{
    // Parse CLI arguments (handles --input, --output, --params)
    auto args = volt::cli::parse(argc, argv);

    // Read the LAMMPS dump frame
    auto frame = volt::core::LammpsParser::parse(args.inputPath);

    // Read parameters from JSON
    double cutoff = args.params.value("cutoff", 3.0);

    // Build neighbor list
    volt::analysis::CutoffNeighborFinder finder(
        frame.positions(),
        frame.simulationCell(),
        cutoff
    );

    // Compute coordination for each atom
    std::vector<int> coordination(frame.atomCount());
    for (size_t i = 0; i < frame.atomCount(); ++i) {
        coordination[i] = finder.neighborCount(i);
    }

    // Build the result
    volt::core::AnalysisResult result;
    result.addProperty("Coordination", coordination);

    // Write MessagePack output
    result.write(args.outputPath);

    return 0;
}

Step 4: Build Locally

First, make sure CoreToolkit is exported as a Conan package:

# Clone CoreToolkit if you haven't already
git clone https://github.com/VoltLabs-Research/CoreToolkit.git
conan export CoreToolkit

# Build your plugin
cd MyPlugin
conan install . --build=missing --output-folder=build -o "hwloc/*:shared=True"
cmake -S . -B build/build/Release \
    -DCMAKE_TOOLCHAIN_FILE=build/build/Release/generators/conan_toolchain.cmake \
    -DCMAKE_BUILD_TYPE=Release
cmake --build build/build/Release -j$(nproc)

The resulting binary will be at build/build/Release/myplugin.

Step 5: CI with GitHub Actions

CoreToolkit provides a reusable workflow that builds your plugin on Linux, macOS, and Windows, then publishes the binary to GHCR as an OCI artifact.

Create .github/workflows/publish-plugin-binary.yml:

name: Publish Plugin Binary

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  build:
    uses: VoltLabs-Research/CoreToolkit/.github/workflows/build-plugin-binary.yml@main
    with:
      plugin_name: MyPlugin
    permissions:
      contents: read
      packages: write

After a push, your binary will be available at:

ghcr.io/your-org/myplugin-binary:sha-<commit>-linux-x64

CoreToolkit API Quick Reference

Parsing

ClassHeaderPurpose
LammpsParservolt/core/lammps_parser.hParse LAMMPS dump files
FrameAdaptervolt/core/frame_adapter.hAccess frame data (positions, types, cell)
SimulationCellvolt/core/simulation_cell.hBox vectors, periodicity, coordinate wrapping
ClassHeaderPurpose
CutoffNeighborFindervolt/analysis/cutoff_neighbor_finder.hFind neighbors within a distance cutoff
NearestNeighborFindervolt/analysis/nearest_neighbor_finder.hFind k-nearest neighbors

Math

ClassHeader
Vector3volt/math/vector3.h
Matrix3volt/math/matrix3.h
Quaternionvolt/math/quaternion.h
SymmetricTensorvolt/math/symmetric_tensor.h
AffineTransformationvolt/math/affine_transformation.h

Output

ClassHeaderPurpose
AnalysisResultvolt/core/analysis_result.hBuild and serialize analysis results
ParticlePropertyvolt/core/particle_property.hPer-atom typed property storage

CLI

FunctionHeaderPurpose
volt::cli::parse()volt/cli/common.hParse --input, --output, --params arguments

Plugin I/O Contract

Input

The plugin receives:

  • --input: Path to a LAMMPS dump file (single timestep).
  • --output: Path where the MessagePack result should be written.
  • --params: JSON string with user-configured parameters.

Output

The plugin writes a MessagePack file containing per-atom properties and optional metadata. The VOLT platform reads this file, stores it in MinIO, and makes it available for visualization in the 3D viewer.

On this page