springDamperTutorial.py
You can view and download this file on Github: springDamperTutorial.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 with coordinateSpringDamper connector
5#
6# Author: Johannes Gerstmayr
7# Date: 2019-11-15
8#
9# 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.
10#
11#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12
13#%%++++++++++++++++++++++++++++++++++
14import exudyn as exu
15from exudyn.utilities import Point, NodePointGround, MassPoint, MarkerNodeCoordinate,\
16 CoordinateSpringDamper, LoadCoordinate, SensorObject
17#to be sure to have all items and functions imported, just do:
18#from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
19import exudyn.graphics as graphics #only import if it does not conflict
20import numpy as np #for postprocessing
21
22SC = exu.SystemContainer()
23mbs = SC.AddSystem()
24
25print('EXUDYN version='+exu.GetVersionString(True))
26
27L=0.5
28mass = 1.6 #mass in kg
29spring = 4000 #stiffness of spring-damper in N/m
30damper = 8 #damping constant in N/(m/s)
31
32u0=-0.08 #initial displacement
33v0=1 #initial velocity
34f =80 #force on mass
35x0=f/spring #static displacement
36
37print('resonance frequency = '+str(np.sqrt(spring/mass)))
38print('static displacement = '+str(x0))
39
40#node for 3D mass point:
41n1=mbs.AddNode(Point(referenceCoordinates = [L,0,0],
42 initialCoordinates = [u0,0,0],
43 initialVelocities= [v0,0,0]))
44
45#ground node
46nGround=mbs.AddNode(NodePointGround(referenceCoordinates = [0,0,0]))
47
48#add mass point (this is a 3D object with 3 coordinates):
49massPoint = mbs.AddObject(MassPoint(physicsMass = mass, nodeNumber = n1))
50
51#marker for ground (=fixed):
52groundMarker=mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= nGround, coordinate = 0))
53#marker for springDamper for first (x-)coordinate:
54nodeMarker =mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate = 0))
55
56#spring-damper between two marker coordinates
57nC = mbs.AddObject(CoordinateSpringDamper(markerNumbers = [groundMarker, nodeMarker],
58 stiffness = spring, damping = damper))
59
60#add load:
61mbs.AddLoad(LoadCoordinate(markerNumber = nodeMarker,
62 load = f))
63
64#add sensor:
65mbs.AddSensor(SensorObject(objectNumber=nC, fileName='solution/groundForce.txt',
66 outputVariableType=exu.OutputVariableType.Force))
67
68print(mbs) #show system properties
69mbs.Assemble()
70
71tEnd = 1 #end time of simulation
72h = 0.001 #step size; leads to 1000 steps
73
74simulationSettings = exu.SimulationSettings()
75simulationSettings.solutionSettings.solutionWritePeriod = 5e-3 #output interval general
76simulationSettings.solutionSettings.sensorsWritePeriod = 5e-3 #output interval of sensors
77simulationSettings.timeIntegration.numberOfSteps = int(tEnd/h) #must be integer
78simulationSettings.timeIntegration.endTime = tEnd
79
80simulationSettings.timeIntegration.verboseMode = 1 #show some solver output
81simulationSettings.displayComputationTime = True #show how fast
82
83simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 1
84
85#add some drawing parameters for this example
86SC.visualizationSettings.nodes.drawNodesAsPoint=False
87SC.visualizationSettings.nodes.defaultSize=0.1
88
89exu.StartRenderer() #start graphics visualization
90#mbs.WaitForUserToContinue() #wait for pressing SPACE bar or 'Q' to continue
91
92#start solver:
93mbs.SolveDynamic(simulationSettings)
94
95#SC.WaitForRenderEngineStopFlag() #wait for pressing 'Q' to quit
96exu.StopRenderer() #safely close rendering window!
97
98#evaluate final (=current) output values
99u = mbs.GetNodeOutput(n1, exu.OutputVariableType.Position)
100print('displacement=',u)
101
102#%%+++++++++++++++++++++++++++++++++++++++++++++++++++++
103#compute exact solution:
104import matplotlib.pyplot as plt
105import matplotlib.ticker as ticker
106
107omega0 = np.sqrt(spring/mass) #eigen frequency of undamped system
108dRel = damper/(2*np.sqrt(spring*mass)) #dimensionless damping
109omega = omega0*np.sqrt(1-dRel**2) #eigen frequency of damped system
110C1 = u0-x0 #static solution needs to be considered!
111C2 = (v0+omega0*dRel*C1) / omega #C1, C2 are coeffs for solution
112steps = int(tEnd/h)
113
114refSol = np.zeros((steps+1,2))
115for i in range(0,steps+1):
116 t = tEnd*i/steps
117 refSol[i,0] = t
118 refSol[i,1] = np.exp(-omega0*dRel*t)*(C1*np.cos(omega*t) + C2*np.sin(omega*t))+x0
119
120data = np.loadtxt('coordinatesSolution.txt', comments='#', delimiter=',')
121plt.plot(data[:,0], data[:,1], 'b-', label='displacement (m); numerical solution')
122plt.plot(refSol[:,0], refSol[:,1], 'r-', label='displacement (m); exact solution')
123
124#show force in constraint/support:
125data = np.loadtxt('solution/groundForce.txt', comments='#', delimiter=',')
126plt.plot(data[:,0], data[:,1]*1e-3, 'g-', label='force (kN)') #numerical solution
127
128ax=plt.gca() # get current axes
129ax.grid(True, 'major', 'both')
130ax.xaxis.set_major_locator(ticker.MaxNLocator(10))
131ax.yaxis.set_major_locator(ticker.MaxNLocator(10))
132plt.legend() #show labels as legend
133plt.tight_layout()
134plt.show()