coordinateSpringDamper.py
You can view and download this file on Github: coordinateSpringDamper.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: Example with 1D spring-mass-damper system;
5# Compare viscous damping or friction (useFriction=True); includes exact reference solution
6#
7# Author: Johannes Gerstmayr
8# Date: 2019-08-15
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
14import exudyn as exu
15from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
16import exudyn.graphics as graphics #only import if it does not conflict
17
18SC = exu.SystemContainer()
19mbs = SC.AddSystem()
20
21print('EXUDYN version='+exu.GetVersionString())
22useGraphics=True
23useFriction = False
24
25
26L=0.5
27mass = 1.6
28k = 4000
29omega0 = 50 # sqrt(4000/1.6)
30dRel = 0.05
31d = dRel * 2 * 80 #80=sqrt(1.6*4000)
32u0=-0.08
33v0=1
34f = 80
35x0 = f/k
36print('static value = '+str(x0))
37fFriction = 20 #force in Newton, only depends on direction of velocity
38#print('damping='+str(d))
39
40#node for mass point:
41n1=mbs.AddNode(Point(referenceCoordinates = [L,0,0], initialCoordinates = [u0,0,0], initialVelocities= [v0,0,0]))
42nGround=mbs.AddNode(NodePointGround(referenceCoordinates = [L,0,0]))
43
44#add mass points and ground object:
45objectGround = mbs.AddObject(ObjectGround(referencePosition = [0,0,0]))
46massPoint = mbs.AddObject(MassPoint(physicsMass = mass, nodeNumber = n1))
47
48#marker for constraint / springDamper
49
50#groundMarker = mbs.AddMarker(MarkerBodyPosition(bodyNumber = objectGround, localPosition= [0, 0, 0]))
51#bodyMarker = mbs.AddMarker(MarkerBodyPosition(bodyNumber = massPoint, localPosition= [0, 0, 0]))
52
53groundCoordinateMarker = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= nGround, coordinate = 0))
54nodeCoordinateMarker0 = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate = 0))
55nodeCoordinateMarker1 = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate = 1))
56nodeCoordinateMarker2 = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate = 2))
57
58#Spring-Dampers
59mbs.AddObject(CoordinateSpringDamperExt(markerNumbers = [groundCoordinateMarker, nodeCoordinateMarker0],
60 stiffness = k,
61 damping = d*(1-useFriction),
62 fDynamicFriction=0.2*fFriction*useFriction,
63 frictionProportionalZone=0.01)) #offset must be zero, because coordinates just represent the displacements
64mbs.AddObject(CoordinateSpringDamper(markerNumbers = [groundCoordinateMarker, nodeCoordinateMarker1], stiffness = k))
65mbs.AddObject(CoordinateSpringDamper(markerNumbers = [groundCoordinateMarker, nodeCoordinateMarker2], stiffness = k))
66
67
68#add loads:
69mbs.AddLoad(LoadCoordinate(markerNumber = nodeCoordinateMarker0, load = f))
70
71print(mbs)
72mbs.Assemble()
73
74simulationSettings = exu.SimulationSettings()
75tEnd = 1 #1
76steps = 1000 #1000
77simulationSettings.solutionSettings.solutionWritePeriod = 1e-3
78simulationSettings.timeIntegration.numberOfSteps = steps
79simulationSettings.timeIntegration.endTime = tEnd
80
81simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 1 #SHOULD work with 0.9 as well
82
83if useGraphics:
84 exu.StartRenderer()
85
86mbs.SolveDynamic(simulationSettings)
87
88if useGraphics:
89 SC.WaitForRenderEngineStopFlag()
90 exu.StopRenderer() #safely close rendering window!
91
92
93u = mbs.GetNodeOutput(n1, exu.OutputVariableType.Position)
94uCartesianSpringDamper= u[0] - L
95errorCartesianSpringDamper = uCartesianSpringDamper - 0.011834933407066539 #for 1000 steps, endtime=1; this is different from CartesianSpringDamper because of offset L (rounding errors around 1e-14)
96print('error cartesianSpringDamper=',errorCartesianSpringDamper)
97
98#return abs(errorCartesianSpringDamper)
99
100#+++++++++++++++++++++++++++++++++++++++++++++++++++++
101#exact solution:
102import numpy as np
103import matplotlib.pyplot as plt
104import matplotlib.ticker as ticker
105
106omega0 = np.sqrt(k/mass) #recompute for safety
107dRel = d/(2*np.sqrt(k*mass)) #recompute for safety
108omega = omega0*np.sqrt(1-dRel**2)
109C1 = u0-x0 #static solution needs to be considered!
110C2 = (v0+omega0*dRel*C1) / omega #C1 used instead of classical solution with u0, because x0 != 0 !!!
111
112refSol = np.zeros((steps+1,2))
113for i in range(0,steps+1):
114 t = tEnd*i/steps
115 refSol[i,0] = t
116 refSol[i,1] = np.exp(-omega0*dRel*t)*(C1*np.cos(omega*t) + C2*np.sin(omega*t))+x0
117
118print('refSol=',refSol[steps,1])
119print('error exact-numerical=',refSol[steps,1] - uCartesianSpringDamper)
120
121data = np.loadtxt('coordinatesSolution.txt', comments='#', delimiter=',')
122plt.plot(data[:,0], data[:,1], 'b-') #numerical solution
123plt.plot(refSol[:,0], refSol[:,1], 'r-') #exact solution
124
125ax=plt.gca() # get current axes
126ax.grid(True, 'major', 'both')
127ax.xaxis.set_major_locator(ticker.MaxNLocator(10)) #use maximum of 8 ticks on y-axis
128ax.yaxis.set_major_locator(ticker.MaxNLocator(10)) #use maximum of 8 ticks on y-axis
129plt.tight_layout()
130plt.show()