Ich bin ein planetarwissenschaftlicher Forscher und ein Projekt, an dem ich arbeite, sind N- Körpersimulationen von Saturnringen. Das Ziel dieser speziellen Studie ist es, zu beobachten, wie Partikel unter ihrer eigenen Schwerkraft zusammenklumpen und die Gesamtmasse der Klumpen gegen die mittlere Geschwindigkeit aller Partikel in der Zelle zu messen. Wir versuchen herauszufinden, ob dies einige Beobachtungen der Cassini- Raumsonde während der Sommersonnenwende im Saturn erklären kann, als große Strukturen Schatten auf die fast kantigen Ringe werfen sahen. Unten sehen Sie einen Screenshot, wie ein bestimmter Zeitschritt aussieht. (Jedes Teilchen hat einen Durchmesser von 2 m und die Simulationszelle selbst hat einen Durchmesser von etwa 700 m.)
Der Code, den ich verwende, gibt die mittlere Geschwindigkeit bereits bei jedem Zeitschritt aus. Was ich tun muss, ist, einen Weg zu finden, um die Masse der Partikel in den Klumpen und NICHT die Streupartikel zwischen ihnen zu bestimmen. Ich kenne die Position, Masse, Größe usw. jedes Partikels, aber ich weiß nicht so leicht, dass beispielsweise die Partikel 30.000 bis 40.000 zusammen mit 102.000 bis 105.000 einen Strang bilden, der für das menschliche Auge offensichtlich ist.
Der Algorithmus, den ich schreiben muss, muss also ein Code mit möglichst wenigen vom Benutzer eingegebenen Parametern sein (aus Gründen der Reproduzierbarkeit und Objektivität), der alle Partikelpositionen durchläuft, herausfindet, welche Partikel zu Klumpen gehören, und dann berechnet Masse. Es wäre großartig, wenn es dies für "jeden" Klumpen / Strang tun könnte, im Gegensatz zu allem über der Zelle, aber ich glaube nicht, dass ich es wirklich brauche, um sie zu trennen.
Das einzige, woran ich dachte, war eine Art N 2 -Distanzberechnung, bei der ich die Entfernung zwischen jedem Partikel berechnet habe und wenn sich die nächsten 100 Partikel beispielsweise innerhalb einer bestimmten Entfernung befinden, wird dieses Partikel als Teil von a betrachtet Cluster. Aber das scheint ziemlich schlampig zu sein und ich hatte gehofft, dass Sie CS-Leute und Programmierer eine elegantere Lösung finden könnten?
Herausgegeben mit Meiner Lösung: Was ich tat , war eine Art Nearest-Neighbor / Cluster - Ansatzes zu nehmen und tun , um die Quick-n-dirty N 2 Implementierung zuerst. Nehmen Sie also jedes Partikel, berechnen Sie den Abstand zu allen anderen Partikeln, und der Schwellenwert für in einem Cluster war, ob sich N Partikel innerhalb des Abstands d befanden (zwei Parameter, die leider a priori festgelegt werden müssen, aber wie von einigen gesagt wurde) Antworten / Kommentare, ich würde nicht durchkommen, wenn ich einige davon nicht hätte).
Ich habe es dann beschleunigt, indem ich nicht die Entfernungen sortiert habe, sondern einfach eine Suche in der Reihenfolge N durchgeführt und einen Zähler für die Partikel innerhalb von d inkrementiert habe . Dann habe ich einen "dummen Programmiererbaum" hinzugefügt (weil ich weiß so gut wie nichts über Baumcodes). Ich teile die Simulationszelle in eine festgelegte Anzahl von Gittern auf (beste Ergebnisse bei einer Gittergröße von ≈7 d ), wobei das Hauptgitter mit der Zelle ausgerichtet ist und ein Gitter in x und y um die Hälfte und die beiden anderen um die Hälfte versetzt sind 1/4 in ± x und ± y . Der Code teilt dann die Partikel in die Gitter auf, wobei für jedes Partikel N nur die Abstände zu den anderen Partikeln in dieser Zelle berechnet werden müssen.
Wenn dies ein echter Baum wäre, müsste ich theoretisch N * log ( N ) anstelle von N 2 Geschwindigkeiten bestellen . Ich bin irgendwo dazwischen gekommen, wo ich für eine Teilmenge mit 50.000 Partikeln eine 17-fache Geschwindigkeitssteigerung und für eine Zelle mit 150.000 Partikeln eine 38-fache Geschwindigkeitssteigerung erzielt habe. 12 Sekunden für die erste, 53 Sekunden für die zweite, 460 Sekunden für eine 500.000-Teilchen-Zelle. Dies ist eine vergleichbare Geschwindigkeit wie die Zeit, die der Code benötigt, um den Zeitschritt der Simulation 1 vorwärts auszuführen. Das ist an dieser Stelle also angemessen. Oh - und es ist voll verlegt, so dass es so viele Prozessoren braucht, wie ich darauf werfen kann.