# -*- 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/<Ds>
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<stabilityThreshold and abs(meanS-table.isoForce)/table.isoForce<0.001: #0.001
break
O.save('confinedState'+key+'.xml')
print "### Isotropic state saved ###"
print 'current porosity=',triax.porosity
print 'current void ratio=',triax.porosity/(1-triax.porosity)
print 'step that starts the deviatoric loading ', O.iter
from yade import plot
from pprint import pprint
plot.reset()
e22Check=triax.strain[1]
plot.addData(CheckpointStep=O.iter,Porosity=triax.porosity,e22=triax.strain[1])
plot.saveDataTxt('checkpoint.txt',vars=('CheckpointStep','Porosity','e22'))
##############################
### DEVIATORIC LOADING ###
##############################
# Change contact friction (remember that decreasing it would generate instantaneous instabilities)
#setContactFriction(radians(finalFricDegree))
setContactFriction(radians(35))
#set stress control on x and z, we will impose strain rate on y (5)
triax.stressMask = 5
#now goal2 is the target strain rate
triax.goal2=-rate
#we assign constant stress to the other directions
triax.goal1=table.conStress
triax.goal3=table.conStress
##we can change damping here. What is the effect in your opinion?
#newton.damping=0.1
##Save temporary state in live memory. This state will be reloaded from the interface with the "reload" button.
O.saveTmp()
while (triax.strain[1]-e22Check) < 0.30: # stop condition: the simulation will stop at epsilon = 0.3
O.run(50); O.wait()
#from yade import plot
### a function saving variables
#def history():
# plot.addData(e11=triax.strain[0], e22=triax.strain[1], e33=triax.strain[2],
# ev=-triax.strain[0]-triax.strain[1]-triax.strain[2],
# s11=triax.stress(triax.wall_right_id)[0],
# s22=triax.stress(triax.wall_top_id)[1],
# s33=triax.stress(triax.wall_front_id)[2],
# p=(triax.stress(triax.wall_right_id)[0]+triax.stress(triax.wall_top_id)[1]+triax.stress(triax.wall_front_id)[2])/3000,
# q=(triax.stress(triax.wall_top_id)[1]-triax.stress(triax.wall_front_id)[2])/1000,
# i=O.iter)
#if 1:
# # include a periodic engine calling that function in the simulation loop
# O.engines=O.engines[0:5]+[PyRunner(iterPeriod=20,command='history()',label='recorder')]+O.engines[5:7]
# O.engines.insert(4,PyRunner(iterPeriod=20,command='history()',label='recorder'))
#else:
# # With the line above, we are recording some variables twice. We could in fact replace the previous
# # TriaxialRecorder
# # by our periodic engine. Uncomment the following line:
# O.engines[4]=PyRunner(iterPeriod=20,command='history()',label='recorder')
#O.run(100,True)
#### declare what is to plot. "None" is for separating y and y2 axis
##plot.plots={'i':('e11','e22','e33',None,'s11','s22','s33')}
#### the traditional triaxial curves would be more like this:
#plot.plots={'e22':('q')}
### display on the screen (doesn't work on VMware image it seems)
#plot.plot()
###### PLAY THE SIMULATION HERE WITH "PLAY" BUTTON OR WITH THE COMMAND O.run(N) #####
### In that case we can still save the data to a text file at the the end of the simulation, with:
#plot.saveDataTxt('results'+key)
###or even generate a script for gnuplot. Open another terminal and type "gnuplot plotScriptKEY.gnuplot:
#plot.saveGnuplot('plotScript'+key)
Comments