New question #706821 on Yade:
https://answers.launchpad.net/yade/+question/706821

Hi! I want to model the particle breakage of clumps during the one-dimensional 
compression in a cylindrical boundary. My steps are as followed:
Step 1:  I  import 800 GTS files into Yade and generated one-on-one 800 clumps. 
That is to say that each GTS corresponds to a unique clump. 
Step 2:  I create a cylindrical boundary to cover those clumps and provide two 
plates (bottom one fixed, top one applied with force). Note that the force 
applied on the top plate is a multi-load, which varies with the strain of the 
sample.
Step 3:  I assign JCFpm material for each clump and material of steel for the 
boundary and plates.
Step 4:  record what we want to know and implement simulation.

Here, my questions are as follows:
1) Is my whole procedure appropriate to simulate the one-dimensional 
compression while considering particle breakage?
2) For Step 2, I would like to know how to assign multi-loads is correct. It 
seems currently the top plate is not quasi-static during loading. Do I need to 
clear the speed for every number of calculation steps?
3) For the whole simulation, how do we know how many clumps are broken and can 
we record the isolated clumps at the final? 

The MWM is presented below (I don't know how to provide the gts files without 
an external link, so maybe randomly generating some clumps can replace them.):

from __future__ import print_function
from yade import pack, ymport
import gts, os.path, locale, plot, random
import numpy as np

locale.setlocale(
        locale.LC_ALL, 'en_US.UTF-8'
)  #gts is locale-dependend.  If, for example, german locale is used, 
gts.read()-function does not import floats normally

############################################
###   DEFINING VARIABLES AND MATERIALS   ###
############################################

# The following lines are used parameter definitions
readParamsFromTable(
        # directory     
        dir_gts = '/home/kyle/Yade/install/bin/gts', # directory of storing gts 
files
        dir_vtk = '/home/kyle/Yade/install/bin/vtk', # directory of storing vtk 
files
        dir_txt = '/home/kyle/Yade/install/bin/txt', # directory of storing txt 
files
        fileType = '.gts', # type of file 

        # type of generating spheres ['hexa','dense']
        genType = 'hexa',
        
        # material parameters
        young_w = 210e9, # Young's modulus of plates and walls
        young_g = 180e6, # Young's modulus of grains [1]
        den_w = 7874, # density of plates and walls
        den_g = 1162, # density of grains
        poi_w = 0.3, # possion's ratio of plates and walls
        poi_g = 0.25, # possion's ratio of grains
        friAngle_w = 15, # friction angle of plates and walls 
        friAngle_g = 19, # friction angle of grains

        # Parameters of cylindrical walls
        x_cyl = 0.0106, # x-coordinate of center of cylindrical walls
        y_cyl = 0.01005, # y-coordinate of center of cylindrical walls
        z_cyl = 0, # z-coordinate of center of cylindrical walls
        r_cyl = 0.0097, # radius of the cylinder
        h_cyl = 0.04151, # height of the cylinder
        n_cyl = 100, # number of boxes forming cylinder
        t_cyl = 0.0001, # thickness of the boxes
        
        #Parameters of lower and upper plates (square box)
        w_plate = 0.015, # width of plates
        t_plate = 0.0001, # thickness of plates

        # applied stress
        stress = [12500, 25000, 50000, 100000, 200000, 300000, 400000, 800000, 
1600000, 3200000], # target applied stress
        
        # target displacement 
        displacement = [3.6e-5, 6.8e-5, 0.00014, 0.00028, 0.00047, 0.000642, 
0.000796, 0.001342, 0.002441, 0.003989] # target displacement
        
)
from yade.params.table import *

# create materials for spheres and walls
wallMat = O.materials.append(FrictMat(young = young_w, poisson = poi_w, 
frictionAngle = friAngle_w, density = den_w, label = 'walls'))
#sphereMat = O.materials.append(FrictMat(young = young_g, poisson = poi_g, 
frictionAngle = friAngle_g, density = den_g, label = 'spheres'))

def sphereMat():
        return JCFpmMat(
                type=1,
                young = young_g,
                frictionAngle = radians(friAngle_g),
                density = den_g,
                poisson = poi_g,
                tensileStrength = 1e6,
                cohesion=1e6,
                jointNormalStiffness=1e7,
                jointShearStiffness=1e7,
                jointCohesion=1e6,
                jointFrictionAngle=radians(20),
                jointDilationAngle=radians(0)
        )  ## Rq: density needs to be adapted as porosity of real rock is 
