diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 35abb6f743..f4661183cb 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1,3 +1,4 @@ +# -*- CMake -*- master configuration file for building LAMMPS ######################################## # CMake build system # This file is part of LAMMPS @@ -888,8 +889,15 @@ else() endif() include(FeatureSummary) feature_summary(DESCRIPTION "The following tools and libraries have been found and configured:" WHAT PACKAGES_FOUND) +if(GIT_FOUND AND EXISTS ${LAMMPS_DIR}/.git) + execute_process(COMMAND ${GIT_EXECUTABLE} describe --dirty=-modified --always + OUTPUT_VARIABLE GIT_DESCRIBE + ERROR_QUIET + WORKING_DIRECTORY ${LAMMPS_DIR} + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() message(STATUS "<<< Build configuration >>> - LAMMPS Version: ${PROJECT_VERSION} + LAMMPS Version: ${PROJECT_VERSION} ${GIT_DESCRIBE} Operating System: ${CMAKE_SYSTEM_NAME} ${CMAKE_LINUX_DISTRO} ${CMAKE_DISTRO_VERSION} CMake Version: ${CMAKE_VERSION} Build type: ${LAMMPS_BUILD_TYPE} @@ -1026,6 +1034,14 @@ endif() if(BUILD_LAMMPS_SHELL) message(STATUS "<<< Building LAMMPS Shell >>>") endif() +if(BUILD_LAMMPS_GUI) + message(STATUS "<<< Building LAMMPS GUI >>>") + if(LAMMPS_GUI_USE_PLUGIN) + message(STATUS "Loading LAMMPS library as plugin at run time") + else() + message(STATUS "Linking LAMMPS library at compile time") + endif() +endif() if(ENABLE_TESTING) message(STATUS "<<< Building Unit Tests >>>") if(ENABLE_COVERAGE) diff --git a/cmake/packaging/build_windows_cross_zip.sh b/cmake/packaging/build_windows_cross_zip.sh index 5659b84f74..d02b9cf761 100755 --- a/cmake/packaging/build_windows_cross_zip.sh +++ b/cmake/packaging/build_windows_cross_zip.sh @@ -1,26 +1,64 @@ -#!/bin/bash -vx +#!/bin/bash APP_NAME=lammps-gui -DESTDIR=${PWD}/../LAMMPS_GUI +DESTDIR=${PWD}/LAMMPS_GUI +SYSROOT="$1" echo "Delete old files, if they exist" -rm -rvf ${DESTDIR} LAMMPS-Win10-amd64.zip +rm -rvf ${DESTDIR}/LAMMPS_GUI ${DESTDIR}/LAMMPS-Win10-amd64.zip echo "Create staging area for deployment and populate" DESTDIR=${DESTDIR} cmake --install . --prefix "/" -echo "Add required dependencies for Qt" -for dll in Qt5Core.dll Qt5Gui.dll Qt5Widgets.dll +# no static libs needed +rm -rvf ${DESTDIR}/lib +# but the LAMMPS lib + +echo "Copying required DLL files" +for dll in $(objdump -p *.exe *.dll | sed -n -e '/DLL Name:/s/^.*DLL Name: *//p' | sort | uniq) do \ - cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/${dll} ${DESTDIR}/bin/ -done -for dir in styles platforms imageformats -do \ - mkdir -p ${DESTDIR}/${dir} - cp -r /usr/x86_64-w64-mingw32/sys-root/mingw/lib/qt5/plugins/${dir}/*.dll ${DESTDIR}/${dir} + doskip=0 + for skip in ADVAPI32 CFGMGR32 GDI32 KERNEL32 MPR NETAPI32 PSAPI SHELL32 USER32 USERENV UxTheme VERSION WS2_32 WSOCK32 d3d11 dwmapi liblammps msvcrt_ole32 + do \ + test ${dll} = ${skip}.dll && doskip=1 + done + test ${doskip} -eq 1 && continue + test -f ${DESTDIR}/bin/${dll} || cp -v ${SYSROOT}/bin/${dll} ${DESTDIR}/bin done -pushd .. -zip -9rv LAMMPS-Win10-amd64.zip LAMMPS_GUI -popd -exit 0 +echo "Copy required Qt plugins" +mkdir -p ${DESTDIR}/qt5plugins +for plugin in imageformats platforms styles +do \ + cp -r ${SYSROOT}/lib/qt5/plugins/${plugin} ${DESTDIR}/qt5plugins/ +done + +echo "Check dependencies of DLL files" +for dll in $(objdump -p ${DESTDIR}/bin/*.dll ${DESTDIR}/qt5plugins/*/*.dll | sed -n -e '/DLL Name:/s/^.*DLL Name: *//p' | sort | uniq) +do \ + doskip=0 + for skip in ADVAPI32 CFGMGR32 GDI32 KERNEL32 MPR NETAPI32 PSAPI SHELL32 USER32 USERENV UxTheme VERSION WS2_32 WSOCK32 d3d11 dwmapi liblammps msvcrt_ole32 + do \ + test ${dll} = ${skip}.dll && doskip=1 + done + test ${doskip} -eq 1 && continue + test -f ${DESTDIR}/bin/${dll} || cp -v ${SYSROOT}/bin/${dll} ${DESTDIR}/bin +done + +for dll in $(objdump -p ${DESTDIR}/bin/*.dll ${DESTDIR}/qt5plugins/*/*.dll | sed -n -e '/DLL Name:/s/^.*DLL Name: *//p' | sort | uniq) +do \ + doskip=0 + for skip in ADVAPI32 CFGMGR32 GDI32 KERNEL32 MPR NETAPI32 PSAPI SHELL32 USER32 USERENV UxTheme VERSION WS2_32 WSOCK32 d3d11 dwmapi liblammps msvcrt_ole32 + do \ + test ${dll} = ${skip}.dll && doskip=1 + done + test ${doskip} -eq 1 && continue + test -f ${DESTDIR}/bin/${dll} || cp -v ${SYSROOT}/bin/${dll} ${DESTDIR}/bin +done + +cat > ${DESTDIR}/bin/qt.conf < TYPE BIN) + install(FILES $ TYPE BIN) + install(FILES $ TYPE BIN) + add_custom_target(zip + COMMAND sh -vx ${LAMMPS_DIR}/cmake/packaging/build_windows_cross_zip.sh ${CMAKE_INSTALL_PREFIX} + DEPENDS lmp lammps-gui + COMMENT "Create zip file with windows binaries" + BYPRODUCT LAMMPS-Win10-amd64.zip + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") install(TARGETS lammps-gui DESTINATION ${CMAKE_INSTALL_BINDIR}) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/lammps-gui.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications/) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/lammps-input.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages/) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/lammps-input.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/text/x-application-lammps.xml) + install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/icons/hicolor DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/) install(CODE [[ file(GET_RUNTIME_DEPENDENCIES LIBRARIES $ diff --git a/tools/lammps-gui/README.md b/tools/lammps-gui/README.md index 2af9ee6faa..d495121bce 100644 --- a/tools/lammps-gui/README.md +++ b/tools/lammps-gui/README.md @@ -1,104 +1,14 @@ LAMMPS GUI -# Overview - LAMMPS GUI is essentially a small graphical text editor that is linked to the LAMMPS library and thus can run LAMMPS using the contents of the -text buffer as input. This is similar to what people usually would do -using a text editor to edit the input and then a command line terminal -window to run the input commands. The main benefit is that this -integrates very well with graphical desktop environments and that it is -easier to use for beginners in running computations and thus very -suitable for tutorials on LAMMPS. +text buffer as input directly without requiring an additional LAMMPS +executable. It can also capture and show the screen output, a line graph +of thermodynamic data and snapshot images in separate windows. -# Features - -The main window of the LAMMPS GUI is a text editor window with syntax -highlighting set up for LAMMPS input files. It can be used to edit any -kind of text file, but then trying to run those files will cause errors. -The output of a run is captured and displayed in a separate window -dialog. The log window is updated during the run and a progress bar for -each run command shown in the main window. Starting a new run will open -another log windows. After the simulation is finished, an image of the -simulated system can be created and shown in another window. Ongoing -runs can be stopped at the next iteration via triggering a timeout. - -When opening a file, the editor will determine the directory where the -file resides and switch its current working directory to that folder. -Many LAMMPS inputs contain commands that read other files, typically -from the folder with the input file. The GUI will show the current -working directory. The editor window can also receive (entire) files -via drag-n-drop from a file manager GUI or a desktop environment. - -Almost all commands are accessible via hotkeys. Which those hotkeys are, -is shown next to the entries in the menu. Log and image viewer windows -can be closed with CTRL-W (or Command-W on macOS). The "About LAMMPS" -dialog will show the LAMMPS version and the features included into the -LAMMPS library linked to the LAMMPS GUI. - -Due to its nature as a graphical application, it is not possible to use -the LAMMPS GUI in parallel with MPI, but OpenMP multi-threading is -available. - -# Prerequisites and portability - -LAMMPS GUI is programmed using the Qt cross-platform GUI toolkit, -currently using Qt version 5.15LTS for better compatibility with older -compilers. It has been successfully compiled and tested on: - -- Fedora Linux 38 x86\_64 using GCC 13 and Clang 16 -- Apple macOS 12 (Monterey) and macOS 13 (Ventura) with Xcode on arm64 and x86\_64 -- Windows 10 and 11 x86_64 with Visual Studio 2022 and Visual C++ 14.36 - -# Compilation - -The source for the LAMMPS GUI is included with the LAMMPS source code -distribution in the folder `tools/lammps-gui` and thus it can be can be -built as part of a regular LAMMPS compilation. Using CMake is required. -To enable its compilation the CMake variable `-D BUILD_LAMMPS_GUI=on` -must be set when creating the CMake configuration. All other settings -(compiler, flags, compile type) for LAMMPS GUI are then inherited from -the regular LAMMPS build. If the Qt library is packaged for Linux -distributions, then its location is typically auto-detected since the -required CMake configuration files are stored in a location where CMake -can find them without additional help. Otherwise, the location of the -Qt library installation must be indicated by setting `-D -Qt5_DIR=/path/to/qt5/lib/cmake/Qt5`, which is a path to a folder inside -the Qt installation that contains the file `Qt5Config.cmake`. - -It is also possible to build the LAMMPS GUI as a standalone executable -(e.g. when LAMMPS has been compiled with traditional make), then the -CMake configuration needs to be told where to find the LAMMPS headers -and the LAMMPS library, via `-D LAMMPS_SOURCE_DIR=/path/to/lammps/src`. -CMake will try to guess a build folder with the LAMMPS library from that -path, but it can also be set with `-D LAMMPS_LIB_DIR=/path/to/lammps/lib`. - -Rather than linking to the LAMMPS library during compilation, it is also -possible to compile the GUI with a plugin loader library that will load -the LAMMPS library at runtime during startup of the GUI from a shared -library; e.g. `liblammps.so` or `liblammps.dylib` or `liblammps.dll` -depending on the operating system. This has the advantage that the -LAMMPS library can be updated LAMMPS without having to recompile the -GUI. The ABI of the LAMMPS C-library interface is very stable and -generally backward compatible. This feature is enabled by setting -`-D LAMMPS_GUI_USE_PLUGIN=on` and then -`-D LAMMPS_PLUGINLIB_DIR=/path/to/lammps/plugin/loader`. Typically, this -would be the `examples/COUPLE/plugin` folder of the LAMMPS distribution. - -# Platform notes - -## macOS - -When building on macOS, the build procedure will try to manufacture a -drag-n-drop installer, LAMMPS-macOS-multiarch.dmg. To build multi-arch -executables that will run on both, arm64 and x86_64 architectures -natively, it is necessary to set the CMake variable -`-D CMAKE_OSX_ARCHITECTURES=arm64;x86_64`. To achieve wide compatibility -with different macOS versions, you can also set -`-D CMAKE_OSX_DEPLOYMENT_TARGET=11.0` which will set compatibility to macOS -11 (Big Sur) and later, even if you are compiling on a more recent macOS -version. +Detailed documentation about installing and using LAMMPS GUI is in +the LAMMPS manual. -------- -updated by Axel Kohlmeyer, 08/1023 +updated by Axel Kohlmeyer, 2023-08-12 diff --git a/tools/lammps-gui/TODO.md b/tools/lammps-gui/TODO.md index af53fb3cf9..d9581e3ae6 100644 --- a/tools/lammps-gui/TODO.md +++ b/tools/lammps-gui/TODO.md @@ -2,18 +2,26 @@ LAMMPS-GUI TODO list: # Short term goals +- rewrite syntax highlighting to be line oriented instead of word oriented. + handle first part of line based on regular expressions, then advance and only highlight strings and numbers. + handle "&" continuation and multiline strings with """ like C style comments in Qt docs example - add CTRL-q hotkey to log windows so you can exit the entire application (add do you really want to? dialog to this) - add "syntax check" with enabled "-skiprun" flag -- add multi-tab settings dialog where certain properties can be set through customizing the LAMMPS command line - + select Font -- add list of 5(?) most recently opened/saved files to file dialog (and also write to settings state on exit) (note: must store full path!) +- need to handle "label" and "jump" commands from within ? +- switch processing of input to line based commands or? +- switch input file editor to read-only while loop is running # Long term ideas +- add feature to LAMMPS (to the LAMMPS class) to store current file name and line number, update while reading/parsing + use in error messages + add API to library interface to query this info and use it for highlighting in text editor +- rewrite entire application to either use QtCreator for everything or just build the App and its layout manually +- port to Qt6 +- also a rewrite should establish consistent naming conventions. now we have a mix of LAMMPS style, Qt style, and others. +- add option to attach a debugger to the running program (highly non-portable, need customization support in preferences) - write a "wizard" dialog that can be used for beginners to create an input file template for a few typical use scenarios -- use the "lammps_get_last_thermo" function to get access to thermodynamic data during a run and add plot/graph dialog that can plot one or more of those graphs while the simulation is still running -- possibly also implement a callback interface, so that external programs can be called after thermo data is updated. - support single stepping, i.e. process input line by line (need to detect continuation chars!) with highlighting active line(s) - have command text input file in/above status bar where individual commands can be tested. have insert button to copy line into file at the current point - support text completion as done with lammps-shell -- have context menu for known commands to offer retrieving help by dispatching URL to webbrowser (process index from sphinx for that purpose) -- add a "python" mode, where instead of launching LAMMPS, python is loaded that the LAMMPS python module is made available. +- add a "python" mode, where instead of launching LAMMPS, python is loaded where the LAMMPS python module is made available. +- support multiple tabs and multiple LAMMPS instances? diff --git a/tools/lammps-gui/antialias.png b/tools/lammps-gui/antialias.png new file mode 100644 index 0000000000..1a7403e11c Binary files /dev/null and b/tools/lammps-gui/antialias.png differ diff --git a/tools/lammps-gui/application-calc.png b/tools/lammps-gui/application-calc.png new file mode 100644 index 0000000000..0c3bea28bb Binary files /dev/null and b/tools/lammps-gui/application-calc.png differ diff --git a/tools/lammps-gui/application-exit.png b/tools/lammps-gui/application-exit.png new file mode 100644 index 0000000000..2d0cd61bd3 Binary files /dev/null and b/tools/lammps-gui/application-exit.png differ diff --git a/tools/lammps-gui/application-plot.png b/tools/lammps-gui/application-plot.png new file mode 100644 index 0000000000..7299b5a4e9 Binary files /dev/null and b/tools/lammps-gui/application-plot.png differ diff --git a/tools/lammps-gui/axes-img.png b/tools/lammps-gui/axes-img.png new file mode 100644 index 0000000000..29ede4787e Binary files /dev/null and b/tools/lammps-gui/axes-img.png differ diff --git a/tools/lammps-gui/chartviewer.cpp b/tools/lammps-gui/chartviewer.cpp new file mode 100644 index 0000000000..d9fedd9129 --- /dev/null +++ b/tools/lammps-gui/chartviewer.cpp @@ -0,0 +1,248 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#include "chartviewer.h" + +#include +#include +#include +#include + +using namespace QtCharts; + +ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : + QWidget(parent), menu(new QMenuBar), file(new QMenu("&File")), active_chart(-1), + filename(_filename) +{ + auto *top = new QHBoxLayout; + menu->addMenu(file); + menu->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + + columns = new QComboBox; + top->addWidget(menu); + top->addWidget(columns); + saveAsAct = file->addAction("&Save Graph As...", this, &ChartWindow::saveAs); + saveAsAct->setIcon(QIcon(":/document-save-as.png")); + exportCsvAct = file->addAction("&Export data to CSV...", this, &ChartWindow::exportCsv); + exportCsvAct->setIcon(QIcon(":/application-calc.png")); + exportDatAct = file->addAction("Export data to &Gnuplot...", this, &ChartWindow::exportDat); + exportDatAct->setIcon(QIcon(":/application-plot.png")); + file->addSeparator(); + closeAct = file->addAction("&Close", this, &QWidget::close); + closeAct->setIcon(QIcon(":/window-close.png")); + auto *layout = new QVBoxLayout; + layout->addLayout(top); + setLayout(layout); + + connect(columns, SIGNAL(currentIndexChanged(int)), this, SLOT(change_chart(int))); + QSettings settings; + resize(settings.value("chartx", 500).toInt(), settings.value("charty", 320).toInt()); +} + +int ChartWindow::get_step() const +{ + if (charts.size() > 0) { + auto *v = charts[0]; + return (int)v->get_step(v->get_count() - 1); + } else { + return -1; + } +} + +void ChartWindow::reset_charts() +{ + while (layout()->count() > 1) { + auto *item = layout()->takeAt(1); + if (item) { + layout()->removeItem(item); + delete item->widget(); + delete item; + } + } + charts.clear(); + columns->clear(); + active_chart = 0; +} + +void ChartWindow::add_chart(const QString &title, int index) +{ + auto *chart = new ChartViewer(title, index); + layout()->addWidget(chart); + columns->addItem(title, index); + columns->show(); + // hide all but the first chart added + if (charts.size() > 0) chart->hide(); + charts.append(chart); + active_chart = 0; +} + +void ChartWindow::add_data(int step, double data, int index) +{ + for (auto &c : charts) + if (c->get_index() == index) c->add_data(step, data); +} + +void ChartWindow::saveAs() +{ + if (charts.empty() || (active_chart < 0)) return; + QString defaultname = filename + "." + columns->currentText() + ".png"; + if (filename.isEmpty()) defaultname = columns->currentText() + ".png"; + QString fileName = QFileDialog::getSaveFileName(this, "Save Chart as Image", defaultname, + "Image Files (*.jpg *.png *.bmp *.ppm)"); + if (!fileName.isEmpty()) { + charts[active_chart]->grab().save(fileName); + } +} + +void ChartWindow::exportDat() +{ + if (charts.empty() || (active_chart < 0)) return; + QString defaultname = filename + ".dat"; + if (filename.isEmpty()) defaultname = "lammpsdata.dat"; + QString fileName = QFileDialog::getSaveFileName(this, "Save Chart as Gnuplot data", defaultname, + "Image Files (*.dat)"); + if (!fileName.isEmpty()) { + QFile file(fileName); + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { + + file.write("# Thermodynamic data from "); + file.write(filename.toLocal8Bit()); + file.write("\n# Columns:"); + for (auto &c : charts) { + file.write(" "); + file.write(c->get_title()); + } + file.write("\n"); + + int lines = charts[0]->get_count(); + for (int i = 0; i < lines; ++i) { + // timestep + file.write(QString::number(charts[0]->get_step(i)).toLocal8Bit()); + for (auto &c : charts) { + file.write(" "); + file.write(QString::number(c->get_data(i)).toLocal8Bit()); + } + file.write("\n"); + } + file.close(); + } + } +} + +void ChartWindow::exportCsv() +{ + if (charts.empty() || (active_chart < 0)) return; + QString defaultname = filename + ".csv"; + if (filename.isEmpty()) defaultname = "lammpsdata.csv"; + QString fileName = QFileDialog::getSaveFileName(this, "Save Chart as CSV data", defaultname, + "Image Files (*.csv)"); + if (!fileName.isEmpty()) { + QFile file(fileName); + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { + + file.write("Step"); + for (auto &c : charts) { + file.write(","); + file.write(c->get_title()); + } + file.write("\n"); + + int lines = charts[0]->get_count(); + for (int i = 0; i < lines; ++i) { + // timestep + file.write(QString::number(charts[0]->get_step(i)).toLocal8Bit()); + for (auto &c : charts) { + file.write(","); + file.write(QString::number(c->get_data(i)).toLocal8Bit()); + } + file.write("\n"); + } + file.close(); + } + } +} + +void ChartWindow::change_chart(int index) +{ + int choice = columns->currentData().toInt(); + for (auto &c : charts) { + if (choice == c->get_index()) + c->show(); + else + c->hide(); + } +} + +void ChartWindow::closeEvent(QCloseEvent *event) +{ + QSettings settings; + if (!isMaximized()) { + settings.setValue("chartx", width()); + settings.setValue("charty", height()); + } + QWidget::closeEvent(event); +} + +/* -------------------------------------------------------------------- */ + +ChartViewer::ChartViewer(const QString &title, int _index, QWidget *parent) : + QChartView(parent), last_step(-1), index(_index), chart(new QChart), series(new QLineSeries), + xaxis(new QValueAxis), yaxis(new QValueAxis) +{ + chart->legend()->hide(); + chart->addAxis(xaxis, Qt::AlignBottom); + chart->addAxis(yaxis, Qt::AlignLeft); + chart->addSeries(series); + series->attachAxis(xaxis); + series->attachAxis(yaxis); + xaxis->setTitleText("Time step"); + xaxis->setTickCount(5); + xaxis->setLabelFormat("%d"); + yaxis->setTickCount(5); + xaxis->setMinorTickCount(5); + yaxis->setMinorTickCount(5); + yaxis->setTitleText(title); + series->setName(title); + + setRenderHint(QPainter::Antialiasing); + setChart(chart); + setRubberBand(QChartView::RectangleRubberBand); +} + +/* -------------------------------------------------------------------- */ + +void ChartViewer::add_data(int step, double data) +{ + if (last_step < step) { + last_step = step; + series->append(step, data); + auto points = series->pointsVector(); + + qreal xmin = 1.0e100; + qreal xmax = -1.0e100; + qreal ymin = 1.0e100; + qreal ymax = -1.0e100; + for (auto &p : points) { + xmin = qMin(xmin, p.x()); + xmax = qMax(xmax, p.x()); + ymin = qMin(ymin, p.y()); + ymax = qMax(ymax, p.y()); + } + xaxis->setRange(xmin, xmax); + yaxis->setRange(ymin, ymax); + } +} + +// Local Variables: +// c-basic-offset: 4 +// End: diff --git a/tools/lammps-gui/chartviewer.h b/tools/lammps-gui/chartviewer.h new file mode 100644 index 0000000000..22f52a82d6 --- /dev/null +++ b/tools/lammps-gui/chartviewer.h @@ -0,0 +1,94 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifndef CHARTVIEWER_H +#define CHARTVIEWER_H + +#include +#include +#include +#include + +class QAction; +class QMenuBar; +class QMenu; +class QComboBox; +class ChartViewer; + +class ChartWindow : public QWidget { + Q_OBJECT + +public: + ChartWindow(const QString &filename, QWidget *parent = nullptr); + + int num_charts() const { return charts.size(); } + bool has_title(const QString &title, int index) const + { + return (columns->itemText(index) == title); + } + int get_step() const; + void reset_charts(); + void add_chart(const QString &title, int index); + void add_data(int step, double data, int index); + +private slots: + void saveAs(); + void exportDat(); + void exportCsv(); + + void change_chart(int index); + +protected: + void closeEvent(QCloseEvent *event) override; + +private: + QMenuBar *menu; + QMenu *file; + QComboBox *columns; + QAction *saveAsAct; + QAction *exportCsvAct; + QAction *exportDatAct; + QAction *closeAct; + + QString filename; + int active_chart; + QList charts; +}; + +/* -------------------------------------------------------------------- */ + +class ChartViewer : public QtCharts::QChartView { + Q_OBJECT + +public: + explicit ChartViewer(const QString &title, int index, QWidget *parent = nullptr); + + void add_data(int step, double data); + int get_index() const { return index; }; + int get_count() const { return series->count(); } + const char *get_title() const { return series->name().toLocal8Bit(); } + double get_step(int index) const { return series->at(index).x(); } + double get_data(int index) const { return series->at(index).y(); } + +private: + int last_step, index; + QtCharts::QChart *chart; + QtCharts::QLineSeries *series; + QtCharts::QValueAxis *xaxis; + QtCharts::QValueAxis *yaxis; +}; +#endif + +// Local Variables: +// c-basic-offset: 4 +// End: diff --git a/tools/lammps-gui/codeeditor.cpp b/tools/lammps-gui/codeeditor.cpp index f0a375efc0..a259e25c51 100644 --- a/tools/lammps-gui/codeeditor.cpp +++ b/tools/lammps-gui/codeeditor.cpp @@ -15,19 +15,61 @@ #include "lammpsgui.h" #include "linenumberarea.h" +#include +#include #include #include +#include +#include +#include #include #include +#include #include +#include CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent) { - lineNumberArea = new LineNumberArea(this); + help_action = new QShortcut(QKeySequence::fromString("Ctrl+?"), parent); + connect(help_action, &QShortcut::activated, this, &CodeEditor::get_help); + // initialize help system + QFile help_index(":/help_index.table"); + if (help_index.open(QIODevice::ReadOnly | QIODevice::Text)) { + while (!help_index.atEnd()) { + auto line = QString(help_index.readLine()); + auto words = line.trimmed().split(' '); + if (words.size() > 2) { + if (words.at(1) == "pair_style") { + pair_map[words.at(2)] = words.at(0); + } else if (words.at(1) == "bond_style") { + bond_map[words.at(2)] = words.at(0); + } else if (words.at(1) == "angle_style") { + angle_map[words.at(2)] = words.at(0); + } else if (words.at(1) == "dihedral_style") { + dihedral_map[words.at(2)] = words.at(0); + } else if (words.at(1) == "improper_style") { + improper_map[words.at(2)] = words.at(0); + } else if (words.at(1) == "fix") { + fix_map[words.at(2)] = words.at(0); + } else if (words.at(1) == "compute") { + compute_map[words.at(2)] = words.at(0); + } else if (words.at(1) == "kspace_style") { + cmd_map["kspace_style"] = "kspace_style.html"; + } + // ignoring: dump, fix_modify ATC + } else if (words.size() == 2) { + cmd_map[words.at(1)] = words.at(0); + } else { + fprintf(stderr, "unhandled: %s", line.toStdString().c_str()); + } + } + help_index.close(); + } + + lineNumberArea = new LineNumberArea(this); connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth); connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea); - updateLineNumberAreaWidth(0); } @@ -138,6 +180,102 @@ void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event) } } +void CodeEditor::contextMenuEvent(QContextMenuEvent *event) +{ + // reposition the cursor here? + QString page, help; + find_help(page, help); + + // print augmented context menu if an entry was found + auto *menu = createStandardContextMenu(); + if (!page.isEmpty()) { + menu->addSeparator(); + auto action = menu->addAction(QString("View Documentation for '%1'").arg(help)); + action->setIcon(QIcon(":/system-help.png")); + action->setData(page); + connect(action, &QAction::triggered, this, &CodeEditor::open_help); + // if we link to help with specific styles (fix, compute, pair, bond, ...) + // also link to the docs for the primary command + auto words = help.split(' '); + if (words.size() > 1) { + help = words.at(0); + page = words.at(0); + page += ".html"; + auto action2 = menu->addAction(QString("View Documentation for '%1'").arg(help)); + action2->setIcon(QIcon(":/system-help.png")); + action2->setData(page); + connect(action2, &QAction::triggered, this, &CodeEditor::open_help); + } + } + auto action3 = menu->addAction(QString("LAMMPS Manual")); + action3->setIcon(QIcon(":/help-browser.png")); + action3->setData(QString()); + connect(action3, &QAction::triggered, this, &CodeEditor::open_help); + + menu->exec(event->globalPos()); + delete menu; +} + +void CodeEditor::get_help() +{ + QString page, help; + find_help(page, help); + if (!page.isEmpty()) + QDesktopServices::openUrl(QUrl(QString("https://docs.lammps.org/%1").arg(page))); +} + +void CodeEditor::find_help(QString &page, QString &help) +{ + // process line of text where the cursor is + auto text = textCursor().block().text().replace('\t', ' ').trimmed(); + auto style = + QRegularExpression("^(pair|bond|angle|dihedral|improper)_style\\s+(\\S+)").match(text); + help.clear(); + page.clear(); + if (style.hasMatch()) { + if (style.captured(1) == "pair") { + page = pair_map.value(style.captured(2), QString()); + help = QString("pair_style %1").arg(style.captured(2)); + } else if (style.captured(1) == "bond") { + page = bond_map.value(style.captured(2), QString()); + help = QString("bond_style %1").arg(style.captured(2)); + } else if (style.captured(1) == "angle") { + page = angle_map.value(style.captured(2), QString()); + help = QString("angle_style %1").arg(style.captured(2)); + } else if (style.captured(1) == "dihedral") { + page = dihedral_map.value(style.captured(2), QString()); + help = QString("dihedral_style %1").arg(style.captured(2)); + } else if (style.captured(1) == "improper") { + page = improper_map.value(style.captured(2), QString()); + help = QString("improper_style %1").arg(style.captured(2)); + } + } + + style = QRegularExpression("^(fix|compute)\\s+\\w+\\s+\\w+\\s+(\\S+)").match(text); + if (style.hasMatch()) { + help = QString("%1 %2").arg(style.captured(1), style.captured(2)); + if (style.captured(1) == "fix") { + page = fix_map.value(style.captured(2), QString()); + } else if (style.captured(1) == "compute") { + page = compute_map.value(style.captured(2), QString()); + } + } + + // could not find a matching "style", now try the plain command + if (page.isEmpty() && !text.isEmpty()) { + auto cmd = text.split(' ').at(0); + help = cmd; + page = cmd_map.value(cmd, QString()); + } +} + +void CodeEditor::open_help() +{ + QAction *act = qobject_cast(sender()); + QDesktopServices::openUrl( + QUrl(QString("https://docs.lammps.org/%1").arg(act->data().toString()))); +} + // Local Variables: // c-basic-offset: 4 // End: diff --git a/tools/lammps-gui/codeeditor.h b/tools/lammps-gui/codeeditor.h index 49abf81553..57cdd8576b 100644 --- a/tools/lammps-gui/codeeditor.h +++ b/tools/lammps-gui/codeeditor.h @@ -14,7 +14,10 @@ #ifndef CODEEDITOR_H #define CODEEDITOR_H +#include #include +#include +#include class CodeEditor : public QPlainTextEdit { Q_OBJECT @@ -30,14 +33,29 @@ protected: void dragEnterEvent(QDragEnterEvent *event) override; bool canInsertFromMimeData(const QMimeData *source) const override; void dropEvent(QDropEvent *event) override; + void contextMenuEvent(QContextMenuEvent *event) override; private slots: void updateLineNumberAreaWidth(int newBlockCount); void highlightCurrentLine(); void updateLineNumberArea(const QRect &rect, int dy); + void get_help(); + void find_help(QString &page, QString &help); + void open_help(); private: QWidget *lineNumberArea; + QShortcut *help_action; + + QMap cmd_map; + QMap fix_map; + QMap compute_map; + QMap pair_map; + QMap bond_map; + QMap angle_map; + QMap dihedral_map; + QMap improper_map; + QMap dump_map; }; #endif diff --git a/tools/lammps-gui/document-new.png b/tools/lammps-gui/document-new.png new file mode 100644 index 0000000000..1bf38e87e0 Binary files /dev/null and b/tools/lammps-gui/document-new.png differ diff --git a/tools/lammps-gui/document-open-recent.png b/tools/lammps-gui/document-open-recent.png new file mode 100644 index 0000000000..c50d71de89 Binary files /dev/null and b/tools/lammps-gui/document-open-recent.png differ diff --git a/tools/lammps-gui/document-open.png b/tools/lammps-gui/document-open.png new file mode 100644 index 0000000000..e4243c428f Binary files /dev/null and b/tools/lammps-gui/document-open.png differ diff --git a/tools/lammps-gui/document-revert.png b/tools/lammps-gui/document-revert.png new file mode 100644 index 0000000000..0dcc72a2d1 Binary files /dev/null and b/tools/lammps-gui/document-revert.png differ diff --git a/tools/lammps-gui/document-save-as.png b/tools/lammps-gui/document-save-as.png new file mode 100644 index 0000000000..76a653a93b Binary files /dev/null and b/tools/lammps-gui/document-save-as.png differ diff --git a/tools/lammps-gui/document-save.png b/tools/lammps-gui/document-save.png new file mode 100644 index 0000000000..c7745e0abc Binary files /dev/null and b/tools/lammps-gui/document-save.png differ diff --git a/tools/lammps-gui/edit-copy.png b/tools/lammps-gui/edit-copy.png new file mode 100644 index 0000000000..3e95555a4e Binary files /dev/null and b/tools/lammps-gui/edit-copy.png differ diff --git a/tools/lammps-gui/edit-cut.png b/tools/lammps-gui/edit-cut.png new file mode 100644 index 0000000000..804d0cdb43 Binary files /dev/null and b/tools/lammps-gui/edit-cut.png differ diff --git a/tools/lammps-gui/edit-delete.png b/tools/lammps-gui/edit-delete.png new file mode 100644 index 0000000000..a2fcfdcf10 Binary files /dev/null and b/tools/lammps-gui/edit-delete.png differ diff --git a/tools/lammps-gui/edit-paste.png b/tools/lammps-gui/edit-paste.png new file mode 100644 index 0000000000..65ac12ed87 Binary files /dev/null and b/tools/lammps-gui/edit-paste.png differ diff --git a/tools/lammps-gui/edit-redo.png b/tools/lammps-gui/edit-redo.png new file mode 100644 index 0000000000..bcf329ad23 Binary files /dev/null and b/tools/lammps-gui/edit-redo.png differ diff --git a/tools/lammps-gui/edit-undo.png b/tools/lammps-gui/edit-undo.png new file mode 100644 index 0000000000..92e643aa5e Binary files /dev/null and b/tools/lammps-gui/edit-undo.png differ diff --git a/tools/lammps-gui/emblem-default.png b/tools/lammps-gui/emblem-default.png new file mode 100644 index 0000000000..84fe175a0e Binary files /dev/null and b/tools/lammps-gui/emblem-default.png differ diff --git a/tools/lammps-gui/emblem-photos.png b/tools/lammps-gui/emblem-photos.png new file mode 100644 index 0000000000..d5b222fe4e Binary files /dev/null and b/tools/lammps-gui/emblem-photos.png differ diff --git a/tools/lammps-gui/gtk-go-down.png b/tools/lammps-gui/gtk-go-down.png new file mode 100644 index 0000000000..c073ec5ebd Binary files /dev/null and b/tools/lammps-gui/gtk-go-down.png differ diff --git a/tools/lammps-gui/gtk-go-up.png b/tools/lammps-gui/gtk-go-up.png new file mode 100644 index 0000000000..e8ff52aeec Binary files /dev/null and b/tools/lammps-gui/gtk-go-up.png differ diff --git a/tools/lammps-gui/gtk-zoom-fit.png b/tools/lammps-gui/gtk-zoom-fit.png new file mode 100644 index 0000000000..9132294eac Binary files /dev/null and b/tools/lammps-gui/gtk-zoom-fit.png differ diff --git a/tools/lammps-gui/gtk-zoom-in.png b/tools/lammps-gui/gtk-zoom-in.png new file mode 100644 index 0000000000..34e8f04195 Binary files /dev/null and b/tools/lammps-gui/gtk-zoom-in.png differ diff --git a/tools/lammps-gui/gtk-zoom-out.png b/tools/lammps-gui/gtk-zoom-out.png new file mode 100644 index 0000000000..42acdd993d Binary files /dev/null and b/tools/lammps-gui/gtk-zoom-out.png differ diff --git a/tools/lammps-gui/hd-img.png b/tools/lammps-gui/hd-img.png new file mode 100644 index 0000000000..906e4d605d Binary files /dev/null and b/tools/lammps-gui/hd-img.png differ diff --git a/tools/lammps-gui/help-about.png b/tools/lammps-gui/help-about.png new file mode 100644 index 0000000000..45b5d62062 Binary files /dev/null and b/tools/lammps-gui/help-about.png differ diff --git a/tools/lammps-gui/help-browser.png b/tools/lammps-gui/help-browser.png new file mode 100644 index 0000000000..f3edf2c430 Binary files /dev/null and b/tools/lammps-gui/help-browser.png differ diff --git a/tools/lammps-gui/help-faq.png b/tools/lammps-gui/help-faq.png new file mode 100644 index 0000000000..1d57544fcf Binary files /dev/null and b/tools/lammps-gui/help-faq.png differ diff --git a/tools/lammps-gui/help_index.table b/tools/lammps-gui/help_index.table new file mode 100644 index 0000000000..d32483760a --- /dev/null +++ b/tools/lammps-gui/help_index.table @@ -0,0 +1,1443 @@ +angle_amoeba.html angle_style amoeba +angle_charmm.html angle_style charmm +angle_charmm.html angle_style charmm/intel +angle_charmm.html angle_style charmm/kk +angle_charmm.html angle_style charmm/omp +angle_class2.html angle_style class2 +angle_class2.html angle_style class2/kk +angle_class2.html angle_style class2/omp +angle_class2.html angle_style class2/p6 +angle_coeff.html angle_coeff +angle_cosine_buck6d.html angle_style cosine/buck6d +angle_cosine_delta.html angle_style cosine/delta +angle_cosine_delta.html angle_style cosine/delta/omp +angle_cosine_periodic.html angle_style cosine/periodic +angle_cosine_periodic.html angle_style cosine/periodic/omp +angle_cosine.html angle_style cosine +angle_cosine.html angle_style cosine/kk +angle_cosine.html angle_style cosine/omp +angle_cosine_shift_exp.html angle_style cosine/shift/exp +angle_cosine_shift_exp.html angle_style cosine/shift/exp/omp +angle_cosine_shift.html angle_style cosine/shift +angle_cosine_shift.html angle_style cosine/shift/omp +angle_cosine_squared.html angle_style cosine/squared +angle_cosine_squared.html angle_style cosine/squared/omp +angle_cross.html angle_style cross +angle_dipole.html angle_style dipole +angle_dipole.html angle_style dipole/omp +angle_fourier.html angle_style fourier +angle_fourier.html angle_style fourier/omp +angle_fourier_simple.html angle_style fourier/simple +angle_fourier_simple.html angle_style fourier/simple/omp +angle_gaussian.html angle_style gaussian +angle_harmonic.html angle_style harmonic +angle_harmonic.html angle_style harmonic/intel +angle_harmonic.html angle_style harmonic/kk +angle_harmonic.html angle_style harmonic/omp +angle_hybrid.html angle_style hybrid +angle_lepton.html angle_style lepton +angle_lepton.html angle_style lepton/omp +angle_mesocnt.html angle_style mesocnt +angle_mm3.html angle_style mm3 +angle_none.html angle_style none +angle_quartic.html angle_style quartic +angle_quartic.html angle_style quartic/omp +angle_spica.html angle_style spica +angle_spica.html angle_style spica/omp +angle_style.html angle_style +angle_table.html angle_style table +angle_table.html angle_style table/omp +angle_write.html angle_write +angle_zero.html angle_style zero +atc_add_molecule.html fix_modify AtC add_molecule +atc_add_species.html fix_modify AtC add_species +atc_atom_element_map.html fix_modify AtC atom_element_map +atc_atomic_charge.html fix_modify AtC atomic_charge +atc_atom_weight.html fix_modify AtC atom_weight +atc_boundary_dynamics.html fix_modify AtC boundary_dynamics +atc_boundary_faceset.html fix_modify AtC boundary_faceset +atc_boundary_type.html fix_modify AtC boundary type +atc_consistent_fe_initialization.html fix_modify AtC consistent_fe_initialization +atc_control_localized_lambda.html fix_modify AtC control localized_lambda +atc_control_momentum.html fix_modify AtC control momentum +atc_control_thermal.html fix_modify AtC control thermal +atc_decomposition.html fix_modify AtC decomposition +atc_electron_integration.html fix_modify AtC extrinsic electron_integration +atc_equilibrium_start.html fix_modify AtC equilibrium_start +atc_extrinsic_exchange.html fix_modify AtC extrinsic exchange +atc_fe_md_boundary.html fix_modify AtC fe_md_boundary +atc_filter_scale.html fix_modify AtC filter scale +atc_filter_type.html fix_modify AtC filter type +atc_fix_flux.html fix_modify AtC fix_flux +atc_fix.html fix_modify AtC fix +atc_hardy_computes.html fix_modify AtC computes +atc_hardy_fields.html fix_modify AtC fields +atc_hardy_gradients.html fix_modify AtC gradients +atc_hardy_kernel.html fix_modify AtC kernel +atc_hardy_on_the_fly.html fix_modify AtC on_the_fly +atc_hardy_rates.html fix_modify AtC rates +atc_initial.html fix_modify AtC initial +atc_internal_element_set.html fix_modify AtC internal_element_set +atc_internal_quadrature.html fix_modify AtC internal_quadrature +atc_kernel_bandwidth.html fix_modify AtC kernel_bandwidth +atc_lumped_lambda_solve.html fix_modify AtC control lumped_lambda_solve +atc_mask_direction.html fix_modify AtC control mask_direction +atc_mass_matrix.html fix_modify AtC mass_matrix +atc_material.html fix_modify AtC material +atc_mesh_add_to_nodeset.html fix_modify AtC mesh add_to_nodeset +atc_mesh_create_elementset.html fix_modify AtC mesh create_elementset +atc_mesh_create_faceset_box.html fix_modify AtC mesh create_faceset box +atc_mesh_create_faceset_plane.html fix_modify AtC mesh create_faceset plane +atc_mesh_create_nodeset.html fix_modify AtC mesh create_nodeset +atc_mesh_create.html fix_modify AtC mesh create +atc_mesh_delete_elements.html fix_modify AtC mesh delete_elements +atc_mesh_nodeset_to_elementset.html fix_modify AtC mesh nodeset_to_elementset +atc_mesh_output.html fix_modify AtC mesh output +atc_mesh_quadrature.html fix_modify AtC mesh quadrature +atc_mesh_read.html fix_modify AtC mesh read +atc_mesh_write.html fix_modify AtC mesh write +atc_output_boundary_integral.html fix_modify AtC output boundary_integral +atc_output_contour_integral.html fix_modify AtC output contour_integral +atc_output_nodeset.html fix_modify AtC output nodeset +atc_output.html fix_modify AtC output +atc_output_volume_integral.html fix_modify AtC output volume_integral +atc_pair_interactions.html fix_modify AtC pair_interactions +atc_poisson_solver.html fix_modify AtC poisson_solver +atc_read_restart.html fix_modify AtC read_restart +atc_remove_molecule.html fix_modify AtC remove_molecule +atc_remove_source.html fix_modify AtC remove_source +atc_remove_species.html fix_modify AtC remove_species +atc_reset_atomic_reference.html fix_modify AtC reset_atomic_reference_positions +atc_reset_time.html fix_modify AtC reset_time +atc_sample_frequency.html fix_modify AtC sample_frequency +atc_set_reference_pe.html fix_modify AtC set reference_potential_energy +atc_source_integration.html fix_modify AtC source_integration +atc_source.html fix_modify AtC source +atc_temperature_definition.html fix_modify AtC temperature_definition +atc_time_filter.html fix_modify AtC filter +atc_time_integration.html fix_modify AtC time_integration +atc_track_displacement.html fix_modify AtC track_displacement +atc_unfix_flux.html fix_modify AtC unfix_flux +atc_unfix.html fix_modify AtC unfix +atc_write_atom_weights.html fix_modify AtC write_atom_weights +atc_write_restart.html fix_modify AtC write_restart +atom_modify.html atom_modify +atom_style.html atom_style +balance.html balance +bond_bpm_rotational.html bond_style bpm/rotational +bond_bpm_spring.html bond_style bpm/spring +bond_class2.html bond_style class2 +bond_class2.html bond_style class2/kk +bond_class2.html bond_style class2/omp +bond_coeff.html bond_coeff +bond_fene_expand.html bond_style fene/expand +bond_fene_expand.html bond_style fene/expand/omp +bond_fene.html bond_style fene +bond_fene.html bond_style fene/intel +bond_fene.html bond_style fene/kk +bond_fene.html bond_style fene/nm +bond_fene.html bond_style fene/omp +bond_gaussian.html bond_style gaussian +bond_gromos.html bond_style gromos +bond_gromos.html bond_style gromos/omp +bond_harmonic_restrain.html bond_style harmonic/restrain +bond_harmonic.html bond_style harmonic +bond_harmonic.html bond_style harmonic/intel +bond_harmonic.html bond_style harmonic/kk +bond_harmonic.html bond_style harmonic/omp +bond_harmonic_shift_cut.html bond_style harmonic/shift/cut +bond_harmonic_shift_cut.html bond_style harmonic/shift/cut/omp +bond_harmonic_shift.html bond_style harmonic/shift +bond_harmonic_shift.html bond_style harmonic/shift/omp +bond_hybrid.html bond_style hybrid +bond_lepton.html bond_style lepton +bond_lepton.html bond_style lepton/omp +bond_mesocnt.html bond_style mesocnt +bond_mm3.html bond_style mm3 +bond_morse.html bond_style morse +bond_morse.html bond_style morse/omp +bond_none.html bond_style none +bond_nonlinear.html bond_style nonlinear +bond_nonlinear.html bond_style nonlinear/omp +bond_oxdna.html bond_style oxdna2/fene +bond_oxdna.html bond_style oxdna/fene +bond_oxdna.html bond_style oxrna2/fene +bond_quartic.html bond_style quartic +bond_quartic.html bond_style quartic/omp +bond_special.html bond_style special +bond_style.html bond_style +bond_table.html bond_style table +bond_table.html bond_style table/omp +bond_write.html bond_write +bond_zero.html bond_style zero +boundary.html boundary +change_box.html change_box +clear.html clear +comm_modify.html comm_modify +comm_style.html comm_style +compute_ackland_atom.html compute ackland/atom +compute_adf.html compute adf +compute_angle_local.html compute angle/local +compute_angle.html compute angle +compute_angmom_chunk.html compute angmom/chunk +compute_ave_sphere_atom.html compute ave/sphere/atom +compute_ave_sphere_atom.html compute ave/sphere/atom/kk +compute_basal_atom.html compute basal/atom +compute_body_local.html compute body/local +compute_bond_local.html compute bond/local +compute_bond.html compute bond +compute_born_matrix.html compute born/matrix +compute_centro_atom.html compute centro/atom +compute_chunk_atom.html compute chunk/atom +compute_chunk_spread_atom.html compute chunk/spread/atom +compute_cluster_atom.html compute aggregate/atom +compute_cluster_atom.html compute cluster/atom +compute_cluster_atom.html compute fragment/atom +compute_cna_atom.html compute cna/atom +compute_cnp_atom.html compute cnp/atom +compute_com_chunk.html compute com/chunk +compute_com.html compute com +compute_contact_atom.html compute contact/atom +compute_coord_atom.html compute coord/atom +compute_coord_atom.html compute coord/atom/kk +compute_count_type.html compute count/type +compute_damage_atom.html compute damage/atom +compute_dihedral_local.html compute dihedral/local +compute_dihedral.html compute dihedral +compute_dilatation_atom.html compute dilatation/atom +compute_dipole_chunk.html compute dipole/chunk +compute_dipole_chunk.html compute dipole/tip4p/chunk +compute_dipole.html compute dipole +compute_dipole.html compute dipole/tip4p +compute_displace_atom.html compute displace/atom +compute_dpd_atom.html compute dpd/atom +compute_dpd.html compute dpd +compute_edpd_temp_atom.html compute edpd/temp/atom +compute_efield_atom.html compute efield/atom +compute_efield_wolf_atom.html compute efield/wolf/atom +compute_entropy_atom.html compute entropy/atom +compute_erotate_asphere.html compute erotate/asphere +compute_erotate_rigid.html compute erotate/rigid +compute_erotate_sphere_atom.html compute erotate/sphere/atom +compute_erotate_sphere.html compute erotate/sphere +compute_erotate_sphere.html compute erotate/sphere/kk +compute_event_displace.html compute event/displace +compute_fabric.html compute fabric +compute_fep.html compute fep +compute_fep_ta.html compute fep/ta +compute_global_atom.html compute global/atom +compute_group_group.html compute group/group +compute_gyration_chunk.html compute gyration/chunk +compute_gyration.html compute gyration +compute_gyration_shape_chunk.html compute gyration/shape/chunk +compute_gyration_shape.html compute gyration/shape +compute_heat_flux.html compute heat/flux +compute_hexorder_atom.html compute hexorder/atom +compute_hma.html compute hma +compute_improper_local.html compute improper/local +compute_improper.html compute improper +compute_inertia_chunk.html compute inertia/chunk +compute_ke_atom_eff.html compute ke/atom/eff +compute_ke_atom.html compute ke/atom +compute_ke_eff.html compute ke/eff +compute_ke_rigid.html compute ke/rigid +compute_ke.html compute ke +compute_local_comp_atom.html compute local/comp/atom +compute_local_comp_atom.html compute local/comp/atom/kk +compute_mliap.html compute mliap +compute_modify.html compute_modify +compute_momentum.html compute momentum +compute_msd_chunk.html compute msd/chunk +compute_msd_nongauss.html compute msd/nongauss +compute_msd.html compute msd +compute_nbond_atom.html compute nbond/atom +compute_omega_chunk.html compute omega/chunk +compute_orientorder_atom.html compute orientorder/atom +compute_orientorder_atom.html compute orientorder/atom/kk +compute_pair_local.html compute pair/local +compute_pair.html compute pair +compute_pe_atom.html compute pe/atom +compute_pe.html compute pe +compute_plasticity_atom.html compute plasticity/atom +compute_pressure_alchemy.html compute pressure/alchemy +compute_pressure.html compute pressure +compute_pressure_uef.html compute pressure/uef +compute_property_atom.html compute property/atom +compute_property_chunk.html compute property/chunk +compute_property_grid.html compute property/grid +compute_property_local.html compute property/local +compute_ptm_atom.html compute ptm/atom +compute_rdf.html compute rdf +compute_reduce_chunk.html compute reduce/chunk +compute_reduce.html compute reduce +compute_reduce.html compute reduce/region +compute_rigid_local.html compute rigid/local +compute.html compute +compute_saed.html compute saed +compute_slice.html compute slice +compute_smd_contact_radius.html compute smd/contact/radius +compute_smd_damage.html compute smd/damage +compute_smd_hourglass_error.html compute smd/hourglass/error +compute_smd_internal_energy.html compute smd/internal/energy +compute_smd_plastic_strain_rate.html compute smd/plastic/strain/rate +compute_smd_plastic_strain.html compute smd/plastic/strain +compute_smd_rho.html compute smd/rho +compute_smd_tlsph_defgrad.html compute smd/tlsph/defgrad +compute_smd_tlsph_dt.html compute smd/tlsph/dt +compute_smd_tlsph_num_neighs.html compute smd/tlsph/num/neighs +compute_smd_tlsph_shape.html compute smd/tlsph/shape +compute_smd_tlsph_strain_rate.html compute smd/tlsph/strain/rate +compute_smd_tlsph_strain.html compute smd/tlsph/strain +compute_smd_tlsph_stress.html compute smd/tlsph/stress +compute_smd_triangle_vertices.html compute smd/triangle/vertices +compute_smd_ulsph_effm.html compute smd/ulsph/effm +compute_smd_ulsph_num_neighs.html compute smd/ulsph/num/neighs +compute_smd_ulsph_strain_rate.html compute smd/ulsph/strain/rate +compute_smd_ulsph_strain.html compute smd/ulsph/strain +compute_smd_ulsph_stress.html compute smd/ulsph/stress +compute_smd_vol.html compute smd/vol +compute_sna_atom.html compute sna/atom +compute_sna_atom.html compute snad/atom +compute_sna_atom.html compute sna/grid +compute_sna_atom.html compute sna/grid/local +compute_sna_atom.html compute snap +compute_sna_atom.html compute snav/atom +compute_sph_e_atom.html compute sph/e/atom +compute_sph_rho_atom.html compute sph/rho/atom +compute_sph_t_atom.html compute sph/t/atom +compute_spin.html compute spin +compute_stress_atom.html compute centroid/stress/atom +compute_stress_atom.html compute stress/atom +compute_stress_cartesian.html compute stress/cartesian +compute_stress_curvilinear.html compute stress/cylinder +compute_stress_curvilinear.html compute stress/spherical +compute_stress_mop.html compute stress/mop +compute_stress_mop.html compute stress/mop/profile +compute_tally.html compute force/tally +compute_tally.html compute heat/flux/tally +compute_tally.html compute heat/flux/virial/tally +compute_tally.html compute pe/mol/tally +compute_tally.html compute pe/tally +compute_tally.html compute stress/tally +compute_tdpd_cc_atom.html compute tdpd/cc/atom +compute_temp_asphere.html compute temp/asphere +compute_temp_body.html compute temp/body +compute_temp_chunk.html compute temp/chunk +compute_temp_com.html compute temp/com +compute_temp_cs.html compute temp/cs +compute_temp_deform_eff.html compute temp/deform/eff +compute_temp_deform.html compute temp/deform +compute_temp_deform.html compute temp/deform/kk +compute_temp_drude.html compute temp/drude +compute_temp_eff.html compute temp/eff +compute_temp_partial.html compute temp/partial +compute_temp_profile.html compute temp/profile +compute_temp_ramp.html compute temp/ramp +compute_temp_region_eff.html compute temp/region/eff +compute_temp_region.html compute temp/region +compute_temp_rotate.html compute temp/rotate +compute_temp.html compute temp +compute_temp.html compute temp/kk +compute_temp_sphere.html compute temp/sphere +compute_temp_uef.html compute temp/uef +compute_ti.html compute ti +compute_torque_chunk.html compute torque/chunk +compute_vacf.html compute vacf +compute_vcm_chunk.html compute vcm/chunk +compute_viscosity_cos.html compute viscosity/cos +compute_voronoi_atom.html compute voronoi/atom +compute_xrd.html compute xrd +create_atoms.html create_atoms +create_bonds.html create_bonds +create_box.html create_box +delete_atoms.html delete_atoms +delete_bonds.html delete_bonds +dielectric.html dielectric +dihedral_charmm.html dihedral_style charmm +dihedral_charmm.html dihedral_style charmmfsw +dihedral_charmm.html dihedral_style charmm/intel +dihedral_charmm.html dihedral_style charmm/kk +dihedral_charmm.html dihedral_style charmm/omp +dihedral_class2.html dihedral_style class2 +dihedral_class2.html dihedral_style class2/kk +dihedral_class2.html dihedral_style class2/omp +dihedral_coeff.html dihedral_coeff +dihedral_cosine_shift_exp.html dihedral_style cosine/shift/exp +dihedral_cosine_shift_exp.html dihedral_style cosine/shift/exp/omp +dihedral_fourier.html dihedral_style fourier +dihedral_fourier.html dihedral_style fourier/intel +dihedral_fourier.html dihedral_style fourier/omp +dihedral_harmonic.html dihedral_style harmonic +dihedral_harmonic.html dihedral_style harmonic/intel +dihedral_harmonic.html dihedral_style harmonic/kk +dihedral_harmonic.html dihedral_style harmonic/omp +dihedral_helix.html dihedral_style helix +dihedral_helix.html dihedral_style helix/omp +dihedral_hybrid.html dihedral_style hybrid +dihedral_lepton.html dihedral_style lepton +dihedral_lepton.html dihedral_style lepton/omp +dihedral_multi_harmonic.html dihedral_style multi/harmonic +dihedral_multi_harmonic.html dihedral_style multi/harmonic/omp +dihedral_nharmonic.html dihedral_style nharmonic +dihedral_nharmonic.html dihedral_style nharmonic/omp +dihedral_none.html dihedral_style none +dihedral_opls.html dihedral_style opls +dihedral_opls.html dihedral_style opls/intel +dihedral_opls.html dihedral_style opls/kk +dihedral_opls.html dihedral_style opls/omp +dihedral_quadratic.html dihedral_style quadratic +dihedral_quadratic.html dihedral_style quadratic/omp +dihedral_spherical.html dihedral_style spherical +dihedral_style.html dihedral_style +dihedral_table.html dihedral_style table +dihedral_table.html dihedral_style table/cut +dihedral_table.html dihedral_style table/omp +dihedral_write.html dihedral_write +dihedral_zero.html dihedral_style zero +dimension.html dimension +displace_atoms.html displace_atoms +dump_adios.html dump atom/adios +dump_adios.html dump custom/adios +dump_cfg_uef.html dump cfg/uef +dump_h5md.html dump h5md +dump_image.html dump image +dump_image.html dump movie +dump_modify.html dump_modify +dump_molfile.html dump molfile +dump_netcdf.html dump netcdf +dump_netcdf.html dump netcdf/mpiio +dump.html dump +dump.html dump atom +dump.html dump atom/gz +dump.html dump atom/mpiio +dump.html dump atom/zstd +dump.html dump cfg +dump.html dump cfg/gz +dump.html dump cfg/mpiio +dump.html dump cfg/zstd +dump.html dump custom +dump.html dump custom/gz +dump.html dump custom/mpiio +dump.html dump custom/zstd +dump.html dump dcd +dump.html dump grid +dump.html dump grid/vtk +dump.html dump local +dump.html dump local/gz +dump.html dump local/zstd +dump.html dump xtc +dump.html dump xyz +dump.html dump xyz/gz +dump.html dump xyz/mpiio +dump.html dump xyz/zstd +dump.html dump yaml +dump_vtk.html dump vtk +dynamical_matrix.html dynamical_matrix +dynamical_matrix.html dynamical_matrix/kk +echo.html echo +fitpod_command.html fitpod +fix_accelerate_cos.html fix accelerate/cos +fix_acks2_reaxff.html fix acks2/reaxff +fix_acks2_reaxff.html fix acks2/reaxff/kk +fix_adapt_fep.html fix adapt/fep +fix_adapt.html fix adapt +fix_addforce.html fix addforce +fix_addtorque.html fix addtorque +fix_alchemy.html fix alchemy +fix_amoeba_bitorsion.html fix amoeba/bitorsion +fix_amoeba_pitorsion.html fix amoeba/pitorsion +fix_append_atoms.html fix append/atoms +fix_atc.html fix atc +fix_atom_swap.html fix atom/swap +fix_ave_atom.html fix ave/atom +fix_ave_chunk.html fix ave/chunk +fix_ave_correlate_long.html fix ave/correlate/long +fix_ave_correlate.html fix ave/correlate +fix_aveforce.html fix aveforce +fix_ave_grid.html fix ave/grid +fix_ave_histo.html fix ave/histo +fix_ave_histo.html fix ave/histo/weight +fix_ave_time.html fix ave/time +fix_balance.html fix balance +fix_bocs.html fix bocs +fix_bond_break.html fix bond/break +fix_bond_create.html fix bond/create +fix_bond_create.html fix bond/create/angle +fix_bond_react.html fix bond/react +fix_bond_swap.html fix bond/swap +fix_box_relax.html fix box/relax +fix_brownian.html fix brownian +fix_brownian.html fix brownian/asphere +fix_brownian.html fix brownian/sphere +fix_charge_regulation.html fix charge/regulation +fix_cmap.html fix cmap +fix_colvars.html fix colvars +fix_controller.html fix controller +fix_damping_cundall.html fix damping/cundall +fix_deform.html fix deform +fix_deform.html fix deform/kk +fix_deposit.html fix deposit +fix_dpd_energy.html fix dpd/energy +fix_dpd_energy.html fix dpd/energy/kk +fix_dpd_source.html fix edpd/source +fix_dpd_source.html fix tdpd/source +fix_drag.html fix drag +fix_drude.html fix drude +fix_drude_transform.html fix drude/transform/direct +fix_drude_transform.html fix drude/transform/inverse +fix_dt_reset.html fix dt/reset +fix_dt_reset.html fix dt/reset/kk +fix_efield.html fix efield +fix_efield.html fix efield/tip4p +fix_ehex.html fix ehex +fix_electrode.html fix electrode/conp +fix_electrode.html fix electrode/conp/intel +fix_electrode.html fix electrode/conq +fix_electrode.html fix electrode/conq/intel +fix_electrode.html fix electrode/thermo +fix_electrode.html fix electrode/thermo/intel +fix_electron_stopping.html fix electron/stopping +fix_electron_stopping.html fix electron/stopping/fit +fix_enforce2d.html fix enforce2d +fix_enforce2d.html fix enforce2d/kk +fix_eos_cv.html fix eos/cv +fix_eos_table.html fix eos/table +fix_eos_table_rx.html fix eos/table/rx +fix_eos_table_rx.html fix eos/table/rx/kk +fix_evaporate.html fix evaporate +fix_external.html fix external +fix_ffl.html fix ffl +fix_filter_corotate.html fix filter/corotate +fix_flow_gauss.html fix flow/gauss +fix_freeze.html fix freeze +fix_freeze.html fix freeze/kk +fix_gcmc.html fix gcmc +fix_gld.html fix gld +fix_gle.html fix gle +fix_gravity.html fix gravity +fix_gravity.html fix gravity/kk +fix_gravity.html fix gravity/omp +fix_grem.html fix grem +fix_halt.html fix halt +fix_heat_flow.html fix heat/flow +fix_heat.html fix heat +fix_hyper_global.html fix hyper/global +fix_hyper_local.html fix hyper/local +fix_imd.html fix imd +fix_indent.html fix indent +fix_ipi.html fix ipi +fix_langevin_drude.html fix langevin/drude +fix_langevin_eff.html fix langevin/eff +fix_langevin.html fix langevin +fix_langevin.html fix langevin/kk +fix_langevin_spin.html fix langevin/spin +fix_lb_fluid.html fix lb/fluid +fix_lb_momentum.html fix lb/momentum +fix_lb_viscous.html fix lb/viscous +fix_lineforce.html fix lineforce +fix_manifoldforce.html fix manifoldforce +fix_mdi_qmmm.html fix mdi/qmmm +fix_mdi_qm.html fix mdi/qm +fix_meso_move.html fix meso/move +fix_modify.html fix_modify +fix_mol_swap.html fix mol/swap +fix_momentum.html fix momentum +fix_momentum.html fix momentum/chunk +fix_momentum.html fix momentum/kk +fix_move.html fix move +fix_msst.html fix msst +fix_mvv_dpd.html fix mvv/dpd +fix_mvv_dpd.html fix mvv/edpd +fix_mvv_dpd.html fix mvv/tdpd +fix_neb.html fix neb +fix_neb_spin.html fix neb/spin +fix_nh_eff.html fix nph/eff +fix_nh_eff.html fix npt/eff +fix_nh_eff.html fix nvt/eff +fix_nh.html fix nph +fix_nh.html fix nph/kk +fix_nh.html fix nph/omp +fix_nh.html fix npt +fix_nh.html fix npt/gpu +fix_nh.html fix npt/intel +fix_nh.html fix npt/kk +fix_nh.html fix npt/omp +fix_nh.html fix nvt +fix_nh.html fix nvt/gpu +fix_nh.html fix nvt/intel +fix_nh.html fix nvt/kk +fix_nh.html fix nvt/omp +fix_nh_uef.html fix npt/uef +fix_nh_uef.html fix nvt/uef +fix_nph_asphere.html fix nph/asphere +fix_nph_asphere.html fix nph/asphere/omp +fix_nph_body.html fix nph/body +fix_nph_sphere.html fix nph/sphere +fix_nph_sphere.html fix nph/sphere/omp +fix_nphug.html fix nphug +fix_nphug.html fix nphug/omp +fix_npt_asphere.html fix npt/asphere +fix_npt_asphere.html fix npt/asphere/omp +fix_npt_body.html fix npt/body +fix_npt_cauchy.html fix npt/cauchy +fix_npt_sphere.html fix npt/sphere +fix_npt_sphere.html fix npt/sphere/omp +fix_numdiff.html fix numdiff +fix_numdiff_virial.html fix numdiff/virial +fix_nve_asphere_noforce.html fix nve/asphere/noforce +fix_nve_asphere.html fix nve/asphere +fix_nve_asphere.html fix nve/asphere/gpu +fix_nve_asphere.html fix nve/asphere/intel +fix_nve_awpmd.html fix nve/awpmd +fix_nve_body.html fix nve/body +fix_nve_bpm_sphere.html fix nve/bpm/sphere +fix_nve_dotc_langevin.html fix nve/dotc/langevin +fix_nve_dot.html fix nve/dot +fix_nve_eff.html fix nve/eff +fix_nve_limit.html fix nve/limit +fix_nve_line.html fix nve/line +fix_nve_manifold_rattle.html fix nve/manifold/rattle +fix_nve_noforce.html fix nve/noforce +fix_nve.html fix nve +fix_nve.html fix nve/gpu +fix_nve.html fix nve/intel +fix_nve.html fix nve/kk +fix_nve.html fix nve/omp +fix_nve_sphere.html fix nve/sphere +fix_nve_sphere.html fix nve/sphere/kk +fix_nve_sphere.html fix nve/sphere/omp +fix_nve_spin.html fix nve/spin +fix_nve_tri.html fix nve/tri +fix_nvk.html fix nvk +fix_nvt_asphere.html fix nvt/asphere +fix_nvt_asphere.html fix nvt/asphere/omp +fix_nvt_body.html fix nvt/body +fix_nvt_manifold_rattle.html fix nvt/manifold/rattle +fix_nvt_sllod_eff.html fix nvt/sllod/eff +fix_nvt_sllod.html fix nvt/sllod +fix_nvt_sllod.html fix nvt/sllod/intel +fix_nvt_sllod.html fix nvt/sllod/kk +fix_nvt_sllod.html fix nvt/sllod/omp +fix_nvt_sphere.html fix nvt/sphere +fix_nvt_sphere.html fix nvt/sphere/omp +fix_oneway.html fix oneway +fix_orient_eco.html fix orient/eco +fix_orient.html fix orient/bcc +fix_orient.html fix orient/fcc +fix_pafi.html fix pafi +fix_pair.html fix pair +fix_phonon.html fix phonon +fix_pimd.html fix pimd/langevin +fix_pimd.html fix pimd/nvt +fix_planeforce.html fix planeforce +fix_plumed.html fix plumed +fix_poems.html fix poems +fix_polarize.html fix polarize/bem/gmres +fix_polarize.html fix polarize/bem/icc +fix_polarize.html fix polarize/functional +fix_pour.html fix pour +fix_precession_spin.html fix precession/spin +fix_press_berendsen.html fix press/berendsen +fix_print.html fix print +fix_propel_self.html fix propel/self +fix_property_atom.html fix property/atom +fix_property_atom.html fix property/atom/kk +fix_python_invoke.html fix python/invoke +fix_python_move.html fix python/move +fix_qbmsst.html fix qbmsst +fix_qeq_comb.html fix qeq/comb +fix_qeq_comb.html fix qeq/comb/omp +fix_qeq_reaxff.html fix qeq/reaxff +fix_qeq_reaxff.html fix qeq/reaxff/kk +fix_qeq_reaxff.html fix qeq/reaxff/omp +fix_qeq.html fix qeq/dynamic +fix_qeq.html fix qeq/fire +fix_qeq.html fix qeq/point +fix_qeq.html fix qeq/shielded +fix_qeq.html fix qeq/slater +fix_qmmm.html fix qmmm +fix_qtb.html fix qtb +fix_reaxff_bonds.html fix reaxff/bonds +fix_reaxff_bonds.html fix reaxff/bonds/kk +fix_reaxff_species.html fix reaxff/species +fix_reaxff_species.html fix reaxff/species/kk +fix_recenter.html fix recenter +fix_restrain.html fix restrain +fix_rhok.html fix rhok +fix_rigid_meso.html fix rigid/meso +fix_rigid.html fix rigid +fix_rigid.html fix rigid/nph +fix_rigid.html fix rigid/nph/omp +fix_rigid.html fix rigid/nph/small +fix_rigid.html fix rigid/npt +fix_rigid.html fix rigid/npt/omp +fix_rigid.html fix rigid/npt/small +fix_rigid.html fix rigid/nve +fix_rigid.html fix rigid/nve/omp +fix_rigid.html fix rigid/nve/small +fix_rigid.html fix rigid/nvt +fix_rigid.html fix rigid/nvt/omp +fix_rigid.html fix rigid/nvt/small +fix_rigid.html fix rigid/omp +fix_rigid.html fix rigid/small +fix_rigid.html fix rigid/small/omp +fix.html fix +fix_rx.html fix rx +fix_rx.html fix rx/kk +fix_saed_vtk.html fix saed/vtk +fix_setforce.html fix setforce +fix_setforce.html fix setforce/kk +fix_setforce.html fix setforce/spin +fix_sgcmc.html fix sgcmc +fix_shake.html fix rattle +fix_shake.html fix shake +fix_shake.html fix shake/kk +fix_shardlow.html fix shardlow +fix_shardlow.html fix shardlow/kk +fix_smd_adjust_dt.html fix smd/adjust_dt +fix_smd_integrate_tlsph.html fix smd/integrate_tlsph +fix_smd_integrate_ulsph.html fix smd/integrate_ulsph +fix_smd_move_triangulated_surface.html fix smd/move_tri_surf +fix_smd.html fix smd +fix_smd_setvel.html fix smd/setvel +fix_smd_wall_surface.html fix smd/wall_surface +fix_sph.html fix sph +fix_sph_stationary.html fix sph/stationary +fix_spring_chunk.html fix spring/chunk +fix_spring_rg.html fix spring/rg +fix_spring.html fix spring +fix_spring_self.html fix spring/self +fix_srd.html fix srd +fix_store_force.html fix store/force +fix_store_state.html fix store/state +fix_temp_berendsen.html fix temp/berendsen +fix_temp_csvr.html fix temp/csld +fix_temp_csvr.html fix temp/csvr +fix_temp_rescale_eff.html fix temp/rescale/eff +fix_temp_rescale.html fix temp/rescale +fix_tfmc.html fix tfmc +fix_tgnh_drude.html fix tgnpt/drude +fix_tgnh_drude.html fix tgnvt/drude +fix_thermal_conductivity.html fix thermal/conductivity +fix_ti_spring.html fix ti/spring +fix_tmd.html fix tmd +fix_ttm.html fix ttm +fix_ttm.html fix ttm/grid +fix_ttm.html fix ttm/mod +fix_tune_kspace.html fix tune/kspace +fix_vector.html fix vector +fix_viscosity.html fix viscosity +fix_viscous.html fix viscous +fix_viscous.html fix viscous/kk +fix_viscous_sphere.html fix viscous/sphere +fix_wall_body_polygon.html fix wall/body/polygon +fix_wall_body_polyhedron.html fix wall/body/polyhedron +fix_wall_ees.html fix wall/ees +fix_wall_ees.html fix wall/region/ees +fix_wall_gran_region.html fix wall/gran/region +fix_wall_gran.html fix wall/gran +fix_wall_gran.html fix wall/gran/kk +fix_wall_piston.html fix wall/piston +fix_wall_reflect.html fix wall/reflect +fix_wall_reflect.html fix wall/reflect/kk +fix_wall_reflect_stochastic.html fix wall/reflect/stochastic +fix_wall_region.html fix wall/region +fix_wall.html fix wall/colloid +fix_wall.html fix wall/harmonic +fix_wall.html fix wall/lepton +fix_wall.html fix wall/lj1043 +fix_wall.html fix wall/lj126 +fix_wall.html fix wall/lj93 +fix_wall.html fix wall/lj93/kk +fix_wall.html fix wall/morse +fix_wall.html fix wall/table +fix_wall_srd.html fix wall/srd +fix_widom.html fix widom +group2ndx.html group2ndx +group2ndx.html ndx2group +group.html group +hyper.html hyper +if.html if +improper_amoeba.html improper_style amoeba +improper_class2.html improper_style class2 +improper_class2.html improper_style class2/kk +improper_class2.html improper_style class2/omp +improper_coeff.html improper_coeff +improper_cossq.html improper_style cossq +improper_cossq.html improper_style cossq/omp +improper_cvff.html improper_style cvff +improper_cvff.html improper_style cvff/intel +improper_cvff.html improper_style cvff/omp +improper_distance.html improper_style distance +improper_distharm.html improper_style distharm +improper_fourier.html improper_style fourier +improper_fourier.html improper_style fourier/omp +improper_harmonic.html improper_style harmonic +improper_harmonic.html improper_style harmonic/intel +improper_harmonic.html improper_style harmonic/kk +improper_harmonic.html improper_style harmonic/omp +improper_hybrid.html improper_style hybrid +improper_inversion_harmonic.html improper_style inversion/harmonic +improper_none.html improper_style none +improper_ring.html improper_style ring +improper_ring.html improper_style ring/omp +improper_sqdistharm.html improper_style sqdistharm +improper_style.html improper_style +improper_umbrella.html improper_style umbrella +improper_umbrella.html improper_style umbrella/omp +improper_zero.html improper_style zero +include.html include +info.html info +jump.html jump +kim_commands.html kim_commands +kspace_modify.html kspace_modify +kspace_style.html kspace_style ewald +kspace_style.html kspace_style ewald/dipole +kspace_style.html kspace_style ewald/dipole/spin +kspace_style.html kspace_style ewald/disp +kspace_style.html kspace_style ewald/disp/dipole +kspace_style.html kspace_style ewald/electrode +kspace_style.html kspace_style ewald/omp +kspace_style.html kspace_style msm +kspace_style.html kspace_style msm/cg +kspace_style.html kspace_style msm/cg/omp +kspace_style.html kspace_style msm/dielectric +kspace_style.html kspace_style msm/omp +kspace_style.html kspace_style pppm +kspace_style.html kspace_style pppm/cg +kspace_style.html kspace_style pppm/cg/omp +kspace_style.html kspace_style pppm/dielectric +kspace_style.html kspace_style pppm/dipole +kspace_style.html kspace_style pppm/dipole/spin +kspace_style.html kspace_style pppm/disp +kspace_style.html kspace_style pppm/disp/dielectric +kspace_style.html kspace_style pppm/disp/intel +kspace_style.html kspace_style pppm/disp/omp +kspace_style.html kspace_style pppm/disp/tip4p +kspace_style.html kspace_style pppm/disp/tip4p/omp +kspace_style.html kspace_style pppm/electrode +kspace_style.html kspace_style pppm/electrode/intel +kspace_style.html kspace_style pppm/gpu +kspace_style.html kspace_style pppm/intel +kspace_style.html kspace_style pppm/kk +kspace_style.html kspace_style pppm/omp +kspace_style.html kspace_style pppm/stagger +kspace_style.html kspace_style pppm/tip4p +kspace_style.html kspace_style pppm/tip4p/omp +kspace_style.html kspace_style scafacos +labelmap.html labelmap +label.html label +lattice.html lattice +log.html log +mass.html mass +mdi.html mdi +minimize.html minimize +minimize.html minimize/kk +min_modify.html min_modify +min_spin.html min_style spin +min_style.html min_style +molecule.html molecule +neb.html neb +neb_spin.html neb/spin +neighbor.html neighbor +neigh_modify.html neigh_modify +newton.html newton +next.html next +package.html package +pair_adp.html pair_style adp +pair_adp.html pair_style adp/kk +pair_adp.html pair_style adp/omp +pair_agni.html pair_style agni +pair_agni.html pair_style agni/omp +pair_aip_water_2dm.html pair_style aip/water/2dm +pair_aip_water_2dm.html pair_style aip/water/2dm/opt +pair_airebo.html pair_style airebo +pair_airebo.html pair_style airebo/intel +pair_airebo.html pair_style airebo/morse +pair_airebo.html pair_style airebo/morse/intel +pair_airebo.html pair_style airebo/morse/omp +pair_airebo.html pair_style airebo/omp +pair_airebo.html pair_style rebo +pair_airebo.html pair_style rebo/intel +pair_airebo.html pair_style rebo/omp +pair_amoeba.html pair_style amoeba +pair_amoeba.html pair_style amoeba/gpu +pair_amoeba.html pair_style hippo +pair_amoeba.html pair_style hippo/gpu +pair_atm.html pair_style atm +pair_awpmd.html pair_style awpmd/cut +pair_beck.html pair_style beck +pair_beck.html pair_style beck/gpu +pair_beck.html pair_style beck/omp +pair_body_nparticle.html pair_style body/nparticle +pair_body_rounded_polygon.html pair_style body/rounded/polygon +pair_body_rounded_polyhedron.html pair_style body/rounded/polyhedron +pair_bop.html pair_style bop +pair_born_gauss.html pair_style born/gauss +pair_born.html pair_style born +pair_born.html pair_style born/coul/dsf +pair_born.html pair_style born/coul/long +pair_born.html pair_style born/coul/long/gpu +pair_born.html pair_style born/coul/long/omp +pair_born.html pair_style born/coul/msm +pair_born.html pair_style born/coul/msm/omp +pair_born.html pair_style born/coul/wolf +pair_born.html pair_style born/coul/wolf/gpu +pair_born.html pair_style born/coul/wolf/omp +pair_born.html pair_style born/gpu +pair_born.html pair_style born/omp +pair_bpm_spring.html pair_style bpm/spring +pair_brownian.html pair_style brownian +pair_brownian.html pair_style brownian/omp +pair_brownian.html pair_style brownian/poly +pair_brownian.html pair_style brownian/poly/omp +pair_buck6d_coul_gauss.html pair_style buck6d/coul/gauss/dsf +pair_buck6d_coul_gauss.html pair_style buck6d/coul/gauss/long +pair_buck_long.html pair_style buck/long/coul/long +pair_buck_long.html pair_style buck/long/coul/long/omp +pair_buck.html pair_style buck +pair_buck.html pair_style buck/coul/cut +pair_buck.html pair_style buck/coul/cut/gpu +pair_buck.html pair_style buck/coul/cut/intel +pair_buck.html pair_style buck/coul/cut/kk +pair_buck.html pair_style buck/coul/cut/omp +pair_buck.html pair_style buck/coul/long +pair_buck.html pair_style buck/coul/long/gpu +pair_buck.html pair_style buck/coul/long/intel +pair_buck.html pair_style buck/coul/long/kk +pair_buck.html pair_style buck/coul/long/omp +pair_buck.html pair_style buck/coul/msm +pair_buck.html pair_style buck/coul/msm/omp +pair_buck.html pair_style buck/gpu +pair_buck.html pair_style buck/intel +pair_buck.html pair_style buck/kk +pair_buck.html pair_style buck/omp +pair_charmm.html pair_style lj/charmm/coul/charmm +pair_charmm.html pair_style lj/charmm/coul/charmm/gpu +pair_charmm.html pair_style lj/charmm/coul/charmm/implicit +pair_charmm.html pair_style lj/charmm/coul/charmm/implicit/kk +pair_charmm.html pair_style lj/charmm/coul/charmm/implicit/omp +pair_charmm.html pair_style lj/charmm/coul/charmm/intel +pair_charmm.html pair_style lj/charmm/coul/charmm/kk +pair_charmm.html pair_style lj/charmm/coul/charmm/omp +pair_charmm.html pair_style lj/charmm/coul/long +pair_charmm.html pair_style lj/charmm/coul/long/gpu +pair_charmm.html pair_style lj/charmm/coul/long/intel +pair_charmm.html pair_style lj/charmm/coul/long/kk +pair_charmm.html pair_style lj/charmm/coul/long/omp +pair_charmm.html pair_style lj/charmm/coul/long/opt +pair_charmm.html pair_style lj/charmm/coul/msm +pair_charmm.html pair_style lj/charmm/coul/msm/omp +pair_charmm.html pair_style lj/charmmfsw/coul/charmmfsh +pair_charmm.html pair_style lj/charmmfsw/coul/long +pair_class2.html pair_style lj/class2 +pair_class2.html pair_style lj/class2/coul/cut +pair_class2.html pair_style lj/class2/coul/cut/kk +pair_class2.html pair_style lj/class2/coul/cut/omp +pair_class2.html pair_style lj/class2/coul/long +pair_class2.html pair_style lj/class2/coul/long/gpu +pair_class2.html pair_style lj/class2/coul/long/kk +pair_class2.html pair_style lj/class2/coul/long/omp +pair_class2.html pair_style lj/class2/gpu +pair_class2.html pair_style lj/class2/kk +pair_class2.html pair_style lj/class2/omp +pair_coeff.html pair_coeff +pair_colloid.html pair_style colloid +pair_colloid.html pair_style colloid/gpu +pair_colloid.html pair_style colloid/omp +pair_comb.html pair_style comb +pair_comb.html pair_style comb3 +pair_comb.html pair_style comb/omp +pair_cosine_squared.html pair_style cosine/squared +pair_coul_diel.html pair_style coul/diel +pair_coul_diel.html pair_style coul/diel/omp +pair_coul.html pair_style coul/cut +pair_coul.html pair_style coul/cut/global +pair_coul.html pair_style coul/cut/global/omp +pair_coul.html pair_style coul/cut/gpu +pair_coul.html pair_style coul/cut/kk +pair_coul.html pair_style coul/cut/omp +pair_coul.html pair_style coul/debye +pair_coul.html pair_style coul/debye/gpu +pair_coul.html pair_style coul/debye/kk +pair_coul.html pair_style coul/debye/omp +pair_coul.html pair_style coul/dsf +pair_coul.html pair_style coul/dsf/gpu +pair_coul.html pair_style coul/dsf/kk +pair_coul.html pair_style coul/dsf/omp +pair_coul.html pair_style coul/exclude +pair_coul.html pair_style coul/long +pair_coul.html pair_style coul/long/gpu +pair_coul.html pair_style coul/long/kk +pair_coul.html pair_style coul/long/omp +pair_coul.html pair_style coul/msm +pair_coul.html pair_style coul/msm/omp +pair_coul.html pair_style coul/streitz +pair_coul.html pair_style coul/wolf +pair_coul.html pair_style coul/wolf/kk +pair_coul.html pair_style coul/wolf/omp +pair_coul.html pair_style tip4p/cut +pair_coul.html pair_style tip4p/cut/omp +pair_coul.html pair_style tip4p/long +pair_coul.html pair_style tip4p/long/omp +pair_coul_shield.html pair_style coul/shield +pair_coul_slater.html pair_style coul/slater +pair_coul_slater.html pair_style coul/slater/cut +pair_coul_slater.html pair_style coul/slater/long +pair_coul_tt.html pair_style coul/tt +pair_cs.html pair_style born/coul/dsf/cs +pair_cs.html pair_style born/coul/long/cs +pair_cs.html pair_style born/coul/long/cs/gpu +pair_cs.html pair_style born/coul/wolf/cs +pair_cs.html pair_style born/coul/wolf/cs/gpu +pair_cs.html pair_style buck/coul/long/cs +pair_cs.html pair_style coul/long/cs +pair_cs.html pair_style coul/long/cs/gpu +pair_cs.html pair_style coul/wolf/cs +pair_cs.html pair_style lj/class2/coul/long/cs +pair_cs.html pair_style lj/cut/coul/long/cs +pair_dielectric.html pair_style coul/cut/dielectric +pair_dielectric.html pair_style coul/long/dielectric +pair_dielectric.html pair_style lj/cut/coul/cut/dielectric +pair_dielectric.html pair_style lj/cut/coul/cut/dielectric/omp +pair_dielectric.html pair_style lj/cut/coul/debye/dielectric +pair_dielectric.html pair_style lj/cut/coul/debye/dielectric/omp +pair_dielectric.html pair_style lj/cut/coul/long/dielectric +pair_dielectric.html pair_style lj/cut/coul/long/dielectric/omp +pair_dielectric.html pair_style lj/cut/coul/msm/dielectric +pair_dielectric.html pair_style lj/long/coul/long/dielectric +pair_dipole.html pair_style lj/cut/dipole/cut +pair_dipole.html pair_style lj/cut/dipole/cut/gpu +pair_dipole.html pair_style lj/cut/dipole/cut/kk +pair_dipole.html pair_style lj/cut/dipole/cut/omp +pair_dipole.html pair_style lj/cut/dipole/long +pair_dipole.html pair_style lj/cut/dipole/long/gpu +pair_dipole.html pair_style lj/long/dipole/long +pair_dipole.html pair_style lj/sf/dipole/sf +pair_dipole.html pair_style lj/sf/dipole/sf/gpu +pair_dipole.html pair_style lj/sf/dipole/sf/omp +pair_dpd_ext.html pair_style dpd/ext +pair_dpd_ext.html pair_style dpd/ext/kk +pair_dpd_ext.html pair_style dpd/ext/omp +pair_dpd_ext.html pair_style dpd/ext/tstat +pair_dpd_ext.html pair_style dpd/ext/tstat/kk +pair_dpd_ext.html pair_style dpd/ext/tstat/omp +pair_dpd_fdt.html pair_style dpd/fdt +pair_dpd_fdt.html pair_style dpd/fdt/energy +pair_dpd_fdt.html pair_style dpd/fdt/energy/kk +pair_dpd.html pair_style dpd +pair_dpd.html pair_style dpd/gpu +pair_dpd.html pair_style dpd/intel +pair_dpd.html pair_style dpd/kk +pair_dpd.html pair_style dpd/omp +pair_dpd.html pair_style dpd/tstat +pair_dpd.html pair_style dpd/tstat/gpu +pair_dpd.html pair_style dpd/tstat/kk +pair_dpd.html pair_style dpd/tstat/omp +pair_drip.html pair_style drip +pair_dsmc.html pair_style dsmc +pair_e3b.html pair_style e3b +pair_eam.html pair_style eam +pair_eam.html pair_style eam/alloy +pair_eam.html pair_style eam/alloy/gpu +pair_eam.html pair_style eam/alloy/intel +pair_eam.html pair_style eam/alloy/kk +pair_eam.html pair_style eam/alloy/omp +pair_eam.html pair_style eam/alloy/opt +pair_eam.html pair_style eam/cd +pair_eam.html pair_style eam/cd/old +pair_eam.html pair_style eam/fs +pair_eam.html pair_style eam/fs/gpu +pair_eam.html pair_style eam/fs/intel +pair_eam.html pair_style eam/fs/kk +pair_eam.html pair_style eam/fs/omp +pair_eam.html pair_style eam/fs/opt +pair_eam.html pair_style eam/gpu +pair_eam.html pair_style eam/he +pair_eam.html pair_style eam/intel +pair_eam.html pair_style eam/kk +pair_eam.html pair_style eam/omp +pair_eam.html pair_style eam/opt +pair_edip.html pair_style edip +pair_edip.html pair_style edip/multi +pair_edip.html pair_style edip/omp +pair_eff.html pair_style eff/cut +pair_eim.html pair_style eim +pair_eim.html pair_style eim/omp +pair_exp6_rx.html pair_style exp6/rx +pair_exp6_rx.html pair_style exp6/rx/kk +pair_extep.html pair_style extep +pair_fep_soft.html pair_style coul/cut/soft +pair_fep_soft.html pair_style coul/cut/soft/omp +pair_fep_soft.html pair_style coul/long/soft +pair_fep_soft.html pair_style coul/long/soft/omp +pair_fep_soft.html pair_style lj/charmm/coul/long/soft +pair_fep_soft.html pair_style lj/charmm/coul/long/soft/omp +pair_fep_soft.html pair_style lj/class2/coul/cut/soft +pair_fep_soft.html pair_style lj/class2/coul/long/soft +pair_fep_soft.html pair_style lj/class2/soft +pair_fep_soft.html pair_style lj/cut/coul/cut/soft +pair_fep_soft.html pair_style lj/cut/coul/cut/soft/omp +pair_fep_soft.html pair_style lj/cut/coul/long/soft +pair_fep_soft.html pair_style lj/cut/coul/long/soft/omp +pair_fep_soft.html pair_style lj/cut/soft +pair_fep_soft.html pair_style lj/cut/soft/omp +pair_fep_soft.html pair_style lj/cut/tip4p/long/soft +pair_fep_soft.html pair_style lj/cut/tip4p/long/soft/omp +pair_fep_soft.html pair_style morse/soft +pair_fep_soft.html pair_style tip4p/long/soft +pair_fep_soft.html pair_style tip4p/long/soft/omp +pair_gauss.html pair_style gauss +pair_gauss.html pair_style gauss/cut +pair_gauss.html pair_style gauss/cut/omp +pair_gauss.html pair_style gauss/gpu +pair_gauss.html pair_style gauss/omp +pair_gayberne.html pair_style gayberne +pair_gayberne.html pair_style gayberne/gpu +pair_gayberne.html pair_style gayberne/intel +pair_gayberne.html pair_style gayberne/omp +pair_gran.html pair_style gran/hertz/history +pair_gran.html pair_style gran/hertz/history/omp +pair_gran.html pair_style gran/hooke +pair_gran.html pair_style gran/hooke/history +pair_gran.html pair_style gran/hooke/history/kk +pair_gran.html pair_style gran/hooke/history/omp +pair_gran.html pair_style gran/hooke/omp +pair_granular.html pair_style granular +pair_gromacs.html pair_style lj/gromacs +pair_gromacs.html pair_style lj/gromacs/coul/gromacs +pair_gromacs.html pair_style lj/gromacs/coul/gromacs/kk +pair_gromacs.html pair_style lj/gromacs/coul/gromacs/omp +pair_gromacs.html pair_style lj/gromacs/gpu +pair_gromacs.html pair_style lj/gromacs/kk +pair_gromacs.html pair_style lj/gromacs/omp +pair_gw.html pair_style gw +pair_gw.html pair_style gw/zbl +pair_harmonic_cut.html pair_style harmonic/cut +pair_harmonic_cut.html pair_style harmonic/cut/omp +pair_hbond_dreiding.html pair_style hbond/dreiding/lj +pair_hbond_dreiding.html pair_style hbond/dreiding/lj/omp +pair_hbond_dreiding.html pair_style hbond/dreiding/morse +pair_hbond_dreiding.html pair_style hbond/dreiding/morse/omp +pair_hdnnp.html pair_style hdnnp +pair_hybrid.html pair_style hybrid +pair_hybrid.html pair_style hybrid/kk +pair_hybrid.html pair_style hybrid/overlay +pair_hybrid.html pair_style hybrid/overlay/kk +pair_hybrid.html pair_style hybrid/scaled +pair_ilp_graphene_hbn.html pair_style ilp/graphene/hbn +pair_ilp_graphene_hbn.html pair_style ilp/graphene/hbn/opt +pair_ilp_tmd.html pair_style ilp/tmd +pair_ilp_tmd.html pair_style ilp/tmd/opt +pair_kim.html pair_style kim +pair_kolmogorov_crespi_full.html pair_style kolmogorov/crespi/full +pair_kolmogorov_crespi_z.html pair_style kolmogorov/crespi/z +pair_lcbop.html pair_style lcbop +pair_lebedeva_z.html pair_style lebedeva/z +pair_lepton.html pair_style lepton +pair_lepton.html pair_style lepton/coul +pair_lepton.html pair_style lepton/coul/omp +pair_lepton.html pair_style lepton/omp +pair_lepton.html pair_style lepton/sphere +pair_lepton.html pair_style lepton/sphere/omp +pair_line_lj.html pair_style line/lj +pair_list.html pair_style list +pair_lj96.html pair_style lj96/cut +pair_lj96.html pair_style lj96/cut/gpu +pair_lj96.html pair_style lj96/cut/omp +pair_lj_cubic.html pair_style lj/cubic +pair_lj_cubic.html pair_style lj/cubic/gpu +pair_lj_cubic.html pair_style lj/cubic/omp +pair_lj_cut_coul.html pair_style lj/cut/coul/cut +pair_lj_cut_coul.html pair_style lj/cut/coul/cut/gpu +pair_lj_cut_coul.html pair_style lj/cut/coul/cut/kk +pair_lj_cut_coul.html pair_style lj/cut/coul/cut/omp +pair_lj_cut_coul.html pair_style lj/cut/coul/debye +pair_lj_cut_coul.html pair_style lj/cut/coul/debye/gpu +pair_lj_cut_coul.html pair_style lj/cut/coul/debye/kk +pair_lj_cut_coul.html pair_style lj/cut/coul/debye/omp +pair_lj_cut_coul.html pair_style lj/cut/coul/dsf +pair_lj_cut_coul.html pair_style lj/cut/coul/dsf/gpu +pair_lj_cut_coul.html pair_style lj/cut/coul/dsf/kk +pair_lj_cut_coul.html pair_style lj/cut/coul/dsf/omp +pair_lj_cut_coul.html pair_style lj/cut/coul/long +pair_lj_cut_coul.html pair_style lj/cut/coul/long/gpu +pair_lj_cut_coul.html pair_style lj/cut/coul/long/intel +pair_lj_cut_coul.html pair_style lj/cut/coul/long/kk +pair_lj_cut_coul.html pair_style lj/cut/coul/long/omp +pair_lj_cut_coul.html pair_style lj/cut/coul/long/opt +pair_lj_cut_coul.html pair_style lj/cut/coul/msm +pair_lj_cut_coul.html pair_style lj/cut/coul/msm/gpu +pair_lj_cut_coul.html pair_style lj/cut/coul/msm/omp +pair_lj_cut_coul.html pair_style lj/cut/coul/wolf +pair_lj_cut_coul.html pair_style lj/cut/coul/wolf/omp +pair_lj_cut_sphere.html pair_style lj/cut/sphere +pair_lj_cut_sphere.html pair_style lj/cut/sphere/omp +pair_lj_cut_tip4p.html pair_style lj/cut/tip4p/cut +pair_lj_cut_tip4p.html pair_style lj/cut/tip4p/cut/omp +pair_lj_cut_tip4p.html pair_style lj/cut/tip4p/long +pair_lj_cut_tip4p.html pair_style lj/cut/tip4p/long/gpu +pair_lj_cut_tip4p.html pair_style lj/cut/tip4p/long/omp +pair_lj_cut_tip4p.html pair_style lj/cut/tip4p/long/opt +pair_lj_expand.html pair_style lj/expand +pair_lj_expand.html pair_style lj/expand/coul/long +pair_lj_expand.html pair_style lj/expand/coul/long/gpu +pair_lj_expand.html pair_style lj/expand/coul/long/kk +pair_lj_expand.html pair_style lj/expand/gpu +pair_lj_expand.html pair_style lj/expand/kk +pair_lj_expand.html pair_style lj/expand/omp +pair_lj_expand_sphere.html pair_style lj/expand/sphere +pair_lj_expand_sphere.html pair_style lj/expand/sphere/omp +pair_lj_long.html pair_style lj/long/coul/long +pair_lj_long.html pair_style lj/long/coul/long/intel +pair_lj_long.html pair_style lj/long/coul/long/omp +pair_lj_long.html pair_style lj/long/coul/long/opt +pair_lj_long.html pair_style lj/long/tip4p/long +pair_lj_long.html pair_style lj/long/tip4p/long/omp +pair_lj_relres.html pair_style lj/relres +pair_lj_relres.html pair_style lj/relres/omp +pair_lj.html pair_style lj/cut +pair_lj.html pair_style lj/cut/gpu +pair_lj.html pair_style lj/cut/intel +pair_lj.html pair_style lj/cut/kk +pair_lj.html pair_style lj/cut/omp +pair_lj.html pair_style lj/cut/opt +pair_lj_smooth_linear.html pair_style lj/smooth/linear +pair_lj_smooth_linear.html pair_style lj/smooth/linear/omp +pair_lj_smooth.html pair_style lj/smooth +pair_lj_smooth.html pair_style lj/smooth/gpu +pair_lj_smooth.html pair_style lj/smooth/omp +pair_lj_switch3_coulgauss_long.html pair_style lj/switch3/coulgauss/long +pair_lj_switch3_coulgauss_long.html pair_style mm3/switch3/coulgauss/long +pair_local_density.html pair_style local/density +pair_lubricate.html pair_style lubricate +pair_lubricate.html pair_style lubricate/omp +pair_lubricate.html pair_style lubricate/poly +pair_lubricate.html pair_style lubricate/poly/omp +pair_lubricateU.html pair_style lubricateU +pair_lubricateU.html pair_style lubricateU/poly +pair_mdf.html pair_style buck/mdf +pair_mdf.html pair_style lennard/mdf +pair_mdf.html pair_style lj/mdf +pair_meam.html pair_style meam +pair_meam.html pair_style meam/kk +pair_meam.html pair_style meam/ms +pair_meam.html pair_style meam/ms/kk +pair_meam_spline.html pair_style meam/spline +pair_meam_spline.html pair_style meam/spline/omp +pair_meam_sw_spline.html pair_style meam/sw/spline +pair_mesocnt.html pair_style mesocnt +pair_mesocnt.html pair_style mesocnt/viscous +pair_mesodpd.html pair_style edpd +pair_mesodpd.html pair_style mdpd +pair_mesodpd.html pair_style mdpd/rhosum +pair_mesodpd.html pair_style tdpd +pair_mgpt.html pair_style mgpt +pair_mie.html pair_style mie/cut +pair_mie.html pair_style mie/cut/gpu +pair_mliap.html pair_style mliap +pair_mliap.html pair_style mliap/kk +pair_modify.html pair_modify +pair_momb.html pair_style momb +pair_morse.html pair_style morse +pair_morse.html pair_style morse/gpu +pair_morse.html pair_style morse/kk +pair_morse.html pair_style morse/omp +pair_morse.html pair_style morse/opt +pair_morse.html pair_style morse/smooth/linear +pair_morse.html pair_style morse/smooth/linear/omp +pair_multi_lucy.html pair_style multi/lucy +pair_multi_lucy_rx.html pair_style multi/lucy/rx +pair_multi_lucy_rx.html pair_style multi/lucy/rx/kk +pair_nb3b_harmonic.html pair_style nb3b/harmonic +pair_nm.html pair_style nm/cut +pair_nm.html pair_style nm/cut/coul/cut +pair_nm.html pair_style nm/cut/coul/cut/omp +pair_nm.html pair_style nm/cut/coul/long +pair_nm.html pair_style nm/cut/coul/long/omp +pair_nm.html pair_style nm/cut/omp +pair_nm.html pair_style nm/cut/split +pair_none.html pair_style none +pair_oxdna2.html pair_style oxdna2/coaxstk +pair_oxdna2.html pair_style oxdna2/dh +pair_oxdna2.html pair_style oxdna2/excv +pair_oxdna2.html pair_style oxdna2/hbond +pair_oxdna2.html pair_style oxdna2/stk +pair_oxdna2.html pair_style oxdna2/xstk +pair_oxdna.html pair_style oxdna/coaxstk +pair_oxdna.html pair_style oxdna/excv +pair_oxdna.html pair_style oxdna/hbond +pair_oxdna.html pair_style oxdna/stk +pair_oxdna.html pair_style oxdna/xstk +pair_oxrna2.html pair_style oxrna2/coaxstk +pair_oxrna2.html pair_style oxrna2/dh +pair_oxrna2.html pair_style oxrna2/excv +pair_oxrna2.html pair_style oxrna2/hbond +pair_oxrna2.html pair_style oxrna2/stk +pair_oxrna2.html pair_style oxrna2/xstk +pair_pace.html pair_style pace +pair_pace.html pair_style pace/extrapolation +pair_pace.html pair_style pace/extrapolation/kk +pair_pace.html pair_style pace/kk +pair_peri.html pair_style peri/eps +pair_peri.html pair_style peri/lps +pair_peri.html pair_style peri/lps/omp +pair_peri.html pair_style peri/pmb +pair_peri.html pair_style peri/pmb/omp +pair_peri.html pair_style peri/ves +pair_pod.html pair_style pod +pair_polymorphic.html pair_style polymorphic +pair_python.html pair_style python +pair_quip.html pair_style quip +pair_rann.html pair_style rann +pair_reaxff.html pair_style reaxff +pair_reaxff.html pair_style reaxff/kk +pair_reaxff.html pair_style reaxff/omp +pair_resquared.html pair_style resquared +pair_resquared.html pair_style resquared/gpu +pair_resquared.html pair_style resquared/omp +pair_saip_metal.html pair_style saip/metal +pair_saip_metal.html pair_style saip/metal/opt +pair_sdpd_taitwater_isothermal.html pair_style sdpd/taitwater/isothermal +pair_smatb.html pair_style smatb +pair_smatb.html pair_style smatb/single +pair_smd_hertz.html pair_style smd/hertz +pair_smd_tlsph.html pair_style smd/tlsph +pair_smd_triangulated_surface.html pair_style smd/tri_surface +pair_smd_ulsph.html pair_style smd/ulsph +pair_smtbq.html pair_style smtbq +pair_snap.html pair_style snap +pair_snap.html pair_style snap/kk +pair_soft.html pair_style soft +pair_soft.html pair_style soft/gpu +pair_soft.html pair_style soft/omp +pair_sph_heatconduction.html pair_style sph/heatconduction +pair_sph_idealgas.html pair_style sph/idealgas +pair_sph_lj.html pair_style sph/lj +pair_sph_rhosum.html pair_style sph/rhosum +pair_sph_taitwater_morris.html pair_style sph/taitwater/morris +pair_sph_taitwater.html pair_style sph/taitwater +pair_spica.html pair_style lj/spica +pair_spica.html pair_style lj/spica/coul/long +pair_spica.html pair_style lj/spica/coul/long/gpu +pair_spica.html pair_style lj/spica/coul/long/omp +pair_spica.html pair_style lj/spica/coul/msm +pair_spica.html pair_style lj/spica/coul/msm/omp +pair_spica.html pair_style lj/spica/gpu +pair_spica.html pair_style lj/spica/kk +pair_spica.html pair_style lj/spica/omp +pair_spin_dipole.html pair_style spin/dipole/cut +pair_spin_dipole.html pair_style spin/dipole/long +pair_spin_dmi.html pair_style spin/dmi +pair_spin_exchange.html pair_style spin/exchange +pair_spin_exchange.html pair_style spin/exchange/biquadratic +pair_spin_magelec.html pair_style spin/magelec +pair_spin_neel.html pair_style spin/neel +pair_srp.html pair_style srp +pair_srp.html pair_style srp/react +pair_style.html pair_style +pair_sw_angle_table.html pair_style sw/angle/table +pair_sw.html pair_style sw +pair_sw.html pair_style sw/gpu +pair_sw.html pair_style sw/intel +pair_sw.html pair_style sw/kk +pair_sw.html pair_style sw/mod +pair_sw.html pair_style sw/mod/omp +pair_sw.html pair_style sw/omp +pair_table.html pair_style table +pair_table.html pair_style table/gpu +pair_table.html pair_style table/kk +pair_table.html pair_style table/omp +pair_table_rx.html pair_style table/rx +pair_table_rx.html pair_style table/rx/kk +pair_tersoff_mod.html pair_style tersoff/mod +pair_tersoff_mod.html pair_style tersoff/mod/c +pair_tersoff_mod.html pair_style tersoff/mod/c/omp +pair_tersoff_mod.html pair_style tersoff/mod/gpu +pair_tersoff_mod.html pair_style tersoff/mod/kk +pair_tersoff_mod.html pair_style tersoff/mod/omp +pair_tersoff.html pair_style tersoff +pair_tersoff.html pair_style tersoff/gpu +pair_tersoff.html pair_style tersoff/intel +pair_tersoff.html pair_style tersoff/kk +pair_tersoff.html pair_style tersoff/omp +pair_tersoff.html pair_style tersoff/table +pair_tersoff.html pair_style tersoff/table/omp +pair_tersoff_zbl.html pair_style tersoff/zbl +pair_tersoff_zbl.html pair_style tersoff/zbl/gpu +pair_tersoff_zbl.html pair_style tersoff/zbl/kk +pair_tersoff_zbl.html pair_style tersoff/zbl/omp +pair_thole.html pair_style lj/cut/thole/long +pair_thole.html pair_style lj/cut/thole/long/omp +pair_thole.html pair_style thole +pair_threebody_table.html pair_style threebody/table +pair_tracker.html pair_style tracker +pair_tri_lj.html pair_style tri/lj +pair_ufm.html pair_style ufm +pair_ufm.html pair_style ufm/gpu +pair_ufm.html pair_style ufm/omp +pair_ufm.html pair_style ufm/opt +pair_vashishta.html pair_style vashishta +pair_vashishta.html pair_style vashishta/gpu +pair_vashishta.html pair_style vashishta/kk +pair_vashishta.html pair_style vashishta/omp +pair_vashishta.html pair_style vashishta/table +pair_vashishta.html pair_style vashishta/table/omp +pair_wf_cut.html pair_style wf/cut +pair_write.html pair_write +pair_ylz.html pair_style ylz +pair_yukawa_colloid.html pair_style yukawa/colloid +pair_yukawa_colloid.html pair_style yukawa/colloid/gpu +pair_yukawa_colloid.html pair_style yukawa/colloid/omp +pair_yukawa.html pair_style yukawa +pair_yukawa.html pair_style yukawa/gpu +pair_yukawa.html pair_style yukawa/kk +pair_yukawa.html pair_style yukawa/omp +pair_zbl.html pair_style zbl +pair_zbl.html pair_style zbl/gpu +pair_zbl.html pair_style zbl/kk +pair_zbl.html pair_style zbl/omp +pair_zero.html pair_style zero +partition.html partition +plugin.html plugin +prd.html prd +print.html print +processors.html processors +python.html python +quit.html quit +read_data.html read_data +read_dump.html read_dump +read_restart.html read_restart +region.html region +replicate.html replicate +rerun.html rerun +reset_atoms.html reset_atoms +reset_timestep.html reset_timestep +restart.html restart +run.html run +run_style.html run_style +set.html set +shell.html shell +special_bonds.html special_bonds +suffix.html suffix +tad.html tad +temper_grem.html temper/grem +temper_npt.html temper/npt +temper.html temper +thermo_modify.html thermo_modify +thermo.html thermo +thermo_style.html thermo_style +third_order.html third_order +third_order.html third_order/kk +timer.html timer +timestep.html timestep +uncompute.html uncompute +undump.html undump +unfix.html unfix +units.html units +variable.html variable +velocity.html velocity +write_coeff.html write_coeff +write_data.html write_data +write_dump.html write_dump +write_restart.html write_restart diff --git a/tools/lammps-gui/highlighter.cpp b/tools/lammps-gui/highlighter.cpp index 3e75cb56d4..c2afb28342 100644 --- a/tools/lammps-gui/highlighter.cpp +++ b/tools/lammps-gui/highlighter.cpp @@ -18,18 +18,23 @@ Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) HighlightingRule rule; outputFormat.setForeground(Qt::darkYellow); + outputFormat.setFontWeight(QFont::Bold); readFormat.setForeground(Qt::magenta); + readFormat.setFontWeight(QFont::Bold); latticeFormat.setForeground(Qt::darkGreen); + latticeFormat.setFontWeight(QFont::Bold); particleFormat.setForeground(Qt::darkRed); + particleFormat.setFontWeight(QFont::Bold); setupFormat.setForeground(Qt::darkCyan); - runFormat.setForeground(Qt::green); + setupFormat.setFontWeight(QFont::Bold); + runFormat.setForeground(Qt::darkBlue); runFormat.setFontWeight(QFont::Bold); defineFormat.setForeground(Qt::darkMagenta); defineFormat.setFontWeight(QFont::Bold); numberFormat.setForeground(Qt::blue); commentFormat.setForeground(Qt::red); - stringFormat.setForeground(Qt::cyan); + stringFormat.setForeground(Qt::darkGreen); stringFormat.setFontWeight(QFont::Normal); const QString output_keywords[] = { @@ -202,11 +207,44 @@ Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) void Highlighter::highlightBlock(const QString &text) { + auto style = QRegularExpression("^(fix|compute|dump|set)\\s+(\\w+)\\s+(\\S+)\\s+(\\S+)").match(text); + auto force = QRegularExpression("^(atom_style|pair_style|bond_style|angle_style|dihedral_style|improper_style|kspace_style)\\s+(\\S+)").match(text); + auto defs = QRegularExpression("^(group|variable)\\s+(\\S+)\\s+(\\S+)").match(text); + auto undo = QRegularExpression("^(unfix|uncompute|undump)\\s+(\\w+)").match(text); + bool do_style = true; + bool do_force = true; + bool do_defs = true; + bool do_undo = true; for (const HighlightingRule &rule : qAsConst(highlightingRules)) { QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); while (matchIterator.hasNext()) { QRegularExpressionMatch match = matchIterator.next(); - setFormat(match.capturedStart(), match.capturedLength(), rule.format); + // special treatment for fix/compute/dump styles etc. + if (style.hasMatch() && do_style) { + setFormat(style.capturedStart(1), style.capturedLength(1), defineFormat); + setFormat(style.capturedStart(2), style.capturedLength(2), numberFormat); + setFormat(style.capturedStart(3), style.capturedLength(3), stringFormat); + setFormat(style.capturedStart(4), style.capturedLength(4), runFormat); + do_style = false; + // special treatment for force styles styles + } else if (force.hasMatch() && do_force) { + setFormat(force.capturedStart(1), force.capturedLength(1), particleFormat); + setFormat(force.capturedStart(2), force.capturedLength(2), runFormat); + do_force = false; + // special treatment for undo commands + } else if (undo.hasMatch() && do_undo) { + setFormat(undo.capturedStart(1), undo.capturedLength(1), defineFormat); + setFormat(undo.capturedStart(2), undo.capturedLength(2), stringFormat); + do_undo = false; + // special treatment for some definitions + } else if (defs.hasMatch() && do_defs) { + setFormat(defs.capturedStart(1), defs.capturedLength(1), particleFormat); + setFormat(defs.capturedStart(2), defs.capturedLength(2), stringFormat); + setFormat(defs.capturedStart(3), defs.capturedLength(3), runFormat); + do_defs = false; + } else { + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } } } } diff --git a/tools/lammps-gui/icons/hicolor/128x128/apps/lammps.png b/tools/lammps-gui/icons/hicolor/128x128/apps/lammps.png new file mode 100644 index 0000000000..bfbeb47978 Binary files /dev/null and b/tools/lammps-gui/icons/hicolor/128x128/apps/lammps.png differ diff --git a/tools/lammps-gui/icons/hicolor/16x16/apps/lammps.png b/tools/lammps-gui/icons/hicolor/16x16/apps/lammps.png new file mode 100644 index 0000000000..b48ea6d6a9 Binary files /dev/null and b/tools/lammps-gui/icons/hicolor/16x16/apps/lammps.png differ diff --git a/tools/lammps-gui/icons/hicolor/22x22/apps/lammps.png b/tools/lammps-gui/icons/hicolor/22x22/apps/lammps.png new file mode 100644 index 0000000000..5f15c747d1 Binary files /dev/null and b/tools/lammps-gui/icons/hicolor/22x22/apps/lammps.png differ diff --git a/tools/lammps-gui/icons/hicolor/32x32/apps/lammps.png b/tools/lammps-gui/icons/hicolor/32x32/apps/lammps.png new file mode 100644 index 0000000000..4609d8a411 Binary files /dev/null and b/tools/lammps-gui/icons/hicolor/32x32/apps/lammps.png differ diff --git a/tools/lammps-gui/icons/hicolor/48x48/apps/lammps.png b/tools/lammps-gui/icons/hicolor/48x48/apps/lammps.png new file mode 100644 index 0000000000..bf578d74da Binary files /dev/null and b/tools/lammps-gui/icons/hicolor/48x48/apps/lammps.png differ diff --git a/tools/lammps-gui/icons/hicolor/64x64/apps/lammps.png b/tools/lammps-gui/icons/hicolor/64x64/apps/lammps.png new file mode 100644 index 0000000000..47fb998982 Binary files /dev/null and b/tools/lammps-gui/icons/hicolor/64x64/apps/lammps.png differ diff --git a/tools/lammps-gui/icons/lammps.ico b/tools/lammps-gui/icons/lammps.ico new file mode 100644 index 0000000000..cce156bf79 Binary files /dev/null and b/tools/lammps-gui/icons/lammps.ico differ diff --git a/tools/lammps-gui/icons/lmpfile.ico b/tools/lammps-gui/icons/lmpfile.ico new file mode 100644 index 0000000000..7e1636584f Binary files /dev/null and b/tools/lammps-gui/icons/lmpfile.ico differ diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index ec2f6cfbc4..a6a661880d 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -12,6 +12,7 @@ ------------------------------------------------------------------------- */ #include "imageviewer.h" +#include "lammpswrapper.h" #include #include @@ -25,15 +26,21 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include -ImageViewer::ImageViewer(const QString &fileName, QWidget *parent) : - QDialog(parent), imageLabel(new QLabel), scrollArea(new QScrollArea), menuBar(new QMenuBar) +static const QString blank(" "); + +ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidget *parent) : + QDialog(parent), imageLabel(new QLabel), scrollArea(new QScrollArea), menuBar(new QMenuBar), + lammps(_lammps), group("all"), filename(fileName) { imageLabel->setBackgroundRole(QPalette::Base); imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); @@ -42,8 +49,6 @@ ImageViewer::ImageViewer(const QString &fileName, QWidget *parent) : scrollArea->setBackgroundRole(QPalette::Dark); scrollArea->setWidget(imageLabel); - scrollArea->setMouseTracking(true); - scrollArea->installEventFilter(this); scrollArea->setVisible(false); buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); @@ -52,23 +57,72 @@ ImageViewer::ImageViewer(const QString &fileName, QWidget *parent) : connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addWidget(menuBar); + + auto *dossao = new QPushButton(QIcon(":/hd-img.png"), ""); + dossao->setCheckable(true); + auto *doanti = new QPushButton(QIcon(":/antialias.png"), ""); + doanti->setCheckable(true); + auto *dobox = new QPushButton(QIcon(":/system-box.png"), ""); + dobox->setCheckable(true); + auto *doaxes = new QPushButton(QIcon(":/axes-img.png"), ""); + doaxes->setCheckable(true); + auto *zoomin = new QPushButton(QIcon(":/gtk-zoom-in.png"), ""); + auto *zoomout = new QPushButton(QIcon(":/gtk-zoom-out.png"), ""); + auto *rotleft = new QPushButton(QIcon(":/object-rotate-left.png"), ""); + auto *rotright = new QPushButton(QIcon(":/object-rotate-right.png"), ""); + auto *rotup = new QPushButton(QIcon(":/gtk-go-up.png"), ""); + auto *rotdown = new QPushButton(QIcon(":/gtk-go-down.png"), ""); + auto *reset = new QPushButton(QIcon(":/gtk-zoom-fit.png"), ""); + auto *combo = new QComboBox; + combo->setObjectName("group"); + int ngroup = lammps->id_count("group"); + char gname[64]; + for (int i = 0; i < ngroup; ++i) { + lammps->id_name("group", i, gname, 64); + combo->addItem(gname); + } + + QHBoxLayout *menuLayout = new QHBoxLayout; + menuLayout->addWidget(menuBar); + menuLayout->addWidget(dossao); + menuLayout->addWidget(doanti); + menuLayout->addWidget(dobox); + menuLayout->addWidget(doaxes); + menuLayout->addWidget(zoomin); + menuLayout->addWidget(zoomout); + menuLayout->addWidget(rotleft); + menuLayout->addWidget(rotright); + menuLayout->addWidget(rotup); + menuLayout->addWidget(rotdown); + menuLayout->addWidget(reset); + menuLayout->addWidget(new QLabel(" Group: ")); + menuLayout->addWidget(combo); + + connect(dossao, &QPushButton::released, this, &ImageViewer::toggle_ssao); + connect(doanti, &QPushButton::released, this, &ImageViewer::toggle_anti); + connect(dobox, &QPushButton::released, this, &ImageViewer::toggle_box); + connect(doaxes, &QPushButton::released, this, &ImageViewer::toggle_axes); + connect(zoomin, &QPushButton::released, this, &ImageViewer::do_zoom_in); + connect(zoomout, &QPushButton::released, this, &ImageViewer::do_zoom_out); + connect(rotleft, &QPushButton::released, this, &ImageViewer::do_rot_left); + connect(rotright, &QPushButton::released, this, &ImageViewer::do_rot_right); + connect(rotup, &QPushButton::released, this, &ImageViewer::do_rot_up); + connect(rotdown, &QPushButton::released, this, &ImageViewer::do_rot_down); + connect(reset, &QPushButton::released, this, &ImageViewer::reset_view); + connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(change_group(int))); + + mainLayout->addLayout(menuLayout); mainLayout->addWidget(scrollArea); mainLayout->addWidget(buttonBox); - setWindowTitle(QString("Image Viewer: ") + QFileInfo(fileName).completeBaseName()); - + setWindowTitle(QString("Image Viewer: ") + QFileInfo(fileName).fileName()); createActions(); - QImageReader reader(fileName); - reader.setAutoTransform(true); - const QImage newImage = reader.read(); - if (newImage.isNull()) { - QMessageBox::warning(this, QGuiApplication::applicationDisplayName(), - tr("Cannot load %1: %2").arg(fileName, reader.errorString())); - return; - } - image = newImage; - imageLabel->setPixmap(QPixmap::fromImage(image)); + reset_view(); + dobox->setChecked(showbox); + doaxes->setChecked(showaxes); + dossao->setChecked(usessao); + doanti->setChecked(antialias); + scaleFactor = 1.0; resize(image.width() + 20, image.height() + 50); @@ -79,6 +133,181 @@ ImageViewer::ImageViewer(const QString &fileName, QWidget *parent) : setLayout(mainLayout); } +void ImageViewer::reset_view() +{ + QSettings settings; + settings.beginGroup("snapshot"); + zoom = settings.value("zoom", 1.0).toDouble(); + hrot = settings.value("hrot", 60).toInt(); + vrot = settings.value("vrot", 30).toInt(); + showbox = settings.value("box", true).toBool(); + showaxes = settings.value("axes", false).toBool(); + usessao = settings.value("ssao", false).toBool(); + antialias = settings.value("antialias", false).toBool(); + settings.endGroup(); + + // reset state of checkable push buttons and combo box (after main layout is set up) + auto *lo = layout(); + if (lo) { + // grab layout manager for the top bar + lo = lo->itemAt(0)->layout(); + // grab the first 4 buttons after the menu bar + auto *button = qobject_cast(lo->itemAt(1)->widget()); + button->setChecked(usessao); + button = qobject_cast(lo->itemAt(2)->widget()); + button->setChecked(antialias); + button = qobject_cast(lo->itemAt(3)->widget()); + button->setChecked(showbox); + button = qobject_cast(lo->itemAt(4)->widget()); + button->setChecked(showaxes); + // grab the last entry -> group selector + auto *cb = qobject_cast(lo->itemAt(lo->count() - 1)->widget()); + cb->setCurrentText("all"); + } + createImage(); +} + +void ImageViewer::toggle_ssao() +{ + QPushButton *button = qobject_cast(sender()); + usessao = !usessao; + button->setChecked(usessao); + createImage(); +} + +void ImageViewer::toggle_anti() +{ + QPushButton *button = qobject_cast(sender()); + antialias = !antialias; + button->setChecked(antialias); + createImage(); +} + +void ImageViewer::toggle_box() +{ + QPushButton *button = qobject_cast(sender()); + showbox = !showbox; + button->setChecked(showbox); + createImage(); +} + +void ImageViewer::toggle_axes() +{ + QPushButton *button = qobject_cast(sender()); + showaxes = !showaxes; + button->setChecked(showaxes); + createImage(); +} + +void ImageViewer::do_zoom_in() +{ + zoom = zoom * 1.1; + if (zoom > 5.0) zoom = 5.0; + createImage(); +} + +void ImageViewer::do_zoom_out() +{ + zoom = zoom / 1.1; + if (zoom < 0.5) zoom = 0.5; + createImage(); +} + +void ImageViewer::do_rot_left() +{ + vrot -= 15; + if (vrot < -180) vrot += 360; + createImage(); +} + +void ImageViewer::do_rot_right() +{ + vrot += 15; + if (vrot > 180) vrot -= 360; + createImage(); +} + +void ImageViewer::do_rot_down() +{ + hrot -= 15; + if (hrot < 0) hrot += 360; + createImage(); +} + +void ImageViewer::do_rot_up() +{ + hrot += 15; + if (hrot > 360) hrot -= 360; + createImage(); +} + +void ImageViewer::change_group(int idx) +{ + QComboBox *box = findChild("group"); + if (box) group = box->currentText(); + createImage(); +} + +void ImageViewer::createImage() +{ + QSettings settings; + QString dumpcmd = QString("write_dump ") + group + " image "; + QDir dumpdir(QDir::tempPath()); + QFile dumpfile(dumpdir.absoluteFilePath(filename + ".ppm")); + dumpcmd += dumpfile.fileName(); + + settings.beginGroup("snapshot"); + int aa = antialias ? 2 : 1; + int xsize = settings.value("xsize", 800).toInt() * aa; + int ysize = settings.value("ysize", 600).toInt() * aa; + int hhrot = (hrot > 180) ? 360 - hrot : hrot; + + dumpcmd += blank + settings.value("color", "type").toString(); + dumpcmd += blank + settings.value("diameter", "type").toString(); + dumpcmd += QString(" size ") + QString::number(xsize) + blank + QString::number(ysize); + dumpcmd += QString(" zoom ") + QString::number(zoom); + lammps->command(dumpcmd.toLocal8Bit()); + if (lammps->extract_setting("dimension") == 3) { + dumpcmd += QString(" view ") + QString::number(hhrot) + blank + QString::number(vrot); + } + if (usessao) dumpcmd += QString(" ssao yes 453983 0.75"); + if (showbox) + dumpcmd += QString(" box yes 0.025"); + else + dumpcmd += QString(" box no 0.0"); + + if (showaxes) + dumpcmd += QString(" axes yes 0.2 0.025"); + else + dumpcmd += QString(" axes no 0.0 0.0"); + + dumpcmd += " modify boxcolor " + settings.value("boxcolor", "yellow").toString(); + dumpcmd += " backcolor " + settings.value("background", "black").toString(); + settings.endGroup(); + + lammps->command(dumpcmd.toLocal8Bit()); + + QImageReader reader(dumpfile.fileName()); + reader.setAutoTransform(true); + const QImage newImage = reader.read(); + + if (newImage.isNull()) { + QMessageBox::warning( + this, QGuiApplication::applicationDisplayName(), + QString("Cannot load %1: %2").arg(dumpfile.fileName(), reader.errorString())); + return; + } + dumpfile.remove(); + + settings.beginGroup("snapshot"); + xsize = settings.value("xsize", 800).toInt(); + ysize = settings.value("ysize", 600).toInt(); + settings.endGroup(); + // scale back to achieve antialiasing + image = newImage.scaled(xsize, ysize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + imageLabel->setPixmap(QPixmap::fromImage(image)); +} + void ImageViewer::saveAs() { QString fileName = QFileDialog::getSaveFileName(this, "Save Image File As", QString(), @@ -90,12 +319,12 @@ void ImageViewer::copy() {} void ImageViewer::zoomIn() { - scaleImage(1.1); + scaleImage(1.25); } void ImageViewer::zoomOut() { - scaleImage(0.9); + scaleImage(0.8); } void ImageViewer::normalSize() @@ -119,38 +348,44 @@ void ImageViewer::saveFile(const QString &fileName) void ImageViewer::createActions() { - QMenu *fileMenu = menuBar->addMenu(tr("&File")); + QMenu *fileMenu = menuBar->addMenu("&File"); - saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &ImageViewer::saveAs); + saveAsAct = fileMenu->addAction("&Save As...", this, &ImageViewer::saveAs); + saveAsAct->setIcon(QIcon(":/document-save-as.png")); saveAsAct->setEnabled(false); fileMenu->addSeparator(); - copyAct = fileMenu->addAction(tr("&Copy"), this, &ImageViewer::copy); + copyAct = fileMenu->addAction("&Copy", this, &ImageViewer::copy); + copyAct->setIcon(QIcon(":/edit-copy.png")); copyAct->setShortcut(QKeySequence::Copy); copyAct->setEnabled(false); fileMenu->addSeparator(); - QAction *exitAct = fileMenu->addAction(tr("&Close"), this, &QWidget::close); - exitAct->setShortcut(tr("Ctrl+W")); + QAction *exitAct = fileMenu->addAction("&Close", this, &QWidget::close); + exitAct->setIcon(QIcon(":/window-close.png")); + exitAct->setShortcut(QKeySequence::fromString("Ctrl+W")); - QMenu *viewMenu = menuBar->addMenu(tr("&View")); + QMenu *viewMenu = menuBar->addMenu("&View"); - zoomInAct = viewMenu->addAction(tr("Zoom &In (10%)"), this, &ImageViewer::zoomIn); + zoomInAct = viewMenu->addAction("Image Zoom &In (25%)", this, &ImageViewer::zoomIn); zoomInAct->setShortcut(QKeySequence::ZoomIn); + zoomInAct->setIcon(QIcon(":/gtk-zoom-in.png")); zoomInAct->setEnabled(false); - zoomOutAct = viewMenu->addAction(tr("Zoom &Out (10%)"), this, &ImageViewer::zoomOut); + zoomOutAct = viewMenu->addAction("Image Zoom &Out (25%)", this, &ImageViewer::zoomOut); zoomOutAct->setShortcut(QKeySequence::ZoomOut); + zoomOutAct->setIcon(QIcon(":/gtk-zoom-out.png")); zoomOutAct->setEnabled(false); - normalSizeAct = viewMenu->addAction(tr("&Normal Size"), this, &ImageViewer::normalSize); - normalSizeAct->setShortcut(tr("Ctrl+S")); + normalSizeAct = viewMenu->addAction("&Reset Image Size", this, &ImageViewer::normalSize); + normalSizeAct->setShortcut(QKeySequence::fromString("Ctrl+0")); + normalSizeAct->setIcon(QIcon(":/gtk-zoom-fit.png")); normalSizeAct->setEnabled(false); viewMenu->addSeparator(); - fitToWindowAct = viewMenu->addAction(tr("&Fit to Window"), this, &ImageViewer::fitToWindow); + fitToWindowAct = viewMenu->addAction("&Fit to Window", this, &ImageViewer::fitToWindow); fitToWindowAct->setEnabled(false); fitToWindowAct->setCheckable(true); - fitToWindowAct->setShortcut(tr("Ctrl+F")); + fitToWindowAct->setShortcut(QKeySequence::fromString("Ctrl+=")); } void ImageViewer::updateActions() @@ -183,27 +418,6 @@ void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor) int(factor * scrollBar->value() + ((factor - 1) * scrollBar->pageStep() / 2))); } -bool ImageViewer::eventFilter(QObject *, QEvent *event) -{ - if (event->type() == QEvent::Wheel) { - wheelEvent((QWheelEvent *)event); - return true; - } - return false; -} - -void ImageViewer::wheelEvent(QWheelEvent *event) -{ - QPoint num = event->angleDelta(); - if (!num.isNull()) { - if (num.y() > 0) - zoomIn(); - else - zoomOut(); - } - event->accept(); -} - // Local Variables: // c-basic-offset: 4 // End: diff --git a/tools/lammps-gui/imageviewer.h b/tools/lammps-gui/imageviewer.h index edd66c9e73..b81e5b0d59 100644 --- a/tools/lammps-gui/imageviewer.h +++ b/tools/lammps-gui/imageviewer.h @@ -14,8 +14,10 @@ #ifndef IMAGEVIEWER_H #define IMAGEVIEWER_H +#include #include #include +#include class QAction; class QMenuBar; @@ -25,13 +27,15 @@ class QObject; class QScrollArea; class QScrollBar; class QStatusBar; -class QWheelEvent; +class LammpsWrapper; +class QComboBox; class ImageViewer : public QDialog { Q_OBJECT public: - explicit ImageViewer(const QString &fileName, QWidget *parent = nullptr); + explicit ImageViewer(const QString &fileName, LammpsWrapper *_lammps, + QWidget *parent = nullptr); private slots: void saveAs(); @@ -41,14 +45,28 @@ private slots: void normalSize(); void fitToWindow(); + void reset_view(); + void toggle_ssao(); + void toggle_anti(); + void toggle_box(); + void toggle_axes(); + void do_zoom_in(); + void do_zoom_out(); + void do_rot_left(); + void do_rot_right(); + void do_rot_up(); + void do_rot_down(); + void change_group(int); + +public: + void createImage(); + private: void createActions(); void updateActions(); void saveFile(const QString &fileName); void scaleImage(double factor); void adjustScrollBar(QScrollBar *scrollBar, double factor); - bool eventFilter(QObject *object, QEvent *event); - void wheelEvent(QWheelEvent *event); private: QImage image; @@ -64,6 +82,13 @@ private: QAction *zoomOutAct; QAction *normalSizeAct; QAction *fitToWindowAct; + + LammpsWrapper *lammps; + QString group; + QString filename; + int hrot, vrot; + double zoom; + bool showbox, showaxes, antialias, usessao; }; #endif diff --git a/tools/lammps-gui/lammps-gui.desktop b/tools/lammps-gui/lammps-gui.desktop new file mode 100644 index 0000000000..ffd903b1d9 --- /dev/null +++ b/tools/lammps-gui/lammps-gui.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Categories=Education;Science +MimeType=text/x-application-lammps +Exec=lammps-gui %f +Name=The LAMMPS GUI +Terminal=false +GenericName=LAMMPS MD Simulator GUI +Keywords=MD Simulation;LAMMPS;Molecular Dynamics;N-Body +Icon=lammps diff --git a/tools/lammps-gui/lammps-input.xml b/tools/lammps-gui/lammps-input.xml new file mode 100644 index 0000000000..20e1646316 --- /dev/null +++ b/tools/lammps-gui/lammps-input.xml @@ -0,0 +1,8 @@ + + + + LAMMPS input file + + + + diff --git a/tools/lammps-gui/lammps-logo.png b/tools/lammps-gui/lammps-logo.png new file mode 100644 index 0000000000..511f064b8a Binary files /dev/null and b/tools/lammps-gui/lammps-logo.png differ diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp index 3902e89abb..d4daf198e9 100644 --- a/tools/lammps-gui/lammpsgui.cpp +++ b/tools/lammps-gui/lammpsgui.cpp @@ -13,10 +13,13 @@ #include "lammpsgui.h" +#include "chartviewer.h" #include "highlighter.h" #include "imageviewer.h" #include "lammpsrunner.h" +#include "logwindow.h" #include "preferences.h" +#include "setvariables.h" #include "stdcapture.h" #include "ui_lammpsgui.h" @@ -26,12 +29,15 @@ #include #include #include +#include #include #include +#include #include #include #include #include +#include #include #include #include @@ -45,13 +51,8 @@ #include #endif -#if defined(_WIN32) -#include -#else -#include -#endif - static const QString blank(" "); +static constexpr int MAXRECENT = 5; // duplicate string static char *mystrdup(const std::string &text) @@ -61,109 +62,60 @@ static char *mystrdup(const std::string &text) return tmp; } +// find if executable is in path +// https://stackoverflow.com/a/51041497 + +static bool has_exe(const QString &exe) +{ + QProcess findProcess; + QStringList arguments; + arguments << exe; +#if defined(_WIN32) + findProcess.start("where", arguments); +#else + findProcess.start("which", arguments); +#endif + findProcess.setReadChannel(QProcess::ProcessChannel::StandardOutput); + + if (!findProcess.waitForFinished()) return false; // Not found or which does not work + + QString retStr(findProcess.readAll()); + retStr = retStr.trimmed(); + + QFile file(retStr); + QFileInfo check_file(file); + if (check_file.exists() && check_file.isFile()) + return true; // Found! + else + return false; // Not found! +} + LammpsGui::LammpsGui(QWidget *parent, const char *filename) : QMainWindow(parent), ui(new Ui::LammpsGui), highlighter(nullptr), capturer(nullptr), - status(nullptr), logwindow(nullptr), imagewindow(nullptr), logupdater(nullptr), - dirstatus(nullptr), progress(nullptr), prefdialog(nullptr) + status(nullptr), logwindow(nullptr), imagewindow(nullptr), chartwindow(nullptr), + logupdater(nullptr), dirstatus(nullptr), progress(nullptr), prefdialog(nullptr), + lammpsstatus(nullptr) { + // enforce using the plain ASCII C locale within the GUI. + QLocale::setDefault(QLocale("C")); + + // register QList + qRegisterMetaTypeStreamOperators>("QList"); + ui->setupUi(this); this->setCentralWidget(ui->textEdit); highlighter = new Highlighter(ui->textEdit->document()); capturer = new StdCapture; current_file.clear(); current_dir = QDir(".").absolutePath(); - recent_files.clear(); QCoreApplication::setOrganizationName("The LAMMPS Developers"); QCoreApplication::setOrganizationDomain("lammps.org"); QCoreApplication::setApplicationName("LAMMPS GUI"); - // restorge and initialize settings + // restore and initialize settings QSettings settings; - // check and initialize nthreads setting. Default is to use max, - // but not override OMP_NUM_THREADS and preferences setting. -#if defined(_OPENMP) - // use maximum number of available threads unless OMP_NUM_THREADS was set - int nthreads = settings.value("nthreads", omp_get_max_threads()).toInt(); -#if _WIN32 - if (!getenv("OMP_NUM_THREADS")) { - _putenv_s("OMP_NUM_THREADS", std::to_string(nthreads).c_str()); - } -#else - setenv("OMP_NUM_THREADS", std::to_string(nthreads).c_str(), 0); -#endif -#else - int nthreads = settings.value("nthreads", 1).toInt(); -#endif - settings.setValue("nthreads", QString::number(nthreads)); - - const char *tmpdir = getenv("TMPDIR"); - if (!tmpdir) tmpdir = getenv("TMP"); - if (!tmpdir) tmpdir = getenv("TEMPDIR"); - if (!tmpdir) tmpdir = getenv("TEMP"); -#if _WIN32 - if (!tmpdir) tmpdir = "C:\\Windows\\Temp"; -#else - if (!tmpdir) tmpdir = "/tmp"; -#endif - settings.setValue("tempdir", QString(tmpdir)); - - lammps_args.clear(); - lammps_args.push_back(mystrdup("LAMMPS-GUI")); - lammps_args.push_back(mystrdup("-log")); - lammps_args.push_back(mystrdup("none")); - - setWindowIcon(QIcon(":/lammps-icon-128x128.png")); -#if (__APPLE__) - QFont text_font("Menlo"); -#else - QFont text_font(":/Monospace.ttf"); -#endif - text_font.setStyleHint(QFont::TypeWriter); - ui->textEdit->document()->setDefaultFont(text_font); - ui->textEdit->setMinimumSize(600, 400); - - connect(ui->actionNew, &QAction::triggered, this, &LammpsGui::new_document); - connect(ui->actionOpen, &QAction::triggered, this, &LammpsGui::open); - connect(ui->actionSave, &QAction::triggered, this, &LammpsGui::save); - connect(ui->actionSave_As, &QAction::triggered, this, &LammpsGui::save_as); - connect(ui->actionQuit, &QAction::triggered, this, &LammpsGui::quit); - connect(ui->actionCopy, &QAction::triggered, this, &LammpsGui::copy); - connect(ui->actionCut, &QAction::triggered, this, &LammpsGui::cut); - connect(ui->actionPaste, &QAction::triggered, this, &LammpsGui::paste); - connect(ui->actionUndo, &QAction::triggered, this, &LammpsGui::undo); - connect(ui->actionRedo, &QAction::triggered, this, &LammpsGui::redo); - connect(ui->actionRun_Buffer, &QAction::triggered, this, &LammpsGui::run_buffer); - connect(ui->actionStop_LAMMPS, &QAction::triggered, this, &LammpsGui::stop_run); - connect(ui->actionImage, &QAction::triggered, this, &LammpsGui::view_image); - connect(ui->actionAbout_LAMMPS_GUI, &QAction::triggered, this, &LammpsGui::about); - connect(ui->action_Help, &QAction::triggered, this, &LammpsGui::help); - connect(ui->actionLAMMPS_Manual, &QAction::triggered, this, &LammpsGui::manual); - connect(ui->actionPreferences, &QAction::triggered, this, &LammpsGui::preferences); - connect(ui->actionDefaults, &QAction::triggered, this, &LammpsGui::defaults); - connect(ui->textEdit->document(), &QTextDocument::modificationChanged, this, - &LammpsGui::modified); - -#if !QT_CONFIG(clipboard) - ui->actionCut->setEnabled(false); - ui->actionCopy->setEnabled(false); - ui->actionPaste->setEnabled(false); -#endif - - status = new QLabel("Ready."); - status->setFixedWidth(300); - ui->statusbar->addWidget(status); - dirstatus = new QLabel(QString(" Directory: ") + current_dir); - dirstatus->setMinimumWidth(500); - ui->statusbar->addWidget(dirstatus); - progress = new QProgressBar(); - progress->setRange(0, 1000); - progress->setMinimumWidth(500); - progress->hide(); - dirstatus->show(); - ui->statusbar->addWidget(progress); - #if defined(LAMMPS_GUI_USE_PLUGIN) plugin_path.clear(); std::string deffile = settings.value("plugin_path", "liblammps.so").toString().toStdString(); @@ -181,16 +133,134 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) : // none of the plugin paths could load, remove key settings.remove("plugin_path"); QMessageBox::critical(this, "Error", "Cannot open LAMMPS shared library file"); - // QCoreApplication::quit(); exit(1); } #endif + // switch configured accelerator back to "none" if needed. + int accel = settings.value("accelerator", AcceleratorTab::None).toInt(); + if (accel == AcceleratorTab::Opt) { + if (!lammps.config_has_package("OPT")) + settings.setValue("accelerator", AcceleratorTab::None); + } else if (accel == AcceleratorTab::OpenMP) { + if (!lammps.config_has_package("OPENMP")) + settings.setValue("accelerator", AcceleratorTab::None); + } else if (accel == AcceleratorTab::Intel) { + if (!lammps.config_has_package("INTEL")) + settings.setValue("accelerator", AcceleratorTab::None); + } else if (accel == AcceleratorTab::Gpu) { + if (!lammps.config_has_package("GPU") || !lammps.has_gpu_device()) + settings.setValue("accelerator", AcceleratorTab::None); + } else if (accel == AcceleratorTab::Kokkos) { + if (!lammps.config_has_package("KOKKOS")) + settings.setValue("accelerator", AcceleratorTab::None); + } + + // check and initialize nthreads setting. Default is to use max if there + // is no preference but do not override OMP_NUM_THREADS +#if defined(_OPENMP) + // use maximum number of available threads unless OMP_NUM_THREADS was set + int nthreads = settings.value("nthreads", omp_get_max_threads()).toInt(); + if (!qEnvironmentVariableIsSet("OMP_NUM_THREADS")) { + qputenv("OMP_NUM_THREADS", std::to_string(nthreads).c_str()); + } +#else + int nthreads = settings.value("nthreads", 1).toInt(); +#endif + settings.setValue("nthreads", QString::number(nthreads)); + + lammps_args.clear(); + lammps_args.push_back(mystrdup("LAMMPS-GUI")); + lammps_args.push_back(mystrdup("-log")); + lammps_args.push_back(mystrdup("none")); + + setWindowIcon(QIcon(":/lammps-icon-128x128.png")); + + QFont all_font("Arial", -1); + all_font.setStyleHint(QFont::SansSerif, QFont::PreferOutline); + all_font.fromString(settings.value("allfont", all_font.toString()).toString()); + settings.setValue("allfont", all_font.toString()); + QApplication::setFont(all_font); + + QFont text_font("Monospace", -1); + text_font.setStyleHint(QFont::Monospace, QFont::PreferOutline); + text_font.fromString(settings.value("textfont", text_font.toString()).toString()); + settings.setValue("textfont", text_font.toString()); + ui->textEdit->document()->setDefaultFont(text_font); + ui->textEdit->setMinimumSize(600, 400); + + update_recents(); + + // check if we have OVITO and VMD installed and deacivate actions if not + ui->actionView_in_OVITO->setEnabled(has_exe("ovito")); + ui->actionView_in_OVITO->setData("ovito"); + ui->actionView_in_VMD->setEnabled(has_exe("vmd")); + ui->actionView_in_VMD->setData("vmd"); + + connect(ui->actionNew, &QAction::triggered, this, &LammpsGui::new_document); + connect(ui->actionOpen, &QAction::triggered, this, &LammpsGui::open); + connect(ui->actionSave, &QAction::triggered, this, &LammpsGui::save); + connect(ui->actionSave_As, &QAction::triggered, this, &LammpsGui::save_as); + connect(ui->actionQuit, &QAction::triggered, this, &LammpsGui::quit); + connect(ui->actionCopy, &QAction::triggered, this, &LammpsGui::copy); + connect(ui->actionCut, &QAction::triggered, this, &LammpsGui::cut); + connect(ui->actionPaste, &QAction::triggered, this, &LammpsGui::paste); + connect(ui->actionUndo, &QAction::triggered, this, &LammpsGui::undo); + connect(ui->actionRedo, &QAction::triggered, this, &LammpsGui::redo); + connect(ui->actionRun_Buffer, &QAction::triggered, this, &LammpsGui::run_buffer); + connect(ui->actionStop_LAMMPS, &QAction::triggered, this, &LammpsGui::stop_run); + connect(ui->actionSet_Variables, &QAction::triggered, this, &LammpsGui::edit_variables); + connect(ui->actionImage, &QAction::triggered, this, &LammpsGui::render_image); + connect(ui->actionAbout_LAMMPS_GUI, &QAction::triggered, this, &LammpsGui::about); + connect(ui->action_Help, &QAction::triggered, this, &LammpsGui::help); + connect(ui->actionLAMMPS_GUI_Howto, &QAction::triggered, this, &LammpsGui::howto); + connect(ui->actionLAMMPS_Manual, &QAction::triggered, this, &LammpsGui::manual); + connect(ui->actionPreferences, &QAction::triggered, this, &LammpsGui::preferences); + connect(ui->actionDefaults, &QAction::triggered, this, &LammpsGui::defaults); + connect(ui->actionView_in_OVITO, &QAction::triggered, this, &LammpsGui::start_exe); + connect(ui->actionView_in_VMD, &QAction::triggered, this, &LammpsGui::start_exe); + connect(ui->actionView_Log_Window, &QAction::triggered, this, &LammpsGui::view_log); + connect(ui->actionView_Graph_Window, &QAction::triggered, this, &LammpsGui::view_chart); + connect(ui->actionView_Image_Window, &QAction::triggered, this, &LammpsGui::view_image); + connect(ui->action_1, &QAction::triggered, this, &LammpsGui::open_recent); + connect(ui->action_2, &QAction::triggered, this, &LammpsGui::open_recent); + connect(ui->action_3, &QAction::triggered, this, &LammpsGui::open_recent); + connect(ui->action_4, &QAction::triggered, this, &LammpsGui::open_recent); + connect(ui->action_5, &QAction::triggered, this, &LammpsGui::open_recent); + + connect(ui->textEdit->document(), &QTextDocument::modificationChanged, this, + &LammpsGui::modified); + +#if !QT_CONFIG(clipboard) + ui->actionCut->setEnabled(false); + ui->actionCopy->setEnabled(false); + ui->actionPaste->setEnabled(false); +#endif + + lammpsstatus = new QLabel(QString()); + auto pix = QPixmap(":/lammps-icon-128x128.png"); + lammpsstatus->setPixmap(pix.scaled(22, 22, Qt::KeepAspectRatio)); + ui->statusbar->addWidget(lammpsstatus); + lammpsstatus->hide(); + status = new QLabel("Ready."); + status->setFixedWidth(300); + ui->statusbar->addWidget(status); + dirstatus = new QLabel(QString(" Directory: ") + current_dir); + dirstatus->setMinimumWidth(400); + ui->statusbar->addWidget(dirstatus); + progress = new QProgressBar(); + progress->setRange(0, 1000); + progress->setMinimumWidth(400); + progress->hide(); + dirstatus->show(); + ui->statusbar->addWidget(progress); + if (filename) { open_file(filename); } else { setWindowTitle(QString("LAMMPS-GUI - *unknown*")); } + resize(settings.value("mainx", "500").toInt(), settings.value("mainy", "320").toInt()); } LammpsGui::~LammpsGui() @@ -201,6 +271,7 @@ LammpsGui::~LammpsGui() delete status; delete logwindow; delete imagewindow; + delete chartwindow; delete dirstatus; } @@ -210,6 +281,7 @@ void LammpsGui::new_document() ui->textEdit->document()->setPlainText(QString()); lammps.close(); + lammpsstatus->hide(); setWindowTitle(QString("LAMMPS-GUI - *unknown*")); } @@ -219,6 +291,171 @@ void LammpsGui::open() open_file(fileName); } +void LammpsGui::open_recent() +{ + QAction *act = qobject_cast(sender()); + if (act) open_file(act->data().toString()); +} + +void LammpsGui::start_exe() +{ + if (!lammps.extract_setting("box_exists")) return; + QAction *act = qobject_cast(sender()); + if (act) { + auto exe = act->data().toString(); + QString datacmd = "write_data "; + QDir datadir(QDir::tempPath()); + QFile datafile(datadir.absoluteFilePath(current_file + ".data")); + datacmd += datafile.fileName(); + if (exe == "vmd") { + QStringList args; + QFile vmdfile(datadir.absoluteFilePath(current_file + ".vmd")); + vmdfile.open(QIODevice::WriteOnly); + vmdfile.write("package require topotools\n"); + vmdfile.write("topo readlammpsdata "); + vmdfile.write(datafile.fileName().toLocal8Bit()); + vmdfile.write("\ntopo guessatom lammps data\n"); + vmdfile.write("animate write psf "); + vmdfile.write(datafile.fileName().toLocal8Bit()); + vmdfile.write(".psf\nanimate write dcd "); + vmdfile.write(datafile.fileName().toLocal8Bit()); + vmdfile.write(".dcd\nmol delete top\nmol new "); + vmdfile.write(datafile.fileName().toLocal8Bit()); + vmdfile.write(".psf type psf waitfor all\nmol addfile "); + vmdfile.write(datafile.fileName().toLocal8Bit()); + vmdfile.write(".dcd type dcd waitfor all\nfile delete "); + vmdfile.write(datafile.fileName().toLocal8Bit()); + vmdfile.write(" "); + vmdfile.write(vmdfile.fileName().toLocal8Bit()); + vmdfile.write(" "); + vmdfile.write(datafile.fileName().toLocal8Bit()); + vmdfile.write(".dcd "); + vmdfile.write(datafile.fileName().toLocal8Bit()); + vmdfile.write(".psf\n"); + vmdfile.close(); + args << "-e" << vmdfile.fileName(); + lammps.command(datacmd.toLocal8Bit()); + auto *vmd = new QProcess(this); + vmd->start(exe, args); + } + if (exe == "ovito") { + QStringList args; + args << datafile.fileName(); + lammps.command(datacmd.toLocal8Bit()); + auto *ovito = new QProcess(this); + ovito->start(exe, args); + } + } +} + +void LammpsGui::update_recents(const QString &filename) +{ + QSettings settings; + recent = settings.value("recent").value>(); + + for (int i = 0; i < recent.size(); ++i) { + QFileInfo fi(recent[i]); + if (!fi.isReadable()) { + recent.removeAt(i); + i = 0; + } + } + + if (!filename.isEmpty() && !recent.contains(filename)) recent.prepend(filename); + if (recent.size() > 5) recent.removeLast(); + settings.setValue("recent", QVariant::fromValue(recent)); + + ui->action_1->setVisible(false); + if ((recent.size() > 0) && !recent[0].isEmpty()) { + QFileInfo fi(recent[0]); + ui->action_1->setText(QString("&1. ") + fi.fileName()); + ui->action_1->setData(recent[0]); + ui->action_1->setVisible(true); + } + ui->action_2->setVisible(false); + if ((recent.size() > 1) && !recent[1].isEmpty()) { + QFileInfo fi(recent[1]); + ui->action_2->setText(QString("&2. ") + fi.fileName()); + ui->action_2->setData(recent[1]); + ui->action_2->setVisible(true); + } + ui->action_3->setVisible(false); + if ((recent.size() > 2) && !recent[2].isEmpty()) { + QFileInfo fi(recent[2]); + ui->action_3->setText(QString("&3. ") + fi.fileName()); + ui->action_3->setData(recent[2]); + ui->action_3->setVisible(true); + } + ui->action_4->setVisible(false); + if ((recent.size() > 3) && !recent[3].isEmpty()) { + QFileInfo fi(recent[3]); + ui->action_4->setText(QString("&4. ") + fi.fileName()); + ui->action_4->setData(recent[3]); + ui->action_4->setVisible(true); + } + ui->action_5->setVisible(false); + if ((recent.size() > 4) && !recent[4].isEmpty()) { + QFileInfo fi(recent[4]); + ui->action_5->setText(QString("&5. ") + fi.fileName()); + ui->action_5->setData(recent[4]); + ui->action_5->setVisible(true); + } +} + +void LammpsGui::update_variables() +{ + const auto doc = ui->textEdit->toPlainText().split('\n'); + QStringList known; + QRegularExpression indexvar("^\\s*variable\\s+(\\w+)\\s+index\\s+(.*)"); + QRegularExpression anyvar("^\\s*variable\\s+(\\w+)\\s+(\\w+)\\s+(.*)"); + QRegularExpression usevar("(\\$(\\w)|\\${(\\w+)})"); + QRegularExpression refvar("v_(\\w+)"); + + // forget previously listed variables + variables.clear(); + + for (const auto &line : doc) { + + // first find variable definitions. + // index variables are special since they can be overridden from the command line + auto index = indexvar.match(line); + auto any = anyvar.match(line); + + if (index.hasMatch()) { + if (index.lastCapturedIndex() >= 2) { + auto name = index.captured(1); + if (!known.contains(name)) { + variables.append(qMakePair(name, index.captured(2))); + known.append(name); + } + } + } else if (any.hasMatch()) { + if (any.lastCapturedIndex() >= 3) { + auto name = any.captured(1); + if (!known.contains(name)) known.append(name); + } + } + + // now split line into words and search for use of undefined variables + auto words = line.split(' '); + for (const auto &word : words) { + auto use = usevar.match(word); + auto ref = refvar.match(word); + if (use.hasMatch()) { + auto name = use.captured(use.lastCapturedIndex()); + if (!known.contains(name)) { + known.append(name); + variables.append(qMakePair(name, QString())); + } + } + if (ref.hasMatch()) { + auto name = ref.captured(use.lastCapturedIndex()); + if (!known.contains(name)) known.append(name); + } + } + } +} + // open file and switch CWD to path of file void LammpsGui::open_file(const QString &fileName) { @@ -250,6 +487,8 @@ void LammpsGui::open_file(const QString &fileName) current_dir = path.absolutePath(); QFile file(path.absoluteFilePath()); + update_recents(path.absoluteFilePath()); + QDir::setCurrent(current_dir); if (!file.open(QIODevice::ReadOnly | QFile::Text)) { QMessageBox::warning(this, "Warning", @@ -265,20 +504,25 @@ void LammpsGui::open_file(const QString &fileName) ui->textEdit->document()->setModified(false); file.close(); dirstatus->setText(QString(" Directory: ") + current_dir); + + update_variables(); } void LammpsGui::write_file(const QString &fileName) { - QFile file(fileName); - QFileInfo path(file); + QFileInfo path(fileName); current_file = path.fileName(); current_dir = path.absolutePath(); + QFile file(path.absoluteFilePath()); if (!file.open(QIODevice::WriteOnly | QFile::Text)) { QMessageBox::warning(this, "Warning", "Cannot save file: " + file.errorString()); return; } setWindowTitle(QString("LAMMPS-GUI - " + current_file)); + + update_recents(path.absoluteFilePath()); + QTextStream out(&file); QString text = ui->textEdit->toPlainText(); out << text; @@ -306,6 +550,7 @@ void LammpsGui::save_as() void LammpsGui::quit() { lammps.close(); + lammpsstatus->hide(); lammps.finalize(); if (ui->textEdit->document()->isModified()) { @@ -330,6 +575,14 @@ void LammpsGui::quit() break; } } + + // store some global settings + QSettings settings; + if (!isMaximized()) { + settings.setValue("mainx", width()); + settings.setValue("mainy", height()); + } + settings.sync(); QCoreApplication::quit(); } @@ -374,6 +627,7 @@ void LammpsGui::logupdate() double t_elapsed, t_remain, t_total; int completed = 1000; + // estimate completion percentage if (lammps.is_running()) { t_elapsed = lammps.get_thermo("cpu"); t_remain = lammps.get_thermo("cpuremain"); @@ -390,6 +644,65 @@ void LammpsGui::logupdate() logwindow->textCursor().deleteChar(); } } + + // extract cached thermo data + if (chartwindow) { + // thermo data is not yet valid during setup + void *ptr = lammps.last_thermo("setup", 0); + if (ptr && *(int *)ptr) return; + + ptr = lammps.last_thermo("step", 0); + if (ptr) { + int step = 0; + if (lammps.extract_setting("bigint") == 4) + step = *(int *)ptr; + else + step = (int)*(int64_t *)ptr; + int ncols = *(int *)lammps.last_thermo("num", 0); + + // check if the column assignment has changed + // if yes, delete charts and start over + if (chartwindow->num_charts() > 0) { + int count = 0; + bool do_reset = false; + if (step < chartwindow->get_step()) do_reset = true; + for (int i = 0, idx = 0; i < ncols; ++i) { + QString label = (const char *)lammps.last_thermo("keyword", i); + // no need to store the timestep column + if (label == "Step") continue; + if (!chartwindow->has_title(label, idx)) { + do_reset = true; + } else { + ++count; + } + ++idx; + } + if (chartwindow->num_charts() != count) do_reset = true; + if (do_reset) chartwindow->reset_charts(); + } + + if (chartwindow->num_charts() == 0) { + for (int i = 0; i < ncols; ++i) { + QString label = (const char *)lammps.last_thermo("keyword", i); + // no need to store the timestep column + if (label == "Step") continue; + chartwindow->add_chart(label, i); + } + } + + for (int i = 0; i < ncols; ++i) { + int datatype = *(int *)lammps.last_thermo("type", i); + double data; + if (datatype == 0) // int + data = *(int *)lammps.last_thermo("data", i); + else if (datatype == 2) // double + data = *(double *)lammps.last_thermo("data", i); + else if (datatype == 4) // bigint + data = (double)*(int64_t *)lammps.last_thermo("data", i); + chartwindow->add_data(step, data, i); + } + } + } } void LammpsGui::modified() @@ -404,7 +717,7 @@ void LammpsGui::modified() void LammpsGui::run_done() { - logupdater->stop(); + if (logupdater) logupdater->stop(); delete logupdater; logupdater = nullptr; progress->setValue(1000); @@ -414,6 +727,35 @@ void LammpsGui::run_done() logwindow->insertPlainText(log.c_str()); logwindow->moveCursor(QTextCursor::End); + if (chartwindow) { + void *ptr = lammps.last_thermo("step", 0); + if (ptr) { + int step = 0; + if (lammps.extract_setting("bigint") == 4) + step = *(int *)ptr; + else + step = (int)*(int64_t *)ptr; + int ncols = *(int *)lammps.last_thermo("num", 0); + for (int i = 0; i < ncols; ++i) { + if (chartwindow->num_charts() == 0) { + QString label = (const char *)lammps.last_thermo("keyword", i); + // no need to store the timestep column + if (label == "Step") continue; + chartwindow->add_chart(label, i); + } + int datatype = *(int *)lammps.last_thermo("type", i); + double data; + if (datatype == 0) // int + data = *(int *)lammps.last_thermo("data", i); + else if (datatype == 2) // double + data = *(double *)lammps.last_thermo("data", i); + else if (datatype == 4) // bigint + data = (double)*(int64_t *)lammps.last_thermo("data", i); + chartwindow->add_data(step, data, i); + } + } + } + bool success = true; constexpr int BUFLEN = 1024; char errorbuf[BUFLEN]; @@ -436,12 +778,24 @@ void LammpsGui::run_done() void LammpsGui::run_buffer() { + if (lammps.is_running()) { + QMessageBox::warning(this, "LAMMPS GUI Error", + "Must stop current run before starting a new run"); + return; + } QSettings settings; progress->setValue(0); dirstatus->hide(); progress->show(); int nthreads = settings.value("nthreads", 1).toInt(); - status->setText(QString("Running LAMMPS with %1 thread(s)...").arg(nthreads)); + int accel = settings.value("accelerator", AcceleratorTab::None).toInt(); + if ((accel != AcceleratorTab::OpenMP) && (accel != AcceleratorTab::Intel) && + (accel != AcceleratorTab::Kokkos)) + nthreads = 1; + if (nthreads > 1) + status->setText(QString("Running LAMMPS with %1 thread(s)...").arg(nthreads)); + else + status->setText(QString("Running LAMMPS ...")); status->repaint(); start_lammps(); if (!lammps.is_open()) return; @@ -458,34 +812,51 @@ void LammpsGui::run_buffer() connect(runner, &LammpsRunner::finished, runner, &QObject::deleteLater); runner->start(); - logwindow = new QPlainTextEdit(); + // if configured, delete old log window before opening new one + if (settings.value("logreplace", false).toBool()) delete logwindow; + logwindow = new LogWindow(); logwindow->setReadOnly(true); logwindow->setCenterOnScroll(true); logwindow->moveCursor(QTextCursor::End); logwindow->setWindowTitle("LAMMPS-GUI - Output from running LAMMPS on buffer - " + current_file); logwindow->setWindowIcon(QIcon(":/lammps-icon-128x128.png")); -#if (__APPLE__) - QFont text_font("Menlo"); -#else - QFont text_font(":/Monospace.ttf"); -#endif - text_font.setStyleHint(QFont::TypeWriter); + QFont text_font; + text_font.fromString(settings.value("textfont", text_font.toString()).toString()); logwindow->document()->setDefaultFont(text_font); - logwindow->setLineWrapMode(QPlainTextEdit::NoWrap); - logwindow->setMinimumSize(600, 400); + logwindow->setLineWrapMode(LogWindow::NoWrap); + logwindow->setMinimumSize(400, 300); QShortcut *shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), logwindow); - QObject::connect(shortcut, &QShortcut::activated, logwindow, &QPlainTextEdit::close); + QObject::connect(shortcut, &QShortcut::activated, logwindow, &LogWindow::close); shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Slash), logwindow); QObject::connect(shortcut, &QShortcut::activated, this, &LammpsGui::stop_run); - logwindow->show(); + if (settings.value("viewlog", true).toBool()) + logwindow->show(); + else + logwindow->hide(); + + // if configured, delete old log window before opening new one + if (settings.value("chartreplace", false).toBool()) delete chartwindow; + chartwindow = new ChartWindow(current_file); + chartwindow->setWindowTitle("LAMMPS-GUI - Thermo charts from running LAMMPS on buffer - " + + current_file); + chartwindow->setWindowIcon(QIcon(":/lammps-icon-128x128.png")); + chartwindow->setMinimumSize(400, 300); + shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), chartwindow); + QObject::connect(shortcut, &QShortcut::activated, chartwindow, &ChartWindow::close); + shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Slash), chartwindow); + QObject::connect(shortcut, &QShortcut::activated, this, &LammpsGui::stop_run); + if (settings.value("viewchart", true).toBool()) + chartwindow->show(); + else + chartwindow->hide(); logupdater = new QTimer(this); connect(logupdater, &QTimer::timeout, this, &LammpsGui::logupdate); - logupdater->start(1000); + logupdater->start(250); } -void LammpsGui::view_image() +void LammpsGui::render_image() { // LAMMPS is not re-entrant, so we can only query LAMMPS when it is not running if (!lammps.is_running()) { @@ -495,33 +866,9 @@ void LammpsGui::view_image() "Cannot create snapshot image without a system box"); return; } - - QSettings settings; - QString dumpcmd = "write_dump all image "; - QString dumpfile = settings.value("tempdir").toString(); -#if defined(_WIN32) - dumpfile += '\\'; -#else - dumpfile += '/'; -#endif - dumpfile += current_file + ".ppm"; - dumpcmd += dumpfile; - - settings.beginGroup("snapshot"); - dumpcmd += blank + settings.value("color", "type").toString(); - dumpcmd += blank + settings.value("diameter", "type").toString(); - dumpcmd += QString(" size ") + settings.value("xsize", "800").toString(); - dumpcmd += blank + settings.value("ysize", "600").toString(); - dumpcmd += QString(" zoom ") + settings.value("zoom", "1.0").toString(); - settings.endGroup(); - - lammps.command(dumpcmd.toLocal8Bit()); - imagewindow = new ImageViewer(dumpfile); -#if defined(_WIN32) - _unlink(dumpfile.toLocal8Bit()); -#else - unlink(dumpfile.toLocal8Bit()); -#endif + // if configured, delete old image window before opening new one + if (QSettings().value("imagereplace", false).toBool()) delete imagewindow; + imagewindow = new ImageViewer(current_file, &lammps); } else { QMessageBox::warning(this, "ImageViewer Error", "Cannot create snapshot image while LAMMPS is running"); @@ -535,17 +882,56 @@ void LammpsGui::clear() ui->textEdit->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor); } +void LammpsGui::view_chart() +{ + QSettings settings; + if (chartwindow) { + if (chartwindow->isVisible()) { + chartwindow->hide(); + settings.setValue("viewchart", false); + } else { + chartwindow->show(); + settings.setValue("viewchart", true); + } + } +} + +void LammpsGui::view_log() +{ + QSettings settings; + if (logwindow) { + if (logwindow->isVisible()) { + logwindow->hide(); + settings.setValue("viewlog", false); + } else { + logwindow->show(); + settings.setValue("viewlog", true); + } + } +} + +void LammpsGui::view_image() +{ + if (imagewindow) { + if (imagewindow->isVisible()) { + imagewindow->hide(); + } else { + imagewindow->show(); + } + } +} + void LammpsGui::about() { std::string version = "This is LAMMPS-GUI version " LAMMPS_GUI_VERSION; if (lammps.has_plugin()) { - version += " - LAMMPS linked dynamically"; + version += " - LAMMPS library loaded as plugin"; if (!plugin_path.empty()) { version += " from file "; version += plugin_path; } } else { - version += " - LAMMPS linked statically"; + version += " - LAMMPS library linked to executable"; } std::string info = "LAMMPS is currently running. LAMMPS config info not available."; @@ -566,13 +952,15 @@ void LammpsGui::about() msg.setText(version.c_str()); msg.setInformativeText(info.c_str()); msg.setIconPixmap(QPixmap(":/lammps-icon-128x128.png").scaled(64, 64)); - msg.setStandardButtons(QMessageBox::Ok); + msg.setStandardButtons(QMessageBox::Close); QFont font; - font.setFixedPitch(true); - font.setStyleHint(QFont::TypeWriter); - font.setFamily("Arial"); - font.setPointSize(8); + font.setPointSizeF(font.pointSizeF() * 0.75); msg.setFont(font); + + auto *minwidth = new QSpacerItem(700, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); + QGridLayout *layout = (QGridLayout *)msg.layout(); + layout->addItem(minwidth, layout->rowCount(), 0, 1, layout->columnCount()); + msg.exec(); } @@ -581,38 +969,44 @@ void LammpsGui::help() QMessageBox msg; msg.setWindowTitle("LAMMPS-GUI Quick Help"); msg.setText("
This is LAMMPS-GUI version " LAMMPS_GUI_VERSION "
"); - msg.setInformativeText("Overview" - "
LAMMPS GUI is a graphical text editor that is " - "linked to the LAMMPS library and thus can run LAMMPS directly using " - "the contents of the text buffer as input through the LAMMPS C-library " - "interface. This makes it convenient to use for beginners and during " - "tutorials


