Я дослідник планетарних наук, і над одним проектом, над яким я працюю, є моделювання кілець Сатурна в N- тілах. Мета цього конкретного дослідження - спостерігати за тим, як частинки збиваються під власною самогравітацією і вимірюють сукупну масу скупчень проти середньої швидкості всіх частинок у клітині. Ми намагаємося розібратися, чи це може пояснити деякі спостереження, зроблені космічним кораблем Кассіні під час сатурнівського літнього сонцестояння, коли великі споруди бачили, як вони кидали тіні на майже крайні кільця. Нижче наведено скріншот того, як виглядає будь-який даний часовий крок. (Кожна частинка має діаметр 2 м, а сама симуляційна комірка становить близько 700 м.)
Код, який я використовую, вже виплюває середню швидкість на кожному кроці. Що мені потрібно зробити - це визначити спосіб визначення маси частинок в грудях, а НЕ збилися частинки між ними. Я знаю положення кожної частинки, масу, розмір тощо, але я не знаю легко, що, скажімо, частинки 30 000-40 000 разом із 102 000-105 000 складають одну ланцюжок, що для людського ока очевидно.
Отже, алгоритм, який мені потрібно написати, повинен бути кодом з якомога менше введених користувачем параметрів (для копіюваності та об'єктивності), який би пройшов усі позиції частинок, з'ясував, які частинки належать до скупчень, а потім обчислить маси. Було б чудово, якби це могло зробити це для "кожної" грудки / пасма на відміну від усього в клітині, але я не думаю, що мені насправді це потрібно, щоб розділити їх.
Єдине, про що я думав, - це зробити якийсь обчислення відстані N 2, де я обчислив би відстань між кожною частинкою, і якщо, скажімо, найближчі 100 частинок знаходилися на певній відстані, то ця частинка вважалася б частиною кластер. Але це здається досить неохайним, і я сподівався, що ви, люди та програмісти, можете знати більш елегантне рішення?
Відредаговано з моїм рішенням: Що я зробив, це скористатись підходом найближчого сусіда / кластера та спершу виконати швидку n-брудну реалізацію N 2 . Отже, візьміть кожну частинку, обчисліть відстань до всіх інших частинок, а поріг для кластера чи ні, чи було N частинок на відстані d відстані ( на жаль, два параметри, які потрібно встановити апріорі , але, як це сказали деякі відповіді / коментарі, я не збирався тікати, не маючи деяких із них).
Потім я проскочив це, не сортуючи відстані, а просто виконую замовлення на пошук N і збільшуючи лічильник частинок в межах d , а цей прискорював коефіцієнт на 6 разів. Потім я додав "дурне дерево програміста" (тому що я знаю майже нічого не стосується деревних кодів). Я поділяю комірку імітації на встановлену кількість сіток (найкращі результати, коли розмір сітки ≈7 д ), де основна сітка вирівнюється з коміркою, одна сітка зміщена вдвічі в x і y , а дві інші зміщені на 1/4 в ± х і ± у . Потім код ділить частинки на сітки, тоді кожна частинка N повинна мати лише відстані, обчислені до інших частинок цієї клітини.
Теоретично, якби це справжнє дерево, я повинен отримати порядок N * log ( N ) на відміну від швидкостей N 2 . Я потрапив десь між двома, де для підмножини на 50 000 частинок я отримав 17-кратне збільшення швидкості, а для клітини-частинки на 150 000 я отримав 38-кратну швидкість. 12 секунд для першої, 53 секунди для другої, 460 секунд для комірки з частинками 500 000 частин. Це порівнянна швидкість з тим, скільки часу потрібно коду, щоб запустити моделювання на 1 крок вперед, так що це розумно в даний момент. О, і це повністю потоком, тому знадобиться стільки процесорів, скільки я можу на нього кинути.