Implementation of QMMM, QMMMSimulationParameterSetup and QMMMOutputProvider classes
authorDmitry Morozov <aracsmd@gmail.com>
Tue, 28 Sep 2021 08:11:51 +0000 (08:11 +0000)
committerMark Abraham <mark.j.abraham@gmail.com>
Tue, 28 Sep 2021 08:11:51 +0000 (08:11 +0000)
src/gromacs/applied_forces/qmmm/CMakeLists.txt
src/gromacs/applied_forces/qmmm/qmmm.cpp [new file with mode: 0644]
src/gromacs/applied_forces/qmmm/qmmm.h [new file with mode: 0644]
src/gromacs/applied_forces/qmmm/tests/CMakeLists.txt
src/gromacs/applied_forces/qmmm/tests/qmmm.cpp [new file with mode: 0644]
src/gromacs/gmxpreprocess/grompp.cpp
src/gromacs/utility/mdmodulesnotifiers.h

index b6066f78422219b670024c7565298674e36dd1dd..9697a49359dbde5ceb9741729bacfada470a7241 100644 (file)
@@ -36,6 +36,7 @@ gmx_add_libgromacs_sources(
     qmmminputgenerator.cpp
     qmmmtopologypreprocessor.cpp
     qmmmoptions.cpp
+    qmmm.cpp
     )
 
 # If we have libcp2k linked then compile qmmmforceprovider.cpp
