Add force correlation to AWH module
[gromacs.git] / src / gromacs / awh / correlationhistory.cpp
blob2ff55aa097ae39ece3f68ac50e555b8ab9306aa0
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2015,2016,2017, 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 /*! \internal \file
38 * \brief
39 * Implements helper functions for checkpointing the AWH state and observables history.
41 * \author Viveca Lindahl
42 * \author Berk Hess <hess@kth.se>
43 * \ingroup module_awh
46 #include "gmxpre.h"
48 #include "correlationhistory.h"
50 #include <assert.h>
52 #include "gromacs/gmxlib/network.h"
53 #include "gromacs/mdtypes/awh-correlation-history.h"
54 #include "gromacs/mdtypes/commrec.h"
55 #include "gromacs/utility/arrayref.h"
56 #include "gromacs/utility/exceptions.h"
57 #include "gromacs/utility/gmxassert.h"
59 #include "correlationgrid.h"
61 namespace gmx
64 void initCorrelationGridHistory(CorrelationGridHistory *correlationGridHistory,
65 int numCorrelationTensors,
66 int tensorSize,
67 int blockDataListSize)
69 correlationGridHistory->numCorrelationTensors = numCorrelationTensors;
70 correlationGridHistory->tensorSize = tensorSize;
71 correlationGridHistory->blockDataListSize = blockDataListSize;
73 correlationGridHistory->blockDataBuffer.resize(numCorrelationTensors*tensorSize*blockDataListSize);
76 CorrelationGridHistory initCorrelationGridHistoryFromState(const CorrelationGrid &correlationGrid)
78 CorrelationGridHistory correlationGridHistory;
80 initCorrelationGridHistory(&correlationGridHistory, correlationGrid.tensors().size(), correlationGrid.tensorSize(), correlationGrid.blockDataListSize());
82 return correlationGridHistory;
85 /* Update the correlation grid history for checkpointing. */
86 void updateCorrelationGridHistory(CorrelationGridHistory *correlationGridHistory,
87 const CorrelationGrid &correlationGrid)
89 GMX_RELEASE_ASSERT(correlationGridHistory != nullptr, "We need a valid history object");
91 gmx::ArrayRef<CorrelationBlockDataHistory> blockDataBuffer = correlationGridHistory->blockDataBuffer;
93 /* Store the grid in a linear array */
94 size_t bufferIndex = 0;
95 for (const CorrelationTensor &tensor : correlationGrid.tensors())
97 const int numDims = tensor.blockDataList()[0].coordData().size();
98 const int tensorSize = tensor.blockDataList()[0].correlationIntegral().size();
100 /* Loop of the tensor elements, ignore the symmetric data */
101 int d1 = 0;
102 int d2 = 0;
103 for (int k = 0; k < tensorSize; k++)
105 /* BlockData for each correlation element */
106 for (const CorrelationBlockData &blockData : tensor.blockDataList())
108 const CorrelationBlockData::CoordData &cx = blockData.coordData()[d1];
109 const CorrelationBlockData::CoordData &cy = blockData.coordData()[d2];
111 CorrelationBlockDataHistory &bdh = blockDataBuffer[bufferIndex];
113 bdh.blockSumWeight = blockData.blockSumWeight();
114 bdh.blockSumSquareWeight = blockData.blockSumSquareWeight();
115 bdh.blockSumWeightX = cx.blockSumWeightX;
116 bdh.blockSumWeightY = cy.blockSumWeightX;
117 bdh.sumOverBlocksSquareBlockWeight = blockData.sumOverBlocksSquareBlockWeight();
118 bdh.sumOverBlocksBlockSquareWeight = blockData.sumOverBlocksBlockSquareWeight();
119 bdh.sumOverBlocksBlockWeightBlockWeightX = cx.sumOverBlocksBlockWeightBlockWeightX;
120 bdh.sumOverBlocksBlockWeightBlockWeightY = cy.sumOverBlocksBlockWeightBlockWeightX;
121 bdh.previousBlockIndex = blockData.previousBlockIndex();
122 bdh.blockLength = blockData.blockLength();
123 bdh.correlationIntegral = blockData.correlationIntegral()[k];
125 bufferIndex++;
128 d1++;
129 if (d1 == numDims)
131 d1 = 0;
132 d2++;
137 GMX_RELEASE_ASSERT(bufferIndex == blockDataBuffer.size(), "We should store exactly as many elements as the buffer size");
140 void CorrelationBlockData::restoreFromHistory(const CorrelationBlockDataHistory &blockHistory,
141 const std::vector<CorrelationBlockData::CoordData> &coordData,
142 const std::vector<double> &correlationIntegral)
144 blockSumWeight_ = blockHistory.blockSumWeight;
145 blockSumSquareWeight_ = blockHistory.blockSumSquareWeight;
146 sumOverBlocksSquareBlockWeight_ = blockHistory.sumOverBlocksSquareBlockWeight;
147 sumOverBlocksBlockSquareWeight_ = blockHistory.sumOverBlocksBlockSquareWeight;
148 previousBlockIndex_ = blockHistory.previousBlockIndex;
149 blockLength_ = blockHistory.blockLength;
150 coordData_ = coordData;
151 correlationIntegral_ = correlationIntegral;
154 /* Restore a correlation element from history. */
155 void CorrelationTensor::restoreFromHistory(const std::vector<CorrelationBlockDataHistory> &blockDataBuffer,
156 size_t *bufferIndex)
158 /* Blockdata for each correlation element */
159 for (CorrelationBlockData &blockData : blockDataList_)
161 /* Correlation elements for each tensor */
162 const int numDims = blockDataList_[0].coordData().size();
163 const int tensorSize = blockDataList_[0].correlationIntegral().size();
164 int d1 = 0;
165 int d2 = 0;
167 /* Temporary containers to collect data */
168 std::vector<CorrelationBlockData::CoordData> coordData(numDims);
169 std::vector<double> correlationIntegral(tensorSize);
170 for (int k = 0; k < tensorSize; k++)
172 if (*bufferIndex >= blockDataBuffer.size())
174 GMX_THROW(InvalidInputError("Mismatch of the correlation tensor size for the force correlation between checkpoint and simulation. Likely you have provided a checkpoint from a different simulation."));
176 const CorrelationBlockDataHistory &blockHistory = blockDataBuffer[*bufferIndex];
178 /* To simplify the checkpointing, CorrelationBlockDataHistory
179 * duplicates some weight data for all tensor elements.
180 * Here we collect the coordinate and tensor data
181 * in temporary buffers.
183 coordData[d1].blockSumWeightX = blockHistory.blockSumWeightX;
184 coordData[d2].blockSumWeightX = blockHistory.blockSumWeightY;
185 coordData[d1].sumOverBlocksBlockWeightBlockWeightX = blockHistory.sumOverBlocksBlockWeightBlockWeightX;
186 coordData[d2].sumOverBlocksBlockWeightBlockWeightX = blockHistory.sumOverBlocksBlockWeightBlockWeightY;
188 correlationIntegral[k] = blockHistory.correlationIntegral;
190 /* Check if we collected all data needed for blockData */
191 if (k == tensorSize - 1)
193 blockData.restoreFromHistory(blockHistory, coordData, correlationIntegral);
196 (*bufferIndex)++;
198 d1++;
199 if (d1 == numDims)
201 d1 = 0;
202 d2++;
208 /* Restores the correlation grid state from the correlation grid history. */
209 void CorrelationGrid::restoreStateFromHistory(const CorrelationGridHistory &correlationGridHistory)
211 if (tensors_.size() != static_cast<size_t>(correlationGridHistory.numCorrelationTensors))
213 GMX_THROW(InvalidInputError("Mismatch of the grid size for the force correlation between checkpoint and simulation. Likely you have provided a checkpoint from a different simulation."));
216 /* Extract the state from the linear history array */
217 size_t bufferIndex = 0;
218 for (CorrelationTensor &tensor : tensors_)
220 tensor.restoreFromHistory(correlationGridHistory.blockDataBuffer,
221 &bufferIndex);
224 if (bufferIndex != correlationGridHistory.blockDataBuffer.size())
226 GMX_THROW(InvalidInputError("Mismatch of the correlation tensor size for the force correlation between checkpoint and simulation. Likely you have provided a checkpoint from a different simulation."));
230 } // namespace gmx