Tutorial - Static and Modal Analyzes#
This is the second part of a basic tutorial on how to use ROSS (rotordynamics open-source software), a Python library for rotordynamic analysis. In this tutorial, you will learn how to run several rotordynamic analyzes with your rotor model.
To get results, we always have to use one of the .run_ methods available for a rotor object. These methods will return objects that store the analysis results and that also have plot methods available. These methods will use the plotly library to make graphs common to a rotordynamic analysis.
Rotor model#
First, let’s recover the rotor model built in the previous tutorial.
import ross as rs
import numpy as np
# Make sure the default renderer is set to 'notebook' for inline plots in Jupyter
import plotly.io as pio
import plotly.graph_objects as go
pio.renderers.default = "notebook"
rotor3 = rs.compressor_example()
node_increment = 5
rotor3.plot_rotor(nodes=node_increment)
Rotor Analyses#
In the last tutorial we have learnt how to create a rotor model with Rotor class. Now, we’ll use the same class to run the simulation. There’re some methods, most of them with the prefix run_ you can use to run the rotordynamics analyses.
For Most of the methods, you can use the command .plot() to display a graphical visualization of the results (e.g run_campbel().plot(), run_modal().plot_mode_3d(mode)).
ROSS offers the following analyses:
Static analysis
Modal analysis
Campbell Diagram
Plotly library#
ROSS uses Plotly for plotting results. All the figures can be stored and manipulated following Plotly API.
The following sections presents the results and how to return the Plotly Figures.
1.1 Static Analysis#
This method runs the static analysis for the rotor. It calculate the static deformation due the gravity effects (shaft and disks weight). It also returns the bending moment and shearing force on each node, and you can return a free-body-diagram representation for the rotor, with the self weight, disks weight and reaction forces on bearings displayed.
1.1.1 Running static analysis#
To run the simulation, use the .run_static() method. You can define a variable to store the results.
Storing the results, it’s possible to return the following arrays:
disk_forces_nodaldisk_forces_tagbearing_forces_nodalbearing_forces_tagdisp_yVxBm
static = rotor3.run_static()
Returning forces#
Disk forces#
.disk_forces_nodal: Returns a dictionaty expliciting the node where the disk is located and the force value..disk_forces_tag: Returns a dictionaty expliciting the the disk tag is located and the force value.
Bearing forces#
.bearing_forces_nodal: Returns a dictionaty expliciting the node where the bearing is located and the force value..bearing_forces_tag: Returns a dictionaty expliciting the the bearing tag is located and the force value.
print("Disk forces - nodes")
print(rotor3.disk_forces_nodal)
print("")
print("Disk forces - tags")
print(rotor3.disk_forces_tag)
print("")
print("Bearing forces - nodes")
print(rotor3.bearing_forces_nodal)
print("")
print("Bearing forces - tags")
print(rotor3.bearing_forces_tag)
Disk forces - nodes
{'node_3': 148.2741036647235, 'node_20': 67.76283441291268, 'node_23': 67.95896417966495, 'node_26': 68.15509394641724, 'node_29': 68.44928859654566, 'node_32': 68.0570290630411, 'node_35': 68.25315882979338}
Disk forces - tags
{'Disk 0': 148.2741036647235, 'Disk 1': 67.76283441291268, 'Disk 2': 67.95896417966495, 'Disk 3': 68.15509394641724, 'Disk 4': 68.44928859654566, 'Disk 5': 68.0570290630411, 'Disk 6': 68.25315882979338}
Bearing forces - nodes
{'node_7': 1216.2827567760548, 'node_48': 1204.6514712820085}
Bearing forces - tags
{'Bearing 0': 1216.2827567760548, 'Bearing 1': 1204.6514712820085}
Other attributes from static analysis#
.Vx: Shearing force array.Bm: Bending moment array.deformationDisplacement in Y direction
1.1.2 Plotting results#
With results stored, you can use some methods to plot the results. Currently, there’re four plots you can retrieve from static analysis:
.plot_free_body_diagram().plot_deformation().plot_shearing_force().plot_bending_moment()
Plotting free-body-diagram#
static.plot_free_body_diagram()
Plotting deformation#
static.plot_deformation()
Plotting shearing force diagram#
static.plot_shearing_force()
Plotting bending moment diagram#
static.plot_bending_moment()
1.2 Modal Analysis#
ROSS performs the modal analysis through method run_modal().
This method calculates natural frequencies, damping ratios and mode shapes.
You must select a speed, which will be used as excitation frequency to calculate the system’s eigenvalues and eigenvectors, and the number of eigenvalues and eigenvectors to be calculated is an optional argument (num_modes).
After running the modal analysis, it’s possible to return the following attributes:
eigenvalues (evalues);
eigenvectors (evectors);
damped natural frequencies (wd);
undamped natural frequencies (wn);
damping ratio (damping_ratio);
logarithmic decrement (log_dec).
1.2.1 Running modal analysis#
To run the modal analysis, choose a speed to instantiate the method. For different speeds, change the the argument and run run_modal() once again.
Returning undamped natural frequencies#
rotor_speed = 100.0 # rad/s
modal = rotor3.run_modal(rotor_speed, num_modes=16)
print(f"Undamped natural frequencies:\n {modal.wn}")
Undamped natural frequencies:
[ 322.46731503 340.20234837 1052.62052765 1060.87679241 2243.16590468
2257.55966937 3361.2288725 3341.04127238]
Returning damped natural frequencies#
# modal.wd
print(f"Damped natural frequencies:\n {modal.wd}")
Damped natural frequencies:
[ 0. 0. 1033.02623171 1043.2598127 2231.61002125
2246.03661745 3325.59588469 3341.04127238]
Returning the damping ratio#
# modal.damping_ratio
print(f"Damping ratio for each mode:\n {modal.damping_ratio}")
Damping ratio for each mode:
[1.00000000e+00 1.00000000e+00 1.92049585e-01 1.81483750e-01
1.01373824e-01 1.00907686e-01 1.45223870e-01 4.05074538e-14]
Returning logarithmic decrement#
# modal.log_dec
print(f"Logarithmic decrement for each mode:\n {modal.log_dec}")
Logarithmic decrement for each mode:
[ inf inf 1.22957133e+00 1.15955161e+00
6.40248822e-01 6.37274472e-01 9.22245373e-01 2.54515838e-13]
1.2.2 Plotting results#
Once run_modal() is completed, you can check for the rotor’s mode shapes. You can plot each one of the modes calculated.
Besides, there’re two options for visualization:
plot_mode_2d- plotting 2D viewplot_mode_3d- plotting 3D view
Plotting 3D view#
Use the command .plot_mode_3d(mode).
mode = 5
modal.plot_mode_3d(mode)
Plotting 2D view#
Use the command .plot_mode_2d(mode).
modal.plot_mode_2d(mode)
Torsional analysis#
You can filter modes by the mode type attribute (“Lateral”, “Axial”, “Torsional”), for example:
torsional_modes = [
mode for mode, shape in enumerate(modal.shapes) if shape.mode_type == "Torsional"
]
torsional_modes
[7]
modal.plot_mode_3d(torsional_modes[0], animation=True)
1.3 Campbell Diagram#
Also called “whirl speed map” in rotordynamics, ROSS calculate and plots the modes’ damped eigenvalues and the logarithmic decrement as a function of rotor speed.
To run the Campbell Diagram, use the command .run_campbell(). The user must input an array of speeds, which will be iterated to calculate each point on the graph.
This method returns the damped natural frequencies, logarithmic decrement and the whirl values (values indicating the whirl direction: backward or forward).
1.3.1 Running campbell diagram#
In this example the whirl speed map is calculated for a speed range from 0 to 1000 rad/s (~9550 RPM).
Storing the results, it’s possible to return the following arrays:
wdlog_decwhirl_values
Each value in these arrays is calculated for each speed value in speed_range
samples = 31
speed_range = np.linspace(315, 1150, samples)
campbell = rotor3.run_campbell(speed_range)
# results for each frequency
frequency_index = 0
print(campbell.wd[:, frequency_index])
[ 0. 0. 0. 0. 0.
0. 0. 0. 0. 587.93352108
800.71637216 947.50369455 1060.26594937 1151.59909347 1228.05252298
1293.58502759 1350.78773738 1401.42252043 1446.74232093 1487.66816251
1524.89882608 1558.98864193 1590.38668443 1619.46273931 1646.51178109
1671.76718981 1695.42609601 1717.65668896 1738.60328929 1758.39043317
1777.12618088]
# results for each frequency
frequency_index = 1
print(campbell.log_dec[:, frequency_index])
[ inf inf inf 2.51999426e+04
inf inf inf 3.28326974e+01
1.45527469e+01 1.06442162e+01 8.70075118e+00 7.47883577e+00
6.61609158e+00 5.96425106e+00 5.44960728e+00 5.03037280e+00
4.68078267e+00 4.38396748e+00 4.12825595e+00 3.90518959e+00
3.70844608e+00 3.53322912e+00 3.37579831e+00 3.23323137e+00
3.10326087e+00 2.98411101e+00 2.87435308e+00 2.77281817e+00
2.67853528e+00 2.59068685e+00 2.50857649e+00]
1.3.2 Plotting results#
Now that the results are stored, use .plot() method to display the Campbell Diagram plot.
For the Campbell Diagram, you can plot more than one harmonic. As default, the plot display only the 1x speed option. Input a list with more harmonics to display it at the graph.
campbell.plot(harmonics=[0.5, 1])