Beispiel #1
0
def calculate_headloss(vol_flow, flow_area, lpipe, idiameter, eroughness,
                       kin_visc, grav):
    """Calculate Darcy-Weisbach friction factor and head loss

       Calculates head loss (m) and Darcy-Wesibach friction factor and
       intermediate quantities flow velocity (m/s), and Reynolds number. These
       values are returned in a named tuple with key names ``head_loss``,
       ``friction``, ``vflow``, and ``Re`` respectively.

    Args:
        vol_flow (float): volumetric flow, in cubic meters per second
        flow_area (float): pipe flow area, in square meters
        lpipe (float): pipe length, in meters
        idiameter (float): pipe inner diameter, in meters
        eroughness (float): pipe relative roughness, dimensionless
        kin_visc (float): kinematic viscosity, in square meters per second
        grav (float): gravitational acceleration, in meters per second squared

    Returns:
        (namedtuple): Results and intermediate quantities

    """
    HeadLoss = namedtuple('HeadLoss', ['head_loss', 'friction', 'vflow', 'Re'])

    flow_vel = vol_flow / flow_area
    Re = flow_vel * idiameter / kin_visc
    friction = friction_factor(Re=Re, eD=eroughness)
    head_loss = (friction * lpipe * flow_vel**2) / (2.0 * grav * idiameter)

    hldat = HeadLoss(head_loss, friction, flow_vel, Re)

    return hldat
Beispiel #2
0
 def accept(self):
     Dp = 0
     elements = list()
     Q = float(self.form.editFlow.text()) / 3600
     if self.form.comboWhat.currentText() == '<on selection>':
         elements = FreeCADGui.Selection.getSelection()
     else:
         o = FreeCAD.ActiveDocument.getObjectsByLabel(
             self.form.comboWhat.currentText())[0]
         if hasattr(o, 'PType') and o.PType == 'PypeBranch':
             elements = o.Tubes + o.Curves
     for o in elements:
         if hasattr(o, 'PType') and o.PType in ['Pipe', 'Elbow']:
             ID = float(o.ID) / 1000
             e = float(self.form.editRough.text()) * 1e-6 / ID
             if self.isLiquid:
                 v = Q / ((ID)**2 * pi / 4)
             else:
                 v = Q / ((ID)**2 * pi / 4) / self.Rho
             Re = Reynolds(V=v, D=ID, rho=self.Rho, mu=self.Mu)
             f = friction.friction_factor(Re, eD=e)  # Darcy, =4xFanning
             if o.PType == 'Pipe':
                 L = float(o.Height) / 1000
                 K = K_from_f(fd=f, L=L, D=ID)
                 FreeCAD.Console.PrintMessage(
                     'ID=%.2f\nV=%.2f\ne=%f\nf=%f\nK=%f\nL=%.3f\n***\n' %
                     (ID, v, e, f, K, L))
                 Dp += dP_from_K(K, rho=self.Rho, V=v)
             elif o.PType == 'Elbow':
                 ang = float(o.BendAngle)
                 R = float(o.BendRadius) / 1000
                 K = fittings.bend_rounded(ID, ang, f, R)
                 FreeCAD.Console.PrintMessage(
                     'ID=%.2f\nV=%.2f\ne=%f\nf=%f\nK=%f\nang=%.3f\nR=%f\n***\n'
                     % (ID, v, e, f, K, ang, R))
                 Dp += dP_from_K(K, rho=self.Rho, V=v)
             elif o.PType == 'Reduct':
                 pass
         elif hasattr(o, 'Kv') and o.Kv > 0:
             if self.isLiquid:
                 Dp += (Q * 3600 / o.Kv)**2 * 100000
             else:
                 pass
         if Dp > 200: result = ' = %.3f bar' % (Dp / 100000)
         else: result = ' = %.2e bar' % (Dp / 100000)
         self.form.labResult.setText(result)
Beispiel #3
0
def pipe_friction(vol_flow, idiameter, kin_visc, flow_area, eroughness):
    """Calculate friction factor from pipe geometry, flow conditions, and fluid
    properties. Input values should be supplied in a consistent unit system
    (all SI or all US Traditional)

    Args:
        vol_flow (float): Volumetric flow
        idiameter (float): Pipe inner diameter
        kin_visc (float): Fluid kinematic viscosity
        flow_area (float): Pipe flow area
        eroughness (float): Relative pipe roughness.

    Returns:
        (float): Darcy-Weisbach friction factor"""
    vflow = vol_flow / flow_area
    Re = vflow * idiameter / kin_visc
    friction = friction_factor(Re=Re, eD=eroughness)
    _logger.debug('{0:16s}{1:12.4E}'.format('vflow', vflow))
    _logger.debug('{0:16s}{1:12.4E}'.format('Re', Re))

    return friction
Beispiel #4
0
    def set_flow_conditions(self, vol_flow, kin_visc):
        """Specify volumetric flow and fluid properties so flow velocity,
        Reynolds number, and friction factor may be calculated.

        Args:
            vol_flow (Quantity): Volumetric flow rate
            kin_visc (Quantity): Kinematic viscosity

        Raises:
            ValueError: An error occurred deriving friction factor, etc."""
        self._vol_flow = vol_flow
        self._kin_visc = kin_visc

        self._vflow = self._vol_flow / self.flow_area

        self._Re = (self._vflow.to('m/s') * self._idiameter.to('m') /
                    self._kin_visc.to('m**2/s')).magnitude

        self._friction = friction_factor(Re=self._Re, eD=self._eroughness)

        self._flow_set = True

        return
