50template <
typename Particle_T>
61 unsigned int rebuildFrequency,
const std::string &outputSuffix)
62 : _tuningManager(tunerManager),
63 _logicHandlerInfo(logicHandlerInfo),
64 _neighborListRebuildFrequency{rebuildFrequency},
67 _remainderPairwiseInteractionHandler(_spatialLocks),
68 _remainderTriwiseInteractionHandler(_spatialLocks),
69 _verletClusterSize(logicHandlerInfo.verletClusterSize),
70 _aosSortingThreshold(logicHandlerInfo.aosSortingThreshold),
71 _soaSortingThreshold(logicHandlerInfo.soaSortingThreshold),
72 _iterationLogger(outputSuffix,
73 std::any_of(tunerManager->getAutoTuners().
begin(), tunerManager->getAutoTuners().end(),
74 [](const auto &tuner) {
return tuner.second->canMeasureEnergy(); })),
75 _flopLogger(outputSuffix),
76 _liveInfoLogger(outputSuffix) {
77 using namespace autopas::utils::ArrayMath::literals;
79 for (
const auto &[interactionType, tuner] : tunerManager->getAutoTuners()) {
80 _interactionTypes.insert(interactionType);
82 const auto configuration = tuner->getCurrentConfig();
86 configuration.cellSizeFactor, _logicHandlerInfo.
verletSkin, _verletClusterSize,
87 _aosSortingThreshold, _soaSortingThreshold, configuration.loadEstimator};
94 const auto interactionLength = logicHandlerInfo.cutoff + logicHandlerInfo.verletSkin;
95 const auto interactionLengthInv = 1. / interactionLength;
96 const auto boxLengthWithHalo = logicHandlerInfo.boxMax - logicHandlerInfo.boxMin + (2 * interactionLength);
97 initSpatialLocks(boxLengthWithHalo, interactionLengthInv);
112 const auto &boxMin = _currentContainer->getBoxMin();
113 const auto &boxMax = _currentContainer->getBoxMax();
114 std::vector<Particle_T> leavingBufferParticles{};
115 for (
auto &cell : _particleBuffer) {
116 auto &buffer = cell._particles;
117 if (insertOwnedParticlesToContainer) {
119 for (
auto &p : buffer) {
125 _currentContainer->addParticle(p);
127 leavingBufferParticles.push_back(p);
132 for (
auto iter = buffer.begin(); iter < buffer.end();) {
135 auto fastRemoveP = [&]() {
137 std::swap(p, buffer.back());
149 if (not buffer.empty() and
utils::notInBox(p.getR(), boxMin, boxMax)) {
150 leavingBufferParticles.push_back(p);
158 return leavingBufferParticles;
167#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
170 if (_tuningManager->isStartOfTuningPhase(_iteration)) {
171 _numRebuildsInNonTuningPhase = 0;
180 if (_tuningManager->inFirstConfigurationLastSample(_iteration)) {
183 double rebuildFrequencyEstimate =
185 double userProvidedRF =
static_cast<double>(_neighborListRebuildFrequency);
190 _tuningManager->setRebuildFrequency(std::min(userProvidedRF, rebuildFrequencyEstimate));
195 if (_tuningManager->tuningPhaseJustFinished()) {
196 _iterationAfterLastTuningPhase = _iteration;
199 if (not _neighborListsAreValid.load(std::memory_order_relaxed)) {
200 _stepsSinceLastListRebuild = 0;
202 ++_stepsSinceLastListRebuild;
207 AutoPasLog(TRACE,
"Initiating container update.");
208 auto leavingParticles = _currentContainer->updateContainer(not doDataStructureUpdate);
209 leavingParticles.insert(leavingParticles.end(), leavingBufferParticles.begin(), leavingBufferParticles.end());
212 _numParticlesOwned.fetch_sub(leavingParticles.size(), std::memory_order_relaxed);
214 std::for_each(_haloParticleBuffer.begin(), _haloParticleBuffer.end(), [](
auto &buffer) { buffer.clear(); });
215 _numParticlesHalo.store(0, std::memory_order_relaxed);
216 return leavingParticles;
225 std::vector<Particle_T>
resizeBox(
const std::array<double, 3> &boxMin,
const std::array<double, 3> &boxMax) {
226 using namespace autopas::utils::ArrayMath::literals;
227 const auto &oldMin = _currentContainer->getBoxMin();
228 const auto &oldMax = _currentContainer->getBoxMax();
231 if (oldMin == boxMin and oldMax == boxMax) {
236 for (
size_t i = 0; i < boxMin.size(); ++i) {
237 if (boxMin[i] >= boxMax[i]) {
239 "New box size in dimension {} is not positive!\nboxMin[{}] = {}\nboxMax[{}] = {}", i, i, boxMin[i], i,
245 const auto newLength = boxMax - boxMin;
246 const auto oldLength = oldMax - oldMin;
247 const auto relDiffLength = newLength / oldLength;
248 for (
size_t i = 0; i < newLength.size(); ++i) {
250 if (relDiffLength[i] > 1.3 or relDiffLength[i] < 0.7) {
252 "LogicHandler.resize(): Domain size changed drastically in dimension {}! Gathered AutoTuning "
253 "information might not be applicable anymore!\n"
254 "Size old box : {}\n"
255 "Size new box : {}\n"
263 _currentContainerSelectorInfo.
boxMin = boxMin;
264 _currentContainerSelectorInfo.
boxMax = boxMax;
267 std::vector<Particle_T> particlesNowOutside;
268 for (
auto pIter = _currentContainer->begin(); pIter.isValid(); ++pIter) {
270 if (not pIter->isOwned()) {
272 "LogicHandler::resizeBox() encountered non owned particle. "
273 "When calling resizeBox() these should be already deleted. "
274 "This could be solved by calling updateContainer() before resizeBox().");
278 particlesNowOutside.push_back(*pIter);
286 _currentContainerSelectorInfo);
287 setCurrentContainer(std::move(newContainer));
289 const auto boxLength = boxMax - boxMin;
290 const auto interactionLengthInv = 1. / _currentContainer->getInteractionLength();
291 initSpatialLocks(boxLength, interactionLengthInv);
294 _neighborListsAreValid.store(
false, std::memory_order_relaxed);
296 return particlesNowOutside;
307 numParticles, _currentContainer->getBoxMin(), _currentContainer->getBoxMax(),
308 _currentContainer->getInteractionLength());
309 reserve(numParticles, numParticlesHaloEstimate);
318 void reserve(
size_t numParticles,
size_t numHaloParticles) {
319 const auto numHaloParticlesPerBuffer = numHaloParticles / _haloParticleBuffer.size();
320 for (
auto &buffer : _haloParticleBuffer) {
321 buffer.reserve(numHaloParticlesPerBuffer);
324 for (
auto &buffer : _particleBuffer) {
325 buffer.reserve(numHaloParticlesPerBuffer);
330 if (not _neighborListsAreValid.load(std::memory_order_relaxed)) {
331 _currentContainer->reserve(numParticles, numHaloParticles);
340 const auto &boxMin = _currentContainer->getBoxMin();
341 const auto &boxMax = _currentContainer->getBoxMax();
344 "LogicHandler: Trying to add a particle that is not in the bounding box.\n"
348 boxMin, boxMax, p.toString());
350 Particle_T particleCopy = p;
352 if (not _neighborListsAreValid.load(std::memory_order_relaxed)) {
354 _currentContainer->template addParticle<false>(particleCopy);
359 _numParticlesOwned.fetch_add(1, std::memory_order_relaxed);
366 const auto &boxMin = _currentContainer->getBoxMin();
367 const auto &boxMax = _currentContainer->getBoxMax();
368 Particle_T haloParticleCopy = haloParticle;
369 if (
utils::inBox(haloParticleCopy.getR(), boxMin, boxMax)) {
371 "LogicHandler: Trying to add a halo particle that is not outside the box of the container.\n"
378 if (not _neighborListsAreValid.load(std::memory_order_relaxed)) {
383 bool updated = _currentContainer->updateHaloParticle(haloParticleCopy);
389 _numParticlesHalo.fetch_add(1, std::memory_order_relaxed);
396 _neighborListsAreValid.store(
false, std::memory_order_relaxed);
397 _currentContainer->deleteAllParticles();
398 std::for_each(_particleBuffer.begin(), _particleBuffer.end(), [](
auto &buffer) { buffer.clear(); });
399 std::for_each(_haloParticleBuffer.begin(), _haloParticleBuffer.end(), [](
auto &buffer) { buffer.clear(); });
401 _numParticlesOwned.store(0, std::memory_order_relaxed);
402 _numParticlesHalo.store(0, std::memory_order_relaxed);
413 auto &bufferCollection = particle.isOwned() ? _particleBuffer : _haloParticleBuffer;
414 for (
auto &cell : bufferCollection) {
415 auto &buffer = cell._particles;
417 if (not buffer.empty() and &(buffer.front()) <= &particle and &particle <= &(buffer.back())) {
418 const bool isRearParticle = &particle == &buffer.back();
420 particle = buffer.back();
422 return {
true, not isRearParticle};
425 return {
false,
true};
434 if (particle.isOwned()) {
435 _numParticlesOwned.fetch_sub(1, std::memory_order_relaxed);
437 _numParticlesHalo.fetch_sub(1, std::memory_order_relaxed);
461 template <
class Functor>
470 template <
class Iterator>
472 typename Iterator::ParticleVecType additionalVectors;
473 if (not(behavior & IteratorBehavior::containerOnly)) {
474 additionalVectors.reserve(
static_cast<bool>(behavior & IteratorBehavior::owned) * _particleBuffer.size() +
475 static_cast<bool>(behavior & IteratorBehavior::halo) * _haloParticleBuffer.size());
476 if (behavior & IteratorBehavior::owned) {
477 for (
auto &buffer : _particleBuffer) {
481 if (not buffer.isEmpty()) {
482 additionalVectors.push_back(&(buffer._particles));
486 if (behavior & IteratorBehavior::halo) {
487 for (
auto &buffer : _haloParticleBuffer) {
488 if (not buffer.isEmpty()) {
489 additionalVectors.push_back(&(buffer._particles));
494 return additionalVectors;
501 auto additionalVectors = gatherAdditionalVectors<ContainerIterator<Particle_T, true, false>>(behavior);
502 return _currentContainer->begin(behavior, std::ref(additionalVectors));
509 auto additionalVectors =
512 return _currentContainer->begin(behavior, std::ref(additionalVectors));
519 const std::array<double, 3> &higherCorner,
520 IteratorBehavior behavior) {
522 for (
size_t d = 0; d < 3; ++d) {
523 if (lowerCorner[d] > higherCorner[d]) {
525 "Requesting region Iterator where the upper corner is lower than the lower corner!\n"
528 lowerCorner, higherCorner);
532 auto additionalVectors = gatherAdditionalVectors<ContainerIterator<Particle_T, true, true>>(behavior);
533 return _currentContainer->getRegionIterator(lowerCorner, higherCorner, behavior, std::ref(additionalVectors));
540 const std::array<double, 3> &higherCorner,
541 IteratorBehavior behavior)
const {
543 for (
size_t d = 0; d < 3; ++d) {
544 if (lowerCorner[d] > higherCorner[d]) {
546 "Requesting region Iterator where the upper corner is lower than the lower corner!\n"
549 lowerCorner, higherCorner);
553 auto additionalVectors =
555 return std::as_const(_currentContainer)
556 ->getRegionIterator(lowerCorner, higherCorner, behavior, std::ref(additionalVectors));
594 template <
class Functor>
618 std::tuple<const std::vector<FullParticleCell<Particle_T>> &,
const std::vector<FullParticleCell<Particle_T>> &>
633#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
634 const auto numRebuilds = considerOnlyLastNonTuningPhase ? _numRebuildsInNonTuningPhase : _numRebuilds;
636 const auto iterationCount =
637 considerOnlyLastNonTuningPhase ? _iteration - _iterationAfterLastTuningPhase : _iteration + 1;
638 if (numRebuilds == 0) {
639 return static_cast<double>(_neighborListRebuildFrequency);
641 return static_cast<double>(iterationCount) / numRebuilds;
644 return static_cast<double>(_neighborListRebuildFrequency);
658 double maxVelocity = 0;
661 for (
auto iter = this->
begin(IteratorBehavior::owned | IteratorBehavior::containerOnly); iter.isValid(); ++iter) {
662 std::array<double, 3> tempVel = iter->getV();
663 double tempVelAbs = sqrt(dot(tempVel, tempVel));
664 maxVelocity = std::max(tempVelAbs, maxVelocity);
667 return skin / maxVelocity / deltaT / 2;
710 void initSpatialLocks(
const std::array<double, 3> &boxLength,
double interactionLengthInv) {
711 using namespace autopas::utils::ArrayMath::literals;
721 constexpr size_t maxNumSpacialLocks{1000000};
724 const std::array<size_t, 3> locksPerDim = [&]() {
727 const std::array<size_t, 3> locksPerDimNaive =
728 static_cast_copy_array<size_t>(ceil(boxLength * interactionLengthInv));
729 const auto totalLocksNaive =
730 std::accumulate(locksPerDimNaive.begin(), locksPerDimNaive.end(), 1ul, std::multiplies<>());
732 if (totalLocksNaive <= maxNumSpacialLocks) {
733 return locksPerDimNaive;
737 const std::array<double, 3> boxSideProportions = {
739 boxLength[0] / boxLength[1],
740 boxLength[0] / boxLength[2],
743 const auto prodProportions =
744 std::accumulate(boxSideProportions.begin(), boxSideProportions.end(), 1., std::multiplies<>());
746 const auto locksInFirstDimFloat = std::floor(std::cbrt(maxNumSpacialLocks * prodProportions));
748 const std::array<size_t, 3> locksPerDimLimited = {
749 static_cast<size_t>(locksInFirstDimFloat),
750 static_cast<size_t>(locksInFirstDimFloat / boxSideProportions[1]),
751 static_cast<size_t>(locksInFirstDimFloat / boxSideProportions[2]),
753 return locksPerDimLimited;
756 _spatialLocks.resize(locksPerDim[0]);
757 for (
auto &lockVecVec : _spatialLocks) {
758 lockVecVec.resize(locksPerDim[1]);
759 for (
auto &lockVec : lockVecVec) {
760 lockVec.resize(locksPerDim[2]);
761 for (
auto &lockPtr : lockVec) {
763 lockPtr = std::make_unique<std::mutex>();
777 template <
class Functor>
778 std::tuple<Configuration, std::unique_ptr<TraversalInterface>,
bool> selectConfiguration(
779 Functor &functor,
const InteractionTypeOption &interactionType);
801 template <
class Functor>
814 template <
class Functor>
815 void computeRemainderInteractions(
Functor &functor,
bool newton3,
bool useSoA);
822 void checkMinimalSize()
const;
828 unsigned int _neighborListRebuildFrequency;
833 unsigned int _verletClusterSize;
838 size_t _numRebuilds{0};
844 size_t _numRebuildsInNonTuningPhase{0};
849 size_t _aosSortingThreshold;
854 size_t _soaSortingThreshold;
856 std::shared_ptr<TuningManager> _tuningManager;
861 std::unique_ptr<ParticleContainerInterface<Particle_T>> _currentContainer{
nullptr};
881 std::set<InteractionTypeOption> _interactionTypes{};
886 std::atomic<bool> _neighborListsAreValid{
false};
891 size_t _stepsSinceLastListRebuild{0};
897 size_t _iteration{std::numeric_limits<size_t>::max()};
902 size_t _iterationAfterLastTuningPhase{0};
907 std::atomic<size_t> _numParticlesOwned{0ul};
912 std::atomic<size_t> _numParticlesHalo{0ul};
917 std::vector<FullParticleCell<Particle_T>> _particleBuffer;
922 std::vector<FullParticleCell<Particle_T>> _haloParticleBuffer;
929 std::vector<std::vector<std::vector<std::unique_ptr<std::mutex>>>> _spatialLocks;
940 bool _neighborListInvalidDoDynamicRebuild{
false};
945 void updateRebuildPositions();
958template <
typename Particle_T>
960#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
965 for (
auto iter = this->begin(IteratorBehavior::owned | IteratorBehavior::containerOnly); iter.isValid(); ++iter) {
966 iter->resetRAtRebuild();
971template <
typename Particle_T>
974 for (
unsigned int dim = 0; dim < 3; ++dim) {
975 if (_currentContainer->getBoxMax()[dim] - _currentContainer->getBoxMin()[dim] <
976 _currentContainer->getInteractionLength()) {
978 "Box (boxMin[{}]={} and boxMax[{}]={}) is too small.\nHas to be at least cutoff({}) + skin({}) = {}.", dim,
979 _currentContainer->getBoxMin()[dim], dim, _currentContainer->getBoxMax()[dim], _currentContainer->getCutoff(),
980 _currentContainer->getVerletSkin(), _currentContainer->getCutoff() + _currentContainer->getVerletSkin());
985template <
typename Particle_T>
987 return _neighborListInvalidDoDynamicRebuild;
990template <
typename Particle_T>
992 if (_stepsSinceLastListRebuild >= _neighborListRebuildFrequency
993#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
994 or getNeighborListsInvalidDoDynamicRebuild()
996 or _tuningManager->requiresRebuilding(_iteration)) {
997 _neighborListsAreValid.store(
false, std::memory_order_relaxed);
1000 return _neighborListsAreValid.load(std::memory_order_relaxed);
1003template <
typename Particle_T>
1005#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
1006 const auto skin = getContainer().getVerletSkin();
1008 const auto halfSkinSquare = skin * skin * 0.25;
1012 AUTOPAS_OPENMP(parallel reduction(or : _neighborListInvalidDoDynamicRebuild))
1013 for (
auto iter = this->begin(IteratorBehavior::owned | IteratorBehavior::containerOnly); iter.isValid(); ++iter) {
1014 const auto distance = iter->calculateDisplacementSinceRebuild();
1017 _neighborListInvalidDoDynamicRebuild |= distanceSquare >= halfSkinSquare;
1022template <
typename Particle_T>
1024 _neighborListInvalidDoDynamicRebuild =
false;
1027template <
typename Particle_T>
1031 auto exchangeBuffer = [](
const auto &newBuffers,
auto &oldBuffers,
auto &particleCounter) {
1033 if (oldBuffers.size() < newBuffers.size()) {
1035 "The number of new buffers ({}) is larger than number of existing buffers ({})!", newBuffers.size(),
1040 const auto numParticlesInOldBuffers =
1041 std::transform_reduce(oldBuffers.begin(), std::next(oldBuffers.begin(), newBuffers.size()), 0, std::plus<>(),
1042 [](
const auto &cell) { return cell.size(); });
1043 particleCounter.fetch_sub(numParticlesInOldBuffers, std::memory_order_relaxed);
1046 size_t numParticlesInNewBuffers = 0;
1047 for (
size_t i = 0; i < newBuffers.size(); ++i) {
1048 oldBuffers[i].clear();
1049 for (
const auto &p : newBuffers[i]) {
1050 ++numParticlesInNewBuffers;
1051 oldBuffers[i].addParticle(p);
1055 particleCounter.fetch_add(numParticlesInNewBuffers, std::memory_order_relaxed);
1058 exchangeBuffer(particleBuffers, _particleBuffer, _numParticlesOwned);
1059 exchangeBuffer(haloParticleBuffers, _haloParticleBuffer, _numParticlesHalo);
1062template <
typename Particle_T>
1063std::tuple<const std::vector<FullParticleCell<Particle_T>> &,
const std::vector<FullParticleCell<Particle_T>> &>
1065 return {_particleBuffer, _haloParticleBuffer};
1068template <
typename Particle_T>
1069template <
class Functor>
1072 constexpr auto interactionType = [] {
1074 return InteractionTypeOption::pairwise;
1076 return InteractionTypeOption::triwise;
1079 "LogicHandler::computeInteractions(): Functor is not valid. Only pairwise and triwise functors are "
1081 "Please use a functor derived from "
1082 "PairwiseFunctor or TriwiseFunctor.");
1086 auto &autoTuner = *_tuningManager->getAutoTuners()[interactionType];
1091 long energyTotalRebuild;
1093 const bool energyMeasurementsPossible = autoTuner.resetEnergy();
1095 timerRebuild.
start();
1099 if (not _neighborListsAreValid.load(std::memory_order_relaxed)) {
1100#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
1101 this->updateRebuildPositions();
1103 _currentContainer->rebuildNeighborLists(&traversal);
1104#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
1105 this->resetNeighborListsInvalidDoDynamicRebuild();
1107 if (not autoTuner.inTuningPhase()) {
1108 _numRebuildsInNonTuningPhase++;
1111 _neighborListsAreValid.store(
true, std::memory_order_relaxed);
1113 timerRebuild.
stop();
1114 std::tie(std::ignore, std::ignore, std::ignore, energyTotalRebuild) = autoTuner.sampleEnergy();
1117 const auto cellToVec = [](
auto &cell) -> std::vector<Particle_T> & {
return cell._particles; };
1122 if constexpr (std::is_base_of_v<InteractionListGeneratorFunctor<Particle_T, false>,
Functor> or
1123 std::is_base_of_v<InteractionListGeneratorFunctor<Particle_T, true>,
Functor>) {
1124 functor.initializeNeighborList(this->begin(IteratorBehavior::ownedOrHalo));
1127 timerComputeInteractions.
start();
1128 _currentContainer->computeInteractions(&traversal);
1129 timerComputeInteractions.
stop();
1131 timerComputeRemainder.
start();
1132 const bool newton3 = autoTuner.getCurrentConfig().newton3;
1133 const auto dataLayout = autoTuner.getCurrentConfig().dataLayout;
1134 computeRemainderInteractions(functor, newton3, dataLayout);
1135 timerComputeRemainder.
stop();
1139 const auto [energyWatts, energyJoules, energyDeltaT, energyTotal] = autoTuner.sampleEnergy();
1142 constexpr auto nanD = std::numeric_limits<double>::quiet_NaN();
1143 constexpr auto nanL = std::numeric_limits<long>::quiet_NaN();
1148 energyMeasurementsPossible,
1149 energyMeasurementsPossible ? energyWatts : nanD,
1150 energyMeasurementsPossible ? energyJoules : nanD,
1151 energyMeasurementsPossible ? energyDeltaT : nanD,
1152 energyMeasurementsPossible ? energyTotalRebuild : nanL,
1153 energyMeasurementsPossible ? energyTotal - energyTotalRebuild
1155 energyMeasurementsPossible ? energyTotal : nanL};
1158template <
typename Particle_T>
1159template <
class Functor>
1164 _remainderPairwiseInteractionHandler.template computeRemainderInteractions<true>(
1165 &functor, actualContainerType, _particleBuffer, _haloParticleBuffer, useSoA);
1167 _remainderPairwiseInteractionHandler.template computeRemainderInteractions<false>(
1168 &functor, actualContainerType, _particleBuffer, _haloParticleBuffer, useSoA);
1172 _remainderTriwiseInteractionHandler.template computeRemainderInteractions<true>(
1173 &functor, actualContainerType, _particleBuffer, _haloParticleBuffer);
1175 _remainderTriwiseInteractionHandler.template computeRemainderInteractions<false>(
1176 &functor, actualContainerType, _particleBuffer, _haloParticleBuffer);
1182template <
typename Particle_T>
1183template <
class Functor>
1185 Functor &functor,
const InteractionTypeOption &interactionType) {
1189#ifdef AUTOPAS_LOG_LIVEINFO
1190 auto particleIter = this->begin(IteratorBehavior::ownedOrHalo);
1191 info.gather(particleIter, _neighborListRebuildFrequency, getNumberOfParticlesOwned(), _logicHandlerInfo.boxMin,
1192 _logicHandlerInfo.boxMax, _logicHandlerInfo.cutoff, _logicHandlerInfo.verletSkin);
1193 _liveInfoLogger.logLiveInfo(info, _iteration);
1198 auto configuration = _tuningManager->getCurrentConfig(interactionType);
1199 auto [traversalPtr, _] = isConfigurationApplicable(configuration, functor);
1201 if (not traversalPtr) {
1204 "LogicHandler: Functor {} is not relevant for tuning but the given configuration is not applicable!",
1208 return {configuration, std::move(traversalPtr),
false};
1211 if (_tuningManager->needsLiveInfo(_iteration)) {
1213 if (info.get().empty()) {
1214 auto particleIter = this->begin(IteratorBehavior::ownedOrHalo);
1215 info.gather(particleIter, _neighborListRebuildFrequency, getNumberOfParticlesOwned(), _logicHandlerInfo.boxMin,
1216 _logicHandlerInfo.boxMax, _logicHandlerInfo.cutoff, _logicHandlerInfo.verletSkin);
1220 size_t numRejectedConfigs = 0;
1222 selectConfigurationTimer.
start();
1224 auto stillTuning = _tuningManager->tune(_iteration, info);
1226 auto configuration = _tuningManager->getCurrentConfig(interactionType);
1231 auto [traversalPtr, rejectIndefinitely] = isConfigurationApplicable(configuration, functor);
1234 selectConfigurationTimer.
stop();
1235 AutoPasLog(TRACE,
"Select Configuration took {} ms. A total of {} configurations were rejected.",
1236 selectConfigurationTimer.
getTotalTime(), numRejectedConfigs);
1237 return {configuration, std::move(traversalPtr), stillTuning};
1239 numRejectedConfigs++;
1241 configuration = _tuningManager->rejectConfiguration(configuration, rejectIndefinitely, interactionType);
1245template <
typename Particle_T>
1249 if (_currentContainer !=
nullptr and newContainer !=
nullptr) {
1251 const auto numParticlesTotal = _currentContainer->size();
1253 numParticlesTotal, _currentContainer->getBoxMin(), _currentContainer->getBoxMax(),
1254 _currentContainer->getInteractionLength());
1256 newContainer->reserve(numParticlesTotal, numParticlesHalo);
1257 for (
auto particleIter = _currentContainer->begin(IteratorBehavior::ownedOrHalo); particleIter.isValid();
1260 if (particleIter->isOwned()) {
1261 newContainer->addParticle(*particleIter);
1263 newContainer->addHaloParticle(*particleIter);
1268 _currentContainer = std::move(newContainer);
1271template <
typename Particle_T>
1272template <
class Functor>
1274 const InteractionTypeOption &interactionType) {
1275 if (not _interactionTypes.contains(interactionType)) {
1277 "LogicHandler::computeInteractionsPipeline(): AutPas was not initialized for the Functor's interactions type: "
1283 tuningTimer.
start();
1284 const auto [configuration, traversalPtr, stillTuning] = selectConfiguration(*functor, interactionType);
1286 _tuningManager->logTuningResult(tuningTimer.
getTotalTime(), _iteration, interactionType);
1289 const auto rebuildIteration = not _neighborListsAreValid.load(std::memory_order_relaxed);
1292 AutoPasLog(DEBUG,
"Iterating with configuration: {} tuning: {}", configuration.toString(), stillTuning);
1296 auto bufferSizeListing = [](
const auto &buffers) -> std::string {
1297 std::stringstream ss;
1299 for (
const auto &buffer : buffers) {
1300 ss << buffer.size() <<
", ";
1301 sum += buffer.size();
1303 ss <<
" Total: " << sum;
1306 AutoPasLog(TRACE,
"particleBuffer size : {}", bufferSizeListing(_particleBuffer));
1307 AutoPasLog(TRACE,
"haloParticleBuffer size : {}", bufferSizeListing(_haloParticleBuffer));
1308 AutoPasLog(DEBUG,
"Type of interaction : {}", interactionType.to_string());
1317 _iterationLogger.logIteration(configuration, _iteration, functor->
getName(), stillTuning, tuningTimer.
getTotalTime(),
1327 const auto measurement = [&]() {
1328 switch (_tuningManager->getTuningMetric(interactionType)) {
1336 return std::make_pair(0l, 0l);
1339 _tuningManager->addMeasurement(measurement.first, measurement.second, rebuildIteration, _iteration,
1343 AutoPasLog(TRACE,
"Skipping adding of sample because functor is not marked relevant.");
1348template <
typename Particle_T>
1349template <
class Functor>
1356 "A configuration was rejected by LogicHandler::isConfigurationApplicable, as it was incompatible"
1357 " independently of domain or functor. This should not occur and implies illegal configurations are being added"
1358 " to the configuration queue during simulation (potentially by a tuning strategy).");
1361 return {
nullptr,
true};
1367 AutoPasLog(DEBUG,
"Configuration rejected: The functor doesn't support Newton 3 {}!", config.
newton3);
1368 return {
nullptr,
true};
1373 AutoPasLog(DEBUG,
"Configuration rejected: The functor doesn't support the Vectorization Pattern {}!",
1375 return {
nullptr,
true};
1378 std::unique_ptr<ParticleContainerInterface<Particle_T>> containerPtr{
nullptr};
1379 auto containerInfo =
1381 _currentContainer->getCutoff(), config.
cellSizeFactor, _currentContainer->getVerletSkin(),
1382 _verletClusterSize, _aosSortingThreshold, _soaSortingThreshold, config.
loadEstimator);
1386 const bool generateNewContainer = _currentContainer ==
nullptr or
1387 _currentContainer->getContainerType() != config.
container or
1388 containerInfo != _currentContainerSelectorInfo;
1390 if (generateNewContainer) {
1396 const auto traversalInfo =
1397 generateNewContainer ? containerPtr->getTraversalSelectorInfo() : _currentContainer->getTraversalSelectorInfo();
1401 TraversalSelector::generateTraversalFromConfig<Particle_T, Functor>(config, functor, traversalInfo);
1406 if (traversalPtr and generateNewContainer) {
1407 _currentContainerSelectorInfo = containerInfo;
1408 setCurrentContainer(std::move(containerPtr));
1411 return {std::move(traversalPtr),
false};
#define AutoPasLog(lvl, fmt,...)
Macro for logging providing common meta information without filename.
Definition: Logger.h:24
#define AUTOPAS_OPENMP(args)
Empty macro to throw away any arguments.
Definition: WrapOpenMP.h:126
Class containing multiple options that form an algorithm configuration for the pairwise iteration.
Definition: Configuration.h:26
std::string toString() const
Returns string representation in JSON style of the configuration object.
Definition: Configuration.cpp:12
LoadEstimatorOption loadEstimator
Load Estimator option.
Definition: Configuration.h:146
double cellSizeFactor
CellSizeFactor.
Definition: Configuration.h:158
ContainerOption container
Container option.
Definition: Configuration.h:134
Newton3Option newton3
Newton 3 option.
Definition: Configuration.h:154
VectorizationPatternOption vecPattern
Vectorization Pattern option.
Definition: Configuration.h:142
bool hasCompatibleValues() const
Checks if any of the configuration values are incompatible with each other.
Definition: Configuration.cpp:53
Public iterator class that iterates over a particle container and additional vectors (which are typic...
Definition: ContainerIterator.h:95
Info to generate a container.
Definition: ContainerSelectorInfo.h:17
std::array< double, 3 > boxMin
Lower corner of the container.
Definition: ContainerSelectorInfo.h:97
std::array< double, 3 > boxMax
Upper corner of the container.
Definition: ContainerSelectorInfo.h:102
static std::unique_ptr< ParticleContainerInterface< Particle_T > > generateContainer(ContainerOption containerChoice, const ContainerSelectorInfo &containerInfo)
Container factory method.
Definition: ContainerSelector.h:44
Helper to log FLOP count and HitRate for AutoPas::iteratePairwise() calls with the functors in the mo...
Definition: FLOPLogger.h:30
This class handles the storage of particles in their full form.
Definition: FullParticleCell.h:26
Functor base class.
Definition: Functor.h:41
virtual size_t getNumFLOPs() const
Get the number of FLOPs.
Definition: Functor.h:206
virtual bool isVecPatternAllowed(const VectorizationPatternOption::Value vecPattern)=0
Specifies whether the functor is capable of using the specified Vectorization Pattern in the SoA func...
virtual bool allowsNewton3()=0
Specifies whether the functor is capable of Newton3-like functors.
virtual void setVecPattern(const VectorizationPatternOption::Value vecPattern)
Setter for the vectorization pattern to be used.
Definition: Functor.h:197
virtual void initTraversal()
This function is called at the start of each traversal.
Definition: Functor.h:64
virtual bool allowsNonNewton3()=0
Specifies whether the functor is capable of non-Newton3-like functors.
virtual void endTraversal(bool newton3)
This function is called at the end of each traversal.
Definition: Functor.h:71
virtual bool isRelevantForTuning()=0
Specifies whether the functor should be considered for the auto-tuning process.
virtual std::string getName()=0
Returns name of functor.
virtual double getHitRate() const
Get the hit rate.
Definition: Functor.h:216
Helper to log performance data of AutoPas::computeInteractions() to a csv file for easier analysis.
Definition: IterationLogger.h:24
Helper to log the collected LiveInfo data during tuning to a csv file for easier analysis.
Definition: LiveInfoLogger.h:23
This class is able to gather and store important information for a tuning phase from a container and ...
Definition: LiveInfo.h:33
Class that wraps all arguments for the logic handler to provide a more stable API.
Definition: LogicHandlerInfo.h:16
double verletSkin
Length added to the cutoff for the Verlet lists' skin.
Definition: LogicHandlerInfo.h:33
std::array< double, 3 > boxMax
Upper corner of the container without halo.
Definition: LogicHandlerInfo.h:25
double deltaT
Time step used in the simulation.
Definition: LogicHandlerInfo.h:52
double cutoff
Cutoff radius to be used in this simulation.
Definition: LogicHandlerInfo.h:29
std::array< double, 3 > boxMin
Lower corner of the container without halo.
Definition: LogicHandlerInfo.h:21
The LogicHandler takes care of the containers s.t.
Definition: LogicHandler.h:51
void setParticleBuffers(const std::vector< FullParticleCell< Particle_T > > &particleBuffers, const std::vector< FullParticleCell< Particle_T > > &haloParticleBuffers)
Directly exchange the internal particle and halo buffers with the given vectors and update particle c...
Definition: LogicHandler.h:1028
void reserve(size_t numParticles, size_t numHaloParticles)
Reserves space in the particle buffers and the container.
Definition: LogicHandler.h:318
std::tuple< std::unique_ptr< TraversalInterface >, bool > isConfigurationApplicable(const Configuration &config, Functor &functor)
Checks if the given configuration can be used with the given functor and the current state of the sim...
Definition: LogicHandler.h:1350
ContainerIterator< Particle_T, true, false > begin(IteratorBehavior behavior)
Iterate over all particles by using for(auto iter = autoPas.begin(); iter.isValid(); ++iter)
Definition: LogicHandler.h:500
std::vector< Particle_T > updateContainer()
Updates the container.
Definition: LogicHandler.h:164
unsigned long getNumberOfParticlesOwned() const
Get the number of owned particles.
Definition: LogicHandler.h:563
bool computeInteractionsPipeline(Functor *functor, const InteractionTypeOption &interactionType)
This function covers the full pipeline of all mechanics happening during the computation of particle ...
Definition: LogicHandler.h:1273
std::tuple< const std::vector< FullParticleCell< Particle_T > > &, const std::vector< FullParticleCell< Particle_T > > & > getParticleBuffers() const
Getter for the particle buffers.
Definition: LogicHandler.h:1064
void addParticle(const Particle_T &p)
Adds a particle to the container.
Definition: LogicHandler.h:338
void decreaseParticleCounter(Particle_T &particle)
Decrease the correct internal particle counters.
Definition: LogicHandler.h:433
std::vector< Particle_T > collectLeavingParticlesFromBuffer(bool insertOwnedParticlesToContainer)
Collects leaving particles from buffer and potentially inserts owned particles to the container.
Definition: LogicHandler.h:111
bool neighborListsAreValid()
Checks if in the next iteration the neighbor lists have to be rebuilt.
Definition: LogicHandler.h:991
unsigned long getNumberOfParticlesHalo() const
Get the number of halo particles.
Definition: LogicHandler.h:569
std::tuple< bool, bool > deleteParticleFromBuffers(Particle_T &particle)
Takes a particle, checks if it is in any of the particle buffers, and deletes it from them if found.
Definition: LogicHandler.h:411
LogicHandler(const std::shared_ptr< TuningManager > &tunerManager, const LogicHandlerInfo &logicHandlerInfo, unsigned int rebuildFrequency, const std::string &outputSuffix)
Constructor of the LogicHandler.
Definition: LogicHandler.h:60
double getVelocityMethodRFEstimate(const double skin, const double deltaT) const
Estimates the rebuild frequency based on the current maximum velocity in the container Using the form...
Definition: LogicHandler.h:655
void checkNeighborListsInvalidDoDynamicRebuild()
Checks if any particle has moved more than skin/2.
Definition: LogicHandler.h:1004
Iterator::ParticleVecType gatherAdditionalVectors(IteratorBehavior behavior)
Create the additional vectors vector for a given iterator behavior.
Definition: LogicHandler.h:471
ParticleContainerInterface< Particle_T > & getContainer()
Returns a non-const reference to the currently selected particle container.
Definition: LogicHandler.h:104
void addHaloParticle(const Particle_T &haloParticle)
Adds a particle to the container that lies in the halo region of the container.
Definition: LogicHandler.h:365
ContainerIterator< Particle_T, false, true > getRegionIterator(const std::array< double, 3 > &lowerCorner, const std::array< double, 3 > &higherCorner, IteratorBehavior behavior) const
Iterate over all particles in a specified region.
Definition: LogicHandler.h:539
void deleteAllParticles()
Deletes all particles.
Definition: LogicHandler.h:395
ContainerIterator< Particle_T, false, false > begin(IteratorBehavior behavior) const
Iterate over all particles by using for(auto iter = autoPas.begin(); iter.isValid(); ++iter)
Definition: LogicHandler.h:508
bool getNeighborListsInvalidDoDynamicRebuild()
getter function for _neighborListInvalidDoDynamicRebuild
Definition: LogicHandler.h:986
void resetNeighborListsInvalidDoDynamicRebuild()
Checks if any particle has moved more than skin/2.
Definition: LogicHandler.h:1023
double getMeanRebuildFrequency(bool considerOnlyLastNonTuningPhase=false) const
Getter for the mean rebuild frequency.
Definition: LogicHandler.h:632
std::vector< Particle_T > resizeBox(const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax)
Pass values to the actual container.
Definition: LogicHandler.h:225
void reserve(size_t numParticles)
Estimates the number of halo particles via autopas::utils::NumParticlesEstimator::estimateNumHalosUni...
Definition: LogicHandler.h:305
ContainerIterator< Particle_T, true, true > getRegionIterator(const std::array< double, 3 > &lowerCorner, const std::array< double, 3 > &higherCorner, IteratorBehavior behavior)
Iterate over all particles in a specified region.
Definition: LogicHandler.h:518
The ParticleContainerInterface class provides a basic interface for all Containers within AutoPas.
Definition: ParticleContainerInterface.h:38
Handles pairwise interactions involving particle buffers (particles not yet inserted into the main co...
Definition: RemainderPairwiseInteractionHandler.h:31
Handles triwise interactions involving particle buffers (particles not yet inserted into the main con...
Definition: RemainderTriwiseInteractionHandler.h:30
This interface serves as a common parent class for all traversals.
Definition: TraversalInterface.h:18
@ energy
Optimize for least energy usage.
Definition: TuningMetricOption.h:31
@ time
Optimize for shortest simulation time.
Definition: TuningMetricOption.h:27
static void exception(const Exception e)
Handle an exception derived by std::exception.
Definition: ExceptionHandler.h:64
Timer class to stop times.
Definition: Timer.h:27
void start()
start the timer.
Definition: Timer.cpp:17
long getTotalTime() const
Get total accumulated time.
Definition: Timer.h:60
long stop()
Stops the timer and returns the time elapsed in nanoseconds since the last call to start.
Definition: Timer.cpp:25
A wrapper around autopas::utils::Timer that only compiles implementation logic if the SPDLOG_ACTIVE_L...
Definition: TraceTimer.h:20
long getTotalTime() const
Get total accumulated time.
Definition: TraceTimer.h:63
void start()
start the timer.
Definition: TraceTimer.h:25
long stop()
Stops the timer and returns the time elapsed in nanoseconds since the last call to start.
Definition: TraceTimer.h:34
void markParticleAsDeleted(Particle_T &p)
Marks a particle as deleted.
Definition: markParticleAsDeleted.h:23
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 > ceil(const std::array< T, SIZE > &a)
For each element in a, computes the smallest integer value not less than the element.
Definition: ArrayMath.h:316
void balanceVectors(OuterContainerT &vecvec)
Given a collection of vectors, redistributes the elements of the vectors so they all have the same (o...
Definition: ArrayUtils.h:151
constexpr std::array< output_t, SIZE > static_cast_copy_array(const std::array< input_t, SIZE > &a)
Creates a new array by performing an element-wise static_cast<>.
Definition: ArrayUtils.h:33
void to_string(std::ostream &os, const Container &container, const std::string &delimiter, const std::array< std::string, 2 > &surround, Fun elemToString)
Generates a string representation of a container which fulfills the Container requirement (provide cb...
Definition: ArrayUtils.h:54
size_t estimateNumHalosUniform(size_t numParticles, const std::array< double, 3 > &boxMin, const std::array< double, 3 > &boxMax, double haloWidth)
Given a number of particles and the dimensions of a box, estimate the number of halo particles.
Definition: NumParticlesEstimator.cpp:9
decltype(isTriwiseFunctorImpl(std::declval< FunctorT >())) isTriwiseFunctor
Check whether a Functor Type is inheriting from TriwiseFunctor.
Definition: checkFunctorType.h:56
bool notInBox(const std::array< T, 3 > &position, const std::array< T, 3 > &low, const std::array< T, 3 > &high)
Checks if position is not inside of a box defined by low and high.
Definition: inBox.h:50
decltype(isPairwiseFunctorImpl(std::declval< FunctorT >())) isPairwiseFunctor
Check whether a Functor Type is inheriting from PairwiseFunctor.
Definition: checkFunctorType.h:49
bool inBox(const std::array< T, 3 > &position, const std::array< T, 3 > &low, const std::array< T, 3 > &high)
Checks if position is inside of a box defined by low and high.
Definition: inBox.h:26
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:34
int autopas_get_max_threads()
Dummy for omp_get_max_threads() when no OpenMP is available.
Definition: WrapOpenMP.h:144
@ halo
Halo state, a particle with this state is an actual particle, but not owned by the current AutoPas ob...
@ owned
Owned state, a particle with this state is an actual particle and owned by the current AutoPas object...
decltype(auto) withStaticContainerType(ParticleContainerInterface< Particle_T > &container, FunctionType &&function)
Will execute the passed function body with the static container type of container.
Definition: StaticContainerSelector.h:35
int autopas_get_thread_num()
Dummy for omp_set_lock() when no OpenMP is available.
Definition: WrapOpenMP.h:132
Struct to collect all sorts of measurements taken during a computeInteractions iteration.
Definition: IterationMeasurements.h:13
double energyWatts
Average energy consumed per time in Watts.
Definition: IterationMeasurements.h:42
double energyDeltaT
Time in seconds during which energy was consumed.
Definition: IterationMeasurements.h:52
long timeRebuild
Time it takes for rebuilding neighbor lists.
Definition: IterationMeasurements.h:27
long timeTotal
Time it takes for the complete iteratePairwise pipeline.
Definition: IterationMeasurements.h:32
long energyTotalRebuild
Total energy consumed during rebuilding.
Definition: IterationMeasurements.h:57
long timeRemainderTraversal
Time it takes for the Remainder Traversal.
Definition: IterationMeasurements.h:22
long energyTotalNonRebuild
Total energy consumed during compute interactions and remainder traversal.
Definition: IterationMeasurements.h:62
long timeComputeInteractions
Time it takes for the LogicHandler's computeInteractions() function.
Definition: IterationMeasurements.h:17
bool energyMeasurementsPossible
Bool whether energy measurements are currently possible.
Definition: IterationMeasurements.h:37
double energyJoules
Total energy consumed in Joules.
Definition: IterationMeasurements.h:47