update LAMMPS GUI code with PR 3890 content

This commit is contained in:
Axel Kohlmeyer
2023-08-17 22:50:10 -04:00
parent 84168fc84d
commit ee16f6503e
24 changed files with 534 additions and 106 deletions

View File

@ -65,12 +65,13 @@ Running LAMMPS
^^^^^^^^^^^^^^
From within the LAMMPS GUI main window LAMMPS can be started either from
the ``Run`` menu or by the hotkey `Ctrl-Enter` (`Command-Enter` on
macOS). LAMMPS is running in a separate thread, so the GUI will stay
responsive and thus is capable to interact with the calculation and
access its data. It is important to note, that LAMMPS is using the
contents of the input buffer for the run, **not** the file it was read
from. If there are unsaved changes in the buffer, they *will* be used.
the ``Run`` menu, by the hotkey `Ctrl-Enter` (`Command-Enter` on macOS),
or by clicking on the green button in the status bar. LAMMPS runs in a
separate thread, so the GUI stays responsive and thus it is able to
interact with the calculation and access its data. It is important to
note, that LAMMPS is using the contents of the input buffer for the run,
**not** the file it was read from. If there are unsaved changes in the
buffer, they *will* be used.
.. image:: JPG/lammps-gui-running.png
:align: center
@ -82,48 +83,59 @@ contain the selected number of threads, if thread-parallel acceleration
was selected in the ``Preferences`` dialog. On the right side, a
progress bar is shown that displays the estimated progress on the
current :doc:`run command <run>`. Additionally, two windows will open:
the log window with the captured screen output and the chart window
with a line graph created from the thermodynamic output of the run.
the log window with the captured screen output and the chart window with
a line graph created from the thermodynamic output of the run.
The run can be stopped cleanly by using either the ``Stop LAMMPS`` entry
in the ``Run`` menu or with the hotkey `Ctrl-/` (`Command-/` on macOS).
This will cause that the running LAMMPS process will complete the
current iteration and then stop. This is equivalent to the command
`timer timeout 0 <timer>` and implemented by calling the
:cpp:func:`lammps_force_timeout()` function of the LAMMPS C-library
interface.
in the ``Run`` menu, the hotkey `Ctrl-/` (`Command-/` on macOS), or
clicking on the red button in the status bar. This will cause that the
running LAMMPS process will complete the current iteration and then
stop. This is equivalent to the command `timer timeout 0 <timer>` and
implemented by calling the :cpp:func:`lammps_force_timeout()` function
of the LAMMPS C-library interface.
Viewing Snapshot Images
^^^^^^^^^^^^^^^^^^^^^^^
By selecting the ``View Image`` entry in the ``Run`` menu or by hitting
the `Ctrl-I` (`Command-I` on macOS) hotkey, LAMMPS gui will issue a
By selecting the ``View Image`` entry in the ``Run`` menu, by hitting
the `Ctrl-I` (`Command-I` on macOS) hotkey or by clicking on the
"palette" button in the status bar, LAMMPS GUI will issue a
:doc:`write_dump image <dump_image>` command and read the resulting
snapshot image into an image viewer window.
snapshot image into an image viewer window. When possible, LAMMPS
GUI will try to detect which elements the atoms correspond to (via
their mass) and then colorize them accordingly. Otherwise just some
predefined sequence of colors are assigned to different atom types.
.. image:: JPG/lammps-gui-image.png
:align: center
:scale: 50%
The image size, some default image quality settings, and some colors
can be changed in the ``Preferences`` dialog window. From the image
viewer window further adjustments can be made: high-quality rendering,
anti-aliasing, display of box or axes, zoom factor. The the image can
be rotated horizontally and vertically and it is possible to only
display the atoms within a predefined group (default is "all").
After each change, the image is rendered again and the display updated.
The default image size, some default image quality settings, the view
style and some colors can be changed in the ``Preferences`` dialog
window. From the image viewer window further adjustments can be made:
actual image size, high-quality rendering, anti-aliasing, view style,
display of box or axes, zoom factor. The the image can be rotated
horizontally and vertically and it is possible to only display the atoms
within a predefined group (default is "all"). After each change, the
image is rendered again and the display updated. The small palette icon
on the top left will be colored while LAMMPS is running to render the
image and it will be grayed out again, when it is done. When there are
many items to show and high quality images with anti-aliasing are
requested, re-rendering can take several seconds. From the ``File``
menu, the shown image can be saved to a file permanently or copied into
the cut-n-paste buffer for pasting into another application.
Editor Functions
^^^^^^^^^^^^^^^^
The editor has the usual functionality that similar programs have: text
selection via mouse or with cursor moves while holding the Shift key,
Cut, Copy, Paste, Undo, Redo. All of these editing functions are available
via hotkeys. When trying to exit the editor with a modified buffer, a
dialog will pop up asking whether to cancel the quit, or don't save or
save the buffer's contents to a file.
The editor has most the usual functionality that similar programs have:
text selection via mouse or with cursor moves while holding the Shift
key, Cut, Copy, Paste, Undo, Redo. All of these editing functions are
available via hotkeys. When trying to exit the editor with a modified
buffer, a dialog will pop up asking whether to cancel the quit, or don't
save or save the buffer's contents to a file.
Context Specific Help
^^^^^^^^^^^^^^^^^^^^^
@ -285,6 +297,13 @@ General Settings:
- *Replace image window on new render:* when checked, an existing
chart window will be replaced when a new snapshot image is requested,
otherwise each command will create a new image window.
- *Path to LAMMPS Shared Library File:* this options is only available
when LAMMPS GUI was compiled to load the LAMMPS library at run time
instead of being linked to it directly. With the ``Browse..`` button
or by changing the text, a different shared library file with a
different compilation of LAMMPS with different settings or from a
different version can be loaded. After this setting was changed,
LAMMPS GUI needs to be re-launched.
- *Select Default Font:* Opens a font selection dialog where the type
and size for the default font (used for everything but the editor and
log) of the application can be set.
@ -294,10 +313,10 @@ General Settings:
Accelerators:
^^^^^^^^^^^^^
This tab enables to select accelerator settings and is equivalent to
using the `-suffix` and `-package` flags on the command line. Only
settings supported by the LAMMPS library and local hardware are
available. The `Number of threads` field allows to set the maximum
This tab enables to select which accelerator package is used and is
equivalent to using the `-suffix` and `-package` flags on the command
line. Only settings supported by the LAMMPS library and local hardware
are available. The `Number of threads` field allows to set the maximum
number of threads for the accelerator packages that use threads.
Snapshot Image:
@ -306,14 +325,16 @@ Snapshot Image:
This tab allows to set some defaults for the snapshot images displayed
in the ``Image Viewer`` window, like its dimensions and the zoom factor
applied. The *Antialias* switch requests to render images with twice
the number of pixels for width and height and then uses a bi-cubic
scaling algorithm to rescale them back to the requested size. This
produces higher quality images with smoother edges at the expense of
requiring more CPU time to render the image. The *HQ Image mode* option
turns on using a screen space ambient occlusion mode (SSAO) when
rendering images. This is also more time consuming, but produces a more
'spatial' representation of the system. Finally there are a couple of
drop down lists to select the background and box color.
the number of pixels for width and height and then smoothly scales the
image back to the requested size. This produces higher quality images
with smoother edges at the expense of requiring more CPU time to render
the image. The *HQ Image mode* option turns on using a screen space
ambient occlusion mode (SSAO) when rendering images. This is also more
time consuming, but produces a more 'spatial' representation of the
system. The *VDW Style* checkbox selects whether atoms are represented
by space filling spheres when checked or by smaller spheres and stick.
Finally there are a couple of drop down lists to select the background
and box color.
Hotkeys

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16)
project(lammps-gui VERSION 1.2.0 LANGUAGES CXX)
project(lammps-gui VERSION 1.2.2 LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)

