0
from sympy.mpmath import *

I'm constructing a beam model, but I've encountered some trouble with the last part - getSlope. Otherwise though, the rest should be fine.

class beam(object):
    """Model of a beam.
    """

    def __init__(self, E, I, L):
        """The class costructor.
        """
        self.E = E  # Young's modulus of the beam in N/m^2
        self.I = I  # Second moment of area of the beam in m^4
        self.L = L  # Length of the beam in m
        self.Loads = [(0.0, 0.0)]  # the list of loads applied to the beam

    def setLoads(self, Loads):
        '''This function allows multiple point loads to be applied to the beam
        using a list of tuples of the form (load, position)
        '''
        self.Loads = Loads

The above doesn't need any adjustment since it was given.

    def beamDeflection(self, Load, x):
        """A measure of how much the beam bends.
        """
        a = 2.5
        b = a + (x - a)
        (P1, A) = Load
        if 0 <= x <= a:
            v = ((P1*b*x)/(6*self.L*self.E*self.I))*((self.L**2)-(x**2)-(b**2))
        else:
            if a < x <= 5:
                v = ((P1*b)/(6*self.L*self.E*self.I)) * (((self.L/b)*((x-a)**3)) - (x**3) + (x*((self.L**2) - (b**2))))
        return v

The above function 'beamDeflection' is some simple hardcoding that I've done, where if a single load is placed on the left hand side, then a certain formula is used and if the load is on the other side, then a different formula is used.

    def getTotalDeflection(self, x):
        """A superposition of the deflection.
        """
        return sum(self.beamDeflection(loadall, x) for loadall in self.Loads)

'getTotalDeflection' calculates the total deflection at a point when multiple loads are placed on it.

    def getSlope(self, x):
        """Differentiate 'v' then input a value for x to obtain a result.
        """
        mp.dps = 15
        mp.pretty = True
        theta = sympy.diff(lambda x: self.beamDeflection(self.Loads, x), x)
        return theta

b = beam(8.0E9, 1.333E-4, 5.0)
b.setLoads([(900, 3.1), (700, 3.8), (1000, 4.2)])
print b.getSlope(1.0)

For this function, I'm supposed to differentiate 'beamDeflection' or 'v' as I defined it while it's under more than one load then input a value for x to find the gradient/slope.

I'm following this: "http://docs.sympy.org/dev/modules/mpmath/calculus/differentiation.html" to differentiate, but it needs a second argument (an integer it seems) for it to work, so I don't think this is the correct method of differentiating it. Could anyone shed some light on this please?

Reti43
  • 9,656
  • 3
  • 28
  • 44
tablue
  • 81
  • 5
  • 1
    It looks like that function takes the function that you're differentiating and the point where you want to calculate the derivative. So that last line should be something like `diff(self.beamDeflection, x)`. The `lambda` is probably unnecessary in your case – JCVanHamme Dec 15 '15 at 20:02
  • @JCV: Thank you for the pointer! :) – tablue Dec 15 '15 at 20:05
  • @Reti: Thank you as well! I'll try that method as well :) – tablue Dec 15 '15 at 20:06
  • 1
    @Reti43, good point. I missed that. So the function call should look like `diff(lambda y: self.beamDeflection(load, y), x)` – JCVanHamme Dec 15 '15 at 20:11
  • @Reti43: I've implemented your method into the code as shown in the last two lines of the editted main post. However, I seem to have a problem with the import as shown here: https://imgur.com/a/pC7wM Would you happen to know how I could resolve this? – tablue Dec 15 '15 at 20:35
  • @Reti43: All of my code is in my main post. I haven't managed to solve the import or diff() error as I'm not sure how to define the load tuple, as you pointed out. I'm now getting the unpacking error. I thought it might have been similar to what I had done above - (P1, A) = Load, but to no success. – tablue Dec 15 '15 at 21:22

1 Answers1

0

Imports

First things first, get in the good habit of not importing things with a star.

Here's a tangible example from the sympy package.

from sympy import *              # imports the symbol pi
>>> type(pi)                     # can be used to construct analytical expressions
<class 'sympy.core.numbers.Pi'>
>>> 2*pi
2*pi

>>> from sympy.mpmath import *   # imports a different pi and shadows the previous one
>>> type(pi)                     # floating point precision of the constant pi
<class 'sympy.mpmath.ctx_mp_python.constant'>
>>> 2*pi
mpf('6.2831853071795862')

Overall, I'd advise you to use from sympy import mpmath as mp and then you can use anything from that package like so: mp.diff(), mp.pi, etc.

Differentiation

sympy.mpmath.diff() (or mp.diff() from now on) computes the derivative of a function at some point x. You need to provide at least the two mandatory arguments; a function of x, and x, the point of interest.

If your function was one like getTotalDeflection(), with only an x input, you could pass it on as is. For example,

def getSlope(self, x):
    return mp.diff(self.getTotalDeflection, x)

However, if you want to use a function like beamDeflection(), you'll have to encapsulate it in a function of only x, while you somehow pass on the other argument. For example,

def getSlope(self, x, load):
    f_of_x = lambda x: self.beamDeflection(load, x)
    return mp.diff(f_of_x, x)

According to the way you've set up the method beamDeflection(), the argument Load is a tuple of two values, i.e. load and position. An example use would be

b.getSlope(1.0, (900, 3.1))

If you want to get the derivative for a list of loads, you'll have to give it a list of lists (or tuples).

def getSlope(self, x, loads):
    f_of_x = lambda x: sum(self.beamDeflection(load, x) for load in loads)
    return mp.diff(f_of_x, x)

b.getSlope(1.0, [(900, 3.1), (700, 3.8)])

Of course, if the loads you want to use are the ones stored in self.Loads, then you can simply use

def getSlope(self, x):
    return mp.diff(self.getTotalDeflection, x)
Community
  • 1
  • 1
Reti43
  • 9,656
  • 3
  • 28
  • 44