Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2024 The METATOMIC-PLUMED team
3 : (see the PEOPLE-METATOMIC file at the root of this folder for a list of names)
4 :
5 : See https://docs.metatensor.org/metatomic/ for more information about the
6 : metatomic package that this module allows you to call from PLUMED.
7 :
8 : This file is part of METATOMIC-PLUMED module.
9 :
10 : The METATOMIC-PLUMED module is free software: you can redistribute it and/or modify
11 : it under the terms of the GNU Lesser General Public License as published by
12 : the Free Software Foundation, either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : The METATOMIC-PLUMED module is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU Lesser General Public License for more details.
19 :
20 : You should have received a copy of the GNU Lesser General Public License
21 : along with the METATOMIC-PLUMED module. If not, see <http://www.gnu.org/licenses/>.
22 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
23 : #ifndef __PLUMED_metatomic_vesin_h
24 : #define __PLUMED_metatomic_vesin_h
25 : /*INDENT-OFF*/
26 :
27 :
28 : #include <cstddef>
29 : #include <cstdint>
30 :
31 : // clang-format off
32 : #if defined(VESIN_SHARED)
33 : #if defined(VESIN_EXPORTS)
34 : #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
35 : #define VESIN_API __attribute__((visibility("default")))
36 : #elif defined(_MSC_VER)
37 : #define VESIN_API __declspec(dllexport)
38 : #else
39 : #define VESIN_API
40 : #endif
41 : #else
42 : #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
43 : #define VESIN_API __attribute__((visibility("default")))
44 : #elif defined(_MSC_VER)
45 : #define VESIN_API __declspec(dllimport)
46 : #else
47 : #define VESIN_API
48 : #endif
49 : #endif
50 : #else
51 : #define VESIN_API
52 : #endif
53 : // clang-format on
54 :
55 : #ifdef __cplusplus
56 : namespace PLMD {
57 : namespace metatomic {
58 : namespace vesin {
59 : extern "C" {
60 : #endif
61 :
62 : /// Algorithm to use for neighbor list construction
63 : enum VesinAlgorithm {
64 : /// Automatically select algorithm based on system characteristics (number
65 : /// of points, size of the box, …), this is the default and recommended
66 : /// option.
67 : VesinAutoAlgorithm = 0,
68 : /// Brute-force O(n^2) algorithm, this requires minimum image convention in
69 : /// CUDA, and is not available on CPU.
70 : VesinBruteForce = 1,
71 : /// Cell list algorithm with O(n) scaling
72 : VesinCellList = 2,
73 : };
74 :
75 : /// Options for a neighbor list calculation
76 : struct VesinOptions {
77 : /// Spherical cutoff, only pairs below this cutoff will be included
78 : double cutoff;
79 : /// Should the returned neighbor list be a full list (include both `i -> j`
80 : /// and `j -> i` pairs) or a half list (include only `i -> j`)?
81 : bool full;
82 : /// Should the neighbor list be sorted? If `true`, the returned pairs will
83 : /// be sorted by the first point index (`i`). The order of the second point
84 : /// index (`j`) and shifts in the list of pairs is unspecified.
85 : bool sorted;
86 : /// Which algorithm to use for the calculation
87 : VesinAlgorithm algorithm;
88 :
89 : /// Should the returned `VesinNeighborList` contain `shifts`?
90 : bool return_shifts;
91 : /// Should the returned `VesinNeighborList` contain `distances`?
92 : bool return_distances;
93 : /// Should the returned `VesinNeighborList` contain `vector`?
94 : bool return_vectors;
95 : };
96 :
97 : /// Device on which the data can be
98 : enum VesinDeviceKind {
99 : /// Unknown device, used for default initialization and to indicate no
100 : /// allocated data.
101 : VesinUnknownDevice = 0,
102 : /// CPU device
103 : VesinCPU = 1,
104 : // CUDA device
105 : VesinCUDA = 2,
106 : };
107 :
108 : /// Represents a device on which data can be allocated.
109 : ///
110 : /// This structure combines the device type (CPU or CUDA) with an optional
111 : /// device index. For CPU allocations, `device_id` is always 0. For CUDA
112 : /// allocations, `device_id` specifies which GPU to use (e.g., 0, 1, 2).
113 : ///
114 : /// Example usage:
115 : /// ```c
116 : /// VesinDevice cpu { VesinCPU, 0 };
117 : /// VesinDevice gpu0 { VesinCUDA, 0 };
118 : /// VesinDevice gpu1 { VesinCUDA, 1 };
119 : /// ```
120 : struct VesinDevice {
121 : /// Type of the device
122 : VesinDeviceKind type;
123 : /// Device index (0 for CPU, GPU index for CUDA)
124 : int device_id = 0;
125 : };
126 :
127 : /// The actual neighbor list
128 : ///
129 : /// This is organized as a list of pairs, where each pair can contain the
130 : /// following data:
131 : ///
132 : /// - indices of the points in the pair;
133 : /// - distance between points in the pair, accounting for periodic boundary
134 : /// conditions;
135 : /// - vector between points in the pair, accounting for periodic boundary
136 : /// conditions;
137 : /// - periodic shift that created the pair. This is only relevant when using
138 : /// periodic boundary conditions, and contains the number of bounding box we
139 : /// need to cross to create the pair. If the positions of the points are `r_i`
140 : /// and `r_j`, the bounding box is described by a matrix of three vectors `H`,
141 : /// and the periodic shift is `S`, the distance vector for a given pair will
142 : /// be given by `r_ij = r_j - r_i + S @ H`.
143 : ///
144 : /// Under periodic boundary conditions, two atoms can be part of multiple pairs,
145 : /// each pair having a different periodic shift.
146 : struct VESIN_API VesinNeighborList {
147 : #ifdef __cplusplus
148 8 : VesinNeighborList():
149 0 : length(0),
150 0 : device({VesinUnknownDevice, 0}),
151 0 : pairs(nullptr),
152 0 : shifts(nullptr),
153 0 : distances(nullptr),
154 0 : vectors(nullptr) {}
155 : #endif
156 :
157 : /// Number of pairs in this neighbor list
158 : size_t length;
159 : /// Device used for the data allocations
160 : VesinDevice device;
161 : /// Array of pairs (storing the indices of the first and second point in the
162 : /// pair), containing `length` elements.
163 : size_t (*pairs)[2];
164 : /// Array of box shifts, one for each `pair`. This is only set if
165 : /// `options.return_pairs` was `true` during the calculation.
166 : int32_t (*shifts)[3];
167 : /// Array of pair distance (i.e. distance between the two points), one for
168 : /// each pair. This is only set if `options.return_distances` was `true`
169 : /// during the calculation.
170 : double* distances;
171 : /// Array of pair vector (i.e. vector between the two points), one for
172 : /// each pair. This is only set if `options.return_vector` was `true`
173 : /// during the calculation.
174 : double (*vectors)[3];
175 :
176 : /// Private pointer used to hold additional internal data
177 : void* opaque = nullptr;
178 :
179 : // TODO: custom memory allocators?
180 : };
181 :
182 : /// Free all allocated memory inside a `VesinNeighborList`, according the it's
183 : /// `device`.
184 : void VESIN_API vesin_free(struct VesinNeighborList* neighbors);
185 :
186 : /// Compute a neighbor list.
187 : ///
188 : /// The data is returned in a `VesinNeighborList`. For an initial call, the
189 : /// `VesinNeighborList` should be zero-initialized (or default-initalized in
190 : /// C++). The `VesinNeighborList` can be re-used across calls to this functions
191 : /// to re-use memory allocations, and once it is no longer needed, users should
192 : /// call `vesin_free` to release the corresponding memory.
193 : ///
194 : /// @param points positions of all points in the system;
195 : /// @param n_points number of elements in the `points` array
196 : /// @param box bounding box for the system. If the system is non-periodic,
197 : /// this is ignored. This should contain the three vectors of the bounding
198 : /// box, one vector per row of the matrix.
199 : /// @param periodic is the system using periodic boundary conditions? This
200 : // should be an array of three booleans, one for each dimension.
201 : /// @param device device where the `points` and `box` data is allocated.
202 : /// @param options options for the calculation
203 : /// @param neighbors non-NULL pointer to `VesinNeighborList` that will be used
204 : /// to store the computed list of neighbors.
205 : /// @param error_message Pointer to a `char*` that wil be set to the error
206 : /// message if this function fails. This does not need to be freed when no
207 : /// longer needed.
208 : int VESIN_API vesin_neighbors(
209 : const double (*points)[3],
210 : size_t n_points,
211 : const double box[3][3],
212 : const bool periodic[3],
213 : VesinDevice device,
214 : struct VesinOptions options,
215 : struct VesinNeighborList* neighbors,
216 : const char** error_message
217 : );
218 :
219 : #ifdef __cplusplus
220 :
221 : } // extern "C"
222 : } // namespace vesin
223 : } // namespace metatomic
224 : } // namespace PLMD
225 :
226 : #endif
227 :
228 : #endif
|