48template <
typename Particle_T>
59 unsigned int rebuildFrequency,
const std::string &outputSuffix)
60 : _tuningManager(tunerManager),
61 _logicHandlerInfo(logicHandlerInfo),
62 _neighborListRebuildFrequency{rebuildFrequency},
65 _remainderPairwiseInteractionHandler(_spatialLocks),
66 _remainderTriwiseInteractionHandler(_spatialLocks),
67 _verletClusterSize(logicHandlerInfo.verletClusterSize),
68 _sortingThreshold(logicHandlerInfo.sortingThreshold),
69 _iterationLogger(outputSuffix,
70 std::any_of(tunerManager->getAutoTuners().
begin(), tunerManager->getAutoTuners().end(),
71 [](const auto &tuner) {
return tuner.second->canMeasureEnergy(); })),
72 _flopLogger(outputSuffix),
73 _liveInfoLogger(outputSuffix) {
74 using namespace autopas::utils::ArrayMath::literals;
76 for (
const auto &[interactionType, tuner] : tunerManager->getAutoTuners()) {
77 _interactionTypes.insert(interactionType);
79 const auto configuration = tuner->getCurrentConfig();
84 configuration.cellSizeFactor,
88 configuration.loadEstimator};
95 const auto interactionLength = logicHandlerInfo.cutoff + logicHandlerInfo.verletSkin;
96 const auto interactionLengthInv = 1. / interactionLength;
97 const auto boxLengthWithHalo = logicHandlerInfo.boxMax - logicHandlerInfo.boxMin + (2 * interactionLength);
98 initSpatialLocks(boxLengthWithHalo, interactionLengthInv);
113 const auto &boxMin = _currentContainer->getBoxMin();
114 const auto &boxMax = _currentContainer->getBoxMax();
115 std::vector<Particle_T> leavingBufferParticles{};
116 for (
auto &cell : _particleBuffer) {
117 auto &buffer = cell._particles;
118 if (insertOwnedParticlesToContainer) {
120 for (
auto &p : buffer) {
126 _currentContainer->addParticle(p);
128 leavingBufferParticles.push_back(p);
133 for (
auto iter = buffer.begin(); iter < buffer.end();) {
136 auto fastRemoveP = [&]() {
138 std::swap(p, buffer.back());
150 if (not buffer.empty() and
utils::notInBox(p.getR(), boxMin, boxMax)) {
151 leavingBufferParticles.push_back(p);
159 return leavingBufferParticles;
168#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
171 if (_tuningManager->isStartOfTuningPhase(_iteration)) {
172 _numRebuildsInNonTuningPhase = 0;
181 if (_tuningManager->inFirstConfigurationLastSample(_iteration)) {
184 double rebuildFrequencyEstimate =
186 double userProvidedRF =
static_cast<double>(_neighborListRebuildFrequency);
191 _tuningManager->setRebuildFrequency(std::min(userProvidedRF, rebuildFrequencyEstimate));
196 if (_tuningManager->tuningPhaseJustFinished()) {
197 _iterationAfterLastTuningPhase = _iteration;
200 if (not _neighborListsAreValid.load(std::memory_order_relaxed)) {
201 _stepsSinceLastListRebuild = 0;
203 ++_stepsSinceLastListRebuild;
208 AutoPasLog(TRACE,
"Initiating container update.");
209 auto leavingParticles = _currentContainer->updateContainer(not doDataStructureUpdate);
210 leavingParticles.insert(leavingParticles.end(), leavingBufferParticles.begin(), leavingBufferParticles.end());
213 _numParticlesOwned.fetch_sub(leavingParticles.size(), std::memory_order_relaxed);
215 std::for_each(_haloParticleBuffer.begin(), _haloParticleBuffer.end(), [](
auto &buffer) { buffer.clear(); });
216 _numParticlesHalo.store(0, std::memory_order_relaxed);
217 return leavingParticles;
226 std::vector<Particle_T>
resizeBox(
const std::array<double, 3> &boxMin,
const std::array<double, 3> &boxMax) {
227 using namespace autopas::utils::ArrayMath::literals;
228 const auto &oldMin = _currentContainer->getBoxMin();
229 const auto &oldMax = _currentContainer->getBoxMax();
232 if (oldMin == boxMin and oldMax == boxMax) {
237 for (
size_t i = 0; i < boxMin.size(); ++i) {
238 if (boxMin[i] >= boxMax[i]) {
240 "New box size in dimension {} is not positive!\nboxMin[{}] = {}\nboxMax[{}] = {}", i, i, boxMin[i], i,
246 const auto newLength = boxMax - boxMin;
247 const auto oldLength = oldMax - oldMin;
248 const auto relDiffLength = newLength / oldLength;
249 for (
size_t i = 0; i < newLength.size(); ++i) {
251 if (relDiffLength[i] > 1.3 or relDiffLength[i] < 0.7) {
253 "LogicHandler.resize(): Domain size changed drastically in dimension {}! Gathered AutoTuning "
254 "information might not be applicable anymore!\n"
255 "Size old box : {}\n"
256 "Size new box : {}\n"
264 _currentContainerSelectorInfo.
boxMin = boxMin;
265 _currentContainerSelectorInfo.
boxMax = boxMax;
268 std::vector<Particle_T> particlesNowOutside;
269 for (
auto pIter = _currentContainer->begin(); pIter.isValid(); ++pIter) {
271 if (not pIter->isOwned()) {
273 "LogicHandler::resizeBox() encountered non owned particle. "
274 "When calling resizeBox() these should be already deleted. "
275 "This could be solved by calling updateContainer() before resizeBox().");
279 particlesNowOutside.push_back(*pIter);
287 _currentContainerSelectorInfo);
288 setCurrentContainer(std::move(newContainer));
290 const auto boxLength = boxMax - boxMin;
291 const auto interactionLengthInv = 1. / _currentContainer->getInteractionLength();
292 initSpatialLocks(boxLength, interactionLengthInv);
295 _neighborListsAreValid.store(
false, std::memory_order_relaxed);
297 return particlesNowOutside;
308 numParticles, _currentContainer->getBoxMin(), _currentContainer->getBoxMax(),
309 _currentContainer->getInteractionLength());
310 reserve(numParticles, numParticlesHaloEstimate);
319 void reserve(
size_t numParticles,
size_t numHaloParticles) {
320 const auto numHaloParticlesPerBuffer = numHaloParticles / _haloParticleBuffer.size();
321 for (
auto &buffer : _haloParticleBuffer) {
322 buffer.reserve(numHaloParticlesPerBuffer);
325 for (
auto &buffer : _particleBuffer) {
326 buffer.reserve(numHaloParticlesPerBuffer);
331 if (not _neighborListsAreValid.load(std::memory_order_relaxed)) {
332 _currentContainer->reserve(numParticles, numHaloParticles);
341 const auto &boxMin = _currentContainer->getBoxMin();
342 const auto &boxMax = _currentContainer->getBoxMax();
345 "LogicHandler: Trying to add a particle that is not in the bounding box.\n"
349 boxMin, boxMax, p.toString());
351 Particle_T particleCopy = p;
353 if (not _neighborListsAreValid.load(std::memory_order_relaxed)) {
355 _currentContainer->template addParticle<false>(particleCopy);
360 _numParticlesOwned.fetch_add(1, std::memory_order_relaxed);
367 const auto &boxMin = _currentContainer->getBoxMin();
368 const auto &boxMax = _currentContainer->getBoxMax();
369 Particle_T haloParticleCopy = haloParticle;
370 if (
utils::inBox(haloParticleCopy.getR(), boxMin, boxMax)) {
372 "LogicHandler: Trying to add a halo particle that is not outside the box of the container.\n"
379 if (not _neighborListsAreValid.load(std::memory_order_relaxed)) {
384 bool updated = _currentContainer->updateHaloParticle(haloParticleCopy);
390 _numParticlesHalo.fetch_add(1, std::memory_order_relaxed);
397 _neighborListsAreValid.store(
false, std::memory_order_relaxed);
398 _currentContainer->deleteAllParticles();
399 std::for_each(_particleBuffer.begin(), _particleBuffer.end(), [](
auto &buffer) { buffer.clear(); });
400 std::for_each(_haloParticleBuffer.begin(), _haloParticleBuffer.end(), [](
auto &buffer) { buffer.clear(); });
402 _numParticlesOwned.store(0, std::memory_order_relaxed);
403 _numParticlesHalo.store(0, std::memory_order_relaxed);
414 auto &bufferCollection = particle.isOwned() ? _particleBuffer : _haloParticleBuffer;
415 for (
auto &cell : bufferCollection) {
416 auto &buffer = cell._particles;
418 if (not buffer.empty() and &(buffer.front()) <= &particle and &particle <= &(buffer.back())) {
419 const bool isRearParticle = &particle == &buffer.back();
421 particle = buffer.back();
423 return {
true, not isRearParticle};
426 return {
false,
true};
435 if (particle.isOwned()) {
436 _numParticlesOwned.fetch_sub(1, std::memory_order_relaxed);
438 _numParticlesHalo.fetch_sub(1, std::memory_order_relaxed);
462 template <
class Functor>
471 template <
class Iterator>
473 typename Iterator::ParticleVecType additionalVectors;
474 if (not(behavior & IteratorBehavior::containerOnly)) {
475 additionalVectors.reserve(
static_cast<bool>(behavior & IteratorBehavior::owned) * _particleBuffer.size() +
476 static_cast<bool>(behavior & IteratorBehavior::halo) * _haloParticleBuffer.size());
477 if (behavior & IteratorBehavior::owned) {
478 for (
auto &buffer : _particleBuffer) {
482 if (not buffer.isEmpty()) {
483 additionalVectors.push_back(&(buffer._particles));
487 if (behavior & IteratorBehavior::halo) {
488 for (
auto &buffer : _haloParticleBuffer) {
489 if (not buffer.isEmpty()) {
490 additionalVectors.push_back(&(buffer._particles));
495 return additionalVectors;
502 auto additionalVectors = gatherAdditionalVectors<ContainerIterator<Particle_T, true, false>>(behavior);
503 return _currentContainer->begin(behavior, std::ref(additionalVectors));
510 auto additionalVectors =
513 return _currentContainer->begin(behavior, std::ref(additionalVectors));
520 const std::array<double, 3> &higherCorner,
521 IteratorBehavior behavior) {
523 for (
size_t d = 0; d < 3; ++d) {
524 if (lowerCorner[d] > higherCorner[d]) {
526 "Requesting region Iterator where the upper corner is lower than the lower corner!\n"
529 lowerCorner, higherCorner);
533 auto additionalVectors = gatherAdditionalVectors<ContainerIterator<Particle_T, true, true>>(behavior);
534 return _currentContainer->getRegionIterator(lowerCorner, higherCorner, behavior, std::ref(additionalVectors));
541 const std::array<double, 3> &higherCorner,
542 IteratorBehavior behavior)
const {
544 for (
size_t d = 0; d < 3; ++d) {
545 if (lowerCorner[d] > higherCorner[d]) {
547 "Requesting region Iterator where the upper corner is lower than the lower corner!\n"
550 lowerCorner, higherCorner);
554 auto additionalVectors =
556 return std::as_const(_currentContainer)
557 ->getRegionIterator(lowerCorner, higherCorner, behavior, std::ref(additionalVectors));
584 template <
class Functor>
608 std::tuple<const std::vector<FullParticleCell<Particle_T>> &,
const std::vector<FullParticleCell<Particle_T>> &>
623#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
624 const auto numRebuilds = considerOnlyLastNonTuningPhase ? _numRebuildsInNonTuningPhase : _numRebuilds;
626 const auto iterationCount =
627 considerOnlyLastNonTuningPhase ? _iteration - _iterationAfterLastTuningPhase : _iteration + 1;
628 if (numRebuilds == 0) {
629 return static_cast<double>(_neighborListRebuildFrequency);
631 return static_cast<double>(iterationCount) / numRebuilds;
634 return static_cast<double>(_neighborListRebuildFrequency);
648 double maxVelocity = 0;
651 for (
auto iter = this->
begin(IteratorBehavior::owned | IteratorBehavior::containerOnly); iter.isValid(); ++iter) {
652 std::array<double, 3> tempVel = iter->getV();
653 double tempVelAbs = sqrt(dot(tempVel, tempVel));
654 maxVelocity = std::max(tempVelAbs, maxVelocity);
657 return skin / maxVelocity / deltaT / 2;
700 void initSpatialLocks(
const std::array<double, 3> &boxLength,
double interactionLengthInv) {
701 using namespace autopas::utils::ArrayMath::literals;
711 constexpr size_t maxNumSpacialLocks{1000000};
714 const std::array<size_t, 3> locksPerDim = [&]() {
717 const std::array<size_t, 3> locksPerDimNaive =
718 static_cast_copy_array<size_t>(ceil(boxLength * interactionLengthInv));
719 const auto totalLocksNaive =
720 std::accumulate(locksPerDimNaive.begin(), locksPerDimNaive.end(), 1ul, std::multiplies<>());
722 if (totalLocksNaive <= maxNumSpacialLocks) {
723 return locksPerDimNaive;
727 const std::array<double, 3> boxSideProportions = {
729 boxLength[0] / boxLength[1],
730 boxLength[0] / boxLength[2],
733 const auto prodProportions =
734 std::accumulate(boxSideProportions.begin(), boxSideProportions.end(), 1., std::multiplies<>());
736 const auto locksInFirstDimFloat = std::floor(std::cbrt(maxNumSpacialLocks * prodProportions));
738 const std::array<size_t, 3> locksPerDimLimited = {
739 static_cast<size_t>(locksInFirstDimFloat),
740 static_cast<size_t>(locksInFirstDimFloat / boxSideProportions[1]),
741 static_cast<size_t>(locksInFirstDimFloat / boxSideProportions[2]),
743 return locksPerDimLimited;
746 _spatialLocks.resize(locksPerDim[0]);
747 for (
auto &lockVecVec : _spatialLocks) {
748 lockVecVec.resize(locksPerDim[1]);
749 for (
auto &lockVec : lockVecVec) {
750 lockVec.resize(locksPerDim[2]);
751 for (
auto &lockPtr : lockVec) {
753 lockPtr = std::make_unique<std::mutex>();
767 template <
class Functor>
768 std::tuple<Configuration, std::unique_ptr<TraversalInterface>,
bool> selectConfiguration(
769 Functor &functor,
const InteractionTypeOption &interactionType);
791 template <
class Functor>
804 template <
class Functor>
805 void computeRemainderInteractions(
Functor &functor,
bool newton3,
bool useSoA);
812 void checkMinimalSize()
const;
818 unsigned int _neighborListRebuildFrequency;
823 unsigned int _verletClusterSize;
828 size_t _numRebuilds{0};
834 size_t _numRebuildsInNonTuningPhase{0};
839 size_t _sortingThreshold;
841 std::shared_ptr<TuningManager> _tuningManager;
846 std::unique_ptr<ParticleContainerInterface<Particle_T>> _currentContainer{
nullptr};
866 std::set<InteractionTypeOption> _interactionTypes{};
871 std::atomic<bool> _neighborListsAreValid{
false};
876 size_t _stepsSinceLastListRebuild{0};
882 size_t _iteration{std::numeric_limits<size_t>::max()};
887 size_t _iterationAfterLastTuningPhase{0};
892 std::atomic<size_t> _numParticlesOwned{0ul};
897 std::atomic<size_t> _numParticlesHalo{0ul};
902 std::vector<FullParticleCell<Particle_T>> _particleBuffer;
907 std::vector<FullParticleCell<Particle_T>> _haloParticleBuffer;
914 std::vector<std::vector<std::vector<std::unique_ptr<std::mutex>>>> _spatialLocks;
925 bool _neighborListInvalidDoDynamicRebuild{
false};
930 void updateRebuildPositions();
943template <
typename Particle_T>
945#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
950 for (
auto iter = this->begin(IteratorBehavior::owned | IteratorBehavior::containerOnly); iter.isValid(); ++iter) {
951 iter->resetRAtRebuild();
956template <
typename Particle_T>
959 for (
unsigned int dim = 0; dim < 3; ++dim) {
960 if (_currentContainer->getBoxMax()[dim] - _currentContainer->getBoxMin()[dim] <
961 _currentContainer->getInteractionLength()) {
963 "Box (boxMin[{}]={} and boxMax[{}]={}) is too small.\nHas to be at least cutoff({}) + skin({}) = {}.", dim,
964 _currentContainer->getBoxMin()[dim], dim, _currentContainer->getBoxMax()[dim], _currentContainer->getCutoff(),
965 _currentContainer->getVerletSkin(), _currentContainer->getCutoff() + _currentContainer->getVerletSkin());
970template <
typename Particle_T>
972 return _neighborListInvalidDoDynamicRebuild;
975template <
typename Particle_T>
977 if (_stepsSinceLastListRebuild >= _neighborListRebuildFrequency
978#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
979 or getNeighborListsInvalidDoDynamicRebuild()
981 or _tuningManager->requiresRebuilding(_iteration)) {
982 _neighborListsAreValid.store(
false, std::memory_order_relaxed);
985 return _neighborListsAreValid.load(std::memory_order_relaxed);
988template <
typename Particle_T>
990#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
991 const auto skin = getContainer().getVerletSkin();
993 const auto halfSkinSquare = skin * skin * 0.25;
997 AUTOPAS_OPENMP(parallel reduction(or : _neighborListInvalidDoDynamicRebuild))
998 for (
auto iter = this->begin(IteratorBehavior::owned | IteratorBehavior::containerOnly); iter.isValid(); ++iter) {
999 const auto distance = iter->calculateDisplacementSinceRebuild();
1002 _neighborListInvalidDoDynamicRebuild |= distanceSquare >= halfSkinSquare;
1007template <
typename Particle_T>
1009 _neighborListInvalidDoDynamicRebuild =
false;
1012template <
typename Particle_T>
1016 auto exchangeBuffer = [](
const auto &newBuffers,
auto &oldBuffers,
auto &particleCounter) {
1018 if (oldBuffers.size() < newBuffers.size()) {
1020 "The number of new buffers ({}) is larger than number of existing buffers ({})!", newBuffers.size(),
1025 const auto numParticlesInOldBuffers =
1026 std::transform_reduce(oldBuffers.begin(), std::next(oldBuffers.begin(), newBuffers.size()), 0, std::plus<>(),
1027 [](
const auto &cell) { return cell.size(); });
1028 particleCounter.fetch_sub(numParticlesInOldBuffers, std::memory_order_relaxed);
1031 size_t numParticlesInNewBuffers = 0;
1032 for (
size_t i = 0; i < newBuffers.size(); ++i) {
1033 oldBuffers[i].clear();
1034 for (
const auto &p : newBuffers[i]) {
1035 ++numParticlesInNewBuffers;
1036 oldBuffers[i].addParticle(p);
1040 particleCounter.fetch_add(numParticlesInNewBuffers, std::memory_order_relaxed);
1043 exchangeBuffer(particleBuffers, _particleBuffer, _numParticlesOwned);
1044 exchangeBuffer(haloParticleBuffers, _haloParticleBuffer, _numParticlesHalo);
1047template <
typename Particle_T>
1048std::tuple<const std::vector<FullParticleCell<Particle_T>> &,
const std::vector<FullParticleCell<Particle_T>> &>
1050 return {_particleBuffer, _haloParticleBuffer};
1053template <
typename Particle_T>
1054template <
class Functor>
1057 constexpr auto interactionType = [] {
1059 return InteractionTypeOption::pairwise;
1061 return InteractionTypeOption::triwise;
1064 "LogicHandler::computeInteractions(): Functor is not valid. Only pairwise and triwise functors are "
1066 "Please use a functor derived from "
1067 "PairwiseFunctor or TriwiseFunctor.");
1071 auto &autoTuner = *_tuningManager->getAutoTuners()[interactionType];
1076 long energyTotalRebuild;
1078 const bool energyMeasurementsPossible = autoTuner.resetEnergy();
1080 timerRebuild.
start();
1084 if (not _neighborListsAreValid.load(std::memory_order_relaxed)) {
1085#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
1086 this->updateRebuildPositions();
1088 _currentContainer->rebuildNeighborLists(&traversal);
1089#ifdef AUTOPAS_ENABLE_DYNAMIC_CONTAINERS
1090 this->resetNeighborListsInvalidDoDynamicRebuild();
1092 if (not autoTuner.inTuningPhase()) {
1093 _numRebuildsInNonTuningPhase++;
1096 _neighborListsAreValid.store(
true, std::memory_order_relaxed);
1098 timerRebuild.
stop();
1099 std::tie(std::ignore, std::ignore, std::ignore, energyTotalRebuild) = autoTuner.sampleEnergy();
1101 timerComputeInteractions.
start();
1102 _currentContainer->computeInteractions(&traversal);
1103 timerComputeInteractions.
stop();
1105 timerComputeRemainder.
start();
1106 const bool newton3 = autoTuner.getCurrentConfig().newton3;
1107 const auto dataLayout = autoTuner.getCurrentConfig().dataLayout;
1108 computeRemainderInteractions(functor, newton3, dataLayout);
1109 timerComputeRemainder.
stop();
1113 const auto [energyWatts, energyJoules, energyDeltaT, energyTotal] = autoTuner.sampleEnergy();
1116 constexpr auto nanD = std::numeric_limits<double>::quiet_NaN();
1117 constexpr auto nanL = std::numeric_limits<long>::quiet_NaN();
1122 energyMeasurementsPossible,
1123 energyMeasurementsPossible ? energyWatts : nanD,
1124 energyMeasurementsPossible ? energyJoules : nanD,
1125 energyMeasurementsPossible ? energyDeltaT : nanD,
1126 energyMeasurementsPossible ? energyTotalRebuild : nanL,
1127 energyMeasurementsPossible ? energyTotal - energyTotalRebuild
1129 energyMeasurementsPossible ? energyTotal : nanL};
1132template <
typename Particle_T>
1133template <
class Functor>
1138 _remainderPairwiseInteractionHandler.template computeRemainderInteractions<true>(
1139 &functor, actualContainerType, _particleBuffer, _haloParticleBuffer, useSoA);
1141 _remainderPairwiseInteractionHandler.template computeRemainderInteractions<false>(
1142 &functor, actualContainerType, _particleBuffer, _haloParticleBuffer, useSoA);
1146 _remainderTriwiseInteractionHandler.template computeRemainderInteractions<true>(
1147 &functor, actualContainerType, _particleBuffer, _haloParticleBuffer);
1149 _remainderTriwiseInteractionHandler.template computeRemainderInteractions<false>(
1150 &functor, actualContainerType, _particleBuffer, _haloParticleBuffer);
1156template <
typename Particle_T>
1157template <
class Functor>
1159 Functor &functor,
const InteractionTypeOption &interactionType) {
1163#ifdef AUTOPAS_LOG_LIVEINFO
1164 auto particleIter = this->begin(IteratorBehavior::ownedOrHalo);
1165 info.gather(particleIter, _neighborListRebuildFrequency, getNumberOfParticlesOwned(), _logicHandlerInfo.boxMin,
1166 _logicHandlerInfo.boxMax, _logicHandlerInfo.cutoff, _logicHandlerInfo.verletSkin);
1167 _liveInfoLogger.logLiveInfo(info, _iteration);
1172 auto configuration = _tuningManager->getCurrentConfig(interactionType);
1173 auto [traversalPtr, _] = isConfigurationApplicable(configuration, functor);
1175 if (not traversalPtr) {
1178 "LogicHandler: Functor {} is not relevant for tuning but the given configuration is not applicable!",
1182 return {configuration, std::move(traversalPtr),
false};
1185 if (_tuningManager->needsLiveInfo(_iteration)) {
1187 if (info.get().empty()) {
1188 auto particleIter = this->begin(IteratorBehavior::ownedOrHalo);
1189 info.gather(particleIter, _neighborListRebuildFrequency, getNumberOfParticlesOwned(), _logicHandlerInfo.boxMin,
1190 _logicHandlerInfo.boxMax, _logicHandlerInfo.cutoff, _logicHandlerInfo.verletSkin);
1194 size_t numRejectedConfigs = 0;
1196 selectConfigurationTimer.
start();
1198 auto stillTuning = _tuningManager->tune(_iteration, info);
1200 auto configuration = _tuningManager->getCurrentConfig(interactionType);
1205 auto [traversalPtr, rejectIndefinitely] = isConfigurationApplicable(configuration, functor);
1208 selectConfigurationTimer.
stop();
1209 AutoPasLog(TRACE,
"Select Configuration took {} ms. A total of {} configurations were rejected.",
1210 selectConfigurationTimer.
getTotalTime(), numRejectedConfigs);
1211 return {configuration, std::move(traversalPtr), stillTuning};
1213 numRejectedConfigs++;
1215 configuration = _tuningManager->rejectConfiguration(configuration, rejectIndefinitely, interactionType);
1219template <
typename Particle_T>
1223 if (_currentContainer !=
nullptr and newContainer !=
nullptr) {
1225 const auto numParticlesTotal = _currentContainer->size();
1227 numParticlesTotal, _currentContainer->getBoxMin(), _currentContainer->getBoxMax(),
1228 _currentContainer->getInteractionLength());
1230 newContainer->reserve(numParticlesTotal, numParticlesHalo);
1231 for (
auto particleIter = _currentContainer->begin(IteratorBehavior::ownedOrHalo); particleIter.isValid();
1234 if (particleIter->isOwned()) {
1235 newContainer->addParticle(*particleIter);
1237 newContainer->addHaloParticle(*particleIter);
1242 _currentContainer = std::move(newContainer);
1245template <
typename Particle_T>
1246template <
class Functor>
1248 const InteractionTypeOption &interactionType) {
1249 if (not _interactionTypes.contains(interactionType)) {
1251 "LogicHandler::computeInteractionsPipeline(): AutPas was not initialized for the Functor's interactions type: "
1257 tuningTimer.
start();
1258 const auto [configuration, traversalPtr, stillTuning] = selectConfiguration(*functor, interactionType);
1260 _tuningManager->logTuningResult(tuningTimer.
getTotalTime(), _iteration, interactionType);
1263 const auto rebuildIteration = not _neighborListsAreValid.load(std::memory_order_relaxed);
1266 AutoPasLog(DEBUG,
"Iterating with configuration: {} tuning: {}", configuration.toString(), stillTuning);
1270 auto bufferSizeListing = [](
const auto &buffers) -> std::string {
1271 std::stringstream ss;
1273 for (
const auto &buffer : buffers) {
1274 ss << buffer.size() <<
", ";
1275 sum += buffer.size();
1277 ss <<
" Total: " << sum;
1280 AutoPasLog(TRACE,
"particleBuffer size : {}", bufferSizeListing(_particleBuffer));
1281 AutoPasLog(TRACE,
"haloParticleBuffer size : {}", bufferSizeListing(_haloParticleBuffer));
1282 AutoPasLog(DEBUG,
"Type of interaction : {}", interactionType.to_string());
1291 _iterationLogger.logIteration(configuration, _iteration, functor->
getName(), stillTuning, tuningTimer.
getTotalTime(),
1301 const auto measurement = [&]() {
1302 switch (_tuningManager->getTuningMetric(interactionType)) {
1310 return std::make_pair(0l, 0l);
1313 _tuningManager->addMeasurement(measurement.first, measurement.second, rebuildIteration, _iteration,
1317 AutoPasLog(TRACE,
"Skipping adding of sample because functor is not marked relevant.");
1322template <
typename Particle_T>
1323template <
class Functor>
1327 const auto allContainerTraversals =
1329 if (allContainerTraversals.find(config.
traversal) == allContainerTraversals.end()) {
1330 AutoPasLog(WARN,
"Configuration rejected: Container {} does not support the traversal {}.", config.
container,
1332 return {
nullptr,
true};
1338 AutoPasLog(DEBUG,
"Configuration rejected: The functor doesn't support Newton 3 {}!", config.
newton3);
1339 return {
nullptr,
true};
1344 AutoPasLog(DEBUG,
"Configuration rejected: The functor doesn't support the Vectorization Pattern {}!",
1346 return {
nullptr,
true};
1349 std::unique_ptr<ParticleContainerInterface<Particle_T>> containerPtr{
nullptr};
1350 auto containerInfo =
1352 _currentContainer->getCutoff(), config.
cellSizeFactor, _currentContainer->getVerletSkin(),
1353 _verletClusterSize, _sortingThreshold, config.
loadEstimator);
1357 const bool generateNewContainer = _currentContainer ==
nullptr or
1358 _currentContainer->getContainerType() != config.
container or
1359 containerInfo != _currentContainerSelectorInfo;
1361 if (generateNewContainer) {
1367 const auto traversalInfo =
1368 generateNewContainer ? containerPtr->getTraversalSelectorInfo() : _currentContainer->getTraversalSelectorInfo();
1372 TraversalSelector::generateTraversalFromConfig<Particle_T, Functor>(config, functor, traversalInfo);
1377 if (traversalPtr and generateNewContainer) {
1378 _currentContainerSelectorInfo = containerInfo;
1379 setCurrentContainer(std::move(containerPtr));
1382 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
LoadEstimatorOption loadEstimator
Load Estimator option.
Definition: Configuration.h:135
TraversalOption traversal
Traversal option.
Definition: Configuration.h:127
double cellSizeFactor
CellSizeFactor.
Definition: Configuration.h:147
InteractionTypeOption interactionType
Interaction type of the configuration.
Definition: Configuration.h:151
ContainerOption container
Container option.
Definition: Configuration.h:123
Newton3Option newton3
Newton 3 option.
Definition: Configuration.h:143
VectorizationPatternOption vecPattern
Vectorization Pattern option.
Definition: Configuration.h:131
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:93
std::array< double, 3 > boxMax
Upper corner of the container.
Definition: ContainerSelectorInfo.h:98
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:192
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:183
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:202
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:46
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:49
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:1013
void reserve(size_t numParticles, size_t numHaloParticles)
Reserves space in the particle buffers and the container.
Definition: LogicHandler.h:319
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:1324
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:501
std::vector< Particle_T > updateContainer()
Updates the container.
Definition: LogicHandler.h:165
unsigned long getNumberOfParticlesOwned() const
Get the number of owned particles.
Definition: LogicHandler.h:564
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:1247
std::tuple< const std::vector< FullParticleCell< Particle_T > > &, const std::vector< FullParticleCell< Particle_T > > & > getParticleBuffers() const
Getter for the particle buffers.
Definition: LogicHandler.h:1049
void addParticle(const Particle_T &p)
Adds a particle to the container.
Definition: LogicHandler.h:339
void decreaseParticleCounter(Particle_T &particle)
Decrease the correct internal particle counters.
Definition: LogicHandler.h:434
std::vector< Particle_T > collectLeavingParticlesFromBuffer(bool insertOwnedParticlesToContainer)
Collects leaving particles from buffer and potentially inserts owned particles to the container.
Definition: LogicHandler.h:112
bool neighborListsAreValid()
Checks if in the next iteration the neighbor lists have to be rebuilt.
Definition: LogicHandler.h:976
unsigned long getNumberOfParticlesHalo() const
Get the number of halo particles.
Definition: LogicHandler.h:570
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:412
LogicHandler(const std::shared_ptr< TuningManager > &tunerManager, const LogicHandlerInfo &logicHandlerInfo, unsigned int rebuildFrequency, const std::string &outputSuffix)
Constructor of the LogicHandler.
Definition: LogicHandler.h:58
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:645
void checkNeighborListsInvalidDoDynamicRebuild()
Checks if any particle has moved more than skin/2.
Definition: LogicHandler.h:989
Iterator::ParticleVecType gatherAdditionalVectors(IteratorBehavior behavior)
Create the additional vectors vector for a given iterator behavior.
Definition: LogicHandler.h:472
ParticleContainerInterface< Particle_T > & getContainer()
Returns a non-const reference to the currently selected particle container.
Definition: LogicHandler.h:105
void addHaloParticle(const Particle_T &haloParticle)
Adds a particle to the container that lies in the halo region of the container.
Definition: LogicHandler.h:366
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:540
void deleteAllParticles()
Deletes all particles.
Definition: LogicHandler.h:396
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:509
bool getNeighborListsInvalidDoDynamicRebuild()
getter function for _neighborListInvalidDoDynamicRebuild
Definition: LogicHandler.h:971
void resetNeighborListsInvalidDoDynamicRebuild()
Checks if any particle has moved more than skin/2.
Definition: LogicHandler.h:1008
double getMeanRebuildFrequency(bool considerOnlyLastNonTuningPhase=false) const
Getter for the mean rebuild frequency.
Definition: LogicHandler.h:622
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:226
void reserve(size_t numParticles)
Estimates the number of halo particles via autopas::utils::NumParticlesEstimator::estimateNumHalosUni...
Definition: LogicHandler.h:306
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:519
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
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