springDamperTutorialNew.py
You can view and download this file on Github: springDamperTutorialNew.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: This is the file for the EXUDYN first tutorial example showing a simple masspoint a SpringDamper
5#
6# Author: Johannes Gerstmayr
7# Date: 2023-05-15
8# Update: 2024-06-04 (now fully using create functions)
9#
10# Copyright:This file is part of Exudyn. Exudyn is free software. You can redistribute it and/or modify it under the terms of the Exudyn license. See 'LICENSE.txt' for more details.
11#
12#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13
14
15import exudyn as exu
16from exudyn.utilities import SensorBody, SensorObject
17import exudyn.graphics as graphics #only import if it does not conflict
18
19import numpy as np #for postprocessing
20
21SC = exu.SystemContainer()
22mbs = SC.AddSystem()
23
24print('EXUDYN version='+exu.GetVersionString())
25
26L=0.5
27mass = 1.6 #mass in kg
28spring = 4000 #stiffness of spring-damper in N/m
29damper = 8 #damping constant in N/(m/s)
30
31u0=-0.08 #initial displacement
32v0=1 #initial velocity
33f =80 #force on mass
34x0=f/spring #static displacement
35
36print('resonance frequency = '+str(np.sqrt(spring/mass)))
37print('static displacement = '+str(x0))
38
39oMass = mbs.CreateMassPoint(referencePosition=[L,0,0],
40 initialDisplacement = [u0,0,0],
41 initialVelocity= [v0,0,0],
42 physicsMass=mass) #force created via gravity
43
44oGround = mbs.CreateGround()
45
46#create spring damper with reference length computed from reference positions (=L)
47oSD = mbs.CreateSpringDamper(bodyOrNodeList=[oMass, oGround],
48 stiffness = spring, damping = damper)
49
50#add load on body:
51mbs.CreateForce(bodyNumber = oMass, loadVector = [f,0,0])
52
53#add sensors:
54sForce = mbs.AddSensor(SensorObject(objectNumber=oSD, storeInternal=True,
55 outputVariableType=exu.OutputVariableType.ForceLocal))
56sDisp = mbs.AddSensor(SensorBody(bodyNumber=oMass, storeInternal=True,
57 outputVariableType=exu.OutputVariableType.Displacement))
58
59print(mbs)
60mbs.Assemble()
61
62tEnd = 1 #end time of simulation
63h = 0.001 #step size; leads to 1000 steps
64
65simulationSettings = exu.SimulationSettings()
66simulationSettings.solutionSettings.solutionWritePeriod = 5e-3 #output interval general
67simulationSettings.solutionSettings.sensorsWritePeriod = 5e-3 #output interval of sensors
68simulationSettings.timeIntegration.numberOfSteps = int(tEnd/h) #must be integer
69simulationSettings.timeIntegration.endTime = tEnd
70
71#add some drawing parameters for this example
72SC.visualizationSettings.nodes.drawNodesAsPoint=False
73SC.visualizationSettings.nodes.defaultSize=0.1
74
75exu.StartRenderer() #start graphics visualization
76mbs.WaitForUserToContinue() #wait for pressing SPACE bar to continue
77
78#start solver:
79mbs.SolveDynamic(simulationSettings,
80 solverType=exu.DynamicSolverType.TrapezoidalIndex2)
81
82SC.WaitForRenderEngineStopFlag()#wait for pressing 'Q' to quit
83exu.StopRenderer() #safely close rendering window!
84
85#evaluate final (=current) output values
86u = mbs.GetNodeOutput(0, exu.OutputVariableType.Position) #Node 0 is first node
87print('displacement=',u)
88
89#+++++++++++++++++++++++++++++++++++++++++++++++++++++
90#compute exact solution:
91
92omega0 = np.sqrt(spring/mass) #eigen frequency of undamped system
93dRel = damper/(2*np.sqrt(spring*mass)) #dimensionless damping
94omega = omega0*np.sqrt(1-dRel**2) #eigen frequency of damped system
95C1 = u0-x0 #static solution needs to be considered!
96C2 = (v0+omega0*dRel*C1) / omega #C1, C2 are coeffs for solution
97steps = int(tEnd/h)
98
99refSol = np.zeros((steps+1,2))
100for i in range(0,steps+1):
101 t = tEnd*i/steps
102 refSol[i,0] = t
103 refSol[i,1] = np.exp(-omega0*dRel*t)*(C1*np.cos(omega*t) + C2*np.sin(omega*t))+x0
104
105#use PlotSensor functionality to plot data:
106mbs.PlotSensor(sensorNumbers=[refSol], components=[0], labels='displacement (m); exact solution',
107 colorCodeOffset=2, closeAll=True) #color code offset to have same colors as in original example
108mbs.PlotSensor(sensorNumbers=[sDisp], components=[0], labels='displacement (m); numerical solution',
109 colorCodeOffset=0, newFigure=False)
110
111mbs.PlotSensor(sensorNumbers=[sForce], labels='force (kN)',
112 colorCodeOffset=1, factors=[1e-3], newFigure=False)