def Q_weir_V_Shen(h1, angle=90): r'''Calculates the flow rate across a V-notch (triangular) weir from the height of the liquid above the tip of the notch, and with the angle of the notch. Most of these type of weir are 90 degrees. Model from [1]_ as reproduced in [2]_. Flow rate is given by: .. math:: Q = C \tan\left(\frac{\theta}{2}\right)\sqrt{g}(h_1 + k)^{2.5} Parameters ---------- h1 : float Height of the fluid above the notch [m] angle : float, optional Angle of the notch [degrees] Returns ------- Q : float Volumetric flow rate across the weir [m^3/s] Notes ----- angles = [20, 40, 60, 80, 100] Cs = [0.59, 0.58, 0.575, 0.575, 0.58] k = [0.0028, 0.0017, 0.0012, 0.001, 0.001] The following limits apply to the use of this equation: h1 >= 0.05 m h2 > 0.45 m h1/h2 <= 0.4 m b > 0.9 m .. math:: \frac{h_1}{b}\tan\left(\frac{\theta}{2}\right) < 2 Flows are lower than obtained by the curves at http://www.lmnoeng.com/Weirs/vweir.php. Examples -------- >>> Q_weir_V_Shen(0.6, angle=45) 0.21071725775478228 References ---------- .. [1] Shen, John. "Discharge Characteristics of Triangular-Notch Thin-Plate Weirs : Studies of Flow to Water over Weirs and Dams." USGS Numbered Series. Water Supply Paper. U.S. Geological Survey : U.S. G.P.O., 1981 .. [2] Blevins, Robert D. Applied Fluid Dynamics Handbook. New York, N.Y.: Van Nostrand Reinhold Co., 1984. ''' C = interp(angle, angles_Shen, Cs_Shen) k = interp(angle, angles_Shen, k_Shen) return C*tan(radians(angle)/2)*g**0.5*(h1 + k)**2.5
def API520_B(Pset, Pback, overpressure=0.1): r'''Calculates capacity correction due to backpressure on balanced spring-loaded PRVs in vapor service. For pilot operated valves, this is always 1. Applicable up to 50% of the percent gauge backpressure, For use in API 520 relief valve sizing. 1D interpolation among a table with 53 backpressures is performed. Parameters ---------- Pset : float Set pressure for relief [Pa] Pback : float Backpressure, [Pa] overpressure : float, optional The maximum fraction overpressure; one of 0.1, 0.16, or 0.21, [-] Returns ------- Kb : float Correction due to vapor backpressure [-] Notes ----- If the calculated gauge backpressure is less than 30%, 38%, or 50% for overpressures of 0.1, 0.16, or 0.21, a value of 1 is returned. Percent gauge backpressure must be under 50%. Examples -------- Custom examples from figure 30: >>> API520_B(1E6, 5E5) 0.7929945420944432 References ---------- .. [1] API Standard 520, Part 1 - Sizing and Selection. ''' gauge_backpressure = (Pback - atm) / (Pset - atm) * 100.0 # in percent if overpressure not in (0.1, 0.16, 0.21): raise Exception('Only overpressure of 10%, 16%, or 21% are permitted') if (overpressure == 0.1 and gauge_backpressure < 30.0) or ( overpressure == 0.16 and gauge_backpressure < 38.0) or (overpressure == 0.21 and gauge_backpressure < 50.0): return 1.0 elif gauge_backpressure > 50.0: raise Exception('Gauge pressure must be < 50%') if overpressure == 0.16: Kb = interp(gauge_backpressure, Kb_16_over_x, Kb_16_over_y) elif overpressure == 0.1: Kb = interp(gauge_backpressure, Kb_10_over_x, Kb_10_over_y) return Kb
def API520_B(Pset, Pback, overpressure=0.1): r'''Calculates capacity correction due to backpressure on balanced spring-loaded PRVs in vapor service. For pilot operated valves, this is always 1. Applicable up to 50% of the percent gauge backpressure, For use in API 520 relief valve sizing. 1D interpolation among a table with 53 backpressures is performed. Parameters ---------- Pset : float Set pressure for relief [Pa] Pback : float Backpressure, [Pa] overpressure : float, optional The maximum fraction overpressure; one of 0.1, 0.16, or 0.21, [] Returns ------- Kb : float Correction due to vapor backpressure [-] Notes ----- If the calculated gauge backpressure is less than 30%, 38%, or 50% for overpressures of 0.1, 0.16, or 0.21, a value of 1 is returned. Percent gauge backpressure must be under 50%. Examples -------- Custom examples from figure 30: >>> API520_B(1E6, 5E5) 0.7929945420944432 References ---------- .. [1] API Standard 520, Part 1 - Sizing and Selection. ''' gauge_backpressure = (Pback-atm)/(Pset-atm)*100 # in percent if overpressure not in [0.1, 0.16, 0.21]: raise Exception('Only overpressure of 10%, 16%, or 21% are permitted') if (overpressure == 0.1 and gauge_backpressure < 30) or ( overpressure == 0.16 and gauge_backpressure < 38) or ( overpressure == 0.21 and gauge_backpressure < 50): return 1 elif gauge_backpressure > 50: raise Exception('Gauge pressure must be < 50%') if overpressure == 0.16: Kb = interp(gauge_backpressure, Kb_16_over_x, Kb_16_over_y) elif overpressure == 0.1: Kb = interp(gauge_backpressure, Kb_10_over_x, Kb_10_over_y) return Kb
def round_edge_screen(alpha, Re, angle=0.0): r'''Returns the loss coefficient for a round edged wire screen or bar screen, as shown in [1]_. Angle of inclination may be specified as well. Parameters ---------- alpha : float Fraction of screen open to flow [-] Re : float Reynolds number of flow through screen with D = space between rods, [] angle : float, optional Angle of inclination, with 0 being straight and 90 being parallel to flow [degrees] Returns ------- K : float Loss coefficient [-] Notes ----- Linear interpolation between a table of values. Re table extends from 20 to 400, with constant values outside of the table. This behavior should be adequate. alpha should be between 0.05 and 0.8. If angle is over 85 degrees, the value at 85 degrees is used. The velocity the loss coefficient relates to is the approach velocity before the screen. Examples -------- >>> round_edge_screen(0.5, 100) 2.0999999999999996 >>> round_edge_screen(0.5, 100, 45) 1.05 References ---------- .. [1] Blevins, Robert D. Applied Fluid Dynamics Handbook. New York, N.Y.: Van Nostrand Reinhold Co., 1984. ''' beta = interp(Re, round_Res, round_betas) alpha2 = alpha * alpha K = beta * (1.0 - alpha2) / alpha2 if angle is not None: if angle <= 45.0: v = cos(radians(angle)) K *= v * v else: K *= interp(angle, round_thetas, round_gammas) return K
def round_edge_screen(alpha, Re, angle=0): r'''Returns the loss coefficient for a round edged wire screen or bar screen, as shown in [1]_. Angle of inclination may be specified as well. Parameters ---------- alpha : float Fraction of screen open to flow [-] Re : float Reynolds number of flow through screen with D = space between rods, [] angle : float, optional Angle of inclination, with 0 being straight and 90 being parallel to flow [degrees] Returns ------- K : float Loss coefficient [-] Notes ----- Linear interpolation between a table of values. Re table extends from 20 to 400, with constant values outside of the table. This behavior should be adequate. alpha should be between 0.05 and 0.8. If angle is over 85 degrees, the value at 85 degrees is used. Examples -------- >>> round_edge_screen(0.5, 100) 2.0999999999999996 >>> round_edge_screen(0.5, 100, 45) 1.05 References ---------- .. [1] Blevins, Robert D. Applied Fluid Dynamics Handbook. New York, N.Y.: Van Nostrand Reinhold Co., 1984. ''' beta = interp(Re, round_Res, round_betas) alpha2 = alpha*alpha K = beta*(1.0 - alpha2)/alpha2 if angle: if angle <= 45: K *= cos(radians(angle))**2 else: K *= interp(angle, round_thetas, round_gammas) return K
def square_edge_screen(alpha): r'''Returns the loss coefficient for a square wire screen or square bar screen or perforated plate with squared edges, as shown in [1]_. Parameters ---------- alpha : float Fraction of screen open to flow [-] Returns ------- K : float Loss coefficient [-] Notes ----- Linear interpolation between a table of values. The velocity the loss coefficient relates to is the approach velocity before the screen. Examples -------- >>> square_edge_screen(0.99) 0.008000000000000007 References ---------- .. [1] Blevins, Robert D. Applied Fluid Dynamics Handbook. New York, N.Y.: Van Nostrand Reinhold Co., 1984. ''' return interp(alpha, square_alphas, square_Ks)
def square_edge_screen(alpha): r'''Returns the loss coefficient for a square wire screen or square bar screen or perforated plate with squared edges, as shown in [1]_. Parameters ---------- alpha : float Fraction of screen open to flow [-] Returns ------- K : float Loss coefficient [-] Notes ----- Linear interpolation between a table of values. Examples -------- >>> square_edge_screen(0.99) 0.008000000000000007 References ---------- .. [1] Blevins, Robert D. Applied Fluid Dynamics Handbook. New York, N.Y.: Van Nostrand Reinhold Co., 1984. ''' return interp(alpha, square_alphas, square_Ks)
def test_interp(): from fluids.numerics import interp # Real world test data a = [ 0.29916, 0.29947, 0.31239, 0.31901, 0.32658, 0.33729, 0.34202, 0.34706, 0.35903, 0.36596, 0.37258, 0.38487, 0.38581, 0.40125, 0.40535, 0.41574, 0.42425, 0.43401, 0.44788, 0.45259, 0.47181, 0.47309, 0.49354, 0.49924, 0.51653, 0.5238, 0.53763, 0.54806, 0.55684, 0.57389, 0.58235, 0.59782, 0.60156, 0.62265, 0.62649, 0.64948, 0.65099, 0.6687, 0.67587, 0.68855, 0.69318, 0.70618, 0.71333, 0.72351, 0.74954, 0.74965 ] b = [ 0.164534, 0.164504, 0.163591, 0.163508, 0.163439, 0.162652, 0.162224, 0.161866, 0.161238, 0.160786, 0.160295, 0.15928, 0.159193, 0.157776, 0.157467, 0.156517, 0.155323, 0.153835, 0.151862, 0.151154, 0.14784, 0.147613, 0.144052, 0.14305, 0.140107, 0.138981, 0.136794, 0.134737, 0.132847, 0.129303, 0.127637, 0.124758, 0.124006, 0.119269, 0.118449, 0.113605, 0.113269, 0.108995, 0.107109, 0.103688, 0.102529, 0.099567, 0.097791, 0.095055, 0.087681, 0.087648 ] xs = np.linspace(0.29, 0.76, 100) ys = [interp(xi, a, b) for xi in xs.tolist()] ys_numpy = np.interp(xs, a, b) assert_allclose(ys, ys_numpy, atol=1e-12, rtol=1e-11)
def RI_to_brix(RI): """Convert a standard refractive index measurement to the `brix` scale. Parameters ---------- RI : float Refractive index, [-] Returns ------- brix : float Degrees brix to be converted, [°Bx] Notes ----- The scale is officially defined from 0 to 85; but the data source contains values up to 95. Linear extrapolation to values under 0 or above 95 is performed. The ICUMSA (International Committee of Uniform Method of Sugar Analysis) published a document setting out the reference values in 1974; but an original data source has not been found and reviewed. Examples -------- >>> RI_to_brix(1.341452) 5.800000000000059 >>> RI_to_brix(1.33299) 0.0 >>> RI_to_brix(1.532) 95.0 References ---------- .. [1] "Refractometer Data Book-Refractive Index and Brix | ATAGO CO., LTD." Accessed June 13, 2020. https://www.atago.net/en/databook-refractometer_relationship.php. """ return interp(RI, ICUMSA_1974_RIs, ICUMSA_1974_brix, extrapolate=True)
def refractory_VDI_Cp(ID, T=None): r'''Returns heat capacity of a refractory material from a table in [1]_. Here, heat capacity is a function of temperature between 673.15 K and 1473.15 K according to linear interpolation among 5 equally-spaced points. Here, heat capacity is not a function of porosity, affects it. If T is outside the acceptable range, it is rounded to the nearest limit. If T is not provided, the lowest temperature's value is provided. Parameters ---------- ID : str ID corresponding to a material in the dictionary `refractories` T : float, optional Temperature of the refractory material, [K] Returns ------- Cp : float Heat capacity of the refractory material, [W/m/K] Examples -------- >>> [refractory_VDI_Cp('Fused silica', i) for i in [None, 200, 1000, 1500]] [917.0, 917.0, 956.78225, 982.0] References ---------- .. [1] Gesellschaft, V. D. I., ed. VDI Heat Atlas. 2nd edition. Berlin; New York:: Springer, 2010. ''' if T is None: return float(refractories[ID][2][0]) else: Cps = refractories[ID][2] if T < _refractory_Ts[0]: T = _refractory_Ts[0] elif T > _refractory_Ts[-1]: T = _refractory_Ts[-1] return float(interp(T, _refractory_Ts, Cps))
def brix_to_RI(brix): """Convert a refractive index measurement on the `brix` scale to a standard refractive index. Parameters ---------- brix : float Degrees brix to be converted, [°Bx] Returns ------- RI : float Refractive index, [-] Notes ----- The scale is officially defined from 0 to 85; but the data source contains values up to 95. Linear extrapolation outside of the bounds is performed; and a table of 96 values are linearly interpolated. The ICUMSA (International Committee of Uniform Method of Sugar Analysis) published a document setting out the reference values in 1974; but an original data source has not been found and reviewed. Examples -------- >>> brix_to_RI(5.8) 1.341452 >>> brix_to_RI(0.0) 1.33299 >>> brix_to_RI(95.0) 1.532 References ---------- .. [1] "Refractometer Data Book-Refractive Index and Brix | ATAGO CO., LTD." Accessed June 13, 2020. https://www.atago.net/en/databook-refractometer_relationship.php. """ return interp(brix, ICUMSA_1974_brix, ICUMSA_1974_RIs, extrapolate=True)
def API520_W(Pset, Pback): r'''Calculates capacity correction due to backpressure on balanced spring-loaded PRVs in liquid service. For pilot operated valves, this is always 1. Applicable up to 50% of the percent gauge backpressure, For use in API 520 relief valve sizing. 1D interpolation among a table with 53 backpressures is performed. Parameters ---------- Pset : float Set pressure for relief [Pa] Pback : float Backpressure, [Pa] Returns ------- KW : float Correction due to liquid backpressure [-] Notes ----- If the calculated gauge backpressure is less than 15%, a value of 1 is returned. Examples -------- Custom example from figure 31: >>> API520_W(1E6, 3E5) # 22% overpressure 0.9511471848008564 References ---------- .. [1] API Standard 520, Part 1 - Sizing and Selection. ''' gauge_backpressure = (Pback - atm) / (Pset - atm) * 100.0 # in percent if gauge_backpressure < 15.0: return 1.0 return interp(gauge_backpressure, Kw_x, Kw_y)
def API520_W(Pset, Pback): r'''Calculates capacity correction due to backpressure on balanced spring-loaded PRVs in liquid service. For pilot operated valves, this is always 1. Applicable up to 50% of the percent gauge backpressure, For use in API 520 relief valve sizing. 1D interpolation among a table with 53 backpressures is performed. Parameters ---------- Pset : float Set pressure for relief [Pa] Pback : float Backpressure, [Pa] Returns ------- KW : float Correction due to liquid backpressure [-] Notes ----- If the calculated gauge backpressure is less than 15%, a value of 1 is returned. Examples -------- Custom example from figure 31: >>> API520_W(1E6, 3E5) # 22% overpressure 0.9511471848008564 References ---------- .. [1] API Standard 520, Part 1 - Sizing and Selection. ''' gauge_backpressure = (Pback-atm)/(Pset-atm)*100.0 # in percent if gauge_backpressure < 15.0: return 1.0 return interp(gauge_backpressure, Kw_x, Kw_y)
def round_edge_open_mesh(alpha, subtype='diamond pattern wire', angle=0.0): r'''Returns the loss coefficient for a round edged open net/screen made of one of the following patterns, according to [1]_: 'round bar screen': .. math:: K = 0.95(1-\alpha) + 0.2(1-\alpha)^2 'diamond pattern wire': .. math:: K = 0.67(1-\alpha) + 1.3(1-\alpha)^2 'knotted net': .. math:: K = 0.70(1-\alpha) + 4.9(1-\alpha)^2 'knotless net': .. math:: K = 0.72(1-\alpha) + 2.1(1-\alpha)^2 Parameters ---------- alpha : float Fraction of net/screen open to flow [-] subtype : str One of 'round bar screen', 'diamond pattern wire', 'knotted net' or 'knotless net'. angle : float, optional Angle of inclination, with 0 being straight and 90 being parallel to flow [degrees] Returns ------- K : float Loss coefficient [-] Notes ----- `alpha` should be between 0.85 and 1 for these correlations. Flow should be turbulent, with Re > 500. The velocity the loss coefficient relates to is the approach velocity before the mesh. Examples -------- >>> round_edge_open_mesh(0.96, angle=33.) 0.02031327712601458 References ---------- .. [1] Blevins, Robert D. Applied Fluid Dynamics Handbook. New York, N.Y.: Van Nostrand Reinhold Co., 1984. ''' one_m_alpha = (1.0 - alpha) if subtype == 'round bar screen': K = 0.95 + 0.2 * one_m_alpha elif subtype == 'diamond pattern wire': K = 0.67 + 1.3 * one_m_alpha elif subtype == 'knotted net': K = 0.70 + 4.9 * one_m_alpha elif subtype == 'knotless net': K = 0.72 + 2.1 * one_m_alpha else: raise ValueError('Subtype not recognized') K *= one_m_alpha if angle is not None: if angle < 45.0: K *= cos(radians(angle))**2.0 else: K *= interp(angle, round_thetas, round_gammas) return K
def round_edge_open_mesh(alpha, subtype='diamond pattern wire', angle=0): r'''Returns the loss coefficient for a round edged open net/screen made of one of the following patterns, according to [1]_: 'round bar screen': .. math:: K = 0.95(1-\alpha) + 0.2(1-\alpha)^2 'diamond pattern wire': .. math:: K = 0.67(1-\alpha) + 1.3(1-\alpha)^2 'knotted net': .. math:: K = 0.70(1-\alpha) + 4.9(1-\alpha)^2 'knotless net': .. math:: K = 0.72(1-\alpha) + 2.1(1-\alpha)^2 Parameters ---------- alpha : float Fraction of net/screen open to flow [-] subtype : str One of 'round bar screen', 'diamond pattern wire', 'knotted net' or 'knotless net'. angle : float, optional Angle of inclination, with 0 being straight and 90 being parallel to flow [degrees] Returns ------- K : float Loss coefficient [-] Notes ----- `alpha` should be between 0.85 and 1 for these correlations. Flow should be turbulent, with Re > 500. Examples -------- >>> round_edge_open_mesh(0.96, angle=33.) 0.02031327712601458 References ---------- .. [1] Blevins, Robert D. Applied Fluid Dynamics Handbook. New York, N.Y.: Van Nostrand Reinhold Co., 1984. ''' if subtype == 'round bar screen': K = 0.95*(1-alpha) + 0.2*(1-alpha)**2 elif subtype == 'diamond pattern wire': K = 0.67*(1-alpha) + 1.3*(1-alpha)**2 elif subtype == 'knotted net': K = 0.70*(1-alpha) + 4.9*(1-alpha)**2 elif subtype == 'knotless net': K = 0.72*(1-alpha) + 2.1*(1-alpha)**2 else: raise Exception('Subtype not recognized') if angle: if angle < 45: K *= cos(radians(angle))**2 else: K *= interp(angle, round_thetas, round_gammas) return K