首页/文章/ 详情

基于PFC3D与Flac3D耦合的SHPB压杆模拟

1年前浏览4702

0 引言

       最近在熟悉PFC6.0的内容,对于6.0来说,其最大的突破就是实现了软件内与FLAC3D的耦合。这其实解决了PFC很大的一个问题,就是颗粒数太多时计算力的限制,我们可以用网格单元作为边界来弱化边界效应,当然也可以和本文一样,使用网格单元模拟金属等连续性材料。

        本文试着去模拟一个结构方向同学经常遇到的一个工况,霍普金森压杆(SHPB)实验,对于测量混凝土材料在高应变率下的力学特性有很大的参考价值。因为我这里也没有看过这方面的实验,仅从有限的资料大概理解其边界设置,利用有限差分和离散元耦合来实现SHPB压杆模拟,希望能给各位有一定的参考价值。


1 成样、预压、加胶结


     首先是我们的离散元部分,这里进行常规的方式来生成一个圆柱形式样。这里不再赘述了。


    成样代码:


    model new

    fish define Par    sample_width=0.05      radmin=0.8e-3    radmax=radmin*1.8    poro=0.28    sample_rad=sample_width*0.5      poleLength=sample_width*40end@Parmodel domain extent [-sample_width]  [sample_width]

    wall generate cylinder base [-sample_width*0.5*1.4] 0 0 axis 1 0 0  ...                    height [sample_width*1.4] radius [sample_rad] resolution 0.3 cap false false

    wall generate plane position [sample_width*0.5] 0 0  dip 90 dip-dir 90wall generate plane position [-sample_width*0.5] 0 0  dip 90 dip-dir 90

    ball distribute group "shiyang" radius [radmin] [radmax] porosity @poro ...    range cylinder end-1 [sample_width*0.5-radmax] 0 0  ...    end-2 [-sample_width*0.5 radmax] 0 0  radius [sample_rad-radmax]

    cmat default type ball-facet model linear method deform emod 100e6 kratio 1.5 cmat default type ball-ball model linear method deform emod 100e6 kratio 1.5  ball attribute density 2.7e3 damp 0.2model cycle 2000 calm 50

    model solve

    model save "sample"


    预压代码:


      model restore "sample"

      ball property "fric" 0.5

      fish def wp_wall    wp_up=wall.find(2)    wp_down=wall.find(3)    wp_rr=wall.find(1)        loop foreach vt wall.vertexlist(wp_rr)        vert_in_ce=vt            endloopend@wp_wall

      [txx=-1e6][trr=-1e6][sevro_fac=0.5]

      [do_xservo=true][do_rservo=true]



      [sevro_freq=100][timestepNow=global.step-1]fish def servo_walls    computer_wallStress    if timestepNow<global.step then        get_gain(sevro_fac)        timestepNow =sevro_freq    endif    if do_xservo=true then        x_vel=gx*(wsxx-txx)        wall.vel.x(wp_up)=-x_vel        wall.vel.x(wp_down)=x_vel    endif    if do_rservo=true then        r_vel_mag=(-1)*gr*(wsrr-trr)        loop foreach vt wall.vertexlist(wp_rr)            mag=math.sqrt(wall.vertex.pos.y(vt)^2 wall.vertex.pos.z(vt)^2)            fang_normal_y=wall.vertex.pos.y(vt)/mag            fang_normal_z=wall.vertex.pos.z(vt)/mag                        r_vel=vector(0,fang_normal_y,fang_normal_z)*r_vel_mag                        wall.vertex.vel(vt)=r_vel        endloop    endif     end



      fish def computer_chicun    y_pos=wall.vertex.pos.y(vert_in_ce)    z_pos=wall.vertex.pos.z(vert_in_ce)    wlr=math.sqrt(y_pos^2 z_pos^2)    wlx=wall.pos.x(wp_up)-wall.pos.x(wp_down)end

      fish def computer_wallStress    computer_chicun    ding_yuanmianji=math.pi*wlr^2    wsxx=(wall.force.contact.x(wp_down)-wall.force.contact.x(wp_up))*0.5/ding_yuanmianji    ce_mianji=2*math.pi*wlr*wlx    wsrr=0    loop foreach ft wall.facetlist(wp_rr)        ft_fangxiang=wall.facet.normal(ft)        loop foreach ct wall.facet.contactmap(ft)            force_in_facet=contact.force.global(ct)            wsrr =(math.dot(force_in_facet,ft_fangxiang))/ce_mianji              endloop    endloop end

      def get_gain(fac)    gx=0    gr=0    zonggangX=1e7    zonggangR=1e7    loop foreach ct wall.contactmap(wp_up)        zonggangX =contact.prop(ct,"kn")    endloop    loop foreach ct wall.contactmap(wp_down)        zonggangX =contact.prop(ct,"kn")    endloop    loop foreach ct wall.contactmap(wp_rr)        zonggangR =contact.prop(ct,"kn")    endloop    gX=fac*ding_yuanmianji/(zonggangX*global.timestep)    gr=fac*ce_mianji/(zonggangR*global.timestep)    end





      fish callback add  @servo_walls -1.0

      history id 1 @wsXXhistory id 2 @wsrr

      model cycle 1model solvemodel save "yuya"



      加胶结代码


        model restore "yuya"

        [pb_coh=100e6][ten_coh=2.7]contact cmat default type ball-facet model linear method deformability emod 10e8 kratio 1.5



        contact cmat 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" 0contact cmat apply



        model cycle 1model solve

        contact method bond gap [radmin*0.5]

        model cycle 1 model solve

        model save "jiajiaojie"



        生成的式样如图


        image.png


        2、卸载


            这里模拟混凝土从模具中取出,或者岩石从地下取出的过程,所以预压的值是有讲究的。



          model restore "jiajiaojie"

          [txx=-1e3][trr=-1e3]

          model cycle 1 model solve

          model save "xiezai"



          3、生成压杆


              这部分需要生产入射杆和透射杆的单元,目前我知道的方式是通过四个1/4的cylinder拼起来,不知道会不会有更便捷的方法,可以后台交流。

              之后就是耦合部分的定义,PFC和FLAC提供了两种耦合方式,wall-zone耦合与ball-zone耦合,就使用来看,本文应当用wall-zone耦合来实现zone与ball之间的力学联系。


              需要注意的一点是,由于我们的杆件是拼起来的,所以zone生成wall时,会出现重复点的情况,这里可以直接指定skip-errors跳过即可。


            model restore "xiezai"

            model domain extent [-poleLength*1.5] [poleLength*1.5] ...                    [-sample_width]  [sample_width] wall delete fish callback remove  @servo_walls -1.0[materialMod=200e9]

            model largestrain on

            [bullet_Length=sample_width*8][midu=5]

            zone create cylinder point 0 ([-poleLength-wlx*0.5],0,0) ...                    point 1 ([-poleLength-wlx*0.5],[-sample_rad],0) ...                    point 2 ([-wlx*0.5],0,0) ...                    point 3 ([-poleLength-wlx*0.5],0,[sample_rad]) ...                    size   @midu [math.floor(midu*poleLength/sample_rad)]  @midu group "ImportPole"zone create cylinder point 0 ([-poleLength-wlx*0.5],0,0) ...                    point 1 ([-poleLength-wlx*0.5],0,[-sample_rad]) ...                    point 2 ([-wlx*0.5],0,0) ...                    point 3 ([-poleLength-wlx*0.5],[-sample_rad],0) ...                    size    @midu [math.floor(midu*poleLength/sample_rad)]  @midu group "ImportPole"zone create cylinder point 0 ([-poleLength-wlx*0.5],0,0) ...                    point 1 ([-poleLength-wlx*0.5],[sample_rad],0) ...                    point 2 ([-wlx*0.5],0,0) ...                    point 3 ([-poleLength-wlx*0.5],0,[-sample_rad]) ...                    size   @midu [math.floor(midu*poleLength/sample_rad)]  @midu group "ImportPole"zone create cylinder point 0 ([-poleLength-wlx*0.5],0,0) ...                    point 1 ([-poleLength-wlx*0.5],0,[sample_rad]) ...                    point 2 ([-wlx*0.5],0,0) ...                    point 3 ([-poleLength-wlx*0.5],[sample_rad],0) ...                    size   @midu [math.floor(midu*poleLength/sample_rad)]  @midu group "ImportPole"





            ; toushezone create cylinder point 0 ([wlx*0.5],0,0)   ...                    point 1 ([wlx*0.5],[-sample_rad],0) ...                    point 2 ([poleLength wlx*0.5],0,0) ...                    point 3 ([wlx*0.5],0,[sample_rad]) ...                    size   @midu [math.floor(midu*poleLength/sample_rad)]  @midu group "ExportPole"zone create cylinder point 0 ([wlx*0.5],0,0) ...                    point 1 ([wlx*0.5],0,[-sample_rad]) ...                    point 2 ([poleLength wlx*0.5],0,0) ...                    point 3 ([wlx*0.5],[-sample_rad],0) ...                    size   @midu [math.floor(midu*poleLength/sample_rad)]  @midu group "ExportPole"zone create cylinder point 0 ([wlx*0.5],0,0) ...                    point 1 ([wlx*0.5],[sample_rad],0) ...                    point 2 ([poleLength wlx*0.5],0,0) ...                    point 3 ([wlx*0.5],0,[-sample_rad]) ...                    size   @midu [math.floor(midu*poleLength/sample_rad)]  @midu group "ExportPole"zone create cylinder point 0 ([wlx*0.5],0,0) ...                    point 1 ([wlx*0.5],0,[sample_rad]) ...                    point 2 ([poleLength wlx*0.5],0,0) ...                    point 3 ([wlx*0.5],[sample_rad],0) ...                    size   @midu [math.floor(midu*poleLength/sample_rad)]  @midu group "ExportPole"

            zone cmodel assign elasticzone property young [materialMod] poisson 0.25



            wall-zone create skip-errors range position-x [-wlx*0.5-0.001] [-wlx*0.5 0.001]wall-zone create skip-errors range position-x [wlx*0.5-0.001] [wlx*0.5 0.001]



            model save "pole"


            生产的压杆如图:

            image.png


            细节放大:



            可以发现此时颗粒是有一定速度的,但是由于我们研究的是高应变率所以这里可以不用管。


            image.png

            4、加载


                这里直接施加一个冲击荷载,在入射杆的端部指定一个200MPa的应力,持续200us。之后接触边界条件,运算1500us。


              model restore "pole"

              model mechanical time-total 0model configure dynamic



              ball attribute displacement multiply 0

              zone face  group "rushe" range position-x [-poleLength-wlx*0.5-0.001] ...    [-poleLength-wlx*0.5 0.001]

              zone face apply stress-xx [(-1)*(200e6)] range group "rushe"



              zone initialize density 7.8e3model cycle 1

              measure create position 0 0 0 radius [wlr*0.5]def cedian    zoneImportPole=zone.near(vector(-wlx*0.5-poleLength*0.5,[-wlr],0))    zoneExportPole=zone.near(vector(wlx*0.5 poleLength*0.5,[-wlr],0))    mp1=measure.find(1)      zone.group(zoneImportPole,"cedianGroup")="cedian"    zone.group(zoneExportPole,"cedianGroup")="cedian"    stressShiyang0=measure.stress.xx(mp1)end@cedian

              def jiance    time=mech.time.total    stressImport=zone.stress.xx(zoneImportPole)    stressExport=zone.stress.xx(zoneExportPole)    stressShiyang=measure.stress.xx(mp1)-stressShiyang0endfish callback add  @jiance -1.0history deletehistory id 1 @stressImporthistory id 2 @stressExporthistory id 3 @stressShiyang

              history id 4 @time[baocunpinlv=500e-6][time_record=-10][count=0]def savefile        if time-time_record >= baocunpinlv then        filename=string.build("jieguo%1",count)        command            model save @filename        endcommand        time_record=time        count =1    endif    end                        fish callback add @savefile -1.0 program call "fracture.p3fis"@track_initmodel solve time 200e-6zone face apply-remove stress-xx range group "rushe"model solve time 1500e-6model save "jieguo"



              5、结果分析


                  首先本文选用的微观参数强度比较大,不会发生破坏,这也是为了和有限元的一些结果做对比。


                  先看一下应力波形图


              这里给出参考曲线:


              image.png

              本文的模拟结果为:

              image.png

                  可以看出无论是波形还是数值,都是在一个比较正常的范围内的。所以也是论证了我们程序的正确性。


              压杆上的应力传递到式样时候的图片:


              image.png

              力链图:


              微信截图_20220719171955.png



              后续各位可以根据自己的实际材料结果进行更多的研究。



              网格处理结构基础离散元代码&命令科普PFC
              著作权归作者所有,欢迎分享,未经许可,不得转载
              首次发布时间:2022-07-19
              最近编辑:1年前
              lobby
              硕士 |擅长颗粒流PFC
              获赞 834粉丝 4491文章 84课程 21
              点赞
              收藏
              作者推荐
              未登录
              3条评论
              Eagle
              签名征集中
              11天前
              为什么第一个代码会报错
              回复
              LTT
              签名征集中
              1年前
              杆可以先生成1/4圆柱,然后用zone reflect生成镜像,生成两次就可以有一个完整圆柱
              回复
              仿真秀0108100412
              签名征集中
              1年前
              请问lobby 大佬,wall-zone和ball-zone有什么区别呢
              回复
              课程
              培训
              服务
              行家
              VIP会员 学习 福利任务 兑换礼品
              下载APP
              联系我们
              帮助与反馈