rigidRotor3DbasicBehaviour.py
You can view and download this file on Github: rigidRotor3DbasicBehaviour.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: Example with 3D rotor, showing basic behaviour of rotor
5# show COM, unbalance for low, critical and high rotation speeds
6#
7# Author: Johannes Gerstmayr
8# Date: 2019-12-05
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#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13import sys
14sys.path.append('../TestModels') #for modelUnitTest as this example may be used also as a unit test
15
16import exudyn as exu
17from exudyn.itemInterface import *
18from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
19import exudyn.graphics as graphics #only import if it does not conflict
20
21import time
22import numpy as np
23
24SC = exu.SystemContainer()
25mbs = SC.AddSystem()
26print('EXUDYN version='+exu.GetVersionString())
27
28L=1 #rotor axis length
29isSymmetric = True
30if isSymmetric:
31 L0 = 0.5 #0.5 (symmetric rotor); position of rotor on x-axis
32else :
33 L0 = 0.9 #default: 0.9m; position of rotor on x-axis
34L1 = L-L0 #
35m = 2 #mass in kg
36r = 0.5*1.5 #radius for disc mass distribution
37lRotor = 0.2 #length of rotor disk
38k = 800 #stiffness of (all/both) springs in rotor in N/m
39Jxx = 0.5*m*r**2 #polar moment of inertia
40Jyyzz = 0.25*m*r**2 + 1/12.*m*lRotor**2 #moment of inertia for y and z axes
41
42omega0=np.sqrt(2*k/m) #linear system
43
44D0 = 0.002 #dimensionless damping
45d = 2*omega0*D0*m #damping constant in N/(m/s)
46
47f0 = 0*omega0/(2*np.pi) #frequency start (Hz)
48f1 = 2.*omega0/(2*np.pi) #frequency end (Hz)
49
50torque = 0*0.2 #driving torque; Nm ; 0.1Nm does not surpass critical speed; 0.2Nm works
51eps = 10e-3 # excentricity of mass in y-direction
52 #symmetric rotor: 2e-3 gives large oscillations;
53 #symmetric rotor: 0.74*2e-3 shows kink in runup curve
54#k*=1000
55
56modeStr=['slow (omega0/2)',
57 'critical (omega0)',
58 'fast (2*omega0)' ]
59mode = 2
60
61#add constraint on euler parameters or euler angles
62#add three cases
63
64if mode == 0:
65 omegaInitial = 0.5*omega0 #initial rotation speed in rad/s
66elif mode == 1:
67 omegaInitial = 1*omega0 #initial rotation speed in rad/s
68 eps *= 0.1
69 d *= 10
70elif mode == 2:
71 omegaInitial = 2*omega0 #initial rotation speed in rad/s
72
73tEnd = 50 #end time of simulation
74steps = 50000 #number of steps
75
76fRes = omega0/(2*np.pi)
77print('symmetric rotor resonance frequency (Hz)= '+str(fRes))
78print('omega intial (Hz)= '+str(omegaInitial/(2*np.pi)))
79#print('runup over '+str(tEnd)+' seconds, fStart='+str(f0)+'Hz, fEnd='+str(f1)+'Hz')
80
81
82# #user function for load
83# def userLoad(t, load):
84# #return load*np.sin(0.5*omega0*t) #gives resonance
85# if t>40: time.sleep(0.02) #make simulation slower
86# return load*Sweep(t, tEnd, f0, f1)
87# #return load*Sweep(t, tEnd, f1, f0) #backward sweep
88
89# #backward whirl excitation:
90# amp = 0.10 #in resonance: *0.01
91# def userLoadBWy(t, load):
92# return load*SweepCos(t, tEnd, f0, f1) #negative sign: BW, positive sign: FW
93# def userLoadBWz(t, load):
94# return load*Sweep(t, tEnd, f0, f1)
95#def userLoadBWx(t, load):
96# return load*np.sin(omegaInitial*t)
97#def userLoadBWy(t, load):
98# return -load*np.cos(omegaInitial*t) #negative sign: FW, positive sign: BW
99
100#background1 = graphics.BrickXYZ(0,0,0,.5,0.5,0.5,[0.3,0.3,0.9,1])
101
102#draw RGB-frame at origin
103p=[0,0,0]
104rDraw = 0.05*r
105lFrame = rDraw*1.2
106tFrame = 0.01*0.15
107backgroundX = graphics.Cylinder(p,[lFrame,0,0],tFrame,[0.9,0.3,0.3,1],12)
108backgroundY = graphics.Cylinder(p,[0,lFrame,0],tFrame*0.5,[0.3,0.9,0.3,1],12)
109backgroundZ = graphics.Cylinder(p,[0,0,lFrame],tFrame*0.5,[0.3,0.3,0.9,1],12)
110black=[0,0,0,1]
111textCOM = {'type':'Text', 'text': 'COM', 'color': black, 'position': [lFrame*1.1,0,0]}
112textSHAFT = {'type':'Text', 'text': 'SHAFT', 'color': black, 'position': [L-L0+0.1,-eps,0]}
113textY = {'type':'Text', 'text': 'Y', 'color': black, 'position': [0,lFrame*1.05,0]}
114textZ = {'type':'Text', 'text': 'Z', 'color': black, 'position': [0,0,lFrame*1.05]}
115
116#rotor is rotating around x-axis
117ep0 = eulerParameters0 #no rotation
118ep_t0 = AngularVelocity2EulerParameters_t([omegaInitial,0,0], ep0)
119print(ep_t0)
120
121p0 = [L0-0.5*L,eps,0] #reference position, displaced by eccentricity eps !
122v0 = [0.,0.,0.] #initial translational velocity
123
124#node for Rigid2D body: px, py, phi:
125n1=mbs.AddNode(NodeRigidBodyEP(referenceCoordinates = p0+ep0,
126 initialVelocities=v0+list(ep_t0)))
127
128#ground nodes
129nGround0=mbs.AddNode(NodePointGround(referenceCoordinates = [-L/2,0,0]))
130nGround1=mbs.AddNode(NodePointGround(referenceCoordinates = [ L/2,0,0]))
131
132#add mass point (this is a 3D object with 3 coordinates):
133gRotor = graphics.Cylinder([-lRotor*0.2,0,0],[lRotor*0.4,0,0],rDraw,
134 [0.3,0.3,0.9,1],128)
135gRotor2 = graphics.Cylinder([-L0,-eps,0],[L,0,0],r*0.01*0.25,[0.6,0.6,0.6,1],16)
136gRotorCOM = graphics.Cylinder([-lRotor*0.1,0,0],[lRotor*0.6*0.1,0,0],r*0.01*0.5,
137 [0.3,0.9,0.3,1],16)
138gRotor3 = [backgroundX, backgroundY, backgroundZ, textCOM, textY, textZ, textSHAFT]
139rigid = mbs.AddObject(RigidBody(physicsMass=m,
140 physicsInertia=[Jxx,Jyyzz,Jyyzz,0,0,0],
141 nodeNumber = n1,
142 visualization=VObjectRigidBody2D(graphicsData=[gRotor, gRotor2, gRotorCOM]+gRotor3)))
143
144mbs.AddSensor(SensorBody(bodyNumber=rigid,
145 fileName='solution/rotorDisplacement.txt',
146 localPosition=[0,-eps,0],
147 outputVariableType=exu.OutputVariableType.Displacement))
148# mbs.AddSensor(SensorBody(bodyNumber=rigid,
149# fileName='solution/rotorAngularVelocity.txt',
150# outputVariableType=exu.OutputVariableType.AngularVelocity))
151
152#marker for ground (=fixed):
153groundMarker0=mbs.AddMarker(MarkerNodePosition(nodeNumber= nGround0))
154groundMarker1=mbs.AddMarker(MarkerNodePosition(nodeNumber= nGround1))
155
156#marker for rotor axis and support:
157rotorAxisMarker0 =mbs.AddMarker(MarkerBodyPosition(bodyNumber=rigid, localPosition=[-L0,-eps,0]))
158rotorAxisMarker1 =mbs.AddMarker(MarkerBodyPosition(bodyNumber=rigid, localPosition=[ L1,-eps,0]))
159
160
161#++++++++++++++++++++++++++++++++++++
162mbs.AddObject(CartesianSpringDamper(markerNumbers=[groundMarker0, rotorAxisMarker0],
163 stiffness=[k,k,k], damping=[d, d, d],
164 visualization=VCartesianSpringDamper(drawSize=0.002)))
165mbs.AddObject(CartesianSpringDamper(markerNumbers=[groundMarker1, rotorAxisMarker1],
166 stiffness=[0,k,k], damping=[0, d, d],
167 visualization=VCartesianSpringDamper(drawSize=0.002))) #do not constrain x-axis twice
168
169
170#add torque:
171# rotorRigidMarker =mbs.AddMarker(MarkerBodyRigid(bodyNumber=rigid, localPosition=[0,0,0]))
172# mbs.AddLoad(Torque(markerNumber=rotorRigidMarker, loadVector=[torque,0,0]))
173
174#constant velocity constraint:
175constantRotorVelocity = True
176if constantRotorVelocity :
177 mRotationAxis = mbs.AddMarker(MarkerNodeRotationCoordinate(nodeNumber = n1, rotationCoordinate=0))
178 mGroundCoordinate =mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= nGround0, coordinate=0))
179 mbs.AddObject(CoordinateConstraint(markerNumbers=[mGroundCoordinate, mRotationAxis],
180 offset=omegaInitial, velocityLevel=True,
181 visualization=VCoordinateConstraint(show=False))) #gives equation omegaMarker1 = offset
182
183
184#print(mbs)
185mbs.Assemble()
186#mbs.systemData.Info()
187
188simulationSettings = exu.SimulationSettings()
189simulationSettings.solutionSettings.solutionWritePeriod = 1e-5 #output interval
190simulationSettings.solutionSettings.sensorsWritePeriod = 1e-5 #output interval
191
192descrStr = "Laval rotor, resonance="+str(round(fRes,3))+", "+modeStr[mode]
193simulationSettings.solutionSettings.solutionInformation = descrStr
194
195simulationSettings.timeIntegration.numberOfSteps = steps
196simulationSettings.timeIntegration.endTime = tEnd
197simulationSettings.timeIntegration.generalizedAlpha.useIndex2Constraints = True
198simulationSettings.timeIntegration.generalizedAlpha.useNewmark = True
199
200simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 1
201SC.visualizationSettings.window.renderWindowSize = [1600,1080]
202SC.visualizationSettings.general.textSize = 22
203
204exu.StartRenderer() #start graphics visualization
205mbs.WaitForUserToContinue() #wait for pressing SPACE bar to continue
206
207#simulate some time to get steady-state solution:
208mbs.SolveDynamic(simulationSettings)
209state = mbs.systemData.GetSystemState()
210
211#now simulate the steady state solution and record
212simulationSettings.timeIntegration.numberOfSteps = 10000
213simulationSettings.timeIntegration.endTime = 2.5
214
215#create animations (causes slow simulation):
216createAnimation=True
217if createAnimation:
218 mbs.WaitForUserToContinue() #wait for pressing SPACE bar to continue
219 simulationSettings.solutionSettings.recordImagesInterval = 0.01
220 if mode == 1:
221 simulationSettings.timeIntegration.endTime = 1
222 simulationSettings.solutionSettings.recordImagesInterval = 0.0025
223 if mode == 2:
224 simulationSettings.timeIntegration.endTime = 0.5
225 simulationSettings.solutionSettings.recordImagesInterval = 0.001
226
227 SC.visualizationSettings.exportImages.saveImageFileName = "images/frame"
228
229 mbs.systemData.SetSystemState(state, configuration=exu.ConfigurationType.Initial)
230 mbs.SolveDynamic(simulationSettings)
231
232#SC.WaitForRenderEngineStopFlag()#wait for pressing 'Q' to quit
233exu.StopRenderer() #safely close rendering window!
234
235#evaluate final (=current) output values
236u = mbs.GetNodeOutput(n1, exu.OutputVariableType.AngularVelocity)
237print('omega final (Hz)=',u/(2*np.pi))
238#print('displacement=',u[0])
239c = mbs.GetNodeOutput(n1, exu.OutputVariableType.Coordinates)
240c_t = mbs.GetNodeOutput(n1, exu.OutputVariableType.Coordinates_t)
241print("nc=",c)
242print("nc_t=",c_t)
243
244##+++++++++++++++++++++++++++++++++++++++++++++++++++++
245import matplotlib.pyplot as plt
246import matplotlib.ticker as ticker
247
248if True:
249 plt.close('all') #close all plots
250
251 dataDisp = np.loadtxt('solution/rotorDisplacement.txt', comments='#', delimiter=',')
252
253 plt.plot(dataDisp[:,0], dataDisp[:,3], 'b-') #numerical solution
254 plt.xlabel("time (s)")
255 plt.ylabel("z-displacement (m)")
256
257 plt.figure()
258 plt.plot(dataDisp[:,2], dataDisp[:,3], 'r-') #numerical solution
259 plt.xlabel("y-displacement (m)")
260 plt.ylabel("z-displacement (m)")
261
262 #plt.plot(data[n-500:n-1,1], data[n-500:n-1,2], 'r-') #numerical solution
263
264 ax=plt.gca() # get current axes
265 ax.grid(True, 'major', 'both')
266 ax.xaxis.set_major_locator(ticker.MaxNLocator(10))
267 ax.yaxis.set_major_locator(ticker.MaxNLocator(10))
268 plt.tight_layout()
269 plt.show()