Jestem badaczem nauk planetarnych, a jednym z projektów, nad którymi pracuję, są symulacje N -pierścieni pierścieni Saturna. Celem tego konkretnego badania jest obserwacja, jak cząstki zbijają się pod własnym ciężarem własnym i mierzą łączną masę grudek w porównaniu ze średnią prędkością wszystkich cząstek w komórce. Próbujemy dowiedzieć się, czy to może wyjaśnić niektóre obserwacje dokonane przez sondę Cassini podczas letniego przesilenia Saturna, gdy zaobserwowano duże struktury rzucające cienie na niemal krawędziowe pierścienie. Poniżej znajduje się zrzut ekranu pokazujący jak wygląda dany czas. (Każda cząstka ma średnicę 2 m, a sama komórka symulacyjna ma około 700 m średnicy.)
The code I'm using already spits out the mean velocity at every timestep. What I need to do is figure out a way to determine the mass of particles in the clumps and NOT the stray particles between them. I know every particle's position, mass, size, etc., but I don't know easily that, say, particles 30,000-40,000 along with 102,000-105,000 make up one strand that to the human eye is obvious.
Tak więc algorytm, który muszę napisać, musiałby być kodem z jak najmniejszą liczbą parametrów wprowadzonych przez użytkownika (dla możliwości replikacji i obiektywności), który przechodziłby przez wszystkie pozycje cząstek, ustalał, które cząstki należą do skupisk, a następnie obliczał masa. Byłoby wspaniale, gdyby mógł to zrobić dla „każdego” kępu / nici w przeciwieństwie do wszystkiego w komórce, ale nie sądzę, że tak naprawdę potrzebuję tego, aby je rozdzielić.
Jedyne, o czym myślałem, to jakieś obliczenie odległości N 2, w którym obliczałbym odległość między każdą cząsteczką, a jeśli powiedzmy, że najbliższe 100 cząstek znajdowało się w pewnej odległości, wówczas cząstka ta byłaby uważana za część grupa. Ale to wydaje się dość niechlujne i miałem nadzieję, że ludzie CS i programiści mogą wiedzieć o bardziej eleganckim rozwiązaniu?
Edytowany ze moje rozwiązanie: Co zrobiłem było podjąć rodzaju najbliższego sąsiedztwa podejścia / klastra i zrobić szybki-n-brudne N 2 pierwsze wdrożenie. Więc weź każdą cząsteczkę, oblicz odległość do wszystkich innych cząstek, a próg dla gromady był, czy nie, czy w odległości d znajduje się N cząstek (dwa parametry, które niestety trzeba ustawić a priori , ale jak powiedzieli niektórzy odpowiedzi / komentarze, nie miałem zamiaru uciec od braku niektórych z nich).
Przyspieszyłem to, nie sortując odległości, ale po prostu wykonując rozkaz N wyszukiwania i zwiększając licznik cząstek w obrębie d , i to przyspieszyłem współczynnik sześciokrotnie. Potem dodałem „głupie drzewo programisty” (bo wiem prawie nic o kodach drzew). I dzieli się na komórki symulacji do zadanej liczby siatek (najlepsze wyniki, gdy rozmiar siatki ≈7 d ), w którym główne linie siatki w górę z komórką jedna kratka jest przesunięta o połowę w X i Y , a pozostałe dwa są przesunięte 1/4 w ± x i ± y . Kod dzieli następnie cząstki na siatki, a następnie każda cząstka N musi mieć tylko obliczone odległości od innych cząstek w tej komórce.
Teoretycznie, gdyby to było prawdziwe drzewo, powinienem uzyskać porządek N * log ( N ) w przeciwieństwie do prędkości N 2 . Dotarłem gdzieś między nimi, gdzie dla podzbioru 50 000 cząstek miałem 17-krotny wzrost prędkości, a dla komórki 150 000 cząstek, miałem 38-krotny wzrost prędkości. 12 sekund dla pierwszej, 53 sekundy dla drugiej, 460 sekund dla komórki 500 000 cząstek. Są to porównywalne prędkości do tego, ile czasu zajmuje wykonanie kodu w kroku 1 symulacji do przodu, więc w tym momencie jest to uzasadnione. Och - i jest w pełni wątkowy, więc zajmie tyle procesorów, ile tylko mogę.