February 06, 2013

Python learning opportunity

I have an honors student this semester who is working on vpython simulations of general physics systems.  She knew no programming as of two weeks ago, but tonight was really close to having a projectile motion simulation done.

In trying to put velocity vector components on the projectile's position every 10 time steps, she was running into a problem: using the modulus operator only worked on the first two vectors, then did not.

Here was her code:

 while ball.y >= -2.75 and int_velo > 0:  
   t = t + dt   
   ball.pos= ball.pos + ball_velocity*dt  
   ball_velocity.y = ball_velocity.y - 9.81*dt  
   if (t*100)%10 == 0: #doesn't work!!!   
     vel_xvec = arrow(pos=(ball.pos.x,ball.pos.y,0), axis=(int_xvelo,0,0), shaftwidth=0.5)    
     vel_yvec = arrow(pos=(ball.pos.x,ball.pos.y,0), axis=(0,ball_velocity.y,0), shaftwidth=0.5)  

The comment tells the story. I guess I should know more about the modulus operator in python. It seems simple to use, but I couldn't really figure out what the problem was initially.

The short version of this story is that my student gets to learn about computer round-off errors and how to debug code by sticking a print command in the code so that she can figure out these problems without too much intervention on my part.

Here's my debug line I ended up using, followed by the fixed if statement:

   print t, t*100, (round(t*100)%10.0)  
   if (round(t*100)%10) == 0: #works now!!!   

I'm looking forward to a fun semester of python projects!


Tony McDaniel said...

I don't see how this is necessarily going to work every 10 time steps unless you're specifically choosing dt such that round(t+10*dt)%10 == 0. If dt is arbitrary, then this may never work out. Alternatively, if t is an integer, and dt =1, then multiplying by 100 will always result in a true return.

I would think the most consistent way to do this would be to add a counter to keep track of the time steps, and use if (counter % 10 == 0) as the condition.

Andrew said...

Ah...you're correct. dt was chosen to be 0.01. I didn't show that part of the code. Having a counter to keep track is another good way to accomplish this. I'll share that with my student. Thanks!