NBLIB listed forces API update
[alexxy/gromacs.git] / api / nblib / listed_forces / traits.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2020, 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 /*! \internal \file
36  * \brief
37  * These traits defined here for supported nblib listed interaction data types
38  * are used to control the dataflow in dataflow.hpp
39  *
40  * \author Victor Holanda <victor.holanda@cscs.ch>
41  * \author Joe Jordan <ejjordan@kth.se>
42  * \author Prashanth Kanduri <kanduri@cscs.ch>
43  * \author Sebastian Keller <keller@cscs.ch>
44  * \author Artem Zhmurov <zhmurov@gmail.com>
45  */
46 #ifndef NBLIB_LISTEDFORCES_TRAITS_H
47 #define NBLIB_LISTEDFORCES_TRAITS_H
48
49 #include <numeric>
50
51 #include "nblib/util/internal.h"
52 #include "bondtypes.h"
53 #include "definitions.h"
54
55 namespace nblib
56 {
57
58 namespace detail
59 {
60
61 template<class InteractionType, class = void>
62 struct CoordinateIndex_
63 {
64 };
65
66 template<class InteractionType>
67 struct CoordinateIndex_<InteractionType, std::enable_if_t<Contains<InteractionType, SupportedTwoCenterTypes>{}>>
68 {
69     typedef std::array<int, 2> type;
70 };
71
72 template<class InteractionType>
73 struct CoordinateIndex_<InteractionType, std::enable_if_t<Contains<InteractionType, SupportedThreeCenterTypes>{}>>
74 {
75     typedef std::array<int, 3> type;
76 };
77
78 template<class InteractionType>
79 struct CoordinateIndex_<InteractionType, std::enable_if_t<Contains<InteractionType, SupportedFourCenterTypes>{}>>
80 {
81     typedef std::array<int, 4> type;
82 };
83
84 template<class InteractionType>
85 struct CoordinateIndex_<InteractionType, std::enable_if_t<Contains<InteractionType, SupportedFiveCenterTypes>{}>>
86 {
87     typedef std::array<int, 5> type;
88 };
89
90 } // namespace detail
91
92 /*! \brief traits class to determine the coordinate index type for InteractionType
93  *  \internal
94  *
95  * \tparam InteractionCategory
96  */
97 template<class InteractionType>
98 using CoordinateIndex = typename detail::CoordinateIndex_<InteractionType>::type;
99
100
101 namespace detail
102 {
103
104 template<class InteractionType, class = void>
105 struct InteractionIndex_
106 {
107 };
108
109 template<class InteractionType>
110 struct InteractionIndex_<InteractionType, std::enable_if_t<Contains<InteractionType, SupportedTwoCenterTypes>{}>>
111 {
112     typedef TwoCenterInteractionIndex type;
113 };
114
115 template<class InteractionType>
116 struct InteractionIndex_<InteractionType, std::enable_if_t<Contains<InteractionType, SupportedThreeCenterTypes>{}>>
117 {
118     typedef ThreeCenterInteractionIndex type;
119 };
120
121 template<class InteractionType>
122 struct InteractionIndex_<InteractionType, std::enable_if_t<Contains<InteractionType, SupportedFourCenterTypes>{}>>
123 {
124     typedef FourCenterInteractionIndex type;
125 };
126
127 template<class InteractionType>
128 struct InteractionIndex_<InteractionType, std::enable_if_t<Contains<InteractionType, SupportedFiveCenterTypes>{}>>
129 {
130     typedef FiveCenterInteractionIndex type;
131 };
132
133 } // namespace detail
134
135 /*! \brief traits class to determine the InteractionIndex type for InteractionType
136  *  \internal
137  *
138  * \tparam InteractionType
139  */
140 template<class InteractionType>
141 using InteractionIndex = typename detail::InteractionIndex_<InteractionType>::type;
142
143
144 template<class I, class = void>
145 struct HasTwoCenterAggregate : std::false_type
146 {
147 };
148
149 template<class I>
150 struct HasTwoCenterAggregate<I, std::void_t<typename I::TwoCenterAggregateType>> : std::true_type
151 {
152 };
153
154 template<class I, class = void>
155 struct HasThreeCenterAggregate : std::false_type
156 {
157 };
158
159 template<class I>
160 struct HasThreeCenterAggregate<I, std::void_t<typename I::ThreeCenterAggregateType>> : std::true_type
161 {
162 };
163
164 //! \internal \brief determines the energy storage location of the carrier part for InteractionTypes without aggregates
165 template<class InteractionType, class = void>
166 struct CarrierIndex :
167     std::integral_constant<size_t, FindIndex<InteractionType, ListedInteractionData>{}>
168 {
169 };
170
171 //! \internal \brief determines the energy storage location of the carrier part for InteractionTypes with aggregates
172 template<class InteractionType>
173 struct CarrierIndex<InteractionType, std::void_t<typename InteractionType::CarrierType>> :
174     std::integral_constant<size_t, FindIndex<typename InteractionType::CarrierType, ListedInteractionData>{}>
175 {
176 };
177
178 //! \internal \brief determines the energy storage location of the 2-C aggregate part for InteractionTypes without aggregates
179 template<class InteractionType, class = void>
180 struct TwoCenterAggregateIndex : std::integral_constant<size_t, 0>
181 {
182 };
183
184 //! \internal \brief determines the energy storage location of the 2-C aggregate part for InteractionTypes with 2-C aggregates
185 template<class InteractionType>
186 struct TwoCenterAggregateIndex<InteractionType, std::void_t<typename InteractionType::TwoCenterAggregateType>> :
187     std::integral_constant<size_t, FindIndex<typename InteractionType::TwoCenterAggregateType, ListedInteractionData>{}>
188 {
189 };
190
191 //! \internal \brief determines the energy storage location of the 3-C aggregate part for InteractionTypes without aggregates
192 template<class InteractionType, class = void>
193 struct ThreeCenterAggregateIndex : std::integral_constant<size_t, 0>
194 {
195 };
196
197 //! \internal \brief determines the energy storage location of the 3-C aggregate part for InteractionTypes with 3-C aggregates
198 template<class InteractionType>
199 struct ThreeCenterAggregateIndex<InteractionType, std::void_t<typename InteractionType::ThreeCenterAggregateType>> :
200     std::integral_constant<size_t, FindIndex<typename InteractionType::ThreeCenterAggregateType, ListedInteractionData>{}>
201 {
202 };
203
204 /*! \brief return type to hold the energies of the different overloads of "dispatchInteraction"
205  * \internal
206  *
207  * \tparam T
208  */
209 template<class T>
210 class KernelEnergy
211 {
212 public:
213     KernelEnergy() : energies_{ 0, 0, 0, 0 } {}
214
215     T&       carrier() { return energies_[0]; }
216     const T& carrier() const { return energies_[0]; }
217
218     T&       twoCenterAggregate() { return energies_[1]; }
219     const T& twoCenterAggregate() const { return energies_[1]; }
220
221     T&       threeCenterAggregate() { return energies_[2]; }
222     const T& threeCenterAggregate() const { return energies_[2]; }
223
224     T&       freeEnergyDerivative() { return energies_[3]; }
225     const T& freeEnergyDerivative() const { return energies_[3]; }
226
227     KernelEnergy& operator+=(const KernelEnergy& other)
228     {
229         for (size_t i = 0; i < energies_.size(); ++i)
230         {
231             energies_[i] += other.energies_[i];
232         }
233         return *this;
234     }
235
236     operator T() const { return std::accumulate(begin(energies_), end(energies_), T{}); }
237
238 private:
239     std::array<T, 4> energies_;
240 };
241
242 template<class BasicVector>
243 using BasicVectorValueType_t = std::remove_all_extents_t<typename BasicVector::RawArray>;
244
245 } // namespace nblib
246 #endif // NBLIB_LISTEDFORCES_TRAITS_H