View File

@ -5,23 +5,17 @@ LAMMPS-GUI TODO list:
- 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
- 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
- triple quoted heredocs don't work with lammps_commands_string()
# 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
- rewrite entire application to 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
- 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
- have command text input line 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
- 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?

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -183,7 +183,7 @@ Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
}
const QString number_keywords[] = {
QStringLiteral("(^|\\s+)[0-9]+"), // integer
QStringLiteral("(^|\\s+)[0-9:*]+"), // integer and integer ranges
QStringLiteral("(^|\\s+)[0-9]+\\.[0-9]*[edED]?[-+]?[0-9]*"), // floating point 1
QStringLiteral("(^|\\s+)[0-9]*\\.[0-9]+[edED]?[-+]?[0-9]*"), // floating point 2
QStringLiteral("(^|\\s+)[0-9]+([edED][-+]?[0-9]+)?") // floating point 3
@ -207,10 +207,12 @@ Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
void Highlighter::highlightBlock(const QString &text)
{
// clang-format off
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);
// clang-format on
bool do_style = true;
bool do_force = true;
bool do_defs = true;

View File

@ -22,6 +22,7 @@
#include <QImage>
#include <QImageReader>
#include <QLabel>
#include <QLineEdit>
#include <QMenuBar>
#include <QMessageBox>
#include <QPalette>
@ -31,11 +32,28 @@
#include <QScrollArea>
#include <QScrollBar>
#include <QSettings>
#include <QSpinBox>
#include <QStatusBar>
#include <QVBoxLayout>
#include <QWheelEvent>
#include <QWidgetAction>
#include <cmath>
extern "C" {
#include "periodic_table.h"
static int get_pte_from_mass(double mass)
{
int idx = 0;
for (int i = 0; i < nr_pte_entries; ++i)
if (fabs(mass - pte_mass[i]) < 0.65) idx = i;
if ((mass > 0.0) && (mass < 2.2)) idx = 1;
// discriminate between Cobalt and Nickel. The loop will detect Nickel
if ((mass < 61.24) && (mass > 58.8133)) idx = 27;
return idx;
}
}
static const QString blank(" ");
ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidget *parent) :
@ -58,23 +76,63 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
QVBoxLayout *mainLayout = new QVBoxLayout;
QSettings settings;
vdwfactor = 0.4;
auto *renderstatus = new QLabel(QString());
auto pix = QPixmap(":/emblem-photos.png");
renderstatus->setPixmap(pix.scaled(22, 22, Qt::KeepAspectRatio));
renderstatus->setEnabled(false);
renderstatus->setToolTip("Render status");
settings.beginGroup("snapshot");
auto *xval = new QSpinBox;
xval->setRange(100, 10000);
xval->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType);
xval->setValue(settings.value("xsize", "800").toInt());
xval->setObjectName("xsize");
xval->setToolTip("Set rendered image width");
auto *yval = new QSpinBox;
yval->setRange(100, 10000);
yval->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType);
yval->setValue(settings.value("ysize", "600").toInt());
yval->setObjectName("ysize");
yval->setToolTip("Set rendered image height");
settings.endGroup();
connect(xval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size);
connect(yval, &QAbstractSpinBox::editingFinished, this, &ImageViewer::edit_size);
auto *dossao = new QPushButton(QIcon(":/hd-img.png"), "");
dossao->setCheckable(true);
dossao->setToolTip("Toggle SSAO rendering");
auto *doanti = new QPushButton(QIcon(":/antialias.png"), "");
doanti->setCheckable(true);
doanti->setToolTip("Toggle anti-aliasing");
auto *dovdw = new QPushButton(QIcon(":/vdw-style.png"), "");
dovdw->setCheckable(true);
dovdw->setToolTip("Toggle VDW style representation");
auto *dobox = new QPushButton(QIcon(":/system-box.png"), "");
dobox->setCheckable(true);
dobox->setToolTip("Toggle displaying box");
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"), "");
doaxes->setToolTip("Toggle displaying axes");
auto *zoomin = new QPushButton(QIcon(":/gtk-zoom-in.png"), "");
zoomin->setToolTip("Zoom in by 10 percent");
auto *zoomout = new QPushButton(QIcon(":/gtk-zoom-out.png"), "");
zoomout->setToolTip("Zoom out by 10 percent");
auto *rotleft = new QPushButton(QIcon(":/object-rotate-left.png"), "");
rotleft->setToolTip("Rotate left by 15 degrees");
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;
rotright->setToolTip("Rotate right by 15 degrees");
auto *rotup = new QPushButton(QIcon(":/gtk-go-up.png"), "");
rotup->setToolTip("Rotate up by 15 degrees");
auto *rotdown = new QPushButton(QIcon(":/gtk-go-down.png"), "");
rotdown->setToolTip("Rotate down by 15 degrees");
auto *reset = new QPushButton(QIcon(":/gtk-zoom-fit.png"), "");
reset->setToolTip("Reset view to defaults");
auto *combo = new QComboBox;
combo->setObjectName("group");
combo->setToolTip("Select group to display");
int ngroup = lammps->id_count("group");
char gname[64];
for (int i = 0; i < ngroup; ++i) {
@ -84,8 +142,14 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
QHBoxLayout *menuLayout = new QHBoxLayout;
menuLayout->addWidget(menuBar);
menuLayout->addWidget(renderstatus);
menuLayout->addWidget(new QLabel(" Width: "));
menuLayout->addWidget(xval);
menuLayout->addWidget(new QLabel(" Height: "));
menuLayout->addWidget(yval);
menuLayout->addWidget(dossao);
menuLayout->addWidget(doanti);
menuLayout->addWidget(dovdw);
menuLayout->addWidget(dobox);
menuLayout->addWidget(doaxes);
menuLayout->addWidget(zoomin);
@ -100,6 +164,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
connect(dossao, &QPushButton::released, this, &ImageViewer::toggle_ssao);
connect(doanti, &QPushButton::released, this, &ImageViewer::toggle_anti);
connect(dovdw, &QPushButton::released, this, &ImageViewer::toggle_vdw);
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);
@ -119,6 +184,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge
reset_view();
dobox->setChecked(showbox);
dovdw->setChecked(vdwfactor > 1.0);
doaxes->setChecked(showaxes);
dossao->setChecked(usessao);
doanti->setChecked(antialias);
@ -137,9 +203,12 @@ void ImageViewer::reset_view()
{
QSettings settings;
settings.beginGroup("snapshot");
xsize = settings.value("xsize", "800").toInt();
ysize = settings.value("ysize", "600").toInt();
zoom = settings.value("zoom", 1.0).toDouble();
hrot = settings.value("hrot", 60).toInt();
vrot = settings.value("vrot", 30).toInt();
vdwfactor = settings.value("vdwstyle", false).toBool() ? 1.6 : 0.5;
showbox = settings.value("box", true).toBool();
showaxes = settings.value("axes", false).toBool();
usessao = settings.value("ssao", false).toBool();
@ -151,18 +220,37 @@ void ImageViewer::reset_view()
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<QPushButton *>(lo->itemAt(1)->widget());
auto *field = qobject_cast<QSpinBox *>(lo->itemAt(3)->widget());
field->setValue(xsize);
field = qobject_cast<QSpinBox *>(lo->itemAt(5)->widget());
field->setValue(ysize);
auto *button = qobject_cast<QPushButton *>(lo->itemAt(6)->widget());
button->setChecked(usessao);
button = qobject_cast<QPushButton *>(lo->itemAt(2)->widget());
button = qobject_cast<QPushButton *>(lo->itemAt(7)->widget());
button->setChecked(antialias);
button = qobject_cast<QPushButton *>(lo->itemAt(3)->widget());
button = qobject_cast<QPushButton *>(lo->itemAt(8)->widget());
button->setChecked(vdwfactor > 1.0);
button = qobject_cast<QPushButton *>(lo->itemAt(9)->widget());
button->setChecked(showbox);
button = qobject_cast<QPushButton *>(lo->itemAt(4)->widget());
button = qobject_cast<QPushButton *>(lo->itemAt(10)->widget());
button->setChecked(showaxes);
// grab the last entry -> group selector
auto *cb = qobject_cast<QComboBox *>(lo->itemAt(lo->count() - 1)->widget());
cb->setCurrentText("all");
this->repaint();
}
createImage();
}
void ImageViewer::edit_size()
{
QSpinBox *field = qobject_cast<QSpinBox *>(sender());
if (field->objectName() == "xsize") {
xsize = field->value();
} else if (field->objectName() == "ysize") {
ysize = field->value();
}
createImage();
}
@ -183,6 +271,17 @@ void ImageViewer::toggle_anti()
createImage();
}
void ImageViewer::toggle_vdw()
{
QPushButton *button = qobject_cast<QPushButton *>(sender());
if (vdwfactor > 1.0)
vdwfactor = 0.4;
else
vdwfactor = 1.6;
button->setChecked(vdwfactor > 1.0);
createImage();
}
void ImageViewer::toggle_box()
{
QPushButton *button = qobject_cast<QPushButton *>(sender());
@ -215,28 +314,28 @@ void ImageViewer::do_zoom_out()
void ImageViewer::do_rot_left()
{
vrot -= 15;
vrot -= 10;
if (vrot < -180) vrot += 360;
createImage();
}
void ImageViewer::do_rot_right()
{
vrot += 15;
vrot += 10;
if (vrot > 180) vrot -= 360;
createImage();
}
void ImageViewer::do_rot_down()
{
hrot -= 15;
hrot -= 10;
if (hrot < 0) hrot += 360;
createImage();
}
void ImageViewer::do_rot_up()
{
hrot += 15;
hrot += 10;
if (hrot > 360) hrot -= 360;
createImage();
}
@ -250,6 +349,11 @@ void ImageViewer::change_group(int idx)
void ImageViewer::createImage()
{
auto *lo = layout();
if (lo) lo = lo->itemAt(0)->layout();
if (lo) qobject_cast<QLabel *>(lo->itemAt(1)->widget())->setEnabled(true);
this->repaint();
QSettings settings;
QString dumpcmd = QString("write_dump ") + group + " image ";
QDir dumpdir(QDir::tempPath());
@ -257,16 +361,36 @@ void ImageViewer::createImage()
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;
int aa = antialias ? 2 : 1;
int tmpxsize = xsize * aa;
int tmpysize = ysize * aa;
int hhrot = (hrot > 180) ? 360 - hrot : hrot;
dumpcmd += blank + settings.value("color", "type").toString();
// determine elements from masses and set their covalent radii
int ntypes = lammps->extract_setting("ntypes");
int nbondtypes = lammps->extract_setting("nbondtypes");
double *masses = (double *)lammps->extract_atom("mass");
QString units = (const char *)lammps->extract_global("units");
QString elements = "element ";
QString adiams;
if ((units == "real") || (units == "metal")) {
for (int i = 1; i <= ntypes; ++i) {
int idx = get_pte_from_mass(masses[i]);
elements += QString(pte_label[idx]) + blank;
adiams += QString("adiam %1 %2 ").arg(i).arg(vdwfactor * pte_vdw_radius[idx]);
}
}
if (!adiams.isEmpty())
dumpcmd += blank + "element";
else
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(" size ") + QString::number(tmpxsize) + blank + QString::number(tmpysize);
dumpcmd += QString(" zoom ") + QString::number(zoom);
lammps->command(dumpcmd.toLocal8Bit());
dumpcmd += " shiny 0.5 ";
if (nbondtypes > 0) dumpcmd += " bond atom 0.4 ";
if (lammps->extract_setting("dimension") == 3) {
dumpcmd += QString(" view ") + QString::number(hhrot) + blank + QString::number(vrot);
}
@ -277,12 +401,13 @@ void ImageViewer::createImage()
dumpcmd += QString(" box no 0.0");
if (showaxes)
dumpcmd += QString(" axes yes 0.2 0.025");
dumpcmd += QString(" axes yes 0.5 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();
if (!adiams.isEmpty()) dumpcmd += blank + elements + blank + adiams + blank;
settings.endGroup();
lammps->command(dumpcmd.toLocal8Bit());
@ -299,13 +424,12 @@ void ImageViewer::createImage()
}
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));
imageLabel->adjustSize();
if (lo) qobject_cast<QLabel *>(lo->itemAt(1)->widget())->setEnabled(false);
this->repaint();
}
void ImageViewer::saveAs()