Beispiel #5
0
def calculate(doc_original):
    doc = deepcopy(doc_original)
    treeUnitConvert(doc, doc['units'], SI_UNITS)

    K_pipe = 0
    K_fittings = 0
    K_entry = 0
    K_exit = 0
    K_fixed = 0
    K_LbyD = 0
    K_total = 0
    LbyD_total = 0
    deltaP_fixed = 0
    deltaP_total = 0

    size_definition = doc['input']['pipe']['size_definition']['_val']
    if (size_definition == "NPS"):
        nps = float(doc['input']['pipe']['NPS']['_val'])
        schedule = doc['input']['pipe']['schedule']['_val']
        NPS, Di, Do, t = nearest_pipe(NPS=nps, schedule=schedule)
    else:
        Di = float(doc['input']['pipe']['Dia_inner']['_val'])
        NPS = math.nan
        Do = math.nan
        t = math.nan

    doc['result'].update({'Di': {'_val': str(Di), '_dim': 'length_mili'}})
    doc['result'].update({'Do': {'_val': str(Do), '_dim': 'length_mili'}})
    doc['result'].update({'t': {'_val': str(t), '_dim': 'length_mili'}})

    area = math.pi * pow(Di / 2, 2)
    Q = float(doc['input']['fluidData']['Q']['_val'])
    V = roundit(Q / area)
    doc['result'].update({'V': {'_val': str(V), '_dim': 'speed'}})

    mu = float(doc['input']['fluidData']['mu']['_val'])
    rho = float(doc['input']['fluidData']['rho']['_val'])
    Re = roundit(Reynolds(V=V, D=Di, rho=rho, mu=mu))
    doc['result'].update({'Re': {'_val': str(Re)}})

    Hdyn = roundit(rho * pow(V, 2) / 2)
    doc['result'].update({'Hdyn': {'_val': str(Hdyn), '_dim': 'length'}})

    #K calculation for straigth pipe
    roughness_basis = doc['input']['pipe']['roughness_basis']['_val']
    if (roughness_basis == "Material"):
        material = doc['input']['pipe']['material']['_val']
        roughness = get_roughness(material)
    else:
        roughness = float(doc['input']['pipe']['roughness']['_val'])

    eD = roughness / Di

    doc['result'].update({'eD': {'_val': str(eD)}})
    fd = roundit(friction_factor(Re=Re, eD=eD, Method="Moody"))
    doc['result'].update({'fd_Moody': {'_val': str(fd)}})

    length = float(doc['input']['pipe']['length']['_val'])
    K_pipe = roundit(K_from_f(fd=fd, L=length, D=Di))
    doc['result'].update({'K_pipe': {'_val': str(K_pipe)}})
    deltaP_pipe = roundit(dP_from_K(K_pipe, rho, V))
    doc['result'].update(
        {'deltaP_pipe': {
            '_val': str(deltaP_pipe),
            '_dim': 'pressure'
        }})

    #calculating pressure drop for entrance

    entry_type = doc['input']['entrance']['entry_type']['_val']
    print('entry type is')
    print(entry_type)
    if entry_type == 'none':
        K_entry = 0
    elif entry_type == 'Sharp':
        K_entry = fluids.fittings.entrance_sharp()
    elif entry_type == 'Rounded':
        Rc = float(doc['input']['entrance']['Rc']['_val'])
        K_entry = fluids.fittings.entrance_rounded(Di, Rc)
    elif entry_type == 'Angled':
        angle_radians = float(doc['input']['entrance']['angle']['_val'])
        angle = angle_radians * 57.2958
        K_entry = fluids.fittings.entrance_angled(angle)
    elif entry_type == 'Projecting':
        wall_thickness = float(
            doc['input']['entrance']['wall_thickness']['_val'])
        K_entry = fluids.fittings.entrance_distance(Di, wall_thickness)

    K_entry = roundit(K_entry)
    doc['result'].update({'K_entry': {'_val': str(K_entry)}})
    deltaP_entry = roundit(dP_from_K(K_entry, rho, V))
    doc['result'].update(
        {'deltaP_entry': {
            '_val': str(deltaP_entry),
            '_dim': 'pressure'
        }})

    #calculating pressure drop for exit
    exit_type = doc['input']['exit']['exit_type']['_val']
    print('exit_type')
    print(exit_type)
    if (exit_type == 'Normal'):
        K_exit = exit_normal()
    else:
        K_exit = 0

    K_exit = roundit(K_exit)
    doc['result'].update({'K_exit': {'_val': str(K_exit)}})
    deltaP_exit = roundit(dP_from_K(K_exit, rho, V))
    doc['result'].update(
        {'deltaP_exit': {
            '_val': str(deltaP_exit),
            '_dim': 'pressure'
        }})

    #calculating pressure drop for fittings
    fittings_list = doc['input']['fittings']
    for fitting in fittings_list:
        name = get_hooper_list()[fitting['index']]
        Di_inch = Di * 39.3701
        K_fitting = Hooper2K(Di_inch, Re, name=name)
        K_fittings += K_fitting * fitting['quantity']

    K_fittings = roundit(K_fittings)
    doc['result'].update({'K_fittings': {'_val': str(K_fittings)}})
    deltaP_fittings = dP_from_K(K_fittings, rho, V)
    deltaP_fittings = roundit(deltaP_fittings)
    doc['result'].update({
        'deltaP_fittings': {
            '_val': str(deltaP_fittings),
            '_dim': 'pressure'
        }
    })

    #calculating pressure drop for sharp contractions
    deltaP_contractions_sharp = 0
    contractions_sharp = doc['input']['contractions_sharp']['_list']
    for contraction in contractions_sharp:
        D1 = contraction['D1']
        D2 = contraction['D2']
        A2 = 3.1416 * (D2**2) / 4
        V2 = Q / A2
        K_contraction = fluids.fittings.contraction_sharp(D1, D2)
        deltaP = dP_from_K(K_contraction, rho, V2)
        deltaP_contractions_sharp += deltaP

    deltaP_contractions_sharp = roundit(deltaP_contractions_sharp)
    doc['result'].update({
        'deltaP_contractions_sharp': {
            '_val': str(deltaP_contractions_sharp),
            '_dim': 'pressure'
        }
    })

    #calculating pressure drop for rounded contractions
    deltaP_contractions_rounded = 0
    contractions_rounded = doc['input']['contractions_rounded']['_list']
    for contraction in contractions_rounded:
        D1 = contraction['D1']
        D2 = contraction['D2']
        Rc = contraction['Rc']
        A2 = 3.1416 * (D2**2) / 4
        V2 = Q / A2
        K_contraction = fluids.fittings.contraction_round(D1, D2, Rc)
        deltaP = dP_from_K(K_contraction, rho, V2)
        deltaP_contractions_rounded += deltaP

    deltaP_contractions_rounded = roundit(deltaP_contractions_rounded)
    doc['result'].update({
        'deltaP_contractions_rounded': {
            '_val': str(deltaP_contractions_rounded),
            '_dim': 'pressure'
        }
    })

    #calculating pressure drop for conical contractions
    deltaP_contractions_conical = 0
    contractions_conical = doc['input']['contractions_conical']['_list']
    for contraction in contractions_conical:
        D1 = contraction['D1']
        D2 = contraction['D2']
        L = contraction['L']
        A2 = 3.1416 * (D2**2) / 4
        V2 = Q / A2
        K_contraction = fluids.fittings.contraction_conical(D1, D2, fd=fd, l=L)
        deltaP = dP_from_K(K_contraction, rho, V2)
        deltaP_contractions_conical += deltaP

    deltaP_contractions_conical = roundit(deltaP_contractions_conical)
    doc['result'].update({
        'deltaP_contractions_conical': {
            '_val': str(deltaP_contractions_conical),
            '_dim': 'pressure'
        }
    })

    #calculating pressure drop for pipe reducers contractions
    deltaP_contractions_reducer = 0
    contractions_reducer = doc['input']['contractions_reducer']['_list']
    for contraction in contractions_reducer:
        reducer_size = contraction['reducer_size']
        D1, D2, L = reducer_dimensions(reducer_size)
        A2 = 3.1416 * (D2**2) / 4
        V2 = Q / A2
        K_contraction = fluids.fittings.contraction_conical(D1, D2, fd=fd, l=L)
        deltaP = dP_from_K(K_contraction, rho, V2)
        deltaP_contractions_reducer += deltaP

    deltaP_contractions_reducer = roundit(deltaP_contractions_reducer)
    doc['result'].update({
        'deltaP_contractions_reducer': {
            '_val': str(deltaP_contractions_reducer),
            '_dim': 'pressure'
        }
    })

    # calculating total pressure drop in all contractions
    deltaP_contractions = deltaP_contractions_sharp + deltaP_contractions_rounded + deltaP_contractions_conical + deltaP_contractions_reducer
    deltaP_contractions = roundit(deltaP_contractions)
    doc['result'].update({
        'deltaP_contractions': {
            '_val': str(deltaP_contractions),
            '_dim': 'pressure'
        }
    })

    #calculating pressure drop for sharp expansions
    deltaP_expansions_sharp = 0
    expansions_sharp = doc['input']['expansions_sharp']['_list']
    for contraction in expansions_sharp:
        D1 = contraction['D1']
        D2 = contraction['D2']
        A1 = 3.1416 * (D1**2) / 4
        V1 = Q / A1
        K_contraction = fluids.fittings.diffuser_sharp(D1, D2)
        deltaP = dP_from_K(K_contraction, rho, V1)
        deltaP_expansions_sharp += deltaP

    deltaP_expansions_sharp = roundit(deltaP_expansions_sharp)
    doc['result'].update({
        'deltaP_expansions_sharp': {
            '_val': str(deltaP_expansions_sharp),
            '_dim': 'pressure'
        }
    })

    #calculating pressure drop for conical expansions
    deltaP_expansions_conical = 0
    expansions_conical = doc['input']['expansions_conical']['_list']
    for contraction in expansions_conical:
        D1 = contraction['D1']
        D2 = contraction['D2']
        L = contraction['L']
        A1 = 3.1416 * (D1**2) / 4
        V1 = Q / A1
        K_contraction = fluids.fittings.diffuser_conical(D1, D2, fd=fd, l=L)
        deltaP = dP_from_K(K_contraction, rho, V1)
        deltaP_expansions_conical += deltaP

    deltaP_expansions_conical = roundit(deltaP_expansions_conical)
    doc['result'].update({
        'deltaP_expansions_conical': {
            '_val': str(deltaP_expansions_conical),
            '_dim': 'pressure'
        }
    })

    #calculating pressure drop for pipe reducer expansions
    deltaP_expansions_reducer = 0
    expansions_reducer = doc['input']['expansions_reducer']['_list']
    for contraction in expansions_reducer:
        reducer_size = contraction['reducer_size']
        D2, D1, L = reducer_dimensions(reducer_size)
        A1 = 3.1416 * (D1**2) / 4
        V1 = Q / A1
        K_contraction = fluids.fittings.diffuser_conical(D1, D2, fd=fd, l=L)
        deltaP = dP_from_K(K_contraction, rho, V1)
        deltaP_expansions_reducer += deltaP

    deltaP_expansions_reducer = roundit(deltaP_expansions_reducer)
    doc['result'].update({
        'deltaP_expansions_reducer': {
            '_val': str(deltaP_expansions_reducer),
            '_dim': 'pressure'
        }
    })

    # calculating total pressure drop in all expansions
    deltaP_expansions = deltaP_expansions_sharp + deltaP_expansions_conical + deltaP_expansions_reducer
    doc['result'].update(
        {'deltaP_expansions': {
            '_val': deltaP_expansions,
            '_dim': 'pressure'
        }})

    fixed_K_loss = doc['input']['fixed_K_losses']['_list']
    for loss in fixed_K_loss:
        K_fixed += loss['K'] * loss['quantity']
    deltaP_fixed_K = dP_from_K(K_fixed, rho, V)

    fixed_LbyD_loss = doc['input']['fixed_LbyD_losses']['_list']
    for loss in fixed_LbyD_loss:
        L_D = loss['LbyD']
        K_LbyD += K_from_L_equiv(L_D=L_D, fd=fd) * loss['quantity']
    deltaP_fixed_LbyD = dP_from_K(K_LbyD, rho, V)

    fixed_deltaP_loss = doc['input']['fixed_deltaP_losses']['_list']
    for loss in fixed_deltaP_loss:
        deltaP_fixed += loss['deltaP'] * loss['quantity']
    deltaP_fixed_deltaP = deltaP_fixed

    deltaP_fixed_all = deltaP_fixed_K + deltaP_fixed_LbyD + deltaP_fixed_deltaP

    deltaP_fixed_all = roundit(deltaP_fixed_all)
    doc['result'].update({
        'deltaP_fixed_all': {
            '_val': str(deltaP_fixed_all),
            '_dim': 'pressure'
        }
    })

    deltaP_total = deltaP_pipe + deltaP_entry + deltaP_exit + deltaP_fittings + deltaP_contractions + deltaP_expansions + deltaP_fixed_all
    deltaP_total = roundit(deltaP_total)
    doc['result'].update(
        {'deltaP_total': {
            '_val': str(deltaP_total),
            '_dim': 'pressure'
        }})

    #    doc_original['input'].update(doc['input'])
    doc_original['result'].update(doc['result'])
    treeUnitConvert(doc, SI_UNITS, doc['units'], autoRoundOff=True)
    return True
