2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2015,2016,2017,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.
39 * This file contains datatypes and function declarations necessary
40 * for AWH to interface with the grid code.
42 * The grid organizes spatial properties of the AWH coordinate points.
43 * This includes traversing points in a specific order, locating
44 * neighboring points and calculating distances. Multiple dimensions
45 * as well as periodic dimensions are supported.
47 * \todo: Replace this by a more generic grid class once that is available.
49 * \author Viveca Lindahl
50 * \author Berk Hess <hess@kth.se>
54 #ifndef GMX_AWH_BIASGRID_H
55 #define GMX_AWH_BIASGRID_H
61 #include "gromacs/utility/arrayref.h"
63 #include "dimparams.h" /* This is needed for awh_dvec */
71 * \brief An axis, i.e. dimension, of the grid.
76 /*! \brief Constructor.
78 * The spacing and number of points are set such that we have
79 * at least the requested point density.
80 * Requesting 0 point density results in the minimum number
83 * \param[in] origin Starting value.
84 * \param[in] end End value.
85 * \param[in] period Period, pass 0 if not periodic.
86 * \param[in] pointDensity Requested number of point per unit of axis length.
88 GridAxis(double origin, double end, double period, double pointDensity);
90 /*! \brief Constructor.
92 * \param[in] origin Starting value.
93 * \param[in] end End value.
94 * \param[in] period Period, pass 0 if not periodic.
95 * \param[in] numPoints The number of points.
96 * \param[in] isFepLambdaAxis If this axis is controlling lambda.
98 GridAxis(double origin, double end, double period, int numPoints, bool isFepLambdaAxis);
100 /*! \brief Returns whether the axis has periodic boundaries.
102 bool isPeriodic() const { return period_ > 0; }
104 /*! \brief Returns the period of the grid along the axis.
106 double period() const { return period_; }
108 /*! \brief Returns the grid origin along the axis.
110 double origin() const { return origin_; }
112 /*! \brief Returns the grid point spacing along the axis.
114 double spacing() const { return spacing_; }
116 /*! \brief Returns the number of grid points along the axis.
118 int numPoints() const { return numPoints_; }
120 /*! \brief Returns the period of the grid in points along the axis.
122 * Returns 0 if the axis is not periodic.
124 int numPointsInPeriod() const { return numPointsInPeriod_; }
126 /*! \brief Returns the length of the interval.
128 * This returns the distance obtained by connecting the origin point to
129 * the end point in the positive direction. Note that this is generally
130 * not the shortest distance. For period > 0, both origin and
131 * end are expected to take values in the same periodic interval.
133 double length() const { return length_; }
135 /*! \brief Map a value to the nearest point index along an axis.
137 * \param[in] value Value along the axis.
138 * \returns the index nearest to the value.
140 int nearestIndex(double value) const;
142 /*! \brief Returns whether this axis is coupled to the free energy lambda state.
144 bool isFepLambdaAxis() const { return isFepLambdaAxis_; }
147 double origin_; /**< Interval start value */
148 double length_; /**< Interval length */
149 double period_; /**< The period, 0 if not periodic */
150 double spacing_; /**< Point spacing */
151 int numPoints_; /**< Number of points in the interval */
152 int numPointsInPeriod_; /**< Number of points in a period (0 if no periodicity) */
153 bool isFepLambdaAxis_; /**< If this axis is coupled to the system's free energy lambda state */
157 * \brief A point in the grid.
159 * A grid point has a coordinate value and a coordinate index of the same dimensionality as the
160 * grid. It knows the linear indices of its neighboring point (which are useful only when handed up
165 awh_dvec coordValue; /**< Multidimensional coordinate value of this point */
166 awh_ivec index; /**< Multidimensional point indices */
167 std::vector<int> neighbor; /**< Linear point indices of the neighboring points */
171 * \brief The grid for a single bias, generally multidimensional and periodic.
173 * The grid discretizes a multidimensional space with some given resolution.
174 * Each dimension is represented by an axis which sets the spatial extent,
175 * point spacing and periodicity of the grid in that direction.
180 /*! \brief Initializes the grid points.
186 * The point density per sigma of the Gaussian distribution in an umbrella.
188 * This value should be at least 1 to uniformly cover the reaction coordinate
189 * range with density and having it larger than 1 does not add information.
191 static constexpr double c_numPointsPerSigma = 1.0;
193 //! Cut-off in sigma for considering points, neglects 4e-8 of the density.
194 static constexpr double c_scopeCutoff = 5.5;
196 /*! \brief Construct a grid using AWH input parameters.
198 * \param[in] dimParams Dimension parameters including the expected inverse variance of the
199 * coordinate living on the grid (determines the grid spacing).
200 * \param[in] awhDimParams Dimension params from inputrec.
202 BiasGrid(ArrayRef<const DimParams> dimParams, const AwhDimParams* awhDimParams);
204 /*! \brief Returns the number of points in the grid.
206 * \returns the number of points in the grid.
208 size_t numPoints() const { return point_.size(); }
210 /*! \brief Returns a reference to a point on the grid.
212 * \returns a constant reference to a point on the grid.
214 const GridPoint& point(size_t pointIndex) const { return point_[pointIndex]; }
216 /*! \brief Returns the dimensionality of the grid.
218 * \returns the dimensionality of the grid.
220 int numDimensions() const { return axis_.size(); }
222 /*! \brief Returns the grid axes.
224 * \returns a constant reference to the grid axes.
226 ArrayRef<const GridAxis> axis() const { return axis_; }
228 /*! \brief Returns a grid axis.
230 * param[in] dim Dimension to return the grid axis for.
231 * \returns a constant reference to the grid axis.
233 const GridAxis& axis(int dim) const { return axis_[dim]; }
235 /*! \brief Find the grid point with value nearest to the given value.
237 * \param[in] value Value vector.
238 * \returns the grid point index.
240 int nearestIndex(const awh_dvec value) const;
242 /*! \brief Query if the value is in the grid.
244 * \param[in] value Value vector.
245 * \returns true if the value is in the grid.
246 * \note It is assumed that any periodicity of value has already been taken care of.
248 bool covers(const awh_dvec value) const;
250 /*! \brief Returns true if the grid has a free energy lambda state axis at all.
252 bool hasLambdaAxis() const
254 return std::any_of(std::begin(axis_), std::end(axis_), [](const auto& axis) {
255 return axis.isFepLambdaAxis();
260 * Returns the index of a free energy lambda state axis (there can be
261 * no more than one) if there is one.
263 std::optional<int> lambdaAxisIndex() const;
266 * Returns the number of free energy lambda states in the grid (the number
267 * of points along a free energy lambda state axis) or 0 if there are no free energy
270 int numFepLambdaStates() const;
273 std::vector<GridPoint> point_; /**< Points on the grid */
274 std::vector<GridAxis> axis_; /**< Axes, one for each dimension. */
279 /*! \brief Convert a multidimensional grid point index to a linear one.
281 * \param[in] grid The grid.
282 * \param[in] indexMulti Multidimensional grid point index to convert to a linear one.
283 * \returns the linear index.
285 int multiDimGridIndexToLinear(const BiasGrid& grid, const awh_ivec indexMulti);
287 /*! \brief Convert multidimensional array index to a linear one.
289 * \param[in] indexMulti Multidimensional index to convert to a linear one.
290 * \param[in] numDim Number of dimensions of the array.
291 * \param[in] numPointsDim Number of points of the array.
292 * \returns the linear index.
293 * \note This function can be used without having an initialized grid.
295 int multiDimArrayIndexToLinear(const awh_ivec indexMulti, int numDim, const awh_ivec numPointsDim);
297 /*! \brief Convert a linear grid point index to a multidimensional one.
299 * \param[in] grid The grid.
300 * \param[in] indexLinear Linear grid point index to convert to a multidimensional one.
301 * \param[out] indexMulti The multidimensional index.
303 void linearGridindexToMultiDim(const BiasGrid& grid, int indexLinear, awh_ivec indexMulti);
305 /*! \brief Convert a linear array index to a multidimensional one.
307 * \param[in] indexLinear Linear array index
308 * \param[in] ndim Number of dimensions of the array.
309 * \param[in] numPointsDim Number of points for each dimension.
310 * \param[out] indexMulti The multidimensional index.
312 void linearArrayIndexToMultiDim(int indexLinear, int ndim, const awh_ivec numPointsDim, awh_ivec indexMulti);
315 * Find the next grid point in the sub-part of the grid given a starting point.
317 * The given grid point index is updated to the next valid grid point index
318 * by traversing the sub-part of the grid, here termed the subgrid.
319 * Since the subgrid range might extend beyond the actual size of the grid,
320 * the subgrid is traversed until a point both in the subgrid and grid is
321 * found. If no point is found, the function returns false and the index is
322 * not modified. The starting point needs to be inside of the subgrid. However,
323 * if this index is not given, meaning < 0, then the search is initialized at
324 * the subgrid origin, i.e. in this case the "next" grid point index is
325 * defined to be the first common grid/subgrid point.
327 * \param[in] grid The grid.
328 * \param[in] subgridOrigin Vector locating the subgrid origin relative to the grid origin.
329 * \param[in] subgridNpoints Number of points along each subgrid dimension.
330 * \param[in,out] gridPointIndex Pointer to the starting/next grid point index.
331 * \returns true if the grid point was updated.
333 bool advancePointInSubgrid(const BiasGrid& grid,
334 const awh_ivec subgridOrigin,
335 const awh_ivec subgridNpoints,
336 int* gridPointIndex);
338 /*! \brief Maps each point in the grid to a point in the data grid.
340 * This functions maps an AWH bias grid to a user provided input data grid.
341 * The value of data grid point i along dimension d is given by data[d][i].
342 * The number of dimensions of the data should equal that of the grid.
343 * A fatal error is thrown if extracting the data fails or the data does not cover the whole grid.
345 * \param[out] gridpointToDatapoint Array mapping each grid point to a data point index.
346 * \param[in] data 2D array in format ndim x ndatapoints with data grid point values.
347 * \param[in] numDataPoints Number of data points.
348 * \param[in] dataFilename The data filename.
349 * \param[in] grid The grid.
350 * \param[in] correctFormatMessage String to include in error message if extracting the data fails.
352 void mapGridToDataGrid(std::vector<int>* gridpointToDatapoint,
353 const double* const* data,
355 const std::string& dataFilename,
356 const BiasGrid& grid,
357 const std::string& correctFormatMessage);
360 * Get the deviation along one dimension from the given value to a point in the grid.
362 * \param[in] grid The grid.
363 * \param[in] dimIndex Dimensional index in [0, ndim -1].
364 * \param[in] pointIndex BiasGrid point index.
365 * \param[in] value Value along the given dimension.
366 * \returns the deviation of the given value to the given point.
368 double getDeviationFromPointAlongGridAxis(const BiasGrid& grid, int dimIndex, int pointIndex, double value);
371 * Get the deviation from one point to another along one dimension in the grid.
373 * \param[in] grid The grid.
374 * \param[in] dimIndex Dimensional index in [0, ndim -1].
375 * \param[in] pointIndex1 Grid point index of the first point.
376 * \param[in] pointIndex2 Grid point index of the second point.
377 * \returns the deviation of the two points along the given axis.
379 double getDeviationFromPointAlongGridAxis(const BiasGrid& grid, int dimIndex, int pointIndex1, int pointIndex2);
382 * Checks whether two points are along a free energy lambda state axis.
384 * \param[in] grid The grid.
385 * \param[in] pointIndex1 Grid point index of the first point.
386 * \param[in] pointIndex2 Grid point index of the second point.
387 * \returns true if the two points are along a free energy lambda state axis.
389 bool pointsAlongLambdaAxis(const BiasGrid& grid, int pointIndex1, int pointIndex2);
392 * Checks whether two points are different in the free energy lambda state
393 * dimension (if any).
395 * \param[in] grid The grid.
396 * \param[in] pointIndex1 Grid point index of the first point.
397 * \param[in] pointIndex2 Grid point index of the second point.
398 * \returns true if the two points have different lambda values.
400 bool pointsHaveDifferentLambda(const BiasGrid& grid, int pointIndex1, int pointIndex2);