vendredi 8 mai 2015

numpy arange values are changing signs unexpectedly

I am teaching mysef a little about numpy and I have dusted off some of my old undergraduate texts to use for examples. So, I wrote a function without numpy to calculate the deflection in a cantilever beam due to a single point load at any point. Pretty straight forward, except that the deflection equation changes depending on what side of the point force you are on, so I will split the beam into two ranges, calculate the deflection values at each interval in the ranges and append the result to a list. Here's the code.

def deflection(l, P, a, E, I):
    """
    Calculate the deflection of a cantilever beam due to a simple point load.

    Calculates the deflection at equal one inch intervals along the beam and
    returns the deflection as a list along with the the length range.

    Parameters
    ----------
    l : float
        beam length (in)
    P : float
        Point Force (lbs)
    a : float
        distance from fixed end to force (in)
    E : float
        modulus of elasticity (psi)
    I : float
        moment of inertia (in**4)

    Returns
    -------
    list
        x : distance along beam (in)

    list of floats
        y : deflection of beam (in)

    Raises
    ------
    ValueError
        If a < 0 or a > l (denoting force location is off the beam)
    """
    if (a < 0) or (a > l):
        raise ValueError('force location is off beam')

    x1 = range(0, a)
    x2 = range(a, l + 1)
    deflects = []
    for x in x1:
        y = (3 * a - x) * (P * x**2) / (6 * E * I)
        deflects.append(y)
    for x in x2:
        y = (3 * x - a) * (P * a**2) / (6 * E * I)
        deflects.append(y)
    return list(x1) + list(x2), deflects

Now I want to do the same thing using numpy, so I wrote the following function:

def np_deflection(l, P, a, E, I):
    """To Do.  Write me."""
    if (a < 0) or (a > l):
        raise ValueError('force location is off beam')
    x1 = np.arange(0, a)
    x2 = np.arange(a, l + 1)
    y1 = (3 * a - x1) * (P * x1**2) / (6 * E * I)
    y2 = (3 * x2 - a) * (P * a**2) / (6 * E * I)
    return np.hstack([x1, x2]), np.hstack([y1, y2])

Here's the issue, at some point in the calculations, the value of y1 changes sign. Here's an example.

if __name__ == '__main__':
import matplotlib.pyplot as plt

l, P, a, E, I = 120, 1200, 100, 30000000, 926

x, y = deflection(l, P, a, E, I)
print(max(y))

np_x, np_y = np_deflection(l, P, a, E, I)
print(max(np_y))

plt.subplot(2, 1, 1)
plt.plot(x, y, 'b.-')
plt.xlabel('dist from fixed end (in)')
plt.ylabel('using a range/list')

plt.subplot(2, 1, 2)
plt.plot(np_x, np_y, 'r.-')
plt.xlabel('dist from fixed end (in)')
plt.ylabel('using numpy range')

plt.show()

If you run the plot, you'll see that at point x = 93 which is in x1, there is a dislocation in the curve where the value seems to change sign.
plot of results Can anyone explain a) what is happening? and b) what I did wrong?

Aucun commentaire:

Enregistrer un commentaire