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
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 // TraceTimers are only active with log level TRACE
71 autopas::utils::TraceTimer timerBufferBufferBuffer;
72 autopas::utils::TraceTimer timerBufferBufferContainer;
73 autopas::utils::TraceTimer timerBufferContainerContainer;
74 timerBufferBufferBuffer.start();
75
76 // Step 1: Triwise interactions of all particles in the buffers (owned and halo)
77 remainderHelper3bBufferBufferBufferAoS(bufferParticles, numOwnedBufferParticles, f);
78
79 timerBufferBufferBuffer.stop();
80 timerBufferBufferContainer.start();
81
82 // Step 2: Triwise interactions of 2 buffer particles with 1 container particle
83 remainderHelper3bBufferBufferContainerAoS(bufferParticles, numOwnedBufferParticles, container, f);
84
85 timerBufferBufferContainer.stop();
86 timerBufferContainerContainer.start();
87
88 // Step 3: Triwise interactions of 1 buffer particle and 2 container particles
89 remainderHelper3bBufferContainerContainerAoS<newton3>(bufferParticles, numOwnedBufferParticles, container, f);
90 timerBufferContainerContainer.stop();
91
92 AutoPasLog(TRACE, "Timer Buffer <-> Buffer <-> Buffer : {}", timerBufferBufferBuffer.getTotalTime());
93 AutoPasLog(TRACE, "Timer Buffer <-> Buffer <-> Container : {}", timerBufferBufferContainer.getTotalTime());
94 AutoPasLog(TRACE, "Timer Buffer <-> Container <-> Container : {}", timerBufferContainerContainer.getTotalTime());
95 }
96
97 private:
101 std::vector<std::vector<std::vector<std::unique_ptr<std::mutex>>>> &_spatialLocks;
102
113 size_t collectBufferParticles(std::vector<Particle_T *> &bufferParticles,
114 std::vector<FullParticleCell<Particle_T>> &particleBuffers,
115 std::vector<FullParticleCell<Particle_T>> &haloParticleBuffers) {
116 // Reserve the needed amount
117 auto cellToVec = [](auto &cell) -> std::vector<Particle_T> & { return cell._particles; };
118
119 const size_t numOwnedBufferParticles =
120 std::transform_reduce(particleBuffers.begin(), particleBuffers.end(), 0, std::plus<>(),
121 [&](auto &vec) { return cellToVec(vec).size(); });
122
123 const size_t numHaloBufferParticles =
124 std::transform_reduce(haloParticleBuffers.begin(), haloParticleBuffers.end(), 0, std::plus<>(),
125 [&](auto &vec) { return cellToVec(vec).size(); });
126
127 bufferParticles.reserve(numOwnedBufferParticles + numHaloBufferParticles);
128
129 // Collect owned buffer particles
130 for (auto &buffer : particleBuffers) {
131 for (auto &p : buffer._particles) {
132 bufferParticles.push_back(&p);
133 }
134 }
135 // Collect halo buffer particles
136 for (auto &buffer : haloParticleBuffers) {
137 for (auto &p : buffer._particles) {
138 bufferParticles.push_back(&p);
139 }
140 }
141 return numOwnedBufferParticles;
142 }
143
153 template <class TriwiseFunctor>
154 void remainderHelper3bBufferBufferBufferAoS(const std::vector<Particle_T *> &bufferParticles,
155 const size_t numOwnedBufferParticles, TriwiseFunctor *f) {
156 AUTOPAS_OPENMP(parallel for)
157 for (auto i = 0; i < numOwnedBufferParticles; ++i) {
158 Particle_T &p1 = *bufferParticles[i];
159
160 for (auto j = 0; j < bufferParticles.size(); ++j) {
161 if (i == j) continue;
162 Particle_T &p2 = *bufferParticles[j];
163
164 for (auto k = j + 1; k < bufferParticles.size(); ++k) {
165 if (k == i) continue;
166 Particle_T &p3 = *bufferParticles[k];
167
168 f->AoSFunctor(p1, p2, p3, false);
169 }
170 }
171 }
172 }
173
185 template <class ContainerType, class TriwiseFunctor>
186 void remainderHelper3bBufferBufferContainerAoS(const std::vector<Particle_T *> &bufferParticles,
187 size_t numOwnedBufferParticles, ContainerType &container,
188 TriwiseFunctor *f) {
190 using namespace autopas::utils::ArrayMath::literals;
191
192 const auto haloBoxMin = container.getBoxMin() - container.getInteractionLength();
193 const auto interactionLengthInv = 1. / container.getInteractionLength();
194 const double cutoff = container.getCutoff();
195
196 AUTOPAS_OPENMP(parallel for)
197 for (auto i = 0; i < bufferParticles.size(); ++i) {
198 Particle_T &p1 = *bufferParticles[i];
199 const auto min = p1.getR() - cutoff;
200 const auto max = p1.getR() + cutoff;
201
202 for (auto j = 0; j < bufferParticles.size(); ++j) {
203 if (j == i) continue;
204 Particle_T &p2 = *bufferParticles[j];
205 container.forEachInRegion(
206 [&](auto &p3) {
207 const auto lockCoords = static_cast_copy_array<size_t>((p3.getR() - haloBoxMin) * interactionLengthInv);
208 if (i < numOwnedBufferParticles) f->AoSFunctor(p1, p2, p3, false);
209 if (!p3.isHalo() && i < j) {
210 const std::lock_guard<std::mutex> lock(*_spatialLocks[lockCoords[0]][lockCoords[1]][lockCoords[2]]);
211 f->AoSFunctor(p3, p1, p2, false);
212 }
213 },
214 min, max, IteratorBehavior::ownedOrHalo);
215 }
216 }
217 }
218
231 template <bool newton3, class ContainerType, class TriwiseFunctor>
232 void remainderHelper3bBufferContainerContainerAoS(const std::vector<Particle_T *> &bufferParticles,
233 size_t numOwnedBufferParticles, ContainerType &container,
234 TriwiseFunctor *f) {
235 // Todo: parallelize without race conditions - https://github.com/AutoPas/AutoPas/issues/904
237 using namespace autopas::utils::ArrayMath::literals;
238
239 const double cutoff = container.getCutoff();
240 for (auto i = 0; i < bufferParticles.size(); ++i) {
241 Particle_T &p1 = *bufferParticles[i];
242 const auto boxMin = p1.getR() - cutoff;
243 const auto boxMax = p1.getR() + cutoff;
244
245 auto p2Iter = container.getRegionIterator(
246 boxMin, boxMax, IteratorBehavior::ownedOrHalo | IteratorBehavior::forceSequential, std::nullopt);
247 for (; p2Iter.isValid(); ++p2Iter) {
248 Particle_T &p2 = *p2Iter;
249
250 auto p3Iter = p2Iter;
251 ++p3Iter;
252
253 for (; p3Iter.isValid(); ++p3Iter) {
254 Particle_T &p3 = *p3Iter;
255
256 if constexpr (newton3) {
257 f->AoSFunctor(p1, p2, p3, true);
258 } else {
259 if (i < numOwnedBufferParticles) {
260 f->AoSFunctor(p1, p2, p3, false);
261 }
262 if (p2.isOwned()) {
263 f->AoSFunctor(p2, p1, p3, false);
264 }
265 if (p3.isOwned()) {
266 f->AoSFunctor(p3, p1, p2, false);
267 }
268 }
269 }
270 }
271 }
272 }
273};
274} // 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
A wrapper around autopas::utils::Timer that only compiles implementation logic if the SPDLOG_ACTIVE_L...
Definition: TraceTimer.h:20
long getTotalTime() const
Get total accumulated time.
Definition: TraceTimer.h:63
void start()
start the timer.
Definition: TraceTimer.h:25
long stop()
Stops the timer and returns the time elapsed in nanoseconds since the last call to start.
Definition: TraceTimer.h:34
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