Sou pesquisador de ciências planetárias e um projeto no qual estou trabalhando é a simulação de corpos em N dos anéis de Saturno. O objetivo deste estudo em particular é observar como as partículas se aglutinam sob sua própria gravidade e medir a massa agregada dos aglomerados versus a velocidade média de todas as partículas na célula. Estamos tentando descobrir se isso pode explicar algumas observações feitas pela sonda Cassini durante o solstício de verão de Saturno, quando grandes estruturas foram vistas projetando sombras nos anéis quase de ponta a ponta. Abaixo está uma captura de tela da aparência de qualquer timestep. (Cada partícula tem 2 m de diâmetro e a própria célula de simulação tem cerca de 700 m de diâmetro.)
O código que estou usando já mostra a velocidade média a cada passo do tempo. O que eu preciso fazer é descobrir uma maneira de determinar a massa de partículas nos aglomerados e NÃO as partículas dispersas entre eles. Conheço a posição, massa, tamanho, etc. de cada partícula, mas não sei com facilidade que, digamos, as partículas 30.000 a 40.000, juntamente com 102.000 a 105.000, formam um filamento que, para o olho humano, é óbvio.
Portanto, o algoritmo que eu preciso escrever seria um código com o menor número possível de parâmetros inseridos pelo usuário (para replicabilidade e objetividade) que passaria por todas as posições das partículas, descobrisse quais partículas pertencem aos aglomerados e calcule o massa. Seria ótimo se isso pudesse ser feito para "cada" grupo / vertente, em oposição a tudo na célula, mas não acho que realmente precise separá-los.
A única coisa em que eu pensava era fazer algum tipo de cálculo de distância de N 2, onde eu calculava a distância entre cada partícula e se, digamos, as 100 partículas mais próximas estivessem dentro de uma certa distância, essa partícula seria considerada parte de um grupo. Mas isso parece muito desleixado e eu esperava que vocês, pessoal e programadores do CS, soubessem de uma solução mais elegante?
Editado com Minha solução: O que fiz foi adotar uma espécie de abordagem de vizinho / cluster mais próximo e fazer a implementação rápida e suja do N 2 primeiro. Portanto, pegue todas as partículas, calcule a distância de todas as outras partículas e o limite para um cluster ou não era se havia N partículas a uma distância d (dois parâmetros que precisam ser definidos a priori , infelizmente, mas como foi dito por alguns respostas / comentários, eu não iria me safar por não ter alguns deles).
Depois, apressei-o não classificando distâncias, mas simplesmente fazendo uma busca N de ordem e incrementando um contador para as partículas dentro de d , e isso acelerou o fator por um fator de 6. Em seguida, adicionei uma "árvore de programador estúpida" (porque eu sei quase nada sobre códigos de árvores). I dividir a célula em simulação de um determinado número de grelhas (melhores resultados quando o tamanho da grade ≈7 d ), onde as principais linhas de grade para cima com a célula, uma grade é compensado pela metade em x e y , e os outros dois são compensados pelos 1/4 in ± x e ± y . O código então divide as partículas nas grades, então cada partícula N só precisa ter distâncias calculadas para as outras partículas naquela célula.
Teoricamente, se essa fosse uma árvore real, eu deveria obter a ordem N * log ( N ) em oposição às velocidades N 2 . Eu cheguei em algum lugar entre os dois, onde para um subconjunto de 50.000 partículas, obtive um aumento de 17x na velocidade e, para uma célula de 150.000 partículas, obtive um aumento de 38x na velocidade. 12 segundos para o primeiro, 53 segundos para o segundo, 460 segundos para uma célula de 500.000 partículas. Essas são velocidades comparáveis a quanto tempo o código leva para executar a simulação 1 passo a passo adiante, então é razoável neste momento. Ah - e é totalmente encadeado, portanto, serão necessários tantos processadores quanto eu puder.