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 */
8995class 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\n Number 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
146207private:
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