diff --git a/src/gromacs/applied_forces/qmmm/qmmm.cpp b/src/gromacs/applied_forces/qmmm/qmmm.cpp
new file mode 100644 (file)
index 0000000..bcf8b96
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2021, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Implements QMMM class that implements IMDModule interface
+ *
+ * \author Dmitry Morozov <dmitry.morozov@jyu.fi>
+ * \author Christian Blau <blau@kth.se>
+ * \ingroup module_applied_forces
+ */
+#include "gmxpre.h"
+
+#include "qmmm.h"
+
+#include <memory>
+#include <numeric>
+
+#include "gromacs/domdec/localatomsetmanager.h"
+#include "gromacs/ewald/pme.h"
+#include "gromacs/fileio/checkpoint.h"
+#include "gromacs/math/multidimarray.h"
+#include "gromacs/mdlib/broadcaststructs.h"
+#include "gromacs/mdtypes/commrec.h"
+#include "gromacs/mdtypes/imdmodule.h"
+#include "gromacs/mdtypes/imdoutputprovider.h"
+#include "gromacs/utility/classhelpers.h"
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/keyvaluetreebuilder.h"
+#include "gromacs/utility/logger.h"
+#include "gromacs/utility/mdmodulesnotifiers.h"
+
+#include "qmmmforceprovider.h"
+#include "qmmmoptions.h"
+
+namespace gmx
+{
+
+namespace
+{
+
+/*! \internal
+ * \brief Helper class that holds simulation data and
+ * callback functions for simulation setup time notifications
+ */
+class QMMMSimulationParameterSetup
+{
+public:
+    QMMMSimulationParameterSetup() = default;
+
+    /*! \brief Set the local atom set for the QM atoms.
+     * \param[in] localAtomSet of QM atoms
+     */
+    void setLocalQMAtomSet(const LocalAtomSet& localAtomSet)
+    {
+        localQMAtomSet_ = std::make_unique<LocalAtomSet>(localAtomSet);
+    }
+
+    /*! \brief Set the local atom set for the MM atoms.
+     * \param[in] localAtomSet of MM atoms
+     */
+    void setLocalMMAtomSet(const LocalAtomSet& localAtomSet)
+    {
+        localMMAtomSet_ = std::make_unique<LocalAtomSet>(localAtomSet);
+    }
+
+    /*! \brief Return local atom set for QM atoms.
+     * \throws InternalError if local atom set is not set
+     * \returns local atom set for QM atoms
+     */
+    const LocalAtomSet& localQMAtomSet() const
+    {
+        if (localQMAtomSet_ == nullptr)
+        {
+            GMX_THROW(InternalError("Local atom set is not set for QM atoms."));
+        }
+        return *localQMAtomSet_;
+    }
+
+    /*! \brief Return local atom set for MM atoms.
+     * \throws InternalError if local atom set is not set
+     * \returns local atom set for MM atoms
+     */
+    const LocalAtomSet& localMMAtomSet() const
+    {
+        if (localMMAtomSet_ == nullptr)
+        {
+            GMX_THROW(InternalError("Local atom set is not set for MM atoms."));
+        }
+        return *localMMAtomSet_;
+    }
+
+    /*! \brief Set the periodic boundary condition via MdModuleNotifier.
+     *
+     * The pbc type is wrapped in PeriodicBoundaryConditionType to
+     * allow the MdModuleNotifier to statically distinguish the callback
+     * function type from other 'int' function callbacks.
+     *
+     * \param[in] pbc MdModuleNotification class that contains a variable
+     *                that enumerates the periodic boundary condition.
+     */
+    void setPeriodicBoundaryConditionType(const PbcType& pbc)
+    {
+        pbcType_ = std::make_unique<PbcType>(pbc);
+    }
+
+    //! Get the periodic boundary conditions
+    PbcType periodicBoundaryConditionType()
+    {
+        if (pbcType_ == nullptr)
+        {
+            GMX_THROW(
+                    InternalError("Periodic boundary condition enum not set for QMMM simulation."));
+        }
+        return *pbcType_;
+    }
+
+    /*! \brief Set the logger for QMMM during mdrun
+     * \param[in] logger Logger instance to be used for output
+     */
+    void setLogger(const MDLogger& logger) { logger_ = &logger; }
+
+    //! Get the logger instance
+    const MDLogger& logger() const
+    {
+        if (logger_ == nullptr)
+        {
+            GMX_THROW(InternalError("Logger not set for QMMM simulation."));
+        }
+        return *logger_;
+    }
+
+private:
+    //! The local QM atom set to act on
+    std::unique_ptr<LocalAtomSet> localQMAtomSet_;
+    //! The local MM atom set to act on
+    std::unique_ptr<LocalAtomSet> localMMAtomSet_;
+    //! The type of periodic boundary conditions in the simulation
+    std::unique_ptr<PbcType> pbcType_;
+    //! MDLogger for notifications during mdrun
+    const MDLogger* logger_ = nullptr;
+
+    GMX_DISALLOW_COPY_AND_ASSIGN(QMMMSimulationParameterSetup);
+};
+
+
+/*! \internal
+ * \brief Handle file output for QMMM simulations.
+ * empty implementation as QMMM does not use that
+ */
+class QMMMOutputProvider final : public IMDOutputProvider
+{
+public:
+    //! Initialize output
+    void initOutput(FILE* /*fplog*/,
+                    int /*nfile*/,
+                    const t_filenm /*fnm*/[],
+                    bool /*bAppendFiles*/,
+                    const gmx_output_env_t* /*oenv*/) override
+    {
+    }
+    //! Finalizes output from a simulation run.
+    void finishOutput() override {}
+};
+
+
+/*! \internal
+ * \brief QMMM module
+ *
+ * Class that implements the QMMM forces and potential
+ * \note the virial calculation is not yet implemented
+ */
+class QMMM final : public IMDModule
+{
+public:
+    //! \brief Construct the QMMM module.
+    explicit QMMM() = default;
+
+    // Now callbacks for several kinds of MdModuleNotification are created
+    // and subscribed, and will be dispatched correctly at run time
+    // based on the type of the parameter required by the lambda.
+
+    /*! \brief Requests to be notified during pre-processing.
+     *
+     * \param[in] notifier allows the module to subscribe to notifications from MdModules.
+     *
+     * The QMMM code subscribes to these notifications:
+     *   - setting atom group indices in the qmmmOptions_ from an
+     *     index group string by taking a parmeter const IndexGroupsAndNames &
+     *   - storing its internal parameters in a tpr file by writing to a
+     *     key-value-tree during pre-processing by a function taking a
+     *     KeyValueTreeObjectBuilder as parameter
+     *   - Modify topology according to QMMM rules using gmx_mtop_t notification
+     *     and utilizing QMMMTopologyPreprocessor class
+     *   - Access MDLogger for notifications output
+     *   - Access warninp for for grompp warnings output
+     *   - Coordinates, PBC and box for CP2K input generation
+     *   - QM Input file provided with -qmi option of grompp
+     */
+    void subscribeToPreProcessingNotifications(MDModulesNotifiers* notifier) override
+    {
+        if (!qmmmOptions_.active())
+        {
+            return;
+        }
+
+        // Writing internal parameters during pre-processing
+        const auto writeInternalParametersFunction = [this](KeyValueTreeObjectBuilder treeBuilder) {
+            qmmmOptions_.writeInternalParametersToKvt(treeBuilder);
+        };
+        notifier->preProcessingNotifier_.subscribe(writeInternalParametersFunction);
+
+        // Setting atom group indices
+        const auto setQMMMGroupIndicesFunction = [this](const IndexGroupsAndNames& indexGroupsAndNames) {
+            qmmmOptions_.setQMMMGroupIndices(indexGroupsAndNames);
+        };
+        notifier->preProcessingNotifier_.subscribe(setQMMMGroupIndicesFunction);
+
+        // Set Logger during pre-processing
+        const auto setLoggerFunction = [this](const MDLogger& logger) {
+            qmmmOptions_.setLogger(logger);
+        };
+        notifier->preProcessingNotifier_.subscribe(setLoggerFunction);
+
+        // Set warning output during pre-processing
+        const auto setWarninpFunction = [this](warninp* wi) { qmmmOptions_.setWarninp(wi); };
+        notifier->preProcessingNotifier_.subscribe(setWarninpFunction);
+
+        // Notification of the Coordinates, box and pbc during pre-processing
+        const auto processCoordinatesFunction = [this](const CoordinatesAndBoxPreprocessed& coord) {
+            qmmmOptions_.processCoordinates(coord);
+        };
+        notifier->preProcessingNotifier_.subscribe(processCoordinatesFunction);
+
+        // Modification of the topology during pre-processing
+        const auto modifyQMMMTopologyFunction = [this](gmx_mtop_t* mtop) {
+            qmmmOptions_.modifyQMMMTopology(mtop);
+        };
+        notifier->preProcessingNotifier_.subscribe(modifyQMMMTopologyFunction);
+
+        // Notification of the QM input file provided via -qmi option of grompp
+        const auto setQMExternalInputFileNameFunction = [this](const QMInputFileName& qmInputFileName) {
+            qmmmOptions_.setQMExternalInputFile(qmInputFileName);
+        };
+        notifier->preProcessingNotifier_.subscribe(setQMExternalInputFileNameFunction);
+    }
+
+    /*! \brief Requests to be notified during simulation setup.
+     * The QMMM code subscribes to these notifications:
+     *   - reading its internal parameters from a key-value-tree during
+     *     simulation setup by taking a const KeyValueTreeObject & parameter
+     *   - *.tpr filename for CP2K input generation
+     *   - constructing local atom sets in the simulation parameter setup
+     *     by taking a LocalAtomSetManager * as parameter
+     *   - the type of periodic boundary conditions that are used
+     *     by taking a PeriodicBoundaryConditionType as parameter
+     *   - Access MDLogger for notifications output
+     *   - Disable PME-only ranks for QMMM runs
+     *   - Request QM energy output to md.log
+     */
+    void subscribeToSimulationSetupNotifications(MDModulesNotifiers* notifier) override
+    {
+        if (!qmmmOptions_.active())
+        {
+            return;
+        }
+
+        // Reading internal parameters during simulation setup
+        const auto readInternalParametersFunction = [this](const KeyValueTreeObject& tree) {
+            qmmmOptions_.readInternalParametersFromKvt(tree);
+        };
+        notifier->simulationSetupNotifier_.subscribe(readInternalParametersFunction);
+
+        // Process tpr filename
+        const auto setTprFileNameFunction = [this](const MdRunInputFilename& tprName) {
+            qmmmOptions_.processTprFilename(tprName);
+        };
+        notifier->simulationSetupNotifier_.subscribe(setTprFileNameFunction);
+
+        // constructing local atom sets during simulation setup
+        const auto setLocalAtomSetFunction = [this](LocalAtomSetManager* localAtomSetManager) {
+            LocalAtomSet atomSet1 = localAtomSetManager->add(qmmmOptions_.parameters().qmIndices_);
+            this->qmmmSimulationParameters_.setLocalQMAtomSet(atomSet1);
+            LocalAtomSet atomSet2 = localAtomSetManager->add(qmmmOptions_.parameters().mmIndices_);
+            this->qmmmSimulationParameters_.setLocalMMAtomSet(atomSet2);
+        };
+        notifier->simulationSetupNotifier_.subscribe(setLocalAtomSetFunction);
+
+        // Reading PBC parameters during simulation setup
+        const auto setPeriodicBoundaryContionsFunction = [this](const PbcType& pbc) {
+            this->qmmmSimulationParameters_.setPeriodicBoundaryConditionType(pbc);
+        };
+        notifier->simulationSetupNotifier_.subscribe(setPeriodicBoundaryContionsFunction);
+
+        // Saving MDLogger during simulation setup
+        const auto setLoggerFunction = [this](const MDLogger& logger) {
+            this->qmmmSimulationParameters_.setLogger(logger);
+        };
+        notifier->simulationSetupNotifier_.subscribe(setLoggerFunction);
+
+        // Adding output to energy file
+        const auto requestEnergyOutput = [](MDModulesEnergyOutputToQMMMRequestChecker* energyOutputRequest) {
+            energyOutputRequest->energyOutputToQMMM_ = true;
+        };
+        notifier->simulationSetupNotifier_.subscribe(requestEnergyOutput);
+
+        // Request to disable PME-only ranks, which are not compatible with CP2K
+        const auto requestPmeRanks = [](SeparatePmeRanksPermitted* pmeRanksPermitted) {
+            pmeRanksPermitted->disablePmeRanks(
+                    "Separate PME-only ranks are not compatible with QMMM MdModule");
+        };
+        notifier->simulationSetupNotifier_.subscribe(requestPmeRanks);
+    }
+
+    //! From IMDModule
+    IMdpOptionProvider* mdpOptionProvider() override { return &qmmmOptions_; }
+
+    //! Add this module to the force providers if active
+    void initForceProviders(ForceProviders* forceProviders) override
+    {
+        if (!qmmmOptions_.active())
+        {
+            return;
+        }
+
+        const auto& parameters = qmmmOptions_.parameters();
+        forceProvider_         = std::make_unique<QMMMForceProvider>(
+                parameters,
+                qmmmSimulationParameters_.localQMAtomSet(),
+                qmmmSimulationParameters_.localMMAtomSet(),
+                qmmmSimulationParameters_.periodicBoundaryConditionType(),
+                qmmmSimulationParameters_.logger());
+        forceProviders->addForceProvider(forceProvider_.get());
+    }
+
+    //! QMMM Module should not use OutputProvider as it will be removed in the furture
+    IMDOutputProvider* outputProvider() override { return &qmmmOutputProvider_; }
+
+private:
+    //! The output provider
+    QMMMOutputProvider qmmmOutputProvider_;
+    //! The options provided for QMMM
+    QMMMOptions qmmmOptions_;
+    //! Object that evaluates the forces
+    std::unique_ptr<QMMMForceProvider> forceProvider_;
+    /*! \brief Parameters for QMMM that become available at
+     * simulation setup time.
+     */
+    QMMMSimulationParameterSetup qmmmSimulationParameters_;
+
+    GMX_DISALLOW_COPY_AND_ASSIGN(QMMM);
+};
+
+} // namespace
+
+std::unique_ptr<IMDModule> QMMMModuleInfo::create()
+{
+    return std::make_unique<QMMM>();
+}
+
+const std::string QMMMModuleInfo::name_ = c_qmmmCP2KModuleName;
+
+} // namespace gmx
diff --git a/src/gromacs/applied_forces/qmmm/qmmm.h b/src/gromacs/applied_forces/qmmm/qmmm.h
new file mode 100644 (file)
index 0000000..b983ce3
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2021, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Declares fabrique structure for QMMM MDModule class
+ *
+ * \author Dmitry Morozov <dmitry.morozov@jyu.fi>
+ * \author Christian Blau <blau@kth.se>
+ * \ingroup module_applied_forces
+ */
+#ifndef GMX_APPLIED_FORCES_QMMM_H
+#define GMX_APPLIED_FORCES_QMMM_H
+
+#include <memory>
+#include <string>
+
+namespace gmx
+{
+
+class IMDModule;
+struct MdModulesNotifier;
+
+/*! \libinternal \brief Information about the QM/MM module.
+ *
+ * Provides name and method to create a QM/MM module.
+ */
+struct QMMMModuleInfo
+{
+    /*! \brief
+     * Creates a module for applying forces according to a QM/MM.
+     *
+     */
+    static std::unique_ptr<IMDModule> create();
+    //! The name of the module
+    static const std::string name_;
+};
+
+} // namespace gmx
+
+#endif
index 0712ef8ac7f760ddb0b293023034ebe8093b4c6c..4d1b8ae0d127bed81742ecafa50b72754a87b2cb 100644 (file)
@@ -38,6 +38,7 @@ gmx_add_unit_test(QMMMAppliedForcesUnitTest qmmm_applied_forces-test
         qmmmtopologypreprocessor.cpp
         qmmmoptions.cpp
         qmmmforceprovider.cpp
+        qmmm.cpp
         )
 
 # For QMMMForceProvider test we need to define wether libcp2k linked
