Search code examples
pythonalgorithmparticle-system

Efficient Particle-Pair Interactions Calculation


I have an N-body simulation that generates a list of particle positions, for multiple timesteps in the simulation. For a given frame, I want to generate a list of the pairs of particles' indices (i, j) such that dist(p[i], p[j]) < masking_radius. Essentially I'm creating a list of "interaction" pairs, where the pairs are within a certain distance of each other. My current implementation looks something like this:

interaction_pairs = []

# going through each unique pair (order doesn't matter)
for i in range(num_particles):
    for j in range(i + 1, num_particles):
        if dist(p[i], p[j]) < masking_radius:
            interaction_pairs.append((i,j))

Because of the large number of particles, this process takes a long time (>1 hr per test), and it is severely limiting to what I need to do with the data. I was wondering if there was any more efficient way to structure the data such that calculating these pairs would be more efficient instead of comparing every possible combination of particles. I was looking into KDTrees, but I couldn't figure out a way to utilize them to compute this more efficiently. Any help is appreciated, thank you!


Solution

  • Since you are using python, sklearn has multiple implementations for nearest neighbours finding: http://scikit-learn.org/stable/modules/neighbors.html

    There is KDTree and Balltree provided.

    As for KDTree the main point is to push all the particles you have into KDTree, and then for each particle ask query: "give me all particles in range X". KDtree usually do this faster than bruteforce search. You can read more for example here: https://www.cs.cmu.edu/~ckingsf/bioinfo-lectures/kdtrees.pdf

    If you are using 2D or 3D space, then other option is to just cut the space into big grid (which cell size of masking radius) and assign each particle into one grid cell. Then you can find possible candidates for interaction just by checking neighboring cells (but you also have to do a distance check, but for much fewer particle pairs).