View File

@ -45,9 +45,11 @@ private slots:
void normalSize();
void fitToWindow();
void edit_size();
void reset_view();
void toggle_ssao();
void toggle_anti();
void toggle_vdw();
void toggle_box();
void toggle_axes();
void do_zoom_in();
@ -86,8 +88,9 @@ private:
LammpsWrapper *lammps;
QString group;
QString filename;
int xsize, ysize;
int hrot, vrot;
double zoom;
double zoom, vdwfactor;
bool showbox, showaxes, antialias, usessao;
};
#endif

View File

@ -34,6 +34,7 @@
#include <QPlainTextEdit>
#include <QProcess>
#include <QProgressBar>
#include <QPushButton>
#include <QSettings>
#include <QShortcut>
#include <QStatusBar>
@ -241,7 +242,22 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) :
auto pix = QPixmap(":/lammps-icon-128x128.png");
lammpsstatus->setPixmap(pix.scaled(22, 22, Qt::KeepAspectRatio));
ui->statusbar->addWidget(lammpsstatus);
lammpsstatus->setToolTip("LAMMPS instance is active");
lammpsstatus->hide();
auto *lammpsrun = new QPushButton(QIcon(":/system-run.png"), "");
auto *lammpsstop = new QPushButton(QIcon(":/process-stop.png"), "");
auto *lammpsimage = new QPushButton(QIcon(":/emblem-photos.png"), "");
lammpsrun->setToolTip("Run LAMMPS on input");
lammpsstop->setToolTip("Stop LAMMPS");
lammpsimage->setToolTip("Create snapshot image");
ui->statusbar->addWidget(lammpsrun);
ui->statusbar->addWidget(lammpsstop);
ui->statusbar->addWidget(lammpsimage);
connect(lammpsrun, &QPushButton::released, this, &LammpsGui::run_buffer);
connect(lammpsstop, &QPushButton::released, this, &LammpsGui::stop_run);
connect(lammpsimage, &QPushButton::released, this, &LammpsGui::render_image);
status = new QLabel("Ready.");
status->setFixedWidth(300);
ui->statusbar->addWidget(status);
@ -280,6 +296,10 @@ void LammpsGui::new_document()
current_file.clear();
ui->textEdit->document()->setPlainText(QString());
if (lammps.is_running()) {
stop_run();
runner->wait();
}
lammps.close();
lammpsstatus->hide();
setWindowTitle(QString("LAMMPS-GUI - *unknown*"));
@ -549,6 +569,10 @@ void LammpsGui::save_as()
void LammpsGui::quit()
{
if (lammps.is_running()) {
stop_run();
runner->wait();
}
lammps.close();
lammpsstatus->hide();
lammps.finalize();
@ -806,7 +830,7 @@ void LammpsGui::run_buffer()
char *input = mystrdup(ui->textEdit->toPlainText().toStdString() + "\n");
is_running = true;
LammpsRunner *runner = new LammpsRunner(this);
runner = new LammpsRunner(this);
runner->setup_run(&lammps, input);
connect(runner, &LammpsRunner::resultReady, this, &LammpsGui::run_done);
connect(runner, &LammpsRunner::finished, runner, &QObject::deleteLater);
@ -1035,6 +1059,11 @@ void LammpsGui::edit_variables()
SetVariables vars(newvars);
if (vars.exec() == QDialog::Accepted) {
variables = newvars;
if (lammps.is_running()) {
stop_run();
runner->wait();
delete runner;
}
lammps.close();
lammpsstatus->hide();
}
@ -1057,6 +1086,11 @@ void LammpsGui::preferences()
(oldthreads != settings.value("nthreads", 1).toInt()) ||
(oldecho != settings.value("echo", 0).toInt()) ||
(oldcite != settings.value("cite", 0).toInt())) {
if (lammps.is_running()) {
stop_run();
runner->wait();
delete runner;
}
lammps.close();
lammpsstatus->hide();
}

