diff --git a/tools/lammps-gui/CMakeLists.txt b/tools/lammps-gui/CMakeLists.txt
index 057d686b12..3c49c4cd8a 100644
--- a/tools/lammps-gui/CMakeLists.txt
+++ b/tools/lammps-gui/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16)
-project(lammps-gui VERSION 1.6.11 LANGUAGES CXX)
+project(lammps-gui VERSION 1.6.12 LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
diff --git a/tools/lammps-gui/lammps-gui.appdata.xml b/tools/lammps-gui/lammps-gui.appdata.xml
index 1f74fc479c..a40f56d3d0 100644
--- a/tools/lammps-gui/lammps-gui.appdata.xml
+++ b/tools/lammps-gui/lammps-gui.appdata.xml
@@ -54,11 +54,17 @@
This wizard will help you to select and populate a folder with materials "
+ "required to work through tutorial %1 from the LAMMPS tutorials article by "
+ "Simon Gravelle, Jake Gissinger, and Axel Kohlmeyer.
github.com/"
+ "lammpstutorials/lammpstutorials-article
Click on the \"Next\" button to begin.
") + .arg(ntutorial)); + label->setWordWrap(true); + + auto *layout = new QVBoxLayout; + layout->addWidget(label); + page->setLayout(layout); + return page; +} + +QWizardPage *LammpsGui::tutorial_info(const int ntutorial, const QString &infotext) +{ + auto *page = new QWizardPage; + page->setTitle(QString("Contents of Tutorial %1").arg(ntutorial)); + page->setPixmap(QWizard::WatermarkPixmap, + QPixmap(QString(":/icons/tutorial%1-logo.png").arg(ntutorial))); + + auto *label = new QLabel(infotext); + label->setWordWrap(true); + + auto *layout = new QVBoxLayout; + layout->addWidget(label); + page->setLayout(layout); + return page; +} + +QWizardPage *LammpsGui::tutorial_directory(const int ntutorial) +{ + auto *page = new QWizardPage; + page->setTitle(QString("Select Directory for Tutorial %1").arg(ntutorial)); + page->setPixmap(QWizard::WatermarkPixmap, + QPixmap(QString(":/icons/tutorial%1-logo.png").arg(ntutorial))); + + auto *frame = new QFrame; + auto *label = new QLabel( + QString("Select a directory to store the files for tutorial %1. The directory will be " + "created if necessary and LAMMPS-GUI will download the files required for the " + "tutorial.
\nIf selected, an existing directory may be " + "cleared.
\nAlso, available files of the tutorial solution may be downloaded " + "to a folder \"solution\", if requested.
\nYou are now ready to start tutorial " + "%1.
\nClick on " + "the \"Finish\" button to complete the setup.
") + .arg(ntutorial)); + label->setWordWrap(true); + + auto *layout = new QVBoxLayout; + layout->addWidget(label); + layout->setStretch(0, 100); + + page->setLayout(layout); + return page; +} + void LammpsGui::start_tutorial1() { if (wizard) delete wizard; - wizard = new Tutorial1Wizard; + wizard = new TutorialWizard(1); + const auto infotext = + QString("In tutorial 1 you will learn about LAMMPS input files, their syntax and " + "structure, how to create and set up models and their interactions, how to run a " + "minimization and a molecular dynamics trajectory, how to plot thermodynamic data " + "and how to create visualizations of your system
Click on the \"Next\" button to select a folder.
"); wizard->setFont(font()); - wizard->addPage(tutorial1_intro()); - wizard->addPage(tutorial1_info()); - wizard->addPage(tutorial1_directory()); - wizard->addPage(tutorial1_finish()); + wizard->addPage(tutorial_intro(1)); + wizard->addPage(tutorial_info(1, infotext)); + wizard->addPage(tutorial_directory(1)); + wizard->addPage(tutorial_finish(1)); wizard->setWindowTitle("Tutorial 1 Setup Wizard"); wizard->setWizardStyle(QWizard::ModernStyle); wizard->show(); } -QWizardPage *LammpsGui::tutorial1_intro() -{ - auto *page = new QWizardPage; - page->setTitle("Getting Started With Tutorial 1"); - page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial1-logo.png")); - - // XXX TODO: update URL to published tutorial DOI - auto *label = - new QLabel("This wizard will help you to select and populate a folder with " - "materials required to work through tutorial 1 from a fourthcoming " - "LAMMPS tutorial using LAMMPS-GUI by Simon Gravelle, Jake Gissinger, " - "and Axel Kohlmeyer.
\n" - "The work-in-progress materials for this tutorial are available at: " - "github.com/lammpstutorials/lammpstutorials-articleClick on the \"Next\" button to begin.
"); - label->setWordWrap(true); - - auto *layout = new QVBoxLayout; - layout->addWidget(label); - page->setLayout(layout); - return page; -} - -QWizardPage *LammpsGui::tutorial1_info() -{ - auto *page = new QWizardPage; - page->setTitle("Contents of Tutorial 1"); - page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial1-logo.png")); - - auto *label = - new QLabel("In tutorial 1 you will learn about LAMMPS input files, their syntax and " - " structure, how to create and set up models and their interactions, how to " - "run a minimization and a molecular dynamics trajectory, how to plot " - "thermodynamic data and how to create visualizations of your system
" - "Click on the \"Next\" button to select a folder.
"); - label->setWordWrap(true); - - auto *layout = new QVBoxLayout; - layout->addWidget(label); - page->setLayout(layout); - return page; -} - -QWizardPage *LammpsGui::tutorial1_directory() -{ - auto *page = new QWizardPage; - page->setTitle("Select Directory for Tutorial 1"); - page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial1-logo.png")); - - auto *frame = new QFrame; - auto *label = new QLabel( - "Select a directory to store the files for tutorial 1. The directory will be " - "created if necessary and LAMMPS-GUI will download the files required for the " - "tutorial.
\n" - "If selected, an existing directory may be cleared.
\n" - "Also, available files of the tutorial solution may be downloaded to a " - "folder \"solution\", if requested.
\n" - "You are now ready to start tutorial 1.
\n" - "Click on the \"Finish\" button to " - "complete the setup.
"); - label->setWordWrap(true); - - auto *layout = new QVBoxLayout; - layout->addWidget(label); - layout->setStretch(0, 100); - - page->setLayout(layout); - return page; -} - void LammpsGui::start_tutorial2() { if (wizard) delete wizard; - wizard = new Tutorial2Wizard; - wizard->addPage(tutorial2_intro()); - wizard->addPage(tutorial2_info()); - wizard->addPage(tutorial2_directory()); - wizard->addPage(tutorial2_finish()); + wizard = new TutorialWizard(2); + const auto infotext = + QString("In tutorial 2 you will learn about setting up a simulation for a molecular " + "system with bonds. The target is to simulate a carbon nanotube with a " + "conventional molecular force field under growing strain and observe the response " + "to it. Since bonds are represented by a harmonic potential, they cannot break. " + "This is then compared to simulating the same system with a reactive force field " + "(AIREBO) where bonds may be broken and formed.
Click on the \"Next\" button to select a folder.
"); + wizard->setFont(font()); + wizard->addPage(tutorial_intro(2)); + wizard->addPage(tutorial_info(2, infotext)); + wizard->addPage(tutorial_directory(2)); + wizard->addPage(tutorial_finish(2)); wizard->setWindowTitle("Tutorial 2 Setup Wizard"); wizard->setWizardStyle(QWizard::ModernStyle); wizard->show(); } -QWizardPage *LammpsGui::tutorial2_intro() +void LammpsGui::start_tutorial3() { - auto *page = new QWizardPage; - page->setTitle("Getting Started With Tutorial 2"); - page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial2-logo.png")); + if (wizard) delete wizard; + wizard = new TutorialWizard(3); + const auto infotext = + QString("In tutorial 3 you will learn about setting up a simulation for a molecular " + "system with bonds. The target is to simulate a carbon nanotube with a " + "conventional molecular force field under growing strain and observe the response " + "to it. Since bonds are represented by a harmonic potential, they cannot break. " + "This is then compared to simulating the same system with a reactive force field " + "(AIREBO) where bonds may be broken and formed.
Click on the \"Next\" button to select a folder.
"); - // XXX TODO: update URL to published tutorial DOI - auto *label = - new QLabel("This wizard will help you to select and populate a folder with " - "materials required to work through tutorial 2 from a fourthcoming " - "LAMMPS tutorial using LAMMPS-GUI by Simon Gravelle, Jake Gissinger, " - "and Axel Kohlmeyer.
\n" - "The work-in-progress materials for this tutorial are available at: " - "github.com/lammpstutorials/lammpstutorials-articleClick on the \"Next\" button to begin.
"); - label->setWordWrap(true); - - auto *layout = new QVBoxLayout; - layout->addWidget(label); - page->setLayout(layout); - return page; + wizard->setFont(font()); + wizard->addPage(tutorial_intro(3)); + wizard->addPage(tutorial_info(3, infotext)); + wizard->addPage(tutorial_directory(3)); + wizard->addPage(tutorial_finish(3)); + wizard->setWindowTitle("Tutorial 3 Setup Wizard"); + wizard->setWizardStyle(QWizard::ModernStyle); + wizard->show(); } -QWizardPage *LammpsGui::tutorial2_info() +void LammpsGui::start_tutorial4() { - auto *page = new QWizardPage; - page->setTitle("Contents of Tutorial 2"); - page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial2-logo.png")); - - auto *label = - new QLabel("In tutorial 2 you will learn about setting up a simulation for a molecular " - "system with bonds. The target is to simulate a carbon nanotube with a " - "conventional molecular force field under growing strain and observe the " - "response to it. Since bonds are represented by a harmonic potential, they " - "cannot break. This is then compared to simulating the same system with a " - "reactive force field (AIREBO) where bonds may be broken and formed.
" - "Click on the \"Next\" button to select a folder.
"); - label->setWordWrap(true); - - auto *layout = new QVBoxLayout; - layout->addWidget(label); - page->setLayout(layout); - return page; + if (wizard) delete wizard; + wizard = new TutorialWizard(4); + const auto infotext = + QString("In tutorial 4 you will learn about setting up a simulation for a molecular " + "system with bonds. The target is to simulate a carbon nanotube with a " + "conventional molecular force field under growing strain and observe the response " + "to it. Since bonds are represented by a harmonic potential, they cannot break. " + "This is then compared to simulating the same system with a reactive force field " + "(AIREBO) where bonds may be broken and formed.
Click on the \"Next\" button to select a folder.
"); + wizard->setFont(font()); + wizard->addPage(tutorial_intro(4)); + wizard->addPage(tutorial_info(4, infotext)); + wizard->addPage(tutorial_directory(4)); + wizard->addPage(tutorial_finish(4)); + wizard->setWindowTitle("Tutorial 4 Setup Wizard"); + wizard->setWizardStyle(QWizard::ModernStyle); + wizard->show(); } -QWizardPage *LammpsGui::tutorial2_directory() +void LammpsGui::start_tutorial5() { - auto *page = new QWizardPage; - page->setTitle("Select Directory for Tutorial 2"); - page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial2-logo.png")); - - auto *frame = new QFrame; - auto *label = new QLabel( - "Select a directory to store the files for tutorial 2. The directory will be " - "created if necessary and LAMMPS-GUI will download the files required for the " - "tutorial.
\n" - "If selected, an existing directory may be cleared.
\n" - "Also, available files of the tutorial solution may be downloaded to a " - "folder \"solution\", if requested.
\n" - "In tutorial 5 you will learn about setting up a simulation for a molecular " + "system with bonds. The target is to simulate a carbon nanotube with a " + "conventional molecular force field under growing strain and observe the response " + "to it. Since bonds are represented by a harmonic potential, they cannot break. " + "This is then compared to simulating the same system with a reactive force field " + "(AIREBO) where bonds may be broken and formed.
Click on the \"Next\" button to select a folder.
"); + wizard->setFont(font()); + wizard->addPage(tutorial_intro(5)); + wizard->addPage(tutorial_info(5, infotext)); + wizard->addPage(tutorial_directory(5)); + wizard->addPage(tutorial_finish(5)); + wizard->setWindowTitle("Tutorial 5 Setup Wizard"); + wizard->setWizardStyle(QWizard::ModernStyle); + wizard->show(); } -QWizardPage *LammpsGui::tutorial2_finish() +void LammpsGui::start_tutorial6() { - auto *page = new QWizardPage; - page->setTitle("Start Tutorial 2"); - page->setPixmap(QWizard::WatermarkPixmap, QPixmap(":/icons/tutorial2-logo.png")); + if (wizard) delete wizard; + wizard = new TutorialWizard(6); + const auto infotext = + QString("In tutorial 6 you will learn about setting up a simulation for a molecular " + "system with bonds. The target is to simulate a carbon nanotube with a " + "conventional molecular force field under growing strain and observe the response " + "to it. Since bonds are represented by a harmonic potential, they cannot break. " + "This is then compared to simulating the same system with a reactive force field " + "(AIREBO) where bonds may be broken and formed.
Click on the \"Next\" button to select a folder.
"); + wizard->setFont(font()); + wizard->addPage(tutorial_intro(6)); + wizard->addPage(tutorial_info(6, infotext)); + wizard->addPage(tutorial_directory(6)); + wizard->addPage(tutorial_finish(6)); + wizard->setWindowTitle("Tutorial 6 Setup Wizard"); + wizard->setWizardStyle(QWizard::ModernStyle); + wizard->show(); +} - auto *label = new QLabel("You are now ready to start tutorial 2.
\n" - "Click on the \"Finish\" button to " - "complete the setup.
"); - label->setWordWrap(true); +void LammpsGui::start_tutorial7() +{ + if (wizard) delete wizard; + wizard = new TutorialWizard(7); + const auto infotext = + QString("In tutorial 7 you will learn about setting up a simulation for a molecular " + "system with bonds. The target is to simulate a carbon nanotube with a " + "conventional molecular force field under growing strain and observe the response " + "to it. Since bonds are represented by a harmonic potential, they cannot break. " + "This is then compared to simulating the same system with a reactive force field " + "(AIREBO) where bonds may be broken and formed.
Click on the \"Next\" button to select a folder.
"); + wizard->setFont(font()); + wizard->addPage(tutorial_intro(7)); + wizard->addPage(tutorial_info(7, infotext)); + wizard->addPage(tutorial_directory(7)); + wizard->addPage(tutorial_finish(7)); + wizard->setWindowTitle("Tutorial 7 Setup Wizard"); + wizard->setWizardStyle(QWizard::ModernStyle); + wizard->show(); +} - auto *layout = new QVBoxLayout; - layout->addWidget(label); - layout->setStretch(0, 100); - - page->setLayout(layout); - return page; +void LammpsGui::start_tutorial8() +{ + if (wizard) delete wizard; + wizard = new TutorialWizard(8); + const auto infotext = + QString("In tutorial 8 you will learn about setting up a simulation for a molecular " + "system with bonds. The target is to simulate a carbon nanotube with a " + "conventional molecular force field under growing strain and observe the response " + "to it. Since bonds are represented by a harmonic potential, they cannot break. " + "This is then compared to simulating the same system with a reactive force field " + "(AIREBO) where bonds may be broken and formed.
Click on the \"Next\" button to select a folder.
"); + wizard->setFont(font()); + wizard->addPage(tutorial_intro(8)); + wizard->addPage(tutorial_info(8, infotext)); + wizard->addPage(tutorial_directory(8)); + wizard->addPage(tutorial_finish(8)); + wizard->setWindowTitle("Tutorial 8 Setup Wizard"); + wizard->setWizardStyle(QWizard::ModernStyle); + wizard->show(); } void LammpsGui::howto() @@ -1983,12 +2013,12 @@ void LammpsGui::start_lammps() lammps.open(narg, args); lammpsstatus->show(); - // must have a version newer than the 2 August 2023 release of LAMMPS + // must have a version newer than the 29 August 2024 release of LAMMPS // TODO: must update this check before next feature release - if (lammps.version() <= 20230802) { + if (lammps.version() < 20240829) { QMessageBox::critical(this, "Incompatible LAMMPS Version", "LAMMPS-GUI version " LAMMPS_GUI_VERSION " requires\n" - "a LAMMPS version more recent than 2 August 2023"); + "a LAMMPS version of at least 29 August 2024"); exit(1); } @@ -2017,7 +2047,8 @@ bool LammpsGui::eventFilter(QObject *watched, QEvent *event) } // LAMMPS geturl command with current location of the input and solution files on the web -static const QString geturl = "geturl https://raw.githubusercontent.com/lammpstutorials/" +static const QString geturl = + "geturl https://raw.githubusercontent.com/lammpstutorials/" "lammpstutorials-article/refs/heads/main/files/tutorial%1/%2 output %2 verify no"; void LammpsGui::setup_tutorial(int tutno, const QString &dir, bool purgedir, bool getsolution) @@ -2071,7 +2102,8 @@ void LammpsGui::setup_tutorial(int tutno, const QString &dir, bool purgedir, boo if (!first.isEmpty()) open_file(first); } -Tutorial1Wizard::Tutorial1Wizard(QWidget *parent) : QWizard(parent) +TutorialWizard::TutorialWizard(int ntutorial, QWidget *parent) : + QWizard(parent), _ntutorial(ntutorial) { setWindowIcon(QIcon(":/icons/tutorial-logo.png")); } @@ -2079,12 +2111,12 @@ Tutorial1Wizard::Tutorial1Wizard(QWidget *parent) : QWizard(parent) // actions to perform when the wizard for tutorial 1 is complete // and the user has clicked on "Finish" -void Tutorial1Wizard::accept() +void TutorialWizard::accept() { // get pointers to the widgets with the information we need - auto *dirname = findChild