Each looping return a result

Question:

I am a beginner and got an issue, really head around now.

Here is the code:

n=3   #time step
#f, v and r are arrays,eg [3,4,5]
#r,v,f all have initial array which is when n=0
def force():
    r=position()
    f=r*2
    return f

def position(n):
    v=velocity(n)
    for i in range(n):    #This part may wrong...
        r=v*i             #How can I return results when i=0,1...5?
    return r

def velocity(n):
    f=force
    for i in range(n):
        v=f*i              #Same problem here.....
    return v

Another problem is force. It is a function of position which is a function of velocity, and velocity is a function of force. So, it’s kind of a logic loop. I can’t even
start. Physically it should initially start from force at time=0 then carrying on looping. But I just don’t know how to do it in .
Also how can I make the row of r,v to be the results with the evolution of the time?

Asked By: user211037

||

Answers:

You could use a list comprehension:

def position(n):
    v=velocity(n)
    return [v*i for i in range(n)]

Or, since you are using numpy:

v=np.array([1,2,3])
# array([1, 2, 3])

you can use numpy broadcasting to express the entire calculation in one blow:

i=np.arange(5)
# array([0, 1, 2, 3, 4])

v[:]*i[:,np.newaxis]
# array([[ 0,  0,  0],
#        [ 1,  2,  3],
#        [ 2,  4,  6],
#        [ 3,  6,  9],
#        [ 4,  8, 12]])

In the above calculation, the scalar values in i (e.g. 0,1,2,3,4) are each multiplied against the array v. The results are collected in a 2-d numpy array. Each row corresponds to a different value of i.
See http://www.scipy.org/EricsBroadcastingDoc for an introduction to numpy broadcasting.

@OP: To address your question regarding a “logic loop”:
Typically, what you do is define a “state” of the system. Perhaps in your case a state would consist of a tuple (time,position,velocity). You would then define a function which is given a state-tuple as an input and return a new state-tuple as output.

Given a (time,position,velocity), the force could be computed (mainly from the old position). From the force, you then compute the new velocity. From the velocity, you compute a new position.

Don’t write code first.

In this case, sit down with paper and pencil and grind out the calculation by hand with a concrete example. Do enough iterations until you see clearly the pattern of how the calculation is done. What is the order of the steps? What parts get repeated?
Once you see how to do it by hand, it will be much clearer how to write the python code.

Answered By: unutbu

You need to use append to add to the list.

def position(n):
    v=velocity(n)
    r = array()
    for i in range(n):    #this part may wrong...
        r.append(v*i)             #how can I return results when i=0,1...5?
    return r
Answered By: unholysampler

You can use yield.


def velocity(n):
  f=force
  for i in range(n):
    v=f*i
    yield(v)

for vel in velocity(n): //do something

One working example. It will print the output of function test as soon as it yields. So you do not need to wait for the next iteration of the loop.


import time
def test():
  for i in range(10):
    time.sleep(i)
    yield(i)

for k in test(): print k

Answered By: bhups

It looks like you're trying to do an Euler algorithm and getting a bit mixed up in the looping. Here's how I think it should look (and I'll assume this is for a game and not homework... if it is for homework you should state that clearly so we don't give the full answer, like I'm doing here.)

This example is for a ball on a spring, which I think you're aiming for. I'm the example, my initial conditions are to thrown diagonally along the x-z axis, and I've also included gravity (if you didn't intend to you vectors you can just replace all the vector quantities with scalars, e.g. t, x, v = 0., 0., 2.; etc).

from numpy import *

# set the start conditions, etc.
n_timesteps = 100
dt, m, k = .1, 1., 2. # timestep, mass, spring-const (I'll write the equations correctly so the units make sense)
t, x, v = 0., array([0.,0.,0.]), array([2., 0., 2.])  # initial values
gravity = array([0., 0., -9.8])  # to make the problem a little more interesting
result = zeros((4, n_timesteps))

# run the simulation, looping through the timesteps
for n in range(n_timesteps):
    # do the calculation
    f = -k*x + gravity
    a = f/m
    v += a*dt
    x += v*dt
    # store the results
    t += dt  # just for easy record keeping
    result[0,n] = t
    result[1:4, n] = x

Note that for loop is looping over the timesteps (and the all looping over the vectors is handles by numpy broadcasting, e.g. f = -k*x+gravity, what could be easier?). Also note that the force is set first, and then we work our way down the chain of integrating the derivatives, then go back to the top and start at the force again. (You're right that this is a bit asymmetric, and really we should update them all at the same time, or something like that, and this is a deficiency of the Euler method, but it works well enough for small timesteps.)

Here's what the plots look like... the ball oscillates as expected
alt text

Edit: To clarify your question: Basically, your code's issue is not a question of "starting the functions" as you imply; instead your code is approaching the problem in the wrong way, so you need to fix the approach. It looks like you're trying to iterate your timesteps within each function. This is incorrect! Instead you need to do an enveloping iteration through the timesteps, and for each timestep, update the current state of each variable used in the calculation at that timestep. You can write this update as a separate function or, for example, you can do it inline like I did. But it makes no sense to iterate the timesteps within each variable calculation function. Instead, for your example to make sense, force, velocity, and other functions should have as inputs things at the present timestep and return an update to the state of that variable to be used in the next timestep. See how my example does this: it just cycles through the timesteps and within each timestep cycle it sequentially updates all the variables, basing each updated variable on the variables that were updated just before it in this current timestep.

Answered By: tom10
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.