Skip to content

Commit 0821849

Browse files
committed
fix(mta-gpu): add topology preprocessing and energy output registration
The GPU metatomic MDModule now subscribes to preprocessing notifications (IndexGroupsAndNames, gmx_mtop_t*, WarningHandler*, MDLogger) to exclude classical NB interactions for ML atoms via addEmbeddedNBExclusions. Without this, Coulomb (SR) was -194K kJ/mol instead of ~6.8K kJ/mol. Also registers MDModulesEnergyOutputToMetatomicPotRequestChecker so the "Metatomic Potential" term appears in .edr output. Adds metatomic-gpu-input-group MDP option (default "System") matching the CPU module pattern.
1 parent 28e8a50 commit 0821849

1 file changed

Lines changed: 102 additions & 10 deletions

File tree

src/gromacs/applied_forces/metatomic/metatomic_gpu_mdmodule.cpp

Lines changed: 102 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,26 @@
4949
#include <cmath>
5050
#include <cstdlib>
5151

52+
#include <set>
5253
#include <string>
5354

55+
#include "gromacs/domdec/localatomset.h"
56+
#include "gromacs/fileio/warninp.h"
5457
#include "gromacs/mdrunutility/mdmodulesnotifiers.h"
5558
#include "gromacs/mdrunutility/plainpairlistranges.h"
5659
#include "gromacs/mdtypes/imdmodule.h"
5760
#include "gromacs/mdtypes/imdpoptionprovider_helpers.h"
5861
#include "gromacs/options/basicoptions.h"
5962
#include "gromacs/options/optionsection.h"
63+
#include "gromacs/selection/indexutil.h"
64+
#include "gromacs/topology/embedded_system_preprocessing.h"
65+
#include "gromacs/topology/topology.h"
6066
#include "gromacs/utility/basenetwork.h"
6167
#include "gromacs/utility/exceptions.h"
6268
#include "gromacs/utility/keyvaluetreebuilder.h"
6369
#include "gromacs/utility/logger.h"
6470
#include "gromacs/utility/strconvert.h"
65-
#include "gromacs/domdec/localatomset.h"
71+
#include "gromacs/utility/stringutil.h"
6672

6773
#include "metatomic_options.h"
6874

@@ -82,9 +88,9 @@ namespace
8288
/*! \internal
8389
* \brief MDP option provider for the metatomic-gpu section.
8490
*
85-
* Lightweight: only stores the "active" flag and model path.
86-
* Shares the model path key with the CPU metatomic module to allow
87-
* both to coexist in the same MDP file.
91+
* Handles MDP parsing, topology preprocessing (NB exclusions for ML atoms),
92+
* and parameter storage. Shares the embedded-system preprocessing logic
93+
* with the CPU metatomic module.
8894
*/
8995
class MetatomicGpuOptions final : public IMdpOptionProvider
9096
{
@@ -99,6 +105,8 @@ class MetatomicGpuOptions final : public IMdpOptionProvider
99105
rules, stringIdentityTransform, "metatomic-gpu", "extensions-directory");
100106
addMdpTransformFromString<std::string>(
101107
rules, stringIdentityTransform, "metatomic-gpu", "variant");
108+
addMdpTransformFromString<std::string>(
109+
rules, stringIdentityTransform, "metatomic-gpu", "input-group");
102110
}
103111

104112
void initMdpOptions(IOptionsContainerWithSections* options) override
@@ -108,6 +116,7 @@ class MetatomicGpuOptions final : public IMdpOptionProvider
108116
section.addOption(StringOption("model-path").store(&modelPath_));
109117
section.addOption(StringOption("extensions-directory").store(&extensionsDir_));
110118
section.addOption(StringOption("variant").store(&variant_));
119+
section.addOption(StringOption("input-group").store(&inputGroup_));
111120
}
112121

113122
void buildMdpOutput(KeyValueTreeObjectBuilder* builder) const override
@@ -122,6 +131,7 @@ class MetatomicGpuOptions final : public IMdpOptionProvider
122131
addMdpOutputValue<std::string>(
123132
builder, "metatomic-gpu", "extensions-directory", extensionsDir_);
124133
addMdpOutputValue<std::string>(builder, "metatomic-gpu", "variant", variant_);
134+
addMdpOutputValue<std::string>(builder, "metatomic-gpu", "input-group", inputGroup_);
125135
}
126136
}
127137

@@ -130,6 +140,56 @@ class MetatomicGpuOptions final : public IMdpOptionProvider
130140
std::string extensionsDir() const { return extensionsDir_; }
131141
std::string variant() const { return variant_; }
132142

