Activate QMMM MDModule
authorDmitry Morozov <aracsmd@gmail.com>
Wed, 29 Sep 2021 17:49:01 +0000 (17:49 +0000)
committerChristian Blau <cblau.mail@gmail.com>
Wed, 29 Sep 2021 17:49:01 +0000 (17:49 +0000)
13 files changed:
docs/user-guide/mdp-options.rst
src/gromacs/applied_forces/qmmm/qmmmforceprovider.cpp
src/gromacs/applied_forces/qmmm/qmmmoptions.cpp
src/gromacs/gmxpreprocess/tests/refdata/GetIrTest_AcceptsDefineParametersWithValuesIncludingAssignment.xml
src/gromacs/gmxpreprocess/tests/refdata/GetIrTest_AcceptsElectricField.xml
src/gromacs/gmxpreprocess/tests/refdata/GetIrTest_AcceptsElectricFieldOscillating.xml
src/gromacs/gmxpreprocess/tests/refdata/GetIrTest_AcceptsElectricFieldPulsed.xml
src/gromacs/gmxpreprocess/tests/refdata/GetIrTest_AcceptsEmptyLines.xml
src/gromacs/gmxpreprocess/tests/refdata/GetIrTest_AcceptsImplicitSolventNo.xml
src/gromacs/gmxpreprocess/tests/refdata/GetIrTest_AcceptsKeyWithoutValue.xml
src/gromacs/gmxpreprocess/tests/refdata/GetIrTest_AcceptsMimic.xml
src/gromacs/gmxpreprocess/tests/refdata/GetIrTest_HandlesDifferentKindsOfMdpLines.xml
src/gromacs/mdrun/mdmodules.cpp

index 95b3f226e3b32a852b881c40feba7b2afb192f92..d88973e007e29077699c8a4e710e2ecbbb0cb179 100644 (file)
@@ -3312,6 +3312,52 @@ electron-microscopy experiments. (See the `reference manual`_ for details)
    z-axis by :math:`\theta` degress by using following input:
    :math:`(\cos \theta , -\sin \theta , 0 , \sin \theta , \cos \theta , 0 , 0 , 0 , 1)` .
 
+QM/MM simulations with CP2K Interface 
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+These options enable and control the calculation and application of additional
+QM/MM forces that are computed by the CP2K package if it is linked into |Gromacs|.
+For further details about QM/MM interface implementation follow :ref:`qmmm`. 
+
+.. mdp:: qmmm-cp2k-active
+
+   (false) Activate QM/MM simulations. Requires CP2K to be linked with |Gromacs|
+
+.. mdp:: qmmm-cp2k-qmgroup
+
+   (System) Index group with atoms that are treated with QM.
+
+.. mdp:: qmmm-cp2k-qmmethod
+
+   (PBE) Method used to describe the QM part of the system.
+
+   .. mdp-value:: PBE
+
+      DFT using PBE functional and DZVP-MOLOPT basis set.
+
+   .. mdp-value:: BLYP
+
+      DFT using BLYP functional and DZVP-MOLOPT basis set.
+
+   .. mdp-value:: INPUT
+
+      Provide an external input file for CP2K when running :ref:`gmx grompp` with the ``-qmi`` command-line option.
+      External input files are subject to the limitations that are described in :ref:`qmmm`.
+
+.. mdp:: qmmm-cp2k-qmcharge
+
+   (0) Total charge of the QM part.
+
+.. mdp:: qmmm-cp2k-qmmultiplicity
+
+   (1) Multiplicity or spin-state of QM part. Default value 1 means singlet state.
+
+.. mdp:: qmmm-cp2k-qmfilenames
+
+   () Names of the CP2K files that will be generated during the simulation. 
+   When using the default, empty, value the name of the simulation input file will be used 
+   with an additional ``_cp2k`` suffix.
+
 User defined thingies
 ^^^^^^^^^^^^^^^^^^^^^
 
