My system is composed of 12000 atoms (3D points), my purpose is to compute quantities on theses atoms.
For that I have informations on each atoms in a dict object (like type, charge and various parameters) a list of neighbors for each atoms (giving all atoms indexes at a distance < threshold), and a distance matrix between all atoms.
Quantities to compute are potentials between a given atom and all of it's neighbors (from the list of neighbors). It require the distance between atoms, the informations and parameters and the list of neighbors for a given atom.
I proceed with this code:
def LJ(sii,sjj,Eii,Ejj,rij):
"""
Fonction that compute the LJ potential. one of the quantities
sii : sigma for atom i ( a parameter )
sjj : sigma for atom j ( a parameter )
Eii : epsilon for atom i ( a parameter )
Ejj : epsilon for atom j ( a parameter )
rij : squared distance between atom i and j
"""
sij = (sii+sjj)*0.5
Eij = (Eii*Ejj)**0.5
return ((4*Eij*(sij**12))/(rij**6)) - ((4*Eij*(sij**6))/(rij**3))
def Coul(qi,qj,rij):
"""
Fonction that compute the Coul potential. another quantities
qi : charge of atom i ( a parameter )
qj : charge of atom j ( a parameter )
rij : squared distance between atom i and j
"""
V = 138.935458*((qi*qj)/(rij**0.5)) # because rij is squared i take the square root
return V
def energies(NL,sP,D):
"""
NL : a vector of neighbors with as index the position and as value a list of indexes of neighbors
for example [[1,2,3],[0,2]...] the first atom at position 0 as 3 neighbors 1,2 and 3. The second atom at position 1 as 2 neighbors 0 and 2 etc...
sP : a distionnary giving the parameters for a given atoms, and also neighbors distant of 4 atoms in the mist 'dihedrals'. The key correspond to the index of the distance matric and the neighboring list, but it's a string
sample : {'key': '0_NH3', 'num': 0, 'type': 'NH3', 'resnr': 0, 'residu': 'ASP', 'atom': 'N', 'charge': -0.3, 'sigma': 0.329632525712, 'epsilon': 0.8368, 'voisins': [1, 2, 3, 4, 5, 6, 12], 'dihedrals': [7, 8, 9, 13, 14]}
D : the squared distance matrix between all atoms
"""
coul,ljk,ljk14,coul14 = [],[],[],[] # I want the potential for each atom and I want 4 types of potentials
# coul and ljk are potentials calculated on neighboring atoms in the NL neighbors list
# coul14 and ljk14 are potentials calculated on neighboring atoms in the sP[key]['dihedrals'] list
for k in sP.keys(): # For each atom
# k is a string that represent an int sP['0'] as the informations for D[0][:] or D[:][0] and NL[0]
ljk.append(sum([LJ(sP[k]['sigma'],sP[str(n)]['sigma'],sP[k]['epsilon'],sP[str(n)]['epsilon'],D[int(k)][n]) for n in NL[int(k)]]))
coul.append(sum([Coul(sP[k]['charge'],sP[str(n)]['charge'],D[int(k)][n]) for n in NL[int(k)]]))
ljk14.append(sum([LJ(sP[k]['sigma'],sP[str(n)]['sigma'],sP[k]['epsilon'],sP[str(n)]['epsilon'],D[int(k)][n]) for n in sP[k]['dihedrals']]))
coul14.append(sum([Coul(sP[k]['charge'],sP[str(n)]['charge'],D[int(k)][n]) for n in sP[k]['dihedrals']]))
# because I want the sum of all potentials for each atom I use a sum on a comprehensive list of potential between a given atom and it's neighbors
On my machine the code takes about 40 seconds to compute for 12134 atoms. I really have to reduce this number as much as possible. This is the best version I got, but I feel something can be done with numpy and vectorization, but I didn't find anything.
Thanks for the help