Sono un ricercatore di scienze planetarie e un progetto a cui sto lavorando sono le simulazioni N- body degli anelli di Saturno. L'obiettivo di questo studio particolare è quello di osservare come le particelle si aggregano insieme sotto la loro stessa gravità e misurare la massa aggregata dei grumi rispetto alla velocità media di tutte le particelle nella cellula. Stiamo cercando di capire se questo può spiegare alcune osservazioni fatte dall'astronave Cassini durante il solstizio d'estate di Saturno, quando furono viste grandi strutture che proiettavano ombre sugli anelli quasi spigolosi. Di seguito è riportato uno screenshot di come appare un determinato timestep. (Ogni particella ha un diametro di 2 m e la cella di simulazione stessa ha un diametro di circa 700 m.)
Il codice che sto usando sputa già la velocità media ad ogni intervallo di tempo. Quello che devo fare è capire un modo per determinare la massa di particelle nei grumi e NON le particelle vaganti tra di loro. Conosco la posizione, la massa, la dimensione di ogni particella, ecc., Ma non so facilmente che, diciamo, le particelle 30.000-40.000 insieme a 102.000-105.000 costituiscono un filone che per l'occhio umano è ovvio.
Quindi, l'algoritmo che devo scrivere dovrebbe essere un codice con il minor numero possibile di parametri immessi dall'utente (per replicabilità e obiettività) che attraverserebbe tutte le posizioni delle particelle, capire quali particelle appartengono ai grumi e quindi calcolare il massa. Sarebbe bello se potesse farlo per "ogni" gruppo / filo al contrario di tutto ciò che si trova sopra la cella, ma non penso di averne effettivamente bisogno per separarli.
L'unica cosa a cui stavo pensando era fare una sorta di calcolo della distanza N 2 in cui avrei calcolato la distanza tra ogni particella e se, diciamo, le 100 particelle più vicine fossero entro una certa distanza, allora quella particella sarebbe considerata parte di un grappolo. Ma questo sembra piuttosto sciatto e speravo che voi CS e programmatori potreste conoscere una soluzione più elegante?
Modificato con la mia soluzione: quello che ho fatto è stato quello di adottare una sorta di approccio più vicino / cluster e fare prima l'implementazione di N 2 quick-n-dirty . Quindi, prendi ogni particella, calcola la distanza da tutte le altre particelle e la soglia per in un cluster o no era se ci fossero N particelle entro la distanza d (due parametri che devono essere impostati a priori , sfortunatamente, ma come è stato detto da alcuni risposte / commenti, non avevo intenzione di cavarmela senza averne qualcuno).
L'ho quindi accelerato non ordinando le distanze ma semplicemente facendo una ricerca nell'ordine N e incrementando un contatore per le particelle all'interno di d , e questo ha velocizzato le cose di un fattore 6. Poi ho aggiunto uno "stupido albero del programmatore" (perché lo so quasi nulla sui codici degli alberi). Divido la cella simulazione in un determinato numero di griglie (migliori risultati quando dimensione della griglia ≈7 d ) se le linee principali della griglia su con la cella, di una griglia è bilanciata da metà in x ed y , e le altre due sono compensati da 1/4 in ± x e ± y . Il codice quindi divide le particelle nelle griglie, quindi ogni particella N deve solo calcolare le distanze rispetto alle altre particelle in quella cella.
Teoricamente, se questo fosse un vero albero, dovrei ottenere l'ordine N * log ( N ) invece delle N 2 velocità. Sono arrivato a metà strada tra i due, dove per un sottoinsieme di 50.000 particelle ho ottenuto un aumento di velocità di 17x, e per una cella di 150.000 particelle, ho ottenuto un aumento di 38x di velocità. 12 secondi per il primo, 53 secondi per il secondo, 460 secondi per una cella da 500.000 particelle. Queste sono velocità comparabili a quanto tempo impiega il codice per eseguire il timestep di simulazione 1 in avanti, quindi è ragionevole a questo punto. Oh - ed è completamente thread, quindi ci vorranno tutti i processori che posso lanciarci.