粒子与网格归属问题
-
@fubianhanshu 嗯,最慢的就是先来个遍历网格,然后每个网格里面遍历粒子 这个循环套起来就很大了
-
把粒子按x坐标排序,i是序号,形成xorder(i,1)存x坐标,xorder(i,2)存粒子编号; 同理,把粒子按y、z坐标排序,形成yorder(i,1..2),zorder(i,1..2) 计算网格顶点的xmin,xmax,ymin,ymax,zmin,zmax loop:循环网格{ 找到xmin,xmax在xorder(i,1)中的位置 同理,处理ymin,ymax,zmin,zmax new 一个数组 possible(i) loop: 处理上面缩小的范围{ 把以上范围内的粒子编号xorder(i,2),yorder(i,2), zorder(i,2)插入排 序到possible(i) } loop: 确定真正在网格中的粒子{ possible(i)中有连续三个相同编号,判断是否真的在网格内, 如果真在,就存起来 } }
至于每个网格里的粒子编号怎么存,搞一个数组叫data(i)一个接一个地存上面伪代码得到的编号,另一个数组叫position(j)存单元j在data(i)中的起始位置
不知道问题理解对不对,抛个砖试试看 -
另外,假如你的问题只是邻域搜索的话,即
知道一个粒子编号,想求它所在的网格的其他粒子的编号,
那么还可以用最小堆实现。PS:最小堆是一个自动按照从小到大排列的数组。(可以在每个时间步开始的时候排序)
我们建立这样一个数组:
这个数组的下标为粒子编号,而存储的值是网格编号。这个数组总是按照网格编号进行排序。
(我们称之为数组a吧。网格编号记作CID,粒子编号记作PID)由于这个数组是从小到大排序好的,所以它应该大概是这样的
24 35 2 31 42 57
0 0 0 1 1 1
上面的代表粒子编号即下标,下面的是网格编号即值。
总之粒子编号是乱的但网格编号是排好的假如我知道某个粒子的编号是31,那么直接通过索引粒子编号就知道它在1号网格,即
a[31]=1
那么搜索所在网格的其他粒子的时候呢,只需要同时向前和向后搜索就行了。直到搜索得到的
网格编号和当前粒子的网格编号不等为止,即CID!=1即可。这就避免了搜索所有的粒子。
-
我现在用的最笨的方法弄得:
- 网格遍历
- 粒子遍历
- 如果粒子恰好在网格内,就把label存储在当前网格的DynamicList
forAll(U_, cell) { DynamicList<label> pL(0); scalar pN = 0; forAllConstIter(typename MomentumCloud<CloudType>, *this, iter) { const parcelType& p = iter(); if (p.cell() == cell) { pN += 1; pL.append(p.origId()); } } if (pN != 0) { Info<< "Cell[" << cell << "] has " << pN << " particles, " << "particle label is " << pL << nl; } }
输出结果还可以:
Cell[2295] has 2 particles, particle label is 2(20 21) Cell[2297] has 2 particles, particle label is 2(4 7) Cell[2298] has 1 particles, particle label is 1(3) Cell[2340] has 3 particles, particle label is 3(17 18 19) Cell[2341] has 5 particles, particle label is 5(11 13 14 15 16) Cell[2342] has 4 particles, particle label is 4(5 6 8 9) Cell[2343] has 1 particles, particle label is 1(1) Cell[2386] has 1 particles, particle label is 1(12) Cell[2387] has 1 particles, particle label is 1(10) Cell[2388] has 2 particles, particle label is 2(0 2)
但是这里面遍历网格+遍历粒子。肯定是要慢。