def calculate_diameter(self) -> qty.Length: """ Calculate the diameter of the pipe if flow rate and friction loss are given on creation. **Returns:** (*quantities.Length*) = calculated or theoretical inside diameter of the pipe. """ # given: friction loss and flow rate rho = self._fluid.density() mu = self._fluid.kinematic_viscosity() pi = math.pi dpf = self._dp_fric V = self._flow_rate l = self._length f = 0.03 i = 0 di: float = 0.0 while i < self._max_iterations: di = (f * l / dpf * rho * 8.0 / (pi**2.0) * V**2.0)**(1.0 / 5.0) A = pi * di**2.0 / 4.0 v = V / A re = reynolds_number(v, di, mu) rel_pipe_rough = self._rough / di f_new = darcy_friction_factor(re, rel_pipe_rough) if abs(f_new - f) <= 1.0e-5: break else: f = f_new i += 1 if i == self._max_iterations: raise OverflowError( 'too many iterations. no solution found') self._cross_section.diameter = qty.Length(di) return qty.Length(di)
def inside_diameter(cls, DN: qty.Length) -> qty.Length: """ Get inside diameter (*quantities.Length*) of pipe with nominal diameter DN (*quantities.Length*). """ DN = int(DN('mm')) try: return qty.Length(cls.dimensions.loc[DN, 'd_int'], 'mm') except KeyError: return qty.Length(0.0, 'mm')
def velocity(self) -> qty.Velocity: """Get flow velocity (*quantities.Velocity*) in the section.""" if self.type != 'pseudo': di = self._pipe_schedule.inside_diameter(self.nominal_diameter) else: di = qty.Length(math.nan) return qty.Velocity(self.V / (math.pi * di()**2 / 4.0))
def wall_thickness(cls, DN: qty.Length) -> qty.Length: """ Get wall thickness (*quantities.Length*) of pipe with nominal diameter DN (*quantities.Length*). """ DN = int(DN('mm')) return qty.Length(cls.dimensions.loc[DN, 't'], 'mm')
def outside_diameter(cls, DN: qty.Length) -> qty.Length: """ Get outside diameter (*quantities.Length*) of pipe with nominal diameter DN (*quantities.Length*). """ DN = int(DN('mm')) return qty.Length(cls.dimensions.loc[DN, 'd_ext'], 'mm')
def diameter(self) -> qty.Length: """ Get/set the inside diameter (object of type *quantities.Length*) of the pipe section the fitting or valve belongs to. """ return qty.Length(self._di)
def zeta(self) -> float: """ Get the resistance coefficient (*float*) of the fitting or valve. """ if not math.isnan(self._zeta_inf): dp = self._calc_pressure_drop_3K() vp = self._fluid.density('kg/m^3') * self._vel**2.0 / 2.0 return dp / vp elif not math.isnan(self._zeta): return self._zeta elif not math.isnan(self._Kv): return ResistanceCoefficient.from_Kv(self._Kv, qty.Length(self._di)) elif not math.isnan(self._ELR): return ResistanceCoefficient.from_ELR(self._ELR, qty.Length(self._di))
def nominal_diameter(self) -> qty.Length: """ Get/set the nominal diameter (*quantities.Length*) of the cross section. The inside diameter that corresponds with the nominal diameter is also set based on the pipe schedule that was passed at the instance the CrossSection object was created. """ return qty.Length(self._dn)
def diameter(self) -> qty.Length: """ Get/set the inside diameter (*quantities.Length) of the cross section. This will also set the nearest nominal diameter and corresponding inside diameter based on the pipe schedule that was passed when creating the cross section. """ return qty.Length(self._di)
def height(self) -> qty.Length: """ Get the height difference (*quantities.Length*) between the end node of the last real section and the start node of first real section in the path. (Any pseudo sections in the path are ignored.) """ first = self.get_first_real_section() last = self.get_last_real_section() z1 = first.start_node.height() z2 = last.end_node.height() return qty.Length(z2 - z1)
def nominal_diameter(cls, d_int: Optional[qty.Length] = None, d_ext: Optional[qty.Length] = None) -> qty.Length: """ Get nearest nominal diameter when either inside or either outside diameter is given. **Parameters:** - `d_int`: (*quantities.Length*) = inside diameter (default None). - `d_ext`: (*quantities.Length*) = outside diameter (default None). **Returns:** (*quantities.Length*) """ if d_int: d_int = d_int('mm') delta = [abs(d_int - d_int_40) for d_int_40 in cls.dimensions['d_int']] idx = delta.index(min(delta)) return qty.Length(cls.dimensions.index[idx], 'mm') elif d_ext: d_ext = d_ext('mm') delta = [d_ext - d_ext_40 for d_ext_40 in cls.dimensions['d_ext']] idx = delta.index(min(delta)) return qty.Length(cls.dimensions.index[idx], 'mm')
def create(cls, id_: str, height: qty.Length = qty.Length(0.0)) -> 'Node': """ Create network node. **Parameters:** - `id_`: (*str*) = the id of the node - height: (*quantities.Length*) = height of the node with respect to a reference plane **Returns:** (*Node*) """ n = cls() n.id = id_ n.height = height return n
class GebMapressSteel(PipeSchedule): """ Class that holds dimensional data and pipe wall roughness for Geberit Mapress C Steel. """ d_ext = [12.0, 15.0, 18.0, 22.0, 28.0, 35.0, 42.0, 54.0, 76.1, 66.7, 88.9, 108.0] # [mm] t = [1.2, 1.2, 1.2, 1.5, 1.5, 1.5, 1.5, 1.5, 2.0, 1.5, 2.0, 2.0] # [mm] d_int = [d_ext - 2 * t for d_ext, t in zip(d_ext, t)] # [mm] d_nom = [10, 12, 15, 20, 25, 32, 40, 50, 65, 66.7, 80, 100] # [mm] dimensions = pd.DataFrame( data={ 'd_ext': d_ext, 't': t, 'd_int': d_int }, index=pd.Index(data=d_nom, name='DN') ) pipe_roughness = qty.Length(0.010, 'mm')
class PipeSchedule40(PipeSchedule): """ Class that holds dimensional data and pipe wall roughness for pipe schedule 40 (ANSI B36.10 - B36.19) for carbon and alloy steel + stainless steel. """ d_ext = [10.3, 13.7, 17.1, 21.3, 26.7, 33.4, 42.2, 48.3, 60.3, 73.0, 88.9, 101.6, 114.3] # [mm] t = [1.73, 2.24, 2.31, 2.77, 2.87, 3.38, 3.56, 3.68, 3.91, 5.16, 5.49, 5.74, 6.02] # [mm] d_int = [6.84, 9.22, 12.5, 15.8, 21.0, 26.6, 35.1, 40.9, 52.5, 62.7, 77.9, 90.1, 102.3] # [mm] d_nom = [6, 8, 10, 15, 20, 25, 32, 40, 50, 65, 80, 90, 100] # [mm] dimensions = pd.DataFrame( data={ 'd_ext': d_ext, 't': t, 'd_int': d_int }, index=pd.Index(data=d_nom, name='DN') ) pipe_roughness = qty.Length(0.046, 'mm')
def length(self) -> qty.Length: """Get length (*quantities.Length*) of the section.""" return qty.Length(self._length)
def nominal_diameter(self) -> qty.Length: """Get diameter (*quantities.Length*) of the section.""" return qty.Length(self._nom_diameter)
""" DEMO 7 ------ Calculate resistance coefficient of elbow from ELR coefficient (Crane-K-method) """ import quantities as qty from pypeflow.core.resistance_coefficient import ResistanceCoefficient from pypeflow.core.pipe_schedules import PipeSchedule40 ELR_elbow = 30.0 # see Crane Technical Paper, appendix A di = PipeSchedule40.inside_diameter(DN=qty.Length(15.0, 'mm')) zeta_elbow = ResistanceCoefficient.from_ELR(ELR=ELR_elbow, di=di) print(f'resistance coefficient elbow = {zeta_elbow:.3f}')
""" DEMO 8 ------ Create a check valve fitting """ import quantities as qty from pypeflow.core.fitting import Fitting from pypeflow.core.fluids import Water from pypeflow.core.cross_sections import Circular from pypeflow.core.pipe_schedules import PipeSchedule40 flow_rate = qty.VolumeFlowRate(1.696, 'L/s') cross_section = Circular.create(pipe_schedule=PipeSchedule40, dn=qty.Length(40.0, 'mm')) velocity = qty.Velocity(flow_rate() / cross_section.area()) check_valve = Fitting.create_w_velocity(type_='check_valve', fluid=Water(10.0), velocity=velocity, di=cross_section.diameter, ELR=55.0) # pressure drop across fitting dp_fitting = check_valve.pressure_drop print(f'Pressure drop across check valve = {dp_fitting("Pa"):.3f} Pa') # resistance coefficient of fitting zeta = check_valve.zeta print(f'Resistance coefficient of check valve = {zeta:.3f}')
def calculated_diameter(self) -> qty.Length: """ Get the calculated or theoretical inside diameter (*quantities.Length*) of the cross section. """ return qty.Length(self._di_th)
def diameter(self) -> qty.Length: """ Get/set the (equivalent) diameter (*quantities.Length*) of the cross section. """ return qty.Length()
def _calc_pressure_drop_ELR(self) -> float: """Calculate pressure drop across fitting with Crane-K-method.""" vp = self._fluid.density('kg/m^3') * self._vel**2.0 / 2.0 zeta = ResistanceCoefficient.from_ELR(self._ELR, qty.Length(self._di)) return zeta * vp
def roughness(self) -> qty.Length: """Get/set the pipe wall roughness (*quantities.Length*) of the pipe.""" return qty.Length(self._rough)
def height(self) -> qty.Length: """Get/set the height (*quantities.Length*) of the node with respect to a reference plane.""" return qty.Length(self._height)
""" DEMO 5 ------ Calculate pressure drop in a pipe. """ from pypeflow.core import Pipe from pypeflow.core.fluids import Water from pypeflow.core.pipe_schedules import PipeSchedule40 import quantities as qty pipe = Pipe.create( fluid=Water(10.0), pipe_schedule=PipeSchedule40, length=qty.Length(2.7, 'm'), flow_rate=qty.VolumeFlowRate(2.180, 'L/s'), nominal_diameter=qty.Length(40.0, 'mm'), sum_zeta=-0.029 ) print(f'Pressure drop = {pipe.pressure_loss("bar"):.3f} bar.')
def length(self) -> qty.Length: """Get/set the length (*quantities.Length*) of the pipe.""" return qty.Length(self._length)