3

I'm trying avoid to use for loops to run my calculations. But I don't know how to do it. I have a matrix w with shape (40,100). Each line holds the position to a wave in a t time. For example first line w[0] is the initial condition (also w[1] for reasons that I will show).

To calculate the next line elements I use, for every t and x on shape range:

w[t+1,x] = a * w[t,x] + b * ( w[t,x-1] + w[t,x+1] ) - w[t-1,x]

Where a and b are some constants based on equation solution (it really doesn't matter), a = 2(1-r), b=r, r=(c*(dt/dx))**2. Where c is the wave speed and dt, dx are related to the increment on x and t direction.

Is there any way to avoid a for loop like:

for t in range(1,nt-1):
    for x in range(1,nx-1):
      w[t+1,x] = a * w[t,x] + b * ( w[t,x-1] + w[t,x+1] ) - w[t-1,x]

nt and nx are the shape of w matrix.

2
  • 1
    I would recommend that you look at this tutorial for implementing partial differential equations (in this case Navier-Stokes) in Python. Commented Apr 17, 2016 at 0:06
  • Thank you very much @RolandSmith. Commented May 25, 2016 at 18:34

2 Answers 2

5

I assume you're setting w[:,0] and w[:-1] beforehand (to some constants?) because I don't see it in the loop. If so, you can eliminate for x loop vectorizing this part of code:

for t in range(1,nt-1):
    w[t+1,1:-1] = a*w[t,1:-1] + b*(w[t,:-2] + w[t,2:]) - w[t-1,1:-1]
Sign up to request clarification or add additional context in comments.

Comments

0

Not really. If you want to do something for every element in your matrix (which you do), you're going to have to operate on each element in some way or another (most obvious way is with a for loop. Less obvious methods will either perform the same or worse).

If you're trying to avoid loops because loops are slow, know that sometimes loops are necessary to solve a certain kind of problem. However, there are lots of ways to make loops more efficient.

Generally with matrix problems like this where you're looking at the neighboring elements, a good solution is using some kind of dynamic programming or memoization (saving your work so you don't have to repeat calculations frequently). Like, suppose for each element you wanted to take the average of it and all the things around it (this is how blurring images works). Each pixel has 8 neighbors, so the average will be the sum / 9. Well, let's say you save the sums of the columns (save NW + W + SW, N + me + S, NE + E + SE). Well when you go to the next one to the right, just sum the values of your previous middle column, your previous last column, and the values of a new column (the new ones to the right). You just replaced adding 9 numbers with adding 5. In operations that are more complicated than addition, reducing 9 to 5 can mean a huge performance increase.

I looked at what you have to do and I couldn't think of a good way to do something like I just described. But see if you can think of something similar.

Also, remember multiplication is much more expensive than addition. So if you had a loop where, for instance, you had to multiply some number by the loop variable, instead of doing 1x, 2x, 3x, ..., you could do (value last time + x).

1 Comment

One of the features of numpy is that its operators and functions act by element of an array. This makes tasks like these easier to write. Under the hood, this is implemented as a loop, but in C instead of Python, making it a lot faster.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.