Beispiel #6
0
def solve_network_flows(case_dom):
    """Find the volumetric flow and head loss for the piping network defined in
    the case_dom structure by using the linear method as described in Chapter 5
    of Jeppson.

    Args:
        case_dom (dict): Pipe flow network data model

    Raises:
        ValueError: Network solution matrix is singular or does not converge.
    """

    # The goal of this project is to reimplement the JEPPSON_CH5 code in Python,
    # not simply translate the original Fortran into Python. For this reason, pipe,
    # junction, and loop indices are zero-based, default NumPy matrix storage is
    # used. This complicates the comparison between the original Fortran and the
    # Python implementations, but effectively illusrates the differences in
    # implementing the solution in each language.

    # The matrix a is constructed in the same manner as in the original Fortran
    # application with a few modifications. While NumPy multidimensional array
    # storage can be set to either C-style (row-major) or Fortran-style
    # (column-major), the default NumPy style is used - C-style.

    # Matrix columns represent flow through pipes. The first (njunctions-1) rows
    # contain 1.0 in a column for outflow via that column's pipe or -1.0 for inflow
    # from that column's pipe. The corresponding term in the first (njunctions - 1)
    # rows of the column vector b contains the fixed flow into the junction from
    # outside the system, positive for inflow and negative for outflow.

    # The remaining nloops rows in the a matrix contain the flow resistance of each
    # pipe, positive if the flow convention is clockwise/forward in the loop,
    # negative if the flow convention is counter-clockwise/reverse in the loop.
    # Flow direction/convention is heuristically assigned by the modeler; the
    # actual flow direction will be determined from the problem solution. The
    # corresponding entries in the b column vector are zero since the flow around a
    # loop is conservative - no net increase or decrease.

    ugrav = Q_(sc.g, 'm/s**2')

    nct = 0
    ssum = 100.0
    flow_units = ''
    npipes = case_dom['params']['npipes']
    njunctions = case_dom['params']['njunctions']
    qpredict = np.zeros(npipes)

    # Set (njunctions-1) independent, conservative junction equations.
    # Note that the remaining junction equation can be derived from the
    # junction equations specified so far.

    _logger.debug('5a. Assemble constant portions of matrix and RHS vector')

    a = np.zeros((npipes, npipes))
    # This portion of the A matrix is constant
    for pipe in case_dom['pipe']:
        pipe_id = pipe['id']
        jfrom = pipe['from']
        jto = pipe['to']
        _logger.debug('Pipe {0:d} goes from {1:d} to {2:d}'.format(
            pipe_id, jfrom, jto))
        if jfrom < njunctions - 1:
            a[jfrom, pipe_id] = -1.0
        if jto < njunctions - 1:
            a[jto, pipe_id] = 1.0

    # The B vector is constant
    b = np.zeros((npipes))
    for idx, inflow in enumerate(case_dom['inflows']):
        # Use base units of first non-zero flow for result
        # conversion.
        if flow_units == '' and inflow.magnitude != 0.0:
            flow_units = inflow.to_base_units().units
        if idx < njunctions - 1:
            b[idx] = inflow.to_base_units().magnitude

    done = False
    converged = False

    while not done:
        # Step 5. Assemble matrix
        _logger.debug('5b. Assemble matrix rows of loop equations')
        for iloop, looppipe in enumerate(case_dom['loop']):
            row_id = njunctions - 1 + iloop
            _logger.debug('Row id is {0:d} = njunctions + iloop = '
                          '{1:d} + {2:d}'.format(row_id, njunctions, iloop))
            for pipe in looppipe:
                pid = pipe['pipe_id']
                col_id = pid
                resistance = (pipe['flow_dir'] * case_dom['pipe'][pid]['kp'])
                _logger.debug(
                    '  Col id is {0:d}; resistance = {1:0.4E}'.format(
                        col_id, resistance))
                a[row_id, col_id] = resistance

        _logger.debug(
            'Resultant flows are in units of {0:s}'.format(flow_units))

        #        print(repr(a))
        #        print(repr(b))

        # Call matrix solver
        # Step 6. Solve matrix
        _logger.debug('6. Solve matrix')
        try:
            x = np.linalg.solve(a, b)
        except np.linalg.LinAlgError as err:
            msg = 'Cannot solve matrix: {0:s}'.format(str(err))
            _logger.error(msg)
            print('Error: ' + msg)
            print('A Matrix:\n{:s}\n'.format(repr(a)))
            print('B Vector:\n{:s}\n'.format(repr(b)))
            converged = False
            # force-exit iteration loop
            break

