Reputation: 485
I have a grid which is x=np.linspace(-1,1,n); y=x
. I perform some calculation for each x
and y
with a for
loop
for a,b in enumerate(x):
for c,d in enumrate(y):
functionstuff(x,y)
To save time, I only need to do the computations on the diamond within the diagonals defined between the points (-1,0)-(0,1)-(1,0)-(0,-1)
. So I am trying to figure out how to best do this. So for a given x
, I want to go from +(1-|x|)
to -(1-|x|)
.
So how would I go about this with adjusting the step size between the smaller y
s (so that I am not doing x = -1
, y = 0
n
times).
So I can make an numpy.array
object to loop over:
for ii,x1 in enumerate(x1):
y = np.linspace(1-np.abs(x1),-(1-np.abs(x1)),2*round((1-np.abs(x1))/dy) + 1)
for jj,y1 in enumerate(y):
f[ii][jj] = DoStuff(x1,y1)
xplot[ii][jj] = x1
yplot[ii][jj] = y1
When I want to look at plot_surface(xplot,yplot,f)
, I just get a line along a diagonal (my guess being that I had to define xplot
and yplot
as a zero array before looping over)
Upvotes: 2
Views: 106
Reputation: 3419
In numpy
it helps to take advantage of broadcasting when you can. In this case, you can set up a two-dimensional grid, X
and Y
and compute on it rather than looping over the elements of x
and y
:
import numpy as np
x = np.linspace(-1,1,N)
y = x.copy()
X,Y = np.meshgrid(x,y,indexing='ij')
Z = functionstuff(X,Y)
You'll find this much more computationally efficient.
If you want to restrict your domain, you can do so with masking:
MASK = (Y<=1+X) & (Y<=1-X) & (Y>=X-1) & (Y>=-X-1)
Z = np.zeros(X.shape)
Z[MASK] = functionstuff(X[MASK],Y[MASK])
If functionstuff = lambda x,y: exp(-(x**2+y**2)/2)
, then no masking results in this first image, and masking results in the second:
Upvotes: 1