void Gl1_Membrane::drawLocalDisplacement(const Vector2r& nodePt, const Vector2r& xy, const shared_ptr<ScalarRange>& range, bool split, char arrow, int lineWd, const Real z){ Vector3r nodePt3(nodePt[0],nodePt[1],0); if(split){ Vector3r p1=Vector3r(nodePt[0]+xy[0],nodePt[1],0), c1=range->color(xy[0]), p2=Vector3r(nodePt[0],nodePt[1]+xy[1],0), c2=range->color(xy[1]); if(arrow==0){ glLineWidth(lineWd); GLUtils::GLDrawLine(nodePt3,p1,c1); GLUtils::GLDrawLine(nodePt3,p2,c2); } else { // this messes OpenGL coords up!?? GLUtils::GLDrawArrow(nodePt3,p1,c1,/*doubled*/arrow>1); GLUtils::GLDrawArrow(nodePt3,p2,c2,/*doubled*/arrow>1); } } else { Vector3r p1=Vector3r(nodePt[0]+xy[0],nodePt[1]+xy[1],0), c1=range->color(xy.norm()); if(arrow==0){ glLineWidth(lineWd); GLUtils::GLDrawLine(nodePt3,p1,c1); } else { // this messes OpenGL coords up!?? GLUtils::GLDrawArrow(nodePt3,p1,c1,/*doubled*/arrow>1); } } if(!isnan(z)){ glLineWidth(lineWd); GLUtils::GLDrawLine(nodePt3,Vector3r(nodePt[0],nodePt[1],z),range->color(z)); } }
bool Law2_L6Geom_PelletPhys_Pellet::go(const shared_ptr<CGeom>& cg, const shared_ptr<CPhys>& cp, const shared_ptr<Contact>& C){ const L6Geom& g(cg->cast<L6Geom>()); PelletPhys& ph(cp->cast<PelletPhys>()); Real& Fn(ph.force[0]); Eigen::Map<Vector2r> Ft(&ph.force[1]); if(C->isFresh(scene)) C->data=make_shared<PelletCData>(); Real& uNPl(C->data->cast<PelletCData>().uNPl); Real& uN0(C->data->cast<PelletCData>().uN0); assert(C->data && dynamic_pointer_cast<PelletCData>(C->data)); if(iniEqlb && C->isFresh(scene)) uN0=g.uN; Real uN=g.uN-uN0; // normal displacement, taking iniEqlb in account // break contact if(uN>0) return false; Real d0=g.lens.sum(); if(ph.normPlastCoeff<=0) uNPl=0.; const Vector2r velT(g.vel[1],g.vel[2]); ph.torque=Vector3r::Zero(); // normal force Fn=ph.kn*(uN-uNPl); // trial force if(ph.normPlastCoeff>0){ // normal plasticity activated if(Fn>0){ if(ph.ka<=0) Fn=0; else{ Fn=min(Fn,adhesionForce(uN,uNPl,ph.ka)); assert(Fn>0); } } else { Real Fy=yieldForce(uN,d0,ph.kn,ph.normPlastCoeff); // normal plastic slip if(Fn<Fy){ Real uNPl0=uNPl; // needed when tracking energy uNPl=uN-Fy/ph.kn; if(unlikely(scene->trackEnergy)){ // backwards trapezoid integration Real Fy0=Fy+yieldForceDerivative(uN,d0,ph.kn,ph.normPlastCoeff)*(uNPl0-uNPl); Real dissip=.5*abs(Fy0+Fy)*abs(uNPl-uNPl0); scene->energy->add(dissip,plastSplit?"normPlast":"plast",plastSplit?normPlastIx:plastIx,EnergyTracker::IsIncrement | EnergyTracker::ZeroDontCreate); tryAddDissipState(DISSIP_NORM_PLAST,dissip,C); } if(thinRate>0 && thinRelRMin<1.){ const Vector2r bendVel(g.angVel[1],g.angVel[2]); Real dRad_0=thinRate*(uNPl0-uNPl)*(scene->dt*bendVel.norm()); for(const Particle* p:{C->leakPA(),C->leakPB()}){ if(!dynamic_cast<Sphere*>(p->shape.get())) continue; Real dRad=dRad_0; // copy to be modified auto& s=p->shape->cast<Sphere>(); //Real r0=(C->geom->cast<L6Geom>().lens[p.get()==C->pA.get()?0:1]); Real r0=cbrt(3*s.nodes[0]->getData<DemData>().mass/(4*M_PI*p->material->density)); Real rMin=r0*thinRelRMin; if(thinRefRad>0.) rMin*=pow(r0/thinRefRad,thinMinExp); if(s.radius<=rMin) continue; // 0..1 norm between rMin and r0 Real r01=(s.radius-rMin)/(r0-rMin); if(thinExp>0) dRad*=pow(r01,thinExp); if(thinRefRad>0.) dRad*=pow(r0/thinRefRad,thinRateExp); boost::mutex::scoped_lock lock(s.nodes[0]->getData<DemData>().lock); // cerr<<"#"<<p->id<<": radius "<<s.radius<<" -> "<<s.radius-dRad<<endl; s.radius=max(rMin,s.radius-dRad*r01); s.color=CompUtils::clamped(1-(s.radius-rMin)/(r0-rMin),0,1); } } Fn=Fy; } // in the elastic regime, Fn is trial force already } } /* add fake confinement */ if(confSigma!=0) Fn-=g.contA*confSigma*(confRefRad>0.?pow(g.contA/(M_PI*pow(confRefRad,2)),confExp):1.); // shear force Ft+=scene->dt*ph.kt*velT; Real maxFt=abs(Fn)*ph.tanPhi; assert(maxFt>=0); // shear plastic slip if(Ft.squaredNorm()>pow(maxFt,2)){ Real FtNorm=Ft.norm(); Real ratio=maxFt/FtNorm; if(unlikely(scene->trackEnergy)){ Real dissip=(.5*(FtNorm-maxFt)+maxFt)*(FtNorm-maxFt)/ph.kt; scene->energy->add(dissip,"plast",plastIx,EnergyTracker::IsIncrement | EnergyTracker::ZeroDontCreate); tryAddDissipState(DISSIP_SHEAR_PLAST,dissip,C); } Ft*=ratio; } assert(!isnan(Fn)); assert(!isnan(Ft[0]) && !isnan(Ft[1])); // elastic potential energy if(unlikely(scene->trackEnergy)) scene->energy->add(0.5*(pow(Fn,2)/ph.kn+Ft.squaredNorm()/ph.kt),"elast",elastPotIx,EnergyTracker::IsResettable); return true; }