" - "Features" - "
The main window of the LAMMPS GUI is a text " - "editor window with syntax highlighting. The output of a LAMMPS run is " - "captured and displayed in a log window. The log window is updated " - "regularly during the run, as is a progress bar in the main window. " - "After the simulation is finished, an image of the simulated system " - "can be created and shown (and saved) in image viewer window. Ongoing " - "runs can be stopped at the next run iteration.

" - "
When opening a file, the editor will determine " - "the directory where the input file resides and switch its current " - "working directory to that same folder. Many LAMMPS inputs contain " - "commands that read other files, typically from the folder as the " - "input file. The GUI will show its current working directory. " - "In addition to using the menu, the editor window also receive files " - "as the first command line argument or via drag-n-drop from a " - "graphical file manager GUI or a desktop environment.

" - "
Almost all commands are accessible via hotkeys. " - "Which those hotkeys are, is shown next to the entries in the menus. " - "Log and image viewer windows can be closed with CTRL-W (or Command-W " - "on macOS).

" - "
The 'About LAMMPS' dialog will show the " - "LAMMPS version and the features included into the LAMMPS library " - "linked to the LAMMPS GUI.

" - "Due to its nature as a graphical application, it is not " - "possible to use the LAMMPS GUI in parallel with MPI, but OpenMP " - "multi-threading is available.
"); + msg.setInformativeText("

