Soy un investigador de ciencias planetarias y un proyecto en el que estoy trabajando es la simulación de cuerpos N de los anillos de Saturno. El objetivo de este estudio en particular es observar cómo las partículas se agrupan bajo su propia gravedad y medir la masa agregada de los grupos frente a la velocidad media de todas las partículas en la célula. Estamos tratando de averiguar si esto puede explicar algunas observaciones hechas por la nave espacial Cassini durante el solsticio de verano de Saturno cuando se vieron grandes estructuras proyectando sombras en los anillos casi de borde. A continuación se muestra una captura de pantalla de cómo se ve cualquier paso de tiempo dado. (Cada partícula tiene 2 m de diámetro y la celda de simulación en sí tiene unos 700 m de diámetro).
El código que estoy usando ya escupe la velocidad media en cada paso de tiempo. Lo que necesito hacer es encontrar una manera de determinar la masa de partículas en los grupos y NO las partículas perdidas entre ellos. Conozco la posición, masa, tamaño, etc. de cada partícula, pero no sé fácilmente que, digamos, las partículas 30,000-40,000 junto con 102,000-105,000 forman una hebra que para el ojo humano es obvia.
Por lo tanto, el algoritmo que necesito escribir debería ser un código con la menor cantidad posible de parámetros ingresados por el usuario (para replicabilidad y objetividad) que atraviese todas las posiciones de las partículas, descubra qué partículas pertenecen a los grupos y luego calcule masa. Sería genial si pudiera hacerlo para "cada" grupo / filamento en lugar de todo sobre la celda, pero no creo que realmente lo necesite para separarlos.
Lo único en lo que estaba pensando era en hacer algún tipo de cálculo de distancia N 2 donde calcularía la distancia entre cada partícula y si, por ejemplo, las 100 partículas más cercanas estuvieran dentro de una cierta distancia, esa partícula se consideraría parte de un racimo. Pero eso parece bastante descuidado y esperaba que ustedes, programadores y CS, conocieran una solución más elegante.
Editado con mi solución: Lo que hice fue tomar una especie de enfoque de vecino / clúster más cercano y hacer primero la implementación rápida y sucia de N 2 . Entonces, tome cada partícula, calcule la distancia a todas las demás partículas, y el umbral para un grupo o no fue si había N partículas dentro de la distancia d (dos parámetros que deben establecerse a priori , desafortunadamente, pero como dijeron algunos respuestas / comentarios, no iba a salirse con la suya al no tener algunos de esos).
Luego lo aceleré no ordenando distancias, sino simplemente haciendo una búsqueda de orden N e incrementando un contador para las partículas dentro de d , y eso aceleró las cosas por un factor de 6. Luego agregué un "árbol de programadores estúpido" (porque sé casi nada sobre códigos de árbol). Divido la celda de simulación en un número establecido de cuadrículas (mejores resultados cuando el tamaño de cuadrícula ≈7 d ) donde la cuadrícula principal se alinea con la celda, una cuadrícula se compensa por la mitad en x e y , y las otras dos se compensan por 1/4 pulg. ± x y ± y . El código luego divide las partículas en las cuadrículas, luego cada partícula N solo debe tener distancias calculadas a las otras partículas en esa celda.
Teóricamente, si este fuera un árbol real, debería obtener el orden N * log ( N ) en lugar de N 2 velocidades. Llegué a algún lugar entre los dos, donde para un subconjunto de 50,000 partículas obtuve un aumento de 17x en la velocidad, y para una celda de 150,000 partículas, obtuve un aumento de 38x en la velocidad. 12 segundos para el primero, 53 segundos para el segundo, 460 segundos para una celda de 500,000 partículas. Esas son velocidades comparables a cuánto tiempo tarda el código en ejecutar la simulación 1 paso adelante, por lo que es razonable en este punto. Ah, y está completamente enhebrado, por lo que necesitará tantos procesadores como pueda.