def ball_and_stick(target,
                   pore_area='pore.area',
                   throat_area='throat.area',
                   pore_diameter='pore.diameter',
                   throat_diameter='throat.diameter',
                   conduit_lengths='throat.conduit_lengths'):
    r"""
    Calculate conduit shape factors for throat conductance associated with
    diffusion-like physics (ex. thermal/diffusive/electrical conductance),
    assuming pores and throats are spheres (balls) and constant cross-section
    cylinders (sticks).

    Parameters
    ----------
    target : OpenPNM Object
        The object which this model is associated with. This controls the
        length of the calculated array, and also provides access to other
        necessary properties.

    pore_area : string
        Dictionary key of the pore area values

    throat_area : string
        Dictionary key of the throat area values

    pore_diameter : string
        Dictionary key of the pore diameter values

    throat_diameter : string
        Dictionary key of the throat diameter values

    conduit_lengths : string
        Dictionary key of the conduit lengths' values

    Returns
    -------
    SF : dictionary
        Dictionary containing conduit shape factors to be used in conductance
        models associated with diffusion-like physics. Shape factors are
        accessible via the keys: 'pore1', 'pore2' and 'throat'.

    Notes
    -----
    (1) This model accounts for the variable cross-section area in spheres.

    (2) WARNING: This model could break if `conduit_lengths` does not
    correspond to an actual ball and stick! Example: pore length is greater
    than pore radius --> :(

    """
    _np.warnings.filterwarnings('ignore', category=RuntimeWarning)
    network = target.project.network
    throats = network.map_throats(throats=target.Ts, origin=target)
    cn = network['throat.conns'][throats]
    # Get pore diameter
    D1 = network[pore_diameter][cn[:, 0]]
    D2 = network[pore_diameter][cn[:, 1]]
    Dt = network[throat_diameter][throats]
    # Get conduit lengths
    L1 = network[conduit_lengths + '.pore1'][throats]
    L2 = network[conduit_lengths + '.pore2'][throats]
    Lt = network[conduit_lengths + '.throat'][throats]
    # Get pore/throat baseline areas (the one used in generic conductance)
    A1 = network[pore_area][cn[:, 0]]
    A2 = network[pore_area][cn[:, 1]]
    At = network[throat_area][throats]
    # Preallocating F, SF
    # F is INTEGRAL(1/A) dx , x : 0 --> L
    F1, F2, Ft = _sp.zeros((3, len(Lt)))
    SF1, SF2, SFt = _sp.ones((3, len(Lt)))
    # Setting SF to 1 when Li = 0 (ex. boundary pores)
    # INFO: This is needed since area could also be zero, which confuses NumPy
    m1, m2, mt = [Li != 0 for Li in [L1, L2, Lt]]
    SF1[~m1] = SF2[~m2] = SFt[~mt] = 1
    # Handle the case where Dt >= Dp
    M1, M2 = [(Di <= Dt) & mi for Di, mi in zip([D1, D2], [m1, m2])]
    F1[M1] = (4 * L1 / (D1 * Dt * _pi))[M1]
    F2[M2] = (4 * L2 / (D2 * Dt * _pi))[M2]
    # Handle the rest (true balls and sticks)
    N1, N2 = [(Di > Dt) & mi for Di, mi in zip([D1, D2], [m1, m2])]
    F1[N1] = (2 / (D1 * _pi) * _atanh(2 * L1 / D1))[N1]
    F2[N2] = (2 / (D2 * _pi) * _atanh(2 * L2 / D2))[N2]
    Ft[mt] = (Lt / At)[mt]
    # Calculate conduit shape factors
    SF1[m1] = (L1 / (A1 * F1))[m1]
    SF2[m2] = (L2 / (A2 * F2))[m2]
    SFt[mt] = (Lt / (At * Ft))[mt]
    _np.warnings.filterwarnings('default', category=RuntimeWarning)
    return {'pore1': SF1, 'throat': SFt, 'pore2': SF2}
