首页/文章/ 详情

【PFC6.0】随机多边形区域划分及颗粒填充

2年前浏览4765

0 引言

    在做岩石的时候,粗糙一点就认为岩石是一个均匀的整体,对整体参数进行标定,达到一个单元层次的宏观特性对应。精细点做的话就需要考虑矿物,这样我们会认为矿物内部是一个均匀的整体,这样的话就需要对岩石内部的区域进行划分,规定每种矿物成分的区域,然后用颗粒进行填充模拟。

    本文主要目的是将区域进行随机多边形划分,并且往其中填充颗粒。使用到的技术主要是rblock中的merge命令。

1 区域划分

    我们主要使用rblock的建模特性作为过渡,得到随机的多边形区域。



















model new

model domain extent -10 10geometry set "box"geometry generate box -5 5

def par    origin_rad_min=0.2    origin_rad_max=origin_rad_min*1.5    scale=3    block_radius_max=origin_rad_max*scale    block_radius_min=origin_rad_min*scaleend@parrblock construct from-geometry "box"  minimum-edge  @origin_rad_min ...        maximum-edge @origin_rad_max group "origin" slot "1"


    第一步是利用rblock construct命令可以对区域进行三角划分,如果可以直接对区域进行多边形划分肯定是更好的。但就我目前对rblock的理解来说,还做不到这种程度,目前只能做到对区域进行三角划分,这里可以指定三角形的边长范围。

    我们生成了一堆三角形的rblock,如下图:

image.png


    第二步就是用所得到的三角形进行随机的合并,这里我们用的是长方形区域进行合并。
























































def inbox(pos,pointer)    groupName=rblock.group(pointer)    if groupName#"1=origin" then        inbox=false        exit    endif    vl=vector(x_pos_random-sousuo_rad_x,y_pos_random-sousuo_rad_y)    vh=vector(x_pos_random sousuo_rad_x,y_pos_random sousuo_rad_y)    rbpos=rblock.pos(pointer)    if comp.x(rbpos)>comp.x(vl) & comp.x(rbpos)<comp.x(vh) &comp.y(rbpos)>comp.y(vl) & comp.y(rbpos)<comp.y(vh) then                inbox=true        exit    endif    inbox=falseend
def conbine_rblock    stop_flag=true    name_count=1    loop while stop_flag        x_pos_random=math.random.uniform*10-5        y_pos_random=math.random.uniform*10-5        sousuo_rad_x=math.random.uniform*(block_radius_max-block_radius_min) block_radius_min        sousuo_rad_y=math.random.uniform*(block_radius_max-block_radius_min) block_radius_min        ishaveRb=false        loop foreach rb rblock.list            vl=vector(x_pos_random-sousuo_rad_x,y_pos_random-sousuo_rad_y)            vh=vector(x_pos_random sousuo_rad_x,y_pos_random sousuo_rad_y)            if inbox(vl,rb) then                ishaveRb=true                exit loop            endif        endloop        group_name=string.build("zu_%1",name_count)        name_count =1        if ishaveRb=true then                    command                                rblock merge group "new" slot "1" group @group_name slot "10"  ...                        range fish @inbox                model clean            endcommand        endif        orgin_count=0        loop foreach rb rblock.groupmap("origin",1)            orgin_count =1        endloop        if orgin_count==0 then            stop_flag=false        endif    endloopend@conbine_rblock



    我们每次随机获得一个长宽的长方形,将长方形中的“origin”组的rblock合并成一个新的rblock。

    这里有个逻辑需要注意是,merge的概念不一定需要rblock紧贴在一起,就算rblock分开一段距离,他们之间的范围也会合并到新的rblock中,所以合并得到的rblock实际上是有重叠的。

    我们看一下新的rblock。


image.png



    可以发现的是,大部分的rblock都被合并了,但是有少部分rblock是被“剩余合并”的,所谓“剩余合并”的概念就是某个rblock或者某几个会被单独剩余下来,最终形成一个rblock,而这个rblock是不满足长宽要求的。

    所以我们还需要进行第三步,也就是把这些小的rblock合并到它周围的大rblock中。













































def findMinRb    VLimit=origin_rad_min*origin_rad_min*10    loop foreach rb rblock.groupmap("new",1)        if rblock.vol(rb)<VLimit*4 then            rblock.group(rb,1)="minRB"        endif    endloopend@findMinRb

def findNearestRb(pos)    minPos=1e100    minId=0    loop foreach rbfind rblock.groupmap("new",1)        vecLenghth=rblock.pos(rbfind)-pos        if math.mag(vecLenghth)<minPos then            minPos=math.mag(vecLenghth)            minId=rblock.id(rbfind)        endif    endloop    findNearestRb=minIdend

def solveMinRb        loop foreach rb  rblock.groupmap("minRB",1)        rbNearest=rblock.find(findNearestRb(rblock.pos(rb)))        rblock.group(rb,20)="dai"        rblock.group(rbNearest,20)="dai"        group_name=string.build("zu_%1",name_count)        name_count =1        command             rblock merge group "new" slot "1" group @group_name ...                slot "10" range group "20=dai"        endcommand        loop foreach rbdai rblock.groupmap("dai",20)            rblock.group(rbdai,20)="none"        endloop    endloopend@solveMinRb


    通过以上的命令,我们可以找到小的颗粒,当然我们也可以调整“小的颗粒”的范围,从而调整模型中区域的精细度。

    运行完的效果如图:

image.png


这个就是我们区域的范围。


2 颗粒填充


    由于没有指定随机数,导致本文出现的图和我既有算例的分布有区别,这里给出我算完的一个sav。如下图:


image.png


    可以看到区域大小基本一致,只是形状不同,这里也体现随机性的概念。

image.png

image.png

  颗粒填充前我们需要把rblock的边界都导出为geometry,方便后面根据区域进行颗粒生成。


    可以看一下区域图:


image.png


    由于rblock有重叠,导致geometry也是有重叠的,所以颗粒的生成规则我们需要进行优化。

    首先定一个考虑区域重叠的规则。


    区域交集优先被id小的geometry使用。


    也就是说id为3区域需要减去其与id 1和id 2区域的交集,作为对应颗粒的生成范围。


    榆树我们可以得到某个区域的颗粒投放逻辑,如下:


image.png

image.png

 第二个逻辑是颗粒的平衡边界,每个区域的颗粒投放后都需要平衡,其边界应当考虑id小于当前geo id的区域,所以需要控制墙体的生成和删除。


image.png

image.png

image.png


  最后便是函数的调用,每次生成新的区域的时候,旧的区域颗粒需要进行固定。


效果如下:

image.png

每次投放都保存了save文件,可以进行查看。

网格处理科普岩土结构基础PFC
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2022-09-09
最近编辑:2年前
lobby
硕士 |擅长颗粒流PFC
获赞 880粉丝 4982文章 83课程 22
点赞
收藏
未登录
3条评论
小瓶子
签名征集中
12月前
为啥7.0这套会跑不起来,也没有语法上的差别
回复
ghfgb
签名征集中
1年前
不同矿物之间的接触怎么设置
回复
工地狗
签名征集中
2年前
第二段代码的错误有点多啊,大佬
回复 3条回复
课程
培训
服务
行家
VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