lavalRotor2Dtest.py
You can view and download this file on Github: lavalRotor2Dtest.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: Example with 2D laval rotor; shows backward and forward whirl effects using
5# Includes user load and Sweep
6#
7# Author: Johannes Gerstmayr
8# Date: 2019-12-03
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 length
31mass = 1.6 #mass in kg
32r = 0.5 #radius for disc mass distribution
33spring = 4000 #stiffness of (all/both) springs in rotor in N/m
34omega0=np.sqrt(spring/mass) #linear system
35
36zeta = 0.001*5
37damper = 2*omega0*zeta*mass #damping constant in N/(m/s)
38
39f0 = 0.*omega0/(2*np.pi)
40f1 = 1.*omega0/(2*np.pi)
41
42torque = 0*1 #Nm
43eps = 1e-2 #excentricity in y-direction
44omegaInitial = 0.5*omega0
45
46print('resonance frequency = '+str(omega0/2/np.pi)+'Hz')
47tEnd = 50 #end time of simulation
48steps = 10000 #number of steps
49
50
51#linear frequency sweep in time interval [0, t1] and frequency interval [f0,f1];
52def Sweep(t, t1, f0, f1):
53 k = (f1-f0)/t1
54 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!!!
55
56#user function for load
57def userLoad(mbs, t, load):
58 #return load*np.sin(0.5*omega0*t) #gives resonance
59 if t>40: time.sleep(0.02) #make simulation slower
60 return load*Sweep(t, tEnd, f0, f1)
61 #return load*Sweep(t, tEnd, f1, f0) #backward sweep
62
63#backward whirl excitation:
64amp = 0*10 #in resonance: *0.01
65def userLoadBWx(mbs, t, load):
66 return load*np.sin(omegaInitial*t)
67def userLoadBWy(mbs, t, load):
68 return -load*np.cos(omegaInitial*t) #negative sign: FW, positive sign: BW
69
70#node for Rigid2D body: px, py, phi:
71n1=mbs.AddNode(Rigid2D(referenceCoordinates = [0,eps,0],
72 initialCoordinates=[0,0,0],
73 initialVelocities=[0,0,omegaInitial]))
74
75#ground node
76nGround=mbs.AddNode(NodePointGround(referenceCoordinates = [0,0,0]))
77
78#add mass point (this is a 3D object with 3 coordinates):
79gRotor = graphics.Lines([[-r*0.5,-r*0.5,0], [r*0.5,-r*0.5,0], [r*0.5,r*0.5,0], [-r*0.5,r*0.5,0], [-r*0.5,-r*0.5,0]], color=[1,0,0,1])
80rigid2D = mbs.AddObject(RigidBody2D(mass=mass, inertia=mass*r**2, nodeNumber = n1, visualization=VObjectRigidBody2D(graphicsData=[gRotor])))
81
82#marker for ground (=fixed):
83groundMarker=mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= nGround, coordinate = 0))
84
85#marker for rotor axis and support:
86rotorAxisMarker =mbs.AddMarker(MarkerBodyPosition(bodyNumber=rigid2D, localPosition=[0,-eps,0]))
87groundBody= mbs.AddObject(ObjectGround(referencePosition=[0,0,0]))
88rotorSupportMarker=mbs.AddMarker(MarkerBodyPosition(bodyNumber=groundBody, localPosition=[0,0,0]))
89
90#marker for springDamper for first (x-)coordinate:
91coordXMarker = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate = 0))
92coordYMarker = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate = 1))
93coordPhiMarker = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber= n1, coordinate = 2))
94
95mbs.AddObject(CartesianSpringDamper(markerNumbers=[rotorSupportMarker, rotorAxisMarker], stiffness=[spring,spring,0], damping=[damper, damper,0]))
96
97#add load:
98mbs.AddLoad(LoadCoordinate(markerNumber = coordYMarker, load = 0, loadUserFunction=userLoad))
99mbs.AddLoad(LoadCoordinate(markerNumber = coordPhiMarker, load = torque))#, loadUserFunction=userLoad))
100
101mbs.AddLoad(LoadCoordinate(markerNumber = coordXMarker, load = amp, loadUserFunction=userLoadBWx))
102mbs.AddLoad(LoadCoordinate(markerNumber = coordYMarker, load = amp, loadUserFunction=userLoadBWy))
103
104print(mbs)
105mbs.Assemble()
106
107simulationSettings = exu.SimulationSettings()
108simulationSettings.solution.file.writePeriod = 1e-5 #output interval
109simulationSettings.timeIntegration.numberOfSteps = steps
110simulationSettings.timeIntegration.endTime = tEnd
111
112simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 1
113
114SC.renderer.Start() #start graphics visualization
115SC.renderer.DoIdleTasks() #wait for pressing SPACE bar to continue
116
117#start solver:
118mbs.SolveDynamic(simulationSettings)
119
120SC.renderer.Stop() #safely close rendering window!
121
122#evaluate final (=current) output values
123u = mbs.GetNodeOutput(n1, exu.OutputVariableType.Position)
124print('displacement=',u[0])
125
126#+++++++++++++++++++++++++++++++++++++++++++++++++++++
127import matplotlib.pyplot as plt
128import matplotlib.ticker as ticker
129
130if True:
131 data = np.loadtxt(OutputFilePath('solution/coordinatesSolution.txt'), comments='#', delimiter=',')
132 n=steps
133 #plt.plot(data[:,0], data[:,6], 'r-') #numerical solution
134 plt.plot(data[n-500:n-1,1], data[n-500:n-1,2], 'r-') #numerical solution
135
136 ax=plt.gca() # get current axes
137 ax.grid(True, 'major', 'both')
138 ax.xaxis.set_major_locator(ticker.MaxNLocator(10))
139 ax.yaxis.set_major_locator(ticker.MaxNLocator(10))
140 plt.tight_layout()
141 plt.show()