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