44template <
class Particle_T,
bool applyShift =
false,
bool useMixing =
false,
46 bool countFLOPs =
false,
bool relevantForTuning =
true>
49 calculateGlobals, relevantForTuning, countFLOPs>> {
53 using SoAArraysType =
typename Particle_T::SoAArraysType;
58 using SoAFloatPrecision =
typename Particle_T::ParticleSoAFloatPrecision;
63 const double _cutoffSquared;
83 const std::vector<std::array<double, 3>> _sitePositionsLJ{};
93 double _potentialEnergySum;
98 std::array<double, 3> _virialSum;
119 calculateGlobals, relevantForTuning, countFLOPs>>(
121 _cutoffSquared{cutoff * cutoff},
122 _potentialEnergySum{0.},
123 _virialSum{0., 0., 0.},
125 _postProcessed{false} {
126 if constexpr (calculateGlobals) {
129 if constexpr (countFLOPs) {
130 AutoPasLog(DEBUG,
"FLOP counting is enabled but is not supported for multi-site functors yet!");
141 static_assert(not useMixing,
142 "Mixing without a ParticlePropertiesLibrary is not possible! Use a different constructor or set "
144 AutoPasLog(WARN,
"Using LJMultisiteFunctor with mixing disabled is untested!");
156 static_assert(useMixing,
157 "Not using Mixing but using a ParticlePropertiesLibrary is not allowed! Use a different constructor "
158 "or set mixing to true.");
159 _PPLibrary = &particlePropertiesLibrary;
162 std::string
getName() final {
return "LJMultisiteFunctor"; }
167 return useNewton3 == autopas::FunctorN3Modes::Newton3Only or useNewton3 == autopas::FunctorN3Modes::Both;
171 return useNewton3 == autopas::FunctorN3Modes::Newton3Off or useNewton3 == autopas::FunctorN3Modes::Both;
181 void AoSFunctor(Particle_T &particleA, Particle_T &particleB,
bool newton3)
final {
182 using namespace autopas::utils::ArrayMath::literals;
183 if (particleA.isDummy() or particleB.isDummy()) {
191 if (distanceSquaredCoM > _cutoffSquared) {
196 const size_t numSitesA = useMixing ? _PPLibrary->
getNumSites(particleA.getTypeId()) : _sitePositionsLJ.size();
197 const size_t numSitesB = useMixing ? _PPLibrary->
getNumSites(particleB.getTypeId()) : _sitePositionsLJ.size();
200 const std::vector<size_t> siteIdsA =
201 useMixing ? _PPLibrary->
getSiteTypes(particleA.getTypeId()) : std::vector<unsigned long>();
202 const std::vector<size_t> siteIdsB =
203 useMixing ? _PPLibrary->
getSiteTypes(particleB.getTypeId()) : std::vector<unsigned long>();
206 const std::vector<std::array<double, 3>> unrotatedSitePositionsA =
207 useMixing ? _PPLibrary->
getSitePositions(particleA.getTypeId()) : _sitePositionsLJ;
208 const std::vector<std::array<double, 3>> unrotatedSitePositionsB =
209 useMixing ? _PPLibrary->
getSitePositions(particleB.getTypeId()) : _sitePositionsLJ;
212 const auto rotatedSitePositionsA =
214 const auto rotatedSitePositionsB =
217 for (
int i = 0; i < numSitesA; i++) {
218 for (
int j = 0; j < numSitesB; j++) {
223 const auto sigmaSquared =
225 const auto epsilon24 = useMixing ? _PPLibrary->
getMixing24Epsilon(siteIdsA[i], siteIdsB[j]) : _epsilon24;
227 applyShift ? (useMixing ? _PPLibrary->
getMixingShift6(siteIdsA[i], siteIdsB[j]) : _shift6) : 0;
234 const auto invDistSquared = 1. / distanceSquared;
235 const auto lj2 = sigmaSquared * invDistSquared;
236 const auto lj6 = lj2 * lj2 * lj2;
237 const auto lj12 = lj6 * lj6;
238 const auto lj12m6 = lj12 - lj6;
239 const auto scalarMultiple = epsilon24 * (lj12 + lj12m6) * invDistSquared;
243 particleA.addF(force);
245 particleB.subF(force);
254 if (calculateGlobals) {
257 const auto potentialEnergy6 = epsilon24 * lj12m6 + shift6;
258 const auto virial = displacement * force;
262 if (particleA.isOwned()) {
263 _aosThreadData[threadNum].potentialEnergySum += potentialEnergy6;
264 _aosThreadData[threadNum].virialSum += virial;
267 if (newton3 and particleB.isOwned()) {
268 _aosThreadData[threadNum].potentialEnergySum += potentialEnergy6;
269 _aosThreadData[threadNum].virialSum += virial;
282 if (soa.size() == 0)
return;
284 const auto *
const __restrict xptr = soa.template begin<Particle_T::AttributeNames::posX>();
285 const auto *
const __restrict yptr = soa.template begin<Particle_T::AttributeNames::posY>();
286 const auto *
const __restrict zptr = soa.template begin<Particle_T::AttributeNames::posZ>();
288 const auto *
const __restrict ownedStatePtr = soa.template begin<Particle_T::AttributeNames::ownershipState>();
290 const auto *
const __restrict q0ptr = soa.template begin<Particle_T::AttributeNames::quaternion0>();
291 const auto *
const __restrict q1ptr = soa.template begin<Particle_T::AttributeNames::quaternion1>();
292 const auto *
const __restrict q2ptr = soa.template begin<Particle_T::AttributeNames::quaternion2>();
293 const auto *
const __restrict q3ptr = soa.template begin<Particle_T::AttributeNames::quaternion3>();
295 SoAFloatPrecision *
const __restrict fxptr = soa.template begin<Particle_T::AttributeNames::forceX>();
296 SoAFloatPrecision *
const __restrict fyptr = soa.template begin<Particle_T::AttributeNames::forceY>();
297 SoAFloatPrecision *
const __restrict fzptr = soa.template begin<Particle_T::AttributeNames::forceZ>();
299 SoAFloatPrecision *
const __restrict txptr = soa.template begin<Particle_T::AttributeNames::torqueX>();
300 SoAFloatPrecision *
const __restrict typtr = soa.template begin<Particle_T::AttributeNames::torqueY>();
301 SoAFloatPrecision *
const __restrict tzptr = soa.template begin<Particle_T::AttributeNames::torqueZ>();
303 [[maybe_unused]]
auto *
const __restrict typeptr = soa.template begin<Particle_T::AttributeNames::typeId>();
305 SoAFloatPrecision potentialEnergySum = 0.;
306 SoAFloatPrecision virialSumX = 0.;
307 SoAFloatPrecision virialSumY = 0.;
308 SoAFloatPrecision virialSumZ = 0.;
311 const SoAFloatPrecision cutoffSquared = _cutoffSquared;
313 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> sigmaSquareds;
314 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> epsilon24s;
315 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> shift6s;
317 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionX;
318 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionY;
319 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionZ;
322 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceX;
323 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceY;
324 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceZ;
326 std::vector<size_t, autopas::AlignedAllocator<size_t>> siteTypes;
327 std::vector<char, autopas::AlignedAllocator<char>> isSiteOwned;
329 const SoAFloatPrecision const_sigmaSquared = _sigmaSquared;
330 const SoAFloatPrecision const_epsilon24 = _epsilon24;
331 const SoAFloatPrecision const_shift6 = _shift6;
333 const auto const_unrotatedSitePositions = _sitePositionsLJ;
336 size_t siteCount = 0;
337 if constexpr (useMixing) {
338 for (
size_t mol = 0; mol < soa.size(); ++mol) {
339 siteCount += _PPLibrary->
getNumSites(typeptr[mol]);
342 siteCount = const_unrotatedSitePositions.size() * soa.size();
346 exactSitePositionX.reserve(siteCount);
347 exactSitePositionY.reserve(siteCount);
348 exactSitePositionZ.reserve(siteCount);
350 if constexpr (useMixing) {
351 siteTypes.reserve(siteCount);
354 siteForceX.reserve((siteCount));
355 siteForceY.reserve((siteCount));
356 siteForceZ.reserve((siteCount));
358 if constexpr (calculateGlobals) {
360 isSiteOwned.reserve(siteCount);
364 if constexpr (useMixing) {
365 size_t siteIndex = 0;
366 for (
size_t mol = 0; mol < soa.size(); ++mol) {
368 {q0ptr[mol], q1ptr[mol], q2ptr[mol], q3ptr[mol]}, _PPLibrary->
getSitePositions(typeptr[mol]));
369 const auto siteTypesOfMol = _PPLibrary->
getSiteTypes(typeptr[mol]);
371 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptr[mol]); ++site) {
372 exactSitePositionX[siteIndex] = rotatedSitePositions[site][0] + xptr[mol];
373 exactSitePositionY[siteIndex] = rotatedSitePositions[site][1] + yptr[mol];
374 exactSitePositionZ[siteIndex] = rotatedSitePositions[site][2] + zptr[mol];
375 siteTypes[siteIndex] = siteTypesOfMol[site];
376 siteForceX[siteIndex] = 0.;
377 siteForceY[siteIndex] = 0.;
378 siteForceZ[siteIndex] = 0.;
379 if (calculateGlobals) {
386 size_t siteIndex = 0;
387 for (
size_t mol = 0; mol < soa.size(); mol++) {
389 {q0ptr[mol], q1ptr[mol], q2ptr[mol], q3ptr[mol]}, const_unrotatedSitePositions);
390 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
391 exactSitePositionX[siteIndex] = rotatedSitePositions[site][0] + xptr[mol];
392 exactSitePositionY[siteIndex] = rotatedSitePositions[site][1] + yptr[mol];
393 exactSitePositionZ[siteIndex] = rotatedSitePositions[site][2] + zptr[mol];
394 siteForceX[siteIndex] = 0.;
395 siteForceY[siteIndex] = 0.;
396 siteForceZ[siteIndex] = 0.;
397 if (calculateGlobals) {
406 size_t siteIndexMolA = 0;
407 for (
size_t molA = 0; molA < soa.size(); ++molA) {
408 const size_t noSitesInMolA = useMixing ? _PPLibrary->
getNumSites(typeptr[molA])
409 : const_unrotatedSitePositions.size();
411 const auto ownedStateA = ownedStatePtr[molA];
413 siteIndexMolA += noSitesInMolA;
417 const size_t siteIndexMolB = siteIndexMolA + noSitesInMolA;
418 const size_t noSitesB = (siteCount - siteIndexMolB);
421 std::vector<char, autopas::AlignedAllocator<char>> molMask;
422 molMask.reserve(soa.size() - (molA + 1));
425 for (
size_t molB = molA + 1; molB < soa.size(); ++molB) {
426 const auto ownedStateB = ownedStatePtr[molB];
428 const auto displacementCoMX = xptr[molA] - xptr[molB];
429 const auto displacementCoMY = yptr[molA] - yptr[molB];
430 const auto displacementCoMZ = zptr[molA] - zptr[molB];
432 const auto distanceSquaredCoMX = displacementCoMX * displacementCoMX;
433 const auto distanceSquaredCoMY = displacementCoMY * displacementCoMY;
434 const auto distanceSquaredCoMZ = displacementCoMZ * displacementCoMZ;
436 const auto distanceSquaredCoM = distanceSquaredCoMX + distanceSquaredCoMY + distanceSquaredCoMZ;
439 molMask[molB - (molA + 1)] =
444 std::vector<char, autopas::AlignedAllocator<char>> siteMask;
445 siteMask.reserve(noSitesB);
447 for (
size_t molB = molA + 1; molB < soa.size(); ++molB) {
448 for (
size_t siteB = 0; siteB < _PPLibrary->
getNumSites(typeptr[molB]); ++siteB) {
449 siteMask.emplace_back(molMask[molB - (molA + 1)]);
454 for (
size_t siteA = siteIndexMolA; siteA < siteIndexMolB; ++siteA) {
457 sigmaSquareds.reserve(noSitesB);
458 epsilon24s.reserve(noSitesB);
459 if constexpr (applyShift) {
460 shift6s.reserve(noSitesB);
463 for (
size_t siteB = 0; siteB < siteCount - (siteIndexMolB); ++siteB) {
464 const auto mixingData = _PPLibrary->
getLJMixingData(siteTypes[siteA], siteTypes[siteIndexMolB + siteB]);
465 sigmaSquareds[siteB] = mixingData.sigmaSquared;
466 epsilon24s[siteB] = mixingData.epsilon24;
468 shift6s[siteB] = mixingData.shift6;
473 SoAFloatPrecision forceSumX = 0.;
474 SoAFloatPrecision forceSumY = 0.;
475 SoAFloatPrecision forceSumZ = 0.;
476 SoAFloatPrecision torqueSumX = 0.;
477 SoAFloatPrecision torqueSumY = 0.;
478 SoAFloatPrecision torqueSumZ = 0.;
480#pragma omp simd reduction (+ : forceSumX, forceSumY, forceSumZ, torqueSumX, torqueSumY, torqueSumZ, potentialEnergySum, virialSumX, virialSumY, virialSumZ)
481 for (
size_t siteB = 0; siteB < noSitesB; ++siteB) {
482 const size_t globalSiteBIndex = siteB + siteIndexMolB;
484 const SoAFloatPrecision sigmaSquared = useMixing ? sigmaSquareds[siteB] : const_sigmaSquared;
485 const SoAFloatPrecision epsilon24 = useMixing ? epsilon24s[siteB] : const_epsilon24;
486 const SoAFloatPrecision shift6 = applyShift ? (useMixing ? shift6s[siteB] : const_shift6) : 0;
488 const auto isSiteBOwned = !calculateGlobals || isSiteOwned[globalSiteBIndex];
490 const auto displacementX = exactSitePositionX[siteA] - exactSitePositionX[globalSiteBIndex];
491 const auto displacementY = exactSitePositionY[siteA] - exactSitePositionY[globalSiteBIndex];
492 const auto displacementZ = exactSitePositionZ[siteA] - exactSitePositionZ[globalSiteBIndex];
494 const auto distanceSquaredX = displacementX * displacementX;
495 const auto distanceSquaredY = displacementY * displacementY;
496 const auto distanceSquaredZ = displacementZ * displacementZ;
498 const auto distanceSquared = distanceSquaredX + distanceSquaredY + distanceSquaredZ;
500 const auto invDistSquared = 1. / distanceSquared;
501 const auto lj2 = sigmaSquared * invDistSquared;
502 const auto lj6 = lj2 * lj2 * lj2;
503 const auto lj12 = lj6 * lj6;
504 const auto lj12m6 = lj12 - lj6;
505 const auto scalarMultiple = siteMask[siteB] ? epsilon24 * (lj12 + lj12m6) * invDistSquared : 0.;
508 const auto forceX = scalarMultiple * displacementX;
509 const auto forceY = scalarMultiple * displacementY;
510 const auto forceZ = scalarMultiple * displacementZ;
517 siteForceX[globalSiteBIndex] -= forceX;
518 siteForceY[globalSiteBIndex] -= forceY;
519 siteForceZ[globalSiteBIndex] -= forceZ;
521 if constexpr (calculateGlobals) {
522 const auto virialX = displacementX * forceX;
523 const auto virialY = displacementY * forceY;
524 const auto virialZ = displacementZ * forceZ;
525 const auto potentialEnergy6 = siteMask[siteB] ? (epsilon24 * lj12m6 + shift6) : 0.;
529 const auto ownershipMask =
531 potentialEnergySum += potentialEnergy6 * ownershipMask;
532 virialSumX += virialX * ownershipMask;
533 virialSumY += virialY * ownershipMask;
534 virialSumZ += virialZ * ownershipMask;
538 siteForceX[siteA] += forceSumX;
539 siteForceY[siteA] += forceSumY;
540 siteForceZ[siteA] += forceSumZ;
542 siteIndexMolA += noSitesInMolA;
546 if constexpr (useMixing) {
547 size_t siteIndex = 0;
548 for (
size_t mol = 0; mol < soa.size(); ++mol) {
550 {q0ptr[mol], q1ptr[mol], q2ptr[mol], q3ptr[mol]}, _PPLibrary->
getSitePositions(typeptr[mol]));
551 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptr[mol]); ++site) {
552 fxptr[mol] += siteForceX[siteIndex];
553 fyptr[mol] += siteForceY[siteIndex];
554 fzptr[mol] += siteForceZ[siteIndex];
555 txptr[mol] += rotatedSitePositions[site][1] * siteForceZ[siteIndex] -
556 rotatedSitePositions[site][2] * siteForceY[siteIndex];
557 typtr[mol] += rotatedSitePositions[site][2] * siteForceX[siteIndex] -
558 rotatedSitePositions[site][0] * siteForceZ[siteIndex];
559 tzptr[mol] += rotatedSitePositions[site][0] * siteForceY[siteIndex] -
560 rotatedSitePositions[site][1] * siteForceX[siteIndex];
565 size_t siteIndex = 0;
566 for (
size_t mol = 0; mol < soa.size(); mol++) {
568 {q0ptr[mol], q1ptr[mol], q2ptr[mol], q3ptr[mol]}, const_unrotatedSitePositions);
569 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
570 fxptr[mol] += siteForceX[siteIndex];
571 fyptr[mol] += siteForceY[siteIndex];
572 fzptr[mol] += siteForceZ[siteIndex];
573 txptr[mol] += rotatedSitePositions[site][1] * siteForceZ[siteIndex] -
574 rotatedSitePositions[site][2] * siteForceY[siteIndex];
575 typtr[mol] += rotatedSitePositions[site][2] * siteForceX[siteIndex] -
576 rotatedSitePositions[site][0] * siteForceZ[siteIndex];
577 tzptr[mol] += rotatedSitePositions[site][0] * siteForceY[siteIndex] -
578 rotatedSitePositions[site][1] * siteForceX[siteIndex];
584 if constexpr (calculateGlobals) {
587 _aosThreadData[threadNum].potentialEnergySum += potentialEnergySum;
588 _aosThreadData[threadNum].virialSum[0] += virialSumX;
589 _aosThreadData[threadNum].virialSum[1] += virialSumY;
590 _aosThreadData[threadNum].virialSum[2] += virialSumZ;
597 const bool newton3)
final {
599 SoAFunctorPairImpl<true>(soa1, soa2);
601 SoAFunctorPairImpl<false>(soa1, soa2);
612 bool newton3)
final {
613 if (soa.size() == 0 or neighborList.empty())
return;
615 SoAFunctorVerletImpl<true>(soa, indexFirst, neighborList);
617 SoAFunctorVerletImpl<false>(soa, indexFirst, neighborList);
630 std::vector<std::array<SoAFloatPrecision, 3>> sitePositionsLJ) {
631 _epsilon24 = epsilon24;
632 _sigmaSquared = sigmaSquared;
638 _sitePositionsLJ = sitePositionsLJ;
645 return std::array<typename Particle_T::AttributeNames, 16>{
646 Particle_T::AttributeNames::id, Particle_T::AttributeNames::posX,
647 Particle_T::AttributeNames::posY, Particle_T::AttributeNames::posZ,
648 Particle_T::AttributeNames::forceX, Particle_T::AttributeNames::forceY,
649 Particle_T::AttributeNames::forceZ, Particle_T::AttributeNames::quaternion0,
650 Particle_T::AttributeNames::quaternion1, Particle_T::AttributeNames::quaternion2,
651 Particle_T::AttributeNames::quaternion3, Particle_T::AttributeNames::torqueX,
652 Particle_T::AttributeNames::torqueY, Particle_T::AttributeNames::torqueZ,
653 Particle_T::AttributeNames::typeId, Particle_T::AttributeNames::ownershipState};
660 return std::array<typename Particle_T::AttributeNames, 16>{
661 Particle_T::AttributeNames::id, Particle_T::AttributeNames::posX,
662 Particle_T::AttributeNames::posY, Particle_T::AttributeNames::posZ,
663 Particle_T::AttributeNames::forceX, Particle_T::AttributeNames::forceY,
664 Particle_T::AttributeNames::forceZ, Particle_T::AttributeNames::quaternion0,
665 Particle_T::AttributeNames::quaternion1, Particle_T::AttributeNames::quaternion2,
666 Particle_T::AttributeNames::quaternion3, Particle_T::AttributeNames::torqueX,
667 Particle_T::AttributeNames::torqueY, Particle_T::AttributeNames::torqueZ,
668 Particle_T::AttributeNames::typeId, Particle_T::AttributeNames::ownershipState};
675 return std::array<typename Particle_T::AttributeNames, 6>{
676 Particle_T::AttributeNames::forceX, Particle_T::AttributeNames::forceY, Particle_T::AttributeNames::forceZ,
677 Particle_T::AttributeNames::torqueX, Particle_T::AttributeNames::torqueY, Particle_T::AttributeNames::torqueZ};
704 const unsigned long siteToSiteFlops = newton3 ? 33ul : 26ul;
713 _potentialEnergySum = 0;
714 _virialSum = {0., 0., 0.};
715 _postProcessed =
false;
716 for (
size_t i = 0; i < _aosThreadData.size(); i++) {
717 _aosThreadData[i].setZero();
726 using namespace autopas::utils::ArrayMath::literals;
728 if (_postProcessed) {
730 "Already postprocessed, endTraversal(bool newton3) was called twice without calling initTraversal().");
732 if (calculateGlobals) {
733 for (
size_t i = 0; i < _aosThreadData.size(); ++i) {
734 _potentialEnergySum += _aosThreadData[i].potentialEnergySum;
735 _virialSum += _aosThreadData[i].virialSum;
740 _potentialEnergySum *= 0.5;
744 _potentialEnergySum /= 6.;
745 _postProcessed =
true;
747 AutoPasLog(DEBUG,
"Final potential energy {}", _potentialEnergySum);
748 AutoPasLog(DEBUG,
"Final virial {}", _virialSum[0] + _virialSum[1] + _virialSum[2]);
758 if (not calculateGlobals) {
760 "Trying to get potential energy even though calculateGlobals is false. If you want this functor to calculate "
762 "values, please specify calculateGlobals to be true.");
764 if (not _postProcessed) {
766 "Cannot get potential energy, because endTraversal was not called.");
768 return _potentialEnergySum;
776 if (not calculateGlobals) {
778 "Trying to get virial even though calculateGlobals is false. If you want this functor to calculate global "
779 "values, please specify calculateGlobals to be true.");
781 if (not _postProcessed) {
783 "Cannot get virial, because endTraversal was not called.");
785 return _virialSum[0] + _virialSum[1] + _virialSum[2];
795 template <
bool newton3>
797 if (soaA.
size() == 0 || soaB.
size() == 0)
return;
799 const auto *
const __restrict xAptr = soaA.template begin<Particle_T::AttributeNames::posX>();
800 const auto *
const __restrict yAptr = soaA.template begin<Particle_T::AttributeNames::posY>();
801 const auto *
const __restrict zAptr = soaA.template begin<Particle_T::AttributeNames::posZ>();
802 const auto *
const __restrict xBptr = soaB.template begin<Particle_T::AttributeNames::posX>();
803 const auto *
const __restrict yBptr = soaB.template begin<Particle_T::AttributeNames::posY>();
804 const auto *
const __restrict zBptr = soaB.template begin<Particle_T::AttributeNames::posZ>();
806 const auto *
const __restrict ownedStatePtrA = soaA.template begin<Particle_T::AttributeNames::ownershipState>();
807 const auto *
const __restrict ownedStatePtrB = soaB.template begin<Particle_T::AttributeNames::ownershipState>();
809 const auto *
const __restrict q0Aptr = soaA.template begin<Particle_T::AttributeNames::quaternion0>();
810 const auto *
const __restrict q1Aptr = soaA.template begin<Particle_T::AttributeNames::quaternion1>();
811 const auto *
const __restrict q2Aptr = soaA.template begin<Particle_T::AttributeNames::quaternion2>();
812 const auto *
const __restrict q3Aptr = soaA.template begin<Particle_T::AttributeNames::quaternion3>();
813 const auto *
const __restrict q0Bptr = soaB.template begin<Particle_T::AttributeNames::quaternion0>();
814 const auto *
const __restrict q1Bptr = soaB.template begin<Particle_T::AttributeNames::quaternion1>();
815 const auto *
const __restrict q2Bptr = soaB.template begin<Particle_T::AttributeNames::quaternion2>();
816 const auto *
const __restrict q3Bptr = soaB.template begin<Particle_T::AttributeNames::quaternion3>();
818 SoAFloatPrecision *
const __restrict fxAptr = soaA.template begin<Particle_T::AttributeNames::forceX>();
819 SoAFloatPrecision *
const __restrict fyAptr = soaA.template begin<Particle_T::AttributeNames::forceY>();
820 SoAFloatPrecision *
const __restrict fzAptr = soaA.template begin<Particle_T::AttributeNames::forceZ>();
821 SoAFloatPrecision *
const __restrict fxBptr = soaB.template begin<Particle_T::AttributeNames::forceX>();
822 SoAFloatPrecision *
const __restrict fyBptr = soaB.template begin<Particle_T::AttributeNames::forceY>();
823 SoAFloatPrecision *
const __restrict fzBptr = soaB.template begin<Particle_T::AttributeNames::forceZ>();
825 SoAFloatPrecision *
const __restrict txAptr = soaA.template begin<Particle_T::AttributeNames::torqueX>();
826 SoAFloatPrecision *
const __restrict tyAptr = soaA.template begin<Particle_T::AttributeNames::torqueY>();
827 SoAFloatPrecision *
const __restrict tzAptr = soaA.template begin<Particle_T::AttributeNames::torqueZ>();
828 SoAFloatPrecision *
const __restrict txBptr = soaB.template begin<Particle_T::AttributeNames::torqueX>();
829 SoAFloatPrecision *
const __restrict tyBptr = soaB.template begin<Particle_T::AttributeNames::torqueY>();
830 SoAFloatPrecision *
const __restrict tzBptr = soaB.template begin<Particle_T::AttributeNames::torqueZ>();
832 [[maybe_unused]]
auto *
const __restrict typeptrA = soaA.template begin<Particle_T::AttributeNames::typeId>();
833 [[maybe_unused]]
auto *
const __restrict typeptrB = soaB.template begin<Particle_T::AttributeNames::typeId>();
835 SoAFloatPrecision potentialEnergySum = 0.;
836 SoAFloatPrecision virialSumX = 0.;
837 SoAFloatPrecision virialSumY = 0.;
838 SoAFloatPrecision virialSumZ = 0.;
841 const SoAFloatPrecision cutoffSquared = _cutoffSquared;
843 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> sigmaSquareds;
844 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> epsilon24s;
845 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> shift6s;
847 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionBx;
848 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionBy;
849 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionBz;
852 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceBx;
853 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceBy;
854 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceBz;
856 std::vector<size_t, autopas::AlignedAllocator<size_t>> siteTypesB;
857 std::vector<char, autopas::AlignedAllocator<char>> isSiteOwnedBArr;
859 const SoAFloatPrecision const_sigmaSquared = _sigmaSquared;
860 const SoAFloatPrecision const_epsilon24 = _epsilon24;
861 const SoAFloatPrecision const_shift6 = _shift6;
863 const auto const_unrotatedSitePositions = _sitePositionsLJ;
866 size_t siteCountB = 0;
867 if constexpr (useMixing) {
868 for (
size_t mol = 0; mol < soaB.
size(); ++mol) {
869 siteCountB += _PPLibrary->
getNumSites(typeptrB[mol]);
872 siteCountB = const_unrotatedSitePositions.size() * soaB.
size();
876 exactSitePositionBx.reserve(siteCountB);
877 exactSitePositionBy.reserve(siteCountB);
878 exactSitePositionBz.reserve(siteCountB);
880 if constexpr (useMixing) {
881 siteTypesB.reserve(siteCountB);
884 siteForceBx.reserve(siteCountB);
885 siteForceBy.reserve(siteCountB);
886 siteForceBz.reserve(siteCountB);
888 if constexpr (calculateGlobals) {
890 isSiteOwnedBArr.reserve(siteCountB);
893 if constexpr (useMixing) {
894 siteTypesB.reserve(siteCountB);
895 sigmaSquareds.reserve(siteCountB);
896 epsilon24s.reserve(siteCountB);
897 if constexpr (applyShift) {
898 shift6s.reserve(siteCountB);
903 if constexpr (useMixing) {
904 size_t siteIndex = 0;
905 for (
size_t mol = 0; mol < soaB.
size(); ++mol) {
907 {q0Bptr[mol], q1Bptr[mol], q2Bptr[mol], q3Bptr[mol]}, _PPLibrary->
getSitePositions(typeptrB[mol]));
908 const auto siteTypesOfMol = _PPLibrary->
getSiteTypes(typeptrB[mol]);
910 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptrB[mol]); ++site) {
911 exactSitePositionBx[siteIndex] = rotatedSitePositions[site][0] + xBptr[mol];
912 exactSitePositionBy[siteIndex] = rotatedSitePositions[site][1] + yBptr[mol];
913 exactSitePositionBz[siteIndex] = rotatedSitePositions[site][2] + zBptr[mol];
914 siteTypesB[siteIndex] = siteTypesOfMol[site];
915 siteForceBx[siteIndex] = 0.;
916 siteForceBy[siteIndex] = 0.;
917 siteForceBz[siteIndex] = 0.;
918 if (calculateGlobals) {
925 size_t siteIndex = 0;
926 for (
size_t mol = 0; mol < soaB.
size(); mol++) {
928 {q0Bptr[mol], q1Bptr[mol], q2Bptr[mol], q3Bptr[mol]}, const_unrotatedSitePositions);
929 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
930 exactSitePositionBx[siteIndex] = rotatedSitePositions[site][0] + xBptr[mol];
931 exactSitePositionBy[siteIndex] = rotatedSitePositions[site][1] + yBptr[mol];
932 exactSitePositionBz[siteIndex] = rotatedSitePositions[site][2] + zBptr[mol];
933 siteForceBx[siteIndex] = 0.;
934 siteForceBy[siteIndex] = 0.;
935 siteForceBz[siteIndex] = 0.;
936 if (calculateGlobals) {
945 for (
size_t molA = 0; molA < soaA.
size(); ++molA) {
946 const auto ownedStateA = ownedStatePtrA[molA];
951 const auto noSitesInMolA =
952 useMixing ? _PPLibrary->
getNumSites(typeptrA[molA]) : const_unrotatedSitePositions.size();
953 const auto unrotatedSitePositionsA =
954 useMixing ? _PPLibrary->
getSitePositions(typeptrA[molA]) : const_unrotatedSitePositions;
957 {q0Aptr[molA], q1Aptr[molA], q2Aptr[molA], q3Aptr[molA]}, unrotatedSitePositionsA);
960 std::vector<char, autopas::AlignedAllocator<char>> molMask;
961 molMask.reserve(soaB.
size());
964 for (
size_t molB = 0; molB < soaB.
size(); ++molB) {
965 const auto ownedStateB = ownedStatePtrB[molB];
967 const auto displacementCoMX = xAptr[molA] - xBptr[molB];
968 const auto displacementCoMY = yAptr[molA] - yBptr[molB];
969 const auto displacementCoMZ = zAptr[molA] - zBptr[molB];
971 const auto distanceSquaredCoMX = displacementCoMX * displacementCoMX;
972 const auto distanceSquaredCoMY = displacementCoMY * displacementCoMY;
973 const auto distanceSquaredCoMZ = displacementCoMZ * displacementCoMZ;
975 const auto distanceSquaredCoM = distanceSquaredCoMX + distanceSquaredCoMY + distanceSquaredCoMZ;
982 std::vector<char, autopas::AlignedAllocator<char>> siteMask;
983 siteMask.reserve(siteCountB);
985 for (
size_t molB = 0; molB < soaB.
size(); ++molB) {
986 for (
size_t siteB = 0; siteB < _PPLibrary->
getNumSites(typeptrB[molB]); ++siteB) {
987 siteMask.emplace_back(molMask[molB]);
992 SoAFloatPrecision forceSumX = 0.;
993 SoAFloatPrecision forceSumY = 0.;
994 SoAFloatPrecision forceSumZ = 0.;
995 SoAFloatPrecision torqueSumX = 0.;
996 SoAFloatPrecision torqueSumY = 0.;
997 SoAFloatPrecision torqueSumZ = 0.;
999 for (
size_t siteA = 0; siteA < noSitesInMolA; ++siteA) {
1002 for (
size_t siteB = 0; siteB < siteCountB; ++siteB) {
1003 const auto mixingData =
1005 sigmaSquareds[siteB] = mixingData.sigmaSquared;
1006 epsilon24s[siteB] = mixingData.epsilon24;
1008 shift6s[siteB] = mixingData.shift6;
1013 const auto rotatedSitePositionAx = rotatedSitePositionsA[siteA][0];
1014 const auto rotatedSitePositionAy = rotatedSitePositionsA[siteA][1];
1015 const auto rotatedSitePositionAz = rotatedSitePositionsA[siteA][2];
1017 const auto exactSitePositionAx = rotatedSitePositionAx + xAptr[molA];
1018 const auto exactSitePositionAy = rotatedSitePositionAy + yAptr[molA];
1019 const auto exactSitePositionAz = rotatedSitePositionAz + zAptr[molA];
1021#pragma omp simd reduction (+ : forceSumX, forceSumY, forceSumZ, torqueSumX, torqueSumY, torqueSumZ, potentialEnergySum, virialSumX, virialSumY, virialSumZ)
1022 for (
size_t siteB = 0; siteB < siteCountB; ++siteB) {
1023 const SoAFloatPrecision sigmaSquared = useMixing ? sigmaSquareds[siteB] : const_sigmaSquared;
1024 const SoAFloatPrecision epsilon24 = useMixing ? epsilon24s[siteB] : const_epsilon24;
1025 const SoAFloatPrecision shift6 = applyShift ? (useMixing ? shift6s[siteB] : const_shift6) : 0;
1027 const auto isSiteOwnedB = !calculateGlobals || isSiteOwnedBArr[siteB];
1029 const auto displacementX = exactSitePositionAx - exactSitePositionBx[siteB];
1030 const auto displacementY = exactSitePositionAy - exactSitePositionBy[siteB];
1031 const auto displacementZ = exactSitePositionAz - exactSitePositionBz[siteB];
1033 const auto distanceSquaredX = displacementX * displacementX;
1034 const auto distanceSquaredY = displacementY * displacementY;
1035 const auto distanceSquaredZ = displacementZ * displacementZ;
1037 const auto distanceSquared = distanceSquaredX + distanceSquaredY + distanceSquaredZ;
1039 const auto invDistSquared = 1. / distanceSquared;
1040 const auto lj2 = sigmaSquared * invDistSquared;
1041 const auto lj6 = lj2 * lj2 * lj2;
1042 const auto lj12 = lj6 * lj6;
1043 const auto lj12m6 = lj12 - lj6;
1044 const auto scalarMultiple = siteMask[siteB] ? epsilon24 * (lj12 + lj12m6) * invDistSquared : 0.;
1047 const auto forceX = scalarMultiple * displacementX;
1048 const auto forceY = scalarMultiple * displacementY;
1049 const auto forceZ = scalarMultiple * displacementZ;
1051 forceSumX += forceX;
1052 forceSumY += forceY;
1053 forceSumZ += forceZ;
1055 torqueSumX += rotatedSitePositionAy * forceZ - rotatedSitePositionAz * forceY;
1056 torqueSumY += rotatedSitePositionAz * forceX - rotatedSitePositionAx * forceZ;
1057 torqueSumZ += rotatedSitePositionAx * forceY - rotatedSitePositionAy * forceX;
1060 if constexpr (newton3) {
1061 siteForceBx[siteB] -= forceX;
1062 siteForceBy[siteB] -= forceY;
1063 siteForceBz[siteB] -= forceZ;
1067 if constexpr (calculateGlobals) {
1068 const auto potentialEnergy6 = siteMask[siteB] ? (epsilon24 * lj12m6 + shift6) : 0.;
1069 const auto virialX = displacementX * forceX;
1070 const auto virialY = displacementY * forceY;
1071 const auto virialZ = displacementZ * forceZ;
1075 const auto ownershipFactor =
1078 potentialEnergySum += potentialEnergy6 * ownershipFactor;
1079 virialSumX += virialX * ownershipFactor;
1080 virialSumY += virialY * ownershipFactor;
1081 virialSumZ += virialZ * ownershipFactor;
1085 fxAptr[molA] += forceSumX;
1086 fyAptr[molA] += forceSumY;
1087 fzAptr[molA] += forceSumZ;
1088 txAptr[molA] += torqueSumX;
1089 tyAptr[molA] += torqueSumY;
1090 tzAptr[molA] += torqueSumZ;
1094 if constexpr (useMixing) {
1095 size_t siteIndex = 0;
1096 for (
size_t mol = 0; mol < soaB.
size(); ++mol) {
1098 {q0Bptr[mol], q1Bptr[mol], q2Bptr[mol], q3Bptr[mol]}, _PPLibrary->
getSitePositions(typeptrB[mol]));
1099 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptrB[mol]); ++site) {
1100 fxBptr[mol] += siteForceBx[siteIndex];
1101 fyBptr[mol] += siteForceBy[siteIndex];
1102 fzBptr[mol] += siteForceBz[siteIndex];
1103 txBptr[mol] += rotatedSitePositions[site][1] * siteForceBz[siteIndex] -
1104 rotatedSitePositions[site][2] * siteForceBy[siteIndex];
1105 tyBptr[mol] += rotatedSitePositions[site][2] * siteForceBx[siteIndex] -
1106 rotatedSitePositions[site][0] * siteForceBz[siteIndex];
1107 tzBptr[mol] += rotatedSitePositions[site][0] * siteForceBy[siteIndex] -
1108 rotatedSitePositions[site][1] * siteForceBx[siteIndex];
1113 size_t siteIndex = 0;
1114 for (
size_t mol = 0; mol < soaB.
size(); ++mol) {
1116 {q0Bptr[mol], q1Bptr[mol], q2Bptr[mol], q3Bptr[mol]}, const_unrotatedSitePositions);
1117 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
1118 fxBptr[mol] += siteForceBx[siteIndex];
1119 fyBptr[mol] += siteForceBy[siteIndex];
1120 fzBptr[mol] += siteForceBz[siteIndex];
1121 txBptr[mol] += rotatedSitePositions[site][1] * siteForceBz[siteIndex] -
1122 rotatedSitePositions[site][2] * siteForceBy[siteIndex];
1123 tyBptr[mol] += rotatedSitePositions[site][2] * siteForceBx[siteIndex] -
1124 rotatedSitePositions[site][0] * siteForceBz[siteIndex];
1125 tzBptr[mol] += rotatedSitePositions[site][0] * siteForceBy[siteIndex] -
1126 rotatedSitePositions[site][1] * siteForceBx[siteIndex];
1131 if constexpr (calculateGlobals) {
1135 _aosThreadData[threadNum].potentialEnergySum += potentialEnergySum;
1136 _aosThreadData[threadNum].virialSum[0] += virialSumX;
1137 _aosThreadData[threadNum].virialSum[1] += virialSumY;
1138 _aosThreadData[threadNum].virialSum[2] += virialSumZ;
1142 template <
bool newton3>
1145 const auto *
const __restrict ownedStatePtr = soa.template begin<Particle_T::AttributeNames::ownershipState>();
1148 const auto ownedStatePrime = ownedStatePtr[indexPrime];
1153 const auto *
const __restrict xptr = soa.template begin<Particle_T::AttributeNames::posX>();
1154 const auto *
const __restrict yptr = soa.template begin<Particle_T::AttributeNames::posY>();
1155 const auto *
const __restrict zptr = soa.template begin<Particle_T::AttributeNames::posZ>();
1157 const auto *
const __restrict q0ptr = soa.template begin<Particle_T::AttributeNames::quaternion0>();
1158 const auto *
const __restrict q1ptr = soa.template begin<Particle_T::AttributeNames::quaternion1>();
1159 const auto *
const __restrict q2ptr = soa.template begin<Particle_T::AttributeNames::quaternion2>();
1160 const auto *
const __restrict q3ptr = soa.template begin<Particle_T::AttributeNames::quaternion3>();
1162 SoAFloatPrecision *
const __restrict fxptr = soa.template begin<Particle_T::AttributeNames::forceX>();
1163 SoAFloatPrecision *
const __restrict fyptr = soa.template begin<Particle_T::AttributeNames::forceY>();
1164 SoAFloatPrecision *
const __restrict fzptr = soa.template begin<Particle_T::AttributeNames::forceZ>();
1166 SoAFloatPrecision *
const __restrict txptr = soa.template begin<Particle_T::AttributeNames::torqueX>();
1167 SoAFloatPrecision *
const __restrict typtr = soa.template begin<Particle_T::AttributeNames::torqueY>();
1168 SoAFloatPrecision *
const __restrict tzptr = soa.template begin<Particle_T::AttributeNames::torqueZ>();
1170 [[maybe_unused]]
auto *
const __restrict typeptr = soa.template begin<Particle_T::AttributeNames::typeId>();
1172 SoAFloatPrecision potentialEnergySum = 0.;
1173 SoAFloatPrecision virialSumX = 0.;
1174 SoAFloatPrecision virialSumY = 0.;
1175 SoAFloatPrecision virialSumZ = 0.;
1178 const SoAFloatPrecision cutoffSquared = _cutoffSquared;
1179 const auto const_unrotatedSitePositions = _sitePositionsLJ;
1181 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> sigmaSquareds;
1182 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> epsilon24s;
1183 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> shift6s;
1185 const auto const_sigmaSquared = _sigmaSquared;
1186 const auto const_epsilon24 = _epsilon24;
1187 const auto const_shift6 = _shift6;
1189 const size_t neighborListSize = neighborList.size();
1190 const size_t *
const __restrict neighborListPtr = neighborList.data();
1193 const size_t siteCountMolPrime =
1194 useMixing ? _PPLibrary->
getNumSites(typeptr[indexPrime]) : const_unrotatedSitePositions.size();
1196 size_t siteCountNeighbors = 0;
1197 if constexpr (useMixing) {
1198 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1199 siteCountNeighbors += _PPLibrary->
getNumSites(typeptr[neighborList[neighborMol]]);
1202 siteCountNeighbors = const_unrotatedSitePositions.size() * neighborListSize;
1206 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactNeighborSitePositionX;
1207 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactNeighborSitePositionY;
1208 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactNeighborSitePositionZ;
1210 std::vector<size_t, autopas::AlignedAllocator<size_t>> siteTypesNeighbors;
1211 std::vector<char, autopas::AlignedAllocator<char>> isNeighborSiteOwnedArr;
1214 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceX;
1215 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceY;
1216 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceZ;
1219 exactNeighborSitePositionX.reserve(siteCountNeighbors);
1220 exactNeighborSitePositionY.reserve(siteCountNeighbors);
1221 exactNeighborSitePositionZ.reserve(siteCountNeighbors);
1223 if constexpr (useMixing) {
1224 siteTypesNeighbors.reserve(siteCountNeighbors);
1227 siteForceX.reserve(siteCountNeighbors);
1228 siteForceY.reserve(siteCountNeighbors);
1229 siteForceZ.reserve(siteCountNeighbors);
1231 if constexpr (calculateGlobals) {
1232 isNeighborSiteOwnedArr.reserve(siteCountNeighbors);
1235 if constexpr (useMixing) {
1236 sigmaSquareds.reserve(siteCountNeighbors);
1237 epsilon24s.reserve(siteCountNeighbors);
1238 if constexpr (applyShift) {
1239 shift6s.reserve(siteCountNeighbors);
1243 const auto rotatedSitePositionsPrime =
1245 {q0ptr[indexPrime], q1ptr[indexPrime], q2ptr[indexPrime], q3ptr[indexPrime]},
1248 {q0ptr[indexPrime], q1ptr[indexPrime], q2ptr[indexPrime], q3ptr[indexPrime]},
1249 const_unrotatedSitePositions);
1251 const auto siteTypesPrime = _PPLibrary->
getSiteTypes(typeptr[indexPrime]);
1254 if constexpr (useMixing) {
1255 size_t siteIndex = 0;
1256 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1257 const auto neighborMolIndex = neighborList[neighborMol];
1259 {q0ptr[neighborMolIndex], q1ptr[neighborMolIndex], q2ptr[neighborMolIndex], q3ptr[neighborMolIndex]},
1261 const auto siteTypesOfMol = _PPLibrary->
getSiteTypes(typeptr[neighborMolIndex]);
1263 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptr[neighborMolIndex]); ++site) {
1264 exactNeighborSitePositionX[siteIndex] = rotatedSitePositions[site][0] + xptr[neighborMolIndex];
1265 exactNeighborSitePositionY[siteIndex] = rotatedSitePositions[site][1] + yptr[neighborMolIndex];
1266 exactNeighborSitePositionZ[siteIndex] = rotatedSitePositions[site][2] + zptr[neighborMolIndex];
1267 siteTypesNeighbors[siteIndex] = siteTypesOfMol[site];
1268 siteForceX[siteIndex] = 0.;
1269 siteForceY[siteIndex] = 0.;
1270 siteForceZ[siteIndex] = 0.;
1271 if (calculateGlobals) {
1278 size_t siteIndex = 0;
1279 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1280 const auto neighborMolIndex = neighborList[neighborMol];
1282 {q0ptr[neighborMolIndex], q1ptr[neighborMolIndex], q2ptr[neighborMolIndex], q3ptr[neighborMolIndex]},
1283 const_unrotatedSitePositions);
1284 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
1285 exactNeighborSitePositionX[siteIndex] = rotatedSitePositions[site][0] + xptr[neighborMolIndex];
1286 exactNeighborSitePositionY[siteIndex] = rotatedSitePositions[site][1] + yptr[neighborMolIndex];
1287 exactNeighborSitePositionZ[siteIndex] = rotatedSitePositions[site][2] + zptr[neighborMolIndex];
1288 siteForceX[siteIndex] = 0.;
1289 siteForceY[siteIndex] = 0.;
1290 siteForceZ[siteIndex] = 0.;
1291 if (calculateGlobals) {
1302 std::vector<char, autopas::AlignedAllocator<char>> molMask;
1303 molMask.reserve(neighborListSize);
1306 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1307 const auto neighborMolIndex = neighborList[neighborMol];
1309 const auto ownedState = ownedStatePtr[neighborMolIndex];
1311 const auto displacementCoMX = xptr[indexPrime] - xptr[neighborMolIndex];
1312 const auto displacementCoMY = yptr[indexPrime] - yptr[neighborMolIndex];
1313 const auto displacementCoMZ = zptr[indexPrime] - zptr[neighborMolIndex];
1315 const auto distanceSquaredCoMX = displacementCoMX * displacementCoMX;
1316 const auto distanceSquaredCoMY = displacementCoMY * displacementCoMY;
1317 const auto distanceSquaredCoMZ = displacementCoMZ * displacementCoMZ;
1319 const auto distanceSquaredCoM = distanceSquaredCoMX + distanceSquaredCoMY + distanceSquaredCoMZ;
1326 std::vector<char, autopas::AlignedAllocator<char>> siteMask;
1327 siteMask.reserve(siteCountNeighbors);
1329 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1330 const auto neighborMolIndex = neighborList[neighborMol];
1331 for (
size_t siteB = 0; siteB < _PPLibrary->
getNumSites(typeptr[neighborMolIndex]); ++siteB) {
1332 siteMask.emplace_back(molMask[neighborMol]);
1337 SoAFloatPrecision forceSumX = 0.;
1338 SoAFloatPrecision forceSumY = 0.;
1339 SoAFloatPrecision forceSumZ = 0.;
1340 SoAFloatPrecision torqueSumX = 0.;
1341 SoAFloatPrecision torqueSumY = 0.;
1342 SoAFloatPrecision torqueSumZ = 0.;
1346 for (
size_t primeSite = 0; primeSite < siteCountMolPrime; ++primeSite) {
1347 const auto rotatedPrimeSitePositionX = rotatedSitePositionsPrime[primeSite][0];
1348 const auto rotatedPrimeSitePositionY = rotatedSitePositionsPrime[primeSite][1];
1349 const auto rotatedPrimeSitePositionZ = rotatedSitePositionsPrime[primeSite][2];
1351 const auto exactPrimeSitePositionX = rotatedPrimeSitePositionX + xptr[indexPrime];
1352 const auto exactPrimeSitePositionY = rotatedPrimeSitePositionY + yptr[indexPrime];
1353 const auto exactPrimeSitePositionZ = rotatedPrimeSitePositionZ + zptr[indexPrime];
1356 if constexpr (useMixing) {
1357 const auto primeSiteType = siteTypesPrime[primeSite];
1359 size_t siteIndex = 0;
1360 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1361 const auto neighborMolIndex = neighborList[neighborMol];
1362 const auto siteTypesOfNeighborMol = _PPLibrary->
getSiteTypes(typeptr[neighborMolIndex]);
1364 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptr[neighborMolIndex]); ++site) {
1365 const auto mixingData = _PPLibrary->
getLJMixingData(primeSiteType, siteTypesOfNeighborMol[site]);
1366 sigmaSquareds[siteIndex] = mixingData.sigmaSquared;
1367 epsilon24s[siteIndex] = mixingData.epsilon24;
1368 if constexpr (applyShift) {
1369 shift6s[siteIndex] = mixingData.shift6;
1376#pragma omp simd reduction(+ : forceSumX, forceSumY, forceSumZ, torqueSumX, torqueSumY, torqueSumZ)
1377 for (
size_t neighborSite = 0; neighborSite < siteCountNeighbors; ++neighborSite) {
1378 const SoAFloatPrecision sigmaSquared = useMixing ? sigmaSquareds[neighborSite] : const_sigmaSquared;
1379 const SoAFloatPrecision epsilon24 = useMixing ? epsilon24s[neighborSite] : const_epsilon24;
1380 const SoAFloatPrecision shift6 = applyShift ? (useMixing ? shift6s[neighborSite] : const_shift6) : 0;
1382 const bool isNeighborSiteOwned = !calculateGlobals || isNeighborSiteOwnedArr[neighborSite];
1384 const auto displacementX = exactPrimeSitePositionX - exactNeighborSitePositionX[neighborSite];
1385 const auto displacementY = exactPrimeSitePositionY - exactNeighborSitePositionY[neighborSite];
1386 const auto displacementZ = exactPrimeSitePositionZ - exactNeighborSitePositionZ[neighborSite];
1388 const auto distanceSquaredX = displacementX * displacementX;
1389 const auto distanceSquaredY = displacementY * displacementY;
1390 const auto distanceSquaredZ = displacementZ * displacementZ;
1392 const auto distanceSquared = distanceSquaredX + distanceSquaredY + distanceSquaredZ;
1394 const auto invDistSquared = 1. / distanceSquared;
1395 const auto lj2 = sigmaSquared * invDistSquared;
1396 const auto lj6 = lj2 * lj2 * lj2;
1397 const auto lj12 = lj6 * lj6;
1398 const auto lj12m6 = lj12 - lj6;
1399 const auto scalarMultiple = siteMask[neighborSite] ? epsilon24 * (lj12 + lj12m6) * invDistSquared : 0.;
1402 const auto forceX = scalarMultiple * displacementX;
1403 const auto forceY = scalarMultiple * displacementY;
1404 const auto forceZ = scalarMultiple * displacementZ;
1406 forceSumX += forceX;
1407 forceSumY += forceY;
1408 forceSumZ += forceZ;
1410 torqueSumX += rotatedPrimeSitePositionY * forceZ - rotatedPrimeSitePositionZ * forceY;
1411 torqueSumY += rotatedPrimeSitePositionZ * forceX - rotatedPrimeSitePositionX * forceZ;
1412 torqueSumZ += rotatedPrimeSitePositionX * forceY - rotatedPrimeSitePositionY * forceX;
1416 siteForceX[neighborSite] -= forceX;
1417 siteForceY[neighborSite] -= forceY;
1418 siteForceZ[neighborSite] -= forceZ;
1422 if constexpr (calculateGlobals) {
1423 const auto potentialEnergy6 = siteMask[neighborSite] ? (epsilon24 * lj12m6 + shift6) : 0.;
1424 const auto virialX = displacementX * forceX;
1425 const auto virialY = displacementY * forceY;
1426 const auto virialZ = displacementZ * forceZ;
1429 const auto ownershipFactor =
1432 potentialEnergySum += potentialEnergy6 * ownershipFactor;
1433 virialSumX += virialX * ownershipFactor;
1434 virialSumY += virialY * ownershipFactor;
1435 virialSumZ += virialZ * ownershipFactor;
1440 fxptr[indexPrime] += forceSumX;
1441 fyptr[indexPrime] += forceSumY;
1442 fzptr[indexPrime] += forceSumZ;
1443 txptr[indexPrime] += torqueSumX;
1444 typtr[indexPrime] += torqueSumY;
1445 tzptr[indexPrime] += torqueSumZ;
1448 if constexpr (newton3) {
1449 if constexpr (useMixing) {
1450 size_t siteIndex = 0;
1451 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1452 const auto neighborMolIndex = neighborList[neighborMol];
1454 {q0ptr[neighborMolIndex], q1ptr[neighborMolIndex], q2ptr[neighborMolIndex], q3ptr[neighborMolIndex]},
1456 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptr[neighborMolIndex]); ++site) {
1457 fxptr[neighborMolIndex] += siteForceX[siteIndex];
1458 fyptr[neighborMolIndex] += siteForceY[siteIndex];
1459 fzptr[neighborMolIndex] += siteForceZ[siteIndex];
1460 txptr[neighborMolIndex] += rotatedSitePositions[site][1] * siteForceZ[siteIndex] -
1461 rotatedSitePositions[site][2] * siteForceY[siteIndex];
1462 typtr[neighborMolIndex] += rotatedSitePositions[site][2] * siteForceX[siteIndex] -
1463 rotatedSitePositions[site][0] * siteForceZ[siteIndex];
1464 tzptr[neighborMolIndex] += rotatedSitePositions[site][0] * siteForceY[siteIndex] -
1465 rotatedSitePositions[site][1] * siteForceX[siteIndex];
1470 size_t siteIndex = 0;
1471 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1472 const auto neighborMolIndex = neighborList[neighborMol];
1474 {q0ptr[neighborMolIndex], q1ptr[neighborMolIndex], q2ptr[neighborMolIndex], q3ptr[neighborMolIndex]},
1475 const_unrotatedSitePositions);
1476 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
1477 fxptr[neighborMolIndex] += siteForceX[siteIndex];
1478 fyptr[neighborMolIndex] += siteForceY[siteIndex];
1479 fzptr[neighborMolIndex] += siteForceZ[siteIndex];
1480 txptr[neighborMolIndex] += rotatedSitePositions[site][1] * siteForceZ[siteIndex] -
1481 rotatedSitePositions[site][2] * siteForceY[siteIndex];
1482 typtr[neighborMolIndex] += rotatedSitePositions[site][2] * siteForceX[siteIndex] -
1483 rotatedSitePositions[site][0] * siteForceZ[siteIndex];
1484 txptr[neighborMolIndex] += rotatedSitePositions[site][0] * siteForceY[siteIndex] -
1485 rotatedSitePositions[site][1] * siteForceX[siteIndex];
1492 if constexpr (calculateGlobals) {
1495 _aosThreadData[threadNum].potentialEnergySum += potentialEnergySum;
1496 _aosThreadData[threadNum].virialSum[0] += virialSumX;
1497 _aosThreadData[threadNum].virialSum[1] += virialSumY;
1498 _aosThreadData[threadNum].virialSum[2] += virialSumZ;
1505 class AoSThreadData {
1507 AoSThreadData() : virialSum{0., 0., 0.}, potentialEnergySum{0.}, __remainingTo64{} {}
1509 virialSum = {0., 0., 0.};
1510 potentialEnergySum = 0.;
1514 std::array<double, 3> virialSum;
1515 double potentialEnergySum;
1519 double __remainingTo64[(64 - 4 *
sizeof(double)) /
sizeof(double)];
1522 static_assert(
sizeof(AoSThreadData) % 64 == 0,
"AoSThreadData has wrong size (should be multiple of 64)");
1527 std::vector<AoSThreadData> _aosThreadData;
#define AutoPasLog(lvl, fmt,...)
Macro for logging providing common meta information without filename.
Definition: Logger.h:24
This class stores the (physical) properties of molecule types, and, in the case of multi-site molecul...
Definition: ParticlePropertiesLibrary.h:28
floatType getMixingShift6(intType i, intType j) const
Returns precomputed mixed shift * 6 for one pair of site types.
Definition: ParticlePropertiesLibrary.h:262
intType getNumSites(intType i) const
Get number of sites of a multi-site molecule.
Definition: ParticlePropertiesLibrary.h:554
std::vector< std::array< floatType, 3 > > getSitePositions(intType i) const
Get relative site positions to a multi-site molecule's center-of-mass.
Definition: ParticlePropertiesLibrary.h:517
floatType getMixingSigmaSquared(intType i, intType j) const
Returns precomputed mixed squared sigma for one pair of site types.
Definition: ParticlePropertiesLibrary.h:252
floatType getMixing24Epsilon(intType i, intType j) const
Returns the precomputed mixed epsilon * 24.
Definition: ParticlePropertiesLibrary.h:224
static double calcShift6(double epsilon24, double sigmaSquared, double cutoffSquared)
Calculate the shift multiplied 6 of the lennard jones potential from given cutoff,...
Definition: ParticlePropertiesLibrary.h:576
auto getLJMixingData(intType i, intType j) const
Get complete mixing data for one pair of LJ site types.
Definition: ParticlePropertiesLibrary.h:234
std::vector< intType > getSiteTypes(intType i) const
Get site types of a multi-site molecule.
Definition: ParticlePropertiesLibrary.h:528
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
Default exception class for autopas exceptions.
Definition: ExceptionHandler.h:116
A functor to handle Lennard-Jones interactions between two Multisite Molecules.
Definition: LJMultisiteFunctor.h:49
void SoAFunctorSingle(autopas::SoAView< SoAArraysType > soa, bool newton3) final
PairwiseFunctor for structure of arrays (SoA)
Definition: LJMultisiteFunctor.h:281
void AoSFunctor(Particle_T &particleA, Particle_T &particleB, bool newton3) final
Functor for arrays of structures (AoS).
Definition: LJMultisiteFunctor.h:181
LJMultisiteFunctor()=delete
Delete Default constructor.
bool isRelevantForTuning() final
Specifies whether the functor should be considered for the auto-tuning process.
Definition: LJMultisiteFunctor.h:164
LJMultisiteFunctor(double cutoff, ParticlePropertiesLibrary< double, size_t > &particlePropertiesLibrary)
Constructor for Functor with particle mixing enabled.
Definition: LJMultisiteFunctor.h:154
LJMultisiteFunctor(double cutoff)
Constructor for Functor with particle mixing disabled.
Definition: LJMultisiteFunctor.h:140
void initTraversal() final
Reset the global values.
Definition: LJMultisiteFunctor.h:712
static constexpr bool getMixing()
Definition: LJMultisiteFunctor.h:683
static constexpr auto getComputedAttr()
Get attributes computed by this functor.
Definition: LJMultisiteFunctor.h:674
void setParticleProperties(SoAFloatPrecision epsilon24, SoAFloatPrecision sigmaSquared, std::vector< std::array< SoAFloatPrecision, 3 > > sitePositionsLJ)
Sets the molecule properties constants for this functor.
Definition: LJMultisiteFunctor.h:629
bool allowsNewton3() final
Specifies whether the functor is capable of Newton3-like functors.
Definition: LJMultisiteFunctor.h:166
bool allowsNonNewton3() final
Specifies whether the functor is capable of non-Newton3-like functors.
Definition: LJMultisiteFunctor.h:170
double getPotentialEnergy()
Get the potential energy.
Definition: LJMultisiteFunctor.h:757
std::string getName() final
Returns name of functor.
Definition: LJMultisiteFunctor.h:162
unsigned long getNumFlopsPerKernelCall(size_t molAType, size_t molBType, bool newton3)
Get the number of flops used per kernel call - i.e.
Definition: LJMultisiteFunctor.h:695
void SoAFunctorPair(autopas::SoAView< SoAArraysType > soa1, autopas::SoAView< SoAArraysType > soa2, const bool newton3) final
PairwiseFunctor for structure of arrays (SoA)
Definition: LJMultisiteFunctor.h:596
static constexpr auto getNeededAttr(std::false_type)
Get attributes needed for computation without N3 optimization.
Definition: LJMultisiteFunctor.h:659
void SoAFunctorVerlet(autopas::SoAView< SoAArraysType > soa, const size_t indexFirst, const std::vector< size_t, autopas::AlignedAllocator< size_t > > &neighborList, bool newton3) final
PairwiseFunctor for structure of arrays (SoA) for neighbor lists.
Definition: LJMultisiteFunctor.h:610
double getVirial()
Get the virial.
Definition: LJMultisiteFunctor.h:775
void endTraversal(bool newton3) final
Postprocesses global values, e.g.
Definition: LJMultisiteFunctor.h:725
static constexpr auto getNeededAttr()
Get attributes needed for computation.
Definition: LJMultisiteFunctor.h:644
constexpr T dot(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Generates the dot product of two arrays.
Definition: ArrayMath.h:233
constexpr std::array< T, SIZE > mulScalar(const std::array< T, SIZE > &a, T s)
Multiplies a scalar s to each element of array a and returns the result.
Definition: ArrayMath.h:181
constexpr std::array< T, SIZE > sub(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Subtracts array b from array a and returns the result.
Definition: ArrayMath.h:45
constexpr std::array< T, SIZE > add(const std::array< T, SIZE > &a, const std::array< T, SIZE > &b)
Adds two arrays, returns the result.
Definition: ArrayMath.h:28
constexpr std::array< T, 3 > cross(const std::array< T, 3 > &a, const std::array< T, 3 > &b)
Generates the cross product of two arrays of 3 floats.
Definition: ArrayMath.h:249
std::vector< std::array< double, 3 > > rotateVectorOfPositions(const std::array< double, 4 > &q, const std::vector< std::array< double, 3 > > &positionVector)
Rotates a std::vector of 3D positions.
Definition: Quaternion.cpp:13
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:34
int autopas_get_max_threads()
Dummy for omp_get_max_threads() when no OpenMP is available.
Definition: WrapOpenMP.h:144
OwnershipState
Enum that specifies the state of ownership.
Definition: OwnershipState.h:20
@ dummy
Dummy or deleted state, a particle with this state is not an actual particle!
@ owned
Owned state, a particle with this state is an actual particle and owned by the current AutoPas object...
FunctorN3Modes
Newton 3 modes for the Functor.
Definition: Functor.h:23
int autopas_get_thread_num()
Dummy for omp_set_lock() when no OpenMP is available.
Definition: WrapOpenMP.h:132