55from copy import copy , deepcopy
66from itertools import chain , cycle
77from pathlib import Path
8- from methodtools import lru_cache
98
109import numpy as np
1110import pandas as pd
1211import toml
12+ from methodtools import lru_cache
1313from plotly import express as px
1414from plotly import graph_objects as go
1515from scipy import io as sio
1616from scipy import linalg as la
1717from scipy import signal as signal
18+ from scipy .integrate import cumulative_trapezoid as integrate
19+ from scipy .linalg import lu_factor , lu_solve
1820from scipy .optimize import newton
1921from scipy .sparse import linalg as las
20- from scipy .integrate import cumulative_trapezoid as integrate
2122
2223from ross .bearing_seal_element import (
2324 BallBearingElement ,
2425 BearingElement ,
2526 BearingFluidFlow ,
27+ CylindricalBearing ,
2628 MagneticBearingElement ,
2729 RollerBearingElement ,
2830 SealElement ,
29- CylindricalBearing ,
3031)
31- from ross .faults import Crack , MisalignmentFlex , MisalignmentRigid , Rubbing
32- from ross .disk_element import DiskElement
3332from ross .coupling_element import CouplingElement
33+ from ross .disk_element import DiskElement
34+ from ross .faults import Crack , MisalignmentFlex , MisalignmentRigid , Rubbing
3435from ross .materials import Material , steel
3536from ross .point_mass import PointMass
3637from ross .results import (
4647 TimeResponseResults ,
4748 UCSResults ,
4849)
50+ from ross .seals .labyrinth_seal import LabyrinthSeal
4951from ross .shaft_element import ShaftElement
5052from ross .units import Q_ , check_units
5153from ross .utils import (
52- intersection ,
53- newmark ,
5454 assemble_C_K_matrices ,
55- remove_dofs ,
5655 convert_6dof_to_4dof ,
5756 convert_6dof_to_torsional ,
57+ intersection ,
58+ newmark ,
59+ remove_dofs ,
5860)
59- from ross .seals .labyrinth_seal import LabyrinthSeal
6061
6162__all__ = [
6263 "Rotor" ,
@@ -1666,7 +1667,7 @@ def _pseudo_modal(self, speed, num_modes):
16661667
16671668 return matrix_to_modal , vector_to_modal , vector_from_modal
16681669
1669- def transfer_matrix (self , speed = None , frequency = None , modes = None ):
1670+ def transfer_matrix (self , speed = None , frequency = None ):
16701671 """Calculate the fer matrix for the frequency response function (FRF).
16711672
16721673 Paramenters
@@ -1675,9 +1676,6 @@ def transfer_matrix(self, speed=None, frequency=None, modes=None):
16751676 Excitation frequency. Default is rotor speed.
16761677 speed : float, optional
16771678 Rotating speed. Default is rotor speed (frequency).
1678- modes : list, optional
1679- List with modes used to calculate the matrix.
1680- (all modes will be used if a list is not given).
16811679
16821680 Returns
16831681 -------
@@ -1693,33 +1691,17 @@ def transfer_matrix(self, speed=None, frequency=None, modes=None):
16931691 if frequency is None :
16941692 frequency = speed
16951693
1696- lti = self ._lti (speed = speed )
1697- B = lti .B
1698- C = lti .C
1699- D = lti .D
1694+ I = np .eye (self .M ().shape [0 ])
17001695
1701- # calculate eigenvalues and eigenvectors using la.eig to get
1702- # left and right eigenvectors.
1703- evals , psi = self ._eigen (speed = speed , frequency = frequency )
1704-
1705- psi_inv = la .inv (psi )
1696+ lu , piv = lu_factor (
1697+ - (frequency ** 2 ) * self .M (frequency = frequency )
1698+ + 1j * frequency * (self .C (frequency = frequency ) + frequency * self .G ())
1699+ + self .K (frequency = frequency )
1700+ )
1701+ H = lu_solve ((lu , piv ), I )
17061702
1707- if modes is not None :
1708- n = self .ndof # n dof -> number of modes
1709- m = len (modes ) # -> number of desired modes
1710- # idx to get each evalue/evector and its conjugate
1711- idx = np .zeros ((2 * m ), int )
1712- idx [0 :m ] = modes # modes
1713- idx [m :] = range (2 * n )[- m :] # conjugates (see how evalues are ordered)
1714- evals = evals [np .ix_ (idx )]
1715- psi = psi [np .ix_ (range (2 * n ), idx )]
1716- psi_inv = psi_inv [np .ix_ (idx , range (2 * n ))]
1717-
1718- with np .errstate (divide = "ignore" , invalid = "ignore" ):
1719- diag = np .diag ([1 / (1j * frequency - lam ) for lam in evals ])
1720- diag [np .isnan (diag )] = 0
1721-
1722- H = C @ psi @ diag @ psi_inv @ B + D
1703+ if np .isnan (H ).any ():
1704+ H = np .zeros ((H .shape ))
17231705
17241706 return H
17251707
@@ -1788,12 +1770,12 @@ def run_freq_response(
17881770 --------
17891771 >>> import ross as rs
17901772 >>> rotor = rs.rotor_example()
1791- >>> speed = np.linspace(0, 1000, 101)
1773+ >>> speed =np.linspace(0, 1000, 101)
17921774 >>> response = rotor.run_freq_response(speed_range=speed)
17931775
17941776 Return the response amplitude
17951777 >>> abs(response.freq_resp) # doctest: +ELLIPSIS
1796- array([[[1 .00000000e-06 , 1.00261725e-06, 1.01076952e-06, ...
1778+ array([[[0 .00000000e+00 , 1.00261725e-06, 1.01076952e-06, ...
17971779
17981780 Return the response phase
17991781 >>> np.angle(response.freq_resp) # doctest: +ELLIPSIS
@@ -1810,7 +1792,7 @@ def run_freq_response(
18101792 Selecting the disirable modes, if you want a reduced model:
18111793 >>> response = rotor.run_freq_response(speed_range=speed, modes=[0, 1, 2, 3, 4])
18121794 >>> abs(response.freq_resp) # doctest: +ELLIPSIS
1813- array([[[2.00154633e-07, 2.02422522e-07, 2.09522044e-07 , ...
1795+ array([[[0.00000000e+00, 1.00261725e-06, 1.01076952e-06 , ...
18141796
18151797 Plotting frequency response function:
18161798 >>> fig = response.plot(inp=13, out=13)
@@ -1877,14 +1859,12 @@ def _run_freq_response(
18771859 accl_resp = np .empty ((self .ndof , self .ndof , len (speed_range )), dtype = complex )
18781860
18791861 if free_free :
1880- transfer_matrix = lambda s , m : self .transfer_matrix (
1881- speed = 0 , modes = m , frequency = s
1882- )
1862+ transfer_matrix = lambda s : self .transfer_matrix (speed = 0 , frequency = s )
18831863 else :
1884- transfer_matrix = lambda s , m : self .transfer_matrix (speed = s , modes = m )
1864+ transfer_matrix = lambda s : self .transfer_matrix (speed = s )
18851865
18861866 for i , speed in enumerate (speed_range ):
1887- H = transfer_matrix (speed , modes )
1867+ H = transfer_matrix (speed )
18881868 freq_resp [..., i ] = H
18891869 velc_resp [..., i ] = 1j * speed * H
18901870 accl_resp [..., i ] = - (speed ** 2 ) * H
@@ -2006,7 +1986,6 @@ def run_forced_response(
20061986 forced_resp [:, i ] = freq_resp .freq_resp [..., i ] @ force [..., i ]
20071987 velc_resp [:, i ] = freq_resp .velc_resp [..., i ] @ force [..., i ]
20081988 accl_resp [:, i ] = freq_resp .accl_resp [..., i ] @ force [..., i ]
2009-
20101989 forced_resp = ForcedResponseResults (
20111990 rotor = self ,
20121991 forced_resp = forced_resp ,
@@ -2210,7 +2189,7 @@ def run_unbalance_response(
22102189
22112190 Return the response phase
22122191 >>> np.angle(response.forced_resp) # doctest: +ELLIPSIS
2213- array([[ 0.00000000e+00 , ...
2192+ array([[ 0. , 0. , 0. , ...
22142193
22152194 Using clustered points option.
22162195 Set `cluster_points=True` and choose how many modes the method must search and
0 commit comments