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