2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2019,2020, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
36 * \brief Defines the modular simulator
38 * \author Pascal Merz <pascal.merz@me.com>
39 * \ingroup module_modularsimulator
44 #include "modularsimulator.h"
46 #include "gromacs/commandline/filenm.h"
47 #include "gromacs/domdec/domdec.h"
48 #include "gromacs/ewald/pme.h"
49 #include "gromacs/ewald/pme_load_balancing.h"
50 #include "gromacs/ewald/pme_pp.h"
51 #include "gromacs/fileio/checkpoint.h"
52 #include "gromacs/gmxlib/nrnb.h"
53 #include "gromacs/listed_forces/listed_forces.h"
54 #include "gromacs/mdlib/checkpointhandler.h"
55 #include "gromacs/mdlib/constr.h"
56 #include "gromacs/mdlib/coupling.h"
57 #include "gromacs/mdlib/energyoutput.h"
58 #include "gromacs/mdlib/mdatoms.h"
59 #include "gromacs/mdlib/resethandler.h"
60 #include "gromacs/mdlib/update.h"
61 #include "gromacs/mdrun/replicaexchange.h"
62 #include "gromacs/mdrun/shellfc.h"
63 #include "gromacs/mdrunutility/handlerestart.h"
64 #include "gromacs/mdrunutility/printtime.h"
65 #include "gromacs/mdtypes/commrec.h"
66 #include "gromacs/mdtypes/fcdata.h"
67 #include "gromacs/mdtypes/forcerec.h"
68 #include "gromacs/mdtypes/inputrec.h"
69 #include "gromacs/mdtypes/mdatom.h"
70 #include "gromacs/mdtypes/mdrunoptions.h"
71 #include "gromacs/mdtypes/observableshistory.h"
72 #include "gromacs/nbnxm/nbnxm.h"
73 #include "gromacs/topology/mtop_util.h"
74 #include "gromacs/topology/topology.h"
75 #include "gromacs/trajectory/trajectoryframe.h"
76 #include "gromacs/utility/fatalerror.h"
77 #include "gromacs/utility/int64_to_int.h"
79 #include "computeglobalselement.h"
80 #include "constraintelement.h"
81 #include "forceelement.h"
82 #include "parrinellorahmanbarostat.h"
83 #include "simulatoralgorithm.h"
84 #include "statepropagatordata.h"
85 #include "velocityscalingtemperaturecoupling.h"
89 void ModularSimulator::run()
91 GMX_LOG(legacySimulatorData_->mdlog.info)
93 .appendText("Using the modular simulator.");
95 ModularSimulatorAlgorithmBuilder algorithmBuilder(compat::make_not_null(legacySimulatorData_),
96 std::move(checkpointDataHolder_));
97 addIntegrationElements(&algorithmBuilder);
98 auto algorithm = algorithmBuilder.build();
100 while (const auto* task = algorithm.getNextTask())
107 void ModularSimulator::addIntegrationElements(ModularSimulatorAlgorithmBuilder* builder)
109 if (legacySimulatorData_->inputrec->eI == eiMD)
111 // The leap frog integration algorithm
112 builder->add<ForceElement>();
113 builder->add<StatePropagatorData::Element>();
114 if (legacySimulatorData_->inputrec->etc == etcVRESCALE
115 || legacySimulatorData_->inputrec->etc == etcBERENDSEN)
117 builder->add<VelocityScalingTemperatureCoupling>(-1, UseFullStepKE::No,
118 ReportPreviousStepConservedEnergy::No);
120 builder->add<Propagator<IntegrationStep::LeapFrog>>(legacySimulatorData_->inputrec->delta_t,
121 RegisterWithThermostat::True,
122 RegisterWithBarostat::True);
123 if (legacySimulatorData_->constr)
125 builder->add<ConstraintsElement<ConstraintVariable::Positions>>();
127 builder->add<ComputeGlobalsElement<ComputeGlobalsAlgorithm::LeapFrog>>();
128 builder->add<EnergyData::Element>();
129 if (legacySimulatorData_->inputrec->epc == epcPARRINELLORAHMAN)
131 builder->add<ParrinelloRahmanBarostat>(-1);
134 else if (legacySimulatorData_->inputrec->eI == eiVV)
136 // The velocity verlet integration algorithm
137 builder->add<ForceElement>();
138 builder->add<Propagator<IntegrationStep::VelocitiesOnly>>(
139 0.5 * legacySimulatorData_->inputrec->delta_t, RegisterWithThermostat::False,
140 RegisterWithBarostat::True);
141 if (legacySimulatorData_->constr)
143 builder->add<ConstraintsElement<ConstraintVariable::Velocities>>();
145 builder->add<ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerlet>>();
146 builder->add<StatePropagatorData::Element>();
147 if (legacySimulatorData_->inputrec->etc == etcVRESCALE
148 || legacySimulatorData_->inputrec->etc == etcBERENDSEN)
150 builder->add<VelocityScalingTemperatureCoupling>(
151 0, UseFullStepKE::Yes, ReportPreviousStepConservedEnergy::Yes);
153 builder->add<Propagator<IntegrationStep::VelocityVerletPositionsAndVelocities>>(
154 legacySimulatorData_->inputrec->delta_t, RegisterWithThermostat::True,
155 RegisterWithBarostat::False);
156 if (legacySimulatorData_->constr)
158 builder->add<ConstraintsElement<ConstraintVariable::Positions>>();
160 builder->add<ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerlet>>();
161 builder->add<EnergyData::Element>();
162 if (legacySimulatorData_->inputrec->epc == epcPARRINELLORAHMAN)
164 builder->add<ParrinelloRahmanBarostat>(-1);
169 gmx_fatal(FARGS, "Integrator not implemented for the modular simulator.");
173 bool ModularSimulator::isInputCompatible(bool exitOnFailure,
174 const t_inputrec* inputrec,
176 const gmx_mtop_t& globalTopology,
177 const gmx_multisim_t* ms,
178 const ReplicaExchangeParameters& replExParams,
180 bool doEssentialDynamics,
183 auto conditionalAssert = [exitOnFailure](bool condition, const char* message) {
186 GMX_RELEASE_ASSERT(condition, message);
191 // GMX_USE_MODULAR_SIMULATOR allows to use modular simulator also for non-standard uses,
192 // such as the leap-frog integrator
193 const auto modularSimulatorExplicitlyTurnedOn = (getenv("GMX_USE_MODULAR_SIMULATOR") != nullptr);
194 // GMX_USE_MODULAR_SIMULATOR allows to use disable modular simulator for all uses,
195 // including the velocity-verlet integrator used by default
196 const auto modularSimulatorExplicitlyTurnedOff = (getenv("GMX_DISABLE_MODULAR_SIMULATOR") != nullptr);
199 !(modularSimulatorExplicitlyTurnedOn && modularSimulatorExplicitlyTurnedOff),
200 "Cannot have both GMX_USE_MODULAR_SIMULATOR=ON and GMX_DISABLE_MODULAR_SIMULATOR=ON. "
201 "Unset one of the two environment variables to explicitly chose which simulator to "
203 "or unset both to recover default behavior.");
206 !(modularSimulatorExplicitlyTurnedOff && inputrec->eI == eiVV
207 && inputrec->epc == epcPARRINELLORAHMAN),
208 "Cannot use a Parrinello-Rahman barostat with md-vv and "
209 "GMX_DISABLE_MODULAR_SIMULATOR=ON, "
210 "as the Parrinello-Rahman barostat is not implemented in the legacy simulator. Unset "
211 "GMX_DISABLE_MODULAR_SIMULATOR or use a different pressure control algorithm.");
213 bool isInputCompatible = conditionalAssert(
214 inputrec->eI == eiMD || inputrec->eI == eiVV,
215 "Only integrators md and md-vv are supported by the modular simulator.");
216 isInputCompatible = isInputCompatible
217 && conditionalAssert(inputrec->eI != eiMD || modularSimulatorExplicitlyTurnedOn,
218 "Set GMX_USE_MODULAR_SIMULATOR=ON to use the modular "
219 "simulator with integrator md.");
222 && conditionalAssert(
224 "Multiple time stepping is not supported by the modular simulator.");
227 && conditionalAssert(!doRerun, "Rerun is not supported by the modular simulator.");
228 isInputCompatible = isInputCompatible
229 && conditionalAssert(inputrec->etc == etcNO || inputrec->etc == etcVRESCALE
230 || inputrec->etc == etcBERENDSEN,
231 "Only v-rescale and Berendsen thermostat are "
232 "supported by the modular simulator.");
235 && conditionalAssert(
236 inputrec->epc == epcNO || inputrec->epc == epcPARRINELLORAHMAN,
237 "Only Parrinello-Rahman barostat is supported by the modular simulator.");
240 && conditionalAssert(
241 !(inputrecNptTrotter(inputrec) || inputrecNphTrotter(inputrec)
242 || inputrecNvtTrotter(inputrec)),
243 "Legacy Trotter decomposition is not supported by the modular simulator.");
244 isInputCompatible = isInputCompatible
245 && conditionalAssert(inputrec->efep == efepNO || inputrec->efep == efepYES
246 || inputrec->efep == efepSLOWGROWTH,
247 "Expanded ensemble free energy calculation is not "
248 "supported by the modular simulator.");
249 isInputCompatible = isInputCompatible
250 && conditionalAssert(!inputrec->bPull,
251 "Pulling is not supported by the modular simulator.");
254 && conditionalAssert(inputrec->opts.ngacc == 1 && inputrec->opts.acc[0][XX] == 0.0
255 && inputrec->opts.acc[0][YY] == 0.0
256 && inputrec->opts.acc[0][ZZ] == 0.0 && inputrec->cos_accel == 0.0,
257 "Acceleration is not supported by the modular simulator.");
260 && conditionalAssert(inputrec->opts.ngfrz == 1 && inputrec->opts.nFreeze[0][XX] == 0
261 && inputrec->opts.nFreeze[0][YY] == 0
262 && inputrec->opts.nFreeze[0][ZZ] == 0,
263 "Freeze groups are not supported by the modular simulator.");
266 && conditionalAssert(
267 inputrec->deform[XX][XX] == 0.0 && inputrec->deform[XX][YY] == 0.0
268 && inputrec->deform[XX][ZZ] == 0.0 && inputrec->deform[YY][XX] == 0.0
269 && inputrec->deform[YY][YY] == 0.0 && inputrec->deform[YY][ZZ] == 0.0
270 && inputrec->deform[ZZ][XX] == 0.0 && inputrec->deform[ZZ][YY] == 0.0
271 && inputrec->deform[ZZ][ZZ] == 0.0,
272 "Deformation is not supported by the modular simulator.");
275 && conditionalAssert(gmx_mtop_interaction_count(globalTopology, IF_VSITE) == 0,
276 "Virtual sites are not supported by the modular simulator.");
277 isInputCompatible = isInputCompatible
278 && conditionalAssert(!inputrec->bDoAwh,
279 "AWH is not supported by the modular simulator.");
282 && conditionalAssert(gmx_mtop_ftype_count(globalTopology, F_DISRES) == 0,
283 "Distance restraints are not supported by the modular simulator.");
286 && conditionalAssert(
287 gmx_mtop_ftype_count(globalTopology, F_ORIRES) == 0,
288 "Orientation restraints are not supported by the modular simulator.");
291 && conditionalAssert(ms == nullptr,
292 "Multi-sim are not supported by the modular simulator.");
295 && conditionalAssert(replExParams.exchangeInterval == 0,
296 "Replica exchange is not supported by the modular simulator.");
298 int numEnsembleRestraintSystems;
301 numEnsembleRestraintSystems = fcd->disres->nsystems;
305 auto distantRestraintEnsembleEnvVar = getenv("GMX_DISRE_ENSEMBLE_SIZE");
306 numEnsembleRestraintSystems =
307 (ms != nullptr && distantRestraintEnsembleEnvVar != nullptr)
308 ? static_cast<int>(strtol(distantRestraintEnsembleEnvVar, nullptr, 10))
313 && conditionalAssert(numEnsembleRestraintSystems <= 1,
314 "Ensemble restraints are not supported by the modular simulator.");
317 && conditionalAssert(!doSimulatedAnnealing(inputrec),
318 "Simulated annealing is not supported by the modular simulator.");
321 && conditionalAssert(!inputrec->bSimTemp,
322 "Simulated tempering is not supported by the modular simulator.");
323 isInputCompatible = isInputCompatible
324 && conditionalAssert(!inputrec->bExpanded,
325 "Expanded ensemble simulations are not supported by "
326 "the modular simulator.");
329 && conditionalAssert(!doEssentialDynamics,
330 "Essential dynamics is not supported by the modular simulator.");
331 isInputCompatible = isInputCompatible
332 && conditionalAssert(inputrec->eSwapCoords == eswapNO,
333 "Ion / water position swapping is not supported by "
334 "the modular simulator.");
337 && conditionalAssert(!inputrec->bIMD,
338 "Interactive MD is not supported by the modular simulator.");
341 && conditionalAssert(!doMembed,
342 "Membrane embedding is not supported by the modular simulator.");
343 // TODO: Change this to the boolean passed when we merge the user interface change for the GPU update.
346 && conditionalAssert(
347 getenv("GMX_FORCE_UPDATE_DEFAULT_GPU") == nullptr,
348 "Integration on the GPU is not supported by the modular simulator.");
349 // Modular simulator is centered around NS updates
350 // TODO: think how to handle nstlist == 0
351 isInputCompatible = isInputCompatible
352 && conditionalAssert(inputrec->nstlist != 0,
353 "Simulations without neighbor list update are not "
354 "supported by the modular simulator.");
355 isInputCompatible = isInputCompatible
356 && conditionalAssert(!GMX_FAHCORE,
357 "GMX_FAHCORE not supported by the modular simulator.");
359 isInputCompatible || !(inputrec->eI == eiVV && inputrec->epc == epcPARRINELLORAHMAN),
360 "Requested Parrinello-Rahman barostat with md-vv, but other options are not compatible "
361 "with the modular simulator. The Parrinello-Rahman barostat is not implemented for "
362 "md-vv in the legacy simulator. Use a different pressure control algorithm.");
364 return isInputCompatible;
367 ModularSimulator::ModularSimulator(std::unique_ptr<LegacySimulatorData> legacySimulatorData,
368 std::unique_ptr<ReadCheckpointDataHolder> checkpointDataHolder) :
369 legacySimulatorData_(std::move(legacySimulatorData)),
370 checkpointDataHolder_(std::move(checkpointDataHolder))
372 checkInputForDisabledFunctionality();
375 void ModularSimulator::checkInputForDisabledFunctionality()
377 isInputCompatible(true, legacySimulatorData_->inputrec, legacySimulatorData_->mdrunOptions.rerun,
378 *legacySimulatorData_->top_global, legacySimulatorData_->ms,
379 legacySimulatorData_->replExParams, legacySimulatorData_->fr->fcdata.get(),
380 opt2bSet("-ei", legacySimulatorData_->nfile, legacySimulatorData_->fnm),
381 legacySimulatorData_->membed != nullptr);
382 if (legacySimulatorData_->observablesHistory->edsamHistory)
385 "The checkpoint is from a run with essential dynamics sampling, "
386 "but the current run did not specify the -ei option. "
387 "Either specify the -ei option to mdrun, or do not use this checkpoint file.");
391 void ModularSimulator::readCheckpointToTrxFrame(t_trxframe* fr,
392 ReadCheckpointDataHolder* readCheckpointDataHolder,
393 const CheckpointHeaderContents& checkpointHeaderContents)
395 GMX_RELEASE_ASSERT(checkpointHeaderContents.isModularSimulatorCheckpoint,
396 "ModularSimulator::readCheckpointToTrxFrame can only read checkpoints "
397 "written by modular simulator.");
400 int64_to_int(checkpointHeaderContents.step, "conversion of checkpoint to trajectory");
402 fr->time = checkpointHeaderContents.t;
406 StatePropagatorData::readCheckpointToTrxFrame(
407 fr, readCheckpointDataHolder->checkpointData(StatePropagatorData::checkpointID()));
408 if (readCheckpointDataHolder->keyExists(FreeEnergyPerturbationData::checkpointID()))
410 FreeEnergyPerturbationData::readCheckpointToTrxFrame(
411 fr, readCheckpointDataHolder->checkpointData(FreeEnergyPerturbationData::checkpointID()));
415 FreeEnergyPerturbationData::readCheckpointToTrxFrame(fr, std::nullopt);