rigidRotor3Drunup.py

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

  1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2# This is an EXUDYN example
  3#
  4# Details:  Example with 3D rotor, showing runup
  5#
  6# Author:   Johannes Gerstmayr
  7# Date:     2019-12-05
  8#
  9# 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.
 10#
 11#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 12import sys
 13sys.path.append('../TestModels')            #for modelUnitTest as this example may be used also as a unit test
 14
 15import exudyn as exu
 16#a local run must not open a plot window when windows are suppressed (#2477)
 17if exu.special.userInterface.suppressPlots: import matplotlib; matplotlib.use('Agg')
 18from exudyn.itemInterface import *
 19from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
 20import exudyn.graphics as graphics
 21
 22import time
 23import numpy as np
 24
 25SC = exu.SystemContainer()
 26mbs = SC.AddSystem()
 27print('EXUDYN version='+exu.config.Version())
 28
 29L=1                     #rotor axis length
 30isSymmetric = True
 31if isSymmetric:
 32    L0 = 0.5            #0.5 (symmetric rotor); position of rotor on x-axis
 33else :
 34    L0 = 0.9            #default: 0.9m; position of rotor on x-axis
 35L1 = L-L0               #
 36m = 2                   #mass in kg
 37r = 0.5*1.5             #radius for disc mass distribution
 38lRotor = 0.2            #length of rotor disk
 39k = 800                 #stiffness of (all/both) springs in rotor in N/m
 40Jxx = 0.5*m*r**2        #polar moment of inertia 
 41Jyyzz = 0.25*m*r**2 + 1/12.*m*lRotor**2      #moment of inertia for y and z axes
 42
 43omega0=np.sqrt(2*k/m) #linear system
 44
 45D0 = 0.002              #dimensionless damping
 46d = 2*omega0*D0*m       #damping constant in N/(m/s)
 47
 48f0 = 0*omega0/(2*np.pi) #frequency start (Hz)
 49f1 = 2.*omega0/(2*np.pi) #frequency end (Hz)
 50
 51torque = 0.2            #driving torque; Nm ; 0.1Nm does not surpass critical speed; 0.2Nm works
 52eps = 2e-3*0.74         # excentricity of mass in y-direction
 53                        #symmetric rotor: 2e-3 gives large oscillations;
 54                        #symmetric rotor: 0.74*2e-3 shows kink in runup curve
 55
 56omegaInitial = 0*4*omega0 #initial rotation speed in rad/s
 57
 58tEnd = 200              #end time of simulation
 59steps = 40000           #number of steps
 60
 61fRes = omega0/(2*np.pi)
 62print('symmetric rotor resonance frequency (Hz)= '+str(fRes))
 63#print('runup over '+str(tEnd)+' seconds, fStart='+str(f0)+'Hz, fEnd='+str(f1)+'Hz')
 64
 65#linear frequency sweep evaluated at time t, for time interval [0, t1] and frequency interval [f0,f1];
 66def Sweep(t, t1, f0, f1):
 67    k = (f1-f0)/t1
 68    return np.sin(2*np.pi*(f0+k*0.5*t)*t) #take care of factor 0.5 in k*0.5*t, in order to obtain correct frequencies!!!
 69def SweepCos(t, t1, f0, f1):
 70    k = (f1-f0)/t1
 71    return np.cos(2*np.pi*(f0+k*0.5*t)*t) #take care of factor 0.5 in k*0.5*t, in order to obtain correct frequencies!!!
 72
 73# #user function for load
 74# def userLoad(t, load):
 75#     #return load*np.sin(0.5*omega0*t) #gives resonance
 76#     if t>40: time.sleep(0.02) #make simulation slower
 77#     return load*Sweep(t, tEnd, f0, f1)
 78#     #return load*Sweep(t, tEnd, f1, f0) #backward sweep
 79
 80# #backward whirl excitation:
 81# amp = 0.10  #in resonance: *0.01
 82# def userLoadBWy(t, load):
 83#     return load*SweepCos(t, tEnd, f0, f1) #negative sign: BW, positive sign: FW
 84# def userLoadBWz(t, load):
 85#     return load*Sweep(t, tEnd, f0, f1)
 86#def userLoadBWx(t, load):
 87#    return load*np.sin(omegaInitial*t)
 88#def userLoadBWy(t, load):
 89#    return -load*np.cos(omegaInitial*t) #negative sign: FW, positive sign: BW
 90
 91#background1 = graphics.BrickXYZ(0,0,0,.5,0.5,0.5,[0.3,0.3,0.9,1])
 92
 93#draw RGB-frame at origin
 94p=[0,0,0]
 95lFrame = 0.8
 96tFrame = 0.01
 97backgroundX = graphics.Cylinder(p,[lFrame,0,0],tFrame,[0.9,0.3,0.3,1],12)
 98backgroundY = graphics.Cylinder(p,[0,lFrame,0],tFrame,[0.3,0.9,0.3,1],12)
 99backgroundZ = graphics.Cylinder(p,[0,0,lFrame],tFrame,[0.3,0.3,0.9,1],12)