index f685efdcf7df1ddac204a3a754dcba3226bbcbcf..451aae269d2b2ce6e6894e8bd499b023f59f6a55 100644 (file)
@@ -103,7 +103,7 @@ void QMMMForceProvider::appendLog(const std::string& msg)
 void QMMMForceProvider::initCP2KForceEnvironment(const t_commrec& cr)
 {
     // Check that we have filename either defined in KVT or deduced from *.tpr name
-    GMX_RELEASE_ASSERT(parameters_.qmFileNameBase_.empty(),
+    GMX_RELEASE_ASSERT(!parameters_.qmFileNameBase_.empty(),
                        "Names of CP2K input/output files is not defined in QMMMParameters");
 
 
index 7c314f72a1a0f40689ecb3181f376e9b7da3c52a..6f8810854dca79e181b696c62adbc7423400cdc5 100644 (file)
@@ -298,7 +298,7 @@ void QMMMOptions::processTprFilename(const MdRunInputFilename& tprFilename)
     }
 
     // Provided name should not be empty
-    GMX_RELEASE_ASSERT(tprFilename.mdRunFilename_.empty(),
+    GMX_RELEASE_ASSERT(!tprFilename.mdRunFilename_.empty(),
                        "Filename of the *.tpr simulation file is empty");
 
     // Exit if parameters_.qmFileNameBase_ has been provided
@@ -368,6 +368,22 @@ void QMMMOptions::processExternalInputFile()
                 qmExternalInputFileName_.c_str())));
     }
 
+    // Check if RUN_TYPE in the file present and is ENERGY_FORCE
+    if (cp2kParams.count("RUN_TYPE") == 0)
+    {
+        GMX_THROW(InconsistentInputError(
+                formatString("Parameter RUN_TYPE not found in the external CP2K input file %s",
+                             qmExternalInputFileName_.c_str())));
+    }
+
+    // Check if RUN_TYPE in the file is equal to ENERGY_FORCE
+    if (toUpperCase(cp2kParams["RUN_TYPE"]) != "ENERGY_FORCE")
+    {
+        GMX_THROW(InconsistentInputError(formatString(
+                "Parameter RUN_TYPE should be ENERGY_FORCE in the external CP2K input file %s",
+                qmExternalInputFileName_.c_str())));
+    }
+
     // Set parameters_.qmCharge_ and qmMult_
     parameters_.qmCharge_       = fromStdString<int>(cp2kParams["CHARGE"]);
     parameters_.qmMultiplicity_ = fromStdString<int>(cp2kParams["MULTIPLICITY"]);
@@ -390,9 +406,9 @@ void QMMMOptions::setQMExternalInputFile(const QMInputFileName& qmExternalInputF
         if (qmExternalInputFileName.hasQMInputFileName_)
         {
             // If parameters_.qmMethod_ != INPUT then user should not provide external input file
-            GMX_THROW(
-                    InconsistentInputError("External CP2K Input file has been provided with -qmi "
-                                           "option, but qmmm-qmmethod is not INPUT"));
+            GMX_THROW(InconsistentInputError(
+                    "External CP2K input file has been provided with -qmi option, but "
+                    + c_qmmmCP2KModuleName + "-" + c_qmMethodTag_ + " is not INPUT"));
         }
 
         // Exit if we dont need to process external input file
@@ -402,9 +418,9 @@ void QMMMOptions::setQMExternalInputFile(const QMInputFileName& qmExternalInputF
     // Case where user should provide external input file with -qmi option
     if (parameters_.qmMethod_ == QMMMQMMethod::INPUT && !qmExternalInputFileName.hasQMInputFileName_)
     {
-        GMX_THROW(
-                InconsistentInputError("qmmm-qmmethod = INPUT requested, but external CP2K Input "
-                                       "file is not provided with -qmi option"));
+        GMX_THROW(InconsistentInputError(c_qmmmCP2KModuleName + "-" + c_qmMethodTag_
+                                         + " = INPUT requested, but external CP2K "
+                                           "input file is not provided with -qmi option"));
     }
 
     // If external input is provided by the user then we should process it and save into the parameters_
@@ -440,7 +456,8 @@ void QMMMOptions::processCoordinates(const CoordinatesAndBoxPreprocessed& coord)
                     "One of the box vectors is shorter than 1 nm.\n"
                     "For stable CP2K SCF convergence all simulation box vectors should be "
                     ">= 1 nm. Please consider to increase simulation box or provide custom CP2K "
-                    "input using qmmm-qmmethod = INPUT"));
+                    "input using "
+                    + c_qmmmCP2KModuleName + "-" + c_qmMethodTag_ + " = INPUT"));
         }
 
         parameters_.qmInput_ = inpGen.generateCP2KInput();
@@ -529,7 +546,7 @@ void QMMMOptions::modifyQMMMTopology(gmx_mtop_t* mtop)
         msg += formatString("QM-MM broken bonds found: %d\n", topInfo.numLinkBonds);
     }
 
