How to simulate the cyclic loading during the biaxial test?

Asked by Xifan Li

I took the triaxial compression code (3d) and modified it to end up with the biaxial compression simulation (2d), but now I want to go a step further and get cyclic loading while doing biaxial compression (which means to allow the sigmaIsoCompaction and sigmaLateralConfinement are not constantly).

Here is the code (The code works fine and completes the biaxial compression test, but it doesn't load the loop, so I'd like to know what the problem is.):

from yade import pack

sp=pack.SpherePack()
## corners of the initial packing
mn,mx=Vector3(0,0,0),Vector3(10,10,.1)

## box between mn and mx, avg radius ± ½(20%), 2k spheres
sp.makeCloud(minCorner=mn,maxCorner=mx,rRelFuzz=0,num=2000)

## create material #0, which will be used as default
O.materials.append(FrictMat(young=15e6,poisson=.4,frictionAngle=radians(30),density=2600,label='spheres'))
O.materials.append(FrictMat(young=15e6,poisson=.4,frictionAngle=0,density=0,label='frictionless'))

## copy spheres from the packing into the scene
## use default material, don't care about that for now
O.bodies.append([sphere(center,rad,material='spheres') for center,rad in sp])
## create walls around the packing
walls=aabbWalls(thickness=1e-10,material='frictionless')
wallIds=O.bodies.append(walls)

triax=TriaxialCompressionEngine(
 wall_bottom_id=wallIds[2],
 wall_top_id=wallIds[3],
 wall_left_id=wallIds[0],
 wall_right_id=wallIds[1],
 wall_back_id=wallIds[4],
 wall_front_id=wallIds[5],
 internalCompaction=True,
 ## define the rest of triax params here
 ## see in pkg/dem/PreProcessor/TriaxialTest.cpp:524 etc
 ## which are assigned in the c++ preprocessor actually
 sigmaIsoCompaction=-5e4,
 sigmaLateralConfinement=-5e4,
 max_vel=10,
 strainRate=0.01,
 label="triax"
)

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=100,timestepSafetyCoefficient=0.8),
 triax,
 TriaxialStateRecorder(iterPeriod=100, file='Stresses(d.id).txt'),
 NewtonIntegrator(damping=.4),
 PyRunner(command='checkUnbalanced()',realPeriod=1,label='checker'),
]

O.dt=.5*PWaveTimeStep()

def checkUnbalanced():

 if O.iter < 5000:
  return

 if unbalancedForce() > .1:
  return
 checker.command ='unload'

def unload():

 if triax.stress(2)[1] > 6e4:
  sigmaIsoCompaction /= 2
  sigmaLateralConfinement /= 2
  checker.command = 'load'

def load():

 if triax.stress(2)[1] < 3e4:
  sigmaIsoCompaction *= 2
  sigmaLateralConfinement *= 2

from yade import plot

O.engines=O.engines[0:5]+[PyRunner(iterPeriod=20,command='history()',label='recorder')]+O.engines[5:7]
def history():
 plot.addData(e11=triax.strain[0],
         e22=-triax.strain[1],
  s11=-triax.stress(0)[0],
  s22=-triax.stress(2)[1],

  i=O.iter)

plot.plots={'e11': ('s11',),'e22': ('s22',)}

O.saveTmp()
plot.plot()

#########################
Many thanks for your help.

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
Xifan Li
Solved:
Last query:
Last reply:
Revision history for this message
Xifan Li (shelvan) said :
#1

Perhaps I have not been particularly clear and I will now add some information about the problems I have encountered.

Method 1: I am trying to run my model in such a way that the moving wall can be paused after the stress on one of the axes(x or y) has reached a certain value when the confining pressure is applied, at which point the stress will definitely change as the model is paused, and the stopped wall can be restarted when this stress value changes to another specific value.

Method 2: In order to achieve the cyclic loading I need, I wonder if it is possible to change (swap) the axes of applied stress and applied strain during the run of this model (when state 3 STATE_TRIAX_LOADING in TriaxialCompressionEngine is reached), for example changing the axis of applied stress to the axis of applied strain and the axis of applied strain to the axis of applied stress. Is the method achievable?

Revision history for this message
Jérôme Duriez (jduriez) said :
#2

Hi,

Generally speaking, it is adviced at [*] to use TriaxialStressController instead of TriaxialCompressionEngine. Regarding your above "Method 2" question, yes you can update

triax.stressMask

during a simulation to swap axes of applied stress and applied strain (rate)