#        print(repr(x))

        _logger.debug('7. Adjust matrix')
        if nct > 0:
            ssum = 0.0

        for ipipe, currpipe in enumerate(case_dom['pipe']):
            if nct > 0:
                qm = 0.5 * (qpredict[ipipe] + x[ipipe])
                ssum += abs(qpredict[ipipe] - x[ipipe])
            else:
                qm = x[ipipe]

            qpredict[ipipe] = qm
            dq = Q_(qm * case_dom['params']['fvol_flow'], flow_units)
            qmu = Q_(abs(qm), flow_units)
            #            vflowe = qmu / currpipe['flow_area']

            qq_lo = qmu - dq
            vflowv_lo = qq_lo / currpipe['flow_area']

            qq_hi = qmu + dq
            vflowv_hi = qq_hi / currpipe['flow_area']

            if vflowv_lo.magnitude < 0.001:
                vflowv_lo = Q_(0.002, vflowv_lo.units)
                _logger.info('  Flow velocity low endpoint for pipe {0:d} '
                             'increased to {1:0.4E~}'.format(ipipe, vflowv_lo))

            re_lo = (vflowv_lo * currpipe['idiameter'] /
                     case_dom['params']['kin_visc']).to_base_units()

            re_hi = (vflowv_hi * currpipe['idiameter'] /
                     case_dom['params']['kin_visc']).to_base_units()

            _logger.debug('  Pipe {0:d} Re varies from {1:0.4E~} to '
                          '{1:0.4E~}'.format(ipipe, re_lo, re_hi))

            friction_lo = friction_factor(Re=re_lo, eD=currpipe['eroughness'])

            friction_hi = friction_factor(Re=re_hi, eD=currpipe['eroughness'])

            _logger.debug(
                '  Pipe {0:d} f varies from {1:0.4E~} to {1:0.4E~}'.format(
                    ipipe, friction_lo, friction_hi))

            # Calculate new Kp for each pipe based on flow regime and
            # friction factor

            # Note: Flow is laminar for Reynolds number less than 2050
            if re_lo < 2050.0:
                currpipe['expp'] = 1.0
                tmp_kp = (2.0 * ugrav * case_dom['params']['kin_visc'] *
                          currpipe['arl'] / currpipe['idiameter'])
                currpipe['kp'] = tmp_kp.to('1/ft**3/s').magnitude
                _logger.debug(
                    '  Pipe {0:d} flow in laminar region'.format(ipipe))
            else:
                # Consider only transition regime, not transition-rough
                be = ((log(friction_lo) - log(friction_hi)) /
                      (log(qq_lo.to('ft**3/s').magnitude) -
                       log(qq_hi.to('ft**3/s').magnitude)))
                ae = friction_lo * qq_lo.to('ft**3/s').magnitude**be
                ep = 1.0 - be
                currpipe['expp'] = 2.0 - be
                currpipe['kp'] = (ae *
                                  currpipe['arl'].to('s**2/ft**5').magnitude *
                                  qmu.to('ft**3/s').magnitude**ep).magnitude
                _logger.debug('  arl is in units of {0:s}'.format(
                    currpipe['arl'].units))
                _logger.debug('  Pipe {0:d} flow in transition / '
                              'turbulent region'.format(ipipe))

            _logger.debug('  Pipe {0:d} Kp is updated to {1:0.4E}'.format(
                ipipe, currpipe['kp']))

        _logger.debug('8. Display interim results')
        print('Iteration {0:d}'.format(nct))
        print('Deviation {0:0.4E} (Tolerance {1:0.4E})'.format(
            ssum, case_dom['params']['tolerance']))

        print()
        print('Pipe   Kp            expp          Qcurrent                  '
              'Qpredict')
        for ipipe, currpipe in enumerate(case_dom['pipe']):
            print('{0:3d}    {1:0.4E}    {2:0.4E}    {3:0.4E~}    {4:0.4E~}'.
                  format(ipipe, currpipe['kp'], currpipe['expp'],
                         Q_(x[ipipe], 'm**3/s').to('ft**3/s'),
                         Q_(qpredict[ipipe], 'm**3/s').to('ft**3/s')))
        print()

        nct += 1

        _logger.debug('9. Check convergence')

        converged = ssum <= case_dom['params']['tolerance']
        done = converged or (nct >= case_dom['params']['maxiter'])

    # End iteration


# ########################################################################
    if not converged:
        msg = 'Case not converged: ssum = {0:0.4E} > tolerance {1:0.4E}' \
              .format(ssum, case_dom['params']['tolerance'])
        # Advance to next case
        raise ValueError(msg)

    # Add final results to case_dom
    flow_disp_units = 'm**3/s'
    for qext in case_dom['inflows']:
        if qext != 0.0:
            flow_disp_units = qext.units
            break

    for ipipe, currpipe in enumerate(case_dom['pipe']):
        currpipe['vol_flow'] = Q_(x[ipipe], 'm**3/s').to(flow_disp_units)
        currpipe['head_loss'] = (Q_(
            currpipe['kp'] * currpipe['vol_flow'].to('ft**3/s').magnitude,
            'ft'))

    return
