2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2019,2020,2021, 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 state for the modular simulator
38 * \author Pascal Merz <pascal.merz@me.com>
39 * \ingroup module_modularsimulator
44 #include "gromacs/utility/enumerationhelpers.h"
45 #include "statepropagatordata.h"
47 #include "gromacs/commandline/filenm.h"
48 #include "gromacs/domdec/collect.h"
49 #include "gromacs/domdec/domdec.h"
50 #include "gromacs/fileio/confio.h"
51 #include "gromacs/math/vec.h"
52 #include "gromacs/mdlib/gmx_omp_nthreads.h"
53 #include "gromacs/mdlib/mdatoms.h"
54 #include "gromacs/mdlib/mdoutf.h"
55 #include "gromacs/mdlib/stat.h"
56 #include "gromacs/mdlib/update.h"
57 #include "gromacs/mdtypes/checkpointdata.h"
58 #include "gromacs/mdtypes/commrec.h"
59 #include "gromacs/mdtypes/forcebuffers.h"
60 #include "gromacs/mdtypes/forcerec.h"
61 #include "gromacs/mdtypes/inputrec.h"
62 #include "gromacs/mdtypes/mdatom.h"
63 #include "gromacs/mdtypes/mdrunoptions.h"
64 #include "gromacs/mdtypes/state.h"
65 #include "gromacs/pbcutil/pbc.h"
66 #include "gromacs/topology/atoms.h"
67 #include "gromacs/topology/topology.h"
68 #include "gromacs/trajectory/trajectoryframe.h"
70 #include "freeenergyperturbationdata.h"
71 #include "modularsimulator.h"
72 #include "simulatoralgorithm.h"
77 * \brief Helper object to scale velocities according to reference temperature change
79 class StatePropagatorData::ReferenceTemperatureHelper
83 ReferenceTemperatureHelper(const t_inputrec* inputrec,
84 StatePropagatorData* statePropagatorData,
85 const t_mdatoms* mdatoms) :
86 numTemperatureGroups_(inputrec->opts.ngtc),
87 referenceTemperature_(inputrec->opts.ref_t, inputrec->opts.ref_t + inputrec->opts.ngtc),
88 velocityScalingFactors_(numTemperatureGroups_),
89 statePropagatorData_(statePropagatorData),
94 /*! \brief Update the reference temperature
96 * Changing the reference temperature requires scaling the velocities, which
99 * \param temperatures New reference temperatures
100 * \param algorithm The algorithm which initiated the temperature update
102 void updateReferenceTemperature(ArrayRef<const real> temperatures,
103 ReferenceTemperatureChangeAlgorithm gmx_unused algorithm)
105 // Currently, we don't know about any temperature change algorithms, so we assert this never gets called
106 GMX_ASSERT(false, "StatePropagatorData: Unknown ReferenceTemperatureChangeAlgorithm.");
107 for (int temperatureGroup = 0; temperatureGroup < numTemperatureGroups_; ++temperatureGroup)
109 velocityScalingFactors_[temperatureGroup] =
110 std::sqrt(temperatures[temperatureGroup] / referenceTemperature_[temperatureGroup]);
113 auto velocities = statePropagatorData_->velocitiesView().unpaddedArrayRef();
114 int nth = gmx_omp_nthreads_get(ModuleMultiThread::Update);
115 #pragma omp parallel for num_threads(nth) schedule(static) default(none) \
116 shared(nth, velocityScalingFactors_, velocities)
117 for (int threadIndex = 0; threadIndex < nth; threadIndex++)
121 getThreadAtomRange(nth, threadIndex, statePropagatorData_->localNAtoms_, &startAtom, &endAtom);
122 for (int atomIdx = startAtom; atomIdx < endAtom; ++atomIdx)
124 const int temperatureGroup = (mdatoms_->cTC != nullptr) ? mdatoms_->cTC[atomIdx] : 0;
125 velocities[atomIdx] *= velocityScalingFactors_[temperatureGroup];
128 std::copy(temperatures.begin(), temperatures.end(), referenceTemperature_.begin());
132 //! The number of temperature groups
133 const int numTemperatureGroups_;
134 //! Coupling temperature per group
135 std::vector<real> referenceTemperature_;
136 //! Working array used at every temperature update
137 std::vector<real> velocityScalingFactors_;
139 //! Pointer to StatePropagatorData to scale velocities
140 StatePropagatorData* statePropagatorData_;
141 //! Atom parameters for this domain (temperature group information)
142 const t_mdatoms* mdatoms_;
145 StatePropagatorData::StatePropagatorData(int numAtoms,
148 t_state* globalState,
151 bool canMoleculesBeDistributedOverPBC,
152 bool writeFinalConfiguration,
153 const std::string& finalConfigurationFilename,
154 const t_inputrec* inputrec,
155 const t_mdatoms* mdatoms,
156 const gmx_mtop_t& globalTop) :
157 totalNumAtoms_(numAtoms),
160 previousBox_{ { 0 } },
162 element_(std::make_unique<Element>(this,
168 inputrec->nstxout_compressed,
169 canMoleculesBeDistributedOverPBC,
170 writeFinalConfiguration,
171 finalConfigurationFilename,
174 referenceTemperatureHelper_(std::make_unique<ReferenceTemperatureHelper>(inputrec, this, mdatoms)),
175 vvResetVelocities_(false),
176 isRegularSimulationEnd_(false),
178 globalState_(globalState)
180 bool stateHasVelocities;
181 // Local state only becomes valid now.
182 if (DOMAINDECOMP(cr))
184 dd_init_local_state(*cr->dd, globalState, localState);
185 stateHasVelocities = ((localState->flags & enumValueToBitMask(StateEntry::V)) != 0);
186 setLocalState(localState);
190 state_change_natoms(globalState, globalState->natoms);
191 f_.resize(globalState->natoms);
192 localNAtoms_ = globalState->natoms;
195 copy_mat(globalState->box, box_);
196 stateHasVelocities = ((globalState->flags & enumValueToBitMask(StateEntry::V)) != 0);
197 previousX_.resizeWithPadding(localNAtoms_);
198 ddpCount_ = globalState->ddp_count;
203 changePinningPolicy(&x_, gmx::PinningPolicy::PinnedIfSupported);
206 if (DOMAINDECOMP(cr) && MASTER(cr))
208 xGlobal_.resizeWithPadding(totalNumAtoms_);
209 previousXGlobal_.resizeWithPadding(totalNumAtoms_);
210 vGlobal_.resizeWithPadding(totalNumAtoms_);
211 fGlobal_.resizeWithPadding(totalNumAtoms_);
214 if (!inputrec->bContinuation)
216 if (stateHasVelocities)
218 auto v = velocitiesView().paddedArrayRef();
219 // Set the velocities of vsites, shells and frozen atoms to zero
220 for (int i = 0; i < mdatoms->homenr; i++)
222 if (mdatoms->ptype[i] == ParticleType::Shell)
226 else if (mdatoms->cFREEZE)
228 for (int m = 0; m < DIM; m++)
230 if (inputrec->opts.nFreeze[mdatoms->cFREEZE[i]][m])
238 if (inputrec->eI == IntegrationAlgorithm::VV)
240 vvResetVelocities_ = true;
245 StatePropagatorData::~StatePropagatorData() = default;
247 StatePropagatorData::Element* StatePropagatorData::element()
249 return element_.get();
252 void StatePropagatorData::setup()
256 element_->elementSetup();
260 ArrayRefWithPadding<RVec> StatePropagatorData::positionsView()
262 return x_.arrayRefWithPadding();
265 ArrayRefWithPadding<const RVec> StatePropagatorData::constPositionsView() const
267 return x_.constArrayRefWithPadding();
270 ArrayRefWithPadding<RVec> StatePropagatorData::previousPositionsView()
272 return previousX_.arrayRefWithPadding();
275 ArrayRefWithPadding<const RVec> StatePropagatorData::constPreviousPositionsView() const
277 return previousX_.constArrayRefWithPadding();
280 ArrayRefWithPadding<RVec> StatePropagatorData::velocitiesView()
282 return v_.arrayRefWithPadding();
285 ArrayRefWithPadding<const RVec> StatePropagatorData::constVelocitiesView() const
287 return v_.constArrayRefWithPadding();
290 ForceBuffersView& StatePropagatorData::forcesView()
295 const ForceBuffersView& StatePropagatorData::constForcesView() const
300 rvec* StatePropagatorData::box()
305 const rvec* StatePropagatorData::constBox() const
310 rvec* StatePropagatorData::previousBox()
315 const rvec* StatePropagatorData::constPreviousBox() const
320 int StatePropagatorData::localNumAtoms() const
325 int StatePropagatorData::totalNumAtoms() const
327 return totalNumAtoms_;
330 t_state* StatePropagatorData::localState()
332 localState_->flags = enumValueToBitMask(StateEntry::X) | enumValueToBitMask(StateEntry::V)
333 | enumValueToBitMask(StateEntry::Box);
334 state_change_natoms(localState_, localNAtoms_);
335 std::swap(localState_->x, x_);
336 std::swap(localState_->v, v_);
337 copy_mat(box_, localState_->box);
338 localState_->ddp_count = ddpCount_;
339 localState_->ddp_count_cg_gl = ddpCountCgGl_;
340 localState_->cg_gl = cgGl_;
344 std::unique_ptr<t_state> StatePropagatorData::copyLocalState(std::unique_ptr<t_state> copy)
346 copy->flags = enumValueToBitMask(StateEntry::X) | enumValueToBitMask(StateEntry::V)
347 | enumValueToBitMask(StateEntry::Box);
348 state_change_natoms(copy.get(), localNAtoms_);
351 copy_mat(box_, copy->box);
352 copy->ddp_count = ddpCount_;
353 copy->ddp_count_cg_gl = ddpCountCgGl_;
358 void StatePropagatorData::setLocalState(t_state* state)
361 localNAtoms_ = state->natoms;
362 previousX_.resizeWithPadding(localNAtoms_);
363 std::swap(x_, state->x);
364 std::swap(v_, state->v);
365 copy_mat(state->box, box_);
367 ddpCount_ = state->ddp_count;
368 ddpCountCgGl_ = state->ddp_count_cg_gl;
369 cgGl_ = state->cg_gl;
371 if (vvResetVelocities_)
373 /* DomDec runs twice early in the simulation, once at setup time, and once before the first
374 * step. Every time DD runs, it sets a new local state here. We are saving a backup during
375 * setup time (ok for non-DD cases), so we need to update our backup to the DD state before
376 * the first step here to avoid resetting to an earlier DD state. This is done before any
377 * propagation that needs to be reset, so it's not very safe but correct for now.
378 * TODO: Get rid of this once input is assumed to be at half steps
380 velocityBackup_ = v_;
384 t_state* StatePropagatorData::globalState()
389 ForceBuffers* StatePropagatorData::forcePointer()
394 void StatePropagatorData::copyPosition()
396 int nth = gmx_omp_nthreads_get(ModuleMultiThread::Update);
398 #pragma omp parallel for num_threads(nth) schedule(static) default(none) shared(nth)
399 for (int th = 0; th < nth; th++)
401 int start_th, end_th;
402 getThreadAtomRange(nth, th, localNAtoms_, &start_th, &end_th);
403 copyPosition(start_th, end_th);
406 /* Box is changed in update() when we do pressure coupling,
407 * but we should still use the old box for energy corrections and when
408 * writing it to the energy file, so it matches the trajectory files for
409 * the same timestep above. Make a copy in a separate array.
411 copy_mat(box_, previousBox_);
414 void StatePropagatorData::copyPosition(int start, int end)
416 for (int i = start; i < end; ++i)
418 previousX_[i] = x_[i];
422 void StatePropagatorData::updateReferenceTemperature(ArrayRef<const real> temperatures,
423 ReferenceTemperatureChangeAlgorithm algorithm)
425 referenceTemperatureHelper_->updateReferenceTemperature(temperatures, algorithm);
428 void StatePropagatorData::Element::scheduleTask(Step step,
429 Time gmx_unused time,
430 const RegisterRunFunction& registerRunFunction)
432 if (statePropagatorData_->vvResetVelocities_)
434 statePropagatorData_->vvResetVelocities_ = false;
435 registerRunFunction([this]() { statePropagatorData_->resetVelocities(); });
437 // copy x -> previousX
438 registerRunFunction([this]() { statePropagatorData_->copyPosition(); });
439 // if it's a write out step, keep a copy for writeout
440 if (step == writeOutStep_ || (step == lastStep_ && writeFinalConfiguration_))
442 registerRunFunction([this]() { saveState(); });
446 void StatePropagatorData::Element::saveState()
448 GMX_ASSERT(!localStateBackupValid_,
449 "Save state called again before previous state was written.");
450 localStateBackup_ = statePropagatorData_->copyLocalState(std::move(localStateBackup_));
451 if (freeEnergyPerturbationData_)
453 localStateBackup_->fep_state = freeEnergyPerturbationData_->currentFEPState();
454 ArrayRef<const real> lambdaView = freeEnergyPerturbationData_->constLambdaView();
455 std::copy(lambdaView.begin(), lambdaView.end(), localStateBackup_->lambda.begin());
456 localStateBackup_->flags |=
457 enumValueToBitMask(StateEntry::Lambda) | enumValueToBitMask(StateEntry::FepState);
459 localStateBackupValid_ = true;
462 std::optional<SignallerCallback> StatePropagatorData::Element::registerTrajectorySignallerCallback(TrajectoryEvent event)
464 if (event == TrajectoryEvent::StateWritingStep)
466 return [this](Step step, Time /*unused*/) { this->writeOutStep_ = step; };
471 std::optional<ITrajectoryWriterCallback>
472 StatePropagatorData::Element::registerTrajectoryWriterCallback(TrajectoryEvent event)
474 if (event == TrajectoryEvent::StateWritingStep)
476 return [this](gmx_mdoutf* outf, Step step, Time time, bool writeTrajectory, bool gmx_unused writeLog) {
479 write(outf, step, time);
486 void StatePropagatorData::Element::write(gmx_mdoutf_t outf, Step currentStep, Time currentTime)
488 wallcycle_start(mdoutf_get_wcycle(outf), WallCycleCounter::Traj);
489 unsigned int mdof_flags = 0;
490 if (do_per_step(currentStep, nstxout_))
492 mdof_flags |= MDOF_X;
494 if (do_per_step(currentStep, nstvout_))
496 mdof_flags |= MDOF_V;
498 if (do_per_step(currentStep, nstfout_))
500 mdof_flags |= MDOF_F;
502 if (do_per_step(currentStep, nstxout_compressed_))
504 mdof_flags |= MDOF_X_COMPRESSED;
506 if (do_per_step(currentStep, mdoutf_get_tng_box_output_interval(outf)))
508 mdof_flags |= MDOF_BOX;
510 if (do_per_step(currentStep, mdoutf_get_tng_lambda_output_interval(outf)))
512 mdof_flags |= MDOF_LAMBDA;
514 if (do_per_step(currentStep, mdoutf_get_tng_compressed_box_output_interval(outf)))
516 mdof_flags |= MDOF_BOX_COMPRESSED;
518 if (do_per_step(currentStep, mdoutf_get_tng_compressed_lambda_output_interval(outf)))
520 mdof_flags |= MDOF_LAMBDA_COMPRESSED;
525 wallcycle_stop(mdoutf_get_wcycle(outf), WallCycleCounter::Traj);
528 GMX_ASSERT(localStateBackupValid_, "Trajectory writing called, but no state saved.");
530 // TODO: This is only used for CPT - needs to be filled when we turn CPT back on
531 ObservablesHistory* observablesHistory = nullptr;
533 mdoutf_write_to_trajectory_files(fplog_,
536 static_cast<int>(mdof_flags),
537 statePropagatorData_->totalNumAtoms_,
540 localStateBackup_.get(),
541 statePropagatorData_->globalState_,
543 statePropagatorData_->f_.view().force(),
544 &dummyCheckpointDataHolder_);
546 if (currentStep != lastStep_ || !isRegularSimulationEnd_)
548 localStateBackupValid_ = false;
550 wallcycle_stop(mdoutf_get_wcycle(outf), WallCycleCounter::Traj);
553 void StatePropagatorData::Element::elementSetup()
555 if (statePropagatorData_->vvResetVelocities_)
557 // MD-VV does the first velocity half-step only to calculate the constraint virial,
558 // then resets the velocities since the input is assumed to be positions and velocities
559 // at full time step. TODO: Change this to have input at half time steps.
560 statePropagatorData_->velocityBackup_ = statePropagatorData_->v_;
564 void StatePropagatorData::resetVelocities()
566 v_ = velocityBackup_;
572 * \brief Enum describing the contents StatePropagatorData::Element writes to modular checkpoint
574 * When changing the checkpoint content, add a new element just above Count, and adjust the
575 * checkpoint functionality.
577 enum class CheckpointVersion
579 Base, //!< First version of modular checkpointing
580 Count //!< Number of entries. Add new versions right above this!
582 constexpr auto c_currentVersion = CheckpointVersion(int(CheckpointVersion::Count) - 1);
585 template<CheckpointDataOperation operation>
586 void StatePropagatorData::doCheckpointData(CheckpointData<operation>* checkpointData)
588 checkpointVersion(checkpointData, "StatePropagatorData version", c_currentVersion);
589 checkpointData->scalar("numAtoms", &totalNumAtoms_);
591 if (operation == CheckpointDataOperation::Read)
593 xGlobal_.resizeWithPadding(totalNumAtoms_);
594 vGlobal_.resizeWithPadding(totalNumAtoms_);
597 checkpointData->arrayRef("positions", makeCheckpointArrayRef<operation>(xGlobal_));
598 checkpointData->arrayRef("velocities", makeCheckpointArrayRef<operation>(vGlobal_));
599 checkpointData->tensor("box", box_);
600 checkpointData->scalar("ddpCount", &ddpCount_);
601 checkpointData->scalar("ddpCountCgGl", &ddpCountCgGl_);
602 checkpointData->arrayRef("cgGl", makeCheckpointArrayRef<operation>(cgGl_));
605 void StatePropagatorData::Element::saveCheckpointState(std::optional<WriteCheckpointData> checkpointData,
608 if (DOMAINDECOMP(cr))
610 // Collect state from all ranks into global vectors
611 dd_collect_vec(cr->dd,
612 statePropagatorData_->ddpCount_,
613 statePropagatorData_->ddpCountCgGl_,
614 statePropagatorData_->cgGl_,
615 statePropagatorData_->x_,
616 statePropagatorData_->xGlobal_);
617 dd_collect_vec(cr->dd,
618 statePropagatorData_->ddpCount_,
619 statePropagatorData_->ddpCountCgGl_,
620 statePropagatorData_->cgGl_,
621 statePropagatorData_->v_,
622 statePropagatorData_->vGlobal_);
626 // Everything is local - copy local vectors into global ones
627 statePropagatorData_->xGlobal_.resizeWithPadding(statePropagatorData_->totalNumAtoms());
628 statePropagatorData_->vGlobal_.resizeWithPadding(statePropagatorData_->totalNumAtoms());
629 std::copy(statePropagatorData_->x_.begin(),
630 statePropagatorData_->x_.end(),
631 statePropagatorData_->xGlobal_.begin());
632 std::copy(statePropagatorData_->v_.begin(),
633 statePropagatorData_->v_.end(),
634 statePropagatorData_->vGlobal_.begin());
638 statePropagatorData_->doCheckpointData<CheckpointDataOperation::Write>(&checkpointData.value());
643 * \brief Update the legacy global state
645 * When restoring from checkpoint, data will be distributed during domain decomposition at setup stage.
646 * Domain decomposition still uses the legacy global t_state object so make sure it's up-to-date.
648 static void updateGlobalState(t_state* globalState,
649 const PaddedHostVector<RVec>& x,
650 const PaddedHostVector<RVec>& v,
654 const std::vector<int>& cgGl)
658 copy_mat(box, globalState->box);
659 globalState->ddp_count = ddpCount;
660 globalState->ddp_count_cg_gl = ddpCountCgGl;
661 globalState->cg_gl = cgGl;
664 void StatePropagatorData::Element::restoreCheckpointState(std::optional<ReadCheckpointData> checkpointData,
669 statePropagatorData_->doCheckpointData<CheckpointDataOperation::Read>(&checkpointData.value());
672 // Copy data to global state to be distributed by DD at setup stage
673 if (DOMAINDECOMP(cr) && MASTER(cr))
675 updateGlobalState(statePropagatorData_->globalState_,
676 statePropagatorData_->xGlobal_,
677 statePropagatorData_->vGlobal_,
678 statePropagatorData_->box_,
679 statePropagatorData_->ddpCount_,
680 statePropagatorData_->ddpCountCgGl_,
681 statePropagatorData_->cgGl_);
683 // Everything is local - copy global vectors to local ones
684 if (!DOMAINDECOMP(cr))
686 statePropagatorData_->x_.resizeWithPadding(statePropagatorData_->totalNumAtoms_);
687 statePropagatorData_->v_.resizeWithPadding(statePropagatorData_->totalNumAtoms_);
688 std::copy(statePropagatorData_->xGlobal_.begin(),
689 statePropagatorData_->xGlobal_.end(),
690 statePropagatorData_->x_.begin());
691 std::copy(statePropagatorData_->vGlobal_.begin(),
692 statePropagatorData_->vGlobal_.end(),
693 statePropagatorData_->v_.begin());
697 const std::string& StatePropagatorData::Element::clientID()
699 return StatePropagatorData::checkpointID();
702 void StatePropagatorData::Element::trajectoryWriterTeardown(gmx_mdoutf* gmx_unused outf)
704 // Note that part of this code is duplicated in do_md_trajectory_writing.
705 // This duplication is needed while both legacy and modular code paths are in use.
706 // TODO: Remove duplication asap, make sure to keep in sync in the meantime.
707 if (!writeFinalConfiguration_ || !isRegularSimulationEnd_)
712 GMX_ASSERT(localStateBackupValid_, "Final trajectory writing called, but no state saved.");
714 wallcycle_start(mdoutf_get_wcycle(outf), WallCycleCounter::Traj);
715 if (DOMAINDECOMP(cr_))
718 MASTER(cr_) ? statePropagatorData_->globalState_->x : gmx::ArrayRef<gmx::RVec>();
719 dd_collect_vec(cr_->dd,
720 localStateBackup_->ddp_count,
721 localStateBackup_->ddp_count_cg_gl,
722 localStateBackup_->cg_gl,
723 localStateBackup_->x,
726 MASTER(cr_) ? statePropagatorData_->globalState_->v : gmx::ArrayRef<gmx::RVec>();
727 dd_collect_vec(cr_->dd,
728 localStateBackup_->ddp_count,
729 localStateBackup_->ddp_count_cg_gl,
730 localStateBackup_->cg_gl,
731 localStateBackup_->v,
736 // We have the whole state locally: copy the local state pointer
737 statePropagatorData_->globalState_ = localStateBackup_.get();
742 fprintf(stderr, "\nWriting final coordinates.\n");
743 if (canMoleculesBeDistributedOverPBC_ && !systemHasPeriodicMolecules_)
745 // Make molecules whole only for confout writing
746 do_pbc_mtop(pbcType_,
747 localStateBackup_->box,
749 statePropagatorData_->globalState_->x.rvec_array());
751 write_sto_conf_mtop(finalConfigurationFilename_.c_str(),
754 statePropagatorData_->globalState_->x.rvec_array(),
755 statePropagatorData_->globalState_->v.rvec_array(),
757 localStateBackup_->box);
759 wallcycle_stop(mdoutf_get_wcycle(outf), WallCycleCounter::Traj);
762 std::optional<SignallerCallback> StatePropagatorData::Element::registerLastStepCallback()
764 return [this](Step step, Time /*time*/) {
766 isRegularSimulationEnd_ = (step == lastPlannedStep_);
770 StatePropagatorData::Element::Element(StatePropagatorData* statePropagatorData,
776 int nstxout_compressed,
777 bool canMoleculesBeDistributedOverPBC,
778 bool writeFinalConfiguration,
779 std::string finalConfigurationFilename,
780 const t_inputrec* inputrec,
781 const gmx_mtop_t& globalTop) :
782 statePropagatorData_(statePropagatorData),
786 nstxout_compressed_(nstxout_compressed),
787 localStateBackup_(std::make_unique<t_state>()),
789 freeEnergyPerturbationData_(nullptr),
790 isRegularSimulationEnd_(false),
792 canMoleculesBeDistributedOverPBC_(canMoleculesBeDistributedOverPBC),
793 systemHasPeriodicMolecules_(inputrec->bPeriodicMols),
794 pbcType_(inputrec->pbcType),
795 lastPlannedStep_(inputrec->nsteps + inputrec->init_step),
796 writeFinalConfiguration_(writeFinalConfiguration),
797 finalConfigurationFilename_(std::move(finalConfigurationFilename)),
800 top_global_(globalTop)
803 void StatePropagatorData::Element::setFreeEnergyPerturbationData(FreeEnergyPerturbationData* freeEnergyPerturbationData)
805 freeEnergyPerturbationData_ = freeEnergyPerturbationData;
808 ISimulatorElement* StatePropagatorData::Element::getElementPointerImpl(
809 LegacySimulatorData gmx_unused* legacySimulatorData,
810 ModularSimulatorAlgorithmBuilderHelper gmx_unused* builderHelper,
811 StatePropagatorData* statePropagatorData,
812 EnergyData gmx_unused* energyData,
813 FreeEnergyPerturbationData* freeEnergyPerturbationData,
814 GlobalCommunicationHelper gmx_unused* globalCommunicationHelper,
815 ObservablesReducer* /*observablesReducer*/)
817 statePropagatorData->element()->setFreeEnergyPerturbationData(freeEnergyPerturbationData);
818 return statePropagatorData->element();
821 void StatePropagatorData::readCheckpointToTrxFrame(t_trxframe* trxFrame, ReadCheckpointData readCheckpointData)
823 StatePropagatorData statePropagatorData;
824 statePropagatorData.doCheckpointData(&readCheckpointData);
826 trxFrame->natoms = statePropagatorData.totalNumAtoms_;
828 trxFrame->x = makeRvecArray(statePropagatorData.xGlobal_, statePropagatorData.totalNumAtoms_);
830 trxFrame->v = makeRvecArray(statePropagatorData.vGlobal_, statePropagatorData.totalNumAtoms_);
831 trxFrame->bF = false;
832 trxFrame->bBox = true;
833 copy_mat(statePropagatorData.box_, trxFrame->box);
836 const std::string& StatePropagatorData::checkpointID()
838 static const std::string identifier = "StatePropagatorData";