Source code for porespy.filters._transforms
import numpy as np
import numpy.typing as npt
from porespy.generators import ramp
from porespy.tools import get_edt
__all__ = [
'capillary_transform',
]
edt = get_edt()
[docs]
def capillary_transform(
im: npt.NDArray,
dt: npt.NDArray = None,
sigma: float = 1.0,
theta: float = 180,
g: float = 0.0,
rho_wp: float = 0.0,
rho_nwp: float = 0.0,
voxel_size: float = 1.0,
spacing: float = None,
):
r"""
Uses the Washburn equation to convert distance transform values to a capillary
transform.
Parameters
----------
im : ndarray
A boolean image describing the porous medium with ``True`` values indicating
the phase of interest.
dt : ndarray, optional
The distance transform of the void phase. If not provided it will be
calculated, so some time can be save if a pre-computed array is already
available.
sigma : scalar (default = 1.0)
The surface tension of the fluid-fluid interface.
theta : scalar (default = 180)
The contact angle of the fluid-fluid-solid system, in degrees.
g : scalar (default = 0)
The gravitational constant acting on the fluids. Gravity is assumed to act
toward the x=0 axis. To have gravity act in different directions just
use `np.swapaxes(im, 0, ax)` where `ax` is the desired direction.
delta_rho : scalar (default = 0.0)
The density difference between the fluids.
voxel_size : scalar (default = 0.0)
The resolution of the image
spacing : scalar (default = None)
If a 2D image is provided, this value is used to compute the second
radii of curvature. Setting it to `inf` will make the calculation truly
2D since only one radii of curvature is considered. Setting it to `None`
will force the calculation to be 3D. If `im` is 3D this argument is
ignored.
Notes
-----
All physical properties should be in self-consistent units, and it is strongly
recommended to use SI for everything.
"""
delta_rho = rho_nwp - rho_wp
if dt is None:
dt = edt(im)
if (im.ndim == 2) and (spacing is not None):
pc = -sigma*np.cos(np.deg2rad(theta))*(1/(dt*voxel_size) + 2/spacing)
else:
pc = -2*sigma*np.cos(np.deg2rad(theta))/(dt*voxel_size)
if delta_rho > 0:
h = ramp(im.shape, inlet=0, outlet=im.shape[0], axis=0)*voxel_size
pc = pc + delta_rho*g*h
elif delta_rho < 0:
h = ramp(im.shape, inlet=im.shape[0], outlet=0, axis=0)*voxel_size
pc = pc + delta_rho*g*h
return pc