Beispiel #2
0
def ball_and_stick_2D(target,
                      pore_area='pore.area',
                      throat_area='throat.area',
                      pore_diameter='pore.diameter',
                      throat_diameter='throat.diameter',
                      conduit_lengths='throat.conduit_lengths'):
    r"""
    Calculate conduit shape factors for hydraulic conductance, assuming
    pores and throats are circles (balls) and rectangles (sticks).

    Parameters
    ----------
    target : OpenPNM Object
        The object which this model is associated with. This controls the
        length of the calculated array, and also provides access to other
        necessary properties.

    pore_area : string
        Dictionary key of the pore area values

    throat_area : string
        Dictionary key of the throat area values

    pore_diameter : string
        Dictionary key of the pore diameter values

    throat_diameter : string
        Dictionary key of the throat diameter values

    conduit_lengths : string
        Dictionary key of the conduit lengths' values

    Returns
    -------
    SF : dictionary
        Dictionary containing conduit shape factors to be used in hagen-
        poiseuille hydraulic conductance model. Shape factors are accessible
        via the keys: 'pore1', 'pore2' and 'throat'.

    Notes
    -----
    (1) This model accounts for the variable cross-section area in spheres.

    (2) WARNING: This model could break if `conduit_lengths` does not
    correspond to an actual ball and stick! Example: pore length is greater
    than pore radius --> :(

    References
    ----------
    Akbari, M., Sinton, D., & Bahrami, M. (2011). Viscous flow in variable
    cross-section microchannels of arbitrary shapes. International Journal of
    Heat and Mass Transfer, 54(17-18), 3970-3978.

    """
    _np.warnings.filterwarnings('ignore', category=RuntimeWarning)
    network = target.project.network
    throats = network.map_throats(throats=target.Ts, origin=target)
    cn = network['throat.conns'][throats]
    # Get pore diameter
    D1 = network[pore_diameter][cn[:, 0]]
    D2 = network[pore_diameter][cn[:, 1]]
    # Get conduit lengths
    L1 = network[conduit_lengths + '.pore1'][throats]
    L2 = network[conduit_lengths + '.pore2'][throats]
    Lt = network[conduit_lengths + '.throat'][throats]
    # Get pore/throat baseline areas (the one used in generic conductance)
    A1 = network[pore_area][cn[:, 0]]
    A2 = network[pore_area][cn[:, 1]]
    At = network[throat_area][throats]
    # Preallocating F, SF
    # F is INTEGRAL(1/A^2) dx , x : 0 --> L
    F1, F2, Ft = _sp.zeros((3, len(Lt)))
    SF1, SF2, SFt = _sp.ones((3, len(Lt)))
    # Setting SF to 1 when Li = 0 (ex. boundary pores)
    # INFO: This is needed since area could also be zero, which confuses NumPy
    m1, m2, mt = [Li != 0 for Li in [L1, L2, Lt]]
    SF1[~m1] = SF2[~m2] = SFt[~mt] = 1
    F1[m1] = (_atanh(2 * L1 / D1) / (2 * D1))[m1]
    F2[m2] = (_atanh(2 * L2 / D2) / (2 * D2))[m2]
    Ft[mt] = (Lt / At**2)[mt]
    # Calculate conduit shape factors
    SF1[m1] = (L1 / (A1**2 * F1))[m1]
    SF2[m2] = (L2 / (A2**2 * F2))[m2]
    SFt[mt] = (Lt / (At**2 * Ft))[mt]
    _np.warnings.filterwarnings('default', category=RuntimeWarning)
    return {'pore1': SF1, 'throat': SFt, 'pore2': SF2}