LAMMPS GUI is a graphical text editor that is linked to the LAMMPS " + "library and thus can run LAMMPS directly using the contents of the " + "text buffer as input through the LAMMPS C-library interface.

" + "

The main window of the LAMMPS GUI is a text editor window with " + "LAMMPS specific syntax highlighting. When typing Ctrl-Enter " + "or clicking on 'Run LAMMMPS' in the 'Run' menu, LAMMPS will be run " + "with the contents of editor buffer as input. The output of the LAMMPS " + "run is captured and displayed in a log window. The thermodynamic data " + "is displayed in a chart window. Both are updated regularly during the " + "run, as is a progress bar in the main window. The running simulation " + "can be stopped cleanly by typing Ctrl-/ or by clicking on " + "'Stop LAMMPS' in the 'Run' menu. After the simulation is finished " + "or stopped, an image of the simulated system can be shown in an image " + "viewer window by typing Ctrl-i or by clicking on 'View Image' " + "in the 'Run' menu. Multiple image settings can be changed through the " + "buttons in the menu bar and the image will be re-renderd.

" + "

When opening a file, the editor will determine the directory " + "where the input file resides and switch its current working directory " + "to that same folder and thus enabling the run to read other files in " + "that folder, e.g. a data file .The GUI will show its current working " + "directory in the status bar. In addition to using the menu, the " + "editor window can also receive files as the first command line " + "argument or via drag-n-drop from a graphical file manager or a " + "desktop environment.

