PFC中基本单元有ball和clump,当然最新的有block。ball模拟圆形刚性颗粒,clump模拟不规则形状刚性颗粒。对于非刚性颗粒来说,柔性簇Cluster方法便可以比较好的去模拟了。但是目前来说cluster方法介绍的并不是很多,这节课主要针对于cluster的模拟框架进行介绍。
本文介绍的cluster框架有两个主要步骤:1、导出cluster中ball的位置信息;2、在双轴或者别的实验的框架中将ball颗粒换为cluster。
本文只介绍圆形柔性簇的方法,非圆形道理是一样的。
一、标定cluster单元的微观参数
首先在按形状生成墙,并且在形状内生成颗粒。这里注意形状中心放在原点,这样可以在预压的时候进行径向伺服。
newset random 10001def parlijing=0.1rdmax=0.009rdmin=0.006poro=0.08end@pardomain extent [-lijing*2] [lijing*2]wall generate circle position 0 0 radius [lijing*0.5]ball distribute radius @rdmin @rdmax porosity @poro ...range annulus center 0 0 radius 0 [lijing*0.5]ball attribute density 2.7e3 damp 0.7cmat default model linear method deform emod 1e8 kratio 1.5cycle 1000 calm 2cmat default model linear method deform emod 1e8 kratio 1.5 property fric 0.2cmat applysolvesave init_model

第二步是进行预压:
restore init_model[trr=-1e6][sevro_factor=0.2][timestep_now=global.step-1][gr_freq=100]def sevro_wallscomputer_stressif global.step>timestep_now thenget_gr(sevro_factor)timestep_now =gr_freqendifrVel=gr*(wrss-trr) ;wrss小于trr,rvel是正值,墙收缩,速度和方向矢量反向loop foreach vt wall.vertex.listvt_pos=wall.vertex.pos(vt)fangxiang_mag=math.sqrt(comp.x(vt_pos)^2 Comp.y(vt_pos)^2)fang_normal=vector(comp.x(vt_pos),comp.y(vt_pos))/fangxiang_magvel=rVel*fang_normal*(-1)wall.vertex.vel(vt) = velendloopend[wp=wall.find(1)][vt1=wall.vertex.find(1) ]def get_chicunpos=wall.vertex.pos(vt1)wlr=math.sqrt(comp.x(pos)^2 Comp.y(pos)^2)enddef computer_stressget_chicunwrss=0loop foreach ct wall.contactmap(wp)ct_force=contact.force.global(ct)force_mag=math.sqrt(comp.x(ct_force)^2 Comp.y(ct_force)^2)wrss =force_magendloopwrss=-wrss/(2*math.pi*wlr)enddef get_gr(fac)zonggangR=0loop foreach ct wall.contactmap(wp)zonggangR =contact.prop(ct,"kn")endloopgr=fac*2*math.pi*wlr/(zonggangR*global.timestep)end@get_gr(@sevro_factor)set fish callback -1.0 @sevro_wallshistory id 1 @wrsshistory id 2 @grcycle 1solve aratio 1e-5save yuya
这个概念和岩石差不多,调整到合适的赋存应力。

第三步是给参数了,这里的参数用的常用的煤岩的参数。这里注意不需要给胶结,我们需要的是加胶结前颗粒的位置,胶结可以在模拟cluster的时候加。这一步主要是对弹性参数进行调整。
restore yuya[pb_coh=10e6][ten_coh=2.7]cmat default type ball-facet model linear method deformability emod 10e8 kratio 1.5 property fric 0.2cmat default type ball-ball model linearpbond method deformability ...emod 12e8 kratio 1.5 pb_deformability emod 54e8 kratio 1.5 ...property pb_coh [pb_coh] pb_ten [pb_coh*ten_coh] pb_fa 50 fric 0cmat applycleancycle 1solvesave fucan

最后一步就是导出颗粒的位置了,这里使用table实现数据的传输,将颗粒的位置和半径存入table中。

这里注意一下颗粒的粒径,由于预压的时候圆形半径会发生改变,一开始是0.1m,后面的0.123才是cluster真实的粒径。这里需要注意一下。
同样的道理可以再生成一个粒径的cluster模板,目录下生成了四个table,这个是我们后面需要用到的。

