2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2015,2017,2018,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.
35 /*! \libinternal \file
37 * \brief Declares the routine running the inetgrators.
39 * \author David van der Spoel <david.vanderspoel@icm.uu.se>
40 * \ingroup module_mdrun
42 #ifndef GMX_MDRUN_RUNNER_H
43 #define GMX_MDRUN_RUNNER_H
50 #include "gromacs/commandline/filenm.h"
51 #include "gromacs/compat/pointers.h"
52 #include "gromacs/domdec/options.h"
53 #include "gromacs/hardware/hw_info.h"
54 #include "gromacs/math/vec.h"
55 #include "gromacs/mdrun/mdmodules.h"
56 #include "gromacs/mdrun/simulationinputhandle.h"
57 #include "gromacs/mdrunutility/handlerestart.h"
58 #include "gromacs/mdtypes/mdrunoptions.h"
59 #include "gromacs/utility/arrayref.h"
60 #include "gromacs/utility/basedefinitions.h"
61 #include "gromacs/utility/gmxmpi.h"
62 #include "gromacs/utility/real.h"
64 #include "replicaexchange.h"
66 struct gmx_multisim_t;
67 struct gmx_output_env_t;
68 struct ReplicaExchangeParameters;
74 // Todo: move to forward declaration headers...
76 class IRestraintPotential; // defined in restraint/restraintpotential.h
77 class RestraintManager;
78 class SimulationContext;
79 class StopHandlerBuilder;
81 //! Work-around for GCC bug 58265 still present in CentOS 7 devtoolset-7
82 constexpr bool BUGFREE_NOEXCEPT_STRING = std::is_nothrow_move_assignable<std::string>::value;
84 /*! \libinternal \brief Runner object for supporting setup and execution of mdrun.
86 * This class has responsibility for the lifetime of data structures
87 * that exist for the life of the simulation, e.g. for logging and
90 * It is also responsible for initializing data members that
91 * e.g. correspond to values potentially set by commmand-line
92 * options. Later these will be obtained directly from modules, and
93 * the results of command-line option handling returned directly to
94 * the modules, rather than propagated to them by data members of this
97 * \todo Most of the attributes should be declared by specific modules
98 * as command-line options. Accordingly, they do not conform to the
99 * naming scheme, because that would make for a lot of noise in the
100 * diff, only to have it change again when the options move to their
103 * \todo Preparing logging and MPI contexts could probably be a
104 * higher-level responsibility, so that an Mdrunner would get made
105 * without needing to re-initialize these components (as currently
106 * happens always for the master rank, and differently for the spawned
107 * ranks with thread-MPI).
109 * \ingroup module_mdrun
114 /*! \brief Builder class to manage object creation.
116 * This class is a member of gmx::Mdrunner so that it can initialize
117 * private members of gmx::Mdrunner.
119 * It is non-trivial to establish an initialized gmx::Mdrunner invariant,
120 * so objects can be obtained by clients using a Builder or a move.
121 * Clients cannot default initialize or copy gmx::Mdrunner.
123 class BuilderImplementation;
128 * \brief Copy not allowed.
130 * An Mdrunner has unique resources and it is not clear whether any of
131 * one of those resources should be duplicated or shared unless the
132 * specific use case is known. Either build a fresh runner or use a
133 * helper function for clearly indicated behavior. API clarification may
134 * allow unambiguous initialization by copy in future versions.
138 Mdrunner(const Mdrunner&) = delete;
139 Mdrunner& operator=(const Mdrunner&) = delete;
143 * \brief Mdrunner objects can be passed by value via move semantics.
145 * \param handle runner instance to be moved from.
148 Mdrunner(Mdrunner&& handle) noexcept;
149 //NOLINTNEXTLINE(performance-noexcept-move-constructor) working around GCC bug 58265 in CentOS 7
150 Mdrunner& operator=(Mdrunner&& handle) noexcept(BUGFREE_NOEXCEPT_STRING);
153 /*! \brief Driver routine, that calls the different simulation methods. */
155 * Currently, thread-MPI does not spawn threads until during mdrunner() and parallelism
156 * is not initialized until some time during this call...
161 * \brief Add a potential to be evaluated during MD integration.
163 * \param restraint MD restraint potential to apply
164 * \param name User-friendly plain-text name to uniquely identify the puller
166 * This implementation attaches an object providing the gmx::IRestraintPotential
168 * \todo Mdrunner should fetch such resources from the SimulationContext
169 * rather than offering this public interface.
171 void addPotential(std::shared_ptr<IRestraintPotential> restraint, const std::string& name);
173 /*! \brief Prepare the thread-MPI communicator to have \c
174 * numThreadsToLaunch ranks, by spawning new thread-MPI
177 * Called by mdrunner() to start a specific number of threads
178 * (including the main thread) for thread-parallel runs. This
179 * in turn calls mdrunner() for each thread. */
180 void spawnThreads(int numThreadsToLaunch);
182 /*! \brief Initializes a new Mdrunner from the master.
184 * Run this method in a new thread from a master runner to get additional
185 * workers on spawned threads.
187 * \returns New Mdrunner instance suitable for thread-MPI work on new ranks.
190 * \todo clarify (multiple) invariants during MD runner start-up.
191 * The runner state before and after launching threads is distinct enough that
192 * it should be codified in the invariants of different classes. That would
193 * mean that the object returned by this method would be of a different type
194 * than the object held by the client up to the point of call, and its name
195 * would be changed to "launchOnSpawnedThread" or something not including the
198 Mdrunner cloneOnSpawnedThread() const;
201 /*! \brief Constructor. */
202 explicit Mdrunner(std::unique_ptr<MDModules> mdModules);
204 //! Parallelism-related user options.
207 //! Filenames and properties from command-line argument values.
208 ArrayRef<const t_filenm> filenames;
210 /*! \brief Output context for writing text files
213 * \todo push this data member down when the information can be queried from an encapsulated resource.
215 gmx_output_env_t* oenv = nullptr;
216 //! Ongoing collection of mdrun options
217 MdrunOptions mdrunOptions;
218 //! Options for the domain decomposition.
219 DomdecOptions domdecOptions;
221 /*! \brief Target short-range interations for "cpu", "gpu", or "auto". Default is "auto".
224 * \todo replace with string or enum class and initialize with sensible value.
226 const char* nbpu_opt = nullptr;
228 /*! \brief Target long-range interactions for "cpu", "gpu", or "auto". Default is "auto".
231 * \todo replace with string or enum class and initialize with sensible value.
233 const char* pme_opt = nullptr;
235 /*! \brief Target long-range interactions FFT/solve stages for "cpu", "gpu", or "auto". Default is "auto".
238 * \todo replace with string or enum class and initialize with sensible value.
240 const char* pme_fft_opt = nullptr;
242 /*! \brief Target bonded interations for "cpu", "gpu", or "auto". Default is "auto".
245 * \todo replace with string or enum class and initialize with sensible value.
247 const char* bonded_opt = nullptr;
249 /*! \brief Target update calculation for "cpu", "gpu", or "auto". Default is "auto".
252 * \todo replace with string or enum class and initialize with sensible value.
254 const char* update_opt = nullptr;
256 //! Command-line override for the duration of a neighbor list with the Verlet scheme.
257 int nstlist_cmdline = 0;
258 //! Parameters for replica-exchange simulations.
259 ReplicaExchangeParameters replExParams;
260 //! Print a warning if any force is larger than this (in kJ/mol nm).
263 //! Handle to file used for logging.
264 LogFilePtr logFileGuard = nullptr;
265 //! \brief Non-owning handle to file used for logging.
266 t_fileio* logFileHandle = nullptr;
268 /*! \brief Non-owning handle to world communication data structure for task assigment.
270 * With real MPI, gets a value from the SimulationContext
271 * supplied to the MdrunnerBuilder. With thread-MPI gets a
272 * value after threads have been spawned. */
273 MPI_Comm libraryWorldCommunicator = MPI_COMM_NULL;
275 /*! \brief Non-owning handle to communication data structure for the current simulation.
277 * With real MPI, gets a value from the SimulationContext
278 * supplied to the MdrunnerBuilder. With thread-MPI gets a
279 * value after threads have been spawned. */
280 MPI_Comm simulationCommunicator = MPI_COMM_NULL;
282 //! \brief Non-owning handle to multi-simulation handler.
283 gmx_multisim_t* ms = nullptr;
285 //! Whether the simulation will start afresh, or restart with/without appending.
286 StartingBehavior startingBehavior = StartingBehavior::NewSimulation;
289 * \brief Handle to restraints manager for the current process.
292 * Use opaque pointer for this implementation detail.
294 std::unique_ptr<RestraintManager> restraintManager_;
297 * \brief Builder for stop signal handler
299 * Optionally provided through MdrunnerBuilder. Client may create a
300 * StopHandlerBuilder and register any number of signal providers before
301 * launching the Mdrunner.
303 * Default is an empty signal handler that will have local signal issuers
304 * added after being passed into the integrator.
307 * We do not need a full type specification here, so we use an opaque pointer.
309 std::unique_ptr<StopHandlerBuilder> stopHandlerBuilder_;
310 //! The modules that comprise mdrun.
311 std::unique_ptr<MDModules> mdModules_;
313 //! Non-owning handle to the results of the hardware detection.
314 const gmx_hw_info_t* hwinfo_ = nullptr;
317 * \brief Holds simulation input specification provided by client, if any.
319 * If present on any instance (rank) of a simulation runner, an identical
320 * (or compatible) SimulationInput must be held on all cooperating instances.
322 SimulationInputHandle inputHolder_;
326 * \brief Build a gmx::Mdrunner.
328 * Client code (such as `gmx mdrun`) uses this builder to get an initialized Mdrunner.
330 * A builder allows the library to ensure that client code cannot obtain an
331 * uninitialized or partially initialized runner by refusing to build() if the
332 * client has not provided sufficient or self-consistent direction. Director
333 * code can be implemented for different user interfaces, encapsulating any
334 * run-time functionality that does not belong in the library MD code, such
335 * as command-line option processing or interfacing to external libraries.
337 * \ingroup module_mdrun
341 * The initial Builder implementation is neither extensible at run time nor
342 * at compile time. Future implementations should evolve to compose the runner,
343 * rather than just consolidating the parameters for initialization, but there
344 * is not yet a firm design for how flexibly module code will be coupled to
345 * the builder and how much of the client interface will be in this Builder
346 * versus Builders provided by the various modules.
348 * The named components for the initial builder implementation are descriptive
349 * of the state of mdrun at the time, and are not intended to be prescriptive of
351 * The probable course of GROMACS development is for the modular components that
352 * support MD simulation to independently express their input parameters (required
353 * and optional) and to provide some sort of help to the UI for input preparation.
354 * If each module provides or aids the instantiation of a Director
355 * for the client code, the Directors could be constructed with a handle to this
356 * Builder and it would not need a public interface.
358 * As the modules are more clearly encapsulated, each module can provide its own
359 * builder, user interface helpers, and/or composable Director code.
360 * The runner and client code will also have to be updated as appropriate
361 * default behavior is clarified for
362 * (a) default behavior of client when user does not provide input,
363 * (b) default behavior of builder when client does not provide input, and
364 * (c) default behavior of runner when builder does not provide input.
366 class MdrunnerBuilder final
370 * \brief Constructor requires a handle to a SimulationContext to share.
372 * \param mdModules The handle to the set of modules active in mdrun
373 * \param context Required handle to simulation context
375 * The calling code must guarantee that the
376 * pointer remains valid for the lifetime of the builder, and that the
377 * resources retrieved from the context remain valid for the lifetime of
378 * the runner produced.
380 explicit MdrunnerBuilder(std::unique_ptr<MDModules> mdModules,
381 compat::not_null<SimulationContext*> context);
384 MdrunnerBuilder() = delete;
385 MdrunnerBuilder(const MdrunnerBuilder&) = delete;
386 MdrunnerBuilder& operator=(const MdrunnerBuilder&) = delete;
389 /*! \brief Allow transfer of ownership with move semantics.
391 * \param builder source object to transfer.
395 MdrunnerBuilder(MdrunnerBuilder&& builder) noexcept;
396 MdrunnerBuilder& operator=(MdrunnerBuilder&& builder) noexcept;
400 * \brief Get ownership of an initialized gmx::Mdrunner.
402 * After build() is called, the Builder object should not be used
403 * again. It is an error to call build without first calling all builder
404 * methods described as "required."
406 * \return A new Mdrunner.
408 * \throws APIError if a required component has not been added before calling build().
413 * \brief Supply the result of hardware detection to the gmx::Mdrunner
415 * \param hwinfo Non-owning not-null handle to result of hardware detection.
417 * \todo It would be better to express this as either a not-null const pointer or
418 * a const reference, but neither of those is consistent with incremental
419 * building of an object. This motivates future work to be able to make a deep copy
420 * of the detection result. See https://gitlab.com/gromacs/gromacs/-/issues/3650 */
421 MdrunnerBuilder& addHardwareDetectionResult(const gmx_hw_info_t* hwinfo);
424 * \brief Set up non-bonded short-range force calculations.
426 * Required. Director code must provide valid options for the non-bonded
427 * interaction code. The builder does not apply any defaults.
429 * \param nbpu_opt Target short-range interactions for "cpu", "gpu", or "auto".
431 * Calling must guarantee that the pointed-to C string is valid through
435 * \todo Replace with string or enum that we can have sensible defaults for.
436 * \todo Either the Builder or modular Director code should provide sensible defaults.
438 MdrunnerBuilder& addNonBonded(const char* nbpu_opt);
441 * \brief Set up long-range electrostatics calculations.
443 * Required. Director code should provide valid options for PME electrostatics,
444 * whether or not PME electrostatics are used. The builder does not apply
445 * any defaults, so client code should be prepared to provide (e.g.) "auto"
446 * in the event no user input or logic provides an alternative argument.
448 * \param pme_opt Target long-range interactions for "cpu", "gpu", or "auto".
449 * \param pme_fft_opt Target long-range interactions FFT/solve stages for "cpu", "gpu", or "auto".
451 * Calling must guarantee that the pointed-to C strings are valid through
455 * The arguments are passed as references to elements of arrays of C strings.
456 * \todo Replace with modern strings or (better) enum classes.
457 * \todo Make optional and/or encapsulate into electrostatics module.
459 MdrunnerBuilder& addElectrostatics(const char* pme_opt, const char* pme_fft_opt);
462 * \brief Assign responsibility for tasks for bonded interactions.
464 * Required. Director code should provide valid options for
465 * bonded interaction task assignment, whether or not such
466 * interactions are present. The builder does not apply any
467 * defaults, so client code should be prepared to provide
468 * (e.g.) "auto" in the event no user input or logic provides
469 * an alternative argument.
471 * \param bonded_opt Target bonded interactions for "cpu", "gpu", or "auto".
473 * Calling must guarantee that the pointed-to C strings are valid through
477 * The arguments are passed as references to elements of arrays of C strings.
478 * \todo Replace with modern strings or (better) enum classes.
479 * \todo Make optional and/or encapsulate into task assignment module.
481 MdrunnerBuilder& addBondedTaskAssignment(const char* bonded_opt);
484 * Assign responsibility for tasks for update and constrain calculation.
486 * Required. Director code should provide valid options for
487 * update and constraint task assignment. The builder does not apply any
488 * defaults, so client code should be prepared to provide
489 * (e.g.) "auto" in the event no user input or logic provides
490 * an alternative argument.
492 * \param[in] update_opt Target update calculation for "cpu", "gpu", or "auto".
494 * Calling must guarantee that the pointed-to C strings are valid through
498 * The arguments are passed as references to elements of arrays of C strings.
499 * \todo Replace with modern strings or (better) enum classes.
500 * \todo Make optional and/or encapsulate into task assignment module.
502 MdrunnerBuilder& addUpdateTaskAssignment(const char* update_opt);
505 * \brief Set MD options not owned by some other module.
507 * Optional. Override simulation parameters
509 * \param options structure to copy
510 * \param forceWarningThreshold Print a warning if any force is larger than this (in kJ/mol nm) (default -1)
511 * \param startingBehavior Whether the simulation will start afresh, or restart with/without appending.
514 * \todo Map these parameters to more appropriate encapsulating types.
515 * Find a better way to indicate "unspecified" than a magic value of the parameter type.
517 MdrunnerBuilder& addSimulationMethod(const MdrunOptions& options,
518 real forceWarningThreshold,
519 StartingBehavior startingBehavior);
522 * \brief Set the domain decomposition module.
524 * Optional. Overrides default constructed DomdecOptions if provided.
526 * \param options options with which to construct domain decomposition.
529 * \todo revisit whether we should be passing this parameter struct or a higher-level handle of some sort.
531 MdrunnerBuilder& addDomainDecomposition(const DomdecOptions& options);
534 * \brief Set Verlet list manager.
536 * Optional. Neighbor list existence, type, and parameters are mostly determined
537 * by the simulation parameters loaded elsewhere. This is just an override.
539 * \param rebuildInterval override for the duration of a neighbor list with the Verlet scheme.
541 MdrunnerBuilder& addNeighborList(int rebuildInterval);
544 * \brief Set replica exchange manager.
546 * Optional. For guidance on preparing a valid ReplicaExchangeParameters
547 * value, refer to the details in mdrun.cpp, the `t_pargs pa[]` defined there,
548 * and the action of parse_common_args() with regards to that structure.
549 * If not provided by client, a default constructed ReplicaExchangeParameters
552 * \param params parameters with which to set up replica exchange.
555 * \todo revisit whether we should be passing this parameter struct or a higher-level handle of some sort.
557 MdrunnerBuilder& addReplicaExchange(const ReplicaExchangeParameters& params);
560 * \brief Specify parameters determining hardware resource allocation.
562 * Optional. If not provided, default-constructed gmx_hw_opt_t will be used.
564 * \param hardwareOptions Parallelism-related user options.
566 MdrunnerBuilder& addHardwareOptions(const gmx_hw_opt_t& hardwareOptions);
569 * \brief Provide the filenames options structure with option values chosen
571 * Required. The object is assumed to have been updated by
572 * parse_common_args or equivalent.
574 * \param filenames Filenames and properties from command-line argument values or defaults.
577 * \todo Modules should manage their own filename options and defaults.
579 MdrunnerBuilder& addFilenames(ArrayRef<const t_filenm> filenames);
582 * \brief Provide parameters for setting up output environment.
584 * Required. Handle is assumed to have been produced by output_env_init
585 * as in parse_common_args.
587 * \param outputEnvironment Output context for writing text files.
590 * \todo Allow client code to set up output environment and provide as a resource.
591 * This parameter is used to set up resources that are dependent on the execution
592 * environment and API context. Such resources should be retrieved by the simulator
593 * from a client-provided resource, but currently the resources are only fully
594 * initialized in Mdrunner.
596 MdrunnerBuilder& addOutputEnvironment(gmx_output_env_t* outputEnvironment);
599 * \brief Provide the filehandle pointer to be used for the MD log.
601 * Required. Either nullptr if no log should be written, or
602 * valid and open reading for writing.
604 * \param logFileHandle Non-owning handle to file used for logging.
607 MdrunnerBuilder& addLogFile(t_fileio* logFileHandle);
610 * \brief Provide a StopHandlerBuilder for the MD stop signal handling.
612 * Optional. Defaults to empty.
614 * Client may provide additional (non-default) issuers of simulation stop
615 * signals by preconfiguring the StopHandlerBuilder used later when the
620 MdrunnerBuilder& addStopHandlerBuilder(std::unique_ptr<StopHandlerBuilder> builder);
623 * \brief Acquire a handle to the SimulationInput.
625 * Required. SimulationInput will be taking responsibility for some of the
626 * input provided through other methods, such as addFilenames.
628 * See also issue https://gitlab.com/gromacs/gromacs/-/issues/3374
630 * \param input Shared ownership of a SimulationInput.
632 MdrunnerBuilder& addInput(SimulationInputHandle input);
637 std::unique_ptr<Mdrunner::BuilderImplementation> impl_;
642 #endif // GMX_MDRUN_RUNNER_H