我是行星科学研究员,我正在研究的一个项目是土星环的N体模拟。这项特定研究的目的是观察粒子在其自身重力作用下会聚在一起,并测量其总质量与细胞中所有粒子的平均速度之间的关系。我们试图找出这是否可以解释卡西尼号航天器在土星夏至期间所做的一些观察,当时观察到大型结构在接近边缘的环上投下了阴影。以下是任何给定时间步长的屏幕截图。(每个粒子的直径为2 m,模拟单元本身的宽度约为700 m。)
我正在使用的代码已经在每个时间步上吐出了平均速度。我需要做的是找出一种方法来确定团块中的粒子质量,而不是它们之间的杂散粒子。我知道每个粒子的位置,质量,大小等,但是我不容易知道,例如,粒子30,000-40,000与102,000-105,000构成了一条对人眼来说很明显的链。
因此,我需要编写的算法必须是具有尽可能少的用户输入参数(用于可复制性和客观性)的代码,该参数将遍历所有粒子的位置,找出哪些粒子属于团块,然后计算质量 如果它可以针对“每个”丛集/链条(而不是单元格中的所有内容)做到这一点,那将是很好的,但是我认为我实际上并不需要将它们分开。
我唯一想到的是进行某种N 2距离计算,在该计算中,我将计算每个粒子之间的距离,例如,如果最接近的100个粒子在一定距离内,则该粒子将被视为粒子的一部分。簇。但这似乎很草率,我希望您的CS人员和程序员可能知道更优雅的解决方案?
使用“我的解决方案”进行编辑: 我要做的是采取一种最邻近/集群方法,并首先执行quick-n-dirty N 2实现。因此,取每个粒子,计算到所有其他粒子的距离,是否在一个簇中的阈值是在d距离内是否有N个粒子(不幸的是,必须先验设置两个参数,但是正如某些人所说的那样)回应/评论,我不会因为没有其中一些而逃脱。
然后,我通过不对距离进行排序而加快了速度,仅执行了N次搜索,并为d中的粒子增加了一个计数器,然后加快了6倍的速度。然后添加了“愚蠢的程序员树”(因为我知道几乎与树代码无关)。我瓜分模拟细胞成网格的一组数(最好的结果,当网格大小≈7 d)其中,主栅线与该单元格,一个网格由一半在偏移X和ÿ,和另外两个是通过胶版1/4 in± x和± y。然后,代码将粒子划分为网格,然后每个粒子N只需要计算到该单元格中其他粒子的距离即可。
从理论上讲,如果这是一棵真正的树,我应该得到N * log(N)的阶数,而不是N 2的速度。我介于两者之间,对于50,000粒子的子集,速度提高了17倍;对于150,000粒子的单元,速度提高了38倍。第一次12秒钟,第二次53秒钟,500,000个粒子的电池460秒钟。这些速度与代码向前运行1个模拟代码所花费的时间相当,因此在这一点上是合理的。哦,而且它是全线程的,因此它将占用尽可能多的处理器。