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