-    appendLog(msg);
+    appendLog(msg + "\n");
 
     /* We should warn the user if there is inconsistence between removed classical charges
      * on QM atoms and total QM charge
@@ -547,9 +564,9 @@ void QMMMOptions::modifyQMMMTopology(gmx_mtop_t* mtop)
     // If there are many constrained bonds in QM system then we should also warn the user
     if (topInfo.numConstrainedBondsInQMSubsystem > 2)
     {
-        msg += "Your QM subsystem has a lot of constrained bonds. They probably have been "
-               "generated automatically. That could produce an artifacts in the simulation. "
-               "Consider constraints = none in the mdp file.\n";
+        msg = "Your QM subsystem has a lot of constrained bonds. They probably have been "
+              "generated automatically. That could produce an artifacts in the simulation. "
+              "Consider constraints = none in the mdp file.\n";
         appendWarning(msg);
     }
 }
index 58d37a7ef6f119eb138a5f35959dbfe07819727e..c88c2aa7928a82785c179cfeff34f872892ba3e5 100644 (file)
@@ -298,5 +298,8 @@ electric-field-z         = 0 0 0 0
 
 ; Density guided simulation
 density-guided-simulation-active = false
+
+; QM/MM with CP2K
+qmmm-cp2k-active         = false
 </String>
 </ReferenceData>
index 8dd09198038c2c3f2e7e52e9678a9af7617dfd64..7b6968ea7c4753af90bdf42345e3d5e88b8b27e0 100644 (file)
@@ -298,5 +298,8 @@ electric-field-z         = 0 0 0 0
 
 ; Density guided simulation
 density-guided-simulation-active = false
+
+; QM/MM with CP2K
+qmmm-cp2k-active         = false
 </String>
 </ReferenceData>
index bbefcc9748f75a82ba1dd2220588a9852dcc8862..4afc56f511fad2b3b3f92d3139766613b7d32858 100644 (file)
@@ -298,5 +298,8 @@ electric-field-z         = 3.7 7.5 0 0
 
 ; Density guided simulation
 density-guided-simulation-active = false
+
+; QM/MM with CP2K
+qmmm-cp2k-active         = false
 </String>
 </ReferenceData>
index 8b21cdf5efd01f4a5fa5450a906bc491529b05f3..4aac61bfa2a7e26bd16d904a61309268bdacc39b 100644 (file)
@@ -298,5 +298,8 @@ electric-field-z         = 0 0 0 0
 
 ; Density guided simulation
 density-guided-simulation-active = false
+
+; QM/MM with CP2K
+qmmm-cp2k-active         = false
 </String>
 </ReferenceData>
index 72c39c0c0e3ea041031f2ce4b466e8babfc3c0db..2f3bebf7c10abb1bda56a7251e9b46c402143a12 100644 (file)
@@ -298,5 +298,8 @@ electric-field-z         = 0 0 0 0
 
 ; Density guided simulation
 density-guided-simulation-active = false
+
+; QM/MM with CP2K
+qmmm-cp2k-active         = false
 </String>
 </ReferenceData>
index 72c39c0c0e3ea041031f2ce4b466e8babfc3c0db..2f3bebf7c10abb1bda56a7251e9b46c402143a12 100644 (file)
@@ -298,5 +298,8 @@ electric-field-z         = 0 0 0 0
 
 ; Density guided simulation
 density-guided-simulation-active = false
+
+; QM/MM with CP2K
+qmmm-cp2k-active         = false
 </String>
 </ReferenceData>
index 72c39c0c0e3ea041031f2ce4b466e8babfc3c0db..2f3bebf7c10abb1bda56a7251e9b46c402143a12 100644 (file)
@@ -298,5 +298,8 @@ electric-field-z         = 0 0 0 0
 
 ; Density guided simulation
 density-guided-simulation-active = false
+
+; QM/MM with CP2K
+qmmm-cp2k-active         = false
 </String>
 </ReferenceData>
index 40e229819f3e95b7b1ad04337abfcdd1b7e5ff25..54545d90e3f21c69a800edd0136101dfd2db4d7f 100644 (file)
@@ -298,5 +298,8 @@ electric-field-z         = 0 0 0 0
 
 ; Density guided simulation
 density-guided-simulation-active = false
+
+; QM/MM with CP2K
+qmmm-cp2k-active         = false
 </String>
 </ReferenceData>
index ed1446672ab540bf08685327b1144f900e675920..136d8617e7d3b08ba68853a762acabcc27f23a1f 100644 (file)
@@ -298,5 +298,8 @@ electric-field-z         = 0 0 0 0
 
 ; Density guided simulation
 density-guided-simulation-active = false
+
+; QM/MM with CP2K
+qmmm-cp2k-active         = false
 </String>
 </ReferenceData>
index 9022b26e80c1dad7548a6f06614dfb4bff5fbe8e..ac1c57bd02edae31a99c7959f2b6915ceb3196bc 100644 (file)
@@ -40,6 +40,7 @@
 
 #include "gromacs/applied_forces/electricfield.h"
 #include "gromacs/applied_forces/densityfitting/densityfitting.h"
+#include "gromacs/applied_forces/qmmm/qmmm.h"
 #include "gromacs/imd/imd.h"
 #include "gromacs/mdtypes/iforceprovider.h"
 #include "gromacs/mdtypes/imdmodule.h"
@@ -66,6 +67,7 @@ public:
         densityFitting_(DensityFittingModuleInfo::create()),
         field_(createElectricFieldModule()),
         imd_(createInteractiveMolecularDynamicsModule()),
+        qmmm_(QMMMModuleInfo::create()),
         swapCoordinates_(createSwapCoordinatesModule())
     {
     }
@@ -76,6 +78,7 @@ public:
         auto appliedForcesOptions = options->addSection(OptionSection("applied-forces"));
         field_->mdpOptionProvider()->initMdpOptions(&appliedForcesOptions);
         densityFitting_->mdpOptionProvider()->initMdpOptions(&appliedForcesOptions);
+        qmmm_->mdpOptionProvider()->initMdpOptions(&appliedForcesOptions);
         // In future, other sections would also go here.
     }
 
@@ -102,6 +105,7 @@ public:
     std::unique_ptr<IMDModule>      field_;
     std::unique_ptr<ForceProviders> forceProviders_;
     std::unique_ptr<IMDModule>      imd_;
+    std::unique_ptr<IMDModule>      qmmm_;
     std::unique_ptr<IMDModule>      swapCoordinates_;
 
     /*! \brief List of registered MDModules
@@ -125,12 +129,14 @@ void MDModules::initMdpTransform(IKeyValueTreeTransformRules* rules)
     auto appliedForcesScope = rules->scopedTransform("/applied-forces");
     impl_->field_->mdpOptionProvider()->initMdpTransform(appliedForcesScope.rules());
     impl_->densityFitting_->mdpOptionProvider()->initMdpTransform(appliedForcesScope.rules());
+    impl_->qmmm_->mdpOptionProvider()->initMdpTransform(appliedForcesScope.rules());
 }
 
 void MDModules::buildMdpOutput(KeyValueTreeObjectBuilder* builder)
 {
     impl_->field_->mdpOptionProvider()->buildMdpOutput(builder);
     impl_->densityFitting_->mdpOptionProvider()->buildMdpOutput(builder);
+    impl_->qmmm_->mdpOptionProvider()->buildMdpOutput(builder);
 }
 
 void MDModules::assignOptionsToModules(const KeyValueTreeObject& params, IKeyValueTreeErrorHandler* errorHandler)
@@ -167,6 +173,7 @@ ForceProviders* MDModules::initForceProviders()
     impl_->forceProviders_ = std::make_unique<ForceProviders>();
     impl_->field_->initForceProviders(impl_->forceProviders_.get());
     impl_->densityFitting_->initForceProviders(impl_->forceProviders_.get());
+    impl_->qmmm_->initForceProviders(impl_->forceProviders_.get());
     for (auto&& module : impl_->modules_)
     {
         module->initForceProviders(impl_->forceProviders_.get());
@@ -177,11 +184,13 @@ ForceProviders* MDModules::initForceProviders()
 void MDModules::subscribeToPreProcessingNotifications()
 {
     impl_->densityFitting_->subscribeToPreProcessingNotifications(&impl_->notifiers_);
+    impl_->qmmm_->subscribeToPreProcessingNotifications(&impl_->notifiers_);
 }
 
 void MDModules::subscribeToSimulationSetupNotifications()
 {
     impl_->densityFitting_->subscribeToSimulationSetupNotifications(&impl_->notifiers_);
+    impl_->qmmm_->subscribeToSimulationSetupNotifications(&impl_->notifiers_);
 }
 
 void MDModules::add(std::shared_ptr<gmx::IMDModule> module)