二、进行cluster双轴
框架还是用我常用的双轴框架。这里注意粒径的选取取决于上一步做的cluster模板。我们这里只有两个粒径。
1、成样:
newset random 10001def parwidth=1.5lijing1=0.123lijing2=0.09443height=width*2.0poro=0.12end@pardomain extent [-width*5] [width*5]wall generate box [-width*0.5] [width*0.5] [-height*0.5] [height*0.5] expand 1.5ball distribute porosity @poro numbins 2 ...bin 1 radius [lijing1*0.5] v 0.5 group cluster_template_big ...bin 2 radius [lijing2*0.5] v 0.5 group cluster_template_small ...box [-width*0.5] [width*0.5] [-height*0.5] [height*0.5]ball attribute density 2.7e3 damp 0.7cmat default model linear method deformability emod 10e8 kratio 1.5cycle 2000 calm 5solvesave sample

2、预压:
restore sample[txx=-1e4][tyy=-1e4][sevro_factor=0.5][do_xSevro=true][do_ySevro=true][sevro_freq=100][timestepNow=global.step-1]def sevro_wallscompute_stressif timestepNow<global.step thenget_g(sevro_factor)timestepNow =sevro_freqendifif do_xSevro=true thenXvel=gx*(wxss-txx)wall.vel.x(wpRight)=-Xvelwall.vel.x(wpLeft)=Xvelendifif do_ySevro=true thenYvel=gy*(wyss-tyy)wall.vel.y(wpUp)=-Yvelwall.vel.y(wpDown)=Yvelendifenddef wp_iniwpDown=wall.find(1)wpRight=wall.find(2)wpUp=wall.find(3)wpLeft=wall.find(4)end@wp_inidef computer_chiCunwlx=wall.pos.x(wpRight)-wall.pos.x(wpLeft)wly=wall.pos.y(wpUp)-wall.pos.y(wpDown)enddef compute_stresscomputer_chiCunwxss=-(wall.force.contact.x(wpRight)-wall.force.contact.x(wpLeft))*0.5/wlywyss=-(wall.force.contact.y(wpUp)-wall.force.contact.y(wpDown))*0.5/wlxenddef get_g(fac)gx=0gy=0zongKNX=100e6*2*10zongKNY=100e6*2*10loop foreach ct wall.contactmap(wpLeft)zongKNX =contact.prop(ct,"kn")endlooploop foreach ct wall.contactmap(wpRight)zongKNX =contact.prop(ct,"kn")endlooploop foreach ct wall.contactmap(wpUp)zongKNY =contact.prop(ct,"kn")endlooploop foreach ct wall.contactmap(wpDown)zongKNY =contact.prop(ct,"kn")endloopgx=fac*wly/(zongKNX*global.timestep)gy=fac*wlx/(zongKNY*global.timestep)endset fish callback -1.0 @sevro_wallshistory id 1 @wxsshistory id 2 @wysshistory id 3 @gxhistory id 4 @gycycle 1solvesave yuya
3、将ball换为cluster
这里注意将第一步生成的table复制粘贴到这个模拟的目录下,导入后进行cluster的生成。这里面细节比较多,就不一一讲解了,读者可以自己理解一下。
restore yuyacmat default type ball-facet model linear method deformability emod 10e8 kratio 1.5[pb_coh=10e6][ten_coh=2.7]contact groupbehavior andcmat default type ball-ball model linearpbond method deformability ...emod 12e8 kratio 1.5 pb_deformability emod 54e8 kratio 1.5 ...property pb_coh [pb_coh] pb_ten [pb_coh*ten_coh] pb_fa 50 fric 0.5table cluster_template_pos_big read cluster_template_pos_bigtable cluster_template_rad_big read cluster_template_rad_bigtable cluster_template_pos_small read cluster_template_pos_smalltable cluster_template_rad_small read cluster_template_rad_small[tb_pos_big=table.find("cluster_template_pos_big")][tb_rad_big=table.find("cluster_template_rad_big")][tb_pos_small=table.find("cluster_template_pos_small")][tb_rad_small=table.find("cluster_template_rad_small")][tb_size_big=table.size(tb_pos_big)][tb_size_small=table.size(tb_pos_small)]def genghuan_clustercount_cluster=0loop foreach bp ball.groupmap("cluster_template_big")x_pos=ball.pos.x(bp)y_pos=ball.pos.y(bp)ball.delete(bp)jiaodu=math.random.uniform*math.pi*2sin_jiaodu=math.sin(jiaodu)cos_jiaodu=math.cos(jiaodu)loop n(1,tb_size_big)ct_posX=table.x(tb_pos_big,n)ct_posY=table.y(tb_pos_big,n)ct_rad=table.y(tb_rad_big,n)cluster_pos_x=x_pos (-1)*sin_jiaodu*ct_posX cos_jiaodu*ct_posYcluster_pos_y=y_pos cos_jiaodu*ct_posX sin_jiaodu*ct_posYpos_vec=vector(cluster_pos_x,cluster_pos_y)bp_temp=ball.create(ct_rad,pos_vec)ball.group(bp_temp)="big_cluster"geoup_2_name=string.build("cluter_num_%1",count_cluster)ball.group(bp_temp,2)=geoup_2_nameendloopcommandcleancontact method bond gap [lijing1*0.08*0.2] range group @geoup_2_name slot 2endcommandcount_cluster =1endlooploop foreach bp ball.groupmap("cluster_template_small")x_pos=ball.pos.x(bp)y_pos=ball.pos.y(bp)ball.delete(bp)jiaodu=math.random.uniform*math.pi*2sin_jiaodu=math.sin(jiaodu)cos_jiaodu=math.cos(jiaodu)loop n(1,tb_size_small)ct_posX=table.x(tb_pos_small,n)ct_posY=table.y(tb_pos_small,n)ct_rad=table.y(tb_rad_small,n)cluster_pos_x=x_pos (-1)*sin_jiaodu*ct_posX cos_jiaodu*ct_posYcluster_pos_y=y_pos cos_jiaodu*ct_posX sin_jiaodu*ct_posYpos_vec=vector(cluster_pos_x,cluster_pos_y)bp_temp=ball.create(ct_rad,pos_vec)ball.group(bp_temp)="small_cluster"geoup_2_name=string.build("cluter_num_%1",count_cluster)ball.group(bp_temp,2)=geoup_2_nameendloopcommandcleancontact method bond gap [lijing1*0.08*0.2] range group @geoup_2_name slot 2endcommandcount_cluster =1endloopend@genghuan_clusterball attribute density 2.7e3 damp 0.7cycle 1solvesave cluster_sample

