cd3742bffc0305437d17d29cb7576f625763912a
[alexxy/gromacs.git] / src / gromacs / modularsimulator / trajectoryelement.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2019, 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 /*! \libinternal
36  * \brief Defines the trajectory element for the modular simulator
37  *
38  * \author Pascal Merz <pascal.merz@me.com>
39  * \ingroup module_modularsimulator
40  */
41 #include "gmxpre.h"
42
43 #include "trajectoryelement.h"
44
45 #include "gromacs/mdlib/mdoutf.h"
46 #include "gromacs/mdlib/stat.h"
47 #include "gromacs/mdrunutility/handlerestart.h"
48 #include "gromacs/mdtypes/inputrec.h"
49
50 namespace gmx
51 {
52 TrajectoryElement::TrajectoryElement(
53         std::vector<SignallerCallbackPtr> signalEnergyCallbacks,
54         std::vector<SignallerCallbackPtr> signalStateCallbacks,
55         std::vector<ITrajectoryWriterClient*> writerClients,
56         FILE *fplog, int nfile, const t_filenm fnm[],
57         const MdrunOptions &mdrunOptions,
58         const t_commrec *cr,
59         gmx::IMDOutputProvider *outputProvider,
60         const t_inputrec *inputrec, gmx_mtop_t *top_global,
61         const gmx_output_env_t *oenv, gmx_wallcycle *wcycle,
62         StartingBehavior startingBehavior) :
63     writeEnergyStep_(-1),
64     writeStateStep_(-1),
65     outf_(init_mdoutf(
66                   fplog, nfile, fnm, mdrunOptions, cr,
67                   outputProvider, inputrec, top_global, oenv, wcycle,
68                   startingBehavior)),
69     nstxout_(inputrec->nstxout),
70     nstvout_(inputrec->nstvout),
71     nstfout_(inputrec->nstfout),
72     nstxoutCompressed_(inputrec->nstxout_compressed),
73     tngBoxOut_(mdoutf_get_tng_box_output_interval(outf_)),
74     tngLambdaOut_(mdoutf_get_tng_lambda_output_interval(outf_)),
75     tngBoxOutCompressed_(mdoutf_get_tng_compressed_box_output_interval(outf_)),
76     tngLambdaOutCompressed_(mdoutf_get_tng_compressed_lambda_output_interval(outf_)),
77     nstenergy_(inputrec->nstenergy),
78     signalEnergyCallbacks_(std::move(signalEnergyCallbacks)),
79     signalStateCallbacks_(std::move(signalStateCallbacks)),
80     lastStep_(-1),
81     lastStepRegistrationDone_(false),
82     writerClients_(std::move(writerClients))
83 {}
84
85 void TrajectoryElement::signallerSetup()
86 {
87     GMX_ASSERT(
88             lastStepRegistrationDone_,
89             "TrajectoryElement needs to be registered to LastStepSignaller.");
90 }
91
92 void TrajectoryElement::signal(Step step, Time time)
93 {
94     if (do_per_step(step, nstxout_) ||
95         do_per_step(step, nstvout_) ||
96         do_per_step(step, nstfout_) ||
97         do_per_step(step, nstxoutCompressed_) ||
98         do_per_step(step, tngBoxOut_) ||
99         do_per_step(step, tngLambdaOut_) ||
100         do_per_step(step, tngBoxOutCompressed_) ||
101         do_per_step(step, tngLambdaOutCompressed_))
102     {
103         writeStateStep_ = step;
104         for (const auto &callback : signalStateCallbacks_)
105         {
106             (*callback)(step, time);
107         }
108     }
109
110     if (do_per_step(step, nstenergy_) || step == lastStep_)
111     {
112         writeEnergyStep_ = step;
113         for (const auto &callback : signalEnergyCallbacks_)
114         {
115             (*callback)(step, time);
116         }
117     }
118 }
119
120 void TrajectoryElement::elementSetup()
121 {
122     for (auto &client : writerClients_)
123     {
124         auto callback = client->registerTrajectoryWriterCallback(
125                     TrajectoryEvent::stateWritingStep);
126         if (callback)
127         {
128             runStateCallbacks_.emplace_back(std::move(callback));
129         }
130         callback = client->registerTrajectoryWriterCallback(
131                     TrajectoryEvent::energyWritingStep);
132         if (callback)
133         {
134             runEnergyCallbacks_.emplace_back(std::move(callback));
135         }
136         client->trajectoryWriterSetup(outf_);
137     }
138 }
139
140 void TrajectoryElement::scheduleTask(
141         Step step, Time time, const RegisterRunFunctionPtr &registerRunFunction)
142 {
143     auto writeEnergyThisStep = writeEnergyStep_ == step;
144     auto writeStateThisStep  = writeStateStep_ == step;
145     if (writeEnergyThisStep || writeStateThisStep)
146     {
147         (*registerRunFunction)(std::make_unique<SimulatorRunFunction>(
148                                        [this, step, time, writeStateThisStep, writeEnergyThisStep]()
149                                        {write(step, time, writeStateThisStep, writeEnergyThisStep); }));
150     }
151 }
152
153 void TrajectoryElement::elementTeardown()
154 {
155     for (auto &client : writerClients_)
156     {
157         client->trajectoryWriterTeardown(outf_);
158     }
159     mdoutf_tng_close(outf_);
160     done_mdoutf(outf_);
161 }
162
163 void TrajectoryElement::write(
164         Step step, Time time, bool writeState, bool writeEnergy)
165 {
166     if (writeState)
167     {
168         for (auto &callback : runStateCallbacks_)
169         {
170             (*callback)(outf_, step, time);
171         }
172     }
173     if (writeEnergy)
174     {
175         for (auto &callback : runEnergyCallbacks_)
176         {
177             (*callback)(outf_, step, time);
178         }
179     }
180 }
181
182 SignallerCallbackPtr TrajectoryElement::registerLastStepCallback()
183 {
184     lastStepRegistrationDone_ = true;
185     return std::make_unique<SignallerCallback>(
186             [this](Step step, Time gmx_unused time){this->lastStep_ = step; });
187 }
188
189 void TrajectoryElementBuilder::registerSignallerClient(
190         compat::not_null<ITrajectorySignallerClient*> client)
191 {
192     signallerClients_.emplace_back(client);
193 }
194
195 void TrajectoryElementBuilder::registerWriterClient(
196         compat::not_null<ITrajectoryWriterClient*> client)
197 {
198     writerClients_.emplace_back(client);
199 }
200
201 }  // namespace gmx