Я - исследователь планетных наук, и один проект, над которым я работаю, это N- тело симуляции колец Сатурна. Цель данного конкретного исследования - наблюдать, как частицы слипаются друг с другом под действием собственной гравитации, и измерять совокупную массу сгустков в зависимости от средней скорости всех частиц в клетке. Мы пытаемся выяснить, может ли это объяснить некоторые наблюдения, сделанные космическим кораблем Кассини во время летнего солнцестояния Сатурна, когда были замечены крупные сооружения, отбрасывающие тени на кольца почти с ребра. Ниже приведен скриншот того, как выглядит любой данный временной шаг. (Каждая частица имеет диаметр 2 м, а сама ячейка моделирования имеет ширину около 700 м.)
Код, который я использую, уже выдает среднюю скорость на каждом шаге. Что мне нужно сделать, так это найти способ определить массу частиц в сгустках, а НЕ рассеянные частицы между ними. Я знаю положение каждой частицы, массу, размер и т. Д., Но я не могу легко понять, что, скажем, частицы 30 000-40 000 вместе со 102 000 105 000 составляют одну нить, которая для человеческого глаза очевидна.
Итак, алгоритм, который мне нужно написать, должен быть кодом с как можно меньшим количеством введенных пользователем параметров (для воспроизводимости и объективности), который будет проходить через все положения частиц, выяснять, какие частицы принадлежат сгусткам, а затем вычислять масса. Было бы замечательно, если бы он мог сделать это для «каждого» сгустка / нити, в отличие от всего, что происходит в камере, но я не думаю, что мне на самом деле нужно это для их разделения.
Единственное, о чем я думал, - это какое-то вычисление расстояния N 2, где я вычислял бы расстояние между каждой частицей, и если, скажем, ближайшие 100 частиц находились в пределах определенного расстояния, то эта частица считалась бы частью кластер. Но это кажется довольно неаккуратным, и я надеялся, что вы, ребята из CS и программисты, возможно, найдете более элегантное решение?
Отредактировано с помощью My Solution: я выбрал своего рода подход «ближайший сосед / кластер» и сначала выполнил реализацию N 2 «quick-n-dirty» . Итак, возьмите каждую частицу, вычислите расстояние до всех других частиц, и порог для в кластере или нет, был ли N частиц на расстоянии d (два параметра, которые, к сожалению, должны быть установлены априори , но, как говорили некоторые ответы / комментарии, я не собирался сойти с рук не имея некоторых из них).
Затем я ускорил его, не сортируя расстояния, а просто выполняя поиск N и увеличивая счетчик для частиц в пределах d , и это ускорилось в 6 раз. Затем я добавил «дерево тупого программиста» (потому что я знаю, почти ничего о кодах деревьев). Я делю ячейку моделирования на заданное количество сеток (наилучшие результаты, когда размер сетки ≈7 d ), где основная сетка совпадает с ячейкой, одна сетка смещена на половину по x и y , а две другие смещены на 1/4 дюйма ± х и ± у . Затем код делит частицы на сетки, тогда каждая частица N должна рассчитывать только расстояния до других частиц в этой ячейке.
Теоретически, если бы это было реальное дерево, я должен получить порядок N * log ( N ), а не N 2 скоростей. Я оказался где-то посередине, где для подмножества из 50 000 частиц я увеличил скорость в 17 раз, а для ячейки из 150 000 я получил скорость в 38 раз. 12 секунд для первого, 53 секунды для второго, 460 секунд для ячейки с 500 000 частиц. Эти скорости сопоставимы с тем, сколько времени занимает код, чтобы запустить симуляцию на 1 шаг вперед, так что это разумно на данный момент. О - и это полностью потоковое, так что потребуется столько процессоров, сколько я могу на него бросить.