This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
LAMMPS-GUI (v3.x) is a Qt6-based graphical interface for the LAMMPS molecular dynamics simulation software. It provides a code editor with syntax highlighting and auto-completion, live LAMMPS simulation execution, log/chart/image visualization, and an integrated tutorial system. The project is GPLv2+ licensed (note: thirdparty/rangeslider/rangeslider.{cpp,h} is third-party under the CeCILL-A license).
- Online documentation: https://lammps-gui.lammps.org/
- C++17, CMake ≥ 3.20, Qt6 (minimum 6.2; only the Gui, Widgets, Network, and Svg modules — charts are rendered natively, so no Qt Charts/Graphs/Quick)
Typical plugin-mode build (LAMMPS library loaded dynamically at runtime — the default):
cmake -S . -B build -DLAMMPS_GUI_USE_PLUGIN=ON -DBUILD_DOC=OFF
cmake --build build -j$(nproc)Linked mode (requires LAMMPS source tree and pre-built library):
cmake -S . -B build \
-DLAMMPS_GUI_USE_PLUGIN=OFF \
-DLAMMPS_SOURCE_DIR=/path/to/lammps/src \
-DLAMMPS_LIBRARY=/path/to/liblammps.so
cmake --build build -j$(nproc)Default install prefix is $HOME/.local (no root required).
Useful CMake options:
| Option | Default | Description |
|---|---|---|
LAMMPS_GUI_USE_PLUGIN |
ON |
Load LAMMPS .so at runtime via dlopen |
BUILD_DOC |
ON |
Build Sphinx HTML docs along with the app (slow; disable for code-only work) |
BUILD_DOC_ONLY |
OFF |
Build only Sphinx/Doxygen docs, skip the C++ binary entirely |
ENABLE_TESTING |
OFF |
Enable unit + GUI tests (Linux only) |
Documentation-only build (no C++ compilation needed):
cmake -S . -B build-doc -DBUILD_DOC_ONLY=ON
cmake --build build-doc --target doc
# Output: build-doc/doc/html/index.htmlDocumentation build targets (when BUILD_DOC=ON or BUILD_DOC_ONLY=ON):
| Target | Description |
|---|---|
html / doc |
Full Sphinx HTML docs (runs Doxygen first) |
doxygen |
Doxygen XML only (intermediate step) |
pdf |
LaTeX → PDF (requires pdflatex + latexmk) |
spelling |
Sphinx spell checker |
linkcheck |
Sphinx broken-link checker |
Tests are Linux-only and off by default. Enable them at configure time:
cmake -S . -B build -DLAMMPS_GUI_USE_PLUGIN=ON -DBUILD_DOC=OFF -DENABLE_TESTING=ON
cmake --build build -j$(nproc)
ctest --test-dir build --output-on-failureRun a subset by name pattern (tests are registered under their GoogleTest suite
names, e.g. HelpersTest.*, not the executable names):
ctest --test-dir build -R HelpersTest --output-on-failure
ctest --test-dir build -R Framebuffer --output-on-failure # GUI tests need Xvfb + screenshooterTest categories:
test_*executables — C++ unit tests (GoogleTest v1.17.0, fetched automatically via FetchContent); one per tested module: helpers, stdcapture, flagwarnings, dumpimage, movieimport, imagecache, leastsquares, plotdata, lepton, levmar, customfunc, analysis, plotaxismath, and fittingCommandLine.*— command-line flag smoke testsFramebuffer.*— Python/PyAutoGUI GUI tests run inside Xvfb; requirexvfb-runand one of:magick,import,xfce4-screenshooter, orgnome-screenshot
The codeql-analysis.yml workflow runs CodeQL on every push to develop in
build mode (it compiles via CMake) with the security-and-quality query
suite; its config is .github/codeql/cpp.yml. Two settled points:
paths/paths-ignoredo nothing for built C/C++. CodeQL honors them only for interpreted languages orbuild-mode: none, so they cannot scope analysis tosrc/or excludethirdparty/,plugin/, or generatedbuild/moc files; dismiss those alerts in the code-scanning UI instead.- Do not switch to
build-mode: none. It was tried and reverted: on this Qt codebase, no-build extraction misparses theslots/signalsmacros (reported asintbit-fields), cannot resolve cross-file references (false "unused" statics), and has weak dataflow (falseconstant-comparison) -- roughly 50 false positives. Build mode analyzes the real compiled + moc output and is accurate.
All C++ source is formatted with clang-format using the config in .clang-format (LLVM base, 4-space indent, 100-column limit, custom brace wrapping). Before committing:
clang-format -i src/*.cpp src/*.hFile headers use // -*- c++ -*- Emacs mode line; maintain it on new files.
- GPG-sign all commits. Every commit must carry a verifiable GPG signature.
- No
Co-Authored-By:orClaude-Session:attribution in commit messages. AI attribution belongs in pull request descriptions only. - Doxygen comments on all new public APIs. Use
/** @brief ... */Javadoc style for classes and methods;///< descriptionfor member variables. Seesrc/lammpsgui.hfor a comprehensive example. - New public classes need a
.. doxygenclass::entry indoc/api_reference.rst. Thehelpers.hblock uses.. doxygenfile:: helpers.h :sections: func, which renders only free functions, so a new helper class (e.g. an RAII guard) is otherwise missing from the generated API docs. - Documentation changes in American English with plain ASCII characters (no typographic quotes, em-dashes as
--, etc.). - New
.cpp/.hfiles must be added toPROJECT_SOURCESincmake/Sources.cmake. Qt'sAUTOMOChandlesmocgeneration automatically, but the file must be listed there. The top-levelCMakeLists.txtholds only the configuration options and the executable target; the remaining build logic lives in include files undercmake/(Platform, Sources, Testing, Sanitizer, Documentation, Packaging).
main.cpp
└─ LammpsGui (QMainWindow) ← central coordinator
├─ CodeEditor (QPlainTextEdit) ← input script editor
│ ├─ Highlighter ← LAMMPS syntax highlighting
│ ├─ FindAndReplace ← non-modal find/replace dialog
│ └─ QCompleter × N ← per-command-type auto-complete
├─ LammpsWrapper ← thin C++ wrapper around LAMMPS C API
├─ LammpsRunner (QThread) ← runs LAMMPS in background thread
├─ StdCapture ← redirects stdout→pipe to capture LAMMPS output
├─ LogWindow (QPlainTextEdit) ← displays captured log; uses FlagWarnings highlighter
├─ ImageViewer (QDialog) ← interactive dump-image viewer
├─ SlideShow (QDialog) ← slideshow viewer for image sequences
├─ TutorialWizard (QWizard) ← step-by-step tutorial setup wizard
├─ ChartWindow ← thermo chart container; owns N ChartColumn data objects
│ └─ ChartViewer ← single rebindable view of the active ChartColumn
│ └─ PlotWidget ← QPainter 2D line/scatter renderer (sole chart backend)
└─ Preferences (QDialog) ← settings; stored via QSettings
Plugin vs. linked mode. When built with LAMMPS_GUI_USE_PLUGIN=ON (default), the executable has no link-time dependency on LAMMPS. plugin/liblammpsplugin.c provides dlopen-based dispatch; LammpsWrapper calls through function pointers loaded at startup. This lets the GUI ship as a standalone binary that can download or swap LAMMPS shared libraries.
Native chart rendering. Charts are drawn by a single self-contained renderer, PlotWidget (src/plotwidget.{cpp,h}), a QWidget+QPainter 2D line/scatter plotter that depends only on Qt Widgets — no Qt Charts, Qt Graphs, or QML. ChartWindow owns one ChartColumn per thermo column — the neutral PlotSeries data objects (src/plotseries.h) live there — plus a single ChartViewer that is rebound (via setColumn()) to whichever column is selected and renders it through PlotWidget; axis-layout math (nice ticks, label formatting) lives in the Qt-free plotaxismath (src/plotaxismath.{cpp,h}). Both the old one-ChartViewer-per-column layout and the ChartBackend/QtCharts/QtGraphs abstraction were removed once the native single-view renderer reached parity; history and rationale are in doc/native-chart-backend.md.
Threading model. LAMMPS simulations run on a LammpsRunner (QThread). StdCapture intercepts the LAMMPS library's stdout by replacing the file descriptor before LammpsRunner::run() starts. A QTimer in LammpsGui polls StdCapture::getChunk() to feed LogWindow without blocking the UI thread.
Auto-completion. CodeEditor maintains a separate QCompleter instance for each LAMMPS command category (fix styles, compute styles, pair styles, etc.). Completions are populated from style lists queried from LammpsWrapper after LAMMPS is initialized, plus static tables embedded as Qt resources.
Resources. resources/lammpsgui.qrc embeds icons, help_index.table (maps LAMMPS commands to doc URLs), image_style.table (dump image options), and lammps_internal_commands.txt. The .table files are plain text and have companion shell scripts (update-help-index.sh, update-image-styles.sh) to regenerate them from a LAMMPS source tree.
Constants and settings keys. src/constants.h holds two intentionally short, internal namespaces: Cfg (application-wide magic numbers and repeated string literals -- UI dimensions, update intervals, resource paths, version constants) and Keys (every persisted QSettings key and group name). New hardcoded values and any new QSettings key go there. Reference them qualified -- Cfg::PREFERENCES_WIDTH, Keys::ZOOM -- never via using namespace/aliases: the namespaces are deliberately terse so the qualifier stays cheap, and the Keys:: prefix keeps the generic key names (e.g. NAME, TYPE, ID) readable and collision-free. A mistyped settings key is then a compile error, not a silently lost setting.
Minimum LAMMPS version. Cfg::MIN_LAMMPS_VERSION (see src/constants.h for the current value) is enforced at startup; the GUI warns and may refuse to run with older LAMMPS builds.
Dialog widget wiring. ImageViewer and the Preferences tabs connect widgets to slots via setObjectName("...") + later findChild<T>("...") rather than stored member pointers. Preserve object names exactly when refactoring these dialogs (a wrong/renamed name fails the lookup silently, with no compile error).
Shared helpers (prefer over re-rolling). Use the StdoutSilencer RAII guard (helpers.h) instead of manual silenceStdout()/restoreStdout() pairs; the QtMessageSilencer RAII guard (helpers.h) around a call whose Qt-internal warnings are expected and handled (note it cannot catch messages a library prints straight to stderr, such as libpng's libpng error: lines); LammpsWrapper::lastErrorMessage() instead of a hand-managed getLastErrorMessage() buffer; LammpsGui::addMenuAction() to build menu actions; monoFontFromSettings() for the configured fixed-width font; styleDialogButtons() to apply the bundled SVG icons to a QDialogButtonBox; toolButtonSize()/styleToolButtons() for square toolbar buttons; applyWindowFlags() for the shared output-window WM hints.
These are the settled conventions for new and refactored code; the staged cleanup that brought the existing code into line is complete.
QString is the canonical internal string type. It already dominates
(~350 declarations vs. ~25 std::string). Keep char * and std::string
out of internal interfaces; pass and return QString.
Confine all string conversions to LammpsWrapper (the LAMMPS C API is
the only place char * is unavoidable). Do not sprinkle toStdString() /
.c_str() / char buf[N] at call sites. Two patterns already in the
wrapper are the templates to copy:
- Input: use either
const char *orconst QString &asextractSetting(),extractGlobal()orcommand(),file(). Do the former when only string constants are used as arguments. - Output: return a
QStringand manage the buffer internally, aslastErrorMessage(),idName(),styleName(), andvariableInfo()do (theirchar *-buffer variants are private implementation details behind the QString-returning public API).
Avoid QString -> std::string -> QString round-trips. splitLine now
parses the QString directly (via utf16()) and returns a QStringList;
the toStdString() calls that remain sit at genuine boundaries to
std::string-only subsystems (LeptonMini, plotaxismath, the LAMMPS
runner) rather than being gratuitous conversions.
Match the existing modern-C++ baseline. This code already uses
nullptr, auto, range-based for, override, constexpr, = default,
and an explicit Rule-of-5 (= delete / = default for all five special
members) on essentially every class; mirror that on new classes. Prefer
std::make_unique and smart pointers for owned non-QObject resources
(QObject parent/child ownership via new with a parent is still the Qt
idiom and is fine). Use static_cast rather than C-style casts, the
function-pointer connect() form (never SIGNAL()/SLOT() strings), and
enum class for new internal enumerations that do not need implicit int
interop with the LAMMPS API.
We are adding an AI assistant to the GUI frontend of this physics-simulation software. Work is exploratory: build a minimal implementation first to probe workflow options, then decide a fuller architecture and implement interactively.
Before working on this feature, read doc/ai-assistant-design.md — it is
the durable design memory (provider abstraction, RAG, reliability via
verification, tool-calling file generation, the wizard/expert-system model, the
probe verify-repair loop, and the case-based learning approach). Treat its
decisions and caveats as binding unless we explicitly revise them here.
- The assistant produces a starting point, not a validated solution.
- Structural correctness comes from vetted templates and executable verification (the simulator as oracle) — never from the model's unaided judgment.
- Treat all model-generated files as untrusted; validate before loading.
- Never hardcode or commit API keys.
- Prefer deterministic checks/lookup tables for known cases; use the LLM for the fuzzy long tail and explanation.
| File(s) | Responsibility |
|---|---|
src/main.cpp |
App entry point, CLI parsing, font init |
src/lammpsgui.{cpp,h} |
Main window: menus, file ops, run control, tutorial wizard glue |
src/lammpswrapper.{cpp,h} |
All calls to the LAMMPS C library API |
src/lammpsrunner.{cpp,h} |
Background thread that calls lammps->commandsString() / lammps->file() |
src/stdcapture.{cpp,h} |
fd-level stdout capture using a pipe |
src/codeeditor.{cpp,h} |
Custom editor: line numbers, context menu help, drag-and-drop |
src/linenumberarea.h |
Header-only margin widget used internally by CodeEditor |
src/highlighter.{cpp,h} |
Syntax highlighting rules for LAMMPS input scripts |
src/findandreplace.{cpp,h} |
Non-modal find/replace dialog for the editor |
src/logwindow.{cpp,h} |
Log viewer; delegates warning highlighting to FlagWarnings |
src/flagwarnings.{cpp,h} |
QSyntaxHighlighter for warnings/errors/URLs in log text |
src/chartviewer.{cpp,h} |
ChartWindow (container; owns N ChartColumn data objects) + a single rebindable ChartViewer that renders the active ChartColumn's PlotSeries via PlotWidget |
src/plotwidget.{cpp,h} |
QWidget+QPainter 2D line/scatter chart renderer — the only chart backend (no chart module/QML) |
src/plotseries.h |
Neutral chart model value types (PlotSeries, PlotAxis) consumed by PlotWidget |
src/plotaxismath.{cpp,h} |
Qt-free axis-layout helpers (nice ticks, tick values, printf label formatting) |
src/plotdata.{cpp,h} |
Column-oriented numeric data model + CSV/.dat/YAML/JSON parsers and writers |
src/plotdatadialog.{cpp,h} |
Column-picker dialog for plotting an external data file |
src/analysis.{cpp,h} |
Qt-free post-processing analyses (autocorrelation) |
src/leastsquares.{cpp,h} |
Qt-free dense LU solver + Savitzky-Golay smoothing |
src/fitting.{cpp,h} |
Qt-free polynomial + Birch-Murnaghan EOS fits (on leastsquares) |
src/levmar.{cpp,h} |
Qt-free Levenberg-Marquardt nonlinear least-squares solver |
src/customfunc.{cpp,h} |
Evaluate/fit user expressions via LeptonMini (custom-function plot + nonlinear fit) |
src/imageviewer.{cpp,h} |
Dump-image viewer with interactive re-render controls (dialog builders split into imageviewersettings.cpp) |
src/imageviewersettings.cpp |
ImageViewer settings/visualization dialog builders, split out of imageviewer.cpp to keep that translation unit manageable |
src/imageviewer_internal.h |
Header-only impl-detail symbols shared between imageviewer.cpp and imageviewersettings.cpp |
src/dumpimage.{cpp,h} |
DumpImageParams struct + assembly of the LAMMPS dump image command from ImageViewer widget state |
src/colormaps.{cpp,h} |
Named dump image color-map definitions (ColorMapStop color stops) |
src/slideshow.{cpp,h} |
Slideshow viewer for sequences of dump images with playback controls |
src/imagecache.{cpp,h} |
ImageCache: temp-dir-backed cache of ImageMagick-converted images and extracted movie frames, owned by SlideShow |
src/movieimport.{cpp,h} |
MovieInfo + ffprobe/ffmpeg probe and frame-extraction free functions, plus the MovieImportDialog confirmation dialog |
src/preferences.{cpp,h} |
Tabbed settings dialog (general, accelerators, snapshot image, editor, charts) |
src/setvariables.{cpp,h} |
Dialog for editing index-style LAMMPS variable name/value pairs |
src/tutorialwizard.{cpp,h} |
Step-by-step wizard for setting up and launching LAMMPS tutorials |
src/tutorials.{cpp,h} |
TutorialCollection metadata/registry for the available tutorial collections |
src/fileviewer.{cpp,h} |
Read-only text viewer for files referenced in input scripts |
src/aboutdialog.{cpp,h} |
Auto-scrolling About dialog showing LAMMPS version and style info |
src/urldownloader.{cpp,h} |
HTTPS file downloader (respects https_proxy setting; stall timeout + abort) |
src/downloadprogress.{cpp,h} |
Splash-style transient progress dialog with Cancel for batch downloads (tutorial wizard) |
src/helpers.{cpp,h} |
Platform utilities, dialog/font/toolbar helpers, stdout and Qt-message silencing |
src/qaddon.{cpp,h} |
Utility widgets: QHline, QColorCompleter, QColorValidator, VerticalLabel |
src/rangebandslider.{cpp,h} |
Horizontal QSlider that paints an active sub-range on its track (distinct from the third-party rangeslider) |
src/constants.h |
Cfg namespace (magic numbers, string constants) and Keys namespace (QSettings keys) |
thirdparty/rangeslider/rangeslider.{cpp,h} |
Dual-handle range slider widget (third-party, CeCILL-A license) |
thirdparty/lepton_mini/ |
Vendored JIT-less subset of the Lepton expression parser, namespace LeptonMini (MIT); built as the lepton_mini static library |
plugin/liblammpsplugin.{c,h} |
C shim for dynamic LAMMPS library loading |
cmake/ |
CMake include files: Platform, Sources (the PROJECT_SOURCES list), Testing, Sanitizer, Documentation, Packaging |
resources/ |
Qt resources: icons, help tables, commands list |
test/ |
Unit tests (GoogleTest) and Python GUI tests (PyAutoGUI/Xvfb) |
doc/ |
Sphinx documentation sources (requirements.txt for venv) |
packaging/ |
Platform packaging scripts (flatpak, DMG, NSIS, tgz) |