std::tuple<vector<shared_ptr<Node>>,vector<shared_ptr<Particle>>> SphereClumpGeom::makeParticles(const shared_ptr<Material>& mat, const Vector3r& clumpPos, const Quaternionr& clumpOri, int mask, Real scale){ ensureOk(); assert(centers.size()==radii.size()); const auto N=centers.size(); if(N==1){ // fast path for a single sphere (do not clump at all) auto s=DemFuncs::makeSphere(radii[0]*scale,mat); s->mask=mask; s->shape->nodes[0]->pos=(isnan(clumpPos.maxCoeff())?centers[0]:clumpPos); // natural or forced position return std::make_tuple(vector<shared_ptr<Node>>({s->shape->nodes[0]}),vector<shared_ptr<Particle>>({s})); } vector<shared_ptr<Particle>> par(N); auto n=make_shared<Node>(); auto cd=make_shared<ClumpData>(); n->setData<DemData>(cd); n->pos=(isnan(clumpPos.maxCoeff())?pos:clumpPos); n->ori=clumpOri; cd->nodes.resize(N); cd->relPos.resize(N); cd->relOri.resize(N); for(size_t i=0; i<N; i++){ par[i]=DemFuncs::makeSphere(radii[i]*scale,mat); par[i]->mask=mask; cd->nodes[i]=par[i]->shape->nodes[0]; cd->nodes[i]->getData<DemData>().setClumped(n); // sets flag and assigned master node cd->relPos[i]=(centers[i]-pos)*scale; cd->relOri[i]=ori.conjugate(); // nice to set, but not really important } // sets particles in global space based on relPos, relOri ClumpData::applyToMembers(n); // set clump properties assert(!isnan(volume)); cd->setClump(); assert(cd->isClump()); // scale = length scale (but not density scale) cd->mass=mat->density*volume*pow(scale,3); cd->inertia=mat->density*inertia*pow(scale,5); cd->equivRad=equivRad; return std::make_tuple(vector<shared_ptr<Node>>({n}),par); }
bool isNoClump() const { return !isClumped() && !isClump(); }