petrobras / ross

ROSS is a library written in Python for rotordynamic analysis.
https://ross.readthedocs.io
Apache License 2.0
129 stars 101 forks source link

Add model reduction method #599

Open rodrigomoliveira1 opened 4 years ago

rodrigomoliveira1 commented 4 years ago

Some rotor models can have a large number of elements and, in addition to this fact, the high number of frequency / time sample points that may be necessary to input, may lead to a very long time and computational consuming, mainly when running ross.stochastic.

Adding a model reduction method will help (a lot) mitigate this problem.

I'm already working on it. I tried a classic static reduction (Guyan reduction - Guyan, 1965) and did a quick test, checking how it'd work for a system with excitation frequencies different from zero. First, I've run the example without damping, then a I added some damping to the bearings (cxx = cyy = 1000N.s/m)

full rotor model

rotor = rotor_example() rotor.ndof # total number of DoFs 28 wd_full = rotor.run_modal(speed=0, num_modes=14).wd np.round(wd_full, 3) array([ 91.797, 96.289, 274.566, 296.5 , 722.898, 765. , 1069.66 ])

model reduction

considering half the model size - rotor.ndof = 14

modes = np.arange(num_modes) # DoFs to be considered on the reduced model wd = model_reduction(modes, speed) np.round(wd, 3) array([ 92.478, 96.954, 302.453, 323.405, 940.636, 949.687, 2191.051])

relative error

error = np.abs(wd_full - wd) / wd_full array([0.007, 0.007, 0.102, 0.091, 0.301, 0.241, 1.048])

>>> speed = 850
>>> num_modes = 14

### full rotor model ###
>>> rotor = rotor_example()
>>> rotor.ndof  # total number of DoFs
28
>>> wd_full = rotor.run_modal(speed=0, num_modes=14).wd
>>> np.round(wd_full, 3)
array([  91.152,   96.735,  254.829,  315.369,  600.995,  864.88 , 1052.441])

### model reduction ###
>>> # considering half the model size - rotor.ndof = 14
>>> modes = np.arange(num_modes)  # DoFs to be considered on the reduced model
>>> wd = model_reduction(modes, speed)
>>> np.round(wd, 3)
array([  91.675,   97.688,  281.892,  342.653,  865.614, 1004.893, 1828.4  ])

### relative error ###
>>> error = np.abs(wd_full - wd) / wd_full
array([0.006, 0.01 , 0.106, 0.087, 0.44 , 0.162, 0.737])
>>> speed = 0
>>> num_modes = 14

### full rotor model ###
>>> rotor = rotor_example()
>>> rotor.ndof  # total number of DoFs
28
>>> wd_full = rotor.run_modal(speed=0, num_modes=14).wd
>>> np.round(wd_full, 3)
array([  91.918,   96.38 ,  276.076,  298.268,  712.741,  757.748, 1047.941])

### model reduction ###
>>> # considering half the model size - rotor.ndof = 14
>>> modes = np.arange(num_modes)  # DoFs to be considered on the reduced model
>>> wd = model_reduction(modes, speed)
>>> np.round(wd, 3)
array([  92.533,   96.997,  303.765,  324.73 ,  923.145,  937.153, 2174.414])

### relative error ###
>>> error = np.abs(wd_full - wd) / wd_full
array([0.007, 0.006, 0.1  , 0.089, 0.295, 0.237, 1.075])
>>> speed = 850
>>> num_modes = 14

### full rotor model ###
>>> rotor = rotor_example()
>>> rotor.ndof  # total number of DoFs
28
>>> wd_full = rotor.run_modal(speed=0, num_modes=14).wd
>>> np.round(wd_full, 3)
array([  91.286,   96.812,  255.798,  317.758,  599.666,  848.088, 1041.274])

### model reduction ###
>>> # considering half the model size - rotor.ndof = 14
>>> modes = np.arange(num_modes)  # DoFs to be considered on the reduced model
>>> wd = model_reduction(modes, speed)
>>> np.round(wd, 3)
array([  91.736,   97.726,  282.765,  344.351,  860.967,  982.931, 1803.597])

### relative error ###
>>> error = np.abs(wd_full - wd) / wd_full
array([0.005, 0.009, 0.105, 0.084, 0.436, 0.159, 0.732])

In this first round, only the first 2 natural frequencies have a low error margin (~0.6%). All others have a considerable relative error to the full model. And, as it's expected, it works fine comparing the first and second modes but it works badly for high speed / excitation frequencies values, when comparing the damped natural frequencies, due some neglected inertia terms in his assumptions.

Of course, increasing the number of DoF's will diminish these relative errors from the lowests natural frequencies.

>>> speed = 0
>>> num_modes = 20

### full rotor model ###
>>> rotor = rotor_example()
>>> rotor.ndof  # total number of DoFs
28
>>> wd_full = rotor.run_modal(speed=0, num_modes=14).wd
>>> np.round(wd_full, 3)
array([  91.918,   96.38 ,  276.076,  298.268,  712.741,  757.748,
       1047.941, 1084.691, 2022.174, 2033.466])

### model reduction ###
>>> # considering half the model size - rotor.ndof = 14
>>> modes = np.arange(num_modes)  # DoFs to be considered on the reduced model
>>> wd = model_reduction(modes, speed)
>>> np.round(wd, 3)
array([  91.879,   96.558,  275.966,  303.713,  761.112,  773.359,
       1135.501, 1262.623, 2110.919, 2358.124])

### relative error ###
>>> error = np.abs(wd_full - wd) / wd_full
array([0.0004, 0.0018, 0.0004, 0.0183, 0.0679, 0.0206, 0.0836, 0.164 ,
       0.0439, 0.1597])

Now, instead of a static method, I'll try a dynamic method. Qu, 2004 has a good reference to help finding a suitable dynamic method.

raphaeltimbo commented 4 years ago

Another good reference: http://michael.friswell.com/PDF_Files/C120.pdf

raphaeltimbo commented 6 months ago

We should check if we can add the following methods: (1) modal reduction, (2) Krylov subspace, (3) Guyan reduction, and (4) System Equivalent Reduction-Expansion Process (SEREP)

This is based on the published article https://asmedigitalcollection.asme.org/vibrationacoustics/article-abstract/doi/10.1115/1.4065038/1198582/Reduced-order-modeling-in-rotordynamics-and-its?redirectedFrom=fulltext

ross-bott commented 5 months ago

Hi there! I have marked this issue as stale because it has not had activity for 45 days. Consider the following options: