Je suis un chercheur en sciences planétaires et un projet sur lequel je travaille est la simulation à N corps des anneaux de Saturne. Le but de cette étude particulière est de regarder les particules s'agglutiner sous leur propre gravité et de mesurer la masse agrégée des mottes en fonction de la vitesse moyenne de toutes les particules de la cellule. Nous essayons de savoir si cela peut expliquer certaines observations faites par le vaisseau spatial Cassini pendant le solstice d'été saturnien lorsque de grandes structures ont été vues projetant des ombres sur les anneaux presque bordés. Voici une capture d'écran de ce à quoi ressemble un pas de temps donné. (Chaque particule a un diamètre de 2 m et la cellule de simulation elle-même mesure environ 700 m de diamètre.)
Le code que j'utilise déjà crache la vitesse moyenne à chaque pas de temps. Ce que je dois faire, c'est trouver un moyen de déterminer la masse de particules dans les mottes et NON les particules parasites entre elles. Je connais la position, la masse, la taille, etc. de chaque particule, mais je ne sais pas facilement que, disons, les particules 30 000-40 000 ainsi que 102 000-105 000 constituent un brin qui, à l'œil humain, est évident.
Ainsi, l'algorithme que je dois écrire devrait être un code avec aussi peu de paramètres saisis par l'utilisateur que possible (pour la réplicabilité et l'objectivité) qui passerait par toutes les positions des particules, déterminer quelles particules appartiennent aux amas, puis calculer la Masse. Ce serait formidable s'il pouvait le faire pour "chaque" touffe / brin par opposition à tout sur la cellule, mais je ne pense pas en avoir vraiment besoin pour les séparer.
La seule chose à laquelle je pensais était de faire une sorte de calcul de la distance N 2 où je calculerais la distance entre chaque particule et si, disons, les 100 particules les plus proches se trouvaient dans une certaine distance, alors cette particule serait considérée comme faisant partie d'un grappe. Mais cela semble assez bâclé et j'espérais que vous, les gens et les programmeurs CS, connaissiez une solution plus élégante?
Modifié avec ma solution: ce que j'ai fait, c'est d'adopter une sorte d'approche de voisin / cluster le plus proche et de commencer par l'implémentation de N 2 rapide et sale . Donc, prenez chaque particule, calculez la distance par rapport à toutes les autres particules, et le seuil pour dans un cluster ou non était de savoir s'il y avait N particules dans la distance d (deux paramètres qui doivent être définis a priori , malheureusement, mais comme certains l'ont dit réponses / commentaires, je n'allais pas m'en tirer sans en avoir).
Je l'ai ensuite accéléré en ne triant pas les distances, mais en faisant simplement une recherche d' ordre N et en incrémentant un compteur pour les particules dans d , et cela a accéléré les choses d'un facteur 6. Puis j'ai ajouté un "arbre de programmeur stupide" (parce que je sais presque rien sur les codes d'arbre). Je divise la cellule de simulation en un nombre défini de grilles (meilleurs résultats lorsque la taille de la grille ≈7 d ) où la grille principale s'aligne avec la cellule, une grille est décalée de moitié en x et y , et les deux autres sont décalées de 1/4 en ± x et ± y . Le code divise ensuite les particules en grilles, puis chaque particule N n'a qu'à avoir des distances calculées par rapport aux autres particules de cette cellule.
Théoriquement, s'il s'agissait d'un véritable arbre, je devrais obtenir la commande N * log ( N ) par opposition à N 2 vitesses. Je suis arrivé quelque part entre les deux, où pour un sous-ensemble de 50 000 particules, j'ai obtenu une augmentation de 17x de la vitesse, et pour une cellule de 150 000 particules, j'ai eu une augmentation de 38x de la vitesse. 12 secondes pour la première, 53 secondes pour la seconde, 460 secondes pour une cellule de 500 000 particules. Ce sont des vitesses comparables au temps que prend le code pour exécuter le pas de temps de simulation 1, c'est donc raisonnable à ce stade. Oh - et il est entièrement fileté, il faudra donc autant de processeurs que je peux y jeter.