OpenMPCD
CUDA/DeviceCode/Simulation.hpp
Go to the documentation of this file.
1 /**
2  * @file
3  * Defines CUDA Device code for OpenMPCD::CUDA::Simulation
4  */
5 
6 #ifndef OPENMPCD_CUDA_DEVICECODE_SIMULATION_HPP
7 #define OPENMPCD_CUDA_DEVICECODE_SIMULATION_HPP
8 
10 #include <OpenMPCD/Types.hpp>
11 #include <OpenMPCD/Vector3D.hpp>
12 
13 namespace OpenMPCD
14 {
15 namespace CUDA
16 {
17 /**
18  * Contains CUDA Device code.
19  */
20 namespace DeviceCode
21 {
22 
23 /**
24  * Returns whether the given position lies within the primary simulation volume.
25  *
26  * The primary simulation volume is defined as
27  * \f[
28  * \left[0, L_x\right) \times \left[0, L_y\right) \times \left[0, L_z\right)
29  * \f]
30  * where \f$ L_x \f$ is the value of `mpcSimulationBoxSizeX`, i.e. the size of
31  * the primary simulation volume along the \f$ x \f$ axis, and analogously for
32  * \f$ L_y \f$ and `mpcSimulationBoxSizeY`,
33  * and \f$ L_z \f$ and `mpcSimulationBoxSizeZ`.
34  *
35  * This function requires that
36  * `OpenMPCD::CUDA::DeviceCode::setSimulationBoxSizeSymbols` has been called.
37  *
38  * @param[in] position The position to check.
39  */
40 __device__ bool isInPrimarySimulationVolume(
41  const Vector3D<MPCParticlePositionType>& position);
42 
43 /**
44  * Returns the collision cell index for the given position.
45  *
46  * The collision cell index is determined as follows:
47  * The three cartesian coordinates of the given particle position are rounded
48  * down towards the nearest integer. This triple of numbers then determine the
49  * coordinates of the collision cell the particle lies in. If they are called
50  * `cellX`, `cellY`, and `cellZ`, respectively, what is returned is
51  * `cellX + cellY * boxSizeX` + cellZ * boxSizeX * boxSizeY`, where `boxSizeX`
52  * and `boxSizeY` are the number of collision cells in the primary simulation
53  * volume along the `x` and `y` directions, respectively.
54  *
55  * This function requires that
56  * `OpenMPCD::CUDA::DeviceCode::setSimulationBoxSizeSymbols` has been called
57  * before.
58  *
59  * @param[in] position The position to consider, which must lie in the primary
60  * simulation volume, i.e. the `x`, `y`, and `z` coordinates
61  * must be non-negative and smaller than the simulation box
62  * size along the respective direction.
63  */
64 __device__ unsigned int getCollisionCellIndex(
65  const Vector3D<MPCParticlePositionType>& position);
66 
67 /**
68  * Sorts the MPC particles into the collision cells, temporarily applying
69  * Lees-Edwards boundary conditions.
70  *
71  * This function requires that
72  * `OpenMPCD::CUDA::DeviceCode::setSimulationBoxSizeSymbols` and
73  * `OpenMPCD::CUDA::DeviceCode::setLeesEdwardsSymbols` have been called before.
74  *
75  * @see LeesEdwardsBoundaryConditions
76  *
77  * @param[in] workUnitOffset The number of particles to skip.
78  * @param[in] particleCount The number of particles there are.
79  * @param[in] gridShift_ The grid shift vector to temporarily add
80  * to all positions.
81  * @param[in] mpcTime The MPC time that has passed since the
82  * start of the simulation.
83  * @param[in] positions The MPC fluid particle positions.
84  * @param[in,out] velocities The MPC fluid particle velocities, which
85  * may be changed due to Lees-Edwards
86  * boundary conditions.
87  * @param[out] velocityCorrections The velocity corrections applied due to
88  * Lees-Edwards boundary conditions, which
89  * can be undone by
90  * `undoLeesEdwardsVelocityCorrections`; the
91  * buffer has to be at least `particleCount`
92  * elements long.
93  * @param[out] collisionCellIndices The collision cell indices for the
94  * particles.
95  */
97  const unsigned int workUnitOffset,
98  const unsigned int particleCount,
99  const MPCParticlePositionType* const gridShift_,
100  const FP mpcTime,
101  const MPCParticlePositionType* const positions,
102  MPCParticleVelocityType* const velocities,
103  MPCParticleVelocityType* const velocityCorrections,
104  unsigned int* const collisionCellIndices);
105 
106 /**
107  * Sorts the given particle into the collision cells, temporarily applying
108  * Lees-Edwards boundary conditions.
109  *
110  * This function requires that
111  * `OpenMPCD::CUDA::DeviceCode::setSimulationBoxSizeSymbols` and
112  * `OpenMPCD::CUDA::DeviceCode::setLeesEdwardsSymbols` have been called before.
113  *
114  * @see LeesEdwardsBoundaryConditions
115  *
116  * @param[in] particleID The particle ID.
117  * @param[in] gridShift_ The grid shift vector to temporarily add
118  * to the position.
119  * @param[in] mpcTime The MPC time that has passed since the
120  * start of the simulation.
121  * @param[in] positions The particle positions.
122  * @param[in,out] velocities The particle velocities, which may be
123  * changed due to Lees-Edwards boundary
124  * conditions.
125  * @param[out] velocityCorrections The velocity corrections applied due to
126  * Lees-Edwards boundary conditions.
127  * @param[out] collisionCellIndices The collision cell indices for the
128  * particles.
129  */
130 __device__ void sortIntoCollisionCellsLeesEdwards(
131  const unsigned int particleID,
132  const MPCParticlePositionType* const gridShift_,
133  const FP mpcTime,
134  const MPCParticlePositionType* const positions,
135  MPCParticleVelocityType* const velocities,
136  MPCParticleVelocityType* const velocityCorrections,
137  unsigned int* const collisionCellIndices);
138 
139 /**
140  * Computes the collision cell mass and momentum contributions by the given
141  * particles.
142  *
143  * @param[in] workUnitOffset The number of particles to skip.
144  * @param[in] particleCount The number of particles there are.
145  * @param[in] velocities The particle velocities.
146  * @param[in] collisionCellIndices The collision cell indices for the
147  * particles.
148  * @param[in,out] collisionCellMomenta The collision cell momenta. This array is
149  * expected to be long enough to store `3`
150  * coordinates for each collision cell, and
151  * is assumed to have each element set to
152  * `0` prior to calling this function.
153  * @param[in,out] collisionCellMasses The masses of the collision cells. This
154  * array is expected to be long enough to
155  * store `1` element for each collision
156  * cell, and is assumed to have each element
157  * set to `0` prior to calling this
158  * function.
159  * @param[in] particleMass The mass of any one particle.
160  */
161 __global__ void collisionCellContributions(
162  const unsigned int workUnitOffset,
163  const unsigned int particleCount,
164  const MPCParticleVelocityType* const velocities,
165  const unsigned int* const collisionCellIndices,
166  MPCParticleVelocityType* const collisionCellMomenta,
167  FP* const collisionCellMasses,
168  const FP particleMass);
169 
170 /**
171  * Returns the center-of-mass velocity of a collision cell.
172  *
173  * @param[in] collisionCellIndex The index of the collision cell.
174  * @param[in] collisionCellMomenta The momenta of the collision cells.
175  * @param[in] collisionCellMasses The masses of the collision cells.
176  */
177 __device__
178 Vector3D<MPCParticleVelocityType> getCollisionCellCenterOfMassVelocity(
179  const unsigned int collisionCellIndex,
180  const MPCParticleVelocityType* const collisionCellMomenta,
181  const FP* const collisionCellMasses);
182 
183 
184 /**
185  * Resets the collision cell data buffers.
186  *
187  * This kernel sets the data pointed to by the arguments provided to `0`.
188  * One needs to spawn at least `collisionCellCount` threads (possibly using
189  * `workUnitOffset`, if one grid does not fit all threads) for this operation to
190  * complete semantically.
191  *
192  * Each pointer argument is required to be non-`nullptr`, and point to at least
193  * `collisionCellCount` elements; `collisionCellMomenta` needs to point to at
194  * least `3 * collisionCellCount` elements instead.
195  *
196  * @param[in] workUnitOffset
197  * The number of collision cells to skip.
198  * @param[in] collisionCellCount
199  * The number of collision cells there are.
200  * @param[out] collisionCellParticleCounts
201  * Pointer to the memory where the collision cell particle counts
202  * are stored.
203  * @param[out] collisionCellMomenta
204  * Pointer to the memory where the collision cell momenta are
205  * stored (three per collision cell).
206  * @param[out] collisionCellFrameInternalKineticEnergies
207  * Pointer to the memory where the collision cell kinetic energies
208  * (in the internal frame) are stored.
209  * @param[out] collisionCellMasses
210  * Pointer to the memory where the collision cell masses are stored.
211  */
212 __global__ void resetCollisionCellData(
213  const unsigned int workUnitOffset,
214  const unsigned int collisionCellCount,
215  unsigned int* const collisionCellParticleCounts,
216  MPCParticleVelocityType* const collisionCellMomenta,
217  FP* const collisionCellFrameInternalKineticEnergies,
218  FP* const collisionCellMasses);
219 
220 /**
221  * Generates a new random grid shift vector.
222  *
223  * This function will draw three Cartesian coordinates from the uniform
224  * distribution over \f$ \left( 0, 1 \right] \f$, multiply the results by
225  * `gridShiftScale`, and store them in the three elements pointed at by
226  * `gridShift`.
227  *
228  * This kernel must be called with one block and one thread only.
229  *
230  * @param[out] gridShift
231  * Where to store the three grid shift coordinates to.
232  * @param[in] gridShiftScale
233  * The scale for the grid shift vector coordinates.
234  * @param[in,out] rngs
235  * Pointer to at least one random number generator.
236  */
237 __global__ void generateGridShiftVector(
238  MPCParticlePositionType* const gridShift,
239  const FP gridShiftScale,
240  GPURNG* const rngs);
241 
242 /**
243  * Generates new rotation axes for the collision cells.
244  *
245  * @param[in] workUnitOffset
246  * The number of particles to skip.
247  * @param[in] collisionCellCount
248  * The number of collision cells there are.
249  * @param[out] collisionCellRotationAxes
250  * For each collision cell, stores the Cartesian coordinates of
251  * the unit-length axis of rotation.
252  * @param[in,out] rngs
253  * The random number generators, of which there must be at least
254  * `collisionCellCount`.
255  */
256 __global__ void generateCollisionCellRotationAxes(
257  const unsigned int workUnitOffset,
258  const unsigned int collisionCellCount,
259  FP* const collisionCellRotationAxes,
260  GPURNG* const rngs);
261 
262 /**
263  * Applies the first step of the SRD rotation to the given particles.
264  *
265  * This function requires that
266  * `OpenMPCD::CUDA::DeviceCode::setSRDCollisionAngleSymbol` has been called
267  * before.
268  *
269  * @param[in] workUnitOffset
270  * The number of particles to skip.
271  * @param[in] particleCount
272  * The number of particles there are.
273  * @param[in,out] velocities
274  * The particle velocities as input; after the function call, the
275  * values in this array will contain the velocities in the
276  * collision cell's center-of-mass frame.
277  * @param[in] particleMass
278  * The mass of any one particle.
279  * @param[in] collisionCellIndices
280  * An array which holds, for each particle, the index of the
281  * collision cell it is currently in.
282  * @param[in] collisionCellMomenta
283  * An array holding, for each collision cell, its three cartesian
284  * momentum coordinates.
285  * @param[in] collisionCellMasses
286  * An array holding, for each collision cell, its total mass
287  * content.
288  * @param[in] collisionCellRotationAxes
289  * An array holding, for each collision cell, the random rotation
290  * axis it is to use during the collision.
291  * @param[out] collisionCellFrameInternalKineticEnergies
292  * An array, long enough to hold an element for each collision
293  * cell. The respective elements are set to the sum of the
294  * kinetic energies of the particles in that collision
295  * cell, as measured in that collision cell's center-of-mass
296  * frame. The array is not set to `0` by this function prior to
297  * execution of the algorithm.
298  * @param[out] collisionCellParticleCounts
299  * An array, long enough to hold an element for each collision
300  * cell. The respective elements are set to the number of
301  * particles in that collision cell. The array is assumed to
302  * contain only values `0` prior to calling this function.
303  */
305  const unsigned int workUnitOffset,
306  const unsigned int particleCount,
307  MPCParticleVelocityType* const velocities,
308  const FP particleMass,
309  const unsigned int* const collisionCellIndices,
310  const MPCParticleVelocityType* const collisionCellMomenta,
311  const FP* const collisionCellMasses,
312  const MPCParticlePositionType* const collisionCellRotationAxes,
313  FP* const collisionCellFrameInternalKineticEnergies,
314  unsigned int* const collisionCellParticleCounts);
315 
316 /**
317  * Generates Maxwell-Boltzmann-Scaling factors for the collision cells.
318  *
319  * @param[in] workUnitOffset
320  * The number of particles to skip.
321  * @param[in] collisionCellCount
322  * The number of collision cells there are.
323  * @param[in] collisionCellFrameInternalKineticEnergies
324  * Stores, for each collision cell, the sum of the kinetic
325  * energies of the particles in that collision cell, as measured
326  * in that collision cell's center-of-mass frame
327  * @param[in] collisionCellParticleCounts
328  * The number of particles in the collision cells.
329  * @param[out] collisionCellRelativeVelocityScalings
330  * For each collision cell, stores the factor by which to scale
331  * the relative velocities.
332  * @param[in] bulkThermostatTargetkT
333  * The target temperature for the thermostat.
334  * @param[in,out] rngs
335  * The random number generators, of which there must be at least
336  * `collisionCellCount`.
337  */
338 __global__ void generateCollisionCellMBSFactors(
339  const unsigned int workUnitOffset,
340  const unsigned int collisionCellCount,
341  const FP* const collisionCellFrameInternalKineticEnergies,
342  unsigned int* const collisionCellParticleCounts,
343  FP* const collisionCellRelativeVelocityScalings,
344  const FP bulkThermostatTargetkT,
345  GPURNG* const rngs);
346 
347 /**
348  * Applies the second step of the SRD rotation to the given particles.
349  *
350  * This kernel scales each particle's velocity with the corresponding collision
351  * cell's scaling factor (stored in `collisionCellVelocityScalings`), and then
352  * adds the corresponding collision cell's center-of-mass velocity.
353  *
354  * @param[in] workUnitOffset
355  * The number of particles to skip.
356  * @param[in] particleCount
357  * The number of particles there are.
358  * @param[in,out] velocities
359  * The new particle velocities as output; as input, the
360  * values in this array are to contain the rotated velocities in
361  * the collision cell's center-of-mass frame.
362  * @param[in] collisionCellIndices
363  * An array which holds, for each particle, the index of the
364  * collision cell it is currently in.
365  * @param[in] collisionCellMomenta
366  * An array holding, for each collision cell, its three Cartesian
367  * momentum coordinates.
368  * @param[in] collisionCellMasses
369  * An array holding, for each collision cell, its total mass
370  * content.
371  * @param[in] collisionCellVelocityScalings
372  * For each collision cell, stores the factor by which to scale
373  * the relative velocities.
374  */
376  const unsigned int workUnitOffset,
377  const unsigned int particleCount,
378  MPCParticleVelocityType* const velocities,
379  const unsigned int* const collisionCellIndices,
380  const MPCParticleVelocityType* const collisionCellMomenta,
381  const FP* const collisionCellMasses,
382  const FP* const collisionCellVelocityScalings);
383 
384 /**
385  * Undoes the velocity corrections applied by
386  * `sortIntoCollisionCellsLeesEdwards`.
387  *
388  * @param[in] workUnitOffset
389  * The number of particles to skip.
390  * @param[in] particleCount
391  * The number of particles there are.
392  * @param[in,out] velocities
393  * The particle velocities.
394  * @param[in] velocityCorrections
395  * The velocity corrections as returned by
396  * `sortIntoCollisionCellsLeesEdwards`.
397  */
398 __global__ void undoLeesEdwardsVelocityCorrections(
399  const unsigned int workUnitOffset,
400  const unsigned int particleCount,
401  MPCParticleVelocityType* const velocities,
402  const MPCParticleVelocityType* const velocityCorrections);
403 
404 /**
405  * Sets up instances of `GPURNG` in the specified memory location.
406  *
407  * The individual RNGs will have subsequence numbers (or, alternatively, seeds)
408  * set such that the individual instances generate independent streams of random
409  * numbers.
410  *
411  * Only the first thread in this kernel does any work.
412  *
413  * @param[in] count
414  * The number of instances to construct.
415  * @param[out] location
416  * The location in memory to store the instances in; memory must
417  * have been allocated at this location prior to calling this
418  * function.
419  * @param[in] seed
420  * The seed to use for the RNGs.
421  */
422 __global__
423 void constructGPURNGs(
424  const std::size_t count,
425  GPURNG* const location,
426  const unsigned long long seed);
427 
428 /**
429  * Destroys instances of `GPURNG` in the specified memory location.
430  *
431  * Only the first thread in this kernel does any work.
432  *
433  * @param[in] count
434  * The number of instances to construct.
435  * @param[out] location
436  * The location in memory where there are instances; memory must
437  * be freed manually after this function call.
438  */
439 __global__
440 void destroyGPURNGs(const std::size_t count, GPURNG* const location);
441 
442 } //namespace DeviceCode
443 } //namespace CUDA
444 } //namespace OpenMPCD
445 
446 #endif
OpenMPCD::CUDA::DeviceCode::generateGridShiftVector
__global__ void generateGridShiftVector(MPCParticlePositionType *const gridShift, const FP gridShiftScale, GPURNG *const rngs)
Generates a new random grid shift vector.
OpenMPCD::CUDA::DeviceCode::generateCollisionCellRotationAxes
__global__ void generateCollisionCellRotationAxes(const unsigned int workUnitOffset, const unsigned int collisionCellCount, FP *const collisionCellRotationAxes, GPURNG *const rngs)
Generates new rotation axes for the collision cells.
OpenMPCD::CUDA::DeviceCode::undoLeesEdwardsVelocityCorrections
__global__ void undoLeesEdwardsVelocityCorrections(const unsigned int workUnitOffset, const unsigned int particleCount, MPCParticleVelocityType *const velocities, const MPCParticleVelocityType *const velocityCorrections)
Undoes the velocity corrections applied by sortIntoCollisionCellsLeesEdwards.
Types.hpp
OpenMPCD::CUDA::DeviceCode::collisionCellStochasticRotationStep1
__global__ void collisionCellStochasticRotationStep1(const unsigned int workUnitOffset, const unsigned int particleCount, MPCParticleVelocityType *const velocities, const FP particleMass, const unsigned int *const collisionCellIndices, const MPCParticleVelocityType *const collisionCellMomenta, const FP *const collisionCellMasses, const MPCParticlePositionType *const collisionCellRotationAxes, FP *const collisionCellFrameInternalKineticEnergies, unsigned int *const collisionCellParticleCounts)
Applies the first step of the SRD rotation to the given particles.
OpenMPCD::CUDA::DeviceCode::destroyGPURNGs
__global__ void destroyGPURNGs(const std::size_t count, GPURNG *const location)
Destroys instances of GPURNG in the specified memory location.
OpenMPCD::CUDA::DeviceCode::sortParticlesIntoCollisionCellsLeesEdwards
__global__ void sortParticlesIntoCollisionCellsLeesEdwards(const unsigned int workUnitOffset, const unsigned int particleCount, const MPCParticlePositionType *const gridShift_, const FP mpcTime, const MPCParticlePositionType *const positions, MPCParticleVelocityType *const velocities, MPCParticleVelocityType *const velocityCorrections, unsigned int *const collisionCellIndices)
Sorts the MPC particles into the collision cells, temporarily applying Lees-Edwards boundary conditio...
OpenMPCD::CUDA::DeviceCode::collisionCellStochasticRotationStep2
__global__ void collisionCellStochasticRotationStep2(const unsigned int workUnitOffset, const unsigned int particleCount, MPCParticleVelocityType *const velocities, const unsigned int *const collisionCellIndices, const MPCParticleVelocityType *const collisionCellMomenta, const FP *const collisionCellMasses, const FP *const collisionCellVelocityScalings)
Applies the second step of the SRD rotation to the given particles.
OpenMPCD::CUDA::DeviceCode::resetCollisionCellData
__global__ void resetCollisionCellData(const unsigned int workUnitOffset, const unsigned int collisionCellCount, unsigned int *const collisionCellParticleCounts, MPCParticleVelocityType *const collisionCellMomenta, FP *const collisionCellFrameInternalKineticEnergies, FP *const collisionCellMasses)
Resets the collision cell data buffers.
OpenMPCD::CUDA::DeviceCode::sortIntoCollisionCellsLeesEdwards
__device__ void sortIntoCollisionCellsLeesEdwards(const unsigned int particleID, const MPCParticlePositionType *const gridShift_, const FP mpcTime, const MPCParticlePositionType *const positions, MPCParticleVelocityType *const velocities, MPCParticleVelocityType *const velocityCorrections, unsigned int *const collisionCellIndices)
Sorts the given particle into the collision cells, temporarily applying Lees-Edwards boundary conditi...
Vector3D.hpp
OpenMPCD::CUDA::DeviceCode::collisionCellCount
__constant__ unsigned int collisionCellCount
The number of collision cells in the system.
OpenMPCD::CUDA::DeviceCode::getCollisionCellIndex
__device__ unsigned int getCollisionCellIndex(const Vector3D< MPCParticlePositionType > &position)
Returns the collision cell index for the given position.
Types.hpp
OpenMPCD::CUDA::GPURNG
Random::Generators::Philox4x32_10 GPURNG
The random number generator type for GPUs.
Definition: CUDA/Types.hpp:18
OpenMPCD::CUDA::DeviceCode::constructGPURNGs
__global__ void constructGPURNGs(const std::size_t count, GPURNG *const location, const unsigned long long seed)
Sets up instances of GPURNG in the specified memory location.
OpenMPCD::CUDA::DeviceCode::generateCollisionCellMBSFactors
__global__ void generateCollisionCellMBSFactors(const unsigned int workUnitOffset, const unsigned int collisionCellCount, const FP *const collisionCellFrameInternalKineticEnergies, unsigned int *const collisionCellParticleCounts, FP *const collisionCellRelativeVelocityScalings, const FP bulkThermostatTargetkT, GPURNG *const rngs)
Generates Maxwell-Boltzmann-Scaling factors for the collision cells.
OpenMPCD::CUDA::DeviceCode::getCollisionCellCenterOfMassVelocity
__device__ Vector3D< MPCParticleVelocityType > getCollisionCellCenterOfMassVelocity(const unsigned int collisionCellIndex, const MPCParticleVelocityType *const collisionCellMomenta, const FP *const collisionCellMasses)
Returns the center-of-mass velocity of a collision cell.
Definition: Simulation.cpp:113
OpenMPCD::CUDA::DeviceCode::isInPrimarySimulationVolume
__device__ bool isInPrimarySimulationVolume(const Vector3D< MPCParticlePositionType > &position)
Returns whether the given position lies within the primary simulation volume.
OpenMPCD::CUDA::DeviceCode::collisionCellContributions
__global__ void collisionCellContributions(const unsigned int workUnitOffset, const unsigned int particleCount, const MPCParticleVelocityType *const velocities, const unsigned int *const collisionCellIndices, MPCParticleVelocityType *const collisionCellMomenta, FP *const collisionCellMasses, const FP particleMass)
Computes the collision cell mass and momentum contributions by the given particles.