143+
//! Resolve input-group name to atom indices from index file
144+
void setInputGroupIndices(const IndexGroupsAndNames& indexGroupsAndNames)
145+
{
146+
mtaIndices_ = indexGroupsAndNames.indices(inputGroup_);
147+
if (mtaIndices_.empty())
148+
{
149+
GMX_THROW(InconsistentInputError(formatString(
150+
"Group '%s' defining metatomic-gpu input atoms should not be empty.",
151+
inputGroup_.c_str())));
152+
}
153+
}
154+
155+
//! Modify topology: exclude classical NB for ML atoms, remove bonded interactions
156+
void modifyTopology(gmx_mtop_t* mtop)
157+
{
158+
std::set<int> mtaIndicesSet(mtaIndices_.begin(), mtaIndices_.end());
159+
int numMTAAtoms = static_cast<int>(mtaIndices_.size());
160+
int numRegularAtoms = mtop->natoms - numMTAAtoms;
161+
162+
GMX_LOG(logger().info)
163+
.appendText("Metatomic GPU potential interface is active, topology was modified!");
164+
GMX_LOG(logger().info)
165+
.appendTextFormatted(
166+
"Number of embedded Metatomic-GPU atoms: %d\nNumber of regular atoms: %d\n",
167+
numMTAAtoms,
168+
numRegularAtoms);
169+
170+
std::vector<bool> isMTABlock = splitEmbeddedBlocks(mtop, mtaIndicesSet);
171+
addEmbeddedNBExclusions(mtop, mtaIndicesSet, logger());
172+
buildEmbeddedAtomNumbers(*mtop);
173+
modifyEmbeddedTwoCenterInteractions(mtop, mtaIndicesSet, isMTABlock, logger());
174+
modifyEmbeddedThreeCenterInteractions(mtop, mtaIndicesSet, isMTABlock, logger());
175+
modifyEmbeddedFourCenterInteractions(mtop, mtaIndicesSet, isMTABlock, logger());
176+
checkConstrainedBonds(mtop, mtaIndicesSet, isMTABlock, wi_);
177+
mtop->finalize();
178+
}
179+
180+
void setLogger(const MDLogger& logger) { logger_ = &logger; }
181+
void setWarningHandler(WarningHandler* wi) { wi_ = wi; }
182+
183+
//! Write input-group indices to KVT for .tpr storage
184+
void writeInputGroupToKvt(KeyValueTreeObjectBuilder kvt)
185+
{
186+
auto indexAdder = kvt.addUniformArray<std::int64_t>("metatomic-gpu-input-group");
187+
for (const auto& idx : mtaIndices_)
188+
{
189+
indexAdder.addValue(idx);
190+
}
191+
}
192+
133193
//! Build a MetatomicParameters struct for the GPU provider
134194
MetatomicParameters buildParams() const
135195
{
@@ -139,15 +199,26 @@ class MetatomicGpuOptions final : public IMdpOptionProvider
139199
params.extensionsDirectory = extensionsDir_;
140200
params.variant = variant_;
141201
params.device = "cuda";
142-
params.nlMode = "full"; // GPU path doesn't use DD NL modes
202+
params.nlMode = "full";
203+
params.inputGroup = inputGroup_;
143204
return params;
144205
}
145206

146207
private:
147-
bool active_ = false;
148-
std::string modelPath_;
149-
std::string extensionsDir_;
150-
std::string variant_;
208+
const MDLogger& logger() const
209+
{
210+
GMX_RELEASE_ASSERT(logger_, "Logger not set for MetatomicGpuOptions.");
211+
return *logger_;
212+
}
213+
214+
bool active_ = false;
215+
std::string modelPath_;
216+
std::string extensionsDir_;
217+
std::string variant_;
218+
std::string inputGroup_ = "System";
219+
std::vector<Index> mtaIndices_;
220+
const MDLogger* logger_ = nullptr;
221+
WarningHandler* wi_ = nullptr;
151222
};
152223

153224

@@ -170,7 +241,23 @@ class MetatomicGpuMDModule final : public IMDModule
170241
return;
171242
}
172243

173-
// Write GPU metatomic params to KVT for storage in .tpr
244+
// Receive logger for topology modification messages
245+
notifiers->preProcessingNotifier_.subscribe(
246+
[this](const MDLogger& logger) { options_.setLogger(logger); });
247+
248+
// Receive warning handler for constraint checks
249+
notifiers->preProcessingNotifier_.subscribe(
250+
[this](WarningHandler* wi) { options_.setWarningHandler(wi); });
251+
252+
// Resolve input-group name to atom indices
253+
notifiers->preProcessingNotifier_.subscribe(
254+
[this](const IndexGroupsAndNames& idx) { options_.setInputGroupIndices(idx); });
255+
256+
// Modify topology: exclude classical NB for ML atoms
257+
notifiers->preProcessingNotifier_.subscribe(
258+
[this](gmx_mtop_t* top) { options_.modifyTopology(top); });
259+
260+
// Write GPU metatomic params + input-group indices to KVT for .tpr
174261
notifiers->preProcessingNotifier_.subscribe(
175262
[this](KeyValueTreeObjectBuilder kvt)
176263
{
@@ -179,6 +266,7 @@ class MetatomicGpuMDModule final : public IMDModule
179266
section.addValue<std::string>("model-path", options_.modelPath());
180267
section.addValue<std::string>("extensions-directory", options_.extensionsDir());
181268
section.addValue<std::string>("variant", options_.variant());
269+
options_.writeInputGroupToKvt(kvt);
182270
});
183271
}
184272

@@ -237,6 +325,10 @@ class MetatomicGpuMDModule final : public IMDModule
237325
ranges->addRange(maxCutoff);
238326
});
239327

328+
// Request "Metatomic Potential" energy term in .edr output
329+
notifiers->simulationSetupNotifier_.subscribe(
330+
[](MDModulesEnergyOutputToMetatomicPotRequestChecker* req)
331+
{ req->energyOutputToMetatomicPot_ = true; });
240332
}
241333

242334
void subscribeToSimulationRunNotifications(MDModulesNotifiers* /*notifiers*/) override

0 commit comments

Comments
 (0)