1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
|
// 2009 © Václav Šmilauer <eudoxos@arcig.cz>
#pragma once
#include <core/Callbacks.hpp>
#include <core/Dispatching.hpp>
#include <core/GlobalEngine.hpp>
#ifdef USE_TIMING_DELTAS
#define TIMING_DELTAS_CHECKPOINT(cpt) timingDeltas->checkpoint(cpt)
#define TIMING_DELTAS_START() timingDeltas->start()
#else
#define TIMING_DELTAS_CHECKPOINT(cpt)
#define TIMING_DELTAS_START()
#endif
namespace yade { // Cannot have #include directive inside.
class InteractionLoop : public GlobalEngine {
bool alreadyWarnedNoCollider;
using idPair = std::pair<Body::id_t, Body::id_t>;
// store interactions that should be deleted after loop in action, not later
#ifdef YADE_OPENMP
std::vector<std::list<idPair>> eraseAfterLoopIds;
void eraseAfterLoop(Body::id_t id1, Body::id_t id2) { eraseAfterLoopIds[omp_get_thread_num()].push_back(idPair(id1, id2)); }
#else
std::list<idPair> eraseAfterLoopIds;
void eraseAfterLoop(Body::id_t id1, Body::id_t id2) { eraseAfterLoopIds.push_back(idPair(id1, id2)); }
//! create transientInteraction between 2 bodies, using existing Dispatcher in Omega
#endif
public:
void pyHandleCustomCtorArgs(boost::python::tuple& t, boost::python::dict& d) override;
static shared_ptr<Interaction> createExplicitInteraction(Body::id_t id1, Body::id_t id2, bool force, bool virtualI);
void action() override;
// clang-format off
YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(InteractionLoop,GlobalEngine,"Unified dispatcher for handling interaction loop at every step, for parallel performance reasons.\n\n.. admonition:: Special constructor\n\n\tConstructs from 3 lists of :yref:`Ig2<IGeomFunctor>`, :yref:`Ip2<IPhysFunctor>`, :yref:`Law2<LawFunctor>` functors respectively; they will be passed to internal dispatchers, which you might retrieve as :yref:`geomDispatcher<InteractionLoop.geomDispatcher>`, :yref:`physDispatcher<InteractionLoop.physDispatcher>`, :yref:`lawDispatcher<InteractionLoop.lawDispatcher>` respectively.",
((shared_ptr<IGeomDispatcher>,geomDispatcher,new IGeomDispatcher,Attr::readonly,":yref:`IGeomDispatcher` object that is used for dispatch."))
((shared_ptr<IPhysDispatcher>,physDispatcher,new IPhysDispatcher,Attr::readonly,":yref:`IPhysDispatcher` object used for dispatch."))
((shared_ptr<LawDispatcher>,lawDispatcher,new LawDispatcher,Attr::readonly,":yref:`LawDispatcher` object used for dispatch."))
((vector<shared_ptr<IntrCallback> >,callbacks,,,":yref:`Callbacks<IntrCallback>` which will be called for every :yref:`Interaction`, if activated."))
((bool, loopOnSortedInteractions, false,,"If true, the main interaction loop will occur on a sorted list of interactions. This is SLOW but useful to workaround floating point force addition non reproducibility when debugging parallel implementations of yade."))
#ifdef YADE_LS_DEM
((bool, warnRoleIg2, true,,"Whether warnings are output (if true) in case the :yref:`IGeomFunctor` would directly request for interaction removal (by returning false in its ::go function) on existing interactions. It is advised to use false only in the specific case of using :yref:`Ig2_LevelSet_LevelSet_LSnodeGeom`, and true otherwise."))
#endif
,
/*ctor*/ alreadyWarnedNoCollider=false;
#ifdef YADE_OPENMP
eraseAfterLoopIds.resize(omp_get_max_threads());
#endif
,
/*py*/
);
// clang-format on
DECLARE_LOGGER;
};
REGISTER_SERIALIZABLE(InteractionLoop);
} // namespace yade
|