42template <
class Particle_T,
bool applyShift =
false,
bool useMixing =
false,
44 bool countFLOPs =
false,
bool relevantForTuning =
true>
47 calculateGlobals, relevantForTuning, countFLOPs>> {
51 using SoAArraysType =
typename Particle_T::SoAArraysType;
56 using SoAFloatPrecision =
typename Particle_T::ParticleSoAFloatPrecision;
61 const double _cutoffSquared;
81 const std::vector<std::array<double, 3>> _sitePositionsLJ{};
91 double _potentialEnergySum;
96 std::array<double, 3> _virialSum;
117 calculateGlobals, relevantForTuning, countFLOPs>>(
119 _cutoffSquared{cutoff * cutoff},
120 _potentialEnergySum{0.},
121 _virialSum{0., 0., 0.},
123 _postProcessed{false} {
124 if constexpr (calculateGlobals) {
127 if constexpr (countFLOPs) {
128 AutoPasLog(DEBUG,
"FLOP counting is enabled but is not supported for multi-site functors yet!");
139 static_assert(not useMixing,
140 "Mixing without a ParticlePropertiesLibrary is not possible! Use a different constructor or set "
142 AutoPasLog(WARN,
"Using LJMultisiteFunctor with mixing disabled is untested!");
154 static_assert(useMixing,
155 "Not using Mixing but using a ParticlePropertiesLibrary is not allowed! Use a different constructor "
156 "or set mixing to true.");
157 _PPLibrary = &particlePropertiesLibrary;
160 std::string
getName() final {
return "LJMultisiteFunctor"; }
165 return useNewton3 == autopas::FunctorN3Modes::Newton3Only or useNewton3 == autopas::FunctorN3Modes::Both;
169 return useNewton3 == autopas::FunctorN3Modes::Newton3Off or useNewton3 == autopas::FunctorN3Modes::Both;
179 void AoSFunctor(Particle_T &particleA, Particle_T &particleB,
bool newton3)
final {
180 using namespace autopas::utils::ArrayMath::literals;
181 if (particleA.isDummy() or particleB.isDummy()) {
189 if (distanceSquaredCoM > _cutoffSquared) {
194 const size_t numSitesA = useMixing ? _PPLibrary->
getNumSites(particleA.getTypeId()) : _sitePositionsLJ.size();
195 const size_t numSitesB = useMixing ? _PPLibrary->
getNumSites(particleB.getTypeId()) : _sitePositionsLJ.size();
198 const std::vector<size_t> siteIdsA =
199 useMixing ? _PPLibrary->
getSiteTypes(particleA.getTypeId()) : std::vector<unsigned long>();
200 const std::vector<size_t> siteIdsB =
201 useMixing ? _PPLibrary->
getSiteTypes(particleB.getTypeId()) : std::vector<unsigned long>();
204 const std::vector<std::array<double, 3>> unrotatedSitePositionsA =
205 useMixing ? _PPLibrary->
getSitePositions(particleA.getTypeId()) : _sitePositionsLJ;
206 const std::vector<std::array<double, 3>> unrotatedSitePositionsB =
207 useMixing ? _PPLibrary->
getSitePositions(particleB.getTypeId()) : _sitePositionsLJ;
210 const auto rotatedSitePositionsA =
212 const auto rotatedSitePositionsB =
215 for (
int i = 0; i < numSitesA; i++) {
216 for (
int j = 0; j < numSitesB; j++) {
221 const auto sigmaSquared =
223 const auto epsilon24 = useMixing ? _PPLibrary->
getMixing24Epsilon(siteIdsA[i], siteIdsB[j]) : _epsilon24;
225 applyShift ? (useMixing ? _PPLibrary->
getMixingShift6(siteIdsA[i], siteIdsB[j]) : _shift6) : 0;
232 const auto invDistSquared = 1. / distanceSquared;
233 const auto lj2 = sigmaSquared * invDistSquared;
234 const auto lj6 = lj2 * lj2 * lj2;
235 const auto lj12 = lj6 * lj6;
236 const auto lj12m6 = lj12 - lj6;
237 const auto scalarMultiple = epsilon24 * (lj12 + lj12m6) * invDistSquared;
241 particleA.addF(force);
243 particleB.subF(force);
252 if (calculateGlobals) {
255 const auto potentialEnergy6 = epsilon24 * lj12m6 + shift6;
256 const auto virial = displacement * force;
260 if (particleA.isOwned()) {
261 _aosThreadData[threadNum].potentialEnergySum += potentialEnergy6;
262 _aosThreadData[threadNum].virialSum += virial;
265 if (newton3 and particleB.isOwned()) {
266 _aosThreadData[threadNum].potentialEnergySum += potentialEnergy6;
267 _aosThreadData[threadNum].virialSum += virial;
280 if (soa.size() == 0)
return;
282 const auto *
const __restrict xptr = soa.template begin<Particle_T::AttributeNames::posX>();
283 const auto *
const __restrict yptr = soa.template begin<Particle_T::AttributeNames::posY>();
284 const auto *
const __restrict zptr = soa.template begin<Particle_T::AttributeNames::posZ>();
286 const auto *
const __restrict ownedStatePtr = soa.template begin<Particle_T::AttributeNames::ownershipState>();
288 const auto *
const __restrict q0ptr = soa.template begin<Particle_T::AttributeNames::quaternion0>();
289 const auto *
const __restrict q1ptr = soa.template begin<Particle_T::AttributeNames::quaternion1>();
290 const auto *
const __restrict q2ptr = soa.template begin<Particle_T::AttributeNames::quaternion2>();
291 const auto *
const __restrict q3ptr = soa.template begin<Particle_T::AttributeNames::quaternion3>();
293 SoAFloatPrecision *
const __restrict fxptr = soa.template begin<Particle_T::AttributeNames::forceX>();
294 SoAFloatPrecision *
const __restrict fyptr = soa.template begin<Particle_T::AttributeNames::forceY>();
295 SoAFloatPrecision *
const __restrict fzptr = soa.template begin<Particle_T::AttributeNames::forceZ>();
297 SoAFloatPrecision *
const __restrict txptr = soa.template begin<Particle_T::AttributeNames::torqueX>();
298 SoAFloatPrecision *
const __restrict typtr = soa.template begin<Particle_T::AttributeNames::torqueY>();
299 SoAFloatPrecision *
const __restrict tzptr = soa.template begin<Particle_T::AttributeNames::torqueZ>();
301 [[maybe_unused]]
auto *
const __restrict typeptr = soa.template begin<Particle_T::AttributeNames::typeId>();
303 SoAFloatPrecision potentialEnergySum = 0.;
304 SoAFloatPrecision virialSumX = 0.;
305 SoAFloatPrecision virialSumY = 0.;
306 SoAFloatPrecision virialSumZ = 0.;
309 const SoAFloatPrecision cutoffSquared = _cutoffSquared;
311 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> sigmaSquareds;
312 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> epsilon24s;
313 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> shift6s;
315 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionX;
316 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionY;
317 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionZ;
320 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceX;
321 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceY;
322 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceZ;
324 std::vector<size_t, autopas::AlignedAllocator<size_t>> siteTypes;
325 std::vector<char, autopas::AlignedAllocator<char>> isSiteOwned;
327 const SoAFloatPrecision const_sigmaSquared = _sigmaSquared;
328 const SoAFloatPrecision const_epsilon24 = _epsilon24;
329 const SoAFloatPrecision const_shift6 = _shift6;
331 const auto const_unrotatedSitePositions = _sitePositionsLJ;
334 size_t siteCount = 0;
335 if constexpr (useMixing) {
336 for (
size_t mol = 0; mol < soa.size(); ++mol) {
337 siteCount += _PPLibrary->
getNumSites(typeptr[mol]);
340 siteCount = const_unrotatedSitePositions.size() * soa.size();
344 exactSitePositionX.reserve(siteCount);
345 exactSitePositionY.reserve(siteCount);
346 exactSitePositionZ.reserve(siteCount);
348 if constexpr (useMixing) {
349 siteTypes.reserve(siteCount);
352 siteForceX.reserve((siteCount));
353 siteForceY.reserve((siteCount));
354 siteForceZ.reserve((siteCount));
356 if constexpr (calculateGlobals) {
358 isSiteOwned.reserve(siteCount);
362 if constexpr (useMixing) {
363 size_t siteIndex = 0;
364 for (
size_t mol = 0; mol < soa.size(); ++mol) {
366 {q0ptr[mol], q1ptr[mol], q2ptr[mol], q3ptr[mol]}, _PPLibrary->
getSitePositions(typeptr[mol]));
367 const auto siteTypesOfMol = _PPLibrary->
getSiteTypes(typeptr[mol]);
369 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptr[mol]); ++site) {
370 exactSitePositionX[siteIndex] = rotatedSitePositions[site][0] + xptr[mol];
371 exactSitePositionY[siteIndex] = rotatedSitePositions[site][1] + yptr[mol];
372 exactSitePositionZ[siteIndex] = rotatedSitePositions[site][2] + zptr[mol];
373 siteTypes[siteIndex] = siteTypesOfMol[site];
374 siteForceX[siteIndex] = 0.;
375 siteForceY[siteIndex] = 0.;
376 siteForceZ[siteIndex] = 0.;
377 if (calculateGlobals) {
384 size_t siteIndex = 0;
385 for (
size_t mol = 0; mol < soa.size(); mol++) {
387 {q0ptr[mol], q1ptr[mol], q2ptr[mol], q3ptr[mol]}, const_unrotatedSitePositions);
388 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
389 exactSitePositionX[siteIndex] = rotatedSitePositions[site][0] + xptr[mol];
390 exactSitePositionY[siteIndex] = rotatedSitePositions[site][1] + yptr[mol];
391 exactSitePositionZ[siteIndex] = rotatedSitePositions[site][2] + zptr[mol];
392 siteForceX[siteIndex] = 0.;
393 siteForceY[siteIndex] = 0.;
394 siteForceZ[siteIndex] = 0.;
395 if (calculateGlobals) {
404 size_t siteIndexMolA = 0;
405 for (
size_t molA = 0; molA < soa.size(); ++molA) {
406 const size_t noSitesInMolA = useMixing ? _PPLibrary->
getNumSites(typeptr[molA])
407 : const_unrotatedSitePositions.size();
409 const auto ownedStateA = ownedStatePtr[molA];
411 siteIndexMolA += noSitesInMolA;
415 const size_t siteIndexMolB = siteIndexMolA + noSitesInMolA;
416 const size_t noSitesB = (siteCount - siteIndexMolB);
419 std::vector<char, autopas::AlignedAllocator<char>> molMask;
420 molMask.reserve(soa.size() - (molA + 1));
423 for (
size_t molB = molA + 1; molB < soa.size(); ++molB) {
424 const auto ownedStateB = ownedStatePtr[molB];
426 const auto displacementCoMX = xptr[molA] - xptr[molB];
427 const auto displacementCoMY = yptr[molA] - yptr[molB];
428 const auto displacementCoMZ = zptr[molA] - zptr[molB];
430 const auto distanceSquaredCoMX = displacementCoMX * displacementCoMX;
431 const auto distanceSquaredCoMY = displacementCoMY * displacementCoMY;
432 const auto distanceSquaredCoMZ = displacementCoMZ * displacementCoMZ;
434 const auto distanceSquaredCoM = distanceSquaredCoMX + distanceSquaredCoMY + distanceSquaredCoMZ;
437 molMask[molB - (molA + 1)] =
442 std::vector<char, autopas::AlignedAllocator<char>> siteMask;
443 siteMask.reserve(noSitesB);
445 for (
size_t molB = molA + 1; molB < soa.size(); ++molB) {
446 for (
size_t siteB = 0; siteB < _PPLibrary->
getNumSites(typeptr[molB]); ++siteB) {
447 siteMask.emplace_back(molMask[molB - (molA + 1)]);
452 for (
size_t siteA = siteIndexMolA; siteA < siteIndexMolB; ++siteA) {
455 sigmaSquareds.reserve(noSitesB);
456 epsilon24s.reserve(noSitesB);
457 if constexpr (applyShift) {
458 shift6s.reserve(noSitesB);
461 for (
size_t siteB = 0; siteB < siteCount - (siteIndexMolB); ++siteB) {
462 const auto mixingData = _PPLibrary->
getLJMixingData(siteTypes[siteA], siteTypes[siteIndexMolB + siteB]);
463 sigmaSquareds[siteB] = mixingData.sigmaSquared;
464 epsilon24s[siteB] = mixingData.epsilon24;
466 shift6s[siteB] = mixingData.shift6;
471 SoAFloatPrecision forceSumX = 0.;
472 SoAFloatPrecision forceSumY = 0.;
473 SoAFloatPrecision forceSumZ = 0.;
474 SoAFloatPrecision torqueSumX = 0.;
475 SoAFloatPrecision torqueSumY = 0.;
476 SoAFloatPrecision torqueSumZ = 0.;
478#pragma omp simd reduction (+ : forceSumX, forceSumY, forceSumZ, torqueSumX, torqueSumY, torqueSumZ, potentialEnergySum, virialSumX, virialSumY, virialSumZ)
479 for (
size_t siteB = 0; siteB < noSitesB; ++siteB) {
480 const size_t globalSiteBIndex = siteB + siteIndexMolB;
482 const SoAFloatPrecision sigmaSquared = useMixing ? sigmaSquareds[siteB] : const_sigmaSquared;
483 const SoAFloatPrecision epsilon24 = useMixing ? epsilon24s[siteB] : const_epsilon24;
484 const SoAFloatPrecision shift6 = applyShift ? (useMixing ? shift6s[siteB] : const_shift6) : 0;
486 const auto isSiteBOwned = !calculateGlobals || isSiteOwned[globalSiteBIndex];
488 const auto displacementX = exactSitePositionX[siteA] - exactSitePositionX[globalSiteBIndex];
489 const auto displacementY = exactSitePositionY[siteA] - exactSitePositionY[globalSiteBIndex];
490 const auto displacementZ = exactSitePositionZ[siteA] - exactSitePositionZ[globalSiteBIndex];
492 const auto distanceSquaredX = displacementX * displacementX;
493 const auto distanceSquaredY = displacementY * displacementY;
494 const auto distanceSquaredZ = displacementZ * displacementZ;
496 const auto distanceSquared = distanceSquaredX + distanceSquaredY + distanceSquaredZ;
498 const auto invDistSquared = 1. / distanceSquared;
499 const auto lj2 = sigmaSquared * invDistSquared;
500 const auto lj6 = lj2 * lj2 * lj2;
501 const auto lj12 = lj6 * lj6;
502 const auto lj12m6 = lj12 - lj6;
503 const auto scalarMultiple = siteMask[siteB] ? epsilon24 * (lj12 + lj12m6) * invDistSquared : 0.;
506 const auto forceX = scalarMultiple * displacementX;
507 const auto forceY = scalarMultiple * displacementY;
508 const auto forceZ = scalarMultiple * displacementZ;
515 siteForceX[globalSiteBIndex] -= forceX;
516 siteForceY[globalSiteBIndex] -= forceY;
517 siteForceZ[globalSiteBIndex] -= forceZ;
519 if constexpr (calculateGlobals) {
520 const auto virialX = displacementX * forceX;
521 const auto virialY = displacementY * forceY;
522 const auto virialZ = displacementZ * forceZ;
523 const auto potentialEnergy6 = siteMask[siteB] ? (epsilon24 * lj12m6 + shift6) : 0.;
527 const auto ownershipMask =
529 potentialEnergySum += potentialEnergy6 * ownershipMask;
530 virialSumX += virialX * ownershipMask;
531 virialSumY += virialY * ownershipMask;
532 virialSumZ += virialZ * ownershipMask;
536 siteForceX[siteA] += forceSumX;
537 siteForceY[siteA] += forceSumY;
538 siteForceZ[siteA] += forceSumZ;
540 siteIndexMolA += noSitesInMolA;
544 if constexpr (useMixing) {
545 size_t siteIndex = 0;
546 for (
size_t mol = 0; mol < soa.size(); ++mol) {
548 {q0ptr[mol], q1ptr[mol], q2ptr[mol], q3ptr[mol]}, _PPLibrary->
getSitePositions(typeptr[mol]));
549 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptr[mol]); ++site) {
550 fxptr[mol] += siteForceX[siteIndex];
551 fyptr[mol] += siteForceY[siteIndex];
552 fzptr[mol] += siteForceZ[siteIndex];
553 txptr[mol] += rotatedSitePositions[site][1] * siteForceZ[siteIndex] -
554 rotatedSitePositions[site][2] * siteForceY[siteIndex];
555 typtr[mol] += rotatedSitePositions[site][2] * siteForceX[siteIndex] -
556 rotatedSitePositions[site][0] * siteForceZ[siteIndex];
557 tzptr[mol] += rotatedSitePositions[site][0] * siteForceY[siteIndex] -
558 rotatedSitePositions[site][1] * siteForceX[siteIndex];
563 size_t siteIndex = 0;
564 for (
size_t mol = 0; mol < soa.size(); mol++) {
566 {q0ptr[mol], q1ptr[mol], q2ptr[mol], q3ptr[mol]}, const_unrotatedSitePositions);
567 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
568 fxptr[mol] += siteForceX[siteIndex];
569 fyptr[mol] += siteForceY[siteIndex];
570 fzptr[mol] += siteForceZ[siteIndex];
571 txptr[mol] += rotatedSitePositions[site][1] * siteForceZ[siteIndex] -
572 rotatedSitePositions[site][2] * siteForceY[siteIndex];
573 typtr[mol] += rotatedSitePositions[site][2] * siteForceX[siteIndex] -
574 rotatedSitePositions[site][0] * siteForceZ[siteIndex];
575 tzptr[mol] += rotatedSitePositions[site][0] * siteForceY[siteIndex] -
576 rotatedSitePositions[site][1] * siteForceX[siteIndex];
582 if constexpr (calculateGlobals) {
585 _aosThreadData[threadNum].potentialEnergySum += potentialEnergySum;
586 _aosThreadData[threadNum].virialSum[0] += virialSumX;
587 _aosThreadData[threadNum].virialSum[1] += virialSumY;
588 _aosThreadData[threadNum].virialSum[2] += virialSumZ;
595 const bool newton3)
final {
597 SoAFunctorPairImpl<true>(soa1, soa2);
599 SoAFunctorPairImpl<false>(soa1, soa2);
610 bool newton3)
final {
611 if (soa.size() == 0 or neighborList.empty())
return;
613 SoAFunctorVerletImpl<true>(soa, indexFirst, neighborList);
615 SoAFunctorVerletImpl<false>(soa, indexFirst, neighborList);
628 std::vector<std::array<SoAFloatPrecision, 3>> sitePositionsLJ) {
629 _epsilon24 = epsilon24;
630 _sigmaSquared = sigmaSquared;
636 _sitePositionsLJ = sitePositionsLJ;
643 return std::array<typename Particle_T::AttributeNames, 16>{
644 Particle_T::AttributeNames::id, Particle_T::AttributeNames::posX,
645 Particle_T::AttributeNames::posY, Particle_T::AttributeNames::posZ,
646 Particle_T::AttributeNames::forceX, Particle_T::AttributeNames::forceY,
647 Particle_T::AttributeNames::forceZ, Particle_T::AttributeNames::quaternion0,
648 Particle_T::AttributeNames::quaternion1, Particle_T::AttributeNames::quaternion2,
649 Particle_T::AttributeNames::quaternion3, Particle_T::AttributeNames::torqueX,
650 Particle_T::AttributeNames::torqueY, Particle_T::AttributeNames::torqueZ,
651 Particle_T::AttributeNames::typeId, Particle_T::AttributeNames::ownershipState};
658 return std::array<typename Particle_T::AttributeNames, 16>{
659 Particle_T::AttributeNames::id, Particle_T::AttributeNames::posX,
660 Particle_T::AttributeNames::posY, Particle_T::AttributeNames::posZ,
661 Particle_T::AttributeNames::forceX, Particle_T::AttributeNames::forceY,
662 Particle_T::AttributeNames::forceZ, Particle_T::AttributeNames::quaternion0,
663 Particle_T::AttributeNames::quaternion1, Particle_T::AttributeNames::quaternion2,
664 Particle_T::AttributeNames::quaternion3, Particle_T::AttributeNames::torqueX,
665 Particle_T::AttributeNames::torqueY, Particle_T::AttributeNames::torqueZ,
666 Particle_T::AttributeNames::typeId, Particle_T::AttributeNames::ownershipState};
673 return std::array<typename Particle_T::AttributeNames, 6>{
674 Particle_T::AttributeNames::forceX, Particle_T::AttributeNames::forceY, Particle_T::AttributeNames::forceZ,
675 Particle_T::AttributeNames::torqueX, Particle_T::AttributeNames::torqueY, Particle_T::AttributeNames::torqueZ};
702 const unsigned long siteToSiteFlops = newton3 ? 33ul : 26ul;
711 _potentialEnergySum = 0;
712 _virialSum = {0., 0., 0.};
713 _postProcessed =
false;
714 for (
size_t i = 0; i < _aosThreadData.size(); i++) {
715 _aosThreadData[i].setZero();
724 using namespace autopas::utils::ArrayMath::literals;
726 if (_postProcessed) {
728 "Already postprocessed, endTraversal(bool newton3) was called twice without calling initTraversal().");
730 if (calculateGlobals) {
731 for (
size_t i = 0; i < _aosThreadData.size(); ++i) {
732 _potentialEnergySum += _aosThreadData[i].potentialEnergySum;
733 _virialSum += _aosThreadData[i].virialSum;
738 _potentialEnergySum *= 0.5;
742 _potentialEnergySum /= 6.;
743 _postProcessed =
true;
745 AutoPasLog(DEBUG,
"Final potential energy {}", _potentialEnergySum);
746 AutoPasLog(DEBUG,
"Final virial {}", _virialSum[0] + _virialSum[1] + _virialSum[2]);
756 if (not calculateGlobals) {
758 "Trying to get potential energy even though calculateGlobals is false. If you want this functor to calculate "
760 "values, please specify calculateGlobals to be true.");
762 if (not _postProcessed) {
764 "Cannot get potential energy, because endTraversal was not called.");
766 return _potentialEnergySum;
774 if (not calculateGlobals) {
776 "Trying to get virial even though calculateGlobals is false. If you want this functor to calculate global "
777 "values, please specify calculateGlobals to be true.");
779 if (not _postProcessed) {
781 "Cannot get virial, because endTraversal was not called.");
783 return _virialSum[0] + _virialSum[1] + _virialSum[2];
793 template <
bool newton3>
795 if (soaA.
size() == 0 || soaB.
size() == 0)
return;
797 const auto *
const __restrict xAptr = soaA.template begin<Particle_T::AttributeNames::posX>();
798 const auto *
const __restrict yAptr = soaA.template begin<Particle_T::AttributeNames::posY>();
799 const auto *
const __restrict zAptr = soaA.template begin<Particle_T::AttributeNames::posZ>();
800 const auto *
const __restrict xBptr = soaB.template begin<Particle_T::AttributeNames::posX>();
801 const auto *
const __restrict yBptr = soaB.template begin<Particle_T::AttributeNames::posY>();
802 const auto *
const __restrict zBptr = soaB.template begin<Particle_T::AttributeNames::posZ>();
804 const auto *
const __restrict ownedStatePtrA = soaA.template begin<Particle_T::AttributeNames::ownershipState>();
805 const auto *
const __restrict ownedStatePtrB = soaB.template begin<Particle_T::AttributeNames::ownershipState>();
807 const auto *
const __restrict q0Aptr = soaA.template begin<Particle_T::AttributeNames::quaternion0>();
808 const auto *
const __restrict q1Aptr = soaA.template begin<Particle_T::AttributeNames::quaternion1>();
809 const auto *
const __restrict q2Aptr = soaA.template begin<Particle_T::AttributeNames::quaternion2>();
810 const auto *
const __restrict q3Aptr = soaA.template begin<Particle_T::AttributeNames::quaternion3>();
811 const auto *
const __restrict q0Bptr = soaB.template begin<Particle_T::AttributeNames::quaternion0>();
812 const auto *
const __restrict q1Bptr = soaB.template begin<Particle_T::AttributeNames::quaternion1>();
813 const auto *
const __restrict q2Bptr = soaB.template begin<Particle_T::AttributeNames::quaternion2>();
814 const auto *
const __restrict q3Bptr = soaB.template begin<Particle_T::AttributeNames::quaternion3>();
816 SoAFloatPrecision *
const __restrict fxAptr = soaA.template begin<Particle_T::AttributeNames::forceX>();
817 SoAFloatPrecision *
const __restrict fyAptr = soaA.template begin<Particle_T::AttributeNames::forceY>();
818 SoAFloatPrecision *
const __restrict fzAptr = soaA.template begin<Particle_T::AttributeNames::forceZ>();
819 SoAFloatPrecision *
const __restrict fxBptr = soaB.template begin<Particle_T::AttributeNames::forceX>();
820 SoAFloatPrecision *
const __restrict fyBptr = soaB.template begin<Particle_T::AttributeNames::forceY>();
821 SoAFloatPrecision *
const __restrict fzBptr = soaB.template begin<Particle_T::AttributeNames::forceZ>();
823 SoAFloatPrecision *
const __restrict txAptr = soaA.template begin<Particle_T::AttributeNames::torqueX>();
824 SoAFloatPrecision *
const __restrict tyAptr = soaA.template begin<Particle_T::AttributeNames::torqueY>();
825 SoAFloatPrecision *
const __restrict tzAptr = soaA.template begin<Particle_T::AttributeNames::torqueZ>();
826 SoAFloatPrecision *
const __restrict txBptr = soaB.template begin<Particle_T::AttributeNames::torqueX>();
827 SoAFloatPrecision *
const __restrict tyBptr = soaB.template begin<Particle_T::AttributeNames::torqueY>();
828 SoAFloatPrecision *
const __restrict tzBptr = soaB.template begin<Particle_T::AttributeNames::torqueZ>();
830 [[maybe_unused]]
auto *
const __restrict typeptrA = soaA.template begin<Particle_T::AttributeNames::typeId>();
831 [[maybe_unused]]
auto *
const __restrict typeptrB = soaB.template begin<Particle_T::AttributeNames::typeId>();
833 SoAFloatPrecision potentialEnergySum = 0.;
834 SoAFloatPrecision virialSumX = 0.;
835 SoAFloatPrecision virialSumY = 0.;
836 SoAFloatPrecision virialSumZ = 0.;
839 const SoAFloatPrecision cutoffSquared = _cutoffSquared;
841 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> sigmaSquareds;
842 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> epsilon24s;
843 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> shift6s;
845 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionBx;
846 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionBy;
847 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactSitePositionBz;
850 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceBx;
851 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceBy;
852 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceBz;
854 std::vector<size_t, autopas::AlignedAllocator<size_t>> siteTypesB;
855 std::vector<char, autopas::AlignedAllocator<char>> isSiteOwnedBArr;
857 const SoAFloatPrecision const_sigmaSquared = _sigmaSquared;
858 const SoAFloatPrecision const_epsilon24 = _epsilon24;
859 const SoAFloatPrecision const_shift6 = _shift6;
861 const auto const_unrotatedSitePositions = _sitePositionsLJ;
864 size_t siteCountB = 0;
865 if constexpr (useMixing) {
866 for (
size_t mol = 0; mol < soaB.
size(); ++mol) {
867 siteCountB += _PPLibrary->
getNumSites(typeptrB[mol]);
870 siteCountB = const_unrotatedSitePositions.size() * soaB.
size();
874 exactSitePositionBx.reserve(siteCountB);
875 exactSitePositionBy.reserve(siteCountB);
876 exactSitePositionBz.reserve(siteCountB);
878 if constexpr (useMixing) {
879 siteTypesB.reserve(siteCountB);
882 siteForceBx.reserve(siteCountB);
883 siteForceBy.reserve(siteCountB);
884 siteForceBz.reserve(siteCountB);
886 if constexpr (calculateGlobals) {
888 isSiteOwnedBArr.reserve(siteCountB);
891 if constexpr (useMixing) {
892 siteTypesB.reserve(siteCountB);
893 sigmaSquareds.reserve(siteCountB);
894 epsilon24s.reserve(siteCountB);
895 if constexpr (applyShift) {
896 shift6s.reserve(siteCountB);
901 if constexpr (useMixing) {
902 size_t siteIndex = 0;
903 for (
size_t mol = 0; mol < soaB.
size(); ++mol) {
905 {q0Bptr[mol], q1Bptr[mol], q2Bptr[mol], q3Bptr[mol]}, _PPLibrary->
getSitePositions(typeptrB[mol]));
906 const auto siteTypesOfMol = _PPLibrary->
getSiteTypes(typeptrB[mol]);
908 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptrB[mol]); ++site) {
909 exactSitePositionBx[siteIndex] = rotatedSitePositions[site][0] + xBptr[mol];
910 exactSitePositionBy[siteIndex] = rotatedSitePositions[site][1] + yBptr[mol];
911 exactSitePositionBz[siteIndex] = rotatedSitePositions[site][2] + zBptr[mol];
912 siteTypesB[siteIndex] = siteTypesOfMol[site];
913 siteForceBx[siteIndex] = 0.;
914 siteForceBy[siteIndex] = 0.;
915 siteForceBz[siteIndex] = 0.;
916 if (calculateGlobals) {
923 size_t siteIndex = 0;
924 for (
size_t mol = 0; mol < soaB.
size(); mol++) {
926 {q0Bptr[mol], q1Bptr[mol], q2Bptr[mol], q3Bptr[mol]}, const_unrotatedSitePositions);
927 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
928 exactSitePositionBx[siteIndex] = rotatedSitePositions[site][0] + xBptr[mol];
929 exactSitePositionBy[siteIndex] = rotatedSitePositions[site][1] + yBptr[mol];
930 exactSitePositionBz[siteIndex] = rotatedSitePositions[site][2] + zBptr[mol];
931 siteForceBx[siteIndex] = 0.;
932 siteForceBy[siteIndex] = 0.;
933 siteForceBz[siteIndex] = 0.;
934 if (calculateGlobals) {
943 for (
size_t molA = 0; molA < soaA.
size(); ++molA) {
944 const auto ownedStateA = ownedStatePtrA[molA];
949 const auto noSitesInMolA =
950 useMixing ? _PPLibrary->
getNumSites(typeptrA[molA]) : const_unrotatedSitePositions.size();
951 const auto unrotatedSitePositionsA =
952 useMixing ? _PPLibrary->
getSitePositions(typeptrA[molA]) : const_unrotatedSitePositions;
955 {q0Aptr[molA], q1Aptr[molA], q2Aptr[molA], q3Aptr[molA]}, unrotatedSitePositionsA);
958 std::vector<char, autopas::AlignedAllocator<char>> molMask;
959 molMask.reserve(soaB.
size());
962 for (
size_t molB = 0; molB < soaB.
size(); ++molB) {
963 const auto ownedStateB = ownedStatePtrB[molB];
965 const auto displacementCoMX = xAptr[molA] - xBptr[molB];
966 const auto displacementCoMY = yAptr[molA] - yBptr[molB];
967 const auto displacementCoMZ = zAptr[molA] - zBptr[molB];
969 const auto distanceSquaredCoMX = displacementCoMX * displacementCoMX;
970 const auto distanceSquaredCoMY = displacementCoMY * displacementCoMY;
971 const auto distanceSquaredCoMZ = displacementCoMZ * displacementCoMZ;
973 const auto distanceSquaredCoM = distanceSquaredCoMX + distanceSquaredCoMY + distanceSquaredCoMZ;
980 std::vector<char, autopas::AlignedAllocator<char>> siteMask;
981 siteMask.reserve(siteCountB);
983 for (
size_t molB = 0; molB < soaB.
size(); ++molB) {
984 for (
size_t siteB = 0; siteB < _PPLibrary->
getNumSites(typeptrB[molB]); ++siteB) {
985 siteMask.emplace_back(molMask[molB]);
990 SoAFloatPrecision forceSumX = 0.;
991 SoAFloatPrecision forceSumY = 0.;
992 SoAFloatPrecision forceSumZ = 0.;
993 SoAFloatPrecision torqueSumX = 0.;
994 SoAFloatPrecision torqueSumY = 0.;
995 SoAFloatPrecision torqueSumZ = 0.;
997 for (
size_t siteA = 0; siteA < noSitesInMolA; ++siteA) {
1000 for (
size_t siteB = 0; siteB < siteCountB; ++siteB) {
1001 const auto mixingData =
1003 sigmaSquareds[siteB] = mixingData.sigmaSquared;
1004 epsilon24s[siteB] = mixingData.epsilon24;
1006 shift6s[siteB] = mixingData.shift6;
1011 const auto rotatedSitePositionAx = rotatedSitePositionsA[siteA][0];
1012 const auto rotatedSitePositionAy = rotatedSitePositionsA[siteA][1];
1013 const auto rotatedSitePositionAz = rotatedSitePositionsA[siteA][2];
1015 const auto exactSitePositionAx = rotatedSitePositionAx + xAptr[molA];
1016 const auto exactSitePositionAy = rotatedSitePositionAy + yAptr[molA];
1017 const auto exactSitePositionAz = rotatedSitePositionAz + zAptr[molA];
1019#pragma omp simd reduction (+ : forceSumX, forceSumY, forceSumZ, torqueSumX, torqueSumY, torqueSumZ, potentialEnergySum, virialSumX, virialSumY, virialSumZ)
1020 for (
size_t siteB = 0; siteB < siteCountB; ++siteB) {
1021 const SoAFloatPrecision sigmaSquared = useMixing ? sigmaSquareds[siteB] : const_sigmaSquared;
1022 const SoAFloatPrecision epsilon24 = useMixing ? epsilon24s[siteB] : const_epsilon24;
1023 const SoAFloatPrecision shift6 = applyShift ? (useMixing ? shift6s[siteB] : const_shift6) : 0;
1025 const auto isSiteOwnedB = !calculateGlobals || isSiteOwnedBArr[siteB];
1027 const auto displacementX = exactSitePositionAx - exactSitePositionBx[siteB];
1028 const auto displacementY = exactSitePositionAy - exactSitePositionBy[siteB];
1029 const auto displacementZ = exactSitePositionAz - exactSitePositionBz[siteB];
1031 const auto distanceSquaredX = displacementX * displacementX;
1032 const auto distanceSquaredY = displacementY * displacementY;
1033 const auto distanceSquaredZ = displacementZ * displacementZ;
1035 const auto distanceSquared = distanceSquaredX + distanceSquaredY + distanceSquaredZ;
1037 const auto invDistSquared = 1. / distanceSquared;
1038 const auto lj2 = sigmaSquared * invDistSquared;
1039 const auto lj6 = lj2 * lj2 * lj2;
1040 const auto lj12 = lj6 * lj6;
1041 const auto lj12m6 = lj12 - lj6;
1042 const auto scalarMultiple = siteMask[siteB] ? epsilon24 * (lj12 + lj12m6) * invDistSquared : 0.;
1045 const auto forceX = scalarMultiple * displacementX;
1046 const auto forceY = scalarMultiple * displacementY;
1047 const auto forceZ = scalarMultiple * displacementZ;
1049 forceSumX += forceX;
1050 forceSumY += forceY;
1051 forceSumZ += forceZ;
1053 torqueSumX += rotatedSitePositionAy * forceZ - rotatedSitePositionAz * forceY;
1054 torqueSumY += rotatedSitePositionAz * forceX - rotatedSitePositionAx * forceZ;
1055 torqueSumZ += rotatedSitePositionAx * forceY - rotatedSitePositionAy * forceX;
1058 if constexpr (newton3) {
1059 siteForceBx[siteB] -= forceX;
1060 siteForceBy[siteB] -= forceY;
1061 siteForceBz[siteB] -= forceZ;
1065 if constexpr (calculateGlobals) {
1066 const auto potentialEnergy6 = siteMask[siteB] ? (epsilon24 * lj12m6 + shift6) : 0.;
1067 const auto virialX = displacementX * forceX;
1068 const auto virialY = displacementY * forceY;
1069 const auto virialZ = displacementZ * forceZ;
1073 const auto ownershipFactor =
1076 potentialEnergySum += potentialEnergy6 * ownershipFactor;
1077 virialSumX += virialX * ownershipFactor;
1078 virialSumY += virialY * ownershipFactor;
1079 virialSumZ += virialZ * ownershipFactor;
1083 fxAptr[molA] += forceSumX;
1084 fyAptr[molA] += forceSumY;
1085 fzAptr[molA] += forceSumZ;
1086 txAptr[molA] += torqueSumX;
1087 tyAptr[molA] += torqueSumY;
1088 tzAptr[molA] += torqueSumZ;
1092 if constexpr (useMixing) {
1093 size_t siteIndex = 0;
1094 for (
size_t mol = 0; mol < soaB.
size(); ++mol) {
1096 {q0Bptr[mol], q1Bptr[mol], q2Bptr[mol], q3Bptr[mol]}, _PPLibrary->
getSitePositions(typeptrB[mol]));
1097 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptrB[mol]); ++site) {
1098 fxBptr[mol] += siteForceBx[siteIndex];
1099 fyBptr[mol] += siteForceBy[siteIndex];
1100 fzBptr[mol] += siteForceBz[siteIndex];
1101 txBptr[mol] += rotatedSitePositions[site][1] * siteForceBz[siteIndex] -
1102 rotatedSitePositions[site][2] * siteForceBy[siteIndex];
1103 tyBptr[mol] += rotatedSitePositions[site][2] * siteForceBx[siteIndex] -
1104 rotatedSitePositions[site][0] * siteForceBz[siteIndex];
1105 tzBptr[mol] += rotatedSitePositions[site][0] * siteForceBy[siteIndex] -
1106 rotatedSitePositions[site][1] * siteForceBx[siteIndex];
1111 size_t siteIndex = 0;
1112 for (
size_t mol = 0; mol < soaB.
size(); ++mol) {
1114 {q0Bptr[mol], q1Bptr[mol], q2Bptr[mol], q3Bptr[mol]}, const_unrotatedSitePositions);
1115 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
1116 fxBptr[mol] += siteForceBx[siteIndex];
1117 fyBptr[mol] += siteForceBy[siteIndex];
1118 fzBptr[mol] += siteForceBz[siteIndex];
1119 txBptr[mol] += rotatedSitePositions[site][1] * siteForceBz[siteIndex] -
1120 rotatedSitePositions[site][2] * siteForceBy[siteIndex];
1121 tyBptr[mol] += rotatedSitePositions[site][2] * siteForceBx[siteIndex] -
1122 rotatedSitePositions[site][0] * siteForceBz[siteIndex];
1123 tzBptr[mol] += rotatedSitePositions[site][0] * siteForceBy[siteIndex] -
1124 rotatedSitePositions[site][1] * siteForceBx[siteIndex];
1129 if constexpr (calculateGlobals) {
1133 _aosThreadData[threadNum].potentialEnergySum += potentialEnergySum;
1134 _aosThreadData[threadNum].virialSum[0] += virialSumX;
1135 _aosThreadData[threadNum].virialSum[1] += virialSumY;
1136 _aosThreadData[threadNum].virialSum[2] += virialSumZ;
1140 template <
bool newton3>
1143 const auto *
const __restrict ownedStatePtr = soa.template begin<Particle_T::AttributeNames::ownershipState>();
1146 const auto ownedStatePrime = ownedStatePtr[indexPrime];
1151 const auto *
const __restrict xptr = soa.template begin<Particle_T::AttributeNames::posX>();
1152 const auto *
const __restrict yptr = soa.template begin<Particle_T::AttributeNames::posY>();
1153 const auto *
const __restrict zptr = soa.template begin<Particle_T::AttributeNames::posZ>();
1155 const auto *
const __restrict q0ptr = soa.template begin<Particle_T::AttributeNames::quaternion0>();
1156 const auto *
const __restrict q1ptr = soa.template begin<Particle_T::AttributeNames::quaternion1>();
1157 const auto *
const __restrict q2ptr = soa.template begin<Particle_T::AttributeNames::quaternion2>();
1158 const auto *
const __restrict q3ptr = soa.template begin<Particle_T::AttributeNames::quaternion3>();
1160 SoAFloatPrecision *
const __restrict fxptr = soa.template begin<Particle_T::AttributeNames::forceX>();
1161 SoAFloatPrecision *
const __restrict fyptr = soa.template begin<Particle_T::AttributeNames::forceY>();
1162 SoAFloatPrecision *
const __restrict fzptr = soa.template begin<Particle_T::AttributeNames::forceZ>();
1164 SoAFloatPrecision *
const __restrict txptr = soa.template begin<Particle_T::AttributeNames::torqueX>();
1165 SoAFloatPrecision *
const __restrict typtr = soa.template begin<Particle_T::AttributeNames::torqueY>();
1166 SoAFloatPrecision *
const __restrict tzptr = soa.template begin<Particle_T::AttributeNames::torqueZ>();
1168 [[maybe_unused]]
auto *
const __restrict typeptr = soa.template begin<Particle_T::AttributeNames::typeId>();
1170 SoAFloatPrecision potentialEnergySum = 0.;
1171 SoAFloatPrecision virialSumX = 0.;
1172 SoAFloatPrecision virialSumY = 0.;
1173 SoAFloatPrecision virialSumZ = 0.;
1176 const SoAFloatPrecision cutoffSquared = _cutoffSquared;
1177 const auto const_unrotatedSitePositions = _sitePositionsLJ;
1179 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> sigmaSquareds;
1180 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> epsilon24s;
1181 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> shift6s;
1183 const auto const_sigmaSquared = _sigmaSquared;
1184 const auto const_epsilon24 = _epsilon24;
1185 const auto const_shift6 = _shift6;
1187 const size_t neighborListSize = neighborList.size();
1188 const size_t *
const __restrict neighborListPtr = neighborList.data();
1191 const size_t siteCountMolPrime =
1192 useMixing ? _PPLibrary->
getNumSites(typeptr[indexPrime]) : const_unrotatedSitePositions.size();
1194 size_t siteCountNeighbors = 0;
1195 if constexpr (useMixing) {
1196 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1197 siteCountNeighbors += _PPLibrary->
getNumSites(typeptr[neighborList[neighborMol]]);
1200 siteCountNeighbors = const_unrotatedSitePositions.size() * neighborListSize;
1204 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactNeighborSitePositionX;
1205 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactNeighborSitePositionY;
1206 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> exactNeighborSitePositionZ;
1208 std::vector<size_t, autopas::AlignedAllocator<size_t>> siteTypesNeighbors;
1209 std::vector<char, autopas::AlignedAllocator<char>> isNeighborSiteOwnedArr;
1212 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceX;
1213 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceY;
1214 std::vector<SoAFloatPrecision, autopas::AlignedAllocator<SoAFloatPrecision>> siteForceZ;
1217 exactNeighborSitePositionX.reserve(siteCountNeighbors);
1218 exactNeighborSitePositionY.reserve(siteCountNeighbors);
1219 exactNeighborSitePositionZ.reserve(siteCountNeighbors);
1221 if constexpr (useMixing) {
1222 siteTypesNeighbors.reserve(siteCountNeighbors);
1225 siteForceX.reserve(siteCountNeighbors);
1226 siteForceY.reserve(siteCountNeighbors);
1227 siteForceZ.reserve(siteCountNeighbors);
1229 if constexpr (calculateGlobals) {
1230 isNeighborSiteOwnedArr.reserve(siteCountNeighbors);
1233 if constexpr (useMixing) {
1234 sigmaSquareds.reserve(siteCountNeighbors);
1235 epsilon24s.reserve(siteCountNeighbors);
1236 if constexpr (applyShift) {
1237 shift6s.reserve(siteCountNeighbors);
1241 const auto rotatedSitePositionsPrime =
1243 {q0ptr[indexPrime], q1ptr[indexPrime], q2ptr[indexPrime], q3ptr[indexPrime]},
1246 {q0ptr[indexPrime], q1ptr[indexPrime], q2ptr[indexPrime], q3ptr[indexPrime]},
1247 const_unrotatedSitePositions);
1249 const auto siteTypesPrime = _PPLibrary->
getSiteTypes(typeptr[indexPrime]);
1252 if constexpr (useMixing) {
1253 size_t siteIndex = 0;
1254 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1255 const auto neighborMolIndex = neighborList[neighborMol];
1257 {q0ptr[neighborMolIndex], q1ptr[neighborMolIndex], q2ptr[neighborMolIndex], q3ptr[neighborMolIndex]},
1259 const auto siteTypesOfMol = _PPLibrary->
getSiteTypes(typeptr[neighborMolIndex]);
1261 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptr[neighborMolIndex]); ++site) {
1262 exactNeighborSitePositionX[siteIndex] = rotatedSitePositions[site][0] + xptr[neighborMolIndex];
1263 exactNeighborSitePositionY[siteIndex] = rotatedSitePositions[site][1] + yptr[neighborMolIndex];
1264 exactNeighborSitePositionZ[siteIndex] = rotatedSitePositions[site][2] + zptr[neighborMolIndex];
1265 siteTypesNeighbors[siteIndex] = siteTypesOfMol[site];
1266 siteForceX[siteIndex] = 0.;
1267 siteForceY[siteIndex] = 0.;
1268 siteForceZ[siteIndex] = 0.;
1269 if (calculateGlobals) {
1276 size_t siteIndex = 0;
1277 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1278 const auto neighborMolIndex = neighborList[neighborMol];
1280 {q0ptr[neighborMolIndex], q1ptr[neighborMolIndex], q2ptr[neighborMolIndex], q3ptr[neighborMolIndex]},
1281 const_unrotatedSitePositions);
1282 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
1283 exactNeighborSitePositionX[siteIndex] = rotatedSitePositions[site][0] + xptr[neighborMolIndex];
1284 exactNeighborSitePositionY[siteIndex] = rotatedSitePositions[site][1] + yptr[neighborMolIndex];
1285 exactNeighborSitePositionZ[siteIndex] = rotatedSitePositions[site][2] + zptr[neighborMolIndex];
1286 siteForceX[siteIndex] = 0.;
1287 siteForceY[siteIndex] = 0.;
1288 siteForceZ[siteIndex] = 0.;
1289 if (calculateGlobals) {
1300 std::vector<char, autopas::AlignedAllocator<char>> molMask;
1301 molMask.reserve(neighborListSize);
1304 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1305 const auto neighborMolIndex = neighborList[neighborMol];
1307 const auto ownedState = ownedStatePtr[neighborMolIndex];
1309 const auto displacementCoMX = xptr[indexPrime] - xptr[neighborMolIndex];
1310 const auto displacementCoMY = yptr[indexPrime] - yptr[neighborMolIndex];
1311 const auto displacementCoMZ = zptr[indexPrime] - zptr[neighborMolIndex];
1313 const auto distanceSquaredCoMX = displacementCoMX * displacementCoMX;
1314 const auto distanceSquaredCoMY = displacementCoMY * displacementCoMY;
1315 const auto distanceSquaredCoMZ = displacementCoMZ * displacementCoMZ;
1317 const auto distanceSquaredCoM = distanceSquaredCoMX + distanceSquaredCoMY + distanceSquaredCoMZ;
1324 std::vector<char, autopas::AlignedAllocator<char>> siteMask;
1325 siteMask.reserve(siteCountNeighbors);
1327 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1328 const auto neighborMolIndex = neighborList[neighborMol];
1329 for (
size_t siteB = 0; siteB < _PPLibrary->
getNumSites(typeptr[neighborMolIndex]); ++siteB) {
1330 siteMask.emplace_back(molMask[neighborMol]);
1335 SoAFloatPrecision forceSumX = 0.;
1336 SoAFloatPrecision forceSumY = 0.;
1337 SoAFloatPrecision forceSumZ = 0.;
1338 SoAFloatPrecision torqueSumX = 0.;
1339 SoAFloatPrecision torqueSumY = 0.;
1340 SoAFloatPrecision torqueSumZ = 0.;
1344 for (
size_t primeSite = 0; primeSite < siteCountMolPrime; ++primeSite) {
1345 const auto rotatedPrimeSitePositionX = rotatedSitePositionsPrime[primeSite][0];
1346 const auto rotatedPrimeSitePositionY = rotatedSitePositionsPrime[primeSite][1];
1347 const auto rotatedPrimeSitePositionZ = rotatedSitePositionsPrime[primeSite][2];
1349 const auto exactPrimeSitePositionX = rotatedPrimeSitePositionX + xptr[indexPrime];
1350 const auto exactPrimeSitePositionY = rotatedPrimeSitePositionY + yptr[indexPrime];
1351 const auto exactPrimeSitePositionZ = rotatedPrimeSitePositionZ + zptr[indexPrime];
1354 if constexpr (useMixing) {
1355 const auto primeSiteType = siteTypesPrime[primeSite];
1357 size_t siteIndex = 0;
1358 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1359 const auto neighborMolIndex = neighborList[neighborMol];
1360 const auto siteTypesOfNeighborMol = _PPLibrary->
getSiteTypes(typeptr[neighborMolIndex]);
1362 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptr[neighborMolIndex]); ++site) {
1363 const auto mixingData = _PPLibrary->
getLJMixingData(primeSiteType, siteTypesOfNeighborMol[site]);
1364 sigmaSquareds[siteIndex] = mixingData.sigmaSquared;
1365 epsilon24s[siteIndex] = mixingData.epsilon24;
1366 if constexpr (applyShift) {
1367 shift6s[siteIndex] = mixingData.shift6;
1374#pragma omp simd reduction(+ : forceSumX, forceSumY, forceSumZ, torqueSumX, torqueSumY, torqueSumZ)
1375 for (
size_t neighborSite = 0; neighborSite < siteCountNeighbors; ++neighborSite) {
1376 const SoAFloatPrecision sigmaSquared = useMixing ? sigmaSquareds[neighborSite] : const_sigmaSquared;
1377 const SoAFloatPrecision epsilon24 = useMixing ? epsilon24s[neighborSite] : const_epsilon24;
1378 const SoAFloatPrecision shift6 = applyShift ? (useMixing ? shift6s[neighborSite] : const_shift6) : 0;
1380 const bool isNeighborSiteOwned = !calculateGlobals || isNeighborSiteOwnedArr[neighborSite];
1382 const auto displacementX = exactPrimeSitePositionX - exactNeighborSitePositionX[neighborSite];
1383 const auto displacementY = exactPrimeSitePositionY - exactNeighborSitePositionY[neighborSite];
1384 const auto displacementZ = exactPrimeSitePositionZ - exactNeighborSitePositionZ[neighborSite];
1386 const auto distanceSquaredX = displacementX * displacementX;
1387 const auto distanceSquaredY = displacementY * displacementY;
1388 const auto distanceSquaredZ = displacementZ * displacementZ;
1390 const auto distanceSquared = distanceSquaredX + distanceSquaredY + distanceSquaredZ;
1392 const auto invDistSquared = 1. / distanceSquared;
1393 const auto lj2 = sigmaSquared * invDistSquared;
1394 const auto lj6 = lj2 * lj2 * lj2;
1395 const auto lj12 = lj6 * lj6;
1396 const auto lj12m6 = lj12 - lj6;
1397 const auto scalarMultiple = siteMask[neighborSite] ? epsilon24 * (lj12 + lj12m6) * invDistSquared : 0.;
1400 const auto forceX = scalarMultiple * displacementX;
1401 const auto forceY = scalarMultiple * displacementY;
1402 const auto forceZ = scalarMultiple * displacementZ;
1404 forceSumX += forceX;
1405 forceSumY += forceY;
1406 forceSumZ += forceZ;
1408 torqueSumX += rotatedPrimeSitePositionY * forceZ - rotatedPrimeSitePositionZ * forceY;
1409 torqueSumY += rotatedPrimeSitePositionZ * forceX - rotatedPrimeSitePositionX * forceZ;
1410 torqueSumZ += rotatedPrimeSitePositionX * forceY - rotatedPrimeSitePositionY * forceX;
1414 siteForceX[neighborSite] -= forceX;
1415 siteForceY[neighborSite] -= forceY;
1416 siteForceZ[neighborSite] -= forceZ;
1420 if constexpr (calculateGlobals) {
1421 const auto potentialEnergy6 = siteMask[neighborSite] ? (epsilon24 * lj12m6 + shift6) : 0.;
1422 const auto virialX = displacementX * forceX;
1423 const auto virialY = displacementY * forceY;
1424 const auto virialZ = displacementZ * forceZ;
1427 const auto ownershipFactor =
1430 potentialEnergySum += potentialEnergy6 * ownershipFactor;
1431 virialSumX += virialX * ownershipFactor;
1432 virialSumY += virialY * ownershipFactor;
1433 virialSumZ += virialZ * ownershipFactor;
1438 fxptr[indexPrime] += forceSumX;
1439 fyptr[indexPrime] += forceSumY;
1440 fzptr[indexPrime] += forceSumZ;
1441 txptr[indexPrime] += torqueSumX;
1442 typtr[indexPrime] += torqueSumY;
1443 tzptr[indexPrime] += torqueSumZ;
1446 if constexpr (newton3) {
1447 if constexpr (useMixing) {
1448 size_t siteIndex = 0;
1449 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1450 const auto neighborMolIndex = neighborList[neighborMol];
1452 {q0ptr[neighborMolIndex], q1ptr[neighborMolIndex], q2ptr[neighborMolIndex], q3ptr[neighborMolIndex]},
1454 for (
size_t site = 0; site < _PPLibrary->
getNumSites(typeptr[neighborMolIndex]); ++site) {
1455 fxptr[neighborMolIndex] += siteForceX[siteIndex];
1456 fyptr[neighborMolIndex] += siteForceY[siteIndex];
1457 fzptr[neighborMolIndex] += siteForceZ[siteIndex];
1458 txptr[neighborMolIndex] += rotatedSitePositions[site][1] * siteForceZ[siteIndex] -
1459 rotatedSitePositions[site][2] * siteForceY[siteIndex];
1460 typtr[neighborMolIndex] += rotatedSitePositions[site][2] * siteForceX[siteIndex] -
1461 rotatedSitePositions[site][0] * siteForceZ[siteIndex];
1462 tzptr[neighborMolIndex] += rotatedSitePositions[site][0] * siteForceY[siteIndex] -
1463 rotatedSitePositions[site][1] * siteForceX[siteIndex];
1468 size_t siteIndex = 0;
1469 for (
size_t neighborMol = 0; neighborMol < neighborListSize; ++neighborMol) {
1470 const auto neighborMolIndex = neighborList[neighborMol];
1472 {q0ptr[neighborMolIndex], q1ptr[neighborMolIndex], q2ptr[neighborMolIndex], q3ptr[neighborMolIndex]},
1473 const_unrotatedSitePositions);
1474 for (
size_t site = 0; site < const_unrotatedSitePositions.size(); ++site) {
1475 fxptr[neighborMolIndex] += siteForceX[siteIndex];
1476 fyptr[neighborMolIndex] += siteForceY[siteIndex];
1477 fzptr[neighborMolIndex] += siteForceZ[siteIndex];
1478 txptr[neighborMolIndex] += rotatedSitePositions[site][1] * siteForceZ[siteIndex] -
1479 rotatedSitePositions[site][2] * siteForceY[siteIndex];
1480 typtr[neighborMolIndex] += rotatedSitePositions[site][2] * siteForceX[siteIndex] -
1481 rotatedSitePositions[site][0] * siteForceZ[siteIndex];
1482 txptr[neighborMolIndex] += rotatedSitePositions[site][0] * siteForceY[siteIndex] -
1483 rotatedSitePositions[site][1] * siteForceX[siteIndex];
1490 if constexpr (calculateGlobals) {
1493 _aosThreadData[threadNum].potentialEnergySum += potentialEnergySum;
1494 _aosThreadData[threadNum].virialSum[0] += virialSumX;
1495 _aosThreadData[threadNum].virialSum[1] += virialSumY;
1496 _aosThreadData[threadNum].virialSum[2] += virialSumZ;
1503 class AoSThreadData {
1505 AoSThreadData() : virialSum{0., 0., 0.}, potentialEnergySum{0.}, __remainingTo64{} {}
1507 virialSum = {0., 0., 0.};
1508 potentialEnergySum = 0.;
1512 std::array<double, 3> virialSum;
1513 double potentialEnergySum;
1517 double __remainingTo64[(64 - 4 *
sizeof(double)) /
sizeof(double)];
1520 static_assert(
sizeof(AoSThreadData) % 64 == 0,
"AoSThreadData has wrong size (should be multiple of 64)");
1525 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:553
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:516
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:575
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:527
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:115
A functor to handle Lennard-Jones interactions between two Multisite Molecules.
Definition: LJMultisiteFunctor.h:47
void SoAFunctorSingle(autopas::SoAView< SoAArraysType > soa, bool newton3) final
PairwiseFunctor for structure of arrays (SoA)
Definition: LJMultisiteFunctor.h:279
void AoSFunctor(Particle_T &particleA, Particle_T &particleB, bool newton3) final
Functor for arrays of structures (AoS).
Definition: LJMultisiteFunctor.h:179
LJMultisiteFunctor()=delete
Delete Default constructor.
bool isRelevantForTuning() final
Specifies whether the functor should be considered for the auto-tuning process.
Definition: LJMultisiteFunctor.h:162
LJMultisiteFunctor(double cutoff, ParticlePropertiesLibrary< double, size_t > &particlePropertiesLibrary)
Constructor for Functor with particle mixing enabled.
Definition: LJMultisiteFunctor.h:152
LJMultisiteFunctor(double cutoff)
Constructor for Functor with particle mixing disabled.
Definition: LJMultisiteFunctor.h:138
void initTraversal() final
Reset the global values.
Definition: LJMultisiteFunctor.h:710
static constexpr bool getMixing()
Definition: LJMultisiteFunctor.h:681
static constexpr auto getComputedAttr()
Get attributes computed by this functor.
Definition: LJMultisiteFunctor.h:672
void setParticleProperties(SoAFloatPrecision epsilon24, SoAFloatPrecision sigmaSquared, std::vector< std::array< SoAFloatPrecision, 3 > > sitePositionsLJ)
Sets the molecule properties constants for this functor.
Definition: LJMultisiteFunctor.h:627
bool allowsNewton3() final
Specifies whether the functor is capable of Newton3-like functors.
Definition: LJMultisiteFunctor.h:164
bool allowsNonNewton3() final
Specifies whether the functor is capable of non-Newton3-like functors.
Definition: LJMultisiteFunctor.h:168
double getPotentialEnergy()
Get the potential energy.
Definition: LJMultisiteFunctor.h:755
std::string getName() final
Returns name of functor.
Definition: LJMultisiteFunctor.h:160
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:693
void SoAFunctorPair(autopas::SoAView< SoAArraysType > soa1, autopas::SoAView< SoAArraysType > soa2, const bool newton3) final
PairwiseFunctor for structure of arrays (SoA)
Definition: LJMultisiteFunctor.h:594
static constexpr auto getNeededAttr(std::false_type)
Get attributes needed for computation without N3 optimization.
Definition: LJMultisiteFunctor.h:657
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:608
double getVirial()
Get the virial.
Definition: LJMultisiteFunctor.h:773
void endTraversal(bool newton3) final
Postprocesses global values, e.g.
Definition: LJMultisiteFunctor.h:723
static constexpr auto getNeededAttr()
Get attributes needed for computation.
Definition: LJMultisiteFunctor.h:642
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:32
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:19
@ 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:22
int autopas_get_thread_num()
Dummy for omp_set_lock() when no OpenMP is available.
Definition: WrapOpenMP.h:132