AutoPas  3.0.0
Loading...
Searching...
No Matches
RemainderTriwiseInteractionHandler.h
Go to the documentation of this file.
1
7#pragma once
8
9#include <cmath>
10#include <memory>
11#include <mutex>
12#include <numeric>
13#include <vector>
14
18#include "autopas/utils/Timer.h"
20
21namespace autopas {
22
29template <typename Particle_T>
31 public:
37 std::vector<std::vector<std::vector<std::unique_ptr<std::mutex>>>> &spatialLocks)
38 : _spatialLocks(spatialLocks) {}
39
60 template <bool newton3, class ContainerType, class TriwiseFunctor>
61 void computeRemainderInteractions(TriwiseFunctor *f, ContainerType &container,
62 std::vector<FullParticleCell<Particle_T>> &particleBuffers,
63 std::vector<FullParticleCell<Particle_T>> &haloParticleBuffers) {
64 // Vector to collect pointers to all buffer particles
65 std::vector<Particle_T *> bufferParticles;
66 const auto numOwnedBufferParticles = collectBufferParticles(bufferParticles, particleBuffers, haloParticleBuffers);
67
68 // The following part performs the main remainder traversal.
69
70 // only activate time measurements if it will actually be logged
71#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE
72 autopas::utils::Timer timerBufferBufferBuffer;
73 autopas::utils::Timer timerBufferBufferContainer;
74 autopas::utils::Timer timerBufferContainerContainer;
75 timerBufferBufferBuffer.start();
76#endif
77
78 // Step 1: Triwise interactions of all particles in the buffers (owned and halo)
79 remainderHelper3bBufferBufferBufferAoS(bufferParticles, numOwnedBufferParticles, f);
80
81#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE
82 timerBufferBufferBuffer.stop();
83 timerBufferBufferContainer.start();
84#endif
85
86 // Step 2: Triwise interactions of 2 buffer particles with 1 container particle
87 remainderHelper3bBufferBufferContainerAoS(bufferParticles, numOwnedBufferParticles, container, f);
88
89#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE
90 timerBufferBufferContainer.stop();
91 timerBufferContainerContainer.start();
92#endif
93
94 // Step 3: Triwise interactions of 1 buffer particle and 2 container particles
95 remainderHelper3bBufferContainerContainerAoS<newton3>(bufferParticles, numOwnedBufferParticles, container, f);
96#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE
97 timerBufferContainerContainer.stop();
98#endif
99
100 AutoPasLog(TRACE, "Timer Buffer <-> Buffer <-> Buffer : {}", timerBufferBufferBuffer.getTotalTime());
101 AutoPasLog(TRACE, "Timer Buffer <-> Buffer <-> Container : {}", timerBufferBufferContainer.getTotalTime());
102 AutoPasLog(TRACE, "Timer Buffer <-> Container <-> Container : {}", timerBufferContainerContainer.getTotalTime());
103 }
104
105 private:
109 std::vector<std::vector<std::vector<std::unique_ptr<std::mutex>>>> &_spatialLocks;
110
121 size_t collectBufferParticles(std::vector<Particle_T *> &bufferParticles,
122 std::vector<FullParticleCell<Particle_T>> &particleBuffers,
123 std::vector<FullParticleCell<Particle_T>> &haloParticleBuffers) {
124 // Reserve the needed amount
125 auto cellToVec = [](auto &cell) -> std::vector<Particle_T> & { return cell._particles; };
126
127 const size_t numOwnedBufferParticles =
128 std::transform_reduce(particleBuffers.begin(), particleBuffers.end(), 0, std::plus<>(),
129 [&](auto &vec) { return cellToVec(vec).size(); });
130
131 const size_t numHaloBufferParticles =
132 std::transform_reduce(haloParticleBuffers.begin(), haloParticleBuffers.end(), 0, std::plus<>(),
133 [&](auto &vec) { return cellToVec(vec).size(); });
134
135 bufferParticles.reserve(numOwnedBufferParticles + numHaloBufferParticles);
136
137 // Collect owned buffer particles
138 for (auto &buffer : particleBuffers) {
139 for (auto &p : buffer._particles) {
140 bufferParticles.push_back(&p);
141 }
142 }
143 // Collect halo buffer particles
144 for (auto &buffer : haloParticleBuffers) {
145 for (auto &p : buffer._particles) {
146 bufferParticles.push_back(&p);
147 }
148 }
149 return numOwnedBufferParticles;
150 }
151
161 template <class TriwiseFunctor>
162 void remainderHelper3bBufferBufferBufferAoS(const std::vector<Particle_T *> &bufferParticles,
163 const size_t numOwnedBufferParticles, TriwiseFunctor *f) {
164 AUTOPAS_OPENMP(parallel for)
165 for (auto i = 0; i < numOwnedBufferParticles; ++i) {
166 Particle_T &p1 = *bufferParticles[i];
167
168 for (auto j = 0; j < bufferParticles.size(); ++j) {
169 if (i == j) continue;
170 Particle_T &p2 = *bufferParticles[j];
171
172 for (auto k = j + 1; k < bufferParticles.size(); ++k) {
173 if (k == i) continue;
174 Particle_T &p3 = *bufferParticles[k];
175
176 f->AoSFunctor(p1, p2, p3, false);
177 }
178 }
179 }
180 }
181
193 template <class ContainerType, class TriwiseFunctor>
194 void remainderHelper3bBufferBufferContainerAoS(const std::vector<Particle_T *> &bufferParticles,
195 size_t numOwnedBufferParticles, ContainerType &container,
196 TriwiseFunctor *f) {
198 using namespace autopas::utils::ArrayMath::literals;
199
200 const auto haloBoxMin = container.getBoxMin() - container.getInteractionLength();
201 const auto interactionLengthInv = 1. / container.getInteractionLength();
202 const double cutoff = container.getCutoff();
203
204 AUTOPAS_OPENMP(parallel for)
205 for (auto i = 0; i < bufferParticles.size(); ++i) {
206 Particle_T &p1 = *bufferParticles[i];
207 const auto min = p1.getR() - cutoff;
208 const auto max = p1.getR() + cutoff;
209
210 for (auto j = 0; j < bufferParticles.size(); ++j) {
211 if (j == i) continue;
212 Particle_T &p2 = *bufferParticles[j];
213 container.forEachInRegion(
214 [&](auto &p3) {
215 const auto lockCoords = static_cast_copy_array<size_t>((p3.getR() - haloBoxMin) * interactionLengthInv);
216 if (i < numOwnedBufferParticles) f->AoSFunctor(p1, p2, p3, false);
217 if (!p3.isHalo() && i < j) {
218 const std::lock_guard<std::mutex> lock(*_spatialLocks[lockCoords[0]][lockCoords[1]][lockCoords[2]]);
219 f->AoSFunctor(p3, p1, p2, false);
220 }
221 },
222 min, max, IteratorBehavior::ownedOrHalo);
223 }
224 }
225 }
226
239 template <bool newton3, class ContainerType, class TriwiseFunctor>
240 void remainderHelper3bBufferContainerContainerAoS(const std::vector<Particle_T *> &bufferParticles,
241 size_t numOwnedBufferParticles, ContainerType &container,
242 TriwiseFunctor *f) {
243 // Todo: parallelize without race conditions - https://github.com/AutoPas/AutoPas/issues/904
245 using namespace autopas::utils::ArrayMath::literals;
246
247 const double cutoff = container.getCutoff();
248 for (auto i = 0; i < bufferParticles.size(); ++i) {
249 Particle_T &p1 = *bufferParticles[i];
250 const auto boxMin = p1.getR() - cutoff;
251 const auto boxMax = p1.getR() + cutoff;
252
253 auto p2Iter = container.getRegionIterator(
254 boxMin, boxMax, IteratorBehavior::ownedOrHalo | IteratorBehavior::forceSequential, std::nullopt);
255 for (; p2Iter.isValid(); ++p2Iter) {
256 Particle_T &p2 = *p2Iter;
257
258 auto p3Iter = p2Iter;
259 ++p3Iter;
260
261 for (; p3Iter.isValid(); ++p3Iter) {
262 Particle_T &p3 = *p3Iter;
263
264 if constexpr (newton3) {
265 f->AoSFunctor(p1, p2, p3, true);
266 } else {
267 if (i < numOwnedBufferParticles) {
268 f->AoSFunctor(p1, p2, p3, false);
269 }
270 if (p2.isOwned()) {
271 f->AoSFunctor(p2, p1, p3, false);
272 }
273 if (p3.isOwned()) {
274 f->AoSFunctor(p3, p1, p2, false);
275 }
276 }
277 }
278 }
279 }
280 }
281};
282} // namespace autopas
#define AutoPasLog(lvl, fmt,...)
Macro for logging providing common meta information without filename.
Definition: Logger.h:24
#define AUTOPAS_OPENMP(args)
Empty macro to throw away any arguments.
Definition: WrapOpenMP.h:126
This class handles the storage of particles in their full form.
Definition: FullParticleCell.h:26
Handles triwise interactions involving particle buffers (particles not yet inserted into the main con...
Definition: RemainderTriwiseInteractionHandler.h:30
RemainderTriwiseInteractionHandler(std::vector< std::vector< std::vector< std::unique_ptr< std::mutex > > > > &spatialLocks)
Constructor for RemainderTriwiseInteractionHandler.
Definition: RemainderTriwiseInteractionHandler.h:36
void computeRemainderInteractions(TriwiseFunctor *f, ContainerType &container, std::vector< FullParticleCell< Particle_T > > &particleBuffers, std::vector< FullParticleCell< Particle_T > > &haloParticleBuffers)
Performs the interactions ParticleContainer::computeInteractions() did not cover.
Definition: RemainderTriwiseInteractionHandler.h:61
TriwiseFunctor class.
Definition: TriwiseFunctor.h:28
virtual void AoSFunctor(Particle_T &i, Particle_T &j, Particle_T &k, bool newton3)
TriwiseFunctor for arrays of structures (AoS).
Definition: TriwiseFunctor.h:54
Timer class to stop times.
Definition: Timer.h:20
void start()
start the timer.
Definition: Timer.cpp:17
long getTotalTime() const
Get total accumulated time.
Definition: Timer.h:53
long stop()
Stops the timer and returns the time elapsed in nanoseconds since the last call to start.
Definition: Timer.cpp:25
constexpr std::array< T, SIZE > max(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Takes elementwise maximum and returns the result.
Definition: ArrayMath.h:96
constexpr std::array< T, SIZE > min(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Takes elementwise minimum, returns the result.
Definition: ArrayMath.h:62
constexpr std::array< output_t, SIZE > static_cast_copy_array(const std::array< input_t, SIZE > &a)
Creates a new array by performing an element-wise static_cast<>.
Definition: ArrayUtils.h:33
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:32