Beispiel #7
0
def Stein_Schmidt(m=None,
                  Dtank=None,
                  Djacket=None,
                  H=None,
                  Dinlet=None,
                  rho=None,
                  Cp=None,
                  k=None,
                  mu=None,
                  muw=None,
                  rhow=None,
                  inlettype='tangential',
                  inletlocation='auto',
                  roughness=0):
    r'''Calculates average heat transfer coefficient for a jacket around a
    vessel according to [1]_ as described in [2]_.

    .. math::
        l_{ch} = \left[\left(\frac{\pi}{2}\right)^2 D_{tank}^2+H^2\right]^{0.5}

        d_{ch} = 2\delta

        Re_j = \frac{v_{ch}d_{ch}\rho}{\mu}

        Gr_J = \frac{g\rho(\rho-\rho_w)d_{ch}^3}{\mu^2}

        Re_{J,eq} = \left[Re_J^2\pm \left(\frac{|Gr_J|\frac{H}{d_{ch}}}{50}
        \right)\right]^{0.5}

        Nu_J = (Nu_A^3 + Nu_B^3 + Nu_C^3 + Nu_D^3)^{1/3}\left(\frac{\mu}
        {\mu_w}\right)^{0.14}

        Nu_J = \frac{h d_{ch}}{k}

        Nu_A = 3.66

        Nu_B = 1.62 Pr^{1/3}Re_{J,eq}^{1/3}\left(\frac{d_{ch}}{l_{ch}}
        \right)^{1/3}

        Nu_C = 0.664Pr^{1/3}(Re_{J,eq}\frac{d_{ch}}{l_{ch}})^{0.5}

        \text{if } Re_{J,eq} < 2300: Nu_D = 0

        Nu_D = 0.0115Pr^{1/3}Re_{J,eq}^{0.9}\left(1 - \left(\frac{2300}
        {Re_{J,eq}}\right)^{2.5}\right)\left(1 + \left(\frac{d_{ch}}{l_{ch}}
        \right)^{2/3}\right)


    For Radial inlets:

    .. math::
        v_{ch} = v_{Mit}\left(\frac{\ln\frac{b_{Mit}}{b_{Ein}}}{1 -
        \frac{b_{Ein}}{b_{Mit}}}\right)

        b_{Ein} = \frac{\pi}{8}\frac{D_{inlet}^2}{\delta}

        b_{Mit} = \frac{\pi}{2}D_{tank}\sqrt{1 + \frac{\pi^2}{4}\frac
        {D_{tank}^2}{H^2}}

        v_{Mit} = \frac{Q}{2\delta b_{Mit}}

    For Tangential inlets:

    .. math::
        v_{ch} = (v_x^2 + v_z^2)^{0.5}

        v_x = v_{inlet}\left(\frac{\ln[1 + \frac{f_d D_{tank}H}{D_{inlet}^2}
        \frac{v_x(0)}{v_{inlet}}]}{\frac{f_d D_{tank}H}{D_{inlet}^2}}\right)

        v_x(0) = K_3 + (K_3^2 + K_4)^{0.5}

        K_3 = \frac{v_{inlet}}{4} -\frac{D_{inlet}^2v_{inlet}}{4f_d D_{tank}H}

        K_4 = \frac{D_{inlet}^2v_{inlet}^2}{2f_d D_{tank} H}

        v_z = \frac{Q}{\pi D_{tank}\delta}

        v_{inlet} = \frac{Q}{\frac{\pi}{4}D_{inlet}^2}


    Parameters
    ----------
    m : float
        Mass flow rate of fluid, [kg/m^3]
    Dtank : float
        Outer diameter of tank or vessel surrounded by jacket, [m]
    Djacket : float
        Inner diameter of jacket surrounding a vessel or tank, [m]
    H : float
        Height of the vessel or tank, [m]
    Dinlet : float
        Inner diameter of inlet into the jacket, [m]
    rho : float
        Density of the fluid at Tm [kg/m^3]
    Cp : float
        Heat capacity of fluid at Tm [J/kg/K]
    k : float
        Thermal conductivity of fluid at Tm [W/m/K]
    mu : float
        Viscosity of fluid at Tm [Pa*s]
    muw : float, optional
        Viscosity of fluid at Tw [Pa*s]
    rhow : float, optional
        Density of the fluid at Tw [kg/m^3]
    inlettype : str, optional
        Either 'tangential' or 'radial'
    inletlocation : str, optional
        Either 'top' or 'bottom' or 'auto'
    roughness : float, optional
        Roughness of the tank walls [m]

    Returns
    -------
    h: float
        Average  transfer coefficient inside the jacket [W/m^2/K]

    Notes
    -----
    [1]_ is in German and has not been reviewed. Multiple other formulations
    are considered in [1]_.

    If the fluid is heated and enters from the bottom, natural convection
    assists the heat tansfer and the Grashof term is added; if it were to enter
    from the top, it would be substracted. The situation is reversed if entry
    is from the top.

    Examples
    --------
    Example as in [2]_, matches in all but friction factor:

    >>> Stein_Schmidt(m=2.5, Dtank=0.6, Djacket=0.65, H=0.6, Dinlet=0.025,
    ... rho=995.7, Cp=4178.1, k=0.615, mu=798E-6, muw=355E-6, rhow=971.8)
    5695.204169808863

    References
    ----------
    .. [1] Stein, Prof Dr-Ing Werner Alexander, and Dipl-Ing (FH) Wolfgang
       Schmidt. "Wärmeübergang auf der Wärmeträgerseite eines Rührbehälters mit
       einem einfachen Mantel." Forschung im Ingenieurwesen 59, no. 5
       (May 1993): 73-90. doi:10.1007/BF02561203.
    .. [2] Gesellschaft, V. D. I., ed. VDI Heat Atlas. 2nd edition.
       Berlin; New York:: Springer, 2010.
    '''
    delta = (Djacket - Dtank) / 2.
    Q = m / rho
    Pr = Cp * mu / k
    lch = (pi**2 / 4 * Dtank**2 + H**2)**0.5
    dch = 2 * delta
    if inlettype == 'radial':
        bEin = pi / 8 * Dinlet**2 / delta
        bMit = pi / 2 * Dtank * (1 + pi**2 / 4 * Dtank**2 / H**2)**0.5
        vMit = Q / (2 * delta * bMit)
        vch = vMit * log(bMit / bEin) / (1 - bEin / bMit)
        ReJ = vch * dch * rho / mu
    elif inlettype == 'tangential':
        f = friction_factor(1E5, roughness / dch)
        for run in range(5):
            vinlet = Q / (pi / 4 * Dinlet**2)
            vz = Q / (pi * Dtank * delta)
            K4 = Dinlet**2 * vinlet**2 / (2 * f * Dtank * H)
            K3 = vinlet / 4. - Dinlet**2 * vinlet / (4 * f * Dtank * H)
            vx0 = K3 + (K3**2 + K4)**0.5
            vx = vinlet * log(1 + f * Dtank * H / Dinlet**2 * vx0 / vinlet) / (
                f * Dtank * H / Dinlet**2)
            vch = (vx**2 + vz**2)**0.5
            ReJ = vch * dch * rho / mu
            f = friction_factor(ReJ, roughness / dch)
    if inletlocation and rhow:
        GrJ = g * rho * (rho - rhow) * dch**3 / mu**2
        if rhow < rho:  # Heating jacket fluid
            if inletlocation == 'auto' or inletlocation == 'bottom':
                ReJeq = (ReJ**2 + GrJ * H / dch / 50.)**0.5
            else:
                ReJeq = (ReJ**2 - GrJ * H / dch / 50.)**0.5
        else:  # Cooling jacket fluid
            if inletlocation == 'auto' or inletlocation == 'top':
                ReJeq = (ReJ**2 + GrJ * H / dch / 50.)**0.5
            else:
                ReJeq = (ReJ**2 - GrJ * H / dch / 50.)**0.5
    else:
        ReJeq = (ReJ**2)**0.5
    NuA = 3.66
    NuB = 1.62 * Pr**(1 / 3.) * ReJeq**(1 / 3.) * (dch / lch)**(1 / 3.)
    NuC = 0.664 * Pr**(1 / 3.) * (ReJeq * dch / lch)**0.5
    if ReJeq < 2300:
        NuD = 0
    else:
        NuD = 0.0115 * Pr**(1 / 3.) * ReJeq**0.9 * (
            1 - (2300. / ReJeq)**2.5) * (1 + (dch / lch)**(2 / 3.))
    if muw:
        NuJ = (NuA**3 + NuB**3 + NuC**3 + NuD**3)**(1 / 3.) * (mu / muw)**0.14
    else:
        NuJ = (NuA**3 + NuB**3 + NuC**3 + NuD**3)**(1 / 3.)
    h = NuJ * k / dch
    return h
