What can I do to speed up the execution of the following code significantly (in particular for even higher values of N). I think the main problem is the sum in the get_field function.
from numpy import *
from numpy.linalg import *
from scipy import constants as co
import pylab as plt
eps0 = co.epsilon_0
charges = []
class charge:
def __init__(self, q, pos):
self.q=q
self.pos=pos
a = 10
N = 1001
d = 1e-3
Q = 1e-8
q = Q/N**2
for x in linspace(0,a,N):
for y in linspace(0,a,N):
## First plate
position = array([x,y,0])
NewCharge = charge(q,position)
charges.append(NewCharge)
## Second Plate
position2 = array([x,y,d])
NewCharge2 = charge(-q,position2)
charges.append(NewCharge2)
def get_field(position):
E = array([0.,0.,0.])
for C in charges:
q = C.q
rVector = position - C.pos
r = norm(rVector)
r0Vector = rVector/r
E += 1/(4*pi*eps0)*q/r**2 * r0Vector
#print(E)
return E[2]
p = 0.1
x0 = 0.5*a
y0 = 0.5*a
#print(get_field([x0,y0,1]))
Z = linspace(p*d,(1-p)*d,100)
E = [get_field([x0,y0,z]) for z in Z]
print(Z)
print(E)
plt.plot(Z,E,'x')
plt.ylim(bottom=0)
plt.show()
The background is a physics problem where I want to find the electric field of a parallel plate capacitor by explicitly summing up the coulomb fields of evenly distributed point charges on two parallel plates.
Update @Blckknght's answer improves the performance of my code significantly, for example for N = 100, my original code takes approx 90 seconds on my system and your code 0,6 seconds. For N = 500 my code takes approx 2300 seconds, Blckknght's code approx 3 seconds.
The problem with this improved code is that the memory consumption is so high that in my case the program just gets killed if my 16 GB memory are exceeded.
So is there any way to get those optimizations without running into the memory problem at all?