Use shiftForces in ForceOuputs
[alexxy/gromacs.git] / src / gromacs / mdtypes / forceoutput.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
36 /*! \libinternal \file
37  *
38  * \brief
39  * This file contains the definition of a container for force and virial
40  * output.
41  *
42  * Currently the only container defined here is one used in algorithms
43  * that provide their own virial tensor contribution.
44  * We can consider adding another containter for forces and shift forces.
45  *
46  * \author Berk Hess
47  *
48  * \inlibraryapi
49  * \ingroup module_mdtypes
50  */
51
52 #ifndef GMX_MDTYPES_FORCEOUTPUT_H
53 #define GMX_MDTYPES_FORCEOUTPUT_H
54
55 #include "gromacs/math/arrayrefwithpadding.h"
56 #include "gromacs/math/vectypes.h"
57 #include "gromacs/utility/arrayref.h"
58
59 namespace gmx
60 {
61
62 /*! \libinternal \brief Container for force and virial for algorithms that compute shift forces for virial calculation
63  *
64  * This force output class should be used when computing forces whos virial contribution
65  * is computed using the "single sum virial" algorithm (see the reference manual for
66  * details). To handle the virial contributions of forces working between periodic
67  * images correctly, so-called "shift forces" need to be accumulated for the different
68  * periodic images.
69  */
70 class ForceWithShiftForces
71 {
72     public:
73         /*! \brief Constructor
74          *
75          * \param[in] force          A force buffer that will be used for storing forces
76          * \param[in] computeVirial  True when algorithms are required to provide their virial contribution (for the current force evaluation)
77          * \param[in] shiftForces    A shift forces buffer of size SHIFTS, also needed with \p computeVirial = false
78          */
79         ForceWithShiftForces(const gmx::ArrayRefWithPadding<gmx::RVec> &force,
80                              const bool                                 computeVirial,
81                              const gmx::ArrayRef<gmx::RVec>            &shiftForces) :
82             force_(force),
83             computeVirial_(computeVirial),
84             shiftForces_(shiftForces) {}
85
86         //! Returns an arrayref to the force buffer without padding
87         gmx::ArrayRef<gmx::RVec> force()
88         {
89             return force_.unpaddedArrayRef();
90         }
91
92         //! Returns a const arrayref to the force buffer without padding
93         gmx::ArrayRef<const gmx::RVec> force() const
94         {
95             return force_.unpaddedConstArrayRef();
96         }
97
98         //! Returns whether the virial needs to be computed
99         bool computeVirial() const
100         {
101             return computeVirial_;
102         }
103
104         //! Returns the shift forces buffer
105         gmx::ArrayRef<gmx::RVec> shiftForces()
106         {
107             return shiftForces_;
108         }
109
110         //! Returns a const shift forces buffer
111         gmx::ArrayRef<const gmx::RVec> shiftForces() const
112         {
113             return shiftForces_;
114         }
115
116     private:
117         //! The force buffer
118         gmx::ArrayRefWithPadding<gmx::RVec> force_;
119         //! True when virial computation is requested
120         bool                                computeVirial_;
121         //! A buffer for storing the shift forces, size SHIFTS
122         gmx::ArrayRef<gmx::RVec>            shiftForces_;
123 };
124
125 /*! \libinternal \brief Container for force and virial for algorithms that provide their own virial tensor contribution
126  *
127  * \note The \p force_ data member is a reference to an external force buffer.
128  */
129 class ForceWithVirial
130 {
131     public:
132         /*! \brief Constructor
133          *
134          * \param[in] force          A force buffer that will be used for storing forces
135          * \param[in] computeVirial  True when algorithms are required to provide their virial contribution (for the current force evaluation)
136          */
137         ForceWithVirial(const ArrayRef<RVec> &force,
138                         const bool            computeVirial) :
139             force_(force),
140             computeVirial_(computeVirial)
141         {
142             for (int dim1 = 0; dim1 < DIM; dim1++)
143             {
144                 for (int dim2 = 0; dim2 < DIM; dim2++)
145                 {
146                     virial_[dim1][dim2] = 0;
147                 }
148             }
149         }
150
151         /*! \brief Adds a virial contribution
152          *
153          * \note Can be called with \p computeVirial=false.
154          * \note It is recommended to accumulate the virial contributions
155          *       of a module internally before calling this method, as that
156          *       will reduce rounding errors.
157          *
158          * \param[in] virial  The virial contribution to add
159          */
160         void addVirialContribution(const matrix virial)
161         {
162             if (computeVirial_)
163             {
164                 for (int dim1 = 0; dim1 < DIM; dim1++)
165                 {
166                     for (int dim2 = 0; dim2 < DIM; dim2++)
167                     {
168                         virial_[dim1][dim2] += virial[dim1][dim2];
169                     }
170                 }
171             }
172         }
173
174         /*! \brief Adds a virial diagonal contribution
175          *
176          * \note Can be called with \p computeVirial=false.
177          * \note It is recommended to accumulate the virial contributions
178          *       of a module internally before calling this method, as that
179          *       will reduce rounding errors.
180          *
181          * \param[in] virial  The virial contribution to add
182          */
183         void addVirialContribution(const RVec virial)
184         {
185             if (computeVirial_)
186             {
187                 for (int dim = 0; dim < DIM; dim++)
188                 {
189                     virial_[dim][dim] += virial[dim];
190                 }
191             }
192         }
193
194         /*! \brief Returns the accumulated virial contributions
195          */
196         const matrix &getVirial() const
197         {
198             return virial_;
199         }
200
201         const ArrayRef<RVec> force_;         //!< Force accumulation buffer reference
202         const bool           computeVirial_; //!< True when algorithms are required to provide their virial contribution (for the current force evaluation)
203     private:
204         matrix               virial_;        //!< Virial accumulation buffer
205 };
206
207 /*! \libinternal \brief Force and virial output buffers for use in force computation
208  */
209 class ForceOutputs
210 {
211     public:
212         //! Constructor
213         ForceOutputs(const ForceWithShiftForces &forceWithShiftForces,
214                      const ForceWithVirial      &forceWithVirial) :
215             forceWithShiftForces_(forceWithShiftForces),
216             forceWithVirial_(forceWithVirial) {}
217
218         //! Returns a reference to the force with shift forces object
219         ForceWithShiftForces &forceWithShiftForces()
220         {
221             return forceWithShiftForces_;
222         }
223
224         //! Returns a reference to the force with virial object
225         ForceWithVirial &forceWithVirial()
226         {
227             return forceWithVirial_;
228         }
229
230     private:
231         //! Force output buffer used by legacy modules (without SIMD padding)
232         ForceWithShiftForces forceWithShiftForces_;
233         //! Force with direct virial contribution (if there are any; without SIMD padding)
234         ForceWithVirial      forceWithVirial_;
235 };
236
237 }  // namespace gmx
238
239 #endif