rigidRotor3DFWBW.py

You can view and download this file on Github: rigidRotor3DFWBW.py

  1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2# This is an EXUDYN example
  3#
  4# Details:  Example with 3D rotor; rotates around X-axis 
  5#           showing forward (FW) and backward (BW) whirls and FW/BW whirl resonances
  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
 22from math import cos, sin
 23
 24import time
 25import numpy as np
 26
 27SC = exu.SystemContainer()
 28mbs = SC.AddSystem()
 29print('EXUDYN version='+exu.config.Version())
 30
 31L=1                     #rotor axis length
 32isSymmetric = True
 33symStr = "General"
 34if isSymmetric:
 35    L0 = 0.5            #0.5 (symmetric rotor); position of rotor on x-axis
 36    symStr = "Laval"
 37    s = "symmetric"
 38else :
 39    L0 = 0.9            #default: 0.9m; position of rotor on x-axis
 40    s = "unsymmetric"
 41    
 42L1 = L-L0               #
 43m = 2                   #mass in kg
 44r = 0.5*1.5             #radius for disc mass distribution
 45lRotor = 0.2            #length of rotor disk
 46k = 800                 #stiffness of (all/both) springs in rotor in N/m
 47Jxx = 0.5*m*r**2        #polar moment of inertia 
 48Jyyzz = 0.25*m*r**2 + 1/12.*m*lRotor**2      #moment of inertia for y and z axes
 49
 50omega0=np.sqrt(2*k/m) #linear system
 51
 52D0 = 0.002              #dimensionless damping
 53d = 2*omega0*D0*m       #damping constant in N/(m/s)
 54
 55f0 = 0*omega0/(2*np.pi) #frequency start (Hz)
 56f1 = 2.*omega0/(2*np.pi) #frequency end (Hz)
 57
 58torque = 0.2*2            #driving torque; Nm ; 0.1Nm does not surpass critical speed; 0.2Nm works
 59eps = 2e-3*0.           #0.74; excentricity of mass in y-direction
 60                        #symmetric rotor: 2e-3 gives large oscillations;
 61                        #symmetric rotor: 0.74*2e-3 shows kink in runup curve
 62
 63omegaInitial = 0*4*omega0 #initial rotation speed in rad/s
 64
 65tEnd = 20              #end time of simulation
 66steps = int(tEnd*1000)           #number of steps
 67
 68modeStr = "BW" #"FW" or "BW"
 69sign = 1
 70if modeStr == "BW": sign = -1
 71
 72fRes = omega0/(2*np.pi)
 73print('symmetric rotor resonance frequency (Hz)= '+str(fRes))
 74#print('runup over '+str(tEnd)+' seconds, fStart='+str(f0)+'Hz, fEnd='+str(f1)+'Hz')
 75
 76#3D load vector
 77loadFact = 1
 78n1 = 0 #rotor node number, will be defined later
 79def UFload(mbs, t, load):
 80    #compute angle of rotation (only true if rotation about 1 axis)
 81    phi = mbs.GetNodeOutput(nodeNumber=n1, variableType=exu.OutputVariableType.Rotation)[0]
 82    return [0, sign*loadFact*cos(phi), loadFact*sin(phi)]
 83
 84#background1 = graphics.BrickXYZ(0,0,0,.5,0.5,0.5,[0.3,0.3,0.9,1])
 85
 86#draw RGB-frame at origin
 87p=[0,0,0]
 88lFrame = 0.9
 89tFrame = 0.01
 90backgroundX = graphics.Cylinder(p,[lFrame,0,0],tFrame,[0.9,0.3,0.3,1],12)
 91backgroundY = graphics.Cylinder(p,[0,lFrame,0],tFrame,[0.3,0.9,0.3,1],12)
 92backgroundZ = graphics.Cylinder(p,[0,0,lFrame],tFrame,[0.3,0.3,0.9,1],12)
 93
 94#visualize forces:
 95lVec = r*0.8
 96f1=0.08 #arrow size
 97f2=0.04 #arrow size 2
 98rigid = 0 #will be set later!
 99#ground user function, but draws load on body