Beispiel #8
0
 def accept(self):
     Dp = Ltot = nc = 0
     elements = list()
     Q = float(self.form.editFlow.text()) / 3600
     if not self.isLiquid:
         Q = Q / self.Rho
     if self.form.comboWhat.currentText() == '<on selection>':
         elements = FreeCADGui.Selection.getSelection()
     else:
         o = FreeCAD.ActiveDocument.getObjectsByLabel(
             self.form.comboWhat.currentText())[0]
         if hasattr(o, 'PType') and o.PType == 'PypeBranch':
             elements = [
                 FreeCAD.ActiveDocument.getObject(name)
                 for name in o.Tubes + o.Curves
             ]
         elif hasattr(o, 'PType') and o.PType == 'PypeLine':
             group = FreeCAD.ActiveDocument.getObjectsByLabel(o.Label +
                                                              '_pieces')[0]
             elements = group.OutList
     self.form.editResults.clear()
     for o in elements:
         loss = 0
         if hasattr(o, 'PType') and o.PType in ['Pipe', 'Elbow', 'Reduct']:
             if o.PType in ['Pipe', 'Elbow']:
                 ID = float(o.ID) / 1000
             else:
                 ID = float(o.OD - 2 * o.thk) / 1000
             e = float(self.form.editRough.text()) * 1e-6 / ID
             v = Q / ((ID)**2 * pi / 4)
             if isFluidsAvailable:
                 Re = Reynolds(V=v, D=ID, rho=self.Rho, mu=self.Mu)
                 f = friction.friction_factor(Re, eD=e)  # Darcy, =4xFanning
             else:
                 Re = v * ID * self.Rho / self.Mu
                 if Re <= 2300: f = 64 / Re
                 else: f = (-1.8 * log((e / 3.7)**1.11 + 6.9 / Re, 10))**-2
             if o.PType == 'Pipe':
                 L = float(o.Height) / 1000
                 Ltot += L
                 if isFluidsAvailable:
                     K = K_from_f(fd=f, L=L, D=ID)
                     loss = dP_from_K(K, rho=self.Rho, V=v)
                 else:
                     loss = v**2 / 2 * self.Rho * f * L / ID
                 self.form.editResults.append(
                     '%s\t%.1f mm\t%.1f m/s\t%.5f bar' %
                     (o.Label, ID * 1000, v, loss / 1e5))
             elif o.PType == 'Elbow':
                 ang = float(o.BendAngle)
                 R = float(o.BendRadius) / 1000
                 nc += 1
                 if isFluidsAvailable:
                     K = fittings.bend_rounded(ID, ang, f, R)
                     loss = dP_from_K(K, rho=self.Rho, V=v)
                 else:
                     ang = radians(ang)
                     K = f * ang * R / ID + (0.10 + 2.4 * f) * sin(
                         ang /
                         2) + (6.6 * f *
                               (sqrt(sin(ang / 2)) + sin(ang / 2))) / (
                                   (R / ID)**(4 * ang / pi))  # Rennels
                     loss = self.Rho * K * v**2 / 2
                 self.form.editResults.append(
                     '%s\t%.1f mm\t%.1f m/s\t%.5f bar' %
                     (o.Label, ID * 1000, v, loss / 1e5))
             elif o.PType == 'Reduct':
                 ID1 = float(o.OD - o.thk * 2)
                 ID2 = float(o.OD2 - o.thk2 * 2)
                 teta = 2 * atan((ID1 - ID2) / 2.0 / float(o.Height))
                 if isFluidsAvailable:
                     K = fittings.contraction_conical(ID1,
                                                      ID2,
                                                      angle=degrees(teta),
                                                      Re=Re)
                     loss = dP_from_K(K, rho=self.Rho, V=v)
                 else:
                     beta = ID2 / ID1
                     if teta < pi / 4:
                         K = 0.8 * sin(teta / 2) * (1 - beta**2)
                     else:
                         K = 0.5 * sqrt(sin(teta / 2)) * (1 - beta**2)
                     loss = self.Rho * K * v**2 / 2
                 self.form.editResults.append(
                     '%s\t%.1f mm\t%.1f m/s\t%.5f bar' %
                     (o.Label, ID * 1000, v, loss / 1e5))
         elif hasattr(o, 'Kv') and o.Kv > 0:
             if self.isLiquid:
                 loss = (Q * 3600 / o.Kv)**2 * 100000 * self.Rho / 1000
             elif self.form.comboFluid.currentText(
             ) == 'water' and not self.isLiquid:
                 pass  # TODO formula for steam
             else:
                 pass  # TODO formula for gases
             if hasattr(o, 'ID'):
                 ID = float(o.ID) / 1000
                 v = Q / (ID**2 * pi / 4)
             else:
                 v = 0
                 ID = 0
             self.form.editResults.append(
                 '%s\t%.1f mm\t%.1f m/s\t%.5f bar' %
                 (o.Label, ID * 1000, v, loss / 1e5))
         Dp += loss
     if Dp > 200: result = ' = %.3f bar' % (Dp / 100000)
     else: result = ' = %.2e bar' % (Dp / 100000)
     self.form.labResult.setText(result)
     self.form.labLength.setText('Total length = %.3f m' % Ltot)
     self.form.labCurves.setText('Nr. of curves = %i' % nc)