diff --git a/src/gromacs/applied_forces/qmmm/tests/qmmm.cpp b/src/gromacs/applied_forces/qmmm/tests/qmmm.cpp
new file mode 100644 (file)
index 0000000..595035d
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2021, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Tests for functionality of the QMMM module.
+ *
+ * \author Dmitry Morozov <dmitry.morozov@jyu.fi>
+ * \author Christian Blau <blau@kth.se>
+ * \ingroup module_applied_forces
+ */
+#include "gmxpre.h"
+
+#include "gromacs/applied_forces/qmmm/qmmm.h"
+
+#include <gtest/gtest.h>
+
+#include "gromacs/gmxlib/network.h"
+#include "gromacs/math/paddedvector.h"
+#include "gromacs/math/vec.h"
+#include "gromacs/mdtypes/enerdata.h"
+#include "gromacs/mdtypes/forceoutput.h"
+#include "gromacs/mdtypes/iforceprovider.h"
+#include "gromacs/mdtypes/imdmodule.h"
+#include "gromacs/mdtypes/imdpoptionprovider.h"
+#include "gromacs/mdtypes/mdatom.h"
+#include "gromacs/options/options.h"
+#include "gromacs/options/treesupport.h"
+#include "gromacs/utility/keyvaluetreebuilder.h"
+#include "gromacs/utility/keyvaluetreetransform.h"
+#include "gromacs/utility/mdmodulesnotifiers.h"
+#include "gromacs/utility/real.h"
+#include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringcompare.h"
+
+#include "testutils/testasserts.h"
+#include "testutils/testfilemanager.h"
+#include "testutils/testmatchers.h"
+
+namespace gmx
+{
+
+namespace
+{
+
+class QMMMTest : public ::testing::Test
+{
+public:
+    void addMdpOptionQMMMActive()
+    {
+        mdpValueBuilder_.rootObject().addValue("qmmm-cp2k-active", std::string("yes"));
+    }
+
+    //! build an mdp options tree that sets the options for the qmmm module
+    void makeQMMMModuleWithSetOptions()
+    {
+        KeyValueTreeObject mdpOptionsTree = mdpValueBuilder_.build();
+
+        QMMMModule_ = QMMMModuleInfo::create();
+
+        // set up options
+        Options QMMMModuleOptions;
+        QMMMModule_->mdpOptionProvider()->initMdpOptions(&QMMMModuleOptions);
+
+        // Add rules to transform mdp inputs to QMMMModule data
+        KeyValueTreeTransformer transform;
+        transform.rules()->addRule().keyMatchType("/", StringCompareType::CaseAndDashInsensitive);
+        QMMMModule_->mdpOptionProvider()->initMdpTransform(transform.rules());
+
+        // Execute the transform on the mdpValues
+        auto transformedMdpValues = transform.transform(mdpOptionsTree, nullptr);
+        assignOptionsFromKeyValueTree(&QMMMModuleOptions, transformedMdpValues.object(), nullptr);
+    }
+
+    void intializeForceProviders() { QMMMModule_->initForceProviders(&QMMMForces_); }
+
+protected:
+    KeyValueTreeBuilder        mdpValueBuilder_;
+    ForceProviders             QMMMForces_;
+    std::unique_ptr<IMDModule> QMMMModule_;
+};
+
+TEST_F(QMMMTest, ForceProviderLackingInputThrows)
+{
+    // Prepare MDP inputs
+    addMdpOptionQMMMActive();
+
+    // Initialize with default options
+    makeQMMMModuleWithSetOptions();
+
+    // Build the force provider, once all input data is gathered
+    EXPECT_ANY_THROW(intializeForceProviders());
+}
+
+} // namespace
+
+} // namespace gmx
index 394143e8e68a1b5bfbe22972117da07782947e97..4c9fbf8d93d4ee2683d65002bad612ccbe9a9be5 100644 (file)
@@ -1935,6 +1935,9 @@ int gmx_grompp(int argc, char* argv[])
     // Notify MDModules of existing logger
     mdModules.notifiers().preProcessingNotifier_.notify(logger);
 