" + "

Almost all commands are accessible via hotkeys. Which those " + "hotkeys are, is typically shown next to their entries in the menus. " + "In addition, the documentation for the command in the current line " + "can be viewed by typing Ctrl-? or by choosing the respective " + "entry in the context menu, available by right-clicking the mouse. " + "Log, chart, and image windows can be closed with Ctrl-W, the " + "main window with Ctrl-Q.

" + "

The 'About LAMMPS' dialog will show the LAMMPS version and the " + "features included into the LAMMPS library linked to the LAMMPS GUI. " + "A number of settings can be adjusted in the 'Preferences' dialog (in " + "the 'Edit' menu or from Ctrl-P) which includes selecting " + "accelerator packages and number of OpenMP threads. Due to its nature " + "as a graphical application, it is not possible to use the " + "LAMMPS GUI in parallel with MPI.

"); msg.setIconPixmap(QPixmap(":/lammps-icon-128x128.png").scaled(64, 64)); msg.setStandardButtons(QMessageBox::Close); msg.exec(); @@ -623,6 +1017,11 @@ void LammpsGui::manual() QDesktopServices::openUrl(QUrl("https://docs.lammps.org/")); } +void LammpsGui::howto() +{ + QDesktopServices::openUrl(QUrl("https://docs.lammps.org/Howto_lammps_gui.html")); +} + void LammpsGui::defaults() { QSettings settings; @@ -630,13 +1029,38 @@ void LammpsGui::defaults() settings.sync(); } +void LammpsGui::edit_variables() +{ + QList> newvars = variables; + SetVariables vars(newvars); + if (vars.exec() == QDialog::Accepted) { + variables = newvars; + lammps.close(); + lammpsstatus->hide(); + } +} + void LammpsGui::preferences() { + QSettings settings; + int oldthreads = settings.value("nthreads", 1).toInt(); + int oldaccel = settings.value("accelerator", AcceleratorTab::None).toInt(); + int oldecho = settings.value("echo", 0).toInt(); + int oldcite = settings.value("cite", 0).toInt(); + Preferences prefs(&lammps); if (prefs.exec() == QDialog::Accepted) { - // must delete LAMMPS instance after setting may be changed so we can apply different - // suffixes - lammps.close(); + // must delete LAMMPS instance after preferences have changed that require + // using different command line flags when creating the LAMMPS instance like + // suffixes or package commands + if ((oldaccel != settings.value("accelerator", AcceleratorTab::None).toInt()) || + (oldthreads != settings.value("nthreads", 1).toInt()) || + (oldecho != settings.value("echo", 0).toInt()) || + (oldcite != settings.value("cite", 0).toInt())) { + lammps.close(); + lammpsstatus->hide(); + } + if (imagewindow) imagewindow->createImage(); } } @@ -685,9 +1109,22 @@ void LammpsGui::start_lammps() lammps_args.push_back(mystrdup("screen")); } + // add variables, if defined + for (auto &var : variables) { + QString name = var.first; + QString value = var.second; + if (!name.isEmpty() && !value.isEmpty()) { + lammps_args.push_back(mystrdup("-var")); + lammps_args.push_back(mystrdup(name.toStdString())); + for (const auto &v : value.split(' ')) + lammps_args.push_back(mystrdup(v.toStdString())); + } + } + char **args = lammps_args.data(); int narg = lammps_args.size(); lammps.open(narg, args); + lammpsstatus->show(); // delete additional arguments again (3 were there initially while (lammps_args.size() > initial_narg) { diff --git a/tools/lammps-gui/lammpsgui.h b/tools/lammps-gui/lammpsgui.h index 78e518609e..5fed14d743 100644 --- a/tools/lammps-gui/lammpsgui.h +++ b/tools/lammps-gui/lammpsgui.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -24,6 +25,8 @@ // forward declarations +class GeneralTab; + QT_BEGIN_NAMESPACE namespace Ui { class LammpsGui; @@ -39,11 +42,13 @@ class Highlighter; class StdCapture; class Preferences; class ImageViewer; +class ChartWindow; class LammpsGui : public QMainWindow { Q_OBJECT friend class CodeEditor; + friend class GeneralTab; public: LammpsGui(QWidget *parent = nullptr, const char *filename = nullptr); @@ -52,12 +57,16 @@ public: protected: void open_file(const QString &filename); void write_file(const QString &filename); + void update_recents(const QString &filename = ""); + void update_variables(); void start_lammps(); void run_done(); private slots: void new_document(); void open(); + void open_recent(); + void start_exe(); void save(); void save_as(); void quit(); @@ -69,33 +78,44 @@ private slots: void clear(); void run_buffer(); void stop_run(); + void edit_variables(); + void render_image(); void view_image(); + void view_chart(); + void view_log(); void about(); void help(); void manual(); + void howto(); void logupdate(); void modified(); void preferences(); void defaults(); -private: +protected: Ui::LammpsGui *ui; + +private: Highlighter *highlighter; StdCapture *capturer; QLabel *status; QPlainTextEdit *logwindow; ImageViewer *imagewindow; + ChartWindow *chartwindow; QTimer *logupdater; QLabel *dirstatus; QProgressBar *progress; Preferences *prefdialog; + QLabel *lammpsstatus; QString current_file; QString current_dir; + QList recent; + QList> variables; + LammpsWrapper lammps; std::string plugin_path; bool is_running; - QList recent_files; std::vector lammps_args; }; #endif // LAMMPSGUI_H diff --git a/tools/lammps-gui/lammpsgui.qrc b/tools/lammps-gui/lammpsgui.qrc index 391ebcc5d1..88526719f0 100644 --- a/tools/lammps-gui/lammpsgui.qrc +++ b/tools/lammps-gui/lammpsgui.qrc @@ -1,6 +1,47 @@ - - - DejaVuSansMono.ttf - lammps-icon-128x128.png - + + + lammps-icon-128x128.png + help_index.table + system-help.png + help-browser.png + gtk-zoom-in.png + gtk-zoom-out.png + gtk-zoom-fit.png + edit-delete.png + object-rotate-right.png + object-rotate-left.png + gtk-go-up.png + gtk-go-down.png + document-save-as.png + document-open-recent.png + document-open.png + document-new.png + edit-undo.png + edit-redo.png + edit-paste.png + edit-cut.png + edit-copy.png + application-exit.png + utilities-terminal.png + x-office-drawing.png + document-save.png + document-revert.png + preferences-desktop.png + preferences-desktop-personal.png + preferences-desktop-font.png + help-faq.png + help-about.png + emblem-photos.png + process-stop.png + emblem-default.png + window-close.png + application-plot.png + application-calc.png + system-box.png + axes-img.png + hd-img.png + antialias.png + ovito.png + vmd.png + diff --git a/tools/lammps-gui/lammpsgui.ui b/tools/lammps-gui/lammpsgui.ui index cc8f6fad50..6bda61dbb4 100644 --- a/tools/lammps-gui/lammpsgui.ui +++ b/tools/lammps-gui/lammpsgui.ui @@ -13,19 +13,13 @@ LammpsGui - - - - - - true - - - true - - - - + + + true + + + true + @@ -33,7 +27,7 @@ 0 0 600 - 23 + 24 @@ -41,8 +35,15 @@ &File + + + + + + + @@ -69,7 +70,11 @@ + + + + @@ -77,219 +82,162 @@ + + + + &View + + + + + + - - .. + &New - - Start a New Input File - - - Start a New Input File - Ctrl+N - - .. + &Open - - Open an Input File - - - Open an Input File - Ctrl+O - - .. + &Save - - Save Input File - - - Save Input File - Ctrl+S - - .. + Save &As - - Save Input File As... - - - Save Input File As... - Ctrl+Shift+S - - .. + &Quit - - Quit LAMMPS-GUI - - - Quit LAMMPS-GUI - Ctrl+Q - - .. + Cu&t - - Cut Selected Text to Clipboard - Ctrl+X - - .. + &Copy - - Copy Selected Text to Clipboard - Ctrl+C - - .. + &Paste - - Paste Text from Clipboard - Ctrl+V - - .. + &Undo - - Undo Edit - Ctrl+Z - - .. + &Redo - - Redo Edit - Ctrl+Shift+Z - - .. + &Run LAMMPS - - Run LAMMPS with Input - Ctrl+Return - - .. + &Stop LAMMPS - - Stop LAMMPS Process - Ctrl+/ - - .. + - &View Snapshot - - - View Snapshot of current LAMMPS state + View &Image Ctrl+I @@ -297,35 +245,29 @@ - - .. + - &About LAMMPS-GUI + &About LAMMPS - - About LAMMPS-GUI + + Ctrl+Shift+A - - .. + Quick &Help - - Quick Help - - Ctrl+Shift+/ + Ctrl+Shift+H - - .. + Pre&ferences... @@ -336,21 +278,140 @@ - - .. + LAMMPS &Manual + + Ctrl+Shift+M + - + Reset to &Defaults + + + + + + View in &OVITO + + + Ctrl+Shift+O + + + + + + + + View in VM&D + + + Ctrl+Shift+D + + + + + + + + &Log Window + + + Ctrl+Shift+L + + + + + + + + &Chart Window + + + Ctrl+Shift+C + + + + + + + + &1. + + + + + + + + &2. + + + + + + + + &3. + + + + + + + + &4. + + + + + + + + &5. + + + + + + + + &Image Window + + + Ctrl+Shift+I + + + + + + + + Set &Variables... + + + Ctrl+Shift+V + + + + + + + + LAMMPS GUI Howto + + + Ctrl+Shift+G + + diff --git a/tools/lammps-gui/lammpsrunner.h b/tools/lammps-gui/lammpsrunner.h index a8cd6a1502..72ad52986e 100644 --- a/tools/lammps-gui/lammpsrunner.h +++ b/tools/lammps-gui/lammpsrunner.h @@ -27,17 +27,17 @@ public: // execute LAMMPS in runner thread void run() override { - lammps->command("clear"); lammps->commands_string(input); delete[] input; emit resultReady(); } - // transfer info to worker thread + // transfer info to worker thread and reset LAMMPS instance void setup_run(LammpsWrapper *_lammps, const char *_input) { lammps = _lammps; input = _input; + lammps->command("clear"); } signals: diff --git a/tools/lammps-gui/lammpswrapper.cpp b/tools/lammps-gui/lammpswrapper.cpp index 3292217d77..ff5a4f2213 100644 --- a/tools/lammps-gui/lammpswrapper.cpp +++ b/tools/lammps-gui/lammpswrapper.cpp @@ -23,13 +23,13 @@ LammpsWrapper::LammpsWrapper() : lammps_handle(nullptr), plugin_handle(nullptr) void LammpsWrapper::open(int narg, char **args) { - if (!lammps_handle) { + // since there may only be one LAMMPS instance in LAMMPS GUI we don't open a second + if (lammps_handle) return; #if defined(LAMMPS_GUI_USE_PLUGIN) - lammps_handle = ((liblammpsplugin_t *)plugin_handle)->open_no_mpi(narg, args, nullptr); + lammps_handle = ((liblammpsplugin_t *)plugin_handle)->open_no_mpi(narg, args, nullptr); #else - lammps_handle = lammps_open_no_mpi(narg, args, nullptr); + lammps_handle = lammps_open_no_mpi(narg, args, nullptr); #endif - } } int LammpsWrapper::extract_setting(const char *keyword) @@ -39,7 +39,33 @@ int LammpsWrapper::extract_setting(const char *keyword) #if defined(LAMMPS_GUI_USE_PLUGIN) val = ((liblammpsplugin_t *)plugin_handle)->extract_setting(lammps_handle, keyword); #else - val = lammps_extract_setting(lammps_handle, keyword); + val = lammps_extract_setting(lammps_handle, keyword); +#endif + } + return val; +} + +int LammpsWrapper::id_count(const char *keyword) +{ + int val = 0; + if (lammps_handle) { +#if defined(LAMMPS_GUI_USE_PLUGIN) + val = ((liblammpsplugin_t *)plugin_handle)->id_count(lammps_handle, keyword); +#else + val = lammps_id_count(lammps_handle, keyword); +#endif + } + return val; +} + +int LammpsWrapper::id_name(const char *keyword, int idx, char *buf, int len) +{ + int val = 0; + if (lammps_handle) { +#if defined(LAMMPS_GUI_USE_PLUGIN) + val = ((liblammpsplugin_t *)plugin_handle)->id_name(lammps_handle, keyword, idx, buf, len); +#else + val = lammps_id_name(lammps_handle, keyword, idx, buf, len); #endif } return val; @@ -52,12 +78,25 @@ double LammpsWrapper::get_thermo(const char *keyword) #if defined(LAMMPS_GUI_USE_PLUGIN) val = ((liblammpsplugin_t *)plugin_handle)->get_thermo(lammps_handle, keyword); #else - val = lammps_get_thermo(lammps_handle, keyword); + val = lammps_get_thermo(lammps_handle, keyword); #endif } return val; } +void *LammpsWrapper::last_thermo(const char *keyword, int index) +{ + void *ptr = nullptr; + if (lammps_handle) { +#if defined(LAMMPS_GUI_USE_PLUGIN) + ptr = ((liblammpsplugin_t *)plugin_handle)->last_thermo(lammps_handle, keyword, index); +#else + ptr = lammps_last_thermo(lammps_handle, keyword, index); +#endif + } + return ptr; +} + bool LammpsWrapper::is_running() { int val = 0; @@ -65,7 +104,7 @@ bool LammpsWrapper::is_running() #if defined(LAMMPS_GUI_USE_PLUGIN) val = ((liblammpsplugin_t *)plugin_handle)->is_running(lammps_handle); #else - val = lammps_is_running(lammps_handle); + val = lammps_is_running(lammps_handle); #endif } return val != 0; @@ -103,6 +142,7 @@ bool LammpsWrapper::has_error() const #endif } +// may be called with null handle. returns global error then. int LammpsWrapper::get_last_error_message(char *buf, int buflen) { #if defined(LAMMPS_GUI_USE_PLUGIN) @@ -115,9 +155,9 @@ int LammpsWrapper::get_last_error_message(char *buf, int buflen) void LammpsWrapper::force_timeout() { #if defined(LAMMPS_GUI_USE_PLUGIN) - ((liblammpsplugin_t *)plugin_handle)->force_timeout(lammps_handle); + if (lammps_handle) ((liblammpsplugin_t *)plugin_handle)->force_timeout(lammps_handle); #else - lammps_force_timeout(lammps_handle); + if (lammps_handle) lammps_force_timeout(lammps_handle); #endif } @@ -188,7 +228,10 @@ bool LammpsWrapper::has_plugin() const bool LammpsWrapper::load_lib(const char *libfile) { - if (plugin_handle) liblammpsplugin_release((liblammpsplugin_t *)plugin_handle); + if (plugin_handle) { + close(); + liblammpsplugin_release((liblammpsplugin_t *)plugin_handle); + } plugin_handle = liblammpsplugin_load(libfile); if (!plugin_handle) return false; if (((liblammpsplugin_t *)plugin_handle)->abiversion != LAMMPSPLUGIN_ABI_VERSION) { diff --git a/tools/lammps-gui/lammpswrapper.h b/tools/lammps-gui/lammpswrapper.h index db8a0ba3d6..064e784981 100644 --- a/tools/lammps-gui/lammpswrapper.h +++ b/tools/lammps-gui/lammpswrapper.h @@ -29,7 +29,11 @@ public: void force_timeout(); int extract_setting(const char *keyword); + int id_count(const char *idtype); + int id_name(const char *idtype, int idx, char *buf, int buflen); + double get_thermo(const char *keyword); + void *last_thermo(const char *keyword, int idx); bool is_open() const { return lammps_handle != nullptr; } bool is_running(); bool has_error() const; diff --git a/tools/lammps-gui/logwindow.cpp b/tools/lammps-gui/logwindow.cpp new file mode 100644 index 0000000000..7091b34f43 --- /dev/null +++ b/tools/lammps-gui/logwindow.cpp @@ -0,0 +1,35 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#include "logwindow.h" +#include + +LogWindow::LogWindow(QWidget *parent) : QPlainTextEdit(parent) +{ + QSettings settings; + resize(settings.value("logx", 500).toInt(), settings.value("logy", 320).toInt()); +} + +void LogWindow::closeEvent(QCloseEvent *event) +{ + QSettings settings; + if (!isMaximized()) { + settings.setValue("logx", width()); + settings.setValue("logy", height()); + } + QPlainTextEdit::closeEvent(event); +} + +// Local Variables: +// c-basic-offset: 4 +// End: diff --git a/tools/lammps-gui/logwindow.h b/tools/lammps-gui/logwindow.h new file mode 100644 index 0000000000..8807ef5cee --- /dev/null +++ b/tools/lammps-gui/logwindow.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifndef LOGWINDOW_H +#define LOGWINDOW_H + +#include + +class LogWindow : public QPlainTextEdit { + Q_OBJECT + +public: + LogWindow(QWidget *parent = nullptr); + +protected: + void closeEvent(QCloseEvent *event) override; +}; + +#endif +// Local Variables: +// c-basic-offset: 4 +// End: diff --git a/tools/lammps-gui/object-rotate-left.png b/tools/lammps-gui/object-rotate-left.png new file mode 100644 index 0000000000..a754bf560a Binary files /dev/null and b/tools/lammps-gui/object-rotate-left.png differ diff --git a/tools/lammps-gui/object-rotate-right.png b/tools/lammps-gui/object-rotate-right.png new file mode 100644 index 0000000000..2103228dd9 Binary files /dev/null and b/tools/lammps-gui/object-rotate-right.png differ diff --git a/tools/lammps-gui/ovito.png b/tools/lammps-gui/ovito.png new file mode 100644 index 0000000000..7b34660cf3 Binary files /dev/null and b/tools/lammps-gui/ovito.png differ diff --git a/tools/lammps-gui/preferences-desktop-font.png b/tools/lammps-gui/preferences-desktop-font.png new file mode 100644 index 0000000000..383eaa6ca1 Binary files /dev/null and b/tools/lammps-gui/preferences-desktop-font.png differ diff --git a/tools/lammps-gui/preferences-desktop-personal.png b/tools/lammps-gui/preferences-desktop-personal.png new file mode 100644 index 0000000000..dd4718435d Binary files /dev/null and b/tools/lammps-gui/preferences-desktop-personal.png differ diff --git a/tools/lammps-gui/preferences-desktop.png b/tools/lammps-gui/preferences-desktop.png new file mode 100644 index 0000000000..208c6ef101 Binary files /dev/null and b/tools/lammps-gui/preferences-desktop.png differ diff --git a/tools/lammps-gui/preferences.cpp b/tools/lammps-gui/preferences.cpp index 628a50a11a..4858592dc3 100644 --- a/tools/lammps-gui/preferences.cpp +++ b/tools/lammps-gui/preferences.cpp @@ -13,16 +13,22 @@ #include "preferences.h" +#include "lammpsgui.h" #include "lammpswrapper.h" +#include "ui_lammpsgui.h" +#include #include +#include #include #include #include #include #include +#include #include #include +#include #include #include #include @@ -38,10 +44,28 @@ #include #endif +#if defined(_WIN32) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#define execl(exe, arg0, arg1) _execl(exe, arg0, arg1) +#else +#include +#endif + +// duplicate string +static char *mystrdup(const std::string &text) +{ + auto tmp = new char[text.size() + 1]; + memcpy(tmp, text.c_str(), text.size() + 1); + return tmp; +} + Preferences::Preferences(LammpsWrapper *_lammps, QWidget *parent) : QDialog(parent), tabWidget(new QTabWidget), buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel)), - settings(new QSettings), lammps(_lammps) + settings(new QSettings), lammps(_lammps), need_relaunch(false) { tabWidget->addTab(new GeneralTab(settings, lammps), "&General Settings"); tabWidget->addTab(new AcceleratorTab(settings, lammps), "&Accelerators"); @@ -94,7 +118,7 @@ void Preferences::accept() if (field) if (field->hasAcceptableInput()) settings->setValue("nthreads", field->text()); - // store image width, height, and zoom + // store image width, height, zoom, and rendering settings settings->beginGroup("snapshot"); field = tabWidget->findChild("xsize"); @@ -106,14 +130,46 @@ void Preferences::accept() field = tabWidget->findChild("zoom"); if (field) if (field->hasAcceptableInput()) settings->setValue("zoom", field->text()); + QCheckBox *box = tabWidget->findChild("anti"); + if (box) settings->setValue("antialias", box->isChecked()); + box = tabWidget->findChild("ssao"); + if (box) settings->setValue("ssao", box->isChecked()); + box = tabWidget->findChild("box"); + if (box) settings->setValue("box", box->isChecked()); + box = tabWidget->findChild("axes"); + if (box) settings->setValue("axes", box->isChecked()); + QComboBox *combo = tabWidget->findChild("background"); + if (combo) settings->setValue("background", combo->currentText()); + combo = tabWidget->findChild("boxcolor"); + if (combo) settings->setValue("boxcolor", combo->currentText()); settings->endGroup(); // general settings - QCheckBox *box = tabWidget->findChild("echo"); - if (box) settings->setValue("echo", box->isChecked() ? "1" : "0"); + box = tabWidget->findChild("echo"); + if (box) settings->setValue("echo", box->isChecked()); box = tabWidget->findChild("cite"); - if (box) settings->setValue("cite", box->isChecked() ? "1" : "0"); + if (box) settings->setValue("cite", box->isChecked()); + box = tabWidget->findChild("logreplace"); + if (box) settings->setValue("logreplace", box->isChecked()); + box = tabWidget->findChild("chartreplace"); + if (box) settings->setValue("chartreplace", box->isChecked()); + box = tabWidget->findChild("imagereplace"); + if (box) settings->setValue("imagereplace", box->isChecked()); + box = tabWidget->findChild("viewlog"); + if (box) settings->setValue("viewlog", box->isChecked()); + box = tabWidget->findChild("viewchart"); + if (box) settings->setValue("viewchart", box->isChecked()); + if (need_relaunch) { + QMessageBox msg(QMessageBox::Information, QString("Relaunching LAMMPS-GUI"), + QString("LAMMPS library plugin path was changed.\n" + "LAMMPS-GUI must be relaunched."), + QMessageBox::Ok); + msg.exec(); + const char *path = mystrdup(QCoreApplication::applicationFilePath().toStdString()); + const char *arg0 = mystrdup(QCoreApplication::arguments().at(0).toStdString()); + execl(path, arg0, (char *)NULL); + } QDialog::accept(); } @@ -123,21 +179,29 @@ GeneralTab::GeneralTab(QSettings *_settings, LammpsWrapper *_lammps, QWidget *pa auto *layout = new QVBoxLayout; auto *echo = new QCheckBox("Echo input to log"); - echo->setCheckState(settings->value("echo", "0").toInt() ? Qt::Checked : Qt::Unchecked); echo->setObjectName("echo"); - auto *cite = new QCheckBox("Include Citations"); - cite->setCheckState(settings->value("cite", "0").toInt() ? Qt::Checked : Qt::Unchecked); + echo->setCheckState(settings->value("echo", false).toBool() ? Qt::Checked : Qt::Unchecked); + auto *cite = new QCheckBox("Include citation details"); cite->setObjectName("cite"); -#if !defined(__APPLE__) - auto *tmplabel = new QLabel("Scratch Folder:"); - auto *tmpedit = new QLineEdit(settings->value("tempdir", ".").toString()); - auto *tmpbrowse = new QPushButton("Browse..."); - auto *tmplayout = new QHBoxLayout; - tmpedit->setObjectName("tmpedit"); - tmplayout->addWidget(tmplabel); - tmplayout->addWidget(tmpedit); - tmplayout->addWidget(tmpbrowse); -#endif + cite->setCheckState(settings->value("cite", false).toBool() ? Qt::Checked : Qt::Unchecked); + auto *logv = new QCheckBox("Show log window by default"); + logv->setObjectName("viewlog"); + logv->setCheckState(settings->value("viewlog", true).toBool() ? Qt::Checked : Qt::Unchecked); + auto *pltv = new QCheckBox("Show chart window by default"); + pltv->setObjectName("viewchart"); + pltv->setCheckState(settings->value("viewchart", true).toBool() ? Qt::Checked : Qt::Unchecked); + auto *logr = new QCheckBox("Replace log window on new run"); + logr->setObjectName("logreplace"); + logr->setCheckState(settings->value("logreplace", false).toBool() ? Qt::Checked + : Qt::Unchecked); + auto *imgr = new QCheckBox("Replace image window on new render"); + imgr->setObjectName("imagereplace"); + imgr->setCheckState(settings->value("imagereplace", false).toBool() ? Qt::Checked + : Qt::Unchecked); + auto *pltr = new QCheckBox("Replace chart window on new run"); + pltr->setObjectName("chartreplace"); + pltr->setCheckState(settings->value("chartreplace", false).toBool() ? Qt::Checked + : Qt::Unchecked); #if defined(LAMMPS_GUI_USE_PLUGIN) auto *pluginlabel = new QLabel("Path to LAMMPS Shared Library File:"); @@ -151,25 +215,69 @@ GeneralTab::GeneralTab(QSettings *_settings, LammpsWrapper *_lammps, QWidget *pa connect(pluginbrowse, &QPushButton::released, this, &GeneralTab::pluginpath); #endif + + auto *fontlayout = new QHBoxLayout; + auto *getallfont = + new QPushButton(QIcon(":/preferences-desktop-font.png"), "Select Default Font..."); + auto *gettextfont = + new QPushButton(QIcon(":/preferences-desktop-font.png"), "Select Text Font..."); + fontlayout->addWidget(getallfont); + fontlayout->addWidget(gettextfont); + connect(getallfont, &QPushButton::released, this, &GeneralTab::newallfont); + connect(gettextfont, &QPushButton::released, this, &GeneralTab::newtextfont); + layout->addWidget(echo); layout->addWidget(cite); -#if !defined(__APPLE__) - layout->addLayout(tmplayout); -#endif + layout->addWidget(logv); + layout->addWidget(pltv); + layout->addWidget(logr); + layout->addWidget(pltr); + layout->addWidget(imgr); #if defined(LAMMPS_GUI_USE_PLUGIN) layout->addWidget(pluginlabel); layout->addLayout(pluginlayout); #endif + layout->addLayout(fontlayout); layout->addStretch(1); setLayout(layout); } -void GeneralTab::newtmpfolder() +void GeneralTab::updatefonts(const QFont &all, const QFont &text) { - QLineEdit *field = findChild("tmpedit"); - QString tmpdir = - QFileDialog::getExistingDirectory(this, "Find Folder for Temporary Files", field->text()); - if (!tmpdir.isEmpty()) field->setText(tmpdir); + LammpsGui *main; + for (QWidget *widget : QApplication::topLevelWidgets()) + if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); + + QApplication::setFont(all); + main->ui->textEdit->document()->setDefaultFont(text); +} + +void GeneralTab::newallfont() +{ + QSettings settings; + QFont all, text; + all.fromString(settings.value("allfont", "").toString()); + text.fromString(settings.value("textfont", "").toString()); + + bool ok = false; + QFont font = QFontDialog::getFont(&ok, all, this, QString("Select Default Font")); + if (ok) updatefonts(font, text); + + settings.setValue("allfont", font.toString()); +} + +void GeneralTab::newtextfont() +{ + QSettings settings; + QFont all, text; + all.fromString(settings.value("allfont", "").toString()); + text.fromString(settings.value("textfont", "").toString()); + + bool ok = false; + QFont font = QFontDialog::getFont(&ok, text, this, QString("Select Text Font")); + if (ok) updatefonts(all, font); + + settings.setValue("textfont", font.toString()); } void GeneralTab::pluginpath() @@ -179,16 +287,11 @@ void GeneralTab::pluginpath() QFileDialog::getOpenFileName(this, "Select Shared LAMMPS Library to Load", field->text(), "Shared Objects (*.so *.dll *.dylib)"); if (!pluginfile.isEmpty() && pluginfile.contains("liblammps", Qt::CaseSensitive)) { - if (lammps->load_lib(pluginfile.toStdString().c_str())) { - auto canonical = QFileInfo(pluginfile).canonicalFilePath(); - field->setText(pluginfile); - settings->setValue("plugin_path", canonical); - } else { - // plugin did not load cannot continue - settings->remove("plugin_path"); - QMessageBox::critical(this, "Error", "Cannot open LAMMPS shared library file"); - QCoreApplication::quit(); - } + auto canonical = QFileInfo(pluginfile).canonicalFilePath(); + field->setText(pluginfile); + settings->setValue("plugin_path", canonical); + // ugly hack + qobject_cast(parent()->parent()->parent())->need_relaunch = true; } } @@ -288,11 +391,28 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) : auto *xsize = new QLabel("Image width:"); auto *ysize = new QLabel("Image height:"); auto *zoom = new QLabel("Zoom factor:"); + auto *anti = new QLabel("Antialias:"); + auto *ssao = new QLabel("HQ Image mode:"); + auto *bbox = new QLabel("Show Box:"); + auto *axes = new QLabel("Show Axes:"); + auto *cback = new QLabel("Background Color:"); + auto *cbox = new QLabel("Box Color:"); settings->beginGroup("snapshot"); auto *xval = new QLineEdit(settings->value("xsize", "800").toString()); auto *yval = new QLineEdit(settings->value("ysize", "600").toString()); auto *zval = new QLineEdit(settings->value("zoom", "1.0").toString()); - settings->endGroup(); + auto *aval = new QCheckBox; + auto *sval = new QCheckBox; + auto *bval = new QCheckBox; + auto *eval = new QCheckBox; + sval->setCheckState(settings->value("ssao", false).toBool() ? Qt::Checked : Qt::Unchecked); + sval->setObjectName("ssao"); + aval->setCheckState(settings->value("antialias", false).toBool() ? Qt::Checked : Qt::Unchecked); + aval->setObjectName("anti"); + bval->setCheckState(settings->value("box", true).toBool() ? Qt::Checked : Qt::Unchecked); + bval->setObjectName("box"); + eval->setCheckState(settings->value("axes", false).toBool() ? Qt::Checked : Qt::Unchecked); + eval->setObjectName("axes"); auto *intval = new QIntValidator(100, 100000, this); xval->setValidator(intval); @@ -302,15 +422,48 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) : zval->setValidator(new QDoubleValidator(0.01, 100.0, 100, this)); zval->setObjectName("zoom"); + auto *background = new QComboBox; + background->setObjectName("background"); + background->addItem("black"); + background->addItem("darkgray"); + background->addItem("gray"); + background->addItem("silver"); + background->addItem("white"); + background->setCurrentText(settings->value("background", "black").toString()); + + auto *boxcolor = new QComboBox; + boxcolor->setObjectName("boxcolor"); + boxcolor->addItem("yellow"); + boxcolor->addItem("silver"); + boxcolor->addItem("gray"); + boxcolor->addItem("darkred"); + boxcolor->addItem("darkgreen"); + boxcolor->addItem("darkblue"); + boxcolor->setCurrentText(settings->value("boxcolor", "yellow").toString()); + settings->endGroup(); + grid->addWidget(xsize, 0, 0, Qt::AlignTop); grid->addWidget(ysize, 1, 0, Qt::AlignTop); grid->addWidget(zoom, 2, 0, Qt::AlignTop); + grid->addWidget(anti, 3, 0, Qt::AlignTop); + grid->addWidget(ssao, 4, 0, Qt::AlignTop); + grid->addWidget(bbox, 5, 0, Qt::AlignTop); + grid->addWidget(axes, 6, 0, Qt::AlignTop); + grid->addWidget(cback, 7, 0, Qt::AlignTop); + grid->addWidget(cbox, 8, 0, Qt::AlignTop); grid->addWidget(xval, 0, 1, Qt::AlignTop); grid->addWidget(yval, 1, 1, Qt::AlignTop); grid->addWidget(zval, 2, 1, Qt::AlignTop); - grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 3, 0); - grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 3, 1); - grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), 3, 2); + grid->addWidget(aval, 3, 1, Qt::AlignTop); + grid->addWidget(sval, 4, 1, Qt::AlignVCenter); + grid->addWidget(bval, 5, 1, Qt::AlignVCenter); + grid->addWidget(eval, 6, 1, Qt::AlignVCenter); + grid->addWidget(background, 7, 1, Qt::AlignVCenter); + grid->addWidget(boxcolor, 8, 1, Qt::AlignVCenter); + + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 9, 0); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), 9, 1); + grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), 9, 2); setLayout(grid); } diff --git a/tools/lammps-gui/preferences.h b/tools/lammps-gui/preferences.h index 46a512772a..1aa447e7b1 100644 --- a/tools/lammps-gui/preferences.h +++ b/tools/lammps-gui/preferences.h @@ -17,6 +17,7 @@ #include class QDialogButtonBox; +class QFont; class QSettings; class QTabWidget; class LammpsWrapper; @@ -31,6 +32,8 @@ public: private slots: void accept() override; +public: + bool need_relaunch; private: QTabWidget *tabWidget; QDialogButtonBox *buttonBox; @@ -48,9 +51,11 @@ public: private slots: void pluginpath(); - void newtmpfolder(); + void newallfont(); + void newtextfont(); private: + void updatefonts(const QFont &all, const QFont &text); QSettings *settings; LammpsWrapper *lammps; }; diff --git a/tools/lammps-gui/process-stop.png b/tools/lammps-gui/process-stop.png new file mode 100644 index 0000000000..5f547cfee3 Binary files /dev/null and b/tools/lammps-gui/process-stop.png differ diff --git a/tools/lammps-gui/setvariables.cpp b/tools/lammps-gui/setvariables.cpp new file mode 100644 index 0000000000..a63832fc57 --- /dev/null +++ b/tools/lammps-gui/setvariables.cpp @@ -0,0 +1,124 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#include "setvariables.h" + +#include +#include +#include +#include +#include +#include +#include + +SetVariables::SetVariables(QList> &_vars, QWidget *parent) : + QDialog(parent), vars(_vars), layout(new QVBoxLayout) +{ + auto *top = new QLabel("Set Variables:"); + layout->addWidget(top, 0, Qt::AlignHCenter); + + int i = 1; + for (const auto &v : vars) { + auto *row = new QHBoxLayout; + auto *name = new QLineEdit(v.first); + auto *val = new QLineEdit(v.second); + auto *del = new QPushButton(QIcon(":/edit-delete.png"), ""); + name->setObjectName("varname"); + val->setObjectName("varval"); + del->setObjectName(QString::number(i)); + connect(del, &QPushButton::released, this, &SetVariables::del_row); + row->addWidget(name); + row->addWidget(val); + row->addWidget(del); + layout->addLayout(row); + ++i; + } + layout->addSpacerItem(new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + auto *add = new QPushButton("&Add Row"); + add->setObjectName("add_row"); + buttonBox->addButton(add, QDialogButtonBox::ActionRole); + connect(add, &QPushButton::released, this, &SetVariables::add_row); + connect(buttonBox, &QDialogButtonBox::accepted, this, &SetVariables::accept); + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + layout->addWidget(buttonBox); + setLayout(layout); + setWindowTitle("LAMMPS-GUI - Set Variables"); + resize(300, 200); +} + +void SetVariables::accept() +{ + // store all data in variables class and then confirm accepting + vars.clear(); + int nrows = layout->count() - 2; + for (int i = 1; i < nrows; ++i) { + auto *row = layout->itemAt(i)->layout(); + auto *var = dynamic_cast(row->itemAt(0)->widget()); + auto *val = dynamic_cast(row->itemAt(1)->widget()); + if (var && val) vars.append(qMakePair(var->text(), val->text())); + } + + QDialog::accept(); +} + +void SetVariables::add_row() +{ + int nrows = layout->count(); + auto *row = new QHBoxLayout; + auto *name = new QLineEdit(QString()); + auto *val = new QLineEdit(QString()); + auto *del = new QPushButton(QIcon(":/edit-delete.png"), ""); + name->setObjectName("varname"); + val->setObjectName("varval"); + del->setObjectName(QString::number(nrows - 2)); + connect(del, &QPushButton::released, this, &SetVariables::del_row); + row->addWidget(name); + row->addWidget(val); + row->addWidget(del); + layout->insertLayout(nrows - 2, row); +} + +void SetVariables::del_row() +{ + int nrows = layout->count(); + auto *who = sender(); + if (who) { + // figure out which row was deleted and delete its layout and widgets + int delrow = who->objectName().toInt(); + auto *row = layout->takeAt(delrow); + while (row->layout()->count() > 0) { + auto *item = row->layout()->takeAt(0); + if (item) { + row->layout()->removeItem(item); + delete item->widget(); + delete item; + } + } + layout->removeItem(row); + delete row->layout(); + + // renumber the delete pushbutton names + for (int i = delrow; i < nrows - 3; ++i) { + auto *row = layout->itemAt(i)->layout(); + auto *widget = row->itemAt(2)->widget(); + widget->setObjectName(QString::number(i)); + } + } +} + +// Local Variables: +// c-basic-offset: 4 +// End: diff --git a/tools/lammps-gui/setvariables.h b/tools/lammps-gui/setvariables.h new file mode 100644 index 0000000000..1d1ca30bf2 --- /dev/null +++ b/tools/lammps-gui/setvariables.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://www.lammps.org/, Sandia National Laboratories + LAMMPS development team: developers@lammps.org + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +#ifndef SET_VARIABLES_H +#define SET_VARIABLES_H + +#include +#include +#include +#include + +class SetVariables : public QDialog { + Q_OBJECT + +public: + explicit SetVariables(QList> &vars, QWidget *parent = nullptr); + ~SetVariables() = default; + +private slots: + void accept() override; + void add_row(); + void del_row(); + +private: + QList> &vars; + class QVBoxLayout *layout; +}; + +#endif + +// Local Variables: +// c-basic-offset: 4 +// End: diff --git a/tools/lammps-gui/system-box.png b/tools/lammps-gui/system-box.png new file mode 100644 index 0000000000..baa5595d27 Binary files /dev/null and b/tools/lammps-gui/system-box.png differ diff --git a/tools/lammps-gui/system-help.png b/tools/lammps-gui/system-help.png new file mode 100644 index 0000000000..5242b608b6 Binary files /dev/null and b/tools/lammps-gui/system-help.png differ diff --git a/tools/lammps-gui/update-help-index.sh b/tools/lammps-gui/update-help-index.sh new file mode 100755 index 0000000000..5bb57c7148 --- /dev/null +++ b/tools/lammps-gui/update-help-index.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# this updates the help index table + +grep '\.\. index::' ../../doc/src/*.rst | sort | sed -e 's/^.*src\/\([^/]\+\)\.rst:/\1.html /' -e 's/\.\. \+index:: \+//' > help_index.table diff --git a/tools/lammps-gui/utilities-terminal.png b/tools/lammps-gui/utilities-terminal.png new file mode 100644 index 0000000000..362f7636f9 Binary files /dev/null and b/tools/lammps-gui/utilities-terminal.png differ diff --git a/tools/lammps-gui/vmd.png b/tools/lammps-gui/vmd.png new file mode 100644 index 0000000000..34b8e737a1 Binary files /dev/null and b/tools/lammps-gui/vmd.png differ diff --git a/tools/lammps-gui/window-close.png b/tools/lammps-gui/window-close.png new file mode 100644 index 0000000000..fdf3eba2b1 Binary files /dev/null and b/tools/lammps-gui/window-close.png differ diff --git a/tools/lammps-gui/x-office-drawing.png b/tools/lammps-gui/x-office-drawing.png new file mode 100644 index 0000000000..e93899922e Binary files /dev/null and b/tools/lammps-gui/x-office-drawing.png differ