# -*- coding: utf-8 -*- from yade import pack ############################################ ### DEFINING VARIABLES AND MATERIALS ### ############################################ # Batch execution nRead=utils.readParamsFromTable( num_spheres=10000,# number of spheres len(O.bodies) to verify: 10006 = 10000 particles + 6 walls is correct compFricDegree = 22, # contact friction unknownOk=True, isoForce=100000, # stress for the isotropic compression phase (1) conStress=100000 # confinement stress, for the deviatoric loading session ) from yade.params import table num_spheres=table.num_spheres targetPorosity = 0.387 #the porosity we want for the packing (3 specimens: (Ei,n) = (1,0.382), (2,0.387), (3,0.409) ) compFricDegree = table.compFricDegree # initial contact friction during the confining phase (will be decreased during the REFD compaction process) finalFricDegree = 35 # contact friction during the deviatoric loading rate=0.1 # loading rate (strain rate) damp=0.06 # damping coefficient stabilityThreshold=0.001 # initial value: 0.001 key='_triax_draine_e633_100kpa' # simulation's name here young=356e6 # contact stiffness k_n/ mn,mx=Vector3(-0.2,-0.2,-0.2),Vector3(0.2,0.2,0.2) # corners of the initial packing thick = 0.01 # thickness of the plates ## create materials for spheres and plates O.materials.append(FrictMat(young=young,poisson=0.42,frictionAngle=radians(compFricDegree),density=3000,label='spheres')) O.materials.append(FrictMat(young=young,poisson=0.5,frictionAngle=0,density=0,label='walls')) ## create walls around the packing walls=utils.aabbWalls([mn,mx],thickness=thick,oversizeFactor=1.5,material='walls') wallIds=O.bodies.append(walls) ## use a SpherePack object to generate a random loose particles packing sp=pack.SpherePack() sp.makeCloud(mn,mx,0.005,0.7,num_spheres,False,0.8,seed=0) #"seed" make the "random" generation always the same sp.toSimulation(material='spheres') ############################ ### DEFINING ENGINES ### ############################ triax=TriaxialStressController( thickness = thick, stressMask = 7, radiusControlInterval=15, goal1=table.isoForce, goal2=table.isoForce, goal3=table.isoForce, max_vel=2, # validated only when internalCompaction = False length/time internalCompaction=False, # If true the confining pressure is generated by growing particles ) newton=NewtonIntegrator(damping=damp) O.engines=[ ForceResetter(), InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb()]), InteractionLoop( [Ig2_Sphere_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom()], [Ip2_FrictMat_FrictMat_FrictPhys()], [Law2_ScGeom_FrictPhys_CundallStrack()] ), GlobalStiffnessTimeStepper(active=1,timeStepUpdateInterval=25,timestepSafetyCoefficient=0.8), triax, TriaxialStateRecorder(iterPeriod=100,file='WallStresses'+key), newton ] O.save('initial'+key+'.xml') #Display spheres with 2 colors for seeing rotations better Gl1_Sphere.stripes=1 if nRead==0: yade.qt.Controller(), yade.qt.View() print 'Number of elements: ', len(O.bodies) #print 'Box Volume: ', triax.boxVolume ####################################### ### APPLYING CONFINING PRESSURE ### ####################################### while 1: O.run(1000, True) #the global unbalanced force on dynamic bodies, thus excluding boundaries, which are not at equilibrium unb=unbalancedForce() #average stress #note: triax.stress(k) returns a stress vector, so we need to keep only the normal component meanS=(triax.stress(triax.wall_right_id)[0]+triax.stress(triax.wall_top_id)[1]+triax.stress(triax.wall_front_id)[2])/3 print 'unbalanced force:',unb,' mean stress: ',meanS print 'void ratio=',triax.porosity/(1-triax.porosity), 'porosity=', triax.porosity print 'mean stress of engine', triax.meanStress if unb