different to granular assembly due to difference in porosity 
(utils.sumForces(baseBodies,(0,1,0))/(Z*X) should be equal to Gamma*g*h with 
h=Y, g=9.82 and Gamma=2700 kg/m3

###############################################
###   IMPORTING GRAINS AND CREATING CLUMPS  ###
###############################################

##### a function that searching all .gts files
def SearchFiles(directory, ftype):
        fileList = []
        for root, subDirs, files in os.walk(directory):
                for fileName in files:
                        if fileName.endswith(ftype):
                                fileList.append(os.path.join(root, fileName))
        return fileList
##### 

# import gts and obatin file list
fileList = SearchFiles(dir_gts,fileType)

##### a function that determining the radius of spheres
def createSphere(pred, ndivmin, spacing, genType):
        #dim = pred.dim()
        #minDim = min(dim[0], dim[1], dim[2])
        aabb = pred.aabb()
        dim0 = aabb[1][0] - aabb[0][0]
        bodyList = []
        ndiv = ndivmin
        if genType == 'hexa':
                while len(bodyList)==0:
                        radius = dim0 / ndiv # get some characteristic 
dimension, use it for radius
                        bodyList = O.bodies.append(pack.regularHexa(pred, 
radius = radius, gap = -radius/4, color = 
[random.random(),random.random(),random.random()], material = sphereMat))
                        ndiv = ndiv + spacing
        else:
                while len(bodyList)==0:
                        radius = dim0 / ndiv # get some characteristic 
dimension, use it for radius
                        sp = 
pack.randomDensePack(pred,radius=radius,returnSpherePack=True, color = 
[random.random(),random.random(),random.random()], material = sphereMat)
                        bodyList = sp.toSimulation()
                        ndiv = ndiv + spacing
        return bodyList
#####

# import gts and create clump for each .gts file
sphereList = []
for gtsName in fileList:
        surf = gts.read(open(gtsName))
        if surf.is_closed():
                print(gtsName)
                pred = pack.inGtsSurface(surf)
                bodyList = createSphere(pred, 20, 2, genType)
                idClump = O.bodies.clump(bodyList)
        del surf
        del pred
        del bodyList
O.bodies.updateClumpProperties() 
print('Number of bodies:', len(O.bodies))

###################################################################
###   CREATING CYLINDRICAL WALLS, BOTTOM PLATE, AND TOP PLATE   ###
###################################################################

##### a function that creating cylindrical walls
def cylSurf(center,radius,height,nSegments=12,thick=0,**kw):
   """creates cylinder made of boxes. Axis is parallel with z+
   center ... center of bottom disc
   radius ... radius of cylinder
   height ... height of cylinder
   nSegments ... number of boxes forming cylinder
   thick ... thickness of the boxes
   **kw ... keywords passed to box function (e.g. material, color ...)
   """
   # just converts (a,b,c) to Vector3(a,b,c) to enable "center + ..."
   center = Vector3(center)
   # nSegments angles to define individual boxes, from 0 to 2*pi
   angles = [i*2*pi/nSegments for i in range(nSegments)]
   # centers of boxes. Vector 3(radius,0,0) rotated by angle 'a'
   # z coordinate is .5*height
   # center + shift = center of corresponding box
   pts = [center + Vector3(radius*cos(a),radius*sin(a),.5*height) for a in 
angles] # centers of plates
   ret = []
   for i,pt in enumerate(pts): # for each box center create corresponding box
      # "length" of the box along circumference, cylinder circumference / 
nSegments
      l = pi*radius/nSegments
      # extents, half dimensions along x,y,z axis
      es = (.5*thick,l,.5*height)
      # by default box is axis-aligned, we need to rotate it along z axis 
(0,0,1) by angle i*2*pi/nSegments
      ori = Quaternion((0,0,1),i*2*pi/nSegments)
      # have a look at utils.box documentation. pt=center of box, es=extents 
(half dimension), ori=orientation
      ret.append(box(pt,es,ori,**kw))
   return ret
#####

# create cylindrical walls and fix them
surf = cylSurf([x_cyl, y_cyl, z_cyl], r_cyl, h_cyl, nSegments = n_cyl, thick = 
t_cyl, material = wallMat, wire=True)
O.bodies.append(surf)
for b in surf: b.state.blockedDOFs = 'xyzXYZ'
for b in surf: b.state.vel = (0, 0, 0)

# create the bottom plate and fix it
bottom_plate = O.bodies.append(box([x_cyl, y_cyl, z_cyl], (w_plate, w_plate, 
t_plate), material = wallMat))
O.bodies[bottom_plate].state.vel = (0, 0, 0)
O.bodies[bottom_plate].state.blockedDOFs = 'xyzXYZ'

# create the top plate 
top_plate=O.bodies.append(box([x_cyl, y_cyl, h_cyl], (w_plate, w_plate, 
t_plate), material = wallMat))

# apply initial force
force = np.dot(stress, w_plate * w_plate) # corresponding applied force
global deltaF
deltaF = force[0]
O.forces.setPermF(top_plate,(0, 0, -deltaF))

# target displacement
global numIter
numIter = 0
global maxIter
maxIter = 9
global dispT
dispT = displacement[numIter]
global disp
disp = 0
global dispE
dispE = displacement[-1]

# calculate initial void ratio
vol0 = h_cyl * pi * r_cyl * r_cyl
volG0 = sum([b.state.mass for b in O.bodies if b.isClump])/den_g
volV0 = vol0 - volG0
e0 = volV0/volG0
print(volG0, e0)
print('numIter', 'dispT', 'disp', 'disp/dispT', 'velTopPlate')

############################
###   DEFINING ENGINES   ###
############################

O.engines = [
        ForceResetter(),
        InsertionSortCollider([Bo1_Sphere_Aabb(aabbEnlargeFactor=1), 
                                Bo1_Box_Aabb()]),
        InteractionLoop(
                [Ig2_Sphere_Sphere_ScGeom(interactionDetectionFactor=1), 
                 Ig2_Box_Sphere_ScGeom()],
                [Ip2_FrictMat_FrictMat_FrictPhys(), 
                 Ip2_JCFpmMat_JCFpmMat_JCFpmPhys(cohesiveTresholdIteration=1)],
                [Law2_ScGeom_FrictPhys_CundallStrack(), 
                 
Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM(smoothJoint=True)]),
                GlobalStiffnessTimeStepper(timestepSafetyCoefficient=0.8),
        PyRunner(iterPeriod = 10,command = "checkDisplacement(displacement, 
force, h_cyl)"),
        VTKRecorder(iterPeriod = 500, recorders = ['jcfpm', 'cracks', 
'spheres', 'boxes', 'stress', 'id', 'clumpId', 'coordNumber', 'colors'], 
fileName = dir_vtk + '/'),
        NewtonIntegrator(gravity = [0, 0, -9.81], damping = 0.4)
]
O.dt= 0.1 * PWaveTimeStep()
                
# check whether the target displacement has already met. if so, update applied 
stress
def checkDisplacement(displacement, force, h_cyl):
        global numIter
        global maxIter
        global disp
        global dispT
        global dispE
        global deltaF
        # at the very start, applied stress is the first of value of array 
'stress'
        t = O.time
        H = O.bodies[top_plate].state.pos[2]
        disp = h_cyl - H
        velTopPlate = O.bodies[top_plate].state.vel[2]
        if disp > dispT:
                if numIter < maxIter:
                        numIter = numIter + 1
                        dispT = displacement[numIter]
                        #deltaF = force[numIter] - force[numIter - 1]
                        O.forces.setPermF(top_plate,(0, 0, -force[numIter]))    
                else:
                        print(numIter, dispT, disp, disp/dispT, velTopPlate, 
O.forces.permF(top_plate)[2], O.forces.f(top_plate)[2])
                        f = open(dir_txt + '/data.txt', 'a')
                        f.write('{} {} {} {} {} {} {}\n'.format(O.iter, 
numIter, dispT, disp, velTopPlate, O.forces.permF(top_plate)[2], H))
                        f.close()
                        plot.saveDataTxt(O.tags['d.id'] + '.txt')
                        O.pause()
        print(numIter, dispT, disp, disp/dispT, velTopPlate, 
O.forces.permF(top_plate)[2], O.forces.f(top_plate)[2])
        plot.addData(t=t,disp=disp)
        f = open(dir_txt + '/data.txt', 'a')
        f.write('{} {} {} {} {} {} {}\n'.format(O.iter, numIter, dispT, disp, 
velTopPlate, O.forces.permF(top_plate)[2], H))
        f.close()

##########################
###   RUN SIMULATION   ###
##########################
plot.plots = {'t':('disp')}
plot.plot()     
O.run()


-- 
You received this question notification because your team yade-users is
an answer contact for Yade.

_______________________________________________
Mailing list: https://launchpad.net/~yade-users
Post to     : yade-users@lists.launchpad.net
Unsubscribe : https://launchpad.net/~yade-users
More help   : https://help.launchpad.net/ListHelp

Reply via email to