【PFC6.0】隨機多邊形區域劃分及顆粒填充

 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,如下圖:

【PFC6.0】隨機多邊形區域劃分及顆粒填充的圖1


    第二步就是用所得到的三角形進行隨機的合并,這里我們用的是長方形區域進行合并。


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。


【PFC6.0】隨機多邊形區域劃分及顆粒填充的圖2



    可以發現的是,大部分的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


    通過以上的命令,我們可以找到小的顆粒,當然我們也可以調整“小的顆粒”的范圍,從而調整模型中區域的精細度。

    運行完的效果如圖:

【PFC6.0】隨機多邊形區域劃分及顆粒填充的圖3


這個就是我們區域的范圍。


2 顆粒填充


    由于沒有指定隨機數,導致本文出現的圖和我既有算例的分布有區別,這里給出我算完的一個sav。如下圖:


【PFC6.0】隨機多邊形區域劃分及顆粒填充的圖4


    可以看到區域大小基本一致,只是形狀不同,這里也體現隨機性的概念。



model restore "rblock_slip"rblock export to-geometry "allgeo" cmat default type ball-facet model linear method deform emod 100e6 kratio 1.5 property fric 0.5cmat default type ball-ball model linear method deform emod 100e6 kratio 1.5  property fric 0.5def GetGeo    geoname_count=1    loop foreach rb rblock.list        groupName=string.build("geo_%1",geoname_count)        idRblock=rblock.id(rb)        command            rblock export to-geometry @groupName range id @idRblock        endcommand        geoname_count+=1    endloopend@GetGeorblock delete


    顆粒填充前我們需要把rblock的邊界都導出為geometry,方便后面根據區域進行顆粒生成。


    可以看一下區域圖:


【PFC6.0】隨機多邊形區域劃分及顆粒填充的圖5


    由于rblock有重疊,導致geometry也是有重疊的,所以顆粒的生成規則我們需要進行優化。

    首先定一個考慮區域重疊的規則。


    區域交集優先被id小的geometry使用。


    也就是說id為3區域需要減去其與id 1和id 2區域的交集,作為對應顆粒的生成范圍。


    榆樹我們可以得到某個區域的顆粒投放邏輯,如下:

def ballDeleteGeo(geo_count_single)    if geo_count_single=1 then        exit    endif    thisGroup=string.build("geo_%1",geo_count_single)    loop n(1,geo_count_single-1)         groupName=string.build("geo_%1",n)        command            ball delete range geometry-space @groupName count 1 group @thisGroup        endcommand    endloopenddef GenerateBallIn(geo_count_single)    groupName=string.build("geo_%1",geo_count_single)    command        ball distribute porosity 0.1 radius 0.03 0.06 group @groupName range geometry-space @groupName count 1         ball attribute density 2.7e3 damp 0.3    endcommand    ballDeleteGeo(geo_count_single)end


    第二個邏輯是顆粒的平衡邊界,每個區域的顆粒投放后都需要平衡,其邊界應當考慮id小于當前geo id的區域,所以需要控制墻體的生成和刪除。


wall import  from-geometry "box" id 100 def genWalls(geo_count_single)    loop n(1,geo_count_single)         groupName=string.build("geo_%1",n)        command            wall import  from-geometry @groupName id [n+10000]         endcommand    endloopenddef deleWalls(geo_count_single)    loop n(1,geo_count_single)        command            wall delete walls range id [n+10000]         endcommand    endloopend


def genAllBall    loop gen_cur(1,geoname_count-1)                genWalls(gen_cur)        command                       model calm            ball fix velocity spin                   endcommand        GenerateBallIn(gen_cur)        groupName=string.build("geo_%1",gen_cur)        command                       model cycle 2000 calm 20            ball delete range geometry-space @groupName count 1 not group @groupName        endcommand        ballDeleteGeo(gen_cur)        command             model solve ratio-average 1e-5 or cycles 10000            model save @groupName        endcommand        deleWalls(gen_cur)    endloopend@genAllBallball free velocity spinmodel cycle 1model solvemodel save "sample"


    最后便是函數的調用,每次生成新的區域的時候,舊的區域顆粒需要進行固定。


效果如下:


【PFC6.0】隨機多邊形區域劃分及顆粒填充的圖6


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


    本算例所有代碼都已公開在上方,同學們可以自行組裝。若組裝有困難,可以轉發朋友圈集齊50贊,可以獲得本案例的文件。













登錄后免費查看全文
立即登錄
App下載
技術鄰APP
工程師必備
  • 項目客服
  • 培訓客服
  • 平臺客服

TOP

2
8