[*] https://yade-dem.org/doc/yade.wrapper.html#yade.wrapper.TriaxialCompressionEngine

Revision history for this message
Xifan Li (shelvan) said :
#3

Thank you Jérôme, I have changed the engine I use from TriaxialCompressionEngine to TriaxialStressController,

My code is below.

This code can run normally, but it still cannot make the cyclic loading realizable.

[1] So I would like to know how to change the parameters in the TriaxialStressController engine while the simulation is running? (Like change the triax.goal1 and tiax.goal2 and the stressMask?

###############

from yade import pack
# The following 5 lines will be used later for batch execution
nRead=readParamsFromTable(
 num_spheres=1000,# number of spheres
 compFricDegree = 30, # contact friction during the confining phase
 key='_triax_base_', # put you simulation's name here
 unknownOk=True
)
from yade.params import table

num_spheres=table.num_spheres# number of spheres
key=table.key
targetPorosity = 0.43 #the porosity we want for the packing
compFricDegree = table.compFricDegree # initial contact friction during the confining phase (will be decreased during the REFD compaction process)
finalFricDegree = 30 # contact friction during the deviatoric loading
rate=-0.02 # loading rate (strain rate)
damp=0.2 # damping coefficient
stabilityThreshold=0.01 # we test unbalancedForce against this value in different loops (see below)
young=5e6 # contact stiffness
mn,mx=Vector3(0,0,0),Vector3(10,10,.1) # corners of the initial packing

## create materials for spheres and plates
O.materials.append(FrictMat(young=young,poisson=0.5,frictionAngle=radians(compFricDegree),density=2600,label='spheres'))
O.materials.append(FrictMat(young=young,poisson=0.5,frictionAngle=0,density=0,label='walls'))

## create walls around the packing
walls=aabbWalls([mn,mx],thickness=0,material='walls')
wallIds=O.bodies.append(walls)

## use a SpherePack object to generate a random loose particles packing
sp=pack.SpherePack()

sp.makeCloud(minCorner=mn,maxCorner=mx,rRelFuzz=0,num=2000)
sp.toSimulation(material='spheres')

triax=TriaxialStressController(

 maxMultiplier=1.+2e4/young, # spheres growing factor (fast growth)
 finalMaxMultiplier=1.+2e3/young, # spheres growing factor (slow growth)
 thickness = 0,

 internalCompaction=False,

 stressMask = 1,
        goal1=-2e5,
 goal2=rate,

 )

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=100,timestepSafetyCoefficient=0.8),

 triax,

 TriaxialStateRecorder(iterPeriod=100, file='WallStresses.txt'),
 NewtonIntegrator(damping=damp),
 PyRunner(command='triaxload()',iterPeriod=1, label='triaxload'),

 #PyRunner(command='triaxload()',realPeriod=2, label='triaxload')
]

triax.stressMask = 1
triax.goal1=-2e5
triax.goal2=rate

def triaxload():
        O.triax.goal1=-3e5
 if abs(O.triax.stress(triax.wall_top_id)[1])> 150000:
  O.triax.stressMask = 1
  O.triax.goal1=-3e5
  O.triax.goal2=rate
  triaxload.command=('triaxunload')

def triaxunload():
 if abs(triax.stress(triax.wall_top_id)[1])< 5e4:
  triax.stressMask = 1
  triax.goal1=-1e5
  triax.goal2=rate

from yade import plot

O.engines=O.engines[0:5]+[PyRunner(iterPeriod=20,command='history()',label='recorder')]+O.engines[5:7]
def history():
 plot.addData(e11=-triax.strain[0],
         e22=-triax.strain[1],
  s11=-triax.stress(triax.wall_right_id)[0],
  s22=-triax.stress(triax.wall_top_id)[1],

  i=O.iter)

plot.plots={'e11': ('s11',),'e22': ('s22',)}

O.saveTmp()
plot.plot()

Revision history for this message
Jérôme Duriez (jduriez) said :
#4

Please do not repeat yourself in two different questions (here and https://answers.launchpad.net/yade/+question/700980)

Revision history for this message
Xifan Li (shelvan) said :
#5

https://answers.launchpad.net/yade/+question/701030

I just solved this problem. Thank you all guys.

Revision history for this message
Winters (winters1q) said :
#6

The dilatancy characteristics of sand at liquefaction state is investigated using a method proposed to quantify dilatancy during undrained cyclic loading in discrete-element numerical tests.

https://www.mysainsburys.net/