View File

@ -26,6 +26,7 @@
// forward declarations
class GeneralTab;
class LammpsRunner;
QT_BEGIN_NAMESPACE
namespace Ui {
@ -114,6 +115,7 @@ private:
QList<QPair<QString, QString>> variables;
LammpsWrapper lammps;
LammpsRunner *runner;
std::string plugin_path;
bool is_running;
std::vector<char *> lammps_args;

View File

@ -33,7 +33,7 @@
<file>help-about.png</file>
<file>emblem-photos.png</file>
<file>process-stop.png</file>
<file>emblem-default.png</file>
<file>system-run.png</file>
<file>window-close.png</file>
<file>application-plot.png</file>
<file>application-calc.png</file>
@ -43,5 +43,6 @@
<file>antialias.png</file>
<file>ovito.png</file>
<file>vmd.png</file>
<file>vdw-style.png</file>
</qresource>
</RCC>

View File

@ -212,7 +212,7 @@
</action>
<action name="actionRun_Buffer">
<property name="icon">
<iconset theme=":/emblem-default.png"/>
<iconset theme=":/system-run.png"/>
</property>
<property name="text">
<string>&amp;Run LAMMPS</string>

View File

@ -45,6 +45,32 @@ int LammpsWrapper::extract_setting(const char *keyword)
return val;
}
void *LammpsWrapper::extract_global(const char *keyword)
{
void *val = nullptr;
if (lammps_handle) {
#if defined(LAMMPS_GUI_USE_PLUGIN)
val = ((liblammpsplugin_t *)plugin_handle)->extract_global(lammps_handle, keyword);
#else
val = lammps_extract_global(lammps_handle, keyword);
#endif
}
return val;
}
void *LammpsWrapper::extract_atom(const char *keyword)
{
void *val = nullptr;
if (lammps_handle) {
#if defined(LAMMPS_GUI_USE_PLUGIN)
val = ((liblammpsplugin_t *)plugin_handle)->extract_atom(lammps_handle, keyword);
#else
val = lammps_extract_atom(lammps_handle, keyword);
#endif
}
return val;
}
int LammpsWrapper::id_count(const char *keyword)
{
int val = 0;

View File

@ -29,15 +29,21 @@ public:
void force_timeout();
int extract_setting(const char *keyword);
void *extract_global(const char *keyword);
void *extract_atom(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;
int get_last_error_message(char *errorbuf, int buflen);
bool config_accelerator(const char *package, const char *category, const char *setting) const;
bool config_has_package(const char *pkg) const;
bool has_gpu_device() const;

View File

@ -0,0 +1,205 @@
/***************************************************************************
* RCS INFORMATION:
*
* $RCSfile: periodic_table.h,v $
* $Author: johns $ $Locker: $ $State: Exp $
* $Revision: 1.12 $ $Date: 2009/01/21 17:45:41 $
*
***************************************************************************/
/*
* periodic table of elements and helper functions to convert
* ordinal numbers to labels and back.
* all tables and functions are declared static, so that it
* can be safely included by all plugins that may need it.
*
* 2002-2009 akohlmey@cmm.chem.upenn.edu, vmd@ks.uiuc.edu
*/
#include <string.h>
#include <ctype.h>
/* periodic table of elements for translation of ordinal to atom type */
static const char *pte_label[] = {
"X", "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne",
"Na", "Mg", "Al", "Si", "P" , "S", "Cl", "Ar", "K", "Ca", "Sc",
"Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge",
"As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc",
"Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe",
"Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb",
"Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W", "Re", "Os",
"Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr",
"Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf",
"Es", "Fm", "Md", "No", "Lr", "Rf", "Db", "Sg", "Bh", "Hs", "Mt",
"Ds", "Rg"
};
static const int nr_pte_entries = sizeof(pte_label) / sizeof(char *);
/* corresponding table of masses. */
static const double pte_mass[] = {
/* X */ 0.00000, 1.00794, 4.00260, 6.941, 9.012182, 10.811,
/* C */ 12.0107, 14.0067, 15.9994, 18.9984032, 20.1797,
/* Na */ 22.989770, 24.3050, 26.981538, 28.0855, 30.973761,
/* S */ 32.065, 35.453, 39.948, 39.0983, 40.078, 44.955910,
/* Ti */ 47.867, 50.9415, 51.9961, 54.938049, 55.845, 58.9332,
/* Ni */ 58.6934, 63.546, 65.409, 69.723, 72.64, 74.92160,
/* Se */ 78.96, 79.904, 83.798, 85.4678, 87.62, 88.90585,
/* Zr */ 91.224, 92.90638, 95.94, 98.0, 101.07, 102.90550,
/* Pd */ 106.42, 107.8682, 112.411, 114.818, 118.710, 121.760,
/* Te */ 127.60, 126.90447, 131.293, 132.90545, 137.327,
/* La */ 138.9055, 140.116, 140.90765, 144.24, 145.0, 150.36,
/* Eu */ 151.964, 157.25, 158.92534, 162.500, 164.93032,
/* Er */ 167.259, 168.93421, 173.04, 174.967, 178.49, 180.9479,
/* W */ 183.84, 186.207, 190.23, 192.217, 195.078, 196.96655,
/* Hg */ 200.59, 204.3833, 207.2, 208.98038, 209.0, 210.0, 222.0,
/* Fr */ 223.0, 226.0, 227.0, 232.0381, 231.03588, 238.02891,
/* Np */ 237.0, 244.0, 243.0, 247.0, 247.0, 251.0, 252.0, 257.0,
/* Md */ 258.0, 259.0, 262.0, 261.0, 262.0, 266.0, 264.0, 269.0,
/* Mt */ 268.0, 271.0, 272.0
};
/*
* corresponding table of VDW radii.
* van der Waals radii are taken from A. Bondi,
* J. Phys. Chem., 68, 441 - 452, 1964,
* except the value for H, which is taken from R.S. Rowland & R. Taylor,
* J.Phys.Chem., 100, 7384 - 7391, 1996. Radii that are not available in
* either of these publications have RvdW = 2.00 \AA
* The radii for Ions (Na, K, Cl, Ca, Mg, and Cs are based on the CHARMM27
* Rmin/2 parameters for (SOD, POT, CLA, CAL, MG, CES) by default.
*/
static const double pte_vdw_radius[] = {
/* X */ 1.5, 1.2, 1.4, 1.82, 2.0, 2.0,
/* C */ 1.7, 1.55, 1.52, 1.47, 1.54,
/* Na */ 1.36, 1.18, 2.0, 2.1, 1.8,
/* S */ 1.8, 2.27, 1.88, 1.76, 1.37, 2.0,
/* Ti */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0,
/* Ni */ 1.63, 1.4, 1.39, 1.07, 2.0, 1.85,
/* Se */ 1.9, 1.85, 2.02, 2.0, 2.0, 2.0,
/* Zr */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0,
/* Pd */ 1.63, 1.72, 1.58, 1.93, 2.17, 2.0,
/* Te */ 2.06, 1.98, 2.16, 2.1, 2.0,
/* La */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0,
/* Eu */ 2.0, 2.0, 2.0, 2.0, 2.0,
/* Er */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0,
/* W */ 2.0, 2.0, 2.0, 2.0, 1.72, 1.66,
/* Hg */ 1.55, 1.96, 2.02, 2.0, 2.0, 2.0, 2.0,
/* Fr */ 2.0, 2.0, 2.0, 2.0, 2.0, 1.86,
/* Np */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0,
/* Md */ 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0,
/* Mt */ 2.0, 2.0, 2.0
};
/* lookup functions */
static const char *get_pte_label(const int idx)
{
if ((idx < 1) || (idx >= nr_pte_entries)) return pte_label[0];
return pte_label[idx];
}
static double get_pte_mass(const int idx)
{
if ((idx < 1) || (idx >= nr_pte_entries)) return pte_mass[0];
return pte_mass[idx];
}
static double get_pte_vdw_radius(const int idx)
{
if ((idx < 1) || (idx >= nr_pte_entries)) return pte_vdw_radius[0];
#if 1
/* Replace with Hydrogen radius with an "all-atom" radius */
if (idx == 1)
return 1.0; /* H */
#else
/* Replace with old VMD atom radii values */
switch (idx) {
case 1: return 1.0; /* H */
case 6: return 1.5; /* C */
case 7: return 1.4; /* N */
case 8: return 1.3; /* O */
case 9: return 1.2; /* F */
case 15: return 1.5; /* P */
case 16: return 1.9; /* S */
}
#endif
return pte_vdw_radius[idx];
}
static int get_pte_idx(const char *label)
{
int i;
char atom[3];
/* zap string */
atom[0] = (char) 0;
atom[1] = (char) 0;
atom[2] = (char) 0;
/* if we don't have a null-pointer, there must be at least two
* chars, which is all we need. we convert to the capitalization
* convention of the table above during assignment. */
if (label != NULL) {
atom[0] = (char) toupper((int) label[0]);
atom[1] = (char) tolower((int) label[1]);
}
/* discard numbers in atom label */
if (isdigit(atom[1])) atom[1] = (char) 0;
for (i=0; i < nr_pte_entries; ++i) {
if ( (pte_label[i][0] == atom[0])
&& (pte_label[i][1] == atom[1]) ) return i;
}
return 0;
}
static int get_pte_idx_from_string(const char *label) {
int i, ind;
char atom[3];
if (label != NULL) {
/* zap string */
atom[0] = atom[1] = atom[2] = '\0';
for (ind=0,i=0; (ind<2) && (label[i]!='\0'); i++) {
if (label[i] != ' ') {
atom[ind] = toupper(label[i]);
ind++;
}
}
if (ind < 1)
return 0; /* no non-whitespace characters */
for (i=0; i < nr_pte_entries; ++i) {
if ((toupper(pte_label[i][0]) == atom[0]) && (toupper(pte_label[i][1]) == atom[1]))
return i;
}
}
return 0;
}
#if 0
#include <stdio.h>
int main() {
int i;
printf("Periodic table check/dump\n");
printf(" Table contains data for %d elements\n", nr_pte_entries);
printf(" Mass table size check: %d\n", sizeof(pte_mass) / sizeof(double));
printf(" VDW table size check: %d\n", sizeof(pte_vdw_radius) / sizeof(double));
printf("\n");
printf("Symbol Num Mass rVDW\n");
for (i=0; i<nr_pte_entries; i++) {
printf(" %-2s %3d %6.2f %4.2f\n",
get_pte_label(i), i, get_pte_mass(i), get_pte_vdw_radius(i));
}
return 0;
}
#endif

View File

@ -138,6 +138,8 @@ void Preferences::accept()
if (box) settings->setValue("box", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("axes");
if (box) settings->setValue("axes", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("vdwstyle");
if (box) settings->setValue("vdwstyle", box->isChecked());
QComboBox *combo = tabWidget->findChild<QComboBox *>("background");
if (combo) settings->setValue("background", combo->currentText());
combo = tabWidget->findChild<QComboBox *>("boxcolor");
@ -395,6 +397,7 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) :
auto *ssao = new QLabel("HQ Image mode:");
auto *bbox = new QLabel("Show Box:");
auto *axes = new QLabel("Show Axes:");
auto *vdw = new QLabel("VDW Style:");
auto *cback = new QLabel("Background Color:");
auto *cbox = new QLabel("Box Color:");
settings->beginGroup("snapshot");
@ -405,6 +408,7 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) :
auto *sval = new QCheckBox;
auto *bval = new QCheckBox;
auto *eval = new QCheckBox;
auto *vval = 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);
@ -413,6 +417,8 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) :
bval->setObjectName("box");
eval->setCheckState(settings->value("axes", false).toBool() ? Qt::Checked : Qt::Unchecked);
eval->setObjectName("axes");
vval->setCheckState(settings->value("vdwstyle", false).toBool() ? Qt::Checked : Qt::Unchecked);
vval->setObjectName("vdwstyle");
auto *intval = new QIntValidator(100, 100000, this);
xval->setValidator(intval);
@ -442,28 +448,31 @@ SnapshotTab::SnapshotTab(QSettings *_settings, QWidget *parent) :
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->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);
int i = 0;
grid->addWidget(xsize, i, 0, Qt::AlignTop);
grid->addWidget(xval, i++, 1, Qt::AlignTop);
grid->addWidget(ysize, i, 0, Qt::AlignTop);
grid->addWidget(yval, i++, 1, Qt::AlignTop);
grid->addWidget(zoom, i, 0, Qt::AlignTop);
grid->addWidget(zval, i++, 1, Qt::AlignTop);
grid->addWidget(anti, i, 0, Qt::AlignTop);
grid->addWidget(aval, i++, 1, Qt::AlignTop);
grid->addWidget(ssao, i, 0, Qt::AlignTop);
grid->addWidget(sval, i++, 1, Qt::AlignVCenter);
grid->addWidget(bbox, i, 0, Qt::AlignTop);
grid->addWidget(bval, i++, 1, Qt::AlignVCenter);
grid->addWidget(axes, i, 0, Qt::AlignTop);
grid->addWidget(eval, i++, 1, Qt::AlignVCenter);
grid->addWidget(vdw, i, 0, Qt::AlignTop);
grid->addWidget(vval, i++, 1, Qt::AlignVCenter);
grid->addWidget(cback, i, 0, Qt::AlignTop);
grid->addWidget(background, i++, 1, Qt::AlignVCenter);
grid->addWidget(cbox, i, 0, Qt::AlignTop);
grid->addWidget(boxcolor, i++, 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);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), i, 0);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), i, 1);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), i, 2);
setLayout(grid);
}

View File

@ -34,6 +34,7 @@ private slots:
public:
bool need_relaunch;
private:
QTabWidget *tabWidget;
QDialogButtonBox *buttonBox;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB