petrobras / ross

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

Delay in calculating FRF #1106

Open ViniciusTxc3 opened 2 weeks ago

ViniciusTxc3 commented 2 weeks ago

@romero-patrick noticed that the execution time when using the ROSS FRF response is high. In one example the time spent was ~5min. To speed up the calculations, here is the code example:

import numpy as np
import ross as rs
import time

samples= 100
speed_range = np.linspace(2*np.pi*0,2*np.pi*30,samples)
inp = 3*4+1
out = 4*4+1

L=np.array([    0,   30,   50,    60,   65,  100,  120,  150,  180,  210,  244,  270,  300,  335,  345,  355,  375,  400,  430,  460,  490,  520,  550, 578,                     
                       616,  626,  636,   676,  700,  730,  765,  791,  820,  850,  880,  915,  950,  985, 1000])

odl = 0.017
L = L*0.001
L = [L[i] - L[i - 1] for i in range(1, len(L))]
list_odl = [odl]*len(L)
for i in [2,3,13,14,24,25]:
    list_odl[i] += 0.020
Nnos = len(L)
Nele = Nnos-1
Steel = rs.Material("Steel", 7850, E=205e9, G_s=None, Poisson=0.29, color='#525252')
Steel2= rs.Material(name="Steel2", rho=7810, E=211e9, G_s=80e9)
shaft = []
for i in range(len(L)):
    shaft.append(
        rs.ShaftElement(
            material=Steel,
            L=L[i],
            idl=0,
            odl=list_odl[i],
            rotary_inertia=False,
            shear_effects=False
    ))

disks = [rs.DiskElement.from_geometry(n = 14, material = Steel2, width = 0.01, i_d = 0, o_d = 0.200),
    rs.DiskElement(Id=0.007377186232163936, Ip=0.003688593116081968,
    m=2.66029, color='Firebrick', n=25),
    rs.DiskElement(Id=0.007377186232163936, Ip=0.003688593116081968,
    m=2.66029, color='Firebrick', n=3)
    ]
bearing2 = rs.BearingElement(6, kxx=1e6, kyy = 8.5e5, cxx=50, cyy = 20)
bearing3 = rs.BearingElement(35, kxx=5e5, kyy = 7e5, cxx=15, cyy = 35)

rotor_data = rs.Rotor(shaft, disks, [bearing2, bearing3])

FRFrstart = time.time()
results = rotor_data.run_freq_response(speed_range)
FRFrend = time.time()
fr = results.freq_resp[inp, out]

print(f'Time FRF of ROSS {FRFrend-FRFrstart} s')
ViniciusTxc3 commented 2 weeks ago

Together with @romero-patrick, we are developing a new way of calculating the FRF, where the time drops considerably ~1s for the same example.

This is the idea of ​​a function:

def FRF(rotor, speed_range, inp, out, num_modes = 10):
    M_mod = rotor.M() 
    K_mod = np.zeros(M_mod.shape)
    K0 = rotor.K(0) + K_mod
    FRF_resp = np.zeros(len(speed_range))
    Lambda, Phi = sp.linalg.eigh(K0, M_mod)
    Phi = Phi[:,:num_modes]
    M_red = Phi.T@M_mod@Phi
    G_red = Phi.T@rotor.G()@Phi
    for i in range(len(speed_range)):
        w=speed_range[i]
        K_red = Phi.T @ (rotor.K(w) + K_mod) @ Phi
        C_red = Phi.T @ rotor.C(w) @ Phi
        H_red = -w**2*M_red + (1j*w)*(C_red+w*G_red) + K_red
        Hinv_red = sp.linalg.inv(H_red)
        Hinv = Phi@Hinv_red@Phi.T
        #FRF_resp[i] = np.abs(Hinv[int(inp)][int(out)])
        FRF_resp[i] = (Hinv[int(inp)][int(out)])

    return FRF_resp

image

image