I am doing a molecular dynamics simulation of an Argon liquid in Python. I have a stable version running, however it runs slowly for more than 100 atoms. I identified the bottleneck to be the following nested for loop. It's a force calculation put inside a function that is called from my main.py script:
def computeForce(currentPositions):
potentialEnergy = 0
force = zeros((NUMBER_PARTICLES,3))
for iParticle in range(0,NUMBER_PARTICLES-1):
for jParticle in range(iParticle + 1, NUMBER_PARTICLES):
distance = currentPositions[iParticle] - currentPositions[jParticle]
distance = distance - BOX_LENGTH * (distance/BOX_LENGTH).round()
#note: this is so much faster than scipy.dot()
distanceSquared = distance[0]*distance[0] + distance[1]*distance[1] + distance[2]*distance[2]
if distanceSquared < CUT_OFF_RADIUS_SQUARED:
r2i = 1. / distanceSquared
r6i = r2i*r2i*r2i
lennardJones = 48. * r2i * r6i * (r6i - 0.5)
force[iParticle] += lennardJones*distance
force[jParticle] -= lennardJones*distance
potentialEnergy += 4.* r6i * (r6i - 1.) - CUT_OFF_ENERGY
return(force,potentialEnergy)
the variables in CAPITAL letters are constant, defined in a config.py file. "currentPositions" is a 3 by number-of-particles matrix.
I have already implemented a version of the nested for loop with scipy.weave, which was inspired from this website: http://www.scipy.org/PerformancePython.
However, I don't like the loss of flexibility. I'm interested in "vectorizing" this for loop. I just don't really get how that works. Can anybody give me a clue or a good tutorial that teaches this?