Question #404070 on Yade changed: https://answers.launchpad.net/yade/+question/404070
Haohui Xin posted a new comment: Hello, Thanks. The latest error is as following. It could cmakem make and make install. But it appeared problems when I run it. Traceback (most recent call last): File "./yade-2016-10-31.git-1b22b1a", line 129, in <module> import yade File "/home/xhh/yade/install/lib/x86_64-linux-gnu/yade-2016-10-31.git-1b22b1a/py/yade/__init__.py", line 67, in <module> import system RuntimeError: extension class wrapper for base class HeatCollider has not been created yet Firstly, I define a new engine. #pragma once #include<core/GlobalEngine.hpp> class HeatEngine: public Engine { public : virtual ~HeatEngine() {}; YADE_CLASS_BASE_DOC(HeatEngine,Engine,"Engine that used for heat simulation."); }; REGISTER_SERIALIZABLE(HeatEngine); Second, I define a new collider #pragma once #include<core/Bound.hpp> #include<core/Interaction.hpp> #include<pkg/common/HeatEngine.hpp> #include<pkg/common/Dispatching.hpp> class HeatCollider: public HeatEngine { public: static int avoidSelfInteractionMask; /*! Probe the Bound on a bodies presense. Returns list of body ids with which there is potential overlap. */ virtual vector<Body::id_t> probeBoundingVolume(const Bound&){throw;} static bool mayCollide(const Body*, const Body*); virtual void invalidatePersistentData(){} // ctor with functors for the integrated BoundDispatcher virtual void pyHandleCustomCtorArgs(boost::python::tuple& t, boost::python::dict& d); int get_avoidSelfInteractionMask(){return avoidSelfInteractionMask;} void set_avoidSelfInteractionMask(const int &v){avoidSelfInteractionMask = v;} YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(HeatCollider,HeatEngine,"Abstract class for finding spatial collisions between bodies. \n\n.. admonition:: Special constructor\n\n\tDerived HeatColliders (unless they override ``pyHandleCustomCtorArgs``) can be given list of :yref:`BoundFunctors <BoundFunctor>` which is used to initialize the internal :yref:`boundDispatcher <HeatCollider.boundDispatcher>` instance.", ((shared_ptr<BoundDispatcher>,boundDispatcher,new BoundDispatcher,Attr::readonly,":yref:`BoundDispatcher` object that is used for creating :yref:`bounds <Body.bound>` on HeatCollider's request as necessary.")), /*ctor*/, .add_property("avoidSelfInteractionMask",&HeatCollider::get_avoidSelfInteractionMask,&HeatCollider::set_avoidSelfInteractionMask,"This mask is used to avoid the interactions inside a group of particles. To do so, the particles must have the same mask and this mask have to be compatible with this one.") ); DECLARE_LOGGER; }; REGISTER_SERIALIZABLE(HeatCollider); #include<pkg/common/HeatCollider.hpp> YADE_PLUGIN((HeatCollider)); int HeatCollider::avoidSelfInteractionMask = 0 ; bool HeatCollider::mayCollide(const Body* b1, const Body* b2){ return // might be called with deleted bodies, i.e. NULL pointers (b1!=NULL && b2!=NULL) && // only collide if at least one particle is standalone or they belong to different clumps (b1->isStandalone() || b2->isStandalone() || b1->clumpId!=b2->clumpId #ifdef YADE_SPH // If SPH-mode enabled, we do not skip interactions between clump-members // to get the correct calculation of density b->rho || true #endif ) && // do not collide clumps, since they are just containers, never interact !b1->isClump() && !b2->isClump() && // masks must have at least 1 bit in common b1->maskCompatible(b2->groupMask) && // avoid contact between particles having the same mask compatible with the avoidSelfInteractionMask. !( (b1->groupMask == b2->groupMask) && b1->maskCompatible(avoidSelfInteractionMask) ) ; } void HeatCollider::pyHandleCustomCtorArgs(boost::python::tuple& t, boost::python::dict& d){ if(boost::python::len(t)==0) return; // nothing to do if(boost::python::len(t)!=1) throw invalid_argument(("HeatCollider optionally takes exactly one list of BoundFunctor's as non-keyword argument for constructor ("+boost::lexical_cast<string>(boost::python::len(t))+" non-keyword ards given instead)").c_str()); typedef std::vector<shared_ptr<BoundFunctor> > vecBound; vecBound vb=boost::python::extract<vecBound>(t[0])(); FOREACH(shared_ptr<BoundFunctor> bf, vb) this->boundDispatcher->add(bf); t=boost::python::tuple(); // empty the args } define an new sort methods /************************************************************************* * Copyright (C) 2008 by Sergei Dorofeenko * * s...@users.berlios.de * * * * This program is free software; it is licensed under the terms of the * * GNU General Public License v2 or later. See file LICENSE for details. * *************************************************************************/ #pragma once #include <pkg/common/HeatCollider.hpp> #include <core/InteractionContainer.hpp> #include <vector> class HeatSpatialQuickSortCollider : public HeatCollider { protected: struct AABBBound { Vector3r min,max; int id; }; class xBoundComparator { public: bool operator() (shared_ptr<AABBBound> b1, shared_ptr<AABBBound> b2) { return b1->min[0] < b2->min[0]; } }; vector<shared_ptr<AABBBound> > rank; public: virtual void action(); YADE_CLASS_BASE_DOC(HeatSpatialQuickSortCollider,HeatCollider,"Collider using quicksort along axes at each step, using :yref:`Aabb` bounds. \n\n Its performance is lower than that of :yref:`InsertionSortCollider` (see `Colliders' performance <https://yade-dem.org/index.php/Colliders_performace>`_), but the algorithm is simple enought to make it good for checking other collider's correctness."); }; REGISTER_SERIALIZABLE(HeatSpatialQuickSortCollider); /************************************************************************* * Copyright (C) 2008 by Sergei Dorofeenko * * s...@users.berlios.de * * * * This program is free software; it is licensed under the terms of the * * GNU General Public License v2 or later. See file LICENSE for details. * *************************************************************************/ #include "HeatSpatialQuickSortCollider.hpp" #include <core/Scene.hpp> #include <core/BodyContainer.hpp> #include <cmath> #include <algorithm> YADE_PLUGIN((HeatSpatialQuickSortCollider)); void HeatSpatialQuickSortCollider::action() { // update bounds boundDispatcher->scene=scene; boundDispatcher->action(); const shared_ptr<BodyContainer>& bodies = scene->bodies; // This collider traverses all interactions at every step, therefore all interactions // that were requested for erase might be erased here and will be recreated if necessary. scene->interactions->eraseNonReal(); size_t nbElements=bodies->size(); if (nbElements!=rank.size()) { size_t n = rank.size(); rank.resize(nbElements); for (; n<nbElements; ++n) rank[n] = shared_ptr<AABBBound>(new AABBBound); } Vector3r min,max; int i=0; FOREACH(const shared_ptr<Body>& b, *bodies){ if(!b->bound) continue; min = b->bound->min; max = b->bound->max; rank[i]->id = b->getId(); rank[i]->min = min; rank[i]->max = max; i++; } const shared_ptr<InteractionContainer>& interactions=scene->interactions; scene->interactions->iterColliderLastRun=scene->iter; sort(rank.begin(), rank.end(), xBoundComparator()); // sorting along X int id,id2; size_t j; shared_ptr<Interaction> interaction; for(int i=0,e=nbElements-1; i<e; ++i) { id = rank[i]->id; min = rank[i]->min; max = rank[i]->max; j=i; while(++j<nbElements) { if ( rank[j]->min[0] > max[0]) break; if ( rank[j]->min[1] < max[1] && rank[j]->max[1] > min[1] && rank[j]->min[2] < max[2] && rank[j]->max[2] > min[2]) { id2=rank[j]->id; if ( (interaction = interactions->find(Body::id_t(id),Body::id_t(id2))) == 0) { interaction = shared_ptr<Interaction>(new Interaction(id,id2) ); interactions->insert(interaction); } interaction->iterLastSeen=scene->iter; } } } } define an new loop #pragma once #include<pkg/common/HeatEngine.hpp> #include <pkg/common/Callbacks.hpp> #include <pkg/common/Dispatching.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 class HeatInteractionLoop: public HeatEngine { 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 list<idPair> eraseAfterLoopIds; void eraseAfterLoop(Body::id_t id1,Body::id_t id2){ eraseAfterLoopIds.push_back(idPair(id1,id2)); } #endif public: virtual void pyHandleCustomCtorArgs(boost::python::tuple& t, boost::python::dict& d); virtual void action(); YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(HeatInteractionLoop,HeatEngine,"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:`Law<LawFunctor>` functors respectively; they will be passed to interal dispatchers, which you might retrieve.", ((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, eraseIntsInLoop, false,,"Defines if the interaction loop should erase pending interactions, else the collider takes care of that alone (depends on what collider is used).")) , /*ctor*/ alreadyWarnedNoCollider=false; #ifdef YADE_OPENMP eraseAfterLoopIds.resize(omp_get_max_threads()); #endif , /*py*/ ); DECLARE_LOGGER; }; REGISTER_SERIALIZABLE(HeatInteractionLoop); #include"HeatInteractionLoop.hpp" YADE_PLUGIN((HeatInteractionLoop)); CREATE_LOGGER(HeatInteractionLoop); void HeatInteractionLoop::pyHandleCustomCtorArgs(boost::python::tuple& t, boost::python::dict& d){ if(boost::python::len(t)==0) return; // nothing to do if(boost::python::len(t)!=3) throw invalid_argument("Exactly 3 lists of functors must be given"); // parse custom arguments (3 lists) and do in-place modification of args using vecGeom = std::vector<shared_ptr<IGeomFunctor> >; using vecPhys = std::vector<shared_ptr<IPhysFunctor> >; using vecLaw = std::vector<shared_ptr<LawFunctor> >; vecGeom vg=boost::python::extract<vecGeom>(t[0])(); vecPhys vp=boost::python::extract<vecPhys>(t[1])(); vecLaw vl=boost::python::extract<vecLaw>(t[2])(); for(const auto gf : vg) this->geomDispatcher->add(gf); for(const auto pf : vp) this->physDispatcher->add(pf); for(const auto cf : vl) this->lawDispatcher->add(cf); t=boost::python::tuple(); // empty the args; not sure if this is OK, as there is some refcounting in raw_constructor code } void HeatInteractionLoop::action(){ // update Scene* of the dispatchers lawDispatcher->scene=scene; physDispatcher->scene=scene; geomDispatcher->scene=scene; // ask dispatchers to update Scene* of their functors geomDispatcher->updateScenePtr(); physDispatcher->updateScenePtr(); lawDispatcher->updateScenePtr(); /* initialize callbacks; they return pointer (used only in this timestep) to the function to be called returning NULL deactivates the callback in this timestep */ // pair of callback object and pointer to the function to be called vector<IntrCallback::FuncPtr> callbackPtrs; for (const auto cb : callbacks){ cb->scene=scene; callbackPtrs.push_back(cb->stepInit()); } assert(callbackPtrs.size()==callbacks.size()); const size_t callbacksSize=callbacks.size(); // cache transformed cell size Matrix3r cellHsize = Matrix3r::Zero(); if(scene->isPeriodic) { cellHsize=scene->cell->hSize; } // force removal of interactions that were not encountered by the collider // (only for some kinds of colliders; see comment for InteractionContainer::iterColliderLastRun) const bool removeUnseenIntrs=(scene->interactions->iterColliderLastRun>=0 && scene->interactions->iterColliderLastRun==scene->iter); #ifdef YADE_OPENMP const long size=scene->interactions->size(); #pragma omp parallel for schedule(guided) num_threads(ompThreads>0 ? min(ompThreads,omp_get_max_threads()) : omp_get_max_threads()) for(long i=0; i<size; i++){ const shared_ptr<Interaction>& I=(*scene->interactions)[i]; #else for (const auto & I : *scene->interactions){ #endif if(removeUnseenIntrs && !I->isReal() && I->iterLastSeen<scene->iter) { eraseAfterLoop(I->getId1(),I->getId2()); continue; } const shared_ptr<Body>& b1_=Body::byId(I->getId1(),scene); const shared_ptr<Body>& b2_=Body::byId(I->getId2(),scene); if(!b1_ || !b2_){ LOG_DEBUG("Body #"<<(b1_?I->getId2():I->getId1())<<" vanished, erasing intr #"<<I->getId1()<<"+#"<<I->getId2()<<"!"); scene->interactions->requestErase(I); continue; } // Skip interaction with clumps if (b1_->isClump() || b2_->isClump()) { continue; } // we know there is no geometry functor already, take the short path if(!I->functorCache.geomExists) { assert(!I->isReal()); continue; } // no interaction geometry for either of bodies; no interaction possible if(!b1_->shape || !b2_->shape) { assert(!I->isReal()); continue; } bool swap=false; // IGeomDispatcher if(!I->functorCache.geom){ I->functorCache.geom=geomDispatcher->getFunctor2D(b1_->shape,b2_->shape,swap); // returns NULL ptr if no functor exists; remember that and shortcut if(!I->functorCache.geom) { I->functorCache.geomExists=false; continue; } } // arguments for the geom functor are in the reverse order (dispatcher would normally call goReverse). // we don't remember the fact that is reverse, so we swap bodies within the interaction // and can call go in all cases if(swap){I->swapOrder();} // body pointers must be updated, in case we swapped const shared_ptr<Body>& b1=swap?b2_:b1_; const shared_ptr<Body>& b2=swap?b1_:b2_; assert(I->functorCache.geom); bool wasReal=I->isReal(); bool geomCreated; if(!scene->isPeriodic){ geomCreated=I->functorCache.geom->go(b1->shape,b2->shape, *b1->state, *b2->state, Vector3r::Zero(), /*force*/false, I); } else { // handle periodicity Vector3r shift2=cellHsize*I->cellDist.cast<Real>(); // in sheared cell, apply shear on the mutual position as well geomCreated=I->functorCache.geom->go(b1->shape,b2->shape,*b1->state,*b2->state,shift2,/*force*/false,I); } if(!geomCreated){ if(wasReal) LOG_WARN("IGeomFunctor returned false on existing interaction!"); if(wasReal) scene->interactions->requestErase(I); // fully created interaction without geometry is reset and perhaps erased in the next step continue; // in any case don't care about this one anymore } // IPhysDispatcher if(!I->functorCache.phys){ I->functorCache.phys=physDispatcher->getFunctor2D(b1->material,b2->material,swap); assert(!swap); // InteractionPhysicsEngineUnits are symmetric } if(!I->functorCache.phys){ throw std::runtime_error("Undefined or ambiguous IPhys dispatch for types "+b1->material->getClassName()+" and "+b2->material->getClassName()+"."); } I->functorCache.phys->go(b1->material,b2->material,I); assert(I->phys); if(!wasReal) I->iterMadeReal=scene->iter; // mark the interaction as created right now // LawDispatcher // populating constLaw cache must be done after geom and physics dispatchers have been called, since otherwise the interaction // would not have geom and phys yet. if(!I->functorCache.constLaw){ I->functorCache.constLaw=lawDispatcher->getFunctor2D(I->geom,I->phys,swap); if(!I->functorCache.constLaw){ LOG_FATAL("None of given Law2 functors can handle interaction #"<<I->getId1()<<"+"<<I->getId2()<<", types geom:"<<I->geom->getClassName()<<"="<<I->geom->getClassIndex()<<" and phys:"<<I->phys->getClassName()<<"="<<I->phys->getClassIndex()<<" (LawDispatcher::getFunctor2D returned empty functor)"); exit(1); } assert(!swap); // reverse call would make no sense, as the arguments are of different types } assert(I->functorCache.constLaw); //If the functor return false, the interaction is reset if (!I->functorCache.constLaw->go(I->geom,I->phys,I.get())) scene->interactions->requestErase(I); // process callbacks for this interaction if(!I->isReal()) continue; // it is possible that Law2_ functor called requestErase, hence this check for(size_t i=0; i<callbacksSize; i++){ if(callbackPtrs[i]!=NULL) (*(callbackPtrs[i]))(callbacks[i].get(),I.get()); } } } -- You received this question notification because your team yade-users is an answer contact for Yade. _______________________________________________ Mailing list: https://launchpad.net/~yade-users Post to : yade-users@lists.launchpad.net Unsubscribe : https://launchpad.net/~yade-users More help : https://help.launchpad.net/ListHelp