From 2b1985f755fb5019f03d4e76b6174808e7f543c1 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 10 Oct 2023 11:36:49 -0400 Subject: [PATCH 01/21] restore GNU make build capability for ML-PACE --- lib/pace/Makefile | 6 +++--- lib/pace/Makefile.lammps | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pace/Makefile b/lib/pace/Makefile index 5a1588ef93..37f00ee70e 100644 --- a/lib/pace/Makefile +++ b/lib/pace/Makefile @@ -1,4 +1,5 @@ SHELL = /bin/sh +CMAKE= cmake # ------ FILES ------ @@ -35,7 +36,7 @@ lib: $(OBJ) lib-yaml-cpp lib-yaml-cpp: - cd $(YAML_CPP_PATH) && $(MAKE) lib + cd $(YAML_CPP_PATH) && $(CMAKE) . && $(MAKE) all # ------ COMPILE RULES ------ @@ -45,9 +46,8 @@ lib-yaml-cpp: # ------ CLEAN ------ clean-all: -rm -f *~ $(OBJ) $(LIB) - cd $(YAML_CPP_PATH) && $(MAKE) clean-all + cd $(YAML_CPP_PATH) && $(MAKE) clean clean-build: -rm -f *~ $(OBJ) - cd $(YAML_CPP_PATH) && $(MAKE) clean-build diff --git a/lib/pace/Makefile.lammps b/lib/pace/Makefile.lammps index 6411e49a07..1c549e31d0 100644 --- a/lib/pace/Makefile.lammps +++ b/lib/pace/Makefile.lammps @@ -1,3 +1,3 @@ pace_SYSINC =-I../../lib/pace/src/ML-PACE -I../../lib/pace/src/yaml-cpp/include -I../../lib/pace/src/wigner-cpp/include -DEXTRA_C_PROJECTIONS -pace_SYSLIB = -L../../lib/pace/ -lpace -L../../lib/pace/src/yaml-cpp/ -lyaml-cpp +pace_SYSLIB = -L../../lib/pace/ -lpace -L../../lib/pace/src/yaml-cpp/ -lyaml-cpp-pace pace_SYSPATH = From 07a03336702ff90501b2158b1ab14d6f1f2391fe Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 10 Oct 2023 13:53:56 -0400 Subject: [PATCH 02/21] prevent potential memory leak --- src/compute_msd_chunk.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/compute_msd_chunk.cpp b/src/compute_msd_chunk.cpp index 07234ecfdb..6e7436d6ad 100644 --- a/src/compute_msd_chunk.cpp +++ b/src/compute_msd_chunk.cpp @@ -27,8 +27,8 @@ using namespace LAMMPS_NS; /* ---------------------------------------------------------------------- */ ComputeMSDChunk::ComputeMSDChunk(LAMMPS *lmp, int narg, char **arg) : - ComputeChunk(lmp, narg, arg), id_fix(nullptr), massproc(nullptr), masstotal(nullptr), - com(nullptr), comall(nullptr), msd(nullptr) + ComputeChunk(lmp, narg, arg), id_fix(nullptr), fix(nullptr), massproc(nullptr), + masstotal(nullptr), com(nullptr), comall(nullptr), msd(nullptr) { if (narg != 4) error->all(FLERR, "Illegal compute msd/chunk command"); @@ -196,6 +196,12 @@ void ComputeMSDChunk::compute_array() void ComputeMSDChunk::allocate() { ComputeChunk::allocate(); + memory->destroy(massproc); + memory->destroy(masstotal); + memory->destroy(com); + memory->destroy(comall); + memory->destroy(msd); + memory->create(massproc, nchunk, "msd/chunk:massproc"); memory->create(masstotal, nchunk, "msd/chunk:masstotal"); memory->create(com, nchunk, 3, "msd/chunk:com"); From 84eab70fb4252eb691d52000dae1ce2280ffb2ea Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 10 Oct 2023 22:18:41 -0400 Subject: [PATCH 03/21] must select entire non-blank string under cursor for completion insertions --- tools/lammps-gui/codeeditor.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/tools/lammps-gui/codeeditor.cpp b/tools/lammps-gui/codeeditor.cpp index 34193bc320..7a1624c192 100644 --- a/tools/lammps-gui/codeeditor.cpp +++ b/tools/lammps-gui/codeeditor.cpp @@ -564,7 +564,7 @@ void CodeEditor::keyPressEvent(QKeyEvent *event) // process key event in parent class QPlainTextEdit::keyPressEvent(event); - // if enabled, try pop up completion automatically after 3 characters + // if enabled, try pop up completion automatically after 2 characters if (automatic_completion) { auto cursor = textCursor(); auto line = cursor.block().text(); @@ -990,8 +990,26 @@ void CodeEditor::insertCompletedCommand(const QString &completion) { auto *completer = qobject_cast(sender()); if (completer->widget() != this) return; + + // select the entire word (non-space text) under the cursor + // we need to do it in this compicated way, since QTextCursor does not recognize + // special characters as part of a word. auto cursor = textCursor(); - cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); + auto line = cursor.block().text(); + int begin = cursor.positionInBlock(); + do { + if (line[begin].isSpace()) break; + --begin; + } while (begin >= 0); + + int end = begin + 1; + while (end < line.length()) { + if (line[end].isSpace()) break; + ++end; + } + + cursor.setPosition(cursor.position() - cursor.positionInBlock() + begin + 1); + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, end - begin); cursor.insertText(completion); setTextCursor(cursor); } From 86a5d6bb151c196bb1843d947d901fe228625669 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 11 Oct 2023 02:05:23 -0400 Subject: [PATCH 04/21] must re-initialized threads also for neigbor lists --- src/OPENMP/npair_omp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/OPENMP/npair_omp.h b/src/OPENMP/npair_omp.h index 318fddfd54..7249c59406 100644 --- a/src/OPENMP/npair_omp.h +++ b/src/OPENMP/npair_omp.h @@ -32,6 +32,7 @@ namespace LAMMPS_NS { // get access to number of threads and per-thread data structures via FixOMP #define NPAIR_OMP_INIT \ const int nthreads = comm->nthreads; \ + omp_set_num_threads(nthreads); \ const int ifix = modify->find_fix("package_omp") // get thread id and then assign each thread a fixed chunk of atoms From cc5c5bbd498553dc529f94516401a24979b65a79 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 11 Oct 2023 02:12:03 -0400 Subject: [PATCH 05/21] block waiting for end of stdout data not more than a second --- tools/lammps-gui/stdcapture.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/lammps-gui/stdcapture.cpp b/tools/lammps-gui/stdcapture.cpp index 428277cc10..b09aebf053 100644 --- a/tools/lammps-gui/stdcapture.cpp +++ b/tools/lammps-gui/stdcapture.cpp @@ -77,6 +77,7 @@ bool StdCapture::EndCapture() int bytesRead; bool fd_blocked; + int maxwait = 100; do { bytesRead = 0; @@ -93,9 +94,10 @@ bool StdCapture::EndCapture() buf[bytesRead] = 0; m_captured += buf; } else if (bytesRead < 0) { - fd_blocked = ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)); + fd_blocked = ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)) && (maxwait > 0); if (fd_blocked) std::this_thread::sleep_for(std::chrono::milliseconds(10)); + --maxwait; } } while (fd_blocked || (bytesRead == (bufSize - 1))); m_capturing = false; From eff74405c1382b4d9b20734e62134333bcf5f88d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 11 Oct 2023 02:16:23 -0400 Subject: [PATCH 06/21] don't replace end of line character from completion --- tools/lammps-gui/codeeditor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lammps-gui/codeeditor.cpp b/tools/lammps-gui/codeeditor.cpp index 7a1624c192..b7a14871b7 100644 --- a/tools/lammps-gui/codeeditor.cpp +++ b/tools/lammps-gui/codeeditor.cpp @@ -1009,7 +1009,7 @@ void CodeEditor::insertCompletedCommand(const QString &completion) } cursor.setPosition(cursor.position() - cursor.positionInBlock() + begin + 1); - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, end - begin); + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, end - begin - 1); cursor.insertText(completion); setTextCursor(cursor); } From bb7e8c66edfedccb7f192d06a6a1595f2c931b13 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 11 Oct 2023 08:26:50 -0400 Subject: [PATCH 07/21] clarify --- doc/src/pair_reaxff.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/src/pair_reaxff.rst b/doc/src/pair_reaxff.rst index 4dac9baf85..067eb3afc3 100644 --- a/doc/src/pair_reaxff.rst +++ b/doc/src/pair_reaxff.rst @@ -43,22 +43,22 @@ Examples Description """"""""""" -Style *reaxff* computes the ReaxFF potential of van Duin, Goddard and -co-workers. ReaxFF uses distance-dependent bond-order functions to +Pair style *reaxff* computes the ReaxFF potential of van Duin, Goddard +and co-workers. ReaxFF uses distance-dependent bond-order functions to represent the contributions of chemical bonding to the potential -energy. There is more than one version of ReaxFF. The version +energy. There is more than one version of ReaxFF. The version implemented in LAMMPS uses the functional forms documented in the supplemental information of the following paper: -:ref:`(Chenoweth et al., 2008) `. The version integrated -into LAMMPS matches the version of ReaxFF From Summer 2010. For more -technical details about the pair reaxff implementation of ReaxFF, see -the :ref:`(Aktulga) ` paper. The *reaxff* style was initially -implemented as a stand-alone C code and is now converted to C++ and -integrated into LAMMPS as a package. +:ref:`(Chenoweth et al., 2008) ` and matches the +version of the reference ReaxFF implementation from Summer 2010. For +more technical details about the implementation of ReaxFF in pair style +*reaxff*, see the :ref:`(Aktulga) ` paper. The *reaxff* style +was initially implemented as a stand-alone C code and is now converted +to C++ and integrated into LAMMPS as a package. The *reaxff/kk* style is a Kokkos version of the ReaxFF potential that -is derived from the *reaxff* style. The Kokkos version can run on GPUs -and can also use OpenMP multithreading. For more information about the +is derived from the *reaxff* style. The Kokkos version can run on GPUs +and can also use OpenMP multithreading. For more information about the Kokkos package, see :doc:`Packages details ` and :doc:`Speed kokkos ` doc pages. One important consideration when using the *reaxff/kk* style is the choice of either From 45172d33a9c2296111e341260912b5cb380e5aac Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 11 Oct 2023 09:20:05 -0400 Subject: [PATCH 08/21] use potential file name distributed with LAMMPS in examples --- doc/src/pair_ilp_tmd.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/src/pair_ilp_tmd.rst b/doc/src/pair_ilp_tmd.rst index 482d75a100..70a4768389 100644 --- a/doc/src/pair_ilp_tmd.rst +++ b/doc/src/pair_ilp_tmd.rst @@ -22,12 +22,12 @@ Examples .. code-block:: LAMMPS pair_style hybrid/overlay ilp/tmd 16.0 1 - pair_coeff * * ilp/tmd TMD.ILP Mo S S + pair_coeff * * ilp/tmd MoS2.ILP Mo S S pair_style hybrid/overlay sw/mod sw/mod ilp/tmd 16.0 pair_coeff * * sw/mod 1 tmd.sw.mod Mo S S NULL NULL NULL pair_coeff * * sw/mod 2 tmd.sw.mod NULL NULL NULL Mo S S - pair_coeff * * ilp/tmd TMD.ILP Mo S S Mo S S + pair_coeff * * ilp/tmd MoS2.ILP Mo S S Mo S S Description """"""""""" @@ -69,7 +69,7 @@ calculating the normals. each atom `i`, its six nearest neighboring atoms belonging to the same sub-layer are chosen to define the normal vector `{\bf n}_i`. -The parameter file (e.g. TMD.ILP), is intended for use with *metal* +The parameter file (e.g. MoS2.ILP), is intended for use with *metal* :doc:`units `, with energies in meV. Two additional parameters, *S*, and *rcut* are included in the parameter file. *S* is designed to facilitate scaling of energies. *rcut* is designed to build the neighbor @@ -77,7 +77,7 @@ list for calculating the normals for each atom pair. .. note:: - The parameters presented in the parameter file (e.g. TMD.ILP), + The parameters presented in the parameter file (e.g. MoS2.ILP), are fitted with taper function by setting the cutoff equal to 16.0 Angstrom. Using different cutoff or taper function should be careful. These parameters provide a good description in both short- and long-range @@ -133,10 +133,10 @@ if LAMMPS was built with that package. See the :doc:`Build package This pair style requires the newton setting to be *on* for pair interactions. -The TMD.ILP potential file provided with LAMMPS (see the potentials +The MoS2.ILP potential file provided with LAMMPS (see the potentials directory) are parameterized for *metal* units. You can use this potential with any LAMMPS units, but you would need to create your own -custom TMD.ILP potential file with coefficients listed in the appropriate +custom MoS2.ILP potential file with coefficients listed in the appropriate units, if your simulation does not use *metal* units. Related commands From fbdd61e28c814ba21a1c2e774386d1f469fc0981 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 11 Oct 2023 18:15:13 -0400 Subject: [PATCH 09/21] enable spacefilling sphere option also for systems with per-atom radius --- tools/lammps-gui/imageviewer.cpp | 14 +++++++++----- tools/lammps-gui/imageviewer.h | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index 86be0b66df..ee81f61253 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -131,7 +131,7 @@ static const QString blank(" "); ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidget *parent) : QDialog(parent), menuBar(new QMenuBar), imageLabel(new QLabel), scrollArea(new QScrollArea), - lammps(_lammps), group("all"), filename(fileName), useelements(false) + lammps(_lammps), group("all"), filename(fileName), useelements(false), usediameter(false) { imageLabel->setBackgroundRole(QPalette::Base); imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); @@ -268,7 +268,7 @@ ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidge // properties directly since lookup in reset_view() will have failed dobox->setChecked(showbox); dovdw->setChecked(vdwfactor > 1.0); - dovdw->setEnabled(useelements); + dovdw->setEnabled(useelements || usediameter); doaxes->setChecked(showaxes); dossao->setChecked(usessao); doanti->setChecked(antialias); @@ -435,7 +435,7 @@ void ImageViewer::createImage() dumpcmd += "'" + dumpfile.fileName() + "'"; settings.beginGroup("snapshot"); - int hhrot = (hrot > 180) ? 360 - hrot : hrot; + int hhrot = (hrot > 180) ? 360 - hrot : hrot; // determine elements from masses and set their covalent radii int ntypes = lammps->extract_setting("ntypes"); @@ -454,9 +454,10 @@ void ImageViewer::createImage() adiams += QString("adiam %1 %2 ").arg(i).arg(vdwfactor * pte_vdw_radius[idx]); } } + usediameter = lammps->extract_setting("radius_flag") != 0; // adjust pushbutton state and clear adiams string to disable VDW display, if needed - if (useelements) { + if (useelements || usediameter) { auto *button = findChild("vdw"); if (button) button->setEnabled(true); } else { @@ -469,7 +470,10 @@ void ImageViewer::createImage() dumpcmd += blank + "element"; else dumpcmd += blank + settings.value("color", "type").toString(); - dumpcmd += blank + settings.value("diameter", "type").toString(); + if (usediameter && (vdwfactor > 1.0)) + dumpcmd += blank + "diameter"; + else + dumpcmd += blank + settings.value("diameter", "type").toString(); dumpcmd += QString(" size %1 %2").arg(xsize).arg(ysize); dumpcmd += QString(" zoom %1").arg(zoom); dumpcmd += " shiny 0.5 "; diff --git a/tools/lammps-gui/imageviewer.h b/tools/lammps-gui/imageviewer.h index 8946c6cc8b..1be7790666 100644 --- a/tools/lammps-gui/imageviewer.h +++ b/tools/lammps-gui/imageviewer.h @@ -88,7 +88,7 @@ private: int xsize, ysize; int hrot, vrot; double zoom, vdwfactor; - bool showbox, showaxes, antialias, usessao, useelements; + bool showbox, showaxes, antialias, usessao, useelements, usediameter; }; #endif From 26133bd26ad1251dd43e16c34f988997fa792b09 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 12 Oct 2023 16:29:01 -0400 Subject: [PATCH 10/21] Revert "restore GNU make build capability for ML-PACE" This reverts commit 2b1985f755fb5019f03d4e76b6174808e7f543c1. --- lib/pace/Makefile | 6 +++--- lib/pace/Makefile.lammps | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pace/Makefile b/lib/pace/Makefile index 37f00ee70e..5a1588ef93 100644 --- a/lib/pace/Makefile +++ b/lib/pace/Makefile @@ -1,5 +1,4 @@ SHELL = /bin/sh -CMAKE= cmake # ------ FILES ------ @@ -36,7 +35,7 @@ lib: $(OBJ) lib-yaml-cpp lib-yaml-cpp: - cd $(YAML_CPP_PATH) && $(CMAKE) . && $(MAKE) all + cd $(YAML_CPP_PATH) && $(MAKE) lib # ------ COMPILE RULES ------ @@ -46,8 +45,9 @@ lib-yaml-cpp: # ------ CLEAN ------ clean-all: -rm -f *~ $(OBJ) $(LIB) - cd $(YAML_CPP_PATH) && $(MAKE) clean + cd $(YAML_CPP_PATH) && $(MAKE) clean-all clean-build: -rm -f *~ $(OBJ) + cd $(YAML_CPP_PATH) && $(MAKE) clean-build diff --git a/lib/pace/Makefile.lammps b/lib/pace/Makefile.lammps index 1c549e31d0..6411e49a07 100644 --- a/lib/pace/Makefile.lammps +++ b/lib/pace/Makefile.lammps @@ -1,3 +1,3 @@ pace_SYSINC =-I../../lib/pace/src/ML-PACE -I../../lib/pace/src/yaml-cpp/include -I../../lib/pace/src/wigner-cpp/include -DEXTRA_C_PROJECTIONS -pace_SYSLIB = -L../../lib/pace/ -lpace -L../../lib/pace/src/yaml-cpp/ -lyaml-cpp-pace +pace_SYSLIB = -L../../lib/pace/ -lpace -L../../lib/pace/src/yaml-cpp/ -lyaml-cpp pace_SYSPATH = From 1a9dac83d7513e9dad2815b2a291f7b810eaa3a6 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 12 Oct 2023 21:52:32 -0400 Subject: [PATCH 11/21] update fix srd docs --- doc/src/fix_srd.rst | 49 +++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/doc/src/fix_srd.rst b/doc/src/fix_srd.rst index 1fc574a7ad..8bfbcf2387 100644 --- a/doc/src/fix_srd.rst +++ b/doc/src/fix_srd.rst @@ -71,14 +71,15 @@ imbue the SRD particles with fluid-like properties, including an effective viscosity. Thus simulations with large solute particles can be run more quickly, to measure solute properties like diffusivity and viscosity in a background fluid. The usual LAMMPS fixes for such -simulations, such as :doc:`fix deform `, :doc:`fix viscosity `, and :doc:`fix nvt/sllod `, +simulations, such as :doc:`fix deform `, +:doc:`fix viscosity `, and :doc:`fix nvt/sllod `, can be used in conjunction with the SRD model. -For more details on how the SRD model is implemented in LAMMPS, :ref:`this paper ` describes the implementation and usage of pure SRD -fluids. :ref:`This paper `, which is nearly complete, describes -the implementation and usage of mixture systems (solute particles in -an SRD fluid). See the examples/srd directory for sample input -scripts using SRD particles in both settings. +For more details on how the SRD model is implemented in LAMMPS, +:ref:`(Petersen) ` describes the implementation and usage of +pure SRD fluids. See the ``examples/srd`` directory for sample input +scripts using SRD particles for that and for mixture systems (solute +particles in an SRD fluid). This fix does two things: @@ -357,28 +358,28 @@ These are the 12 quantities. All are values for the current timestep, except for quantity 5 and the last three, each of which are cumulative quantities since the beginning of the run. -* (1) # of SRD/big collision checks performed -* (2) # of SRDs which had a collision -* (3) # of SRD/big collisions (including multiple bounces) -* (4) # of SRD particles inside a big particle -* (5) # of SRD particles whose velocity was rescaled to be < Vmax -* (6) # of bins for collision searching -* (7) # of bins for SRD velocity rotation -* (8) # of bins in which SRD temperature was computed -* (9) SRD temperature -* (10) # of SRD particles which have undergone max # of bounces -* (11) max # of bounces any SRD particle has had in a single step -* (12) # of reneighborings due to SRD particles moving too far +(1) # of SRD/big collision checks performed +(2) # of SRDs which had a collision +(3) # of SRD/big collisions (including multiple bounces) +(4) # of SRD particles inside a big particle +(5) # of SRD particles whose velocity was rescaled to be < Vmax +(6) # of bins for collision searching +(7) # of bins for SRD velocity rotation +(8) # of bins in which SRD temperature was computed +(9) SRD temperature +(10) # of SRD particles which have undergone max # of bounces +(11) max # of bounces any SRD particle has had in a single step +(12) # of reneighborings due to SRD particles moving too far No parameter of this fix can be used with the *start/stop* keywords of -the :doc:`run ` command. This fix is not invoked during :doc:`energy minimization `. +the :doc:`run ` command. This fix is not invoked during +:doc:`energy minimization `. Restrictions """""""""""" -This command can only be used if LAMMPS was built with the SRD -package. See the :doc:`Build package ` doc -page for more info. +This command can only be used if LAMMPS was built with the SRD package. +See the :doc:`Build package ` doc page for more info. Related commands """""""""""""""" @@ -403,7 +404,3 @@ no, and rescale = yes. **(Petersen)** Petersen, Lechman, Plimpton, Grest, in' t Veld, Schunk, J Chem Phys, 132, 174106 (2010). - -.. _Lechman: - -**(Lechman)** Lechman, et al, in preparation (2010). From 6ad5c0eced4a80b80a0c9b7aa2c3d8ee23450408 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 12 Oct 2023 23:24:11 -0400 Subject: [PATCH 12/21] port LAMMPS GUI to Qt6 while still supporting Qt5 --- tools/lammps-gui/CMakeLists.txt | 41 +++++++++++++++++++++++++------- tools/lammps-gui/chartviewer.cpp | 12 ++++++++-- tools/lammps-gui/chartviewer.h | 24 ++++++++++++------- tools/lammps-gui/lammpsgui.cpp | 16 ++++++++----- tools/lammps-gui/lammpsgui.h | 2 ++ 5 files changed, 71 insertions(+), 24 deletions(-) diff --git a/tools/lammps-gui/CMakeLists.txt b/tools/lammps-gui/CMakeLists.txt index 44fc45c0e2..83d5dc3216 100644 --- a/tools/lammps-gui/CMakeLists.txt +++ b/tools/lammps-gui/CMakeLists.txt @@ -11,6 +11,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) option(LAMMPS_GUI_USE_PLUGIN "Load LAMMPS library dynamically at runtime" OFF) mark_as_advanced(LAMMPS_GUI_USE_PLUGIN) +option(LAMMPS_GUI_USE_QT5 "Prefer using Qt5 over Qt6" OFF) # checks # when this file is included as subdirectory in the LAMMPS build, many settings are directly imported @@ -73,7 +74,15 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows") endif() # we require Qt 5 and at least version 5.12 at that. -find_package(Qt5 5.12 REQUIRED COMPONENTS Widgets Charts) +if(NOT LAMMPS_GUI_USE_QT5) + find_package(Qt6 6.2 COMPONENTS Widgets Charts) +endif() +if(NOT Qt6_FOUND) + find_package(Qt5 5.12 REQUIRED COMPONENTS Widgets Charts) + set(QT_VERSION_MAJOR "5") +else() + set(QT_VERSION_MAJOR "6") +endif() set(PROJECT_SOURCES main.cpp @@ -105,7 +114,11 @@ set(PROJECT_SOURCES ${PLUGIN_LOADER_SRC} ${ICON_RC_FILE} ) -qt5_add_resources(PROJECT_SOURCES lammpsgui.qrc) +if(QT_VERSION_MAJOR EQUAL 6) + qt6_add_resources(PROJECT_SOURCES lammpsgui.qrc) +else() + qt5_add_resources(PROJECT_SOURCES lammpsgui.qrc) +endif() if(APPLE) set(MACOSX_ICON_FILE ${LAMMPS_DIR}/cmake/packaging/lammps.icns) @@ -113,10 +126,22 @@ if(APPLE) set(MACOSX_BACKGROUND_FILE ${LAMMPS_DIR}/cmake/packaging/LAMMPS_DMG_Background.png) endif() -add_executable(lammps-gui - ${MACOSX_ICON_FILE} - ${PROJECT_SOURCES} -) +if(QT_VERSION_MAJOR EQUAL 6) + qt_add_executable(lammps-gui + MANUAL_FINALIZATION + ${MACOSX_ICON_FILE} + ${PROJECT_SOURCES} + ) +else() + add_executable(lammps-gui + ${MACOSX_ICON_FILE} + ${PROJECT_SOURCES} + ) +endif() + +if(QT_VERSION_MAJOR EQUAL 6) + qt_finalize_executable(lammps-gui) +endif() # compilation settings if(LAMMPS_GUI_USE_PLUGIN) @@ -128,7 +153,7 @@ else() endif() target_include_directories(lammps-gui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(lammps-gui PRIVATE LAMMPS_GUI_VERSION="${PROJECT_VERSION}") -target_link_libraries(lammps-gui PRIVATE Qt5::Widgets Qt5::Charts) +target_link_libraries(lammps-gui PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${VERSION_MAJOR}::Charts) if(BUILD_OMP) find_package(OpenMP COMPONENTS CXX REQUIRED) target_link_libraries(lammps-gui PRIVATE OpenMP::OpenMP_CXX) @@ -209,7 +234,7 @@ elseif((CMAKE_SYSTEM_NAME STREQUAL "Windows") AND CMAKE_CROSSCOMPILING) COMMENT "Create zip file with windows binaries" BYPRODUCT LAMMPS-Win10-amd64.zip WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") +elseif((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND NOT LAMMPS_GUI_USE_PLUGIN) 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/) diff --git a/tools/lammps-gui/chartviewer.cpp b/tools/lammps-gui/chartviewer.cpp index f28625d9dc..ab03a110b5 100644 --- a/tools/lammps-gui/chartviewer.cpp +++ b/tools/lammps-gui/chartviewer.cpp @@ -15,11 +15,19 @@ #include "lammpsgui.h" +#include +#include +#include #include +#include +#include #include +#include +#include #include #include #include +#include #include using namespace QtCharts; @@ -288,7 +296,7 @@ void ChartViewer::add_data(int step, double data) if (last_step < step) { last_step = step; series->append(step, data); - auto points = series->pointsVector(); + auto points = series->points(); qreal xmin = 1.0e100; qreal xmax = -1.0e100; @@ -309,7 +317,7 @@ void ChartViewer::add_data(int step, double data) void ChartViewer::reset_zoom() { - auto points = series->pointsVector(); + auto points = series->points(); qreal xmin = 1.0e100; qreal xmax = -1.0e100; diff --git a/tools/lammps-gui/chartviewer.h b/tools/lammps-gui/chartviewer.h index 248fdad7bb..0954f4a9a8 100644 --- a/tools/lammps-gui/chartviewer.h +++ b/tools/lammps-gui/chartviewer.h @@ -14,16 +14,17 @@ #ifndef CHARTVIEWER_H #define CHARTVIEWER_H +#include #include #include #include -#include class QAction; class QMenuBar; class QMenu; -class QComboBox; +namespace QtCharts { class ChartViewer; +} class ChartWindow : public QWidget { Q_OBJECT @@ -64,12 +65,18 @@ private: QAction *closeAct, *stopAct, *quitAct; QString filename; - QList charts; + QList charts; }; /* -------------------------------------------------------------------- */ -class ChartViewer : public QtCharts::QChartView { +#include +#include +#include +#include + +namespace QtCharts { +class ChartViewer : public QChartView { Q_OBJECT public: @@ -86,11 +93,12 @@ public: private: int last_step, index; - QtCharts::QChart *chart; - QtCharts::QLineSeries *series; - QtCharts::QValueAxis *xaxis; - QtCharts::QValueAxis *yaxis; + QChart *chart; + QLineSeries *series; + QValueAxis *xaxis; + QValueAxis *yaxis; }; +} // namespace QtCharts #endif // Local Variables: diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp index ba080dbec3..e0bcb38dc6 100644 --- a/tools/lammps-gui/lammpsgui.cpp +++ b/tools/lammps-gui/lammpsgui.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -69,8 +70,10 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) : // enforce using the plain ASCII C locale within the GUI. QLocale::setDefault(QLocale("C")); - // register QList +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + // register QList only needed for Qt5 qRegisterMetaTypeStreamOperators>("QList"); +#endif ui->setupUi(this); this->setCentralWidget(ui->textEdit); @@ -588,7 +591,8 @@ void LammpsGui::open_file(const QString &fileName) if (!file.open(QIODevice::ReadOnly | QFile::Text)) { QMessageBox::warning(this, "Warning", "Cannot open file " + path.absoluteFilePath() + ": " + - file.errorString() + ".\nWill create new file on saving editor buffer."); + file.errorString() + + ".\nWill create new file on saving editor buffer."); ui->textEdit->document()->setPlainText(QString()); } else { QTextStream in(&file); @@ -1039,9 +1043,9 @@ void LammpsGui::do_run(bool use_buffer) logwindow->document()->setDefaultFont(text_font); logwindow->setLineWrapMode(LogWindow::NoWrap); logwindow->setMinimumSize(400, 300); - QShortcut *shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), logwindow); + QShortcut *shortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_W), logwindow); QObject::connect(shortcut, &QShortcut::activated, logwindow, &LogWindow::close); - shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Slash), logwindow); + shortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Slash), logwindow); QObject::connect(shortcut, &QShortcut::activated, this, &LammpsGui::stop_run); if (settings.value("viewlog", true).toBool()) logwindow->show(); @@ -1058,9 +1062,9 @@ void LammpsGui::do_run(bool use_buffer) .arg(run_counter)); chartwindow->setWindowIcon(QIcon(":/icons/lammps-icon-128x128.png")); chartwindow->setMinimumSize(400, 300); - shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), chartwindow); + 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); + 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(); diff --git a/tools/lammps-gui/lammpsgui.h b/tools/lammps-gui/lammpsgui.h index 0c622f0285..0dd34f2c49 100644 --- a/tools/lammps-gui/lammpsgui.h +++ b/tools/lammps-gui/lammpsgui.h @@ -16,8 +16,10 @@ #include +#include #include #include +#include #include #include From 506de7015df9c6049033f9084a6cf62420ef2b5e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 13 Oct 2023 05:13:30 -0400 Subject: [PATCH 13/21] document support for building LAMMPS GUI with Qt6 --- doc/src/Tools.rst | 15 +++++++++++---- tools/lammps-gui/TODO.md | 1 - 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/doc/src/Tools.rst b/doc/src/Tools.rst index a42e7c56a5..49022a4ee9 100644 --- a/doc/src/Tools.rst +++ b/doc/src/Tools.rst @@ -702,11 +702,15 @@ Prerequisites and portability LAMMPS GUI is programmed in C++ based on the C++11 standard and using the `Qt GUI framework `_. Currently, Qt version 5.12 or later is required; Qt 5.15LTS is -recommended; Qt 6.x not (yet) supported. Building LAMMPS with CMake is -required. The LAMMPS GUI has been successfully compiled and tested on: +recommended; support for Qt version 6.x is under active development and +thus far only tested with Qt 6.5LTS on Linux. Building LAMMPS with +CMake is required. + +The LAMMPS GUI has been successfully compiled and tested on: - Ubuntu Linux 20.04LTS x86_64 using GCC 9, Qt version 5.12 - Fedora Linux 38 x86\_64 using GCC 13 and Clang 16, Qt version 5.15LTS +- Fedora Linux 38 x86\_64 using GCC 13, Qt version 6.5LTS - Apple macOS 12 (Monterey) and macOS 13 (Ventura) with Xcode on arm64 and x86\_64, Qt version 5.15LTS - Windows 10 and 11 x86_64 with Visual Studio 2022 and Visual C++ 14.36, Qt version 5.15LTS - Windows 10 and 11 x86_64 with MinGW / GCC 10.0 cross-compiler on Fedora 38, Qt version 5.15LTS @@ -717,7 +721,7 @@ required. The LAMMPS GUI has been successfully compiled and tested on: Pre-compiled executables ^^^^^^^^^^^^^^^^^^^^^^^^ -Pre-compiled LAMMPS executables including the GUI are currently +Pre-compiled LAMMPS executable packages that include the GUI are currently available from https://download.lammps.org/static or https://github.com/lammps/lammps/releases. You can unpack the archives (or mount the macOS disk image) and run the GUI directly in place. The @@ -742,7 +746,10 @@ 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``. +``Qt5Config.cmake``. Similarly, for Qt6 the location of the Qt library +installation can be indicated by setting ``-D Qt6_DIR=/path/to/qt6/lib/cmake/Qt6``, +if necessary. When both, Qt5 and Qt6 are available, Qt6 will be preferred +unless ``-D LAMMPS_GUI_USE_QT5=yes`` is set. It should be possible to build the LAMMPS GUI as a standalone compilation (e.g. when LAMMPS has been compiled with traditional make), diff --git a/tools/lammps-gui/TODO.md b/tools/lammps-gui/TODO.md index e4ca44ba3d..ee05e67225 100644 --- a/tools/lammps-gui/TODO.md +++ b/tools/lammps-gui/TODO.md @@ -23,7 +23,6 @@ LAMMPS-GUI TODO list: # Long term ideas (v2.x) - rewrite entire application to build the App and its layout manually -- port to Qt6 (with compatibility to Qt5?) - 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 From 6195be5af72baea2a7cd8870b3c0bdb615401da7 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 13 Oct 2023 05:59:20 -0400 Subject: [PATCH 14/21] make keyboard shortcut handling consistent across the entire app --- tools/lammps-gui/chartviewer.cpp | 7 ++++--- tools/lammps-gui/imageviewer.cpp | 5 +++-- tools/lammps-gui/logwindow.cpp | 32 +++++++++++++++++++++++++++----- tools/lammps-gui/logwindow.h | 1 + tools/lammps-gui/slideshow.cpp | 7 ++++--- 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/tools/lammps-gui/chartviewer.cpp b/tools/lammps-gui/chartviewer.cpp index ab03a110b5..ee29ab9540 100644 --- a/tools/lammps-gui/chartviewer.cpp +++ b/tools/lammps-gui/chartviewer.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -61,13 +62,13 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) : file->addSeparator(); stopAct = file->addAction("Stop &Run", this, &ChartWindow::stop_run); stopAct->setIcon(QIcon(":/icons/process-stop.png")); - stopAct->setShortcut(QKeySequence::fromString("Ctrl+/")); + stopAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Slash)); closeAct = file->addAction("&Close", this, &QWidget::close); closeAct->setIcon(QIcon(":/icons/window-close.png")); - closeAct->setShortcut(QKeySequence::fromString("Ctrl+W")); + closeAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_W)); quitAct = file->addAction("&Quit", this, &ChartWindow::quit); quitAct->setIcon(QIcon(":/icons/application-exit.png")); - quitAct->setShortcut(QKeySequence::fromString("Ctrl+Q")); + quitAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q)); auto *layout = new QVBoxLayout; layout->addLayout(top); setLayout(layout); diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index ee81f61253..7406f1860a 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -558,10 +559,10 @@ void ImageViewer::createActions() fileMenu->addSeparator(); QAction *exitAct = fileMenu->addAction("&Close", this, &QWidget::close); exitAct->setIcon(QIcon(":/icons/window-close.png")); - exitAct->setShortcut(QKeySequence::fromString("Ctrl+W")); + exitAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_W)); QAction *quitAct = fileMenu->addAction("&Quit", this, &ImageViewer::quit); quitAct->setIcon(QIcon(":/icons/application-exit.png")); - quitAct->setShortcut(QKeySequence::fromString("Ctrl+Q")); + quitAct->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q)); } void ImageViewer::updateActions() diff --git a/tools/lammps-gui/logwindow.cpp b/tools/lammps-gui/logwindow.cpp index ab1886f1bd..374c4c89b1 100644 --- a/tools/lammps-gui/logwindow.cpp +++ b/tools/lammps-gui/logwindow.cpp @@ -35,12 +35,14 @@ LogWindow::LogWindow(const QString &_filename, QWidget *parent) : QSettings settings; resize(settings.value("logx", 500).toInt(), settings.value("logy", 320).toInt()); - auto action = new QShortcut(QKeySequence::fromString("Ctrl+S"), this); + auto action = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_S), this); connect(action, &QShortcut::activated, this, &LogWindow::save_as); - action = new QShortcut(QKeySequence::fromString("Ctrl+Q"), this); + action = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q), this); connect(action, &QShortcut::activated, this, &LogWindow::quit); - action = new QShortcut(QKeySequence(Qt::Key_Slash, Qt::CTRL), this); + action = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Slash), this); connect(action, &QShortcut::activated, this, &LogWindow::stop_run); + + installEventFilter(this); } void LogWindow::closeEvent(QCloseEvent *event) @@ -99,15 +101,35 @@ void LogWindow::contextMenuEvent(QContextMenuEvent *event) menu->addSeparator(); auto action = menu->addAction(QString("Save Log to File ...")); action->setIcon(QIcon(":/icons/document-save-as.png")); - action->setShortcut(QKeySequence::fromString("Ctrl+S")); + action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_S)); connect(action, &QAction::triggered, this, &LogWindow::save_as); action = menu->addAction("&Close Window", this, &QWidget::close); action->setIcon(QIcon(":/icons/window-close.png")); - action->setShortcut(QKeySequence::fromString("Ctrl+W")); + action->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_W)); menu->exec(event->globalPos()); delete menu; } +// event filter to handle "Ambiguous shortcut override" issues +bool LogWindow::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == QEvent::ShortcutOverride) { + QKeyEvent *keyEvent = dynamic_cast(event); + if (!keyEvent) return QWidget::eventFilter(watched, event); + if (keyEvent->modifiers().testFlag(Qt::ControlModifier) && keyEvent->key() == '/') { + stop_run(); + event->accept(); + return true; + } + if (keyEvent->modifiers().testFlag(Qt::ControlModifier) && keyEvent->key() == 'W') { + close(); + event->accept(); + return true; + } + } + return QWidget::eventFilter(watched, event); +} + // Local Variables: // c-basic-offset: 4 // End: diff --git a/tools/lammps-gui/logwindow.h b/tools/lammps-gui/logwindow.h index 8923e35ee5..ad0691d0cc 100644 --- a/tools/lammps-gui/logwindow.h +++ b/tools/lammps-gui/logwindow.h @@ -30,6 +30,7 @@ private slots: protected: void closeEvent(QCloseEvent *event) override; void contextMenuEvent(QContextMenuEvent *event) override; + bool eventFilter(QObject *watched, QEvent *event) override; private: QString filename; diff --git a/tools/lammps-gui/slideshow.cpp b/tools/lammps-gui/slideshow.cpp index de7742f22f..92eca9a530 100644 --- a/tools/lammps-gui/slideshow.cpp +++ b/tools/lammps-gui/slideshow.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -50,11 +51,11 @@ SlideShow::SlideShow(const QString &fileName, QWidget *parent) : imageName->setAlignment(Qt::AlignCenter); imageName->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - auto *shortcut = new QShortcut(QKeySequence::fromString("Ctrl+W"), this); + auto *shortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_W), this); QObject::connect(shortcut, &QShortcut::activated, this, &QWidget::close); - shortcut = new QShortcut(QKeySequence::fromString("Ctrl+/"), this); + shortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Slash), this); QObject::connect(shortcut, &QShortcut::activated, this, &SlideShow::stop_run); - shortcut = new QShortcut(QKeySequence::fromString("Ctrl+Q"), this); + shortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q), this); QObject::connect(shortcut, &QShortcut::activated, this, &SlideShow::quit); buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); From 3ebcb0f6f18cf68c38ae89a4c0b65911fda5c90d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 13 Oct 2023 06:00:29 -0400 Subject: [PATCH 15/21] store settings to different locations for different Qt versions --- tools/lammps-gui/lammpsgui.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp index e0bcb38dc6..11f2554b55 100644 --- a/tools/lammps-gui/lammpsgui.cpp +++ b/tools/lammps-gui/lammpsgui.cpp @@ -84,9 +84,13 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) : // use $HOME if we get dropped to "/" like on macOS if (current_dir == "/") current_dir = QDir::homePath(); +#define stringify(x) myxstr(x) +#define myxstr(x) #x QCoreApplication::setOrganizationName("The LAMMPS Developers"); QCoreApplication::setOrganizationDomain("lammps.org"); - QCoreApplication::setApplicationName("LAMMPS GUI"); + QCoreApplication::setApplicationName("LAMMPS GUI - QT" stringify(QT_VERSION_MAJOR)); +#undef stringify +#undef myxstr // restore and initialize settings QSettings settings; From 262913695824a407091b16a493cd1165f0fff591 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 13 Oct 2023 06:18:34 -0400 Subject: [PATCH 16/21] avoid uninitialized data access and segfaults when calling main widget functions --- tools/lammps-gui/chartviewer.cpp | 8 ++++---- tools/lammps-gui/imageviewer.cpp | 4 ++-- tools/lammps-gui/logwindow.cpp | 8 ++++---- tools/lammps-gui/preferences.cpp | 4 ++-- tools/lammps-gui/slideshow.cpp | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/lammps-gui/chartviewer.cpp b/tools/lammps-gui/chartviewer.cpp index ee29ab9540..c981b2777d 100644 --- a/tools/lammps-gui/chartviewer.cpp +++ b/tools/lammps-gui/chartviewer.cpp @@ -124,10 +124,10 @@ void ChartWindow::add_data(int step, double data, int index) void ChartWindow::quit() { - LammpsGui *main; + LammpsGui *main = nullptr; for (QWidget *widget : QApplication::topLevelWidgets()) if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); - main->quit(); + if (main) main->quit(); } void ChartWindow::reset_zoom() @@ -138,10 +138,10 @@ void ChartWindow::reset_zoom() void ChartWindow::stop_run() { - LammpsGui *main; + LammpsGui *main = nullptr; for (QWidget *widget : QApplication::topLevelWidgets()) if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); - main->stop_run(); + if (main) main->stop_run(); } void ChartWindow::saveAs() diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index 7406f1860a..00b08f3f47 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -533,10 +533,10 @@ void ImageViewer::copy() {} void ImageViewer::quit() { - LammpsGui *main; + LammpsGui *main = nullptr; for (QWidget *widget : QApplication::topLevelWidgets()) if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); - main->quit(); + if (main) main->quit(); } void ImageViewer::saveFile(const QString &fileName) diff --git a/tools/lammps-gui/logwindow.cpp b/tools/lammps-gui/logwindow.cpp index 374c4c89b1..73ec81d06c 100644 --- a/tools/lammps-gui/logwindow.cpp +++ b/tools/lammps-gui/logwindow.cpp @@ -57,18 +57,18 @@ void LogWindow::closeEvent(QCloseEvent *event) void LogWindow::quit() { - LammpsGui *main; + LammpsGui *main = nullptr; for (QWidget *widget : QApplication::topLevelWidgets()) if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); - main->quit(); + if (main) main->quit(); } void LogWindow::stop_run() { - LammpsGui *main; + LammpsGui *main = nullptr; for (QWidget *widget : QApplication::topLevelWidgets()) if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); - main->stop_run(); + if (main) main->stop_run(); } void LogWindow::save_as() diff --git a/tools/lammps-gui/preferences.cpp b/tools/lammps-gui/preferences.cpp index c760e6610b..f7fe9ec025 100644 --- a/tools/lammps-gui/preferences.cpp +++ b/tools/lammps-gui/preferences.cpp @@ -286,12 +286,12 @@ GeneralTab::GeneralTab(QSettings *_settings, LammpsWrapper *_lammps, QWidget *pa void GeneralTab::updatefonts(const QFont &all, const QFont &text) { - LammpsGui *main; + LammpsGui *main = nullptr; for (QWidget *widget : QApplication::topLevelWidgets()) if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); QApplication::setFont(all); - main->ui->textEdit->document()->setDefaultFont(text); + if (main) main->ui->textEdit->document()->setDefaultFont(text); } void GeneralTab::newallfont() diff --git a/tools/lammps-gui/slideshow.cpp b/tools/lammps-gui/slideshow.cpp index 92eca9a530..140c703ca3 100644 --- a/tools/lammps-gui/slideshow.cpp +++ b/tools/lammps-gui/slideshow.cpp @@ -199,18 +199,18 @@ void SlideShow::loadImage(int idx) void SlideShow::quit() { - LammpsGui *main; + LammpsGui *main = nullptr; for (QWidget *widget : QApplication::topLevelWidgets()) if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); - main->quit(); + if (main) main->quit(); } void SlideShow::stop_run() { - LammpsGui *main; + LammpsGui *main = nullptr; for (QWidget *widget : QApplication::topLevelWidgets()) if (widget->objectName() == "LammpsGui") main = dynamic_cast(widget); - main->stop_run(); + if (main) main->stop_run(); } void SlideShow::movie() From 926de1575c74d98cec2319c54ef4ddc2b75e4ad0 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 13 Oct 2023 06:18:56 -0400 Subject: [PATCH 17/21] avoid completion on empty lines --- tools/lammps-gui/codeeditor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lammps-gui/codeeditor.cpp b/tools/lammps-gui/codeeditor.cpp index b7a14871b7..f374b098e2 100644 --- a/tools/lammps-gui/codeeditor.cpp +++ b/tools/lammps-gui/codeeditor.cpp @@ -568,6 +568,7 @@ void CodeEditor::keyPressEvent(QKeyEvent *event) if (automatic_completion) { auto cursor = textCursor(); auto line = cursor.block().text(); + if (line.isEmpty()) return; // QTextCursor::WordUnderCursor is unusable here since recognizes '/' as word boundary. // Work around it by manually searching for the location of the beginning of the word. From 3db7e1f9cf3b370da126dbe9b4d667d108833735 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 13 Oct 2023 06:50:06 -0400 Subject: [PATCH 18/21] avoid invalid data accesses --- tools/lammps-gui/chartviewer.cpp | 5 ++++- tools/lammps-gui/chartviewer.h | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/lammps-gui/chartviewer.cpp b/tools/lammps-gui/chartviewer.cpp index c981b2777d..fbd888f1cd 100644 --- a/tools/lammps-gui/chartviewer.cpp +++ b/tools/lammps-gui/chartviewer.cpp @@ -85,7 +85,10 @@ int ChartWindow::get_step() const { if (charts.size() > 0) { auto *v = charts[0]; - return (int)v->get_step(v->get_count() - 1); + if (v) + return (int)v->get_step(v->get_count() - 1); + else + return -1; } else { return -1; } diff --git a/tools/lammps-gui/chartviewer.h b/tools/lammps-gui/chartviewer.h index 0954f4a9a8..da0468eaf8 100644 --- a/tools/lammps-gui/chartviewer.h +++ b/tools/lammps-gui/chartviewer.h @@ -88,8 +88,8 @@ public: 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(); } + double get_step(int index) const { return (index < 0) ? 0.0 : series->at(index).x(); } + double get_data(int index) const { return (index < 0) ? 0.0 : series->at(index).y(); } private: int last_step, index; From 50d2ebc27d7fd96cc94153540d953a02d9abd5bf Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 13 Oct 2023 06:50:52 -0400 Subject: [PATCH 19/21] auto-detect OpenMP support also when compiling a standalone binary --- tools/lammps-gui/CMakeLists.txt | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tools/lammps-gui/CMakeLists.txt b/tools/lammps-gui/CMakeLists.txt index 83d5dc3216..edfeeb1128 100644 --- a/tools/lammps-gui/CMakeLists.txt +++ b/tools/lammps-gui/CMakeLists.txt @@ -13,6 +13,41 @@ option(LAMMPS_GUI_USE_PLUGIN "Load LAMMPS library dynamically at runtime" OFF) mark_as_advanced(LAMMPS_GUI_USE_PLUGIN) option(LAMMPS_GUI_USE_QT5 "Prefer using Qt5 over Qt6" OFF) +include(CheckIncludeFileCXX) +# helper function to check for usable omp.h header +function(check_omp_h_include) + find_package(OpenMP COMPONENTS CXX QUIET) + if(OpenMP_CXX_FOUND) + set(CMAKE_REQUIRED_FLAGS ${OpenMP_CXX_FLAGS}) + set(CMAKE_REQUIRED_INCLUDES ${OpenMP_CXX_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_LINK_OPTIONS ${OpenMP_CXX_FLAGS}) + set(CMAKE_REQUIRED_LIBRARIES ${OpenMP_CXX_LIBRARIES}) + check_include_file_cxx(omp.h _have_omp_h) + else() + set(_have_omp_h FALSE) + endif() + set(HAVE_OMP_H_INCLUDE ${_have_omp_h} PARENT_SCOPE) +endfunction() + +# detect if we may enable OpenMP support by default +set(BUILD_OMP_DEFAULT OFF) +find_package(OpenMP COMPONENTS CXX QUIET) +if(OpenMP_CXX_FOUND) + check_omp_h_include() + if(HAVE_OMP_H_INCLUDE) + set(BUILD_OMP_DEFAULT ON) + endif() +endif() + +option(BUILD_OMP "Build with OpenMP support" ${BUILD_OMP_DEFAULT}) +if(BUILD_OMP) + find_package(OpenMP COMPONENTS CXX REQUIRED) + check_omp_h_include() + if(NOT HAVE_OMP_H_INCLUDE) + message(FATAL_ERROR "Cannot find the 'omp.h' header file required for full OpenMP support") + endif() +endif() + # checks # when this file is included as subdirectory in the LAMMPS build, many settings are directly imported if(LAMMPS_DIR) From 2f6782636382e25eb832292606951ac387d2a3e7 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 13 Oct 2023 06:59:06 -0400 Subject: [PATCH 20/21] indicate whether multi-thread is available in preferences --- tools/lammps-gui/preferences.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/lammps-gui/preferences.cpp b/tools/lammps-gui/preferences.cpp index f7fe9ec025..fd01bb5046 100644 --- a/tools/lammps-gui/preferences.cpp +++ b/tools/lammps-gui/preferences.cpp @@ -410,11 +410,19 @@ AcceleratorTab::AcceleratorTab(QSettings *_settings, LammpsWrapper *_lammps, QWi #endif auto *choices = new QFrame; auto *choiceLayout = new QVBoxLayout; +#if defined(_OPENMP) auto *ntlabel = new QLabel(QString("Number of threads (max %1):").arg(maxthreads)); auto *ntchoice = new QLineEdit(settings->value("nthreads", maxthreads).toString()); +#else + auto *ntlabel = new QLabel(QString("Number of threads (OpenMP not available):")); + auto *ntchoice = new QLineEdit("1"); +#endif auto *intval = new QIntValidator(1, maxthreads, this); ntchoice->setValidator(intval); ntchoice->setObjectName("nthreads"); +#if !defined(_OPENMP) + ntchoice->setEnabled(false); +#endif choiceLayout->addWidget(ntlabel); choiceLayout->addWidget(ntchoice); From ae8791c6820ca858b809237aef7a229ae815ffbb Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 13 Oct 2023 08:17:10 -0400 Subject: [PATCH 21/21] avoid out of bounds access to string under cursor --- tools/lammps-gui/codeeditor.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/lammps-gui/codeeditor.cpp b/tools/lammps-gui/codeeditor.cpp index f374b098e2..e95f576be0 100644 --- a/tools/lammps-gui/codeeditor.cpp +++ b/tools/lammps-gui/codeeditor.cpp @@ -572,7 +572,8 @@ void CodeEditor::keyPressEvent(QKeyEvent *event) // QTextCursor::WordUnderCursor is unusable here since recognizes '/' as word boundary. // Work around it by manually searching for the location of the beginning of the word. - int begin = cursor.positionInBlock(); + int begin = qMin(cursor.positionInBlock(), line.length() - 1); + while (begin >= 0) { if (line[begin].isSpace()) break; --begin; @@ -749,7 +750,7 @@ void CodeEditor::runCompletion() // QTextCursor::WordUnderCursor is unusable here since it recognizes '/' as word boundary. // Work around it by manually searching for the beginning and end position of the word // under the cursor and then using that substring. - int begin = cursor.positionInBlock(); + int begin = qMin(cursor.positionInBlock(), line.length() - 1); line = cursor.block().text(); while (begin >= 0) { if (line[begin].isSpace()) break;