dbb04d3fb5746b839d715b0e5a786d155a1d84b6
[alexxy/gromacs.git] / src / gromacs / modularsimulator / modularsimulator.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
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.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35 /*! \internal \file
36  * \brief Defines the modular simulator
37  *
38  * \author Pascal Merz <pascal.merz@me.com>
39  * \ingroup module_modularsimulator
40  */
41
42 #include "gmxpre.h"
43
44 #include "modularsimulator.h"
45
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/gmxlib/nrnb.h"
52 #include "gromacs/listed_forces/listed_forces.h"
53 #include "gromacs/mdlib/checkpointhandler.h"
54 #include "gromacs/mdlib/constr.h"
55 #include "gromacs/mdlib/coupling.h"
56 #include "gromacs/mdlib/energyoutput.h"
57 #include "gromacs/mdlib/mdatoms.h"
58 #include "gromacs/mdlib/resethandler.h"
59 #include "gromacs/mdlib/update.h"
60 #include "gromacs/mdrun/replicaexchange.h"
61 #include "gromacs/mdrun/shellfc.h"
62 #include "gromacs/mdrunutility/handlerestart.h"
63 #include "gromacs/mdrunutility/printtime.h"
64 #include "gromacs/mdtypes/commrec.h"
65 #include "gromacs/mdtypes/fcdata.h"
66 #include "gromacs/mdtypes/forcerec.h"
67 #include "gromacs/mdtypes/inputrec.h"
68 #include "gromacs/mdtypes/mdatom.h"
69 #include "gromacs/mdtypes/mdrunoptions.h"
70 #include "gromacs/mdtypes/observableshistory.h"
71 #include "gromacs/nbnxm/nbnxm.h"
72 #include "gromacs/topology/mtop_util.h"
73 #include "gromacs/topology/topology.h"
74 #include "gromacs/utility/fatalerror.h"
75
76 #include "computeglobalselement.h"
77 #include "constraintelement.h"
78 #include "forceelement.h"
79 #include "parrinellorahmanbarostat.h"
80 #include "simulatoralgorithm.h"
81 #include "statepropagatordata.h"
82 #include "vrescalethermostat.h"
83
84 namespace gmx
85 {
86 void ModularSimulator::run()
87 {
88     GMX_LOG(legacySimulatorData_->mdlog.info)
89             .asParagraph()
90             .appendText("Using the modular simulator.");
91
92     ModularSimulatorAlgorithmBuilder algorithmBuilder(compat::make_not_null(legacySimulatorData_));
93     addIntegrationElements(&algorithmBuilder);
94     auto algorithm = algorithmBuilder.build();
95
96     while (const auto* task = algorithm.getNextTask())
97     {
98         // execute task
99         (*task)();
100     }
101 }
102
103 void ModularSimulator::addIntegrationElements(ModularSimulatorAlgorithmBuilder* builder)
104 {
105     if (legacySimulatorData_->inputrec->eI == eiMD)
106     {
107         // The leap frog integration algorithm
108         builder->add<ForceElement>();
109         builder->add<StatePropagatorData::Element>();
110         if (legacySimulatorData_->inputrec->etc == etcVRESCALE)
111         {
112             builder->add<VRescaleThermostat>(-1, VRescaleThermostatUseFullStepKE::No);
113         }
114         builder->add<Propagator<IntegrationStep::LeapFrog>>(legacySimulatorData_->inputrec->delta_t,
115                                                             RegisterWithThermostat::True,
116                                                             RegisterWithBarostat::True);
117         if (legacySimulatorData_->constr)
118         {
119             builder->add<ConstraintsElement<ConstraintVariable::Positions>>();
120         }
121         builder->add<ComputeGlobalsElement<ComputeGlobalsAlgorithm::LeapFrog>>();
122         builder->add<EnergyData::Element>();
123         if (legacySimulatorData_->inputrec->epc == epcPARRINELLORAHMAN)
124         {
125             builder->add<ParrinelloRahmanBarostat>(-1);
126         }
127     }
128     else if (legacySimulatorData_->inputrec->eI == eiVV)
129     {
130         // The velocity verlet integration algorithm
131         builder->add<ForceElement>();
132         builder->add<Propagator<IntegrationStep::VelocitiesOnly>>(
133                 0.5 * legacySimulatorData_->inputrec->delta_t, RegisterWithThermostat::False,
134                 RegisterWithBarostat::True);
135         if (legacySimulatorData_->constr)
136         {
137             builder->add<ConstraintsElement<ConstraintVariable::Velocities>>();
138         }
139         builder->add<ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerlet>>();
140         builder->add<StatePropagatorData::Element>();
141         if (legacySimulatorData_->inputrec->etc == etcVRESCALE)
142         {
143             builder->add<VRescaleThermostat>(0, VRescaleThermostatUseFullStepKE::Yes);
144         }
145         builder->add<Propagator<IntegrationStep::VelocityVerletPositionsAndVelocities>>(
146                 legacySimulatorData_->inputrec->delta_t, RegisterWithThermostat::True,
147                 RegisterWithBarostat::False);
148         if (legacySimulatorData_->constr)
149         {
150             builder->add<ConstraintsElement<ConstraintVariable::Positions>>();
151         }
152         builder->add<ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerlet>>();
153         builder->add<EnergyData::Element>();
154         if (legacySimulatorData_->inputrec->epc == epcPARRINELLORAHMAN)
155         {
156             builder->add<ParrinelloRahmanBarostat>(-1);
157         }
158     }
159     else
160     {
161         gmx_fatal(FARGS, "Integrator not implemented for the modular simulator.");
162     }
163 }
164
165 bool ModularSimulator::isInputCompatible(bool                             exitOnFailure,
166                                          const t_inputrec*                inputrec,
167                                          bool                             doRerun,
168                                          const gmx_mtop_t&                globalTopology,
169                                          const gmx_multisim_t*            ms,
170                                          const ReplicaExchangeParameters& replExParams,
171                                          const t_fcdata*                  fcd,
172                                          bool                             doEssentialDynamics,
173                                          bool                             doMembed)
174 {
175     auto conditionalAssert = [exitOnFailure](bool condition, const char* message) {
176         if (exitOnFailure)
177         {
178             GMX_RELEASE_ASSERT(condition, message);
179         }
180         return condition;
181     };
182
183     bool isInputCompatible = true;
184
185     // GMX_USE_MODULAR_SIMULATOR allows to use modular simulator also for non-standard uses,
186     // such as the leap-frog integrator
187     const auto modularSimulatorExplicitlyTurnedOn = (getenv("GMX_USE_MODULAR_SIMULATOR") != nullptr);
188     // GMX_USE_MODULAR_SIMULATOR allows to use disable modular simulator for all uses,
189     // including the velocity-verlet integrator used by default
190     const auto modularSimulatorExplicitlyTurnedOff = (getenv("GMX_DISABLE_MODULAR_SIMULATOR") != nullptr);
191
192     GMX_RELEASE_ASSERT(
193             !(modularSimulatorExplicitlyTurnedOn && modularSimulatorExplicitlyTurnedOff),
194             "Cannot have both GMX_USE_MODULAR_SIMULATOR=ON and GMX_DISABLE_MODULAR_SIMULATOR=ON. "
195             "Unset one of the two environment variables to explicitly chose which simulator to "
196             "use, "
197             "or unset both to recover default behavior.");
198
199     GMX_RELEASE_ASSERT(
200             !(modularSimulatorExplicitlyTurnedOff && inputrec->eI == eiVV
201               && inputrec->epc == epcPARRINELLORAHMAN),
202             "Cannot use a Parrinello-Rahman barostat with md-vv and "
203             "GMX_DISABLE_MODULAR_SIMULATOR=ON, "
204             "as the Parrinello-Rahman barostat is not implemented in the legacy simulator. Unset "
205             "GMX_DISABLE_MODULAR_SIMULATOR or use a different pressure control algorithm.");
206
207     isInputCompatible =
208             isInputCompatible
209             && conditionalAssert(
210                        inputrec->eI == eiMD || inputrec->eI == eiVV,
211                        "Only integrators md and md-vv are supported by the modular simulator.");
212     isInputCompatible = isInputCompatible
213                         && conditionalAssert(inputrec->eI != eiMD || modularSimulatorExplicitlyTurnedOn,
214                                              "Set GMX_USE_MODULAR_SIMULATOR=ON to use the modular "
215                                              "simulator with integrator md.");
216     isInputCompatible =
217             isInputCompatible
218             && conditionalAssert(!doRerun, "Rerun is not supported by the modular simulator.");
219     isInputCompatible =
220             isInputCompatible
221             && conditionalAssert(
222                        inputrec->etc == etcNO || inputrec->etc == etcVRESCALE,
223                        "Only v-rescale thermostat is supported by the modular simulator.");
224     isInputCompatible =
225             isInputCompatible
226             && conditionalAssert(
227                        inputrec->epc == epcNO || inputrec->epc == epcPARRINELLORAHMAN,
228                        "Only Parrinello-Rahman barostat is supported by the modular simulator.");
229     isInputCompatible =
230             isInputCompatible
231             && conditionalAssert(
232                        !(inputrecNptTrotter(inputrec) || inputrecNphTrotter(inputrec)
233                          || inputrecNvtTrotter(inputrec)),
234                        "Legacy Trotter decomposition is not supported by the modular simulator.");
235     isInputCompatible = isInputCompatible
236                         && conditionalAssert(inputrec->efep == efepNO || inputrec->efep == efepYES
237                                                      || inputrec->efep == efepSLOWGROWTH,
238                                              "Expanded ensemble free energy calculation is not "
239                                              "supported by the modular simulator.");
240     isInputCompatible = isInputCompatible
241                         && conditionalAssert(!inputrec->bPull,
242                                              "Pulling is not supported by the modular simulator.");
243     isInputCompatible =
244             isInputCompatible
245             && conditionalAssert(inputrec->opts.ngacc == 1 && inputrec->opts.acc[0][XX] == 0.0
246                                          && inputrec->opts.acc[0][YY] == 0.0
247                                          && inputrec->opts.acc[0][ZZ] == 0.0 && inputrec->cos_accel == 0.0,
248                                  "Acceleration is not supported by the modular simulator.");
249     isInputCompatible =
250             isInputCompatible
251             && conditionalAssert(inputrec->opts.ngfrz == 1 && inputrec->opts.nFreeze[0][XX] == 0
252                                          && inputrec->opts.nFreeze[0][YY] == 0
253                                          && inputrec->opts.nFreeze[0][ZZ] == 0,
254                                  "Freeze groups are not supported by the modular simulator.");
255     isInputCompatible =
256             isInputCompatible
257             && conditionalAssert(
258                        inputrec->deform[XX][XX] == 0.0 && inputrec->deform[XX][YY] == 0.0
259                                && inputrec->deform[XX][ZZ] == 0.0 && inputrec->deform[YY][XX] == 0.0
260                                && inputrec->deform[YY][YY] == 0.0 && inputrec->deform[YY][ZZ] == 0.0
261                                && inputrec->deform[ZZ][XX] == 0.0 && inputrec->deform[ZZ][YY] == 0.0
262                                && inputrec->deform[ZZ][ZZ] == 0.0,
263                        "Deformation is not supported by the modular simulator.");
264     isInputCompatible =
265             isInputCompatible
266             && conditionalAssert(gmx_mtop_interaction_count(globalTopology, IF_VSITE) == 0,
267                                  "Virtual sites are not supported by the modular simulator.");
268     isInputCompatible = isInputCompatible
269                         && conditionalAssert(!inputrec->bDoAwh,
270                                              "AWH is not supported by the modular simulator.");
271     isInputCompatible =
272             isInputCompatible
273             && conditionalAssert(gmx_mtop_ftype_count(globalTopology, F_DISRES) == 0,
274                                  "Distance restraints are not supported by the modular simulator.");
275     isInputCompatible =
276             isInputCompatible
277             && conditionalAssert(
278                        gmx_mtop_ftype_count(globalTopology, F_ORIRES) == 0,
279                        "Orientation restraints are not supported by the modular simulator.");
280     isInputCompatible =
281             isInputCompatible
282             && conditionalAssert(ms == nullptr,
283                                  "Multi-sim are not supported by the modular simulator.");
284     isInputCompatible =
285             isInputCompatible
286             && conditionalAssert(replExParams.exchangeInterval == 0,
287                                  "Replica exchange is not supported by the modular simulator.");
288
289     int numEnsembleRestraintSystems;
290     if (fcd)
291     {
292         numEnsembleRestraintSystems = fcd->disres->nsystems;
293     }
294     else
295     {
296         auto distantRestraintEnsembleEnvVar = getenv("GMX_DISRE_ENSEMBLE_SIZE");
297         numEnsembleRestraintSystems =
298                 (ms != nullptr && distantRestraintEnsembleEnvVar != nullptr)
299                         ? static_cast<int>(strtol(distantRestraintEnsembleEnvVar, nullptr, 10))
300                         : 0;
301     }
302     isInputCompatible =
303             isInputCompatible
304             && conditionalAssert(numEnsembleRestraintSystems <= 1,
305                                  "Ensemble restraints are not supported by the modular simulator.");
306     isInputCompatible =
307             isInputCompatible
308             && conditionalAssert(!doSimulatedAnnealing(inputrec),
309                                  "Simulated annealing is not supported by the modular simulator.");
310     isInputCompatible =
311             isInputCompatible
312             && conditionalAssert(!inputrec->bSimTemp,
313                                  "Simulated tempering is not supported by the modular simulator.");
314     isInputCompatible = isInputCompatible
315                         && conditionalAssert(!inputrec->bExpanded,
316                                              "Expanded ensemble simulations are not supported by "
317                                              "the modular simulator.");
318     isInputCompatible =
319             isInputCompatible
320             && conditionalAssert(!doEssentialDynamics,
321                                  "Essential dynamics is not supported by the modular simulator.");
322     isInputCompatible = isInputCompatible
323                         && conditionalAssert(inputrec->eSwapCoords == eswapNO,
324                                              "Ion / water position swapping is not supported by "
325                                              "the modular simulator.");
326     isInputCompatible =
327             isInputCompatible
328             && conditionalAssert(!inputrec->bIMD,
329                                  "Interactive MD is not supported by the modular simulator.");
330     isInputCompatible =
331             isInputCompatible
332             && conditionalAssert(!doMembed,
333                                  "Membrane embedding is not supported by the modular simulator.");
334     // TODO: Change this to the boolean passed when we merge the user interface change for the GPU update.
335     isInputCompatible =
336             isInputCompatible
337             && conditionalAssert(
338                        getenv("GMX_FORCE_UPDATE_DEFAULT_GPU") == nullptr,
339                        "Integration on the GPU is not supported by the modular simulator.");
340     // Modular simulator is centered around NS updates
341     // TODO: think how to handle nstlist == 0
342     isInputCompatible = isInputCompatible
343                         && conditionalAssert(inputrec->nstlist != 0,
344                                              "Simulations without neighbor list update are not "
345                                              "supported by the modular simulator.");
346     isInputCompatible = isInputCompatible
347                         && conditionalAssert(!GMX_FAHCORE,
348                                              "GMX_FAHCORE not supported by the modular simulator.");
349
350     return isInputCompatible;
351 }
352
353 ModularSimulator::ModularSimulator(std::unique_ptr<LegacySimulatorData> legacySimulatorData) :
354     legacySimulatorData_(std::move(legacySimulatorData))
355 {
356     checkInputForDisabledFunctionality();
357 }
358
359 void ModularSimulator::checkInputForDisabledFunctionality()
360 {
361     isInputCompatible(true, legacySimulatorData_->inputrec,
362                       legacySimulatorData_->mdrunOptions.rerun, *legacySimulatorData_->top_global,
363                       legacySimulatorData_->ms, legacySimulatorData_->replExParams,
364                       &legacySimulatorData_->fr->listedForces->fcdata(),
365                       opt2bSet("-ei", legacySimulatorData_->nfile, legacySimulatorData_->fnm),
366                       legacySimulatorData_->membed != nullptr);
367     if (legacySimulatorData_->observablesHistory->edsamHistory)
368     {
369         gmx_fatal(FARGS,
370                   "The checkpoint is from a run with essential dynamics sampling, "
371                   "but the current run did not specify the -ei option. "
372                   "Either specify the -ei option to mdrun, or do not use this checkpoint file.");
373     }
374 }
375
376 } // namespace gmx