A python package for calculating permeability
Project description
permeability
A Python package for calculating permeability of porous media using the seepage distance method, derived from the Darcy's law-based formula, with capillary pressure correction via the Young-Laplace equation:
$$ K = \frac{L^2 \cdot \mu \cdot \phi}{2 \cdot t \cdot \Delta P} $$
$$ t = \frac{\mu \cdot \phi \cdot L^2}{2 \cdot K \cdot \Delta P} $$
$$ z(t) = \sqrt{\frac{2 \cdot K \cdot \Delta P \cdot t}{\mu \cdot \phi}} $$
$$ p_c = \frac{2 \cdot \gamma \cdot \cos(\theta)}{r} $$
Capillary-Corrected Forms
When capillary pressure $p_c$ is considered, $\Delta P$ is replaced by $(\Delta P + p_c)$:
$$ K = \frac{L^2 \cdot \mu \cdot \phi}{2 \cdot t \cdot (\Delta P + p_c)} $$
$$ t = \frac{\mu \cdot \phi \cdot L^2}{2 \cdot K \cdot (\Delta P + p_c)} $$
$$ z(t) = \sqrt{\frac{2 \cdot K \cdot (\Delta P + p_c) \cdot t}{\mu \cdot \phi}} $$
$$ \Delta P = \frac{\mu \cdot \phi \cdot L^2}{2 \cdot K \cdot t} $$
$$ \Delta P = \frac{\mu \cdot \phi \cdot L^2}{2 \cdot K \cdot t} - p_c $$
Anisotropic Permeability Tensor
For orthotropic media (e.g., woven composites), the permeability is represented as a diagonal tensor:
$$ K = \begin{bmatrix} K_x & 0 & 0 \ 0 & K_y & 0 \ 0 & 0 & K_z \end{bmatrix} $$
The Darcy velocity in anisotropic media is:
$$ v = -\frac{1}{\mu} \cdot K \cdot \nabla p $$
After coordinate rotation, the tensor transforms as:
$$ K' = R \cdot K \cdot R^T $$
The effective permeability in an arbitrary direction (unit vector $n$) is:
$$ K_{\text{eff}} = n^T \cdot K \cdot n $$
Key derived quantities include the in-plane average, anisotropy ratio, and degree of anisotropy:
$$ K_{\text{in-plane}} = \frac{K_x + K_y}{2}, \qquad \beta = \frac{K_{\text{in-plane}}}{K_z}, \qquad \delta = 1 - \frac{\min(K_x, K_y, K_z)}{\max(K_x, K_y, K_z)} $$
For a full symmetric tensor $K$ (with off-diagonal components), the principal permeability values are its eigenvalues $K_1 \ge K_2 \ge K_3$, and the principal directions are the corresponding eigenvectors, obtained via eigenvalue decomposition:
$$ K \cdot \phi_i = K_i \cdot \phi_i $$
| Symbol | Meaning | Unit |
|---|---|---|
| $K$ | Permeability | m² |
| $L$ | Sample thickness along flow direction | m |
| $\mu$ | Dynamic viscosity of fluid | Pa·s |
| $\phi$ | Porosity of porous medium | dimensionless |
| $t$ | Time for fluid to fully penetrate sample | s |
| $\Delta P$ | Constant pressure difference across sample | Pa |
| $z$ | Infiltration front position | m |
| $p_c$ | Capillary pressure | Pa |
| $\gamma$ | Surface tension of the liquid | N/m |
| $\theta$ | Contact angle (wetting angle) | Degrees |
| $r$ | Equivalent pore radius | m |
This package also provides an MCP server that exposes these calculations as tools for AI assistants like Claude.
Installation
Using pip
pip install permeability
Using uv (recommended)
uv add permeability
Quick Start
Calculate Permeability from Experimental Data
from permeability.permeability import Seepage
# Experimental parameters
K = Seepage.calculate_permeability(
L=0.003, # Sample thickness: 3 mm
mu=0.192, # Fluid viscosity: 0.192 Pa·s
phi=0.445, # Porosity: 0.445
t=100, # Penetration time: 100 s
dP=1e4 # Pressure difference: 10,000 Pa
)
print(f"Permeability: {K:.3e} m²") # ~3.84e-13 m²
Predict Infiltration Time
t = Seepage.calculate_infiltration_time(
L=0.003,
mu=0.192,
phi=0.445,
K=3.8448e-13,
dP=1e4
)
print(f"Infiltration time: {t:.2f} s") # ~100.00 s
Calculate Infiltration Front Position
# Single time point
z = Seepage.calculate_infiltration_front_position(
K=1.284e-13,
mu=0.192,
phi=0.642,
dP=1e5,
t=120
)
print(f"Front position: {z:.4f} m") # ~0.0050 m
# Multiple time points (for graphing)
import numpy as np
z_array = Seepage.calculate_infiltration_front_position_with_multiple_time(
K=1.284e-13,
mu=0.192,
phi=0.642,
dP=1e5,
t=np.array([0, 30, 120])
)
print(f"Front positions: {z_array}") # [0.0, 0.0025, 0.005]
Calculate Capillary Pressure
from permeability.permeability.Capillary import calculate_capillary_pressure
# Capillary pressure via Young-Laplace equation
p_c = calculate_capillary_pressure(
gamma=0.072, # Surface tension of water: 0.072 N/m
theta=30, # Contact angle: 30 degrees
r=1e-6 # Pore radius: 1 µm
)
print(f"Capillary pressure: {p_c:.2f} Pa") # ~124.71 Pa
Permeability with Capillary Correction
# Calculate permeability considering capillary pressure
K_corrected = Seepage.calculate_permeability(
L=0.003,
mu=0.192,
phi=0.445,
t=100,
dP=1e4,
p_c=124.71 # Capillary pressure (Pa)
)
print(f"Corrected permeability: {K_corrected:.3e} m²")
Calculate Pressure Difference
# Calculate the pressure difference applied across the sample
dP = Seepage.calculate_pressure_difference(
L=0.003,
mu=0.192,
phi=0.445,
K=3.8448e-13,
t=100
)
print(f"Pressure difference: {dP:.2f} Pa") # ~10000.00 Pa
# With capillary correction
dP_corrected = Seepage.calculate_pressure_difference(
L=0.003,
mu=0.192,
phi=0.445,
K=3.8448e-13,
t=100,
p_c=124.71 # Capillary pressure (Pa)
)
print(f"Corrected pressure difference: {dP_corrected:.2f} Pa")
Unit Conversion
from permeability.utils.UnitConverter import darcy2m2, m22darcy
# Convert m² to Darcy
darcy = m22darcy(m2K=3.8448e-13)
print(f"Permeability: {darcy:.3f} Darcy") # ~0.390 Darcy
# Convert Darcy to m²
m2 = darcy2m2(darcyK=0.3896)
print(f"Permeability: {m2:.3e} m²") # ~3.845e-13 m²
Anisotropic Permeability Tensor
For orthotropic materials (e.g., woven composites), the PermeabilityTensor class represents a diagonal permeability tensor $K = \text{diag}(K_x, K_y, K_z)$.
from permeability.permeability.AnisotropicTensor import PermeabilityTensor
# Construct from principal values (orthotropic)
tensor = PermeabilityTensor.from_principal_values(
Kx=1e-12, # Warp/fiber direction (m²)
Ky=5e-13, # Weft direction (m²)
Kz=1e-13 # Through-thickness direction (m²)
)
# Isotropic tensor
iso_tensor = PermeabilityTensor.from_isotopic(K=1e-12)
# Transversely isotropic (e.g., unidirectional fiber bundles)
trans_tensor = PermeabilityTensor.from_transversely_isotropic(
K_in_plane=1e-12,
K_out_plane=1e-13
)
Tensor Properties
# 3x3 diagonal matrix
print(tensor.tensor)
# Average in-plane permeability (Kx + Ky) / 2
print(f"In-plane avg: {tensor.in_plane_average:.3e} m²")
# Anisotropy ratio β = in_plane_avg / Kz
print(f"Anisotropy ratio: {tensor.anisotropy_ratio:.2f}")
# Degree of anisotropy (0 = isotropic, 1 = fully anisotropic)
print(f"Degree of anisotropy: {tensor.degree_of_anisotropy:.3f}")
# Export to dictionary
print(tensor.to_dict())
Darcy Velocity in Anisotropic Media
import numpy as np
# Darcy velocity: v = -(1/μ) · K · ∇p
grad_p = np.array([1000, 500, 100]) # Pressure gradient (Pa/m)
v = tensor.darcy_velocity(grad_p=grad_p, mu=0.192)
print(f"Darcy velocity: {v} m/s")
Effective Permeability in a Direction
# Along principal axes
print(tensor.effective_permeability_in_direction(direction='x'))
print(tensor.effective_permeability_in_direction(direction='xy')) # in-plane avg
# In an arbitrary direction
n = np.array([1, 1, 0]) # arbitrary direction vector
print(tensor.effective_permeability_in_direction(direction_vector=n))
Anisotropic Darcy Flux
The anisotropic_darcy_flux function computes Darcy flux and related quantities in anisotropic media.
from permeability.permeability.AnisotropicTensor import (
PermeabilityTensor,
anisotropic_darcy_flux
)
tensor = PermeabilityTensor.from_principal_values(
Kx=1e-12, Ky=5e-13, Kz=1e-13
)
result = anisotropic_darcy_flux(
tensor=tensor,
grad_p=np.array([1000, 500, 100]), # Pa/m
mu=0.192, # Pa·s
area_normal=np.array([1, 0, 0]) # Optional: unit normal of cross-section
)
print(f"Darcy velocity: {result['darcy_velocity']} m/s")
print(f"Flux magnitude: {result['flux_magnitude']:.3e} m/s")
print(f"Velocity angle from gradP: {result['velocity_angle_from_gradP_deg']:.2f}°")
print(f"Area flux: {result['area_flux']:.3e} m³/s per m²")
MCP Server
The package includes a Model Context Protocol (MCP) server that exposes permeability calculations as AI-accessible tools. After installing the package, start the server with:
Starting the Server
Once installed, simply run:
# Default port 8000
permeability_mcp
# Custom port
permeability_mcp --port 8080
The server starts via HTTP/SSE transport (http://localhost:8000 by default).
If you prefer to try it without installing, you can also use:
uvx --from permeability permeability_mcp
Configuration for AI Assistants
For Claude Desktop, add to your claude_desktop_config.json:
{
"mcpServers": {
"permeability": {
"command": "permeability_mcp",
"args": ["--port", "8080"]
}
}
}
For Cline (VS Code extension), add to your MCP settings:
{
"mcpServers": {
"permeability": {
"command": "permeability_mcp",
"args": ["--port", "8080"]
}
}
}
Available Tools
Once the MCP server is running, AI assistants can call:
| Tool | Description |
|---|---|
calculate_permeability_by_seepage_distance |
Calculate $K$ (optionally with capillary correction via $p_c$) |
calculate_infiltration_time |
Calculate $t$ (optionally with capillary correction via $p_c$) |
calculate_infiltration_front_position |
Calculate $z(t)$ (optionally with capillary correction via $p_c$) |
calculate_infiltration_front_position4multiple_times |
Calculate $z(t)$ for multiple time points (optionally with capillary correction via $p_c$) |
calculate_capillary_pressure |
Calculate $p_c = 2\gamma\cos(\theta),/,r$ (Young-Laplace equation) |
calculate_pressure_difference |
Calculate $\Delta P$ (optionally with capillary correction via $p_c$) |
darcy_m2_converter |
Convert Darcy to m² and/or m² to Darcy (bidirectional) |
calculate_darcy_flux_tool |
Compute Darcy flux in anisotropic media; accepts permeability tensor from principal values, isotropic, or transversely isotropic |
Each tool accepts the same parameters as the Python API.
API Reference
Seepage.calculate_permeability(L, mu, phi, t, dP, p_c=None)
Calculate permeability from seepage distance experiment data. When $p_c$ is provided, the capillary-corrected form is used.
$$ K = \frac{L^2 \cdot \mu \cdot \phi}{2 \cdot t \cdot \Delta P} \qquad\text{or}\qquad K = \frac{L^2 \cdot \mu \cdot \phi}{2 \cdot t \cdot (\Delta P + p_c)} $$
| Parameter | Type | Description |
|---|---|---|
L |
float | Sample length/thickness along flow direction (m) |
mu |
float | Dynamic viscosity of fluid (Pa·s) |
phi |
float | Porosity of porous medium ($0 < \phi \le 1$) |
t |
float | Total time for fluid to fully penetrate sample (s) |
dP |
float | Constant pressure difference across sample (Pa) |
p_c |
float, optional | Capillary pressure for correction (Pa) |
Returns: float — Permeability $K$ (m²)
Seepage.calculate_infiltration_time(L, mu, phi, K, dP, p_c=None)
Predict the time required for fluid to fully penetrate a sample. When $p_c$ is provided, the capillary-corrected form is used.
$$ t = \frac{\mu \cdot \phi \cdot L^2}{2 \cdot K \cdot \Delta P} \qquad\text{or}\qquad t = \frac{\mu \cdot \phi \cdot L^2}{2 \cdot K \cdot (\Delta P + p_c)} $$
| Parameter | Type | Description |
|---|---|---|
L |
float | Sample length/thickness along flow direction (m) |
mu |
float | Dynamic viscosity of fluid (Pa·s) |
phi |
float | Porosity of porous medium ($0 < \phi \le 1$) |
K |
float | Permeability (m²) |
dP |
float | Constant pressure difference across sample (Pa) |
p_c |
float, optional | Capillary pressure for correction (Pa) |
Returns: float — Infiltration time $t$ (s)
Seepage.calculate_infiltration_front_position(K, mu, phi, dP, t, p_c=None)
Calculate the infiltration front position at a given time. When $p_c$ is provided, the capillary-corrected form is used.
$$ z(t) = \sqrt{\frac{2 \cdot K \cdot \Delta P \cdot t}{\mu \cdot \phi}} \qquad\text{or}\qquad z(t) = \sqrt{\frac{2 \cdot K \cdot (\Delta P + p_c) \cdot t}{\mu \cdot \phi}} $$
| Parameter | Type | Description |
|---|---|---|
K |
float | Permeability (m²) |
mu |
float | Dynamic viscosity of fluid (Pa·s) |
phi |
float | Porosity of porous medium ($0 < \phi \le 1$) |
dP |
float | Constant pressure difference across sample (Pa) |
t |
float | Time elapsed (s) |
p_c |
float, optional | Capillary pressure for correction (Pa) |
Returns: float — Infiltration front position $z$ (m)
Seepage.calculate_infiltration_front_position_with_multiple_time(K, mu, phi, dP, t, p_c=None)
Calculate the infiltration front position at multiple time points (useful for plotting). When $p_c$ is provided, the capillary-corrected form is used.
$$ z(t) = \sqrt{\frac{2 \cdot K \cdot \Delta P \cdot t}{\mu \cdot \phi}} \qquad\text{or}\qquad z(t) = \sqrt{\frac{2 \cdot K \cdot (\Delta P + p_c) \cdot t}{\mu \cdot \phi}} $$
| Parameter | Type | Description |
|---|---|---|
K |
float | Permeability (m²) |
mu |
float | Dynamic viscosity of fluid (Pa·s) |
phi |
float | Porosity of porous medium ($0 < \phi \le 1$) |
dP |
float | Constant pressure difference across sample (Pa) |
t |
numpy.ndarray | Array of time values (s) |
p_c |
float, optional | Capillary pressure for correction (Pa) |
Returns: numpy.ndarray — Array of infiltration front positions $z$ (m)
Seepage.calculate_pressure_difference(L, mu, phi, K, t, p_c=None)
Calculate the pressure difference across a sample. When $p_c$ is provided, the capillary-corrected form is used.
$$ \Delta P = \frac{\mu \cdot \phi \cdot L^2}{2 \cdot K \cdot t} \qquad\text{or}\qquad \Delta P = \frac{\mu \cdot \phi \cdot L^2}{2 \cdot K \cdot t} - p_c $$
| Parameter | Type | Description |
|---|---|---|
L |
float | Sample length/thickness along flow direction (m) |
mu |
float | Dynamic viscosity of fluid (Pa·s) |
phi |
float | Porosity of porous medium ($0 < \phi \le 1$) |
K |
float | Permeability (m²) |
t |
float | Total time for fluid to fully penetrate sample (s) |
p_c |
float, optional | Capillary pressure for correction (Pa) |
Returns: float — Pressure difference $\Delta P$ (Pa)
calculate_capillary_pressure(gamma, theta, r)
Calculate capillary pressure using the Young-Laplace equation.
$$ p_c = \frac{2 \cdot \gamma \cdot \cos(\theta)}{r} $$
| Parameter | Type | Description |
|---|---|---|
gamma |
float | Surface tension of the liquid (N/m) |
theta |
float | Contact angle / wetting angle (Degrees) |
r |
float | Equivalent pore radius (m) |
Returns: float — Capillary pressure $p_c$ (Pa)
darcy2m2(darcyK)
Convert permeability from Darcy to m².
| Parameter | Type | Description |
|---|---|---|
darcyK |
float | Permeability in Darcy |
Returns: float — Permeability in m²
m22darcy(m2K)
Convert permeability from m² to Darcy.
| Parameter | Type | Description |
|---|---|---|
m2K |
float | Permeability in m² |
Returns: float — Permeability in Darcy
PermeabilityTensor(Kx, Ky, Kz)
Anisotropic permeability tensor for 2D woven composites. Represents a diagonal permeability tensor $K = \text{diag}(K_x, K_y, K_z)$.
| Parameter | Type | Description |
|---|---|---|
Kx |
float | Permeability in x-direction (warp/fiber direction) (m²) |
Ky |
float | Permeability in y-direction (weft direction) (m²) |
Kz |
float | Permeability in z-direction (through-thickness) (m²) |
Class Methods
PermeabilityTensor.from_principal_values(Kx, Ky, Kz)
Construct tensor from principal direction permeabilities (orthotropic materials).
PermeabilityTensor.from_isotopic(K)
Construct an isotropic permeability tensor where $K_x = K_y = K_z = K$.
PermeabilityTensor.from_transversely_isotropic(K_in_plane, K_out_plane)
Construct a transversely isotropic permeability tensor where $K_x = K_y = K_\text{in-plane}$, $K_z = K_\text{out-plane}$ (suitable for unidirectional fiber bundles).
Properties
| Property | Return Type | Description |
|---|---|---|
tensor |
numpy.ndarray |
Full 3x3 diagonal tensor matrix |
in_plane_average |
float |
Average in-plane permeability $(K_x + K_y),/,2$ (m²) |
anisotropy_ratio |
float |
Anisotropy ratio $\beta = \text{in_plane_avg},/,K_z$ |
degree_of_anisotropy |
float |
Degree of anisotropy (0 = isotropic, 1 = fully anisotropic) |
Methods
darcy_velocity(grad_p, mu)
Calculate Darcy velocity vector $v = -(1/\mu) \cdot K \cdot \nabla p$.
| Parameter | Type | Description |
|---|---|---|
grad_p |
numpy.ndarray | Pressure gradient vector (Pa/m), shape (3,) |
mu |
float | Dynamic viscosity (Pa·s) |
Returns: numpy.ndarray — Darcy velocity vector (m/s), shape (3,)
effective_permeability_in_direction(direction=None, direction_vector=None)
Calculate effective permeability in a specified direction. For a direction unit vector $n$, $K_\text{eff} = n^T \cdot K \cdot n$.
| Parameter | Type | Description |
|---|---|---|
direction |
str, optional | One of 'x', 'y', 'z', 'xy' (in-plane), or 'avg' |
direction_vector |
numpy.ndarray, optional | Arbitrary unit vector of shape (3,) |
Returns: float — Effective permeability in the specified direction (m²)
rotate(R)
Rotate the permeability tensor by rotation matrix $R$: $K' = R \cdot K \cdot R^T$.
| Parameter | Type | Description |
|---|---|---|
R |
numpy.ndarray | Orthogonal rotation matrix (3x3) |
Returns: PermeabilityTensor or FullTensor — Rotated tensor (diagonal if off-diagonal terms negligible)
to_dict()
Export tensor data as a dictionary with keys: Kx, Ky, Kz, in_plane_average, anisotropy_ratio, degree_of_anisotropy.
Returns: dict
FullTensor(matrix)
Full 3x3 symmetric permeability tensor with off-diagonal components, used after coordinate rotation.
| Parameter | Type | Description |
|---|---|---|
matrix |
numpy.ndarray | Full 3x3 symmetric tensor matrix |
Properties
| Property | Return Type | Description |
|---|---|---|
principal_values |
tuple |
Principal permeability values $(K_1, K_2, K_3)$, descending order |
principal_directions |
numpy.ndarray |
Principal permeability directions (eigenvectors), shape (3, 3) |
Methods
to_principal_tensor()
Convert to diagonal PermeabilityTensor in the principal coordinate system using eigenvalues.
Returns: PermeabilityTensor
anisotropic_darcy_flux(tensor, grad_p, mu, area_normal=None)
Compute Darcy flux and related quantities for anisotropic media.
| Parameter | Type | Description |
|---|---|---|
tensor |
PermeabilityTensor | Anisotropic permeability tensor |
grad_p |
numpy.ndarray | Pressure gradient vector (Pa/m) |
mu |
float | Dynamic viscosity (Pa·s) |
area_normal |
numpy.ndarray, optional | Unit normal vector of cross-section area for flux computation |
Returns: dict with keys:
| Key | Description |
|---|---|
darcy_velocity |
Darcy velocity vector (m/s) |
flux_magnitude |
Magnitude of Darcy velocity (m/s) |
velocity_angle_from_gradP_deg |
Angle between velocity and pressure gradient (degrees) |
area_flux |
Volumetric flux per unit area (m³/s per m²), only if area_normal provided |
Development
Setup
git clone https://github.com/1Vewton/permeability.git
cd permeability
uv sync
Running Tests
uv run pytest
Code Style
uv run flake8
License
This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file permeability-0.2.1.tar.gz.
File metadata
- Download URL: permeability-0.2.1.tar.gz
- Upload date:
- Size: 119.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8146f84a0d0b84ef40ba19364f94cbbd864760790b5a3e6fcdb87b90ca9cd604
|
|
| MD5 |
56ca1a2f95f06807cdbcb79ff2dbb2dc
|
|
| BLAKE2b-256 |
4e5eb98b4ba2ac879f53d1b9826596cce1799f70eacf56c0096deb68a49745d2
|
File details
Details for the file permeability-0.2.1-py3-none-any.whl.
File metadata
- Download URL: permeability-0.2.1-py3-none-any.whl
- Upload date:
- Size: 30.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b2c96037890463861e2f8841f767f1e5827b271ed48055aa5fedbf2d6a3287e1
|
|
| MD5 |
6bb4be3eb3d32016baaaa61f9fe4e3de
|
|
| BLAKE2b-256 |
3b61e18c24f34e76be3793d70ad355b5c8550858410c37d40b8b0096d87d1b05
|