edb67b5e51bc72a8d62e9ede3b71739c2c576b5a
[alexxy/gromacs.git] / src / gromacs / applied_forces / awh / tests / awh_setup.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2017,2018,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.
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 #include "gmxpre.h"
36
37 #include "awh_setup.h"
38
39 #include <cmath>
40
41 #include <memory>
42 #include <tuple>
43 #include <vector>
44
45 #include <gmock/gmock.h>
46 #include <gmock/gmock-matchers.h>
47 #include <gtest/gtest.h>
48
49 #include "gromacs/applied_forces/awh/bias.h"
50 #include "gromacs/applied_forces/awh/correlationgrid.h"
51 #include "gromacs/applied_forces/awh/pointstate.h"
52 #include "gromacs/mdtypes/awh_params.h"
53 #include "gromacs/utility/arrayref.h"
54 #include "gromacs/utility/inmemoryserializer.h"
55 #include "gromacs/utility/stringutil.h"
56
57 #include "testutils/refdata.h"
58 #include "testutils/testasserts.h"
59
60 namespace gmx
61 {
62
63 namespace test
64 {
65
66 using ::testing::Eq;
67 using ::testing::Pointwise;
68
69 std::vector<char> awhDimParamSerialized(AwhCoordinateProviderType inputCoordinateProvider,
70                                         int                       inputCoordIndex,
71                                         double                    inputOrigin,
72                                         double                    inputEnd,
73                                         double                    inputPeriod,
74                                         double                    inputDiffusion)
75 {
76     AwhCoordinateProviderType eCoordProvider = inputCoordinateProvider;
77     int                       coordIndex     = inputCoordIndex;
78     double                    forceConstant  = 10;
79     double                    period         = inputPeriod;
80     double                    diffusion      = inputDiffusion;
81     double                    origin         = inputOrigin;
82     double                    end            = inputEnd;
83     double                    coordValueInit = inputOrigin;
84     double                    coverDiameter  = 0;
85
86     gmx::InMemorySerializer serializer;
87     serializer.doEnumAsInt(&eCoordProvider);
88     serializer.doInt(&coordIndex);
89     serializer.doDouble(&origin);
90     serializer.doDouble(&end);
91     serializer.doDouble(&period);
92     serializer.doDouble(&forceConstant);
93     serializer.doDouble(&diffusion);
94     serializer.doDouble(&coordValueInit);
95     serializer.doDouble(&coverDiameter);
96     return serializer.finishAndGetBuffer();
97 }
98
99 /*! \internal \brief
100  * Prepare a memory buffer with serialized AwhBiasParams.
101  *
102  * \param[in] eawhgrowth Way to grow potential.
103  * \param[in] beta Value for 1/(kB*T).
104  * \param[in] inputErrorScaling Factor for initial error scaling.
105  * \param[in] dimensionParameterBuffers Buffers containing the dimension parameters.
106  * \param[in] inputUserData If there is a user provided PMF estimate.
107  */
108 static std::vector<char> awhBiasParamSerialized(AwhHistogramGrowthType            eawhgrowth,
109                                                 double                            beta,
110                                                 double                            inputErrorScaling,
111                                                 ArrayRef<const std::vector<char>> dimensionParameterBuffers,
112                                                 bool                              inputUserData)
113 {
114     int                    ndim                 = dimensionParameterBuffers.size();
115     AwhTargetType          eTarget              = AwhTargetType::Constant;
116     double                 targetBetaScaling    = 0;
117     double                 targetCutoff         = 0;
118     AwhHistogramGrowthType eGrowth              = eawhgrowth;
119     bool                   bUserData            = inputUserData;
120     double                 errorInitial         = inputErrorScaling / beta;
121     int                    shareGroup           = 0;
122     bool                   equilibrateHistogram = false;
123
124     gmx::InMemorySerializer serializer;
125     serializer.doEnumAsInt(&eTarget);
126     serializer.doDouble(&targetBetaScaling);
127     serializer.doDouble(&targetCutoff);
128     serializer.doEnumAsInt(&eGrowth);
129     int temp = static_cast<int>(bUserData);
130     serializer.doInt(&temp);
131     serializer.doDouble(&errorInitial);
132     serializer.doInt(&ndim);
133     serializer.doInt(&shareGroup);
134     serializer.doBool(&equilibrateHistogram);
135
136     auto awhDimBuffer  = awhDimParamSerialized();
137     auto awhBiasBuffer = serializer.finishAndGetBuffer();
138     for (const auto& dimParamBuffer : dimensionParameterBuffers)
139     {
140         awhBiasBuffer.insert(awhBiasBuffer.end(), dimParamBuffer.begin(), dimParamBuffer.end());
141     }
142     return awhBiasBuffer;
143 }
144
145 /*! \internal \brief
146  * Prepare a memory buffer with serialized AwhParams.
147  *
148  * \param[in] eawhgrowth Way to grow potential.
149  * \param[in] eawhpotential Which potential to use.
150  * \param[in] beta Value for 1/(kB*T).
151  * \param[in] inputErrorScaling Factor for initial error scaling.
152  * \param[in] inputSeed Seed value to use.
153  * \param[in] dimensionParameterBuffers Buffers containing the dimension parameters.
154  * \param[in] inputUserData If there is a user provided PMF estimate.
155  */
156 static std::vector<char> awhParamSerialized(AwhHistogramGrowthType            eawhgrowth,
157                                             AwhPotentialType                  eawhpotential,
158                                             double                            beta,
159                                             double                            inputErrorScaling,
160                                             int64_t                           inputSeed,
161                                             ArrayRef<const std::vector<char>> dimensionParameterBuffers,
162                                             bool                              inputUserData)
163 {
164     int              numBias                    = 1;
165     int64_t          seed                       = inputSeed;
166     int              nstOut                     = 0;
167     int              nstSampleCoord             = 1;
168     int              numSamplesUpdateFreeEnergy = 10;
169     AwhPotentialType ePotential                 = eawhpotential;
170     bool             shareBiasMultisim          = false;
171
172     gmx::InMemorySerializer serializer;
173     serializer.doInt(&numBias);
174     serializer.doInt(&nstOut);
175     serializer.doInt64(&seed);
176     serializer.doInt(&nstSampleCoord);
177     serializer.doInt(&numSamplesUpdateFreeEnergy);
178     serializer.doEnumAsInt(&ePotential);
179     serializer.doBool(&shareBiasMultisim);
180
181     auto awhParamBuffer = serializer.finishAndGetBuffer();
182     auto awhBiasBuffer  = awhBiasParamSerialized(
183             eawhgrowth, beta, inputErrorScaling, dimensionParameterBuffers, inputUserData);
184
185     awhParamBuffer.insert(awhParamBuffer.end(), awhBiasBuffer.begin(), awhBiasBuffer.end());
186
187     return awhParamBuffer;
188 }
189
190 AwhTestParameters::AwhTestParameters(ISerializer* serializer) : awhParams(serializer) {}
191 /*! \brief
192  * Helper function to set up the C-style AWH parameters for the test.
193  *
194  * Builds the test input data from serialized data.
195  */
196 AwhTestParameters getAwhTestParameters(AwhHistogramGrowthType            eawhgrowth,
197                                        AwhPotentialType                  eawhpotential,
198                                        ArrayRef<const std::vector<char>> dimensionParameterBuffers,
199                                        bool                              inputUserData,
200                                        double                            beta,
201                                        bool                              useAwhFep,
202                                        double                            inputErrorScaling,
203                                        int                               numFepLambdaStates)
204 {
205     double  convFactor = 1;
206     double  k          = 1000;
207     int64_t seed       = 93471803;
208
209     auto awhParamBuffer = awhParamSerialized(
210             eawhgrowth, eawhpotential, beta, inputErrorScaling, seed, dimensionParameterBuffers, inputUserData);
211     gmx::InMemoryDeserializer deserializer(awhParamBuffer, false);
212     AwhTestParameters         params(&deserializer);
213
214     params.beta = beta;
215
216     if (useAwhFep)
217     {
218         params.dimParams.emplace_back(DimParams::fepLambdaDimParams(numFepLambdaStates, params.beta));
219     }
220     else
221     {
222         params.dimParams.emplace_back(DimParams::pullDimParams(convFactor, k, params.beta));
223     }
224     return params;
225 }
226
227 TEST(SerializationTest, CanSerializeDimParams)
228 {
229     auto                      awhDimBuffer = awhDimParamSerialized();
230     gmx::InMemoryDeserializer deserializer(awhDimBuffer, false);
231     AwhDimParams              awhDimParams(&deserializer);
232     EXPECT_EQ(awhDimParams.coordinateProvider(), AwhCoordinateProviderType::Pull);
233     EXPECT_EQ(awhDimParams.coordinateIndex(), 0);
234     EXPECT_FLOAT_EQ(awhDimParams.forceConstant(), 10);
235     EXPECT_FLOAT_EQ(awhDimParams.period(), 0);
236     EXPECT_FLOAT_EQ(awhDimParams.diffusion(), 0.34690997);
237     EXPECT_FLOAT_EQ(awhDimParams.origin(), 0.5);
238     EXPECT_FLOAT_EQ(awhDimParams.end(), 1.5);
239     EXPECT_FLOAT_EQ(awhDimParams.initialCoordinate(), awhDimParams.origin());
240     EXPECT_FLOAT_EQ(awhDimParams.coverDiameter(), 0);
241
242     gmx::InMemorySerializer serializer;
243     awhDimParams.serialize(&serializer);
244     EXPECT_THAT(awhDimBuffer, Pointwise(Eq(), serializer.finishAndGetBuffer()));
245 }
246
247 TEST(SerializationTest, CanSerializeBiasParams)
248 {
249     auto awhDimBuffer   = awhDimParamSerialized();
250     auto awhDimArrayRef = gmx::arrayRefFromArray(&awhDimBuffer, 1);
251     auto awhBiasBuffer  = awhBiasParamSerialized(
252             AwhHistogramGrowthType::ExponentialLinear, 0.4, 0.5, awhDimArrayRef, false);
253     gmx::InMemoryDeserializer deserializer(awhBiasBuffer, false);
254     AwhBiasParams             awhBiasParams(&deserializer);
255     EXPECT_EQ(awhBiasParams.ndim(), 1);
256     EXPECT_EQ(awhBiasParams.targetDistribution(), AwhTargetType::Constant);
257     EXPECT_FLOAT_EQ(awhBiasParams.targetBetaScaling(), 0);
258     EXPECT_FLOAT_EQ(awhBiasParams.targetCutoff(), 0);
259     EXPECT_EQ(awhBiasParams.growthType(), AwhHistogramGrowthType::ExponentialLinear);
260     EXPECT_EQ(awhBiasParams.userPMFEstimate(), 0);
261     EXPECT_FLOAT_EQ(awhBiasParams.initialErrorEstimate(), 0.5 / 0.4);
262     EXPECT_EQ(awhBiasParams.shareGroup(), 0);
263     EXPECT_EQ(awhBiasParams.equilibrateHistogram(), false);
264     const auto& awhDimParams = awhBiasParams.dimParams()[0];
265     EXPECT_EQ(awhDimParams.coordinateProvider(), AwhCoordinateProviderType::Pull);
266     EXPECT_EQ(awhDimParams.coordinateIndex(), 0);
267     EXPECT_FLOAT_EQ(awhDimParams.forceConstant(), 10);
268     EXPECT_FLOAT_EQ(awhDimParams.period(), 0);
269     EXPECT_FLOAT_EQ(awhDimParams.diffusion(), 0.34690997);
270     EXPECT_FLOAT_EQ(awhDimParams.origin(), 0.5);
271     EXPECT_FLOAT_EQ(awhDimParams.end(), 1.5);
272     EXPECT_FLOAT_EQ(awhDimParams.initialCoordinate(), awhDimParams.origin());
273     EXPECT_FLOAT_EQ(awhDimParams.coverDiameter(), 0);
274
275     gmx::InMemorySerializer serializer;
276     awhBiasParams.serialize(&serializer);
277     EXPECT_THAT(awhBiasBuffer, Pointwise(Eq(), serializer.finishAndGetBuffer()));
278 }
279
280 TEST(SerializationTest, CanSerializeAwhParams)
281 {
282     auto awhDimBuffer   = awhDimParamSerialized();
283     auto awhDimArrayRef = gmx::arrayRefFromArray(&awhDimBuffer, 1);
284     auto awhParamBuffer = awhParamSerialized(
285             AwhHistogramGrowthType::ExponentialLinear, AwhPotentialType::Convolved, 0.4, 0.5, 1337, awhDimArrayRef, false);
286     gmx::InMemoryDeserializer deserializer(awhParamBuffer, false);
287     AwhParams                 awhParams(&deserializer);
288     EXPECT_EQ(awhParams.numBias(), 1);
289     EXPECT_EQ(awhParams.seed(), 1337);
290     EXPECT_EQ(awhParams.nstout(), 0);
291     EXPECT_EQ(awhParams.nstSampleCoord(), 1);
292     EXPECT_EQ(awhParams.numSamplesUpdateFreeEnergy(), 10);
293     EXPECT_EQ(awhParams.potential(), AwhPotentialType::Convolved);
294     EXPECT_EQ(awhParams.shareBiasMultisim(), false);
295     const auto& awhBiasParams = awhParams.awhBiasParams()[0];
296     EXPECT_EQ(awhBiasParams.ndim(), 1);
297     EXPECT_EQ(awhBiasParams.targetDistribution(), AwhTargetType::Constant);
298     EXPECT_FLOAT_EQ(awhBiasParams.targetBetaScaling(), 0);
299     EXPECT_FLOAT_EQ(awhBiasParams.targetCutoff(), 0);
300     EXPECT_EQ(awhBiasParams.growthType(), AwhHistogramGrowthType::ExponentialLinear);
301     EXPECT_EQ(awhBiasParams.userPMFEstimate(), 0);
302     EXPECT_FLOAT_EQ(awhBiasParams.initialErrorEstimate(), 0.5 / 0.4);
303     EXPECT_EQ(awhBiasParams.shareGroup(), 0);
304     EXPECT_EQ(awhBiasParams.equilibrateHistogram(), false);
305     const auto& awhDimParams = awhBiasParams.dimParams()[0];
306     EXPECT_EQ(awhDimParams.coordinateProvider(), AwhCoordinateProviderType::Pull);
307     EXPECT_EQ(awhDimParams.coordinateIndex(), 0);
308     EXPECT_FLOAT_EQ(awhDimParams.forceConstant(), 10);
309     EXPECT_FLOAT_EQ(awhDimParams.period(), 0);
310     EXPECT_FLOAT_EQ(awhDimParams.diffusion(), 0.34690997);
311     EXPECT_FLOAT_EQ(awhDimParams.origin(), 0.5);
312     EXPECT_FLOAT_EQ(awhDimParams.end(), 1.5);
313     EXPECT_FLOAT_EQ(awhDimParams.initialCoordinate(), awhDimParams.origin());
314     EXPECT_FLOAT_EQ(awhDimParams.coverDiameter(), 0);
315
316     gmx::InMemorySerializer serializer;
317     awhParams.serialize(&serializer);
318     EXPECT_THAT(awhParamBuffer, Pointwise(Eq(), serializer.finishAndGetBuffer()));
319 }
320
321 } // namespace test
322 } // namespace gmx