AutoPas  3.0.0
Loading...
Searching...
No Matches
LeavingParticleCollector.h
Go to the documentation of this file.
1
8#pragma once
9
14#include "autopas/utils/inBox.h"
15
31template <class ContainerType>
32std::array<std::tuple<const std::array<double, 3>, const std::array<double, 3>>, 6> calculateHaloVolumes(
33 const ContainerType &container) {
34 using namespace autopas::utils::ArrayMath::literals;
35
36 const auto upperBoundForMisplacement = container.getVerletSkin() / 2.0;
37 const auto interactionLength = container.getInteractionLength();
38 const auto &boxMin = container.getBoxMin();
39 const auto &boxMax = container.getBoxMax();
40 // Halo extends one interaction length away from the edge of the container. On top of that particles can drift.
41 const auto lowerHaloCorner = boxMin - interactionLength - upperBoundForMisplacement;
42 const auto upperHaloCorner = boxMax + interactionLength + upperBoundForMisplacement;
43 // We need to extend these boundaries into the container because we need to include cells that still hold particles,
44 // which now have left the cells region towards the outside of the container.
45 // travelled beyond that and skin can be 0.
46 const auto lowerInnerCorner = boxMin + upperBoundForMisplacement;
47 const auto upperInnerCorner = boxMax - upperBoundForMisplacement;
48
49 // volumes describing the halo regions on the six faces of the cuboid shaped container.
50 // The total volume can be thought of as:
51 // 6 faces
52 // 8 corners
53 // 12 edges
54 // These 26 pieces are combined to six volumes, the minimal number to cover it with region iterators.
55 const std::array<std::tuple<decltype(lowerHaloCorner), decltype(upperHaloCorner)>, 6> haloVolumes{{
56 // left face + edge shared by left and bottom faces
57 {{lowerHaloCorner[0], lowerInnerCorner[1], lowerHaloCorner[2]},
58 {lowerInnerCorner[0], upperInnerCorner[1], upperInnerCorner[2]}},
59 // right face + edge shared by right and upper faces
60 {{upperInnerCorner[0], lowerInnerCorner[1], lowerInnerCorner[2]},
61 {upperHaloCorner[0], upperInnerCorner[1], upperHaloCorner[2]}},
62 // top face + edge shared by left and top faces
63 {{lowerHaloCorner[0], lowerInnerCorner[1], upperInnerCorner[2]},
64 {upperInnerCorner[0], upperInnerCorner[1], upperHaloCorner[2]}},
65 // bottom face + edge shared by right and bottom faces
66 {{lowerInnerCorner[0], lowerInnerCorner[1], lowerHaloCorner[2]},
67 {upperHaloCorner[0], upperInnerCorner[1], lowerInnerCorner[2]}},
68 // front face with the all adjacent four edges and four corners
69 {lowerHaloCorner, {upperHaloCorner[0], lowerInnerCorner[1], upperHaloCorner[2]}},
70 // back face with the all adjacent four edges and four corners
71 {{lowerHaloCorner[0], upperInnerCorner[1], lowerHaloCorner[2]}, upperHaloCorner},
72 }};
73
74 return haloVolumes;
75}
76
84template <class ContainerType>
85std::vector<typename ContainerType::ParticleType> collectParticlesAndMarkNonOwnedAsDummy(ContainerType &container) {
86 const auto haloVolumes = calculateHaloVolumes(container);
87
88 std::vector<typename ContainerType::ParticleType> leavingParticles{};
89 // Random number which is better than 0
90 leavingParticles.reserve(10);
91
92 // aliases for less getter accesses
93 const auto &boxMin = container.getBoxMin();
94 const auto &boxMax = container.getBoxMax();
95 // custom openmp reduction to concatenate all local vectors to one at the end of a parallel region
96 AUTOPAS_OPENMP(declare reduction(vecMergeParticle : \
97 std::vector<typename ContainerType::ParticleType> : \
98 omp_out.insert(omp_out.end(), omp_in.begin(), omp_in.end())))
99 // this has to be a `parallel` and not `parallel for` because we are actually interested in parallelizing the inner
100 // loops without having a barrier between outer loop iterations.
101 // The way this works is that all threads iterate the outer loop but due to the way the iterators are parallelized,
102 // each thread only picks its iterations of the inner loops, hence nothing is done multiple times.
103 AUTOPAS_OPENMP(parallel reduction(vecMergeParticle : leavingParticles))
104 for (const auto &[regionStart, regionEnd] : haloVolumes) {
105 for (auto iter = container.getRegionIterator(regionStart, regionEnd, autopas::IteratorBehavior::ownedOrHalo);
106 iter.isValid(); ++iter) {
107 // Mark halo particles for deletion
108 if (iter->isHalo()) {
109 iter->setOwnershipState(OwnershipState::dummy);
110 // Collect leaving particles and mark them for deletion
111 } else if (not utils::inBox(iter->getR(), boxMin, boxMax)) {
112 leavingParticles.push_back(*iter);
113 iter->setOwnershipState(OwnershipState::dummy);
114 }
115 }
116 }
117 return leavingParticles;
118}
119} // namespace autopas::LeavingParticleCollector
#define AUTOPAS_OPENMP(args)
Empty macro to throw away any arguments.
Definition: WrapOpenMP.h:126
Namespace to collect leaving particles from a container.
Definition: LeavingParticleCollector.h:19
std::array< std::tuple< const std::array< double, 3 >, const std::array< double, 3 > >, 6 > calculateHaloVolumes(const ContainerType &container)
For a given container that supports getCutoff(), getBoxMin() and getBoxMax(), calculates a set of 6 n...
Definition: LeavingParticleCollector.h:32
std::vector< typename ContainerType::ParticleType > collectParticlesAndMarkNonOwnedAsDummy(ContainerType &container)
Collects leaving particles and marks halo particles as dummy.
Definition: LeavingParticleCollector.h:85
bool inBox(const std::array< T, 3 > &position, const std::array< T, 3 > &low, const std::array< T, 3 > &high)
Checks if position is inside of a box defined by low and high.
Definition: inBox.h:26
@ dummy
Dummy or deleted state, a particle with this state is not an actual particle!