Beispiel #9
0
def Stein_Schmidt(m=None, Dtank=None, Djacket=None, H=None, Dinlet=None,
                  rho=None, Cp=None, k=None, mu=None, muw=None, rhow=None,
                  inlettype='tangential', inletlocation='auto', roughness=0):
    r'''Calculates average heat transfer coefficient for a jacket around a
    vessel according to [1]_ as described in [2]_.

    .. math::
        l_{ch} = \left[\left(\frac{\pi}{2}\right)^2 D_{tank}^2+H^2\right]^{0.5}

        d_{ch} = 2\delta

        Re_j = \frac{v_{ch}d_{ch}\rho}{\mu}

        Gr_J = \frac{g\rho(\rho-\rho_w)d_{ch}^3}{\mu^2}

        Re_{J,eq} = \left[Re_J^2\pm \left(\frac{|Gr_J|\frac{H}{d_{ch}}}{50}
        \right)\right]^{0.5}

        Nu_J = (Nu_A^3 + Nu_B^3 + Nu_C^3 + Nu_D^3)^{1/3}\left(\frac{\mu}
        {\mu_w}\right)^{0.14}

        Nu_J = \frac{h d_{ch}}{k}

        Nu_A = 3.66

        Nu_B = 1.62 Pr^{1/3}Re_{J,eq}^{1/3}\left(\frac{d_{ch}}{l_{ch}}
        \right)^{1/3}

        Nu_C = 0.664Pr^{1/3}(Re_{J,eq}\frac{d_{ch}}{l_{ch}})^{0.5}

        \text{if } Re_{J,eq} < 2300: Nu_D = 0

        Nu_D = 0.0115Pr^{1/3}Re_{J,eq}^{0.9}\left(1 - \left(\frac{2300}
        {Re_{J,eq}}\right)^{2.5}\right)\left(1 + \left(\frac{d_{ch}}{l_{ch}}
        \right)^{2/3}\right)


    For Radial inlets:

    .. math::
        v_{ch} = v_{Mit}\left(\frac{\ln\frac{b_{Mit}}{b_{Ein}}}{1 -
        \frac{b_{Ein}}{b_{Mit}}}\right)

        b_{Ein} = \frac{\pi}{8}\frac{D_{inlet}^2}{\delta}

        b_{Mit} = \frac{\pi}{2}D_{tank}\sqrt{1 + \frac{\pi^2}{4}\frac
        {D_{tank}^2}{H^2}}

        v_{Mit} = \frac{Q}{2\delta b_{Mit}}

    For Tangential inlets:

    .. math::
        v_{ch} = (v_x^2 + v_z^2)^{0.5}

        v_x = v_{inlet}\left(\frac{\ln[1 + \frac{f_d D_{tank}H}{D_{inlet}^2}
        \frac{v_x(0)}{v_{inlet}}]}{\frac{f_d D_{tank}H}{D_{inlet}^2}}\right)

        v_x(0) = K_3 + (K_3^2 + K_4)^{0.5}

        K_3 = \frac{v_{inlet}}{4} -\frac{D_{inlet}^2v_{inlet}}{4f_d D_{tank}H}

        K_4 = \frac{D_{inlet}^2v_{inlet}^2}{2f_d D_{tank} H}

        v_z = \frac{Q}{\pi D_{tank}\delta}

        v_{inlet} = \frac{Q}{\frac{\pi}{4}D_{inlet}^2}


    Parameters
    ----------
    m : float
        Mass flow rate of fluid, [kg/m^3]
    Dtank : float
        Outer diameter of tank or vessel surrounded by jacket, [m]
    Djacket : float
        Inner diameter of jacket surrounding a vessel or tank, [m]
    H : float
        Height of the vessel or tank, [m]
    Dinlet : float
        Inner diameter of inlet into the jacket, [m]
    rho : float
        Density of the fluid at Tm [kg/m^3]
    Cp : float
        Heat capacity of fluid at Tm [J/kg/K]
    k : float
        Thermal conductivity of fluid at Tm [W/m/K]
    mu : float
        Viscosity of fluid at Tm [Pa*s]
    muw : float, optional
        Viscosity of fluid at Tw [Pa*s]
    rhow : float, optional
        Density of the fluid at Tw [kg/m^3]
    inlettype : str, optional
        Either 'tangential' or 'radial'
    inletlocation : str, optional
        Either 'top' or 'bottom' or 'auto'
    roughness : float, optional
        Roughness of the tank walls [m]

    Returns
    -------
    h: float
        Average  transfer coefficient inside the jacket [W/m^2/K]

    Notes
    -----
    [1]_ is in German and has not been reviewed. Multiple other formulations
    are considered in [1]_.

    If the fluid is heated and enters from the bottom, natural convection
    assists the heat tansfer and the Grashof term is added; if it were to enter
    from the top, it would be substracted. The situation is reversed if entry
    is from the top.

    Examples
    --------
    Example as in [2]_, matches in all but friction factor:

    >>> Stein_Schmidt(m=2.5, Dtank=0.6, Djacket=0.65, H=0.6, Dinlet=0.025,
    ... rho=995.7, Cp=4178.1, k=0.615, mu=798E-6, muw=355E-6, rhow=971.8)
    5695.1871940874225

    References
    ----------
    .. [1] Stein, Prof Dr-Ing Werner Alexander, and Dipl-Ing (FH) Wolfgang
       Schmidt. "Wärmeübergang auf der Wärmeträgerseite eines Rührbehälters mit
       einem einfachen Mantel." Forschung im Ingenieurwesen 59, no. 5
       (May 1993): 73-90. doi:10.1007/BF02561203.
    .. [2] Gesellschaft, V. D. I., ed. VDI Heat Atlas. 2nd edition.
       Berlin; New York:: Springer, 2010.
    '''
    delta = (Djacket-Dtank)/2.
    Q = m/rho
    Pr = Cp*mu/k
    lch = (pi**2/4*Dtank**2 + H**2)**0.5
    dch = 2*delta
    if inlettype == 'radial':
        bEin = pi/8*Dinlet**2/delta
        bMit = pi/2*Dtank*(1 + pi**2/4*Dtank**2/H**2)**0.5
        vMit = Q/(2*delta*bMit)
        vch = vMit*log(bMit/bEin)/(1 - bEin/bMit)
        ReJ = vch*dch*rho/mu
    elif inlettype == 'tangential':
        f = friction_factor(1E5, roughness/dch)
        for run in range(5):
            vinlet = Q/(pi/4*Dinlet**2)
            vz = Q/(pi*Dtank*delta)
            K4 = Dinlet**2*vinlet**2/(2*f*Dtank*H)
            K3 = vinlet/4. - Dinlet**2*vinlet/(4*f*Dtank*H)
            vx0 = K3 + (K3**2 + K4)**0.5
            vx = vinlet*log(1 + f*Dtank*H/Dinlet**2*vx0/vinlet)/(f*Dtank*H/Dinlet**2)
            vch = (vx**2 + vz**2)**0.5
            ReJ = vch*dch*rho/mu
            f = friction_factor(ReJ, roughness/dch)
    if inletlocation and rhow:
        GrJ = g*rho*(rho-rhow)*dch**3/mu**2
        if rhow < rho: # Heating jacket fluid
            if inletlocation == 'auto' or inletlocation == 'bottom':
                ReJeq = (ReJ**2 + GrJ*H/dch/50.)**0.5
            else:
                ReJeq = (ReJ**2 - GrJ*H/dch/50.)**0.5
        else: # Cooling jacket fluid
            if inletlocation == 'auto' or inletlocation == 'top':
                ReJeq = (ReJ**2 + GrJ*H/dch/50.)**0.5
            else:
                ReJeq = (ReJ**2 - GrJ*H/dch/50.)**0.5
    else:
        ReJeq = (ReJ**2)**0.5
    NuA = 3.66
    NuB = 1.62*Pr**(1/3.)*ReJeq**(1/3.)*(dch/lch)**(1/3.)
    NuC = 0.664*Pr**(1/3.)*(ReJeq*dch/lch)**0.5
    if ReJeq < 2300:
        NuD = 0
    else:
        NuD = 0.0115*Pr**(1/3.)*ReJeq**0.9*(1 - (2300./ReJeq)**2.5)*(1 + (dch/lch)**(2/3.))
    if muw:
        NuJ = (NuA**3 + NuB**3 + NuC**3 + NuD**3)**(1/3.)*(mu/muw)**0.14
    else:
        NuJ = (NuA**3 + NuB**3 + NuC**3 + NuD**3)**(1/3.)
    h = NuJ*k/dch
    return h
Beispiel #10
0
 def accept(self):
   Dp=Ltot=nc=0
   elements=list()
   Q=float(self.form.editFlow.text())/3600
   if not self.isLiquid:
     Q=Q/self.Rho
   if self.form.comboWhat.currentText()=='<on selection>':
     elements = FreeCADGui.Selection.getSelection()
   else:
     o=FreeCAD.ActiveDocument.getObjectsByLabel(self.form.comboWhat.currentText())[0]
     if hasattr(o,'PType') and o.PType=='PypeBranch':
       elements=[FreeCAD.ActiveDocument.getObject(name) for name in o.Tubes+o.Curves]
     elif hasattr(o,'PType') and o.PType=='PypeLine':
       group=FreeCAD.ActiveDocument.getObjectsByLabel(o.Label+'_pieces')[0]
       elements=group.OutList
   self.form.editResults.clear()
   for o in elements:
     loss=0
     if hasattr(o,'PType') and o.PType in ['Pipe','Elbow']:
       ID=float(o.ID)/1000
       e=float(self.form.editRough.text())*1e-6/ID
       v=Q/((ID)**2*pi/4)
       Re=Reynolds(V=v,D=ID,rho=self.Rho, mu=self.Mu)
       f=friction.friction_factor(Re, eD=e) # Darcy, =4xFanning
       if o.PType=='Pipe':
         L=float(o.Height)/1000
         Ltot+=L
         K=K_from_f(fd=f, L=L, D=ID)
         loss=dP_from_K(K,rho=self.Rho,V=v)
         FreeCAD.Console.PrintMessage('%s: %s\nID=%.2f\nV=%.2f\ne=%f\nf=%f\nK=%f\nL=%.3f\nDp = %.5f bar\n***'%(o.PType,o.Label,ID,v,e,f,K,L,loss/1e5))
         self.form.editResults.append('%s\t%.1f mm\t%.1f m/s\t%.5f bar'%(o.Label,ID*1000,v,loss/1e5))
       elif o.PType=='Elbow':
         ang=float(o.BendAngle)
         R=float(o.BendRadius)/1000
         nc+=1
         K=fittings.bend_rounded(ID,ang,f,R)
         loss=dP_from_K(K,rho=self.Rho,V=v)
         FreeCAD.Console.PrintMessage('%s: %s\nID=%.2f\nV=%.2f\ne=%f\nf=%f\nK=%f\nang=%.3f\nR=%f\nDp = %.5f bar\n***'%(o.PType,o.Label,ID,v,e,f,K,ang,R,loss/1e5))
         self.form.editResults.append('%s\t%.1f mm\t%.1f m/s\t%.5f bar'%(o.Label,ID*1000,v,loss/1e5))
       elif o.PType=='Reduct':
         pass
     elif hasattr(o,'Kv') and o.Kv>0:
       if self.isLiquid:
         loss=(Q*3600/o.Kv)**2*100000
       elif self.form.comboFluid.currentText()=='water' and not self.isLiquid:
         pass # TODO formula for steam
       else:
         pass # TODO formula for gases
       if hasattr(o,'ID'):
         ID = float(o.ID)/1000
         v=Q/(ID**2*pi/4)
       else: 
         v = 0
         ID = 0
       self.form.editResults.append('%s\t%.1f mm\t%.1f m/s\t%.5f bar'%(o.Label,ID*1000,v,loss/1e5))
     Dp+=loss
   if Dp>200: result=' = %.3f bar'%(Dp/100000)
   else: result=' = %.2e bar'%(Dp/100000)
   self.form.labResult.setText(result)
   self.form.labLength.setText('Total length = %.3f m' %Ltot)
   self.form.labCurves.setText('Nr. of curves = %i' %nc)