可以看一下pb_state观察一下这其中的效果。可以看到不同cluster之间是没有胶结的。

4、加围压
后面就跟双轴一样了,只是第三步不一样。
restore cluster_sample[txx=-300e3][tyy=-300e3]cycle 1solvesave weiya
5、加载:
restore weiyaset mech age 0ball attribute displacement multiply 0[streainRatio=1e-2][do_xSevro=true][do_ySevro=false]wall attribute yvelocity [wly*streainRatio*0.5] range id 1wall attribute yvelocity [-wly*streainRatio*0.5] range id 3[Ix0=wlx][Iy0=wly]def computer_strainwexx=(wlx-Ix0)/Ix0weyy=(wly-Iy0)/Iy0weVol=wexx weyypianyingli=(wyss-wxss)endset fish callback -1.1 @computer_strainhistory deletehistory id 1 @wysshistory id 2 @weyyhistory id 3 @wxsshistory id 4 @wexxhistory id 5 @weVolhistory id 6 @pianyingli[stop_me=0]def stop_meif weyy<-20e-2 thenstop_me=1endifend[baocunpinlv=-1e-2][time_record=weyy 1][count=0]def savefileif weyy-time_record <= baocunpinlv thenfilename=string.build("jieguo_%1",count)commandsave @filenameendcommandtime_record=weyycount =1endifendset fish callback -1.0 @savefilesolve fishhalt @stop_mesave result
看一下应力应变,由于颗粒不多,波动还是比较大的。

位移图和刚性颗粒差不多。

我们看一下细观:

对于低围压来说,基本上都不会坏,这里的特性可能和刚性差不多。
这里尝试一下1mpa的围压:
应力应变:

细观:
可以看到很多颗粒被压坏了。

放大点看看:

本文只给出模拟框架,分析方面不多,读者可以根据自己需求加入一些后处理。