Exemple #1
0
void Gl1_CPhys::go(const shared_ptr<CPhys>& cp, const shared_ptr<Contact>& C, const GLViewInfo& viewInfo){
	if(!range) return;
	if(shearColor && !shearRange) shearColor=false;
	// shared_ptr<CGeom> cg(C->geom); if(!cg) return; // changed meanwhile?
	Real fn=cp->force[0];
	if(isnan(fn)) return;
	if((signFilter>0 && fn<0) || (signFilter<0 && fn>0)) return;
	range->norm(fn); // adjust range, return value discarded
	Real r=relMaxRad*viewInfo.sceneRadius*min(1.,(abs(fn)/(max(abs(range->mnmx[0]),abs(range->mnmx[1])))));
	if(r<viewInfo.sceneRadius*1e-4 || isnan(r)) return;
	Vector3r color=shearColor?shearRange->color(Vector2r(cp->force[1],cp->force[2]).norm()):range->color(fn);
	if(isnan(color.maxCoeff())) return;
	const Particle *pA=C->leakPA(), *pB=C->leakPB();
	// get both particle's space positions, but B moved so that it is relative to A as the contact is
	Vector3r A=(pA->shape->isA<Sphere>()?pA->shape->nodes[0]->pos:C->geom->node->pos);
	Vector3r B=pB->shape->avgNodePos()+((scene->isPeriodic)?(scene->cell->intrShiftPos(C->cellDist)):Vector3r::Zero());
	if(pA->shape->nodes[0]->hasData<GlData>() && pB->shape->nodes[0]->hasData<GlData>()){
		const GlData &glA=pA->shape->nodes[0]->getData<GlData>(), &glB=pB->shape->nodes[0]->getData<GlData>();
		// move particles so that they are as they would be displayed (A is the master, B may be off if necessary for the contact, as per intrShiftPos above)
		A+=glA.dGlPos; B+=glB.dGlPos;
		// if points were wrapped by different number of cells in dGlPos, fix that
		if(scene->isPeriodic && glA.dCellDist!=glB.dCellDist){
			// move B by its position difference, but by as many cells as A
			// so move it back by glB.dCellDist and forward by glA.dCellDist
			// then they should be positioned relatively as they should be for the contact
			// adjacent to the position where "A" is displayed as particle
			B+=scene->cell->intrShiftPos(glB.dCellDist-glA.dCellDist);
		}
	}
	// cerr<<"["<<r<<"]";
	GLUtils::Cylinder(A,B,r,color,/*wire*/false,/*caps*/false,/*rad2*/-1,slices);
}
Exemple #2
0
void ActReactGlRep::render(const shared_ptr<Node>& node, const GLViewInfo* viewInfo){
	Real len0=relSz*viewInfo->sceneRadius;
	Vector3r offset=relOff*viewInfo->sceneRadius*(node->ori.conjugate()*Vector3r::UnitX());
	Vector3r pos=node->pos;
	if(viewInfo->scene->isPeriodic) pos=viewInfo->scene->cell->canonicalizePt(pos);
	if(range && !shearRange) shearRange=range;
	// separate normal component
	if(comp==0 || comp==2){
		Vector3r c=range?range->color(val[0]):CompUtils::scalarOnColorScale(val[0],0,1);
		Real len=len0*abs(val[0])/(range?range->maxAbs(val[0]):1);
		//arr.push_back(Vector3r(len,0,0)*sgn(val[0]));
		renderDoubleArrow(pos,node->ori.conjugate()*Vector3r(sgn(val[0])*len,0,0),/*posStart*/val[0]>0,offset,c);
	}
	// separate shear component
	if(comp==1 || comp==2){
		Real shear=Vector2r(val[1],val[2]).norm();
		Vector3r c=shearRange?shearRange->color(shear):CompUtils::scalarOnColorScale(shear,0,1);
		Real len=len0*shear/(shearRange?shearRange->maxAbs(shear):1);
		renderDoubleArrow(pos,node->ori.conjugate()*Vector3r(0,val[1]/shear*len,val[2]/shear*len),/*posStart*/true,offset,c);
	}
	if(comp==3){
		Real fNorm=val.norm();
		Vector3r c=range?range->color(fNorm):CompUtils::scalarOnColorScale(fNorm,0,1);
		Real len=len0*fNorm/(range?range->maxAbs(fNorm):1);
		renderDoubleArrow(pos,node->ori.conjugate()*(len*val/fNorm),/*posStart*/val[0]>0,offset,c);
	}
}
Exemple #3
0
bool CylinderInlet::validateBox(const AlignedBox3r& b) {
	if(!node) throw std::runtime_error("CylinderInlet.node==None.");
	/* check all corners are inside the cylinder */
	#if 0
		boxesTried.push_back(b);
	#endif
	for(AlignedBox3r::CornerType c:{AlignedBox3r::BottomLeft,AlignedBox3r::BottomRight,AlignedBox3r::TopLeft,AlignedBox3r::TopRight,AlignedBox3r::BottomLeftCeil,AlignedBox3r::BottomRightCeil,AlignedBox3r::TopLeftCeil,AlignedBox3r::TopRightCeil}){
		Vector3r p=node->glob2loc(b.corner(c));
		if(p[0]<0. || p[0]>height) return false;
		if(Vector2r(p[1],p[2]).squaredNorm()>pow(radius,2)) return false;
	}
	return true;
}
Exemple #4
0
void POVRayExport::run(){
	// force some color range
	if(!colorRange) colorRange=make_shared<ScalarRange>();
	colorRange->mnmx=Vector2r(0,1); // full range

	out=scene->expandTags(out);
	string staticInc=out+"_static.inc";
	string masterPov=out+"_master.pov";
	if(!boost::filesystem::exists(masterPov)) writeMasterPov(masterPov);
	// overwrite static mesh when run the first time always
	if(nDone==1 || !boost::filesystem::exists(staticInc)) writeParticleInc(staticInc,/*doStatic*/true);

	string frameInc=out+(boost::format("_frame_%05d.inc")%frameCounter).str();
	writeParticleInc(frameInc,/*doStatic*/false);
	frameCounter++;
}
Exemple #5
0
size_t DemFuncs::radialAxialForce(const Scene* scene, const DemField* dem, int mask, Vector3r axis, bool shear, Vector2r& radAxF){
	size_t ret=0;
	radAxF=Vector2r::Zero();
	axis.normalize();
	for(const shared_ptr<Particle>& p: *dem->particles){
		if(!(p->mask & mask) || !p->shape) continue;
		ret++;
		for(const auto& idC: p->contacts){
			const shared_ptr<Contact>& C(idC.second);
			if(!C->isReal()) continue;
			Vector3r F=C->geom->node->ori*((shear?C->phys->force:Vector3r(C->phys->force[0],0,0))*C->forceSign(p));
			Vector3r axF=F.dot(axis);
			radAxF+=Vector2r(axF,(F-axF).norm());
		}
	}
	return ret;
}
Exemple #6
0
	/* return list of quantile values for contact coordinates in node-local z-coordinates, for contacts inside *box* (in local coordinates). The list returned has the same length as *quantiles* */
	static vector<Real> contactCoordQuantiles(const shared_ptr<DemField>& dem, const vector<Real>& quantiles, const shared_ptr<Node>& node, const AlignedBox3r& box);

	#if 0
		static Vector2r radialAxialForce(const Scene* scene, const DemField* dem, int mask, Vector3r axis, bool shear);
	#endif

	# if 0
		// helper zip range adaptor, when psd should iterates over 2 sequences (of diameters and radii)
		// http://stackoverflow.com/a/8513803/761090
		auto zip_end = 
		template <typename... T>
		auto zip(const T&... containers) -> boost::iterator_range<boost::zip_iterator<decltype(boost::make_tuple(std::begin(containers)...))>>{ return boost::make_iterator_range(boost::make_zip_iterator(boost::make_tuple(std::begin(containers)...)),boost::make_zip_iterator(boost::make_tuple(std::end(containers)...))); }
	#endif

	
	template<class IteratorRange, class DiameterGetter, class WeightGetter> /* iterate over spheres */
	static vector<Vector2r> psd(const IteratorRange& particleRange,
		bool cumulative, bool normalize, int num, Vector2r dRange,
		DiameterGetter diameterGetter,
		WeightGetter weightGetter,
		bool emptyOk=false
	){
		/* determine dRange if not given */
		if(isnan(dRange[0]) || isnan(dRange[1]) || dRange[0]<0 || dRange[1]<=0 || dRange[0]>=dRange[1]){
			dRange=Vector2r(Inf,-Inf); size_t n=0;
			for(const auto& p: particleRange){
				Real d=diameterGetter(p,n);
				if(d<dRange[0]) dRange[0]=d;
				if(d>dRange[1]) dRange[1]=d;
				n+=1;
			}
			if(isinf(dRange[0])){
				if(!emptyOk) throw std::runtime_error("DemFuncs::psd: no spherical particles?");
				else return vector<Vector2r>{Vector2r::Zero(),Vector2r::Zero()};
			}
		}
		/* put particles in bins */
		vector<Vector2r> ret(num,Vector2r::Zero());
		Real weight=0; size_t n=0;
		for(const auto& p: particleRange){
			Real d=diameterGetter(p,n);
			Real w=weightGetter(p,n);
			n+=1;
			// NaN diameter or weight, or zero weight make the particle effectively disappear
			if(isnan(d) || isnan(w) || w==0.) continue;
			// particles beyong upper bound are discarded, though their weight is taken in account
			weight+=w;
			if(d>dRange[1]) continue;
			int bin=max(0,min(num-1,1+(int)((num-1)*((d-dRange[0])/(dRange[1]-dRange[0])))));
			ret[bin][1]+=w;
		}
		// set diameter values
		for(int i=0;i<num;i++) ret[i][0]=dRange[0]+i*(dRange[1]-dRange[0])/(num-1);
		// cummulate and normalize
		if(normalize) for(int i=0;i<num;i++) ret[i][1]=ret[i][1]/weight;
		if(cumulative) for(int i=1;i<num;i++) ret[i][1]+=ret[i-1][1];
		return ret;
	};
		((Real,maxExten,0.0,,"Plastic failure extension (stretching)."))
		((Real,maxContract,0.0,,"Plastic failure contraction (shrinkage)."))
		((Real,maxBendMom,0.0,,"Plastic failure bending moment."))
		((Real,maxTwist,0.0,,"Plastic failure twist angle"))
		
		((bool,isBroken,false,,"true if compression plastic fracture achieved"))

		((Real,unp,0,,"plastic normal penetration depth describing the equilibrium state."))
		((Real,twp,0,,"plastic twist penetration depth describing the equilibrium state."))
		
		((bool,onPlastB,false,Attr::readonly,"true if plasticity achieved on bending"))
		((bool,onPlastTw,false,Attr::readonly,"true if plasticity achieved on twisting"))
		((bool,onPlastT,false,Attr::readonly,"true if plasticity achieved on traction"))
		((bool,onPlastC,false,Attr::readonly,"true if plasticity achieved on compression"))
		
		((Vector2r,maxCrpRchdT,Vector2r(0,0),Attr::readonly,"maximal extension reached on plastic deformation. maxCrpRchdT[0] stores un and maxCrpRchdT[1] stores Fn."))
		((Vector2r,maxCrpRchdC,Vector2r(0,0),Attr::readonly,"maximal compression reached on plastic deformation. maxCrpRchdC[0] stores un and maxCrpRchdC[1] stores Fn."))
		((Vector2r,maxCrpRchdTw,Vector2r(0,0),Attr::readonly,"maximal twist reached on plastic deformation. maxCrpRchdTw[0] stores twist angle and maxCrpRchdTw[1] stores twist moment."))
		((Vector3r,maxCrpRchdB,Vector3r(0,0,0),Attr::readonly,"maximal bending moment reached on plastic deformation."))
		
		((Vector3r,moment_twist,Vector3r(0,0,0),(Attr::readonly),"Twist moment"))
		((Vector3r,moment_bending,Vector3r(0,0,0),(Attr::readonly),"Bending moment"))
		((Vector3r,pureCreep,Vector3r(0,0,0),(Attr::readonly),"Pure creep curve, used for comparison in calculation."))
		((Real,kDam,0,(Attr::readonly),"Damage coefficient on bending, computed from maximum bending moment reached and pure creep behaviour. Its values will vary between :yref:`InelastCohFrictPhys::kr` and :yref:`InelastCohFrictPhys::kRCrp` ."))
		// internal attributes
		,
		createIndex();
	);
/// Indexable
	REGISTER_CLASS_INDEX(InelastCohFrictPhys,FrictPhys);