Beispiel #11
0
roughness = .05E-3

plt.plot(Crane_fts_Ds, Crane_fts, 'o', label='Crane data')

spline_obj = UnivariateSpline(Crane_fts_Ds, Crane_fts, k=3, s=5e-6)
Ds_interp = np.linspace(Crane_fts_Ds[0], Crane_fts_Ds[-1], 500)
plt.plot(Ds_interp, spline_obj(Ds_interp), label='Cubic spline')

ft_crane_correlation = [.25/log10(roughness/(Di)/3.7)**2 for Di in Crane_fts_Ds]

plt.plot(Crane_fts_Ds, ft_crane_correlation,
         label='Crane formula')

plt.plot(Crane_fts_Ds, [round(i, 3) for i in ft_crane_correlation], '.',
         label='Crane formula (rounded)')

eDs_Farshad = [roughness_Farshad(ID='Carbon steel, bare', D=D)/D for D in Crane_fts_Ds]

fts_good = [friction_factor(Re=7.5E6*Di, eD=ed) for ed, Di in zip(eDs_Farshad, Crane_fts_Ds)]

plt.plot(Crane_fts_Ds, fts_good, label='Colebrook')

plt.plot(Crane_fts_Ds, [round(i, 3) for i in fts_good], 'x', label='Colebrook (rounded)')


plt.legend()
plt.title("Comparison of implementation options")
plt.xlabel('Pipe actual diameter, [m]')
plt.ylabel('Darcy friction factor, [-]')
#plt.show()
Beispiel #12
0
def solve_network_flows(case_dom):
    """Find the volumetric flow and head loss for the piping network defined in
    the case_dom structure by using the first method described in Chapter 6 of
    Jeppson.

    Args:
        case_dom (dict): Pipe flow network object model

    Raises:
        ValueError: Network solution matrix is singular or does not converge.
    """

    # The goal of this project is to reimplement the JEPPSON_CH7 code in Python,
    # not simply translate the original Fortran into Python. For this reason, pipe,
    # junction, and loop indices are zero-based, default NumPy matrix storage is
    # used. This complicates the comparison between the original Fortran and the
    # Python implementations, but effectively illusrates the differences in
    # implementing the solution in each language.

    # The matrix a is constructed in the same manner as in the original Fortran
    # application with a few modifications. While NumPy multidimensional array
    # storage can be set to either C-style (row-major) or Fortran-style
    # (column-major), the default NumPy style is used - C-style.

    # Matrix columns represent flow through pipes. The first (njunctions-1) rows
    # contain 1.0 in a column for outflow via that column's pipe or -1.0 for inflow
    # from that column's pipe. The corresponding term in the first (njunctions - 1)
    # rows of the column vector b contains the fixed flow into the junction from
    # outside the system, positive for inflow and negative for outflow.

    # The remaining nloops rows in the a matrix contain the flow resistance of each
    # pipe, positive if the flow convention is clockwise/forward in the loop,
    # negative if the flow convention is counter-clockwise/reverse in the loop.
    # Flow direction/convention is heuristically assigned by the modeler; the
    # actual flow direction will be determined from the problem solution. The
    # corresponding entries in the b column vector are zero since the flow around a
    # loop is conservative - no net increase or decrease.

    nct = 0
    ssum = 100.0
    kin_visc = case_dom['params']['kin_visc']

    # Set kp and expp for each pipe
    for pipe in case_dom['pipe']:
        qm = abs(pipe['init_vol_flow'])
        pipe['vol_flow'] = qm
        dq = case_dom['params']['fvol_flow'] * qm

        q1 = qm - dq
        q2 = qm + dq
        v1 = q1 / pipe['flow_area'].to('ft**2')
        v2 = q2 / pipe['flow_area'].to('ft**2')
        Re1 = (v1 * pipe['idiameter'].to('ft') / kin_visc) \
            .to_base_units().magnitude
        Re2 = (v2 * pipe['idiameter'].to('ft') / kin_visc) \
            .to_base_units().magnitude
        f1 = friction_factor(Re=Re1, eD=pipe['eroughness'])
        f2 = friction_factor(Re=Re2, eD=pipe['eroughness'])

        _logger.debug('Pipe {0:d} Re = {1:0.4E}'.format(pipe['id'], Re1))
        if Re1 < 2050.0:
            # laminar
            pipe['expp'] = 1.0
            pipe['kp'] = (case_dom['params']['grav2'] * kin_visc *
                          pipe['arl'] / pipe['idiameter'].to('ft')).magnitude

        else:
            # Transition/tubulent
            be = ((log(f1) - log(f2)) / (log(q2.to('ft**3/s').magnitude) -
                                         log(q1.to('ft**3/s').magnitude)))
            ae = f1 * (q1.to('ft**3/s').magnitude)**be

            pipe['expp'] = 2.0 - be
            pipe['kp'] = (ae * pipe['arl']).magnitude

        _logger.debug('Pipe {0:d} kp = {1:0.4E} expp = {2:0.4f}'.format(
            pipe['id'], pipe['kp'], pipe['expp']))

        _logger.debug('Pipe {0:d} ae = {1:0.4f} be = {2:0.4f}'.format(
            pipe['id'], ae, be))

    done = False
    converged = False

    while not done:
        # Step 5. Iteratively correct flows
        _logger.debug('Iteratively correct flows')
        ssum = 0.0
        for iloop, looppipe in enumerate(case_dom['loop']):
            sum1 = 0.0
            sum2 = 0.0
            for pipe in looppipe:
                pid = pipe['pipe_id']
                currpipe = case_dom['pipe'][pid]
                hl = ((pipe['flow_dir'] * currpipe['kp'] *
                       currpipe['vol_flow'].to('ft**3/s').magnitude**
                       currpipe['expp']))
                currpipe['head_loss'] = Q_(abs(hl), 'ft')
                sum1 += hl
                _logger.debug('q = {0:0.4E~}'.format(currpipe['vol_flow']))
                _logger.debug('expp = {0:0.4E}'.format(currpipe['expp']))
                _logger.debug('hl = {0:0.4E~}'.format(currpipe['head_loss']))
                sum2 += (currpipe['expp'] * abs(hl) /
                         (currpipe['vol_flow'].to('ft**3/s').magnitude))

            dq = sum1 / sum2

            # 5c) Increment the deviation accumulator with the net flow
            # correction

            ssum = ssum + abs(dq)

            for pipe in looppipe:
                pid = pipe['pipe_id']
                currpipe = case_dom['pipe'][pid]
                currpipe['vol_flow'] -= Q_(pipe['flow_dir'] * dq, 'ft**3/s')

        converged = ssum <= case_dom['params']['tolerance']
        done = converged or (nct >= case_dom['params']['maxiter'])

    # End iteration


# ########################################################################
    if not converged:
        msg = 'Case not converged: ssum = {0:0.4E} > tolerance {1:0.4E}' \
              .format(ssum, case_dom['params']['tolerance'])
        # Advance to next case
        raise ValueError(msg)

    return