Apply clang-format to source tree
[alexxy/gromacs.git] / src / gromacs / math / gausstransform.h
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 \file
36  * \brief
37  * Declares Gaussian function evaluations on lattices and related functionality
38  *
39  * \author Christian Blau <blau@kth.se>
40  * \inlibraryapi
41  * \ingroup module_math
42  */
43 #ifndef GMX_MATH_GAUSSTRANSFORM_H
44 #define GMX_MATH_GAUSSTRANSFORM_H
45
46 #include <vector>
47
48 #include "gromacs/math/multidimarray.h"
49 #include "gromacs/math/vectypes.h"
50 #include "gromacs/mdspan/extensions.h"
51 #include "gromacs/mdspan/mdspan.h"
52 #include "gromacs/utility/arrayref.h"
53 #include "gromacs/utility/classhelpers.h"
54 #include "gromacs/utility/real.h"
55
56 namespace gmx
57 {
58
59 /*! \internal
60  * \brief Provide result of Gaussian function evaluation on a one-dimensional lattice.
61  *
62  * This class owns the result of the operation and provides a view on it.
63  *
64  * The distance between lattice points is one. Unit length is normalized by the
65  * lattice spacing, thus spreading width and range are given as multiples of
66  * lattice points distances.
67  *
68  * This works well as approximation to piece-wise integration of a Gaussian on a
69  * lattice, when \f$\sigma > 1\f$. The maximal relative error to evaluating erf
70  * differences for \f$\sigma = 1\f$ is 0.01602.
71  *
72  */
73 class GaussianOn1DLattice
74 {
75 public:
76     /*! \brief Construct Gaussian spreader with spreading range and Gaussian width.
77      *
78      * Spread weights are distributed over a non-periodic lattice of length
79      * 2*numGridPointsForSpreadingHalfWidth+1. The lattice comprises a center point and
80      * spreadDistance points to the left and to the right.
81      *
82      * \note There is a maximum spreading width
83      *
84      * \param[in] numGridPointsForSpreadingHalfWidth maximum distance in number of gridpoints from 0
85      * \param[in] sigma Gaussian width.
86      */
87     GaussianOn1DLattice(int numGridPointsForSpreadingHalfWidth, real sigma);
88     ~GaussianOn1DLattice();
89     //! Copy constructor
90     GaussianOn1DLattice(const GaussianOn1DLattice& other);
91     //! Copy assignment
92     GaussianOn1DLattice& operator=(const GaussianOn1DLattice& other);
93     //! Move constructor
94     GaussianOn1DLattice(GaussianOn1DLattice&& other) noexcept;
95     //! Move assignment
96     GaussianOn1DLattice& operator=(GaussianOn1DLattice&& other) noexcept;
97     /*! \brief Spreads weight onto grid points in one dimension.
98      *
99      *
100      *            .            :            |            :            .
101      *            o            o            o            o            o
102      *                                  O---|
103      *                          latticeOffset
104      * O - atom position
105      * o - lattice positions
106      * . : | spreading value at grid points.
107      *
108      * \note Highest numerical accuracy is achieved when the spreading
109      *       with offset to the nearest lattice coordinated < 0.5
110      *
111      * Spreading on lattice coordinate \f$x_i\f$
112      * \f[
113      *      f(x_i) = \frac{\mathrm{amplitude}}{\sigma\sqrt{2\pi}}\exp(-\frac{\mathrm{offset}-x_i^2}{2 \sigma ^2})
114      * \f]
115      * \param[in] amplitude of the Gaussian spread.
116      * \param[in] latticeOffset The distance to the nearest grid point in lattice coordinates.
117      */
118     void spread(double amplitude, real latticeOffset);
119     /*! \brief Returns view on spread result. */
120     ArrayRef<const float> view();
121
122 private:
123     class Impl;
124     PrivateImplPointer<Impl> impl_;
125 };
126
127 /*! \libinternal \brief Parameters for density spreading kernels.
128  */
129 struct GaussianSpreadKernelParameters
130 {
131     /*! \libinternal \brief Shape parameters for Gaussian spreading kernels describe
132      * the kernel shape.
133      */
134     struct Shape
135     {
136         //! The width of the Gaussian function in lattice spacings
137         DVec sigma_;
138         //! The range of the spreading function in multiples of sigma
139         double spreadWidthMultiplesOfSigma_;
140         //! The spread range in lattice coordinates
141         IVec latticeSpreadRange() const;
142     };
143     /*! \libinternal \brief Parameters that describe the kernel position and amplitude.
144      */
145     struct PositionAndAmplitude
146     {
147         //! position of the kernel to be spread onto the lattice
148         const RVec& coordinate_;
149         //! amplitude of the spread kernel
150         real amplitude_;
151     };
152 };
153
154 /*! \libinternal \brief Sums Gaussian values at three dimensional lattice coordinates.
155  * The Gaussian is defined as \f$A \frac{1}{\sigma^3 \sqrt(2^3\pi^3)} * \exp(-\frac{(x-x0)^2}{2
156  \sigma^2})\f$ \verbatim x0:              X           x
157                /   \        / \
158              --     --    --   --
159    lattice: |    |    |    |    |    |    |
160    \endverbatim
161  * The lattice has spacing 1, all coordinates are given with respect to the lattice
162  * coordinates.
163  */
164 class GaussTransform3D
165 {
166 public:
167     /*! \brief Construct a three-dimensional Gauss transform.
168      *
169      * Transform lattice values will be zero-initialized.
170      *
171      * \param[in] extent of the spread lattice
172      * \param[in] globalParameters of the spreading kernel
173      */
174     GaussTransform3D(const dynamicExtents3D&                      extent,
175                      const GaussianSpreadKernelParameters::Shape& globalParameters);
176
177     ~GaussTransform3D();
178
179     //! Copy constructor
180     GaussTransform3D(const GaussTransform3D& other);
181
182     //! Copy assignment
183     GaussTransform3D& operator=(const GaussTransform3D& other);
184
185     //! Move constructor
186     GaussTransform3D(GaussTransform3D&& other) noexcept;
187
188     //! Move assignment
189     GaussTransform3D& operator=(GaussTransform3D&& other) noexcept;
190
191     /*! \brief Add a three dimensional Gaussian with given amplitude at a coordinate.
192      * \param[in] localParameters of the spreading kernel
193      */
194     void add(const GaussianSpreadKernelParameters::PositionAndAmplitude& localParameters);
195
196     //! \brief Set all values on the lattice to zero.
197     void setZero();
198
199     //! Return a view on the spread lattice.
200     basic_mdspan<float, dynamicExtents3D> view();
201
202     //! Return a const view on the spread lattice.
203     basic_mdspan<const float, dynamicExtents3D> constView() const;
204
205 private:
206     class Impl;
207     PrivateImplPointer<Impl> impl_;
208 };
209
210 /*! \internal \brief A 3-orthotope over integer intervals.
211  */
212 class IntegerBox
213 {
214 public:
215     //! Construct from begin and end
216     IntegerBox(const IVec& begin, const IVec& end);
217     //! Begin indices of the box
218     const IVec& begin() const;
219     //! End indices of the box
220     const IVec& end() const;
221     //! Empty if for any dimension, end <= begin;
222     bool empty() const;
223
224 private:
225     const IVec begin_; //< interger indices denoting begin of box
226     const IVec end_;   //< integer indices denoting one-past end of box in any dimension
227 };
228
229 /*! \brief Construct a box that holds all indices that are not more than a given range remote from
230  * center coordinates and still within a given lattice extent.
231  *
232  * \param[in] center the coordinates of the center of the spread range
233  * \param[in] extent the end of the lattice, number of lattice points in each dimension
234  * \param[in] range the distance from the center
235  * \returns box describing the range of indices
236  */
237 IntegerBox spreadRangeWithinLattice(const IVec& center, dynamicExtents3D extent, IVec range);
238
239 /*! \internal \brief Evaluate the outer product of two number ranges.
240  * Keeps the memory for the outer product allocated.
241  */
242 class OuterProductEvaluator
243 {
244 public:
245     //! Evaluate the outer product of two float number ranges.
246     mdspan<const float, dynamic_extent, dynamic_extent> operator()(ArrayRef<const float> x,
247                                                                    ArrayRef<const float> y);
248
249 private:
250     MultiDimArray<std::vector<float>, extents<dynamic_extent, dynamic_extent>> data_;
251 };
252
253 } // namespace gmx
254
255 #endif /* end of include guard: GMX_MATH_GAUSSTRANSFORM_H */