AutoPas  3.0.0
Loading...
Searching...
No Matches
AutoPasImpl.h
Go to the documentation of this file.
1
7#pragma once
8
9#include <array>
10#include <memory>
11#include <ostream>
12#include <type_traits>
13#include <vector>
14
15// The LogicHandler includes dependencies to wide parts of AutoPas, making it expensive to compile and thus is moved
16// here from AutoPasDecl.h.
17#include "autopas/AutoPasDecl.h"
20#include "autopas/Version.h"
32
33namespace autopas {
34
35template <class Particle_T>
36AutoPas<Particle_T>::AutoPas(std::ostream &logOutputStream) {
37 // count the number of autopas instances. This is needed to ensure that the autopas
38 // logger is not unregistered while other instances are still using it.
40 // remove potentially existing logger
42 // initialize the Logger
43 autopas::Logger::create(logOutputStream);
44 // The logger is normally only flushed on successful program termination.
45 // This line ensures flushing when log messages of level warning or more severe are created.
46 autopas::Logger::get()->flush_on(spdlog::level::warn);
47}
48
49template <class Particle_T>
52 if (InstanceCounter::count == 0) {
53 // remove the Logger from the registry. Do this only if we have no other autopas instances running.
55 }
56}
57
58template <class Particle_T>
60 _autoTuners = std::move(other._autoTuners);
61 _logicHandler = std::move(other._logicHandler);
62 return *this;
63}
64
65template <class Particle_T>
67 int myRank{};
69 if (myRank == 0) {
70 AutoPasLog(INFO, "AutoPas Version: {}", AutoPas_VERSION);
71 AutoPasLog(INFO, "Compiled with : {}", utils::CompileInfo::getCompilerInfo());
72 }
73
74 if (_tuningStrategyFactoryInfo.autopasMpiCommunicator == AUTOPAS_MPI_COMM_NULL) {
75 AutoPas_MPI_Comm_dup(AUTOPAS_MPI_COMM_WORLD, &_tuningStrategyFactoryInfo.autopasMpiCommunicator);
76 } else {
77 _externalMPICommunicator = true;
78 }
79 if (std::find(_tuningStrategyOptions.begin(), _tuningStrategyOptions.end(),
80 TuningStrategyOption::mpiDivideAndConquer) != _tuningStrategyOptions.end()) {
81 _tuningStrategyFactoryInfo.mpiDivideAndConquer = true;
82 }
83
84 _logicHandlerInfo.sortingThreshold = _sortingThreshold;
85
86 // If an interval was given for the cell size factor, change it to the relevant values.
87 // Don't modify _allowedCellSizeFactors to preserve the initial (type) information.
88 const auto cellSizeFactors = [&]() -> NumberSetFinite<double> {
89 if (const auto *csfIntervalPtr = dynamic_cast<NumberInterval<double> *>(_allowedCellSizeFactors.get())) {
90 const auto interactionLength = _logicHandlerInfo.cutoff * _logicHandlerInfo.verletSkin;
91 const auto boxLengthX = _logicHandlerInfo.boxMax[0] - _logicHandlerInfo.boxMin[0];
92 return {SearchSpaceGenerators::calculateRelevantCsfs(*csfIntervalPtr, interactionLength, boxLengthX)};
93 } else {
94 // in this case _allowedCellSizeFactors is a finite set
95 return {_allowedCellSizeFactors->getAll()};
96 }
97 }();
98
99 // Create autotuners for each interaction type
100 for (const auto &interactionType : _allowedInteractionTypeOptions) {
101 const auto searchSpace = SearchSpaceGenerators::cartesianProduct(
102 _allowedContainers, _allowedTraversals[interactionType], _allowedLoadEstimators,
103 _allowedDataLayouts[interactionType], _allowedNewton3Options[interactionType], &cellSizeFactors,
104 interactionType);
105
107 tuningStrategies.reserve(_tuningStrategyOptions.size());
108 for (const auto &strategy : _tuningStrategyOptions) {
109 tuningStrategies.emplace_back(TuningStrategyFactory::generateTuningStrategy(
110 searchSpace, strategy, _tuningStrategyFactoryInfo, _outputSuffix));
111 }
112 if (_useTuningStrategyLoggerProxy) {
113 tuningStrategies.emplace_back(std::make_unique<TuningStrategyLogger>(_outputSuffix));
114 }
115 auto tunerOutputSuffix = _outputSuffix + "_" + interactionType.to_string();
116 _autoTuners.emplace(interactionType,
117 std::make_unique<autopas::AutoTuner>(tuningStrategies, searchSpace, _autoTunerInfo,
118 _verletRebuildFrequency, tunerOutputSuffix));
119 }
120
121 // Create logic handler
122 _logicHandler = std::make_unique<std::remove_reference_t<decltype(*_logicHandler)>>(
123 _autoTuners, _logicHandlerInfo, _verletRebuildFrequency, _outputSuffix);
124}
125
126template <class Particle_T>
127template <class Functor>
129 static_assert(
130 not std::is_same_v<Functor, autopas::Functor<Particle_T, Functor>>,
131 "The static type of Functor in computeInteractions is not allowed to be autopas::Functor. Please use the "
132 "derived type instead, e.g. by using a dynamic_cast.");
133 if (f->getCutoff() > this->getCutoff()) {
134 utils::ExceptionHandler::exception("Functor cutoff ({}) must not be larger than container cutoff ({})",
135 f->getCutoff(), this->getCutoff());
136 }
137
138 if constexpr (utils::isPairwiseFunctor<Functor>()) {
139 return _logicHandler->template computeInteractionsPipeline<Functor>(f, InteractionTypeOption::pairwise);
140 } else if constexpr (utils::isTriwiseFunctor<Functor>()) {
141 return _logicHandler->template computeInteractionsPipeline<Functor>(f, InteractionTypeOption::triwise);
142 } else {
144 "Functor is not valid. Only pairwise and triwise functors are supported. Please use a functor derived from "
145 "PairwiseFunctor or TriwiseFunctor.");
146 }
147 return false;
148}
149
150template <class Particle_T>
151size_t AutoPas<Particle_T>::getNumberOfParticles(IteratorBehavior behavior) const {
152 size_t numParticles{0};
153 if (behavior & IteratorBehavior::owned) {
154 numParticles += _logicHandler->getNumberOfParticlesOwned();
155 }
156 if (behavior & IteratorBehavior::halo) {
157 numParticles += _logicHandler->getNumberOfParticlesHalo();
158 }
159 // non fatal sanity check whether the behavior contained anything else
160 if (behavior & ~(IteratorBehavior::ownedOrHalo)) {
162 "AutoPas::getNumberOfParticles() does not support iterator behaviors other than owned or halo.");
163 }
164
165 return numParticles;
166}
167
168template <class Particle_T>
169void AutoPas<Particle_T>::reserve(size_t numParticles) {
170 _logicHandler->reserve(numParticles);
171}
172
173template <class Particle_T>
174void AutoPas<Particle_T>::reserve(size_t numParticles, size_t numHaloParticles) {
175 _logicHandler->reserve(numParticles, numHaloParticles);
176}
177
178template <class Particle_T>
179template <class F>
180void AutoPas<Particle_T>::addParticlesAux(size_t numParticlesToAdd, size_t numHalosToAdd, size_t collectionSize,
181 F loopBody) {
182 reserve(getNumberOfParticles(IteratorBehavior::owned) + numParticlesToAdd,
183 getNumberOfParticles(IteratorBehavior::halo) + numHalosToAdd);
184 AUTOPAS_OPENMP(parallel for schedule(static, std::max(1ul, collectionSize / omp_get_max_threads())))
185 for (auto i = 0; i < collectionSize; ++i) {
186 loopBody(i);
187 }
188}
189
190template <class Particle_T>
191void AutoPas<Particle_T>::addParticle(const Particle_T &p) {
192 _logicHandler->addParticle(p);
193}
194
195template <class Particle_T>
196template <class Collection>
197void AutoPas<Particle_T>::addParticles(Collection &&particles) {
198 addParticlesAux(particles.size(), 0, particles.size(), [&](auto i) { addParticle(particles[i]); });
199}
200
201template <class Particle_T>
202template <class Collection, class F>
203void AutoPas<Particle_T>::addParticlesIf(Collection &&particles, F predicate) {
204 std::vector<char> predicateMask(particles.size());
205 int numTrue = 0;
206 AUTOPAS_OPENMP(parallel for reduction(+ : numTrue))
207 for (auto i = 0; i < particles.size(); ++i) {
208 if (predicate(particles[i])) {
209 predicateMask[i] = static_cast<char>(true);
210 ++numTrue;
211 } else {
212 predicateMask[i] = static_cast<char>(false);
213 }
214 }
215
216 addParticlesAux(numTrue, 0, particles.size(), [&](auto i) {
217 if (predicateMask[i]) {
218 addParticle(particles[i]);
219 }
220 });
221}
222
223template <class Particle_T>
224std::vector<Particle_T> AutoPas<Particle_T>::updateContainer() {
225 return _logicHandler->updateContainer();
226}
227
228template <class Particle_T>
229std::vector<Particle_T> AutoPas<Particle_T>::resizeBox(const std::array<double, 3> &boxMin,
230 const std::array<double, 3> &boxMax) {
231 if (_allowedCellSizeFactors->isInterval()) {
232 AutoPasLog(WARN,
233 "The allowed Cell Size Factors are a continuous interval but internally only those values that "
234 "yield unique numbers of cells are used. Resizing does not cause these values to be recalculated so "
235 "the same configurations might now yield different and non-unique numbers of cells!");
236 }
237 _logicHandlerInfo.boxMin = boxMin;
238 _logicHandlerInfo.boxMax = boxMax;
239 return _logicHandler->resizeBox(boxMin, boxMax);
240}
241
242template <class Particle_T>
244 for (auto &[interaction, tuner] : _autoTuners) {
245 tuner->forceRetune();
246 }
247}
248
249template <class Particle_T>
250void AutoPas<Particle_T>::addHaloParticle(const Particle_T &haloParticle) {
251 _logicHandler->addHaloParticle(haloParticle);
252}
253
254template <class Particle_T>
255template <class Collection>
256void AutoPas<Particle_T>::addHaloParticles(Collection &&particles) {
257 addParticlesAux(0, particles.size(), particles.size(), [&](auto i) { addHaloParticle(particles[i]); });
258}
259
260template <class Particle_T>
261template <class Collection, class F>
262void AutoPas<Particle_T>::addHaloParticlesIf(Collection &&particles, F predicate) {
263 std::vector<char> predicateMask(particles.size());
264 int numTrue = 0;
265 AUTOPAS_OPENMP(parallel for reduction(+ : numTrue))
266 for (auto i = 0; i < particles.size(); ++i) {
267 if (predicate(particles[i])) {
268 predicateMask[i] = static_cast<char>(true);
269 ++numTrue;
270 } else {
271 predicateMask[i] = static_cast<char>(false);
272 }
273 }
274
275 addParticlesAux(0, numTrue, particles.size(), [&](auto i) {
276 if (predicateMask[i]) {
277 addHaloParticle(particles[i]);
278 }
279 });
280}
281
282template <class Particle_T>
284 _logicHandler->deleteAllParticles();
285}
286
287template <class Particle_T>
289 _logicHandler->decreaseParticleCounter(*iter);
290 internal::deleteParticle(iter);
291}
292
293template <class Particle_T>
295 _logicHandler->decreaseParticleCounter(*iter);
296 internal::deleteParticle(iter);
297}
298
299template <class Particle_T>
300bool AutoPas<Particle_T>::deleteParticle(Particle_T &particle) {
301 _logicHandler->decreaseParticleCounter(particle);
302 // if the particle was not found in the logic handler's buffers it must be in the container
303 auto [particleDeleted, refStillValid] = _logicHandler->deleteParticleFromBuffers(particle);
304 if (not particleDeleted) {
305 refStillValid = _logicHandler->getContainer().deleteParticle(particle);
306 }
307 return refStillValid;
308}
309
310template <class Particle_T>
312 return _logicHandler->begin(behavior);
313}
314
315template <class Particle_T>
316typename AutoPas<Particle_T>::ConstIteratorT AutoPas<Particle_T>::begin(IteratorBehavior behavior) const {
317 return std::as_const(*_logicHandler).begin(behavior);
318}
319
320template <class Particle_T>
322 const std::array<double, 3> &lowerCorner, const std::array<double, 3> &higherCorner, IteratorBehavior behavior) {
323 return _logicHandler->getRegionIterator(lowerCorner, higherCorner, behavior);
324}
325
326template <class Particle_T>
328 const std::array<double, 3> &lowerCorner, const std::array<double, 3> &higherCorner,
329 IteratorBehavior behavior) const {
330 return std::as_const(*_logicHandler).getRegionIterator(lowerCorner, higherCorner, behavior);
331}
332
333template <class Particle_T>
335 return _logicHandler->getContainer().getContainerType();
336}
337
338template <class Particle_T>
339const std::array<double, 3> &AutoPas<Particle_T>::getBoxMin() const {
340 return _logicHandler->getContainer().getBoxMin();
341}
342
343template <class Particle_T>
344const std::array<double, 3> &AutoPas<Particle_T>::getBoxMax() const {
345 return _logicHandler->getContainer().getBoxMax();
346}
347
348template <class Particle_T>
350 return _logicHandler->getContainer();
351}
352
353template <class Particle_T>
354const autopas::ParticleContainerInterface<Particle_T> &AutoPas<Particle_T>::getContainer() const {
355 return _logicHandler->getContainer();
356}
357
358template <class Particle_T>
360 bool isTrivial = true;
361 for (auto &[interaction, tuner] : _autoTuners) {
362 isTrivial = isTrivial and tuner->searchSpaceIsTrivial();
363 }
364 return isTrivial;
365}
366
367} // namespace autopas
#define AutoPasLog(lvl, fmt,...)
Macro for logging providing common meta information without filename.
Definition: Logger.h:24
#define AUTOPAS_MPI_COMM_NULL
Wrapper for MPI_COMM_NULL.
Definition: WrapMPI.h:118
#define AUTOPAS_MPI_COMM_WORLD
Wrapper for MPI_COMM_WORLD.
Definition: WrapMPI.h:120
#define AUTOPAS_OPENMP(args)
Empty macro to throw away any arguments.
Definition: WrapOpenMP.h:126
The AutoPas class is intended to be the main point of Interaction for the user.
Definition: AutoPasDecl.h:46
std::vector< Particle_T > updateContainer()
Updates the container.
Definition: AutoPasImpl.h:224
bool searchSpaceIsTrivial()
get the bool value indicating if the search space is trivial (not more than one configuration to test...
Definition: AutoPasImpl.h:359
void reserve(size_t numParticles)
Reserve memory for a given number of particles in the container and logic layers.
Definition: AutoPasImpl.h:169
void addParticles(Collection &&particles)
Adds all particles from the collection to the container.
Definition: AutoPasImpl.h:197
void addParticlesIf(Collection &&particles, F predicate)
Adds all particles for which predicate(particle) == true to the container.
Definition: AutoPasImpl.h:203
void addHaloParticle(const Particle_T &haloParticle)
Adds a particle to the container that lies in the halo region of the container.
Definition: AutoPasImpl.h:250
AutoPas(std::ostream &logOutputStream=std::cout)
Constructor for the autopas class.
Definition: AutoPasImpl.h:36
RegionIteratorT getRegionIterator(const std::array< double, 3 > &lowerCorner, const std::array< double, 3 > &higherCorner, IteratorBehavior behavior=IteratorBehavior::ownedOrHalo)
Iterate over all particles in a specified region.
Definition: AutoPasImpl.h:321
AutoPas & operator=(AutoPas &&other) noexcept
Move assignment operator.
Definition: AutoPasImpl.h:59
void init()
Initialize AutoPas.
Definition: AutoPasImpl.h:66
void forceRetune()
Force the internal tuner to enter a new tuning phase upon the next call to computeInteractions().
Definition: AutoPasImpl.h:243
size_t getNumberOfParticles(IteratorBehavior behavior=IteratorBehavior::owned) const
Returns the number of particles in this container.
Definition: AutoPasImpl.h:151
void deleteAllParticles()
Deletes all particles.
Definition: AutoPasImpl.h:283
bool computeInteractions(Functor *f)
Function to iterate over all inter-particle interactions in the container This function only handles ...
Definition: AutoPasImpl.h:128
void addParticle(const Particle_T &p)
Adds a particle to the container.
Definition: AutoPasImpl.h:191
IteratorT begin(IteratorBehavior behavior=IteratorBehavior::ownedOrHalo)
Iterate over all particles by using for(auto iter = autoPas.begin(); iter.isValid(); ++iter)
Definition: AutoPasImpl.h:311
std::vector< std::unique_ptr< TuningStrategyInterface > > TuningStrategiesListType
Type for the member holding all tuning strategies.
Definition: AutoTuner.h:46
Public iterator class that iterates over a particle container and additional vectors (which are typic...
Definition: ContainerIterator.h:93
Functor base class.
Definition: Functor.h:40
double getCutoff() const
Getter for the functor's cutoff.
Definition: Functor.h:168
static void create(std::string &filename)
create a logger writing to the file system
Definition: Logger.h:44
static auto get()
Get a pointer to the actual logger object.
Definition: Logger.h:90
static void unregister()
removes the logger.
Definition: Logger.h:84
Class describing an interval.
Definition: NumberInterval.h:15
Class describing a finite set of numbers.
Definition: NumberSetFinite.h:19
The ParticleContainerInterface class provides a basic interface for all Containers within AutoPas.
Definition: ParticleContainerInterface.h:37
static void exception(const Exception e)
Handle an exception derived by std::exception.
Definition: ExceptionHandler.h:63
std::set< double > calculateRelevantCsfs(const NumberInterval< double > &numberInterval, double interactionLength, double domainLengthX)
For a given domain parametrization, calculate which cell size factors (csf) in an interval actually a...
Definition: SearchSpaceGenerators.cpp:79
std::set< Configuration > cartesianProduct(const std::set< ContainerOption > &allowedContainerOptions, const std::set< TraversalOption > &allowedTraversalOptions, const std::set< LoadEstimatorOption > &allowedLoadEstimatorOptions, const std::set< DataLayoutOption > &allowedDataLayoutOptions, const std::set< Newton3Option > &allowedNewton3Options, const NumberSet< double > *allowedCellSizeFactors, const InteractionTypeOption &interactionType)
Fills the search space with the cartesian product of the given options (minus invalid combinations).
Definition: SearchSpaceGenerators.cpp:18
std::string getCompilerInfo()
Get name and version number of a list of known compilers.
Definition: CompileInfo.cpp:9
decltype(isTriwiseFunctorImpl(std::declval< FunctorT >())) isTriwiseFunctor
Check whether a Functor Type is inheriting from TriwiseFunctor.
Definition: checkFunctorType.h:56
decltype(isPairwiseFunctorImpl(std::declval< FunctorT >())) isPairwiseFunctor
Check whether a Functor Type is inheriting from PairwiseFunctor.
Definition: checkFunctorType.h:49
This is the main namespace of AutoPas.
Definition: AutoPasDecl.h:32
int AutoPas_MPI_Comm_dup(AutoPas_MPI_Comm comm, AutoPas_MPI_Comm *newComm)
Wrapper for MPI_Comm_dup.
Definition: WrapMPI.h:815
int AutoPas_MPI_Comm_rank(AutoPas_MPI_Comm comm, int *rank)
Wrapper for MPI_Comm_rank.
Definition: WrapMPI.h:807
static unsigned int count
Instance counter to help track the number of autopas instances.
Definition: InstanceCounter.h:18