def test_bearing_link_global_index(): b0 = BearingElement(n=0, n_link=3, kxx=1, cxx=1) idx = b0.dof_global_index() assert idx.x_0 == 0 assert idx.y_0 == 1 print(idx) assert idx.x_3 == 12 assert idx.y_3 == 13
def test_bearing_link_matrices(): b0 = BearingElement(n=0, n_link=3, kxx=1, cxx=1) # fmt: off M = np.array([[1, 0, -1, 0], [0, 1, 0, -1], [-1, 0, 1, 0], [0, -1, 0, 1]]) # fmt: on assert_allclose(b0.K(0), M) assert_allclose(b0.C(0), M)
def test_bearing_error2(): with pytest.raises(ValueError) as excinfo: BearingElement(4, kxx=[7e8, 8e8, 9e8], cxx=[0, 0, 0, 0], frequency=[10, 100, 1000, 10000]) assert ("Arguments (coefficients and frequency) " "must have the same dimension" in str(excinfo.value)) with pytest.raises(ValueError) as excinfo: BearingElement(4, kxx=[6e8, 7e8, 8e8, 9e8], cxx=[0, 0, 0, 0, 0]) assert ("Arguments (coefficients and frequency) " "must have the same dimension" in str(excinfo.value))
def test_bearing_len_3(): bearing = BearingElement( n=0, kxx=[481, 4810, 18810], cxx=[3.13, 10.81, 22.99], kyy=[481, 4810, 18810], kxy=[194, 2078, 8776], kyx=[-194, -2078, -8776], cyy=[3.13, 10.81, 22.99], cxy=[0.276, 0.69, 1.19], cyx=[-0.276, -0.69, -1.19], frequency=[115.19, 345.575, 691.15], ) assert_allclose(bearing.kxx_interpolated(115.19), 481, rtol=1e5)
def test_bearing_len_2(): bearing = BearingElement( n=0, kxx=[481, 4810], cxx=[3.13, 10.81], kyy=[481, 4810], kxy=[194, 2078], kyx=[-194, -2078], cyy=[3.13, 10.81], cxy=[0.276, 0.69], cyx=[-0.276, -0.69], frequency=[115.19, 345.575], ) assert_allclose(bearing.kxx_interpolated(115.19), 481, rtol=1e5)
def test_save_load(bearing0, bearing_constant, bearing_6dof): file = Path(tempdir) / "bearing0.toml" bearing0.save(file) bearing0_loaded = BearingElement.load(file) assert bearing0 == bearing0_loaded file = Path(tempdir) / "bearing_constant.toml" bearing_constant.save(file) bearing_constant_loaded = BearingElement.load(file) assert bearing_constant == bearing_constant_loaded file = Path(tempdir) / "bearing_6dof.toml" bearing_6dof.save(file) bearing_6dof_loaded = BearingElement6DoF.load(file) assert bearing_6dof == bearing_6dof_loaded
def test_from_table(): bearing_file = (os.path.dirname(os.path.realpath(__file__)) + "/data/bearing_seal_si.xls") bearing = BearingElement.from_table(0, bearing_file) assert bearing.n == 0 assert_allclose(bearing.frequency[2], 523.5987755985) assert_allclose(bearing.kxx.coefficient[2], 53565700) # bearing with us units bearing_file = (os.path.dirname(os.path.realpath(__file__)) + "/data/bearing_seal_us.xls") bearing = BearingElement.from_table(0, bearing_file) assert bearing.n == 0 assert_allclose(bearing.frequency[2], 523.5987755985) assert_allclose(bearing.kxx.coefficient[2], 53565700)
def bearing1(): # using lists Kxx_bearing = [ 8.5e07, 1.1e08, 1.3e08, 1.6e08, 1.8e08, 2.0e08, 2.3e08, 2.5e08, 2.6e08, ] Kyy_bearing = np.array([ 9.2e07, 1.1e08, 1.4e08, 1.6e08, 1.9e08, 2.1e08, 2.3e08, 2.5e08, 2.6e08 ]) Cxx_bearing = np.array([ 226837, 211247, 197996, 185523, 174610, 163697, 153563, 144209, 137973 ]) Cyy_bearing = np.array([ 235837, 211247, 197996, 185523, 174610, 163697, 153563, 144209, 137973 ]) wb = [314.2, 418.9, 523.6, 628.3, 733.0, 837.8, 942.5, 1047.2, 1151.9] bearing1 = BearingElement( 4, kxx=Kxx_bearing, kyy=Kyy_bearing, cxx=Cxx_bearing, cyy=Cyy_bearing, frequency=wb, ) return bearing1
def test_bearing_error_speed_not_given(): speed = np.linspace(0, 10000, 5) kx = 1e8 * speed cx = 1e8 * speed with pytest.raises(Exception) as excinfo: BearingElement(-1, kxx=kx, cxx=cx) assert ("Arguments (coefficients and frequency)" " must have the same dimension" in str(excinfo.value))
def test_st_point_mass_elements_odd_length(): tim0 = ShaftElement(L=0.25, idl=0, odl=0.05, material=steel) tim1 = ShaftElement(L=0.25, idl=0, odl=0.05, material=steel) shaft_elm = [tim0, tim1] disk0 = DiskElement(n=1, m=20, Id=1, Ip=1) brg0 = BearingElement(n=0, kxx=1e6, cxx=1e3, n_link=3) brg1 = BearingElement(n=2, kxx=1e6, cxx=1e3, n_link=4) sup0 = BearingElement(n=3, kxx=1e6, cxx=1e3) sup1 = BearingElement(n=4, kxx=1e6, cxx=1e3) pm0 = ST_PointMass(n=3, m=[1, 2], is_random=["m"]) pm1 = ST_PointMass(n=4, m=[1, 2, 3], is_random=["m"]) with pytest.raises(ValueError) as ex: ST_Rotor(shaft_elm, [disk0], [brg0, brg1, sup0, sup1], [pm0, pm1]) assert "not all random point mass lists have same length." in str(ex.value)
def test_save_load(bearing0, bearing_constant, bearing_6dof, magnetic_bearing): file = Path(tempdir) / "bearing0.toml" bearing0.save(file) bearing0_loaded = BearingElement.load(file) assert bearing0 == bearing0_loaded file = Path(tempdir) / "bearing_constant.toml" bearing_constant.save(file) bearing_constant_loaded = BearingElement.load(file) assert bearing_constant == bearing_constant_loaded file = Path(tempdir) / "bearing_6dof.toml" bearing_6dof.save(file) bearing_6dof_loaded = BearingElement6DoF.load(file) assert bearing_6dof == bearing_6dof_loaded file = Path(tempdir) / "magnetic_bearing.toml" magnetic_bearing.save(file) magnetic_bearing_loaded = MagneticBearingElement.load(file) assert magnetic_bearing == magnetic_bearing_loaded
def report2(): # rotor type: single double overhung i_d = 0.0 o_d = 0.05 n = 50 L = [0.03 for _ in range(n)] shaft_elem = [ ShaftElement(l, i_d, o_d, material=steel, shear_effects=True, rotary_inertia=True, gyroscopic=True) for l in L ] disk0 = DiskElement.from_geometry(n=0, material=steel, width=0.07, i_d=0.05, o_d=0.28) disk1 = DiskElement.from_geometry(n=50, material=steel, width=0.07, i_d=0.05, o_d=0.35) stfx = 1e6 stfy = 0.8e6 bearing0 = BearingElement(15, kxx=stfx, kyy=stfy, cxx=1000) bearing1 = BearingElement(35, kxx=stfx, kyy=stfy, cxx=1000) rotor = Rotor(shaft_elem, [disk0, disk1], [bearing0, bearing1]) minspeed = 3820.0 maxspeed = 9550.0 machine_type = "pump" units = "rpm" return Report(rotor, minspeed, maxspeed, machine_type, units)
def report0(): # rotor type: between bearings i_d = 0.0 o_d = 0.05 n = 50 L = [0.03 for _ in range(n)] shaft_elem = [ ShaftElement(l, i_d, o_d, material=steel, shear_effects=True, rotary_inertia=True, gyroscopic=True) for l in L ] disk0 = DiskElement.from_geometry(n=15, material=steel, width=0.07, i_d=0.05, o_d=0.28) disk1 = DiskElement.from_geometry(n=35, material=steel, width=0.07, i_d=0.05, o_d=0.35) stfx = 1e6 stfy = 0.8e6 bearing0 = BearingElement(0, kxx=stfx, kyy=stfy, cxx=1000) bearing1 = BearingElement(50, kxx=stfx, kyy=stfy, cxx=1000) rotor = Rotor(shaft_elem, [disk0, disk1], [bearing0, bearing1]) minspeed = 400.0 maxspeed = 1000.0 machine_type = "compressor" units = "rad/s" return Report(rotor, minspeed, maxspeed, machine_type, units)
def random_var(self, is_random, *args): """Generate a list of objects as random attributes. This function creates a list of objects with random values for selected attributes from ross.BearingElement. Parameters ---------- is_random : list List of the object attributes to become stochastic. *args : dict Dictionary instanciating the ross.BearingElement class. The attributes that are supposed to be stochastic should be set as lists of random variables. Returns ------- f_list : generator Generator of random objects. """ args_dict = args[0] new_args = [] try: for i in range(len(args_dict[is_random[0]][0])): arg = [] for key, value in args_dict.items(): if key in is_random: arg.append([value[j][i] for j in range(len(value))]) else: arg.append(value) new_args.append(arg) except TypeError: for i in range(len(args_dict[is_random[0]])): arg = [] for key, value in args_dict.items(): if key in is_random: arg.append(value[i]) else: arg.append(value) new_args.append(arg) f_list = (BearingElement(*arg) for arg in new_args) return f_list
def bearing0(): Kxx_bearing = np.array([ 8.5e07, 1.1e08, 1.3e08, 1.6e08, 1.8e08, 2.0e08, 2.3e08, 2.5e08, 2.6e08 ]) Kyy_bearing = np.array([ 9.2e07, 1.1e08, 1.4e08, 1.6e08, 1.9e08, 2.1e08, 2.3e08, 2.5e08, 2.6e08 ]) Cxx_bearing = np.array([ 226837, 211247, 197996, 185523, 174610, 163697, 153563, 144209, 137973 ]) Cyy_bearing = np.array([ 235837, 211247, 197996, 185523, 174610, 163697, 153563, 144209, 137973 ]) wb = np.array( [314.2, 418.9, 523.6, 628.3, 733.0, 837.8, 942.5, 1047.2, 1151.9]) bearing0 = BearingElement(4, kxx=Kxx_bearing, kyy=Kyy_bearing, cxx=Cxx_bearing, cyy=Cyy_bearing, w=wb) return bearing0
def stability_level_1(self, D, H, HP, oper_speed, RHO_ratio, RHOs, RHOd, unit="m"): """Stability analysis level 1. This analysis consider a anticipated cross coupling QA based on conditions at the normal operating point and the cross-coupling required to produce a zero log decrement, Q0. Components such as seals and impellers are not considered in this analysis. Parameters ---------- D: list Impeller diameter, m (in.), Blade pitch diameter, m (in.), H: list Minimum diffuser width per impeller, m (in.), Effective blade height, m (in.), HP: list Rated power per stage/impeller, W (HP), oper_speed: float Operating speed, rpm, RHO_ratio: list Density ratio between the discharge gas density and the suction gas density per impeller (RHO_discharge / RHO_suction), kg/m3 (lbm/in.3), RHOs: float Suction gas density in the first stage, kg/m3 (lbm/in.3). RHOd: float Discharge gas density in the last stage, kg/m3 (lbm/in.3), unit: str, optional Adopted unit system. Options are "m" (meter) and "in" (inch) Default is "m" Attributes ---------- condition: str not required: Stability Level 1 satisfies the analysis; required: Stability Level 2 is required. Return ------ fig1: bokeh.figure Applied Cross-Coupled Stiffness vs. Log Decrement plot; fig2: bokeh.figure CSR vs. Mean Gas Density plot. Example ------- >>> rotor = rotor_example() >>> report = Report(rotor=rotor, ... minspeed=400, ... maxspeed=1000, ... speed_units="rad/s") >>> stability = report.stability_level_1(D=[0.35, 0.35], ... H=[0.08, 0.08], ... HP=[10000, 10000], ... RHO_ratio=[1.11, 1.14], ... RHOd=30.45, ... RHOs=37.65, ... oper_speed=1000.0) >>> report.Qa 23022.32142857143 """ steps = 11 if unit == "m": C = 9.55 elif unit == "in": C = 63.0 else: raise TypeError("choose between meters (m) or inches (in)") if len(D) != len(H): raise Exception("length of D must be the same of H") Qa = 0.0 cross_coupled_array = np.array([]) # Qa - Anticipated cross-coupling for compressors - API 684 - SP6.8.5.6 if self.machine_type == "compressor": Bc = 3.0 Dc, Hc = D, H for i, disk in enumerate(self.rotor.disk_elements): if disk.n in self.disk_nodes: qi = HP[i] * Bc * C * RHO_ratio[i] / (Dc[i] * Hc[i] * oper_speed) Qi = np.linspace(0, 10 * qi, steps) cross_coupled_array = np.append(cross_coupled_array, Qi) Qa += qi # Qa - Anticipated cross-coupling for turbines - API 684 - SP6.8.5.6 if self.machine_type == "turbine" or self.machine_type == "axial_flow": Bt = 1.5 Dt, Ht = D, H for i, disk in enumerate(self.rotor.disk_elements): if disk.n in self.disk_nodes: qi = (HP[i] * Bt * C) / (Dt[i] * Ht[i] * oper_speed) Qi = np.linspace(0, 10 * qi, steps) cross_coupled_array = np.append(cross_coupled_array, Qi) Qa += qi # Defining cross-coupling range to 10*Qa - API 684 - SP6.8.5.8 Qi = np.linspace(0, 10 * Qa, steps) cross_coupled_array = np.append(cross_coupled_array, Qi) cross_coupled_array = cross_coupled_array.reshape( [len(self.disk_nodes) + 1, steps] ).T log_dec = np.zeros(len(cross_coupled_array)) # remove disks and seals from the rotor model bearing_list = [ copy(b) for b in self.rotor.bearing_seal_elements if b.__class__.__name__ != "SealElement" ] # Applying cross-coupling on rotor mid-span if self.rotor_type == "between_bearings": for i, Q in enumerate(cross_coupled_array[:, -1]): bearings = [copy(b) for b in bearing_list] # cross-coupling introduced at the rotor mid-span n = np.round(np.mean(self.rotor.nodes)) cross_coupling = BearingElement(n=int(n), kxx=0, cxx=0, kxy=Q, kyx=-Q) bearings.append(cross_coupling) aux_rotor = Rotor( shaft_elements=self.rotor.shaft_elements, disk_elements=[], bearing_seal_elements=bearings, rated_w=self.rotor.rated_w, ) modal = aux_rotor.run_modal(speed=oper_speed * np.pi / 30) non_backward = modal.whirl_direction() != "Backward" log_dec[i] = modal.log_dec[non_backward][0] # Applying cross-coupling for each disk - API 684 - SP6.8.5.9 else: for i, Q in enumerate(cross_coupled_array[:, :-1]): bearings = [copy(b) for b in bearing_list] # cross-coupling introduced at overhung disks for n, q in zip(self.disk_nodes, Q): cross_coupling = BearingElement( n=n, kxx=0, cxx=0, kxy=q, kyx=-q ) bearings.append(cross_coupling) aux_rotor = Rotor( shaft_elements=self.rotor.shaft_elements, disk_elements=[], bearing_seal_elements=bearings, rated_w=self.rotor.rated_w, ) modal = aux_rotor.run_modal(speed=oper_speed * np.pi / 30) non_backward = modal.whirl_direction() != "Backward" log_dec[i] = modal.log_dec[non_backward][0] # verifies if log dec is greater than zero to begin extrapolation cross_coupled_Qa = cross_coupled_array[:, -1] if log_dec[-1] >= 0: g = interp1d( cross_coupled_Qa, log_dec, fill_value="extrapolate", kind="linear" ) stiff = cross_coupled_Qa[-1] * (1 + 1 / (len(cross_coupled_Qa))) while g(stiff) > 0: log_dec = np.append(log_dec, g(stiff)) cross_coupled_Qa = np.append(cross_coupled_Qa, stiff) stiff += cross_coupled_Qa[-1] / (len(cross_coupled_Qa)) Q0 = cross_coupled_Qa[-1] else: idx = min(range(len(log_dec)), key=lambda i: abs(log_dec[i])) Q0 = cross_coupled_Qa[idx] # Find value for log_dec corresponding to Qa log_dec_a = log_dec[np.where(cross_coupled_Qa == Qa)][0] # CSR - Critical Speed Ratio crit_speed = self.rotor.run_modal(speed=self.maxspeed).wn[0] CSR = self.maxspeed / crit_speed # RHO_mean - Average gas density RHO_mean = (RHOd + RHOs) / 2 RHO = np.linspace(0, RHO_mean * 5, 501) # CSR_boundary - function to define the CSR boundaries CSR_boundary = np.piecewise( RHO, [RHO <= 16.53, RHO > 16.53, RHO == 60, RHO > 60], [2.5, lambda RHO: (-0.0115 * RHO + 2.69), 2.0, 0.0], ) # Plotting area fig1 = figure( tools="pan, box_zoom, wheel_zoom, reset, save", title="Applied Cross-Coupled Stiffness vs. Log Decrement - (API 684 - SP 6.8.5.10)", width=640, height=480, x_axis_label="Applied Cross-Coupled Stiffness, Q (N/m)", y_axis_label="Log Dec", x_range=(0, max(cross_coupled_Qa)), y_range=DataRange1d(start=0), ) fig1.title.text_font_size = "14pt" fig1.xaxis.axis_label_text_font_size = "20pt" fig1.yaxis.axis_label_text_font_size = "20pt" fig1.axis.major_label_text_font_size = "16pt" fig1.line( cross_coupled_Qa, log_dec, line_width=3, line_color=bokeh_colors[0] ) fig1.circle(Qa, log_dec_a, size=8, fill_color=bokeh_colors[0]) fig1.add_layout( Label( x=Qa, y=log_dec_a, text="Qa", text_font_style="bold", text_font_size="12pt", text_baseline="middle", text_align="left", y_offset=10 ) ) if unit == "m": f = 0.062428 x_label1 = "kg/m³" x_label2 = "lb/ft³" if unit == "in": f = 16.0185 x_label1 = "lb/ft³" x_label2 = "kg/m³" fig2 = figure( tools="pan, box_zoom, wheel_zoom, reset, save", title="CSR vs. Mean Gas Density - (API 684 - SP 6.8.5.10)", width=640, height=480, x_axis_label=x_label1, y_axis_label="MCSR", y_range=DataRange1d(start=0), x_range=DataRange1d(start=0), ) fig2.title.text_font_size = "14pt" fig2.xaxis.axis_label_text_font_size = "20pt" fig2.yaxis.axis_label_text_font_size = "20pt" fig2.axis.major_label_text_font_size = "16pt" fig2.extra_x_ranges = {"x_range2": Range1d(f * min(RHO), f * max(RHO))} fig2.add_layout( LinearAxis( x_range_name="x_range2", axis_label=x_label2, axis_label_text_font_size="11pt", ), place="below", ) fig2.add_layout( Label( x=RHO_mean, y=CSR, text=self.tag, text_font_style="bold", text_font_size="12pt", text_baseline="middle", text_align="left", x_offset=10, ) ) for txt, x, y in zip(["Region A", "Region B"], [30, 60], [1.20, 2.75]): fig2.add_layout( Label( x=x, y=y, text=txt, text_alpha=0.4, text_font_style="bold", text_font_size="12pt", text_baseline="middle", text_align="center", ) ) fig2.line(x=RHO, y=CSR_boundary, line_width=3, line_color=bokeh_colors[0]) fig2.circle(x=RHO_mean, y=CSR, size=8, color=bokeh_colors[0]) # Level 1 screening criteria - API 684 - SP6.8.5.10 idx = min(range(len(RHO)), key=lambda i: abs(RHO[i] - RHO_mean)) if self.machine_type == "compressor": if Q0 / Qa < 2.0: condition = "required" if log_dec_a < 0.1: condition = "required" if 2.0 < Q0 / Qa < 10.0 and CSR > CSR_boundary[idx]: condition = "required" else: condition = "not required" if self.machine_type == "turbine" or self.machine_type == "axial flow": if log_dec_a < 0.1: condition = "required" else: condition = "not required" # updating attributes self.Q0 = Q0 self.Qa = Qa self.log_dec_a = log_dec_a self.CSR = CSR self.Qratio = Q0 / Qa self.crit_speed = crit_speed self.MCS = self.maxspeed self.RHO_gas = RHO_mean self.condition = condition return fig1, fig2
def report2(): # rotor type: double overhung i_d = 0 o_d = 0.05 n = 6 L = [0.25 for _ in range(n)] shaft_elem = [ ShaftElement( l, i_d, o_d, material=steel, shear_effects=True, rotary_inertia=True, gyroscopic=True, ) for l in L ] disk0 = DiskElement.from_geometry(n=0, material=steel, width=0.07, i_d=0.05, o_d=0.28) disk1 = DiskElement.from_geometry(n=6, material=steel, width=0.07, i_d=0.05, o_d=0.28) stfx = [0.4e7, 0.5e7, 0.6e7, 0.7e7] stfy = [0.8e7, 0.9e7, 1.0e7, 1.1e7] freq = [400, 800, 1200, 1600] bearing0 = BearingElement(2, kxx=stfx, kyy=stfy, cxx=2e3, frequency=freq) bearing1 = BearingElement(4, kxx=stfx, kyy=stfy, cxx=2e3, frequency=freq) oper_clerance_brg = [bearing0, bearing1] rotor = Rotor(shaft_elem, [disk0, disk1], [bearing0, bearing1]) # coefficients for minimum clearance stfx = [0.7e7, 0.8e7, 0.9e7, 1.0e7] dampx = [2.0e3, 1.9e3, 1.8e3, 1.7e3] freq = [400, 800, 1200, 1600] bearing0 = BearingElement(2, kxx=stfx, cxx=dampx, frequency=freq) bearing1 = BearingElement(4, kxx=stfx, cxx=dampx, frequency=freq) min_clearance_brg = [bearing0, bearing1] # coefficients for maximum clearance stfx = [0.4e7, 0.5e7, 0.6e7, 0.7e7] dampx = [2.8e3, 2.7e3, 2.6e3, 2.5e3] freq = [400, 800, 1200, 1600] bearing0 = BearingElement(2, kxx=stfx, cxx=dampx, frequency=freq) bearing1 = BearingElement(4, kxx=stfx, cxx=dampx, frequency=freq) max_clearance_brg = [bearing0, bearing1] config = Config() config.update_config( rotor_properties={ "rotor_speeds": { "min_speed": 3820.0, "max_speed": 9550.0, "oper_speed": 8000.0, "trip_speed": 10500.0, "unit": "rpm", }, "rotor_id": { "type": "axial_flow" }, }, bearings={ "oper_clearance": oper_clerance_brg, "min_clearance": min_clearance_brg, "max_clearance": max_clearance_brg, }, run_campbell={"speed_range": np.linspace(0, 1500, 51)}, run_unbalance_response={ "probes": { "node": [1, 4], "orientation": [np.pi / 2, np.pi / 2], "unit": "rad", }, "frequency_range": np.linspace(0, 1500, 101), "plot_deflected_shape": { "speed": [615] }, }, plot_ucs={"stiffness_range": (5, 8)}, stability_level1={ "D": [0.35, 0.35], "H": [0.08, 0.08], "rated_power": [6000, 8000], "rho_ratio": [1.11, 1.14], "rho_suction": 30.45, "rho_discharge": 37.65, "length_unit": "m", "power_unit": "hp", "density_unit": "kg/m**3", }, ) return Report(rotor, config)
def test_from_table(): bearing_file = (os.path.dirname(os.path.realpath(__file__)) + "/data/bearing_seal.xls") bearing = BearingElement.from_table(0, bearing_file) assert bearing.n == 0 assert math.isclose(bearing.w[2], 523.6, abs_tol=0.1)
def test_from_table(): bearing_file = os.path.dirname( os.path.realpath(__file__)) + "/data/bearing_seal.xls" bearing = BearingElement.from_table(0, bearing_file) assert bearing.n == 0 assert bearing.w[2] == 5000
def report1(): # rotor type: single overhung i_d = 0.0 o_d = 0.05 n = 50 L = [0.03 for _ in range(n)] shaft_elem = [ ShaftElement( l, i_d, o_d, material=steel, shear_effects=True, rotary_inertia=True, gyroscopic=True, ) for l in L ] disk0 = DiskElement.from_geometry( n=0, material=steel, width=0.07, i_d=0.05, o_d=0.28 ) stfx = 1e6 stfy = 0.8e6 bearing0 = BearingElement(15, kxx=stfx, kyy=stfy, cxx=1000) bearing1 = BearingElement(50, kxx=stfx, kyy=stfy, cxx=1000) rotor = Rotor(shaft_elem, [disk0], [bearing0, bearing1]) # coefficients for minimum clearance stfx = [0.7e7, 0.8e7, 0.9e7, 1.0e7] dampx = [2.0e3, 1.9e3, 1.8e3, 1.7e3] freq = [400, 800, 1200, 1600] bearing0 = BearingElement(0, kxx=stfx, cxx=dampx, frequency=freq) bearing1 = BearingElement(6, kxx=stfx, cxx=dampx, frequency=freq) min_clearance_brg = [bearing0, bearing1] # coefficients for maximum clearance stfx = [0.4e7, 0.5e7, 0.6e7, 0.7e7] dampx = [2.8e3, 2.7e3, 2.6e3, 2.5e3] freq = [400, 800, 1200, 1600] bearing0 = BearingElement(0, kxx=stfx, cxx=dampx, frequency=freq) bearing1 = BearingElement(6, kxx=stfx, cxx=dampx, frequency=freq) max_clearance_brg = [bearing0, bearing1] bearing_clearance_lists = [min_clearance_brg, max_clearance_brg] bearing_stiffness_range = (5, 8) speed_range = (400, 1000) tripspeed = 1200 machine_type = "turbine" units = "rad/s" return Report( rotor, speed_range, tripspeed, bearing_stiffness_range, bearing_clearance_lists, machine_type, units, )
def bearing_constant(): bearing = BearingElement(n=4, kxx=8e7, cxx=0) return bearing
def stability_level_1(self, D, H, HP, N, RHOd, RHOs, steps=21, unit="m"): """Stability analysis level 1. This analysis consider a anticipated cross coupling QA based on conditions at the normal operating point and the cross-coupling required to produce a zero log decrement, Q0. Components such as seals and impellers are not considered in this analysis. Parameters ---------- D : list Impeller diameter, m (in.), Blade pitch diameter, m (in.), H : list Minimum diffuser width per impeller, m (in.), Effective blade height, m (in.), HP : list Rated power per stage/impeller, W (HP), N : float Operating speed, rpm, RHOd : float Discharge gas density per impeller, kg/m3 (lbm/in.3), RHOs : float Suction gas density per impeller, kg/m3 (lbm/in.3). steps : int Number of steps in the cross coupled stiffness range. Default is 21. unit : str Adopted unit system. Default is "m" Return ------ Example ------- """ if unit == "m": C = 9.55 elif unit == "in": C = 63.0 else: raise TypeError("choose between meters (m) or inches (in)") if len(D) != len(H): raise Exception("length of D must be the same of H") # Qa - Anticipated cross-coupling - API 684 - SP6.8.5.6 if self.machine_type == "compressor": Bc = 3.0 Dc, Hc = D, H Qa = 0.0 Qa_list = [] for i in range(len(self.rotor.disk_elements)): qi = (HP[i] * Bc * C * RHOd) / (Dc[i] * Hc[i] * N * RHOs) Qa_list.append(qi) Qa += qi # Qa - Anticipated cross-coupling - API 684 - SP6.8.5.6 if self.machine_type == "turbine" or self.machine_type == "axial_flow": Bt = 1.5 Dt, Ht = D, H Qa = 0.0 Qa_list = [] for i in range(len(self.rotor.disk_elements)): qi = (HP[i] * Bt * C) / (Dt[i] * Ht[i] * N) Qa_list.append(qi) Qa += qi cross_coupled_stiff = np.linspace(0, 10 * Qa, steps) log_dec = np.zeros(len(cross_coupled_stiff)) for i, Q in enumerate(cross_coupled_stiff): bearings = [copy(b) for b in self.rotor.bearing_seal_elements] if self.rotor_type == "between_bearings": # cross-coupling introduced at the rotor mid-span n = np.round(np.mean(self.rotor.nodes)) cross_coupling = BearingElement(n=int(n), kxx=0, cxx=0, kxy=Q, kyx=-Q) bearings.append(cross_coupling) else: # cross-coupling introduced at overhung disks for n in self.disk_nodes: cross_coupling = BearingElement(n=int(n), kxx=0, cxx=0, kxy=Q, kyx=-Q) bearings.append(cross_coupling) aux_rotor = Rotor( self.rotor.shaft_elements, self.rotor.disk_elements, bearings, self.rotor.rated_w, ) non_backward = aux_rotor.whirl_direction() != "Backward" log_dec[i] = aux_rotor.log_dec[non_backward][0] g = interp1d(cross_coupled_stiff, log_dec, fill_value="extrapolate", kind="quadratic") stiff = cross_coupled_stiff[-1] * (1 + 1 / (len(cross_coupled_stiff))) while g(stiff) > 0: log_dec = np.append(log_dec, g(stiff)) cross_coupled_stiff = np.append(cross_coupled_stiff, stiff) stiff += cross_coupled_stiff[-1] / (len(cross_coupled_stiff)) Q0 = cross_coupled_stiff[-1] # CSR - Critical Speed Ratio CSR = self.maxspeed / self.rotor.run_modal(speed=self.maxspeed).wn[0] # RHO_mean - Average gas density RHO_mean = (RHOd + RHOs) / 2 RHO = np.linspace(0, RHO_mean * 5, 201) Qc = np.piecewise( RHO, [RHO <= 16.53, RHO > 16.53, RHO == 60, RHO > 60], [2.5, lambda RHO: (-0.0115 * RHO + 2.69), 2.0, 0.0], ) # Plot area fig1 = figure( tools="pan, box_zoom, wheel_zoom, reset, save", title= "Applied Cross-Coupled Stiffness vs. Log Decrement - (API 684 - SP 6.8.5.10)", x_axis_label="Applied Cross-Coupled Stiffness, Q (N/m)", y_axis_label="Log Dec", x_range=(0, max(cross_coupled_stiff)), y_range=DataRange1d(start=0), ) fig1.title.text_font_size = "11pt" fig1.xaxis.axis_label_text_font_size = "11pt" fig1.yaxis.axis_label_text_font_size = "11pt" fig1.line(cross_coupled_stiff, log_dec, line_width=3, line_color=bokeh_colors[0]) fig1.add_layout( Span( location=Qa, dimension="height", line_color="black", line_dash="dashed", line_width=3, )) if unit == "m": f = 0.062428 x_label1 = "kg/m³" x_label2 = "lb/ft³" if unit == "in": f = 16.0185 x_label1 = "lb/ft³" x_label2 = "kg/m³" fig2 = figure( tools="pan, box_zoom, wheel_zoom, reset, save", title="CSR vs. Mean Gas Density - (API 684 - SP 6.8.5.10)", x_axis_label=x_label1, y_axis_label="MCSR", y_range=DataRange1d(start=0), x_range=DataRange1d(start=0)) fig2.title.text_font_size = "11pt" fig2.xaxis.axis_label_text_font_size = "11pt" fig2.yaxis.axis_label_text_font_size = "11pt" fig2.extra_x_ranges = {"x_range2": Range1d(f * min(RHO), f * max(RHO))} fig2.add_layout(LinearAxis(x_range_name="x_range2", axis_label=x_label2, axis_label_text_font_size="11pt"), place="below") fig2.add_layout( Label( x=RHO_mean, y=CSR, text=self.tag, text_font_style="bold", text_font_size="12pt", text_baseline="middle", text_align="left", x_offset=10, )) for txt, x, y in zip(["Region A", "Region B"], [30, 60], [1.20, 2.75]): fig2.add_layout( Label( x=x, y=y, text=txt, text_font_style="bold", text_font_size="12pt", text_baseline="middle", text_align="center", )) fig2.line(x=RHO, y=Qc, line_width=3, line_color=bokeh_colors[0]) fig2.circle(x=RHO_mean, y=CSR, size=8, color=bokeh_colors[0]) plot = gridplot([[fig1, fig2]]) return plot