AutoPas  3.0.0
Loading...
Searching...
No Matches
SPHCalcDensityFunctor.h
Go to the documentation of this file.
1
7#pragma once
8
9#include "SPHKernels.h"
12
13namespace sphLib {
19template <class Particle_T>
20class SPHCalcDensityFunctor : public autopas::PairwiseFunctor<Particle_T, SPHCalcDensityFunctor<Particle_T>> {
21 public:
23 using SoAArraysType = typename Particle_T::SoAArraysType;
24
25 SPHCalcDensityFunctor() : autopas::PairwiseFunctor<Particle_T, SPHCalcDensityFunctor<Particle_T>>(0.){};
26
27 virtual std::string getName() override { return "SPHDensityFunctor"; }
28
29 bool isRelevantForTuning() override { return true; }
30
31 bool allowsNewton3() override { return true; }
32
33 bool allowsNonNewton3() override { return true; }
34
43 inline void AoSFunctor(Particle_T &i, Particle_T &j, bool newton3 = true) override {
44 using namespace autopas::utils::ArrayMath::literals;
45
46 if (i.isDummy() or j.isDummy()) {
47 return;
48 }
49 const std::array<double, 3> dr = j.getR() - i.getR(); // ep_j[j].pos - ep_i[i].pos;
50 const double density =
51 j.getMass() * SPHKernels::W(dr, i.getSmoothingLength()); // ep_j[j].mass * W(dr, ep_i[i].smth)
52 i.addDensity(density);
53 if (newton3) {
54 // Newton 3:
55 // W is symmetric in dr, so no -dr needed, i.e. we can reuse dr
56 const double density2 = i.getMass() * SPHKernels::W(dr, j.getSmoothingLength());
57 j.addDensity(density2);
58 }
59 }
60
65 static unsigned long getNumFlopsPerKernelCall() {
66 unsigned long flops = 0;
67 flops += 3; // calculating dr
68 flops += 2 * SPHKernels::getFlopsW(); // flops for calling W
69 flops += 2 * 1; // calculating density
70 flops += 2 * 1; // adding density
71 return flops;
72 }
73
78 void SoAFunctorSingle(autopas::SoAView<SoAArraysType> soa, bool newton3) override {
79 if (soa.size() == 0) return;
80
81 double *const __restrict xptr = soa.template begin<Particle_T::AttributeNames::posX>();
82 double *const __restrict yptr = soa.template begin<Particle_T::AttributeNames::posY>();
83 double *const __restrict zptr = soa.template begin<Particle_T::AttributeNames::posZ>();
84
85 double *const __restrict densityptr = soa.template begin<Particle_T::AttributeNames::density>();
86 double *const __restrict smthptr = soa.template begin<Particle_T::AttributeNames::smth>();
87 double *const __restrict massptr = soa.template begin<Particle_T::AttributeNames::mass>();
88
89 const auto *const __restrict ownedStatePtr = soa.template begin<Particle_T::AttributeNames::ownershipState>();
90
91 size_t numParticles = soa.size();
92 for (unsigned int i = 0; i < numParticles; ++i) {
93 // checks whether particle i is owned.
94 if (ownedStatePtr[i] == autopas::OwnershipState::dummy) {
95 continue;
96 }
97
98 double densacc = 0.;
99// icpc vectorizes this.
100// g++ only with -ffast-math or -funsafe-math-optimizations
101#pragma omp simd reduction(+ : densacc)
102 for (unsigned int j = i + 1; j < numParticles; ++j) {
103 const double drx = xptr[i] - xptr[j];
104 const double dry = yptr[i] - yptr[j];
105 const double drz = zptr[i] - zptr[j];
106
107 const double drx2 = drx * drx;
108 const double dry2 = dry * dry;
109 const double drz2 = drz * drz;
110
111 const double dr2 = drx2 + dry2 + drz2;
112
113 // if second particle is a dummy, we skip the interaction.
114 const bool mask = ownedStatePtr[j] != autopas::OwnershipState::dummy;
115
116 const double density = mask ? massptr[j] * SPHKernels::W(dr2, smthptr[i]) : 0.;
117 densacc += density;
118
119 // Newton 3:
120 // W is symmetric in dr, so no -dr needed, i.e. we can reuse dr
121 const double density2 = mask ? massptr[i] * SPHKernels::W(dr2, smthptr[j]) : 0.;
122 densityptr[j] += density2;
123 }
124
125 densityptr[i] += densacc;
126 }
127 }
128
133 bool newton3) override {
134 if (soa1.size() == 0 || soa2.size() == 0) return;
135
136 double *const __restrict xptr1 = soa1.template begin<Particle_T::AttributeNames::posX>();
137 double *const __restrict yptr1 = soa1.template begin<Particle_T::AttributeNames::posY>();
138 double *const __restrict zptr1 = soa1.template begin<Particle_T::AttributeNames::posZ>();
139
140 double *const __restrict densityptr1 = soa1.template begin<Particle_T::AttributeNames::density>();
141 double *const __restrict smthptr1 = soa1.template begin<Particle_T::AttributeNames::smth>();
142 double *const __restrict massptr1 = soa1.template begin<Particle_T::AttributeNames::mass>();
143
144 double *const __restrict xptr2 = soa2.template begin<Particle_T::AttributeNames::posX>();
145 double *const __restrict yptr2 = soa2.template begin<Particle_T::AttributeNames::posY>();
146 double *const __restrict zptr2 = soa2.template begin<Particle_T::AttributeNames::posZ>();
147
148 double *const __restrict densityptr2 = soa2.template begin<Particle_T::AttributeNames::density>();
149 double *const __restrict smthptr2 = soa2.template begin<Particle_T::AttributeNames::smth>();
150 double *const __restrict massptr2 = soa2.template begin<Particle_T::AttributeNames::mass>();
151
152 const auto *const __restrict ownedStatePtr1 = soa1.template begin<Particle_T::AttributeNames::ownershipState>();
153 const auto *const __restrict ownedStatePtr2 = soa2.template begin<Particle_T::AttributeNames::ownershipState>();
154
155 size_t numParticlesi = soa1.size();
156 for (unsigned int i = 0; i < numParticlesi; ++i) {
157 // checks whether particle i is in the domain box, unused if calculateGlobals is false!
158 if (ownedStatePtr1[i] == autopas::OwnershipState::dummy) {
159 continue;
160 }
161
162 double densacc = 0.;
163 size_t numParticlesj = soa2.size();
164// icpc vectorizes this.
165// g++ only with -ffast-math or -funsafe-math-optimizations
166#pragma omp simd reduction(+ : densacc)
167 for (unsigned int j = 0; j < numParticlesj; ++j) {
168 const double drx = xptr1[i] - xptr2[j];
169 const double dry = yptr1[i] - yptr2[j];
170 const double drz = zptr1[i] - zptr2[j];
171
172 const double drx2 = drx * drx;
173 const double dry2 = dry * dry;
174 const double drz2 = drz * drz;
175
176 const double dr2 = drx2 + dry2 + drz2;
177
178 // if second particle is a dummy, we skip the interaction.
179 const bool mask = ownedStatePtr2[j] != autopas::OwnershipState::dummy;
180
181 const double density = mask ? massptr2[j] * SPHKernels::W(dr2, smthptr1[i]) : 0.;
182 densacc += density;
183 if (newton3) {
184 // Newton 3:
185 // W is symmetric in dr, so no -dr needed, i.e. we can reuse dr
186 const double density2 = mask ? massptr1[i] * SPHKernels::W(dr2, smthptr2[j]) : 0.;
187 densityptr2[j] += density2;
188 }
189 }
190
191 densityptr1[i] += densacc;
192 }
193 }
194
195 // clang-format off
199 // clang-format on
200 void SoAFunctorVerlet(autopas::SoAView<SoAArraysType> soa, const size_t indexFirst,
201 const std::vector<size_t, autopas::AlignedAllocator<size_t>> &neighborList,
202 bool newton3) override {
203 if (soa.size() == 0) return;
204
205 const auto *const __restrict ownedStatePtr = soa.template begin<Particle_T::AttributeNames::ownershipState>();
206
207 // checks whether particle i is owned.
208 if (ownedStatePtr[indexFirst] == autopas::OwnershipState::dummy) {
209 return;
210 }
211
212 double *const __restrict xptr = soa.template begin<Particle_T::AttributeNames::posX>();
213 double *const __restrict yptr = soa.template begin<Particle_T::AttributeNames::posY>();
214 double *const __restrict zptr = soa.template begin<Particle_T::AttributeNames::posZ>();
215
216 double *const __restrict densityptr = soa.template begin<Particle_T::AttributeNames::density>();
217 double *const __restrict smthptr = soa.template begin<Particle_T::AttributeNames::smth>();
218 double *const __restrict massptr = soa.template begin<Particle_T::AttributeNames::mass>();
219
220 double densacc = 0;
221 const auto &currentList = neighborList;
222 size_t listSize = currentList.size();
223// icpc vectorizes this.
224// g++ only with -ffast-math or -funsafe-math-optimizations
225#pragma omp simd reduction(+ : densacc)
226 for (unsigned int j = 0; j < listSize; ++j) {
227 const double drx = xptr[indexFirst] - xptr[currentList[j]];
228 const double dry = yptr[indexFirst] - yptr[currentList[j]];
229 const double drz = zptr[indexFirst] - zptr[currentList[j]];
230
231 const double drx2 = drx * drx;
232 const double dry2 = dry * dry;
233 const double drz2 = drz * drz;
234
235 const double dr2 = drx2 + dry2 + drz2;
236
237 // if second particle is a dummy, we skip the interaction.
238 const bool mask = ownedStatePtr[currentList[j]] != autopas::OwnershipState::dummy;
239
240 const double density = mask ? massptr[currentList[j]] * SPHKernels::W(dr2, smthptr[indexFirst]) : 0.;
241 densacc += density;
242 if (newton3) {
243 // Newton 3:
244 // W is symmetric in dr, so no -dr needed, i.e. we can reuse dr
245 const double density2 = mask ? massptr[indexFirst] * SPHKernels::W(dr2, smthptr[currentList[j]]) : 0.;
246 densityptr[currentList[j]] += density2;
247 }
248 }
249
250 densityptr[indexFirst] += densacc;
251 }
252
256 constexpr static auto getNeededAttr() {
257 return std::array<typename Particle_T::AttributeNames, 7>{
258 Particle_T::AttributeNames::mass, Particle_T::AttributeNames::posX,
259 Particle_T::AttributeNames::posY, Particle_T::AttributeNames::posZ,
260 Particle_T::AttributeNames::smth, Particle_T::AttributeNames::density,
261 Particle_T::AttributeNames::ownershipState};
262 }
263
267 constexpr static auto getNeededAttr(std::false_type) {
268 return std::array<typename Particle_T::AttributeNames, 6>{
269 Particle_T::AttributeNames::mass, Particle_T::AttributeNames::posX, Particle_T::AttributeNames::posY,
270 Particle_T::AttributeNames::posZ, Particle_T::AttributeNames::smth, Particle_T::AttributeNames::ownershipState};
271 }
272
276 constexpr static auto getComputedAttr() {
277 return std::array<typename Particle_T::AttributeNames, 1>{Particle_T::AttributeNames::density};
278 }
279};
280} // namespace sphLib
AlignedAllocator class.
Definition: AlignedAllocator.h:29
PairwiseFunctor class.
Definition: PairwiseFunctor.h:31
PairwiseFunctor(double cutoff)
Constructor.
Definition: PairwiseFunctor.h:42
View on a fixed part of a SoA between a start index and an end index.
Definition: SoAView.h:23
size_t size() const
Returns the number of particles in the view.
Definition: SoAView.h:83
Class that defines the density functor.
Definition: SPHCalcDensityFunctor.h:20
bool isRelevantForTuning() override
Specifies whether the functor should be considered for the auto-tuning process.
Definition: SPHCalcDensityFunctor.h:29
bool allowsNewton3() override
Specifies whether the functor is capable of Newton3-like functors.
Definition: SPHCalcDensityFunctor.h:31
void SoAFunctorSingle(autopas::SoAView< SoAArraysType > soa, bool newton3) override
PairwiseFunctor for structure of arrays (SoA)
Definition: SPHCalcDensityFunctor.h:78
void SoAFunctorVerlet(autopas::SoAView< SoAArraysType > soa, const size_t indexFirst, const std::vector< size_t, autopas::AlignedAllocator< size_t > > &neighborList, bool newton3) override
PairwiseFunctor for structure of arrays (SoA) for neighbor lists.
Definition: SPHCalcDensityFunctor.h:200
static constexpr auto getComputedAttr()
Get attributes computed by this functor.
Definition: SPHCalcDensityFunctor.h:276
virtual std::string getName() override
Returns name of functor.
Definition: SPHCalcDensityFunctor.h:27
static constexpr auto getNeededAttr(std::false_type)
Get attributes needed for computation without N3 optimization.
Definition: SPHCalcDensityFunctor.h:267
typename Particle_T::SoAArraysType SoAArraysType
soa arrays type
Definition: SPHCalcDensityFunctor.h:23
void SoAFunctorPair(autopas::SoAView< SoAArraysType > soa1, autopas::SoAView< SoAArraysType > soa2, bool newton3) override
PairwiseFunctor for structure of arrays (SoA)
Definition: SPHCalcDensityFunctor.h:132
static constexpr auto getNeededAttr()
Get attributes needed for computation.
Definition: SPHCalcDensityFunctor.h:256
bool allowsNonNewton3() override
Specifies whether the functor is capable of non-Newton3-like functors.
Definition: SPHCalcDensityFunctor.h:33
static unsigned long getNumFlopsPerKernelCall()
Get the number of floating point operations used in one full kernel call.
Definition: SPHCalcDensityFunctor.h:65
void AoSFunctor(Particle_T &i, Particle_T &j, bool newton3=true) override
Calculates the density contribution of the interaction of particle i and j.
Definition: SPHCalcDensityFunctor.h:43
static unsigned long getFlopsW()
returns the flops for one full calculation of the kernel
Definition: SPHKernels.cpp:11
static double W(const std::array< double, 3 > &dr, const double h)
A kernel function for SPH simulations.
Definition: SPHKernels.h:37
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:32
@ dummy
Dummy or deleted state, a particle with this state is not an actual particle!