Beispiel #3
0
def ball_and_stick_2D(target, pore_area='pore.area',
                      throat_area='throat.area',
                      pore_diameter='pore.diameter',
                      throat_diameter='throat.diameter',
                      conduit_lengths='throat.conduit_lengths'):
    r"""
    Calculate conduit shape factors for throat conductance associated with
    diffusion-like physics (ex. thermal/diffusive/electrical conductance),
    assuming pores and throats are circles (balls) and rectangles (sticks).

    Parameters
    ----------
    target : OpenPNM Object
        The object which this model is associated with. This controls the
        length of the calculated array, and also provides access to other
        necessary properties.

    pore_area : string
        Dictionary key of the pore area values

    throat_area : string
        Dictionary key of the throat area values

    pore_diameter : string
        Dictionary key of the pore diameter values

    throat_diameter : string
        Dictionary key of the throat diameter values

    conduit_lengths : string
        Dictionary key of the conduit lengths' values

    Returns
    -------
    SF : dictionary
        Dictionary containing conduit shape factors to be used in conductance
        models associated with diffusion-like physics. Shape factors are
        accessible via the keys: 'pore1', 'pore2' and 'throat'.

    Notes
    -----
    (1) This model accounts for the variable cross-section area in circles.

    (2) WARNING: This model could break if `conduit_lengths` does not
    correspond to an actual ball and stick! Example: pore length is greater
    than pore radius --> :(

    """
    _np.warnings.filterwarnings('ignore', category=RuntimeWarning)
    network = target.project.network
    throats = network.map_throats(throats=target.Ts, origin=target)
    cn = network['throat.conns'][throats]
    # Get pore diameter
    D1 = network[pore_diameter][cn[:, 0]]
    D2 = network[pore_diameter][cn[:, 1]]
    # Get conduit lengths
    L1 = network[conduit_lengths + '.pore1'][throats]
    L2 = network[conduit_lengths + '.pore2'][throats]
    Lt = network[conduit_lengths + '.throat'][throats]
    # Get pore/throat baseline areas (the one used in generic conductance)
    A1 = network[pore_area][cn[:, 0]]
    A2 = network[pore_area][cn[:, 1]]
    At = network[throat_area][throats]
    # Preallocating F, SF
    # F is INTEGRAL(1/A) dx , x : 0 --> L
    F1, F2, Ft = _sp.zeros((3, len(Lt)))
    SF1, SF2, SFt = _sp.ones((3, len(Lt)))
    # Setting SF to 1 when Li = 0 (ex. boundary pores)
    # INFO: This is needed since area could also be zero, which confuses NumPy
    m1, m2, mt = [Li != 0 for Li in [L1, L2, Lt]]
    SF1[~m1] = SF2[~m2] = SFt[~mt] = 1
    F1[m1] = (0.5 * _atanh(2*L1/_sqrt(D1**2 - 4*L1**2)))[m1]
    F2[m2] = (0.5 * _atanh(2*L2/_sqrt(D2**2 - 4*L2**2)))[m2]
    Ft[mt] = (Lt/At)[mt]
    # Calculate conduit shape factors
    SF1[m1] = (L1 / (A1*F1))[m1]
    SF2[m2] = (L2 / (A2*F2))[m2]
    SFt[mt] = (Lt / (At*Ft))[mt]
    _np.warnings.filterwarnings('default', category=RuntimeWarning)
    return {'pore1': SF1, 'throat': SFt, 'pore2': SF2}
Beispiel #4
0
def ball_and_stick(target, pore_area='pore.area',
                   throat_area='throat.area',
                   pore_diameter='pore.diameter',
                   throat_diameter='throat.diameter',
                   conduit_lengths='throat.conduit_lengths'):
    r"""
    Calculate conduit shape factors for hydraulic conductance, assuming
    pores and throats are spheres (balls) and constant cross-section
    cylinders (sticks).

    Parameters
    ----------
    target : OpenPNM Object
        The object which this model is associated with. This controls the
        length of the calculated array, and also provides access to other
        necessary properties.

    pore_area : string
        Dictionary key of the pore area values

    throat_area : string
        Dictionary key of the throat area values

    pore_diameter : string
        Dictionary key of the pore diameter values

    throat_diameter : string
        Dictionary key of the throat diameter values

    conduit_lengths : string
        Dictionary key of the conduit lengths' values

    Returns
    -------
    SF : dictionary
        Dictionary containing conduit shape factors to be used in hagen-
        poiseuille hydraulic conductance model. Shape factors are accessible
        via the keys: 'pore1', 'pore2' and 'throat'.

    Notes
    -----
    (1) This model accounts for the variable cross-section area in spheres.

    (2) WARNING: This model could break if `conduit_lengths` does not
    correspond to an actual ball and stick! Example: pore length is greater
    than pore radius --> :(

    References
    ----------
    Akbari, M., Sinton, D., & Bahrami, M. (2011). Viscous flow in variable
    cross-section microchannels of arbitrary shapes. International Journal of
    Heat and Mass Transfer, 54(17-18), 3970-3978.

    """
    _np.warnings.filterwarnings('ignore', category=RuntimeWarning)
    network = target.project.network
    throats = network.map_throats(throats=target.Ts, origin=target)
    cn = network['throat.conns'][throats]
    # Get pore diameter
    D1 = network[pore_diameter][cn[:, 0]]
    D2 = network[pore_diameter][cn[:, 1]]
    Dt = network[throat_diameter][throats]
    # Get conduit lengths
    L1 = network[conduit_lengths + '.pore1'][throats]
    L2 = network[conduit_lengths + '.pore2'][throats]
    Lt = network[conduit_lengths + '.throat'][throats]
    # Get pore/throat baseline areas (the one used in generic conductance)
    A1 = network[pore_area][cn[:, 0]]
    A2 = network[pore_area][cn[:, 1]]
    At = network[throat_area][throats]
    # Preallocating F, SF
    # F is INTEGRAL(1/A^2) dx , x : 0 --> L
    F1, F2, Ft = _sp.zeros((3, len(Lt)))
    SF1, SF2, SFt = _sp.ones((3, len(Lt)))
    # Setting SF to 1 when Li = 0 (ex. boundary pores)
    # INFO: This is needed since area could also be zero, which confuses NumPy
    m1, m2, mt = [Li != 0 for Li in [L1, L2, Lt]]
    SF1[~m1] = SF2[~m2] = SFt[~mt] = 1
    # Handle the case where Dt >= Dp
    M1, M2 = [(Di <= Dt) & mi for Di, mi in zip([D1, D2], [m1, m2])]
    F1[M1] = 16/3 * (L1*(D1**2 + D1*Dt + Dt**2) / (D1**3 * Dt**3 * _pi**2))[M1]
    F2[M2] = 16/3 * (L2*(D2**2 + D2*Dt + Dt**2) / (D2**3 * Dt**3 * _pi**2))[M2]
    # Handle the rest (true balls and sticks)
    N1, N2 = [(Di > Dt) & mi for Di, mi in zip([D1, D2], [m1, m2])]
    F1[N1] = (4/(D1**3*_pi**2) * ((2*D1*L1) / (D1**2-4*L1**2) + _atanh(2*L1/D1)))[N1]
    F2[N2] = (4/(D2**3*_pi**2) * ((2*D2*L2) / (D2**2-4*L2**2) + _atanh(2*L2/D2)))[N2]
    Ft[mt] = (Lt / At**2)[mt]
    # Calculate conduit shape factors
    SF1[m1] = (L1 / (A1**2 * F1))[m1]
    SF2[m2] = (L2 / (A2**2 * F2))[m2]
    SFt[mt] = (Lt / (At**2 * Ft))[mt]
    _np.warnings.filterwarnings('default', category=RuntimeWarning)
    return {'pore1': SF1, 'throat': SFt, 'pore2': SF2}