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