100#mbs.AddObject(ObjectGround(referencePosition= [0,0,0], visualization=VObjectGround(graphicsData= [backgroundX, backgroundY, backgroundZ])))
101
102#rotor is rotating around x-axis
103ep0 = eulerParameters0 #no rotation
104ep_t0 = AngularVelocity2EulerParameters_t([omegaInitial,0,0], ep0)
105print(ep_t0)
106
107p0 = [L0-0.5*L,eps,0] #reference position
108v0 = [0.,0.,0.] #initial translational velocity
109
110#node for Rigid2D body: px, py, phi:
111n1=mbs.AddNode(NodeRigidBodyEP(referenceCoordinates = p0+ep0, initialVelocities=v0+list(ep_t0)))
112
113#ground nodes
114nGround0=mbs.AddNode(NodePointGround(referenceCoordinates = [-L/2,0,0]))
115nGround1=mbs.AddNode(NodePointGround(referenceCoordinates = [ L/2,0,0]))
116
117#add mass point (this is a 3D object with 3 coordinates):
118gRotor = graphics.Cylinder([-lRotor*0.5,0,0],[lRotor,0,0],r,[0.3,0.3,0.9,1],128)
119gRotor2 = graphics.Cylinder([-L0,0,0],[L,0,0],r*0.05,[0.3,0.3,0.9,1],16)
120gRotor3 = [backgroundX, backgroundY, backgroundZ]
121rigid = mbs.AddObject(RigidBody(mass=m, inertia=[Jxx,Jyyzz,Jyyzz,0,0,0], nodeNumber = n1, visualization=VObjectRigidBody2D(graphicsData=[gRotor, gRotor2]+gRotor3)))
122
123mbs.AddSensor(SensorBody(bodyNumber=rigid, 
124                         fileName='solution/runupDisplacement.txt',
125                         outputVariableType=exu.OutputVariableType.Displacement))
126mbs.AddSensor(SensorBody(bodyNumber=rigid, 
127                         fileName='solution/runupAngularVelocity.txt',
128                         outputVariableType=exu.OutputVariableType.AngularVelocity))
129
130#marker for ground (=fixed):
131groundMarker0=mbs.AddMarker(MarkerNodePosition(nodeNumber= nGround0))
132groundMarker1=mbs.AddMarker(MarkerNodePosition(nodeNumber= nGround1))
133
134#marker for rotor axis and support:
135rotorAxisMarker0 =mbs.AddMarker(MarkerBodyPosition(bodyNumber=rigid, localPosition=[-L0,-eps,0]))
136rotorAxisMarker1 =mbs.AddMarker(MarkerBodyPosition(bodyNumber=rigid, localPosition=[ L1,-eps,0]))
137
138
139#++++++++++++++++++++++++++++++++++++
140mbs.AddObject(CartesianSpringDamper(markerNumbers=[groundMarker0, rotorAxisMarker0], 
141                                    stiffness=[k,k,k], damping=[d, d, d]))
142mbs.AddObject(CartesianSpringDamper(markerNumbers=[groundMarker1, rotorAxisMarker1], 
143                                   stiffness=[0,k,k], damping=[0, d, d])) #do not constrain x-axis twice
144
145#coordinate markers for loads:
146rotorMarkerUy=mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate=1))
147rotorMarkerUz=mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate=2))
148
149#add torque:
150rotorRigidMarker =mbs.AddMarker(MarkerBodyRigid(bodyNumber=rigid, localPosition=[0,0,0]))
151mbs.AddLoad(Torque(markerNumber=rotorRigidMarker, loadVector=[torque,0,0]))
152
153#print(mbs)
154mbs.Assemble()
155#mbs.systemData.Info()
156
157simulationSettings = exu.SimulationSettings()
158simulationSettings.solution.file.writePeriod = 1e-5  #output interval
159simulationSettings.solution.sensors.writePeriod = 1e-5  #output interval
160
161if isSymmetric:
162    simulationSettings.solution.file.information = "Runup of Laval rotor, resonance="+str(round(fRes,3))+"Hz at 80-90 seconds"
163else:
164    simulationSettings.solution.file.information = "Runup of unsymmetric rotor"
165
166simulationSettings.timeIntegration.numberOfSteps = steps
167simulationSettings.timeIntegration.endTime = tEnd
168simulationSettings.timeIntegration.generalizedAlpha.useIndex2Constraints = True
169simulationSettings.timeIntegration.generalizedAlpha.useNewmark = True
170
171simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 1
172
173#create animations (causes slow simulation):
174createAnimation=True
175if createAnimation:
176    simulationSettings.solution.recordImagesInterval = 0.2
177    SC.visualizationSettings.exportImages.saveImageFileName = "images/frame"
178    SC.visualizationSettings.view0.window.renderWindowSize = [1600,1080]
179
180
181SC.renderer.Start()              #start graphics visualization
182SC.renderer.DoIdleTasks()    #wait for pressing SPACE bar to continue
183
184#start solver:
185mbs.SolveDynamic(simulationSettings)
186
187#SC.renderer.DoIdleTasks()#wait for pressing 'Q' to quit
188SC.renderer.Stop()               #safely close rendering window!
189
190#evaluate final (=current) output values
191u = mbs.GetNodeOutput(n1, exu.OutputVariableType.AngularVelocity)
192print('omega=',u)
193#print('displacement=',u[0])
194
195#+++++++++++++++++++++++++++++++++++++++++++++++++++++
196import matplotlib.pyplot as plt
197import matplotlib.ticker as ticker
198
199if False:
200    plt.close('all') #close all plots
201
202    dataDisp = np.loadtxt(OutputFilePath('solution/runupDisplacement.txt'), comments='#', delimiter=',')
203    dataOmega = np.loadtxt(OutputFilePath('solution/runupAngularVelocity.txt'), comments='#', delimiter=',')
204
205    plt.plot(dataDisp[:,0], dataDisp[:,3], 'b-') #numerical solution
206    plt.xlabel("time (s)")
207    plt.ylabel("z-displacement (m)")
208
209    plt.figure()
210    plt.plot((1/(2*np.pi))*dataOmega[:,1], dataDisp[:,3], 'b-') #numerical solution
211    plt.xlabel("angular velocity (1/s)")
212    plt.ylabel("z-displacement (m)")
213
214    plt.figure()
215    plt.plot(dataOmega[:,0], (1/(2*np.pi))*dataOmega[:,1], 'b-') #numerical solution
216    plt.xlabel("time (s)")
217    plt.ylabel("angular velocity (1/s)")
218
219    plt.figure()
220    plt.plot(dataDisp[:,2], dataDisp[:,3], 'r-') #numerical solution
221    plt.xlabel("y-displacement (m)")
222    plt.ylabel("z-displacement (m)")
223    
224    #plt.plot(data[n-500:n-1,1], data[n-500:n-1,2], 'r-') #numerical solution
225    
226    ax=plt.gca() # get current axes
227    ax.grid(True, 'major', 'both')
228    ax.xaxis.set_major_locator(ticker.MaxNLocator(10)) 
229    ax.yaxis.set_major_locator(ticker.MaxNLocator(10)) 
230    plt.tight_layout()
231    plt.show()