+    // Notify MDModules of existing warninp
+    mdModules.notifiers().preProcessingNotifier_.notify(wi);
+
     // Notify QMMM MDModule of external QM input file command-line option
     {
         gmx::QMInputFileName qmInputFileName = { ftp2bSet(efQMI, NFILE, fnm), ftp2fn(efQMI, NFILE, fnm) };
index 020091515ff177a53e8511909606014d4d3d1e9d..0cbb56515d842dff4a79650a5edc33ac2fbdbfcc 100644 (file)
@@ -53,6 +53,7 @@
 
 struct t_commrec;
 struct gmx_mtop_t;
+struct warninp;
 enum class PbcType : int;
 
 namespace gmx
@@ -252,26 +253,28 @@ notifier =>> moduleC [label="returns"];
 struct MDModulesNotifiers
 {
     /*! \brief Pre-processing callback functions.
-     * const CoordinatesAndBoxPreprocessed Allows modules to access coordinates,
+     * CoordinatesAndBoxPreprocessed Allows modules to access coordinates,
      *                                box and pbc during grompp
-     * const MDLogger& Allows MdModule to use standard logging class for messages output
+     * MDLogger Allows MdModule to use standard logging class for messages output
+     * warninp* Allows modules to make grompp warnings, notes and errors
      * EnergyCalculationFrequencyErrors* allows modules to check if they match
      *                                   their required calculation frequency
      *                                   and add their error message if needed
      *                                   to the collected error messages
-     * gmx_mtop_t * Allows modules to modify the topology during pre-processing
+     * gmx_mtop_t* Allows modules to modify the topology during pre-processing
      * IndexGroupsAndNames provides modules with atom indices and their names
      * KeyValueTreeObjectBuilder enables writing of module internal data to
      *                           .tpr files.
      * QMInputFileName Allows QMMM module to know if user provided external QM input file
      */
-    BuildMDModulesNotifier<const CoordinatesAndBoxPreprocessed,
+    BuildMDModulesNotifier<const CoordinatesAndBoxPreprocessed&,
                            const MDLogger&,
+                           warninp*,
                            EnergyCalculationFrequencyErrors*,
                            gmx_mtop_t*,
                            const IndexGroupsAndNames&,
                            KeyValueTreeObjectBuilder,
-                           QMInputFileName>::type preProcessingNotifier_;
+                           const QMInputFileName&>::type preProcessingNotifier_;
 
     /*! \brief Handles subscribing and calling checkpointing callback functions.
      *
@@ -311,7 +314,7 @@ struct MDModulesNotifiers
      *                           time information
      * const t_commrec& provides a communicator to the modules during simulation
      *                  setup
-     * MdRunInputFilename Allows modules to know .tpr filename during mdrun
+     * const MdRunInputFilename& Allows modules to know .tpr filename during mdrun
      */
     BuildMDModulesNotifier<const KeyValueTreeObject&,
                            LocalAtomSetManager*,
@@ -323,7 +326,7 @@ struct MDModulesNotifiers
                            const PbcType&,
                            const SimulationTimeStep&,
                            const t_commrec&,
-                           MdRunInputFilename>::type simulationSetupNotifier_;
+                           const MdRunInputFilename&>::type simulationSetupNotifier_;
 };
 
 } // namespace gmx