100def UFgraphics(mainSystem, bodyNr):
101    t=mainSystem.systemData.GetTime()
102    #get rotation for rigid body:
103    rot = mbs.GetObjectOutputBody(rigid, exu.OutputVariableType.Rotation, 
104                                [0,0,0], exu.ConfigurationType.Visualization)
105    omega = mbs.GetObjectOutputBody(rigid, exu.OutputVariableType.AngularVelocity, 
106                                [0,0,0], exu.ConfigurationType.Visualization)
107    phi = rot[0]
108    phi += 0.9*0.05*omega[0] #graphics is always delayed ...
109    #print("rot=", phi)
110
111    #g0=graphics.Sphere(point=p0,radius=0.01, color=graphics.color.green)
112    #g1=graphics.Sphere(point=p1,radius=0.01, color=graphics.color.red)
113    xVec = 0.5+lRotor
114    p0 = [xVec,0,0]
115    p1 = [xVec,sign*lVec*cos(phi), lVec*sin(phi)]
116    p2 = [xVec,sign*(1-f1)*lVec*cos(phi)-f2*lVec*sin(phi), (1-f1)*lVec*sin(phi)+f2*sign*lVec*cos(phi)]
117    p3 = [xVec,sign*(1-f1)*lVec*cos(phi)+f2*lVec*sin(phi), (1-f1)*lVec*sin(phi)-f2*sign*lVec*cos(phi)]
118    gLine = {'type':'Line', 'data': p0+p1+p2+p1+p3, 'color':graphics.color.red}
119    return [gLine]#,g0,g1] #return list of graphics data
120
121mbs.AddObject(ObjectGround(referencePosition= [0,0,0], 
122                           visualization=VObjectGround(graphicsDataUserFunction=UFgraphics)))
123
124#rotor is rotating around x-axis
125ep0 = eulerParameters0 #no rotation
126ep_t0 = AngularVelocity2EulerParameters_t([omegaInitial,0,0], ep0)
127print(ep_t0)
128
129p0 = [L0-0.5*L,eps,0] #reference position
130v0 = [0.,0.,0.] #initial translational velocity
131
132#node for Rigid2D body: px, py, phi:
133n1=mbs.AddNode(NodeRigidBodyEP(referenceCoordinates = p0+ep0, initialVelocities=v0+list(ep_t0)))
134
135#ground nodes
136nGround0=mbs.AddNode(NodePointGround(referenceCoordinates = [-L/2,0,0]))
137nGround1=mbs.AddNode(NodePointGround(referenceCoordinates = [ L/2,0,0]))
138
139#add mass point (this is a 3D object with 3 coordinates):
140gRotor = graphics.Cylinder([-lRotor*0.5,0,0],[lRotor,0,0],r,[0.3,0.3,0.9,1],128)
141gRotor2 = graphics.Cylinder([-L0,0,0],[L,0,0],r*0.05,[0.3,0.3,0.9,1],16)
142gRotor3 = [backgroundX, backgroundY, backgroundZ]
143rigid = mbs.AddObject(RigidBody(mass=m, inertia=[Jxx,Jyyzz,Jyyzz,0,0,0], nodeNumber = n1, visualization=VObjectRigidBody2D(graphicsData=[gRotor, gRotor2]+gRotor3)))
144
145mbs.AddSensor(SensorBody(bodyNumber=rigid, 
146                         fileName='solution/runupDisplacement'+modeStr+'.txt',
147                         outputVariableType=exu.OutputVariableType.Displacement))
148mbs.AddSensor(SensorBody(bodyNumber=rigid, 
149                         fileName='solution/runupAngularVelocity'+modeStr+'.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]))
164mbs.AddObject(CartesianSpringDamper(markerNumbers=[groundMarker1, rotorAxisMarker1], 
165                                   stiffness=[0,k,k], damping=[0, d, d])) #do not constrain x-axis twice
166
167#coordinate markers for loads:
168rotorMarkerUy=mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate=1))
169rotorMarkerUz=mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate=2))
170
171#add torque:
172rotorRigidMarker =mbs.AddMarker(MarkerBodyRigid(bodyNumber=rigid, localPosition=[0,0,0]))
173mbs.AddLoad(Torque(markerNumber=rotorRigidMarker, 
174                   loadVector=[torque,0,0],
175                   visualization={'show':False}))
176
177#BW/FW load vector:
178mbs.AddLoad(Force(markerNumber=rotorRigidMarker, 
179                  loadVector=[0,0,0],
180                  loadVectorUserFunction=UFload))
181
182#print(mbs)
183mbs.Assemble()
184#mbs.systemData.Info()
185
186simulationSettings = exu.SimulationSettings()
187simulationSettings.solution.file.writePeriod = 1e-5  #output interval
188simulationSettings.solution.sensors.writePeriod = 1e-5  #output interval
189
190simulationSettings.solution.file.information = "Runup of "+s+" rotor: "+modeStr + ", " + symStr
191
192simulationSettings.timeIntegration.numberOfSteps = steps
193simulationSettings.timeIntegration.endTime = tEnd
194simulationSettings.timeIntegration.generalizedAlpha.useIndex2Constraints = True
195simulationSettings.timeIntegration.generalizedAlpha.useNewmark = True
196
197simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 1
198
199#create animations (causes slow simulation):
200createAnimation=True
201if createAnimation:
202    simulationSettings.solution.recordImagesInterval = 0.05
203    SC.visualizationSettings.exportImages.saveImageFileName = "images/frame"
204    SC.visualizationSettings.view0.window.renderWindowSize = [1600,1080]
205    SC.visualizationSettings.openGL.multiSampling = 4
206    
207#visualize loads:
208# SC.visualizationSettings.loads.fixedLoadSize=False
209# SC.visualizationSettings.loads.loadSizeFactor=100
210# SC.visualizationSettings.loads.drawSimplified = False
211
212if True:
213    SC.renderer.Start()              #start graphics visualization
214    SC.renderer.DoIdleTasks()    #wait for pressing SPACE bar to continue
215    
216    #start solver:
217    mbs.SolveDynamic(simulationSettings)
218    
219    #SC.renderer.DoIdleTasks()#wait for pressing 'Q' to quit
220    SC.renderer.Stop()               #safely close rendering window!
221    
222    #evaluate final (=current) output values
223    u = mbs.GetNodeOutput(n1, exu.OutputVariableType.AngularVelocity)
224    print('omega final (Hz)=',(1./(2.*np.pi))*u)
225    #print('displacement=',u[0])
226
227
228##+++++++++++++++++++++++++++++++++++++++++++++++++++++
229import matplotlib.pyplot as plt
230import matplotlib.ticker as ticker
231
232if False:
233    plt.close('all') #close all plots
234
235        
236    dataDispFW = np.loadtxt(OutputFilePath('solution/runupDisplacementFW.txt'), comments='#', delimiter=',')
237    dataOmegaFW = np.loadtxt(OutputFilePath('solution/runupAngularVelocityFW.txt'), comments='#', delimiter=',')
238    dataDispBW = np.loadtxt(OutputFilePath('solution/runupDisplacementBW.txt'), comments='#', delimiter=',')
239    dataOmegaBW = np.loadtxt(OutputFilePath('solution/runupAngularVelocityBW.txt'), comments='#', delimiter=',')
240    plt.rcParams.update({'font.size': 12})
241
242    if False:
243        plt.plot(dataDispFW[:,0], dataDispFW[:,3], 'r-', label='FW') #numerical solution
244        plt.plot(dataDispBW[:,0], dataDispBW[:,3], 'b-', label='BW') #numerical solution
245        plt.xlabel("time (s)")
246        plt.ylabel("z-displacement (m)")
247        ax=plt.gca() # get current axes
248        ax.grid(True, 'major', 'both')
249        ax.xaxis.set_major_locator(ticker.MaxNLocator(10)) 
250        ax.yaxis.set_major_locator(ticker.MaxNLocator(10)) 
251        plt.legend()
252        plt.tight_layout()
253
254    plt.figure()
255    plt.plot((1/(2*np.pi))*dataOmegaFW[:,1], dataDispFW[:,3], 'r-', label='FW', linewidth=0.7) #numerical solution
256    plt.plot((1/(2*np.pi))*dataOmegaBW[:,1], dataDispBW[:,3], 'b-', label='BW', linewidth=0.7) #numerical solution
257    plt.xlabel("angular velocity (1/s)")
258    plt.ylabel("z-displacement (m)")
259    ax=plt.gca() # get current axes
260    ax.grid(True, 'major', 'both')
261    ax.xaxis.set_major_locator(ticker.MaxNLocator(10)) 
262    ax.yaxis.set_major_locator(ticker.MaxNLocator(10)) 
263    plt.legend()
264    plt.tight_layout()
265    
266    #save figure:
267    #plt.savefig("rotorBWFWrunup"+symStr+".pdf")
268
269    # plt.figure()
270    # plt.plot(dataOmegaFW[:,0], (1/(2*np.pi))*dataOmegaFW[:,1], 'r-') #numerical solution
271    # plt.xlabel("time (s)")
272    # plt.ylabel("angular velocity (1/s)")
273    # ax=plt.gca() # get current axes
274    # ax.grid(True, 'major', 'both')
275    # ax.xaxis.set_major_locator(ticker.MaxNLocator(10)) 
276    # ax.yaxis.set_major_locator(ticker.MaxNLocator(10)) 
277    # plt.tight_layout()
278
279    # plt.figure()
280    # plt.plot(dataDispFW[:,2], dataDispFW[:,3], 'r-') #numerical solution
281    # plt.xlabel("y-displacement (m)")
282    # plt.ylabel("z-displacement (m)")
283    # ax=plt.gca() # get current axes
284    # ax.grid(True, 'major', 'both')
285    # ax.xaxis.set_major_locator(ticker.MaxNLocator(10)) 
286    # ax.yaxis.set_major_locator(ticker.MaxNLocator(10)) 
287    # plt.tight_layout()
288    
289    #plt.plot(data[n-500:n-1,1], data[n-500:n-1,2], 'r-') #numerical solution
290    
291    plt.show()