Source code for openpnm.models.geometry.throat_endpoints._funcs

import numpy as _np
from openpnm.models.geometry import _geodocs


__all__ = [
    'spheres_and_cylinders',
]


[docs] @_geodocs def spheres_and_cylinders( network, pore_diameter='pore.diameter', throat_diameter='throat.diameter', throat_centroid='throat.centroid', ): r""" Computes the endpoints of throats when pores are spherical. The endpoints lie inside the sphere, defined by the lens formed between the intersection of the sphere and cylinder. Parameters ---------- %(network)s %(Dp)s %(Dt)s %(Tcen)s Returns ------- endpoints : ndarray An array containing the Nt-2-3 coordinates of the end points of each throat. """ xyz = network.coords cn = network.conns L = network['throat.spacing'] Dt = network[throat_diameter] D1 = network[pore_diameter][cn[:, 0]] D2 = network[pore_diameter][cn[:, 1]] L1 = _np.zeros_like(L) L2 = _np.zeros_like(L) # Handle the case where Dt > Dp mask = Dt > D1 L1[mask] = 0.5 * D1[mask] L1[~mask] = _np.sqrt(D1[~mask]**2 - Dt[~mask]**2) / 2 mask = Dt > D2 L2[mask] = 0.5 * D2[mask] L2[~mask] = _np.sqrt(D2[~mask]**2 - Dt[~mask]**2) / 2 # Handle non-colinear pores and throat centroids try: TC = network[throat_centroid] LP1T = _np.linalg.norm(TC - xyz[cn[:, 0]], axis=1) + 1e-15 LP2T = _np.linalg.norm(TC - xyz[cn[:, 1]], axis=1) + 1e-15 unit_vec_P1T = (TC - xyz[cn[:, 0]]) / LP1T[:, None] unit_vec_P2T = (TC - xyz[cn[:, 1]]) / LP2T[:, None] except KeyError: unit_vec_P1T = (xyz[cn[:, 1]] - xyz[cn[:, 0]]) / L[:, None] unit_vec_P2T = -1 * unit_vec_P1T # Find throat endpoints EP1 = xyz[cn[:, 0]] + L1[:, None] * unit_vec_P1T EP2 = xyz[cn[:, 1]] + L2[:, None] * unit_vec_P2T # Handle throats w/ overlapping pores L1 = (4 * L**2 + D1**2 - D2**2) / (8 * L) L2 = (4 * L**2 + D2**2 - D1**2) / (8 * L) h = (2 * _np.sqrt(D1**2 / 4 - L1**2)).real overlap = L - 0.5 * (D1 + D2) < 0 mask = overlap & (Dt < h) EP1[mask] = (xyz[cn[:, 0]] + L1[:, None] * unit_vec_P1T)[mask] EP2[mask] = (xyz[cn[:, 1]] + L2[:, None] * unit_vec_P2T)[mask] return {'head': EP1, 'tail': EP2}