3

I am trying to write a program that uses recursion to solve for the velocity of an object shot straight into the air and calculates when it hits the ground while accounting for gravity changing with altitude with this equation g(s) = G∙ME / (RE + s)^2 displacement with this equation s(t) = s(t-∆t) + v(t)∙∆t and velocity with this equation v(t) = v(t-∆t) - g(s(t-∆t)) ∙ ∆t I am using the previous values (denoted by t-∆t) as inputs and then updating the variables and returning them which makes sense to me but I must be doing something wrong. Originally I was getting an error saying the maximum recursion limit was exceeded but after some googling I found that I should change the recursion limit. Now the program seems like it begins to run but then python crashes before outputing anything. I have been unable to figure out what I could do to make this work. Any help would be greatly appreciated

import math as m
import sys
sys.setrecursionlimit(20000)
  #
    #
    # Method that runs the simulation
    #

def run(deltat, G, ME, RE, velocity):
    # set initial time to 0
    s = 0
    t = 0

    # Save the initial velocity because it is needed to find when the ground is hit
    initialvelocity = velocity
    # while the height is greater than 0 execute the loop
    while s >= 0:
        # Find the height based on gravity, and velocity
        s = calculatedisplacement(t ,deltat, velocity, s, G, ME, RE)

        # Calculate the velocity based on the changing gravity
        velocity = calculatevelocity(velocity, t ,deltat, s, G, ME, RE)

        # If s is larger than 0 print where the object is
        if s >= 0:
            print ("At time t = " + str(t) + " The object is " + str(s) + " meters high")
            t = t + deltat
            print("Time: " + str(t))

        elif s < 0:
            print ("The object hits the ground at t = " + str(quadraticsolver((-0.5 * (G * ME)) / (m.pow(RE, 2)), initialvelocity, 0)))


# Function used to calculate gravity
def calculategravity(s, G, ME, RE):


    gravity = ((G * ME) / (m.pow((RE + s), 2)))

    print ("Gravity = " + str(gravity))

    return gravity

# Function used to calculate height
def calculatedisplacement(t ,deltat, velocity, s, G, ME, RE):
    s = s + (calculatevelocity(velocity, t ,deltat, s, G, ME, RE) * deltat)
    print("height = " + str(s))
    return s

# Function used to calculatevelocity
def calculatevelocity(t ,deltat, velocity, s, G, ME, RE):
    velocity = velocity - ((calculategravity(G, ME, RE,calculatedisplacement(t ,deltat, velocity, s, G, ME, RE)))* deltat)
    print("Velocity " + str(velocity))
    return velocity

# Used to solve quadratic equations and find where the object hits the ground
def quadraticsolver(a, b, c):
    discriminant = (m.pow(b, 2)) - (2 * a * c)
    # Two solutions to account for the + or - in the quadratic formula
    solution1 = (((-b) + (m.sqrt(discriminant))) / (2 * a))
    solution2 = (((-b) - (m.sqrt(discriminant))) / (2 * a))
    # One solution will always be 0 because height is 0 when time is 0 so return the solution that is not zero
    # This is the time when height = 0
    if solution1 == 0:
        return solution2
    elif solution2 == 0:
        return solution1
user3282276
  • 3,674
  • 8
  • 32
  • 48
  • What error are you getting? – AlG Feb 25 '14 at 20:17
  • 3
    You don't actually show anything failing, or a call on any of your code. Please post the traceback (feel free to remove about 19,980 duplicated stack frames). Without knowing how you are calling your function it's hard to know what might be going wrong. You might also see whether a larger value of time delta reduces the number of calls to keep you within bounds. I doubt it can, though, since the first thing `calculate_velocity` does is call `calculate_displacement` and vice versa, so there is little hope of terminating this infinite recursion as your logic is currently structured. – holdenweb Feb 25 '14 at 20:26

1 Answers1

4

(This got too big for a comment.)

Recursion is good for solving many problems, but iterating a numerical simulation is not one of them. The number of stack frames is a limited quantity, to be used sparingly (Python has a limit on the number of stack frames because it's usually an error when you use too many of them). You might be running out of memory allocated for the stack (as opposed to heap) or you might be running out of all memory, stack and heap. Out-of-memory errors sometimes come without warning because the program or operating system doesn't have the resources to generate a warning.

You'll probably find that your program is more efficient, easier to debug, and maybe even bug-free if you rewrite it as a for or while loop.

Some programming languages, like Scheme, encourage the use of recursion for iteration, but these languages internally convert your recursive functions into while loops ("tail-call optimization"). Python is not one of those languages: every time you call a function, it creates a new stack frame and does not delete the old stack frame until the recursion ends, which is effectively like a memory leak. (That is, the objects are no longer useful, but they're still referenced and still in memory.)

Jim Pivarski
  • 5,568
  • 2
  • 35
  • 47