CIE4140_Lecture_13_Part_1_Python#
Consider the steady-state vibrations of a string subjected to distributed viscous damping under a harmonic force#
import sympy as sp
We represent the harmonic time-dependence by \(e^{i \Omega t}\). The real part of the response to this load will give the response to the corresponding cosinusoidal load , whereas the imaginary part will give the response to the corresponding sinusoidal load
Let us write the equation of motion
w = sp.symbols('w',cls=sp.Function)
q1 = sp.symbols('q1',cls=sp.Function,real=True)
x,t = sp.symbols('x t',real=True)
nd, c, Omega= sp.symbols('nd c Omega',real=True)
EQM = sp.diff(w(x,t),t,2) + 2 * nd * sp.diff(w(x,t),t) - c**2 * sp.diff(w(x,t),x,2) - q1(x)*sp.exp(sp.I*Omega*t)
display(EQM)
We search for the steady-state solution in the form:
W = sp.symbols('W',cls=sp.Function)
w_form = W(x) * sp.exp(sp.I * Omega * t)
Substitution of this equation in the equation of motion gives:
EQM_fr = sp.simplify(EQM.subs(w(x,t),w_form))
display(EQM_fr)
\(e^{i \Omega t}\) is not dropped, so can dropped manually, not necessary:
display(EQM_fr.subs(sp.exp(sp.I * Omega * t),1))
Let us find the soluton to this equation that satisfies the boundary conditions of a fixed-fixed string
L = sp.symbols('L')
W_sol = sp.dsolve(EQM_fr,W(x),ics={W(0):0,W(L):0}).rhs
display(W_sol)
We introduce numerical values for the parameters
W_sol = W_sol.subs([(L,1),(c,2),(nd,1/2)])
display(W_sol)
Let us consider two different shapes of the exernal force:
q1_second_normal_mode = sp.sin(2 * sp.pi * x / 1)
q1_arbitrary = 14.39 * x **5 * (x - 1)
q1_constant = 1
p0 = sp.plotting.plot(q1_second_normal_mode, (x, 0, 1),label='$q1_{second\ normal\ mode}$' ,legend=True,show=False)
p1 = sp.plotting.plot(q1_arbitrary , (x, 0, 1),label='$q1_{arbitrary}$' ,show=False)
p2 = sp.plotting.plot(q1_constant , (x, 0, 1),label='$q1_{constant}$' ,show=False)
p0.append(p1[0])
p0.append(p2[0])
p0.show()
W_to_second_normal_mode = W_sol.subs(q1(x),q1_second_normal_mode).subs(q1(L),q1_second_normal_mode.subs(x,L)).subs(q1(0),q1_second_normal_mode.subs(x,0))
display(W_to_second_normal_mode)
W_to_arbitrary = W_sol.subs(q1(x),q1_arbitrary).subs(q1(L),q1_second_normal_mode.subs(x,L)).subs(q1(0),q1_second_normal_mode.subs(x,0))
display(W_to_arbitrary)
W_to_constant = W_sol.subs(q1(x),q1_constant).subs(q1(L),q1_second_normal_mode.subs(x,L)).subs(q1(0),q1_second_normal_mode.subs(x,0))
display(W_to_constant)
Let us animate the reponses to these two loads assuming that the time-depandence is sinusoidal and introducing a numerical value of the load frequency: \(\Omega=5\)
W_to_second_normal_mode_sin = sp.im(W_to_second_normal_mode*sp.exp(sp.I*Omega*t)).subs(Omega,5)
W_to_arbitrary_sin = sp.im(W_to_arbitrary*sp.exp(sp.I*Omega*t)).subs(Omega,5)
W_to_constant_sin = sp.im(W_to_constant*sp.exp(sp.I*Omega*t)).subs(Omega,5)
display(W_to_second_normal_mode_sin.subs([(x,0.25),(t,3)]).evalf())
W_to_second_normal_mode_sin_func = sp.lambdify((x,t),W_to_second_normal_mode_sin)
W_to_arbitrary_sin_func = sp.lambdify((x,t),W_to_arbitrary_sin)
W_to_constant_sin_func = sp.lambdify((x,t),W_to_constant_sin)
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_2968\3484483245.py in <module>
----> 1 W_to_second_normal_mode_sin_func = sp.lambdify((x,t),W_to_second_normal_mode_sin)
2 W_to_arbitrary_sin_func = sp.lambdify((x,t),W_to_arbitrary_sin)
3 W_to_constant_sin_func = sp.lambdify((x,t),W_to_constant_sin)
~\Anaconda3\lib\site-packages\sympy\utilities\lambdify.py in lambdify(args, expr, modules, printer, use_imps, dummify, cse)
873 else:
874 cses, _expr = (), expr
--> 875 funcstr = funcprinter.doprint(funcname, iterable_args, _expr, cses=cses)
876
877 # Collect the module imports from the code printers.
~\Anaconda3\lib\site-packages\sympy\utilities\lambdify.py in doprint(self, funcname, args, expr, cses)
1150 funcbody.append('{} = {}'.format(s, self._exprrepr(e)))
1151
-> 1152 str_expr = _recursive_to_string(self._exprrepr, expr)
1153
1154
~\Anaconda3\lib\site-packages\sympy\utilities\lambdify.py in _recursive_to_string(doprint, arg)
954
955 if isinstance(arg, (Basic, MatrixOperations)):
--> 956 return doprint(arg)
957 elif iterable(arg):
958 if isinstance(arg, list):
~\Anaconda3\lib\site-packages\sympy\printing\codeprinter.py in doprint(self, expr, assign_to)
148 self._number_symbols = set() # type: tSet[tTuple[Expr, Float]]
149
--> 150 lines = self._print(expr).splitlines()
151
152 # format the output
~\Anaconda3\lib\site-packages\sympy\printing\printer.py in _print(self, expr, **kwargs)
329 printmethod = getattr(self, printmethodname, None)
330 if printmethod is not None:
--> 331 return printmethod(expr, **kwargs)
332 # Unknown object, fall back to the emptyPrinter.
333 return self.emptyPrinter(expr)
~\Anaconda3\lib\site-packages\sympy\printing\str.py in _print_Add(self, expr, order)
56 l = []
57 for term in terms:
---> 58 t = self._print(term)
59 if t.startswith('-'):
60 sign = "-"
~\Anaconda3\lib\site-packages\sympy\printing\printer.py in _print(self, expr, **kwargs)
329 printmethod = getattr(self, printmethodname, None)
330 if printmethod is not None:
--> 331 return printmethod(expr, **kwargs)
332 # Unknown object, fall back to the emptyPrinter.
333 return self.emptyPrinter(expr)
~\Anaconda3\lib\site-packages\sympy\printing\codeprinter.py in _print_Mul(self, expr)
543 a_str = [self.parenthesize(a[0], 0.5*(PRECEDENCE["Pow"]+PRECEDENCE["Mul"]))]
544 else:
--> 545 a_str = [self.parenthesize(x, prec) for x in a]
546 b_str = [self.parenthesize(x, prec) for x in b]
547
~\Anaconda3\lib\site-packages\sympy\printing\codeprinter.py in <listcomp>(.0)
543 a_str = [self.parenthesize(a[0], 0.5*(PRECEDENCE["Pow"]+PRECEDENCE["Mul"]))]
544 else:
--> 545 a_str = [self.parenthesize(x, prec) for x in a]
546 b_str = [self.parenthesize(x, prec) for x in b]
547
~\Anaconda3\lib\site-packages\sympy\printing\str.py in parenthesize(self, item, level, strict)
35 def parenthesize(self, item, level, strict=False):
36 if (precedence(item) < level) or ((not strict) and precedence(item) <= level):
---> 37 return "(%s)" % self._print(item)
38 else:
39 return self._print(item)
~\Anaconda3\lib\site-packages\sympy\printing\printer.py in _print(self, expr, **kwargs)
329 printmethod = getattr(self, printmethodname, None)
330 if printmethod is not None:
--> 331 return printmethod(expr, **kwargs)
332 # Unknown object, fall back to the emptyPrinter.
333 return self.emptyPrinter(expr)
~\Anaconda3\lib\site-packages\sympy\printing\str.py in _print_Add(self, expr, order)
56 l = []
57 for term in terms:
---> 58 t = self._print(term)
59 if t.startswith('-'):
60 sign = "-"
~\Anaconda3\lib\site-packages\sympy\printing\printer.py in _print(self, expr, **kwargs)
329 printmethod = getattr(self, printmethodname, None)
330 if printmethod is not None:
--> 331 return printmethod(expr, **kwargs)
332 # Unknown object, fall back to the emptyPrinter.
333 return self.emptyPrinter(expr)
~\Anaconda3\lib\site-packages\sympy\printing\codeprinter.py in _print_Mul(self, expr)
543 a_str = [self.parenthesize(a[0], 0.5*(PRECEDENCE["Pow"]+PRECEDENCE["Mul"]))]
544 else:
--> 545 a_str = [self.parenthesize(x, prec) for x in a]
546 b_str = [self.parenthesize(x, prec) for x in b]
547
~\Anaconda3\lib\site-packages\sympy\printing\codeprinter.py in <listcomp>(.0)
543 a_str = [self.parenthesize(a[0], 0.5*(PRECEDENCE["Pow"]+PRECEDENCE["Mul"]))]
544 else:
--> 545 a_str = [self.parenthesize(x, prec) for x in a]
546 b_str = [self.parenthesize(x, prec) for x in b]
547
~\Anaconda3\lib\site-packages\sympy\printing\str.py in parenthesize(self, item, level, strict)
35 def parenthesize(self, item, level, strict=False):
36 if (precedence(item) < level) or ((not strict) and precedence(item) <= level):
---> 37 return "(%s)" % self._print(item)
38 else:
39 return self._print(item)
~\Anaconda3\lib\site-packages\sympy\printing\printer.py in _print(self, expr, **kwargs)
329 printmethod = getattr(self, printmethodname, None)
330 if printmethod is not None:
--> 331 return printmethod(expr, **kwargs)
332 # Unknown object, fall back to the emptyPrinter.
333 return self.emptyPrinter(expr)
~\Anaconda3\lib\site-packages\sympy\printing\str.py in _print_Add(self, expr, order)
56 l = []
57 for term in terms:
---> 58 t = self._print(term)
59 if t.startswith('-'):
60 sign = "-"
~\Anaconda3\lib\site-packages\sympy\printing\printer.py in _print(self, expr, **kwargs)
329 printmethod = getattr(self, printmethodname, None)
330 if printmethod is not None:
--> 331 return printmethod(expr, **kwargs)
332 # Unknown object, fall back to the emptyPrinter.
333 return self.emptyPrinter(expr)
~\Anaconda3\lib\site-packages\sympy\printing\codeprinter.py in _print_Mul(self, expr)
541 # an operator precedence between multiplication and exponentiation,
542 # so we use this to compute a weight.
--> 543 a_str = [self.parenthesize(a[0], 0.5*(PRECEDENCE["Pow"]+PRECEDENCE["Mul"]))]
544 else:
545 a_str = [self.parenthesize(x, prec) for x in a]
~\Anaconda3\lib\site-packages\sympy\printing\str.py in parenthesize(self, item, level, strict)
37 return "(%s)" % self._print(item)
38 else:
---> 39 return self._print(item)
40
41 def stringify(self, args, sep, level=0):
~\Anaconda3\lib\site-packages\sympy\printing\printer.py in _print(self, expr, **kwargs)
329 printmethod = getattr(self, printmethodname, None)
330 if printmethod is not None:
--> 331 return printmethod(expr, **kwargs)
332 # Unknown object, fall back to the emptyPrinter.
333 return self.emptyPrinter(expr)
~\Anaconda3\lib\site-packages\sympy\printing\numpy.py in _print_re(self, expr)
229
230 def _print_re(self, expr):
--> 231 return "%s(%s)" % (self._module_format(self._module + '.real'), self._print(expr.args[0]))
232
233 def _print_sinc(self, expr):
~\Anaconda3\lib\site-packages\sympy\printing\printer.py in _print(self, expr, **kwargs)
329 printmethod = getattr(self, printmethodname, None)
330 if printmethod is not None:
--> 331 return printmethod(expr, **kwargs)
332 # Unknown object, fall back to the emptyPrinter.
333 return self.emptyPrinter(expr)
~\Anaconda3\lib\site-packages\sympy\printing\codeprinter.py in _print_Mul(self, expr)
543 a_str = [self.parenthesize(a[0], 0.5*(PRECEDENCE["Pow"]+PRECEDENCE["Mul"]))]
544 else:
--> 545 a_str = [self.parenthesize(x, prec) for x in a]
546 b_str = [self.parenthesize(x, prec) for x in b]
547
~\Anaconda3\lib\site-packages\sympy\printing\codeprinter.py in <listcomp>(.0)
543 a_str = [self.parenthesize(a[0], 0.5*(PRECEDENCE["Pow"]+PRECEDENCE["Mul"]))]
544 else:
--> 545 a_str = [self.parenthesize(x, prec) for x in a]
546 b_str = [self.parenthesize(x, prec) for x in b]
547
~\Anaconda3\lib\site-packages\sympy\printing\str.py in parenthesize(self, item, level, strict)
37 return "(%s)" % self._print(item)
38 else:
---> 39 return self._print(item)
40
41 def stringify(self, args, sep, level=0):
~\Anaconda3\lib\site-packages\sympy\printing\printer.py in _print(self, expr, **kwargs)
329 printmethod = getattr(self, printmethodname, None)
330 if printmethod is not None:
--> 331 return printmethod(expr, **kwargs)
332 # Unknown object, fall back to the emptyPrinter.
333 return self.emptyPrinter(expr)
~\Anaconda3\lib\site-packages\sympy\printing\numpy.py in _print_Integral(self, e)
452
453 def _print_Integral(self, e):
--> 454 integration_vars, limits = _unpack_integral_limits(e)
455
456 if len(limits) == 1:
~\Anaconda3\lib\site-packages\sympy\printing\pycode.py in _unpack_integral_limits(integral_expr)
546 integration_var, lower_limit, upper_limit = integration_range
547 else:
--> 548 raise NotImplementedError("Only definite integrals are supported")
549 integration_vars.append(integration_var)
550 limits.append((lower_limit, upper_limit))
NotImplementedError: Only definite integrals are supported
Integral cannot be evaluated numerically, see CIE4140_Lecture_13_Part_1_Python_seperate_q
Now we plot the amplitude-frequency response functions at two locations along the string for the two load shapes
AFRF_second_normal_mode = sp.Abs(W_to_second_normal_mode.subs(x,3/4))
display(AFRF_second_normal_mode.evalf())
AFRF can neither be evaluated