voids is a scientific Python package for pore network modeling (PNM) aimed at
research workflows where reproducibility, explicit assumptions, and validation matter.
The current project emphasis is a clean canonical network model, interoperability with
PoreSpy/OpenPNM-style data, and a validated single-phase workflow that now includes
shape-aware conductance, pressure-dependent thermodynamic viscosity, and nonlinear
solve options before expanding to more complex multiphase physics.
The intended direction of voids is:
- provide a rigorous internal representation of pore-throat networks
- preserve sample geometry and provenance information needed for reproducible studies
- support import and normalization of extracted networks from external tools
- expose well-scoped physics modules with diagnostics and regression tests
- build confidence on single-phase transport first, then expand toward richer models
This is a research codebase, not a GUI application or a full image-to-network extraction pipeline. Raw segmentation and extraction are intentionally delegated to upstream tools such as PoreSpy.
The current v0.1.x implementation includes:
- canonical
Network,SampleGeometry, andProvenancedata structures - import of PoreSpy/OpenPNM-style dictionaries into the canonical model
- geometry normalization helpers for extracted networks
- static petrophysics:
- absolute porosity
- effective porosity
- connectivity metrics
- single-phase incompressible flow with directional permeability estimation
- shape-aware
valvatne_blunt_throatandvalvatne_bluntconductance closures - pressure-dependent water viscosity via
thermoandCoolProp - Picard and damped-Newton nonlinear solves for variable-viscosity problems
- Krylov linear solvers with optional
pyamgpreconditioning - HDF5 serialization
- optional Plotly and PyVista network visualization
- interoperability cross-checks against OpenPNM
- optional direct-image permeability benchmarking against XLB
- synthetic and manufactured examples for regression and tutorials
Important boundaries:
- multiphase flow is not implemented yet
- production image acquisition and fully automated "push-button" extraction pipelines are out of scope
- controlled grayscale preprocessing, segmentation helpers, and
snow2-based extraction helpers are available invoids.image - synthetic mesh/manufactured examples are controlled validation cases, not realistic rock reconstructions
For a more formal statement of scope and assumptions, see spec_v0_1.md.
The rendered documentation is intended to live alongside the repository at https://geomech-project.github.io/voids/.
If you want the published package rather than a local editable checkout:
pip install voidsPyPI package page: https://pypi.org/project/voids/
This repository is configured for Pixi and exposes four main environments:
default: core runtime + notebooks + plotting + PyVista + thermodynamic backendstest: everything indefaultplus test-only dependencieslbm: test environment plus the optional XLB stackdocs: MkDocs, Material for MkDocs, and mkdocstrings
pixi install
pixi run -e default python -c "import voids; print(voids.__version__)"Pixi activation also provides project path variables used by notebooks:
VOIDS_PROJECT_ROOTVOIDS_NOTEBOOKS_PATHVOIDS_EXAMPLES_PATHVOIDS_DATA_PATH
If you prefer a plain Python environment from the repository checkout:
python -m pip install -e .Optional extras:
python -m pip install -e ".[dev,viz,test,lbm,docs]"Assumption to keep in mind: the notebooks are exercised primarily through the Pixi environments, so the most reliable setup is still Pixi.
from voids.examples import make_linear_chain_network
from voids.physics.petrophysics import absolute_porosity
from voids.physics.singlephase import FluidSinglePhase, PressureBC, solve
net = make_linear_chain_network()
result = solve(
net,
fluid=FluidSinglePhase(viscosity=1.0),
bc=PressureBC("inlet_xmin", "outlet_xmax", pin=1.0, pout=0.0),
axis="x",
)
print("phi_abs =", absolute_porosity(net))
print("Q =", result.total_flow_rate)
print("Kx =", result.permeability["x"])
print("mass_balance_error =", result.mass_balance_error)There is also a small workflow entry point:
pixi run examples-singlephaseThe repository includes paired notebooks and py:percent scripts under notebooks/:
01_mwe_singlephase_porosity_perm- minimal single-phase solve, porosity, and permeability
02_mwe_openpnm_crosscheck_optional- roundtrip and OpenPNM cross-check workflow
03_mwe_pyvista_visualization- optional PyVista-based network rendering
04_mwe_manufactured_porespy_extraction- manufactured 3D void image, PoreSpy extraction, import into
voids, and serialization
- manufactured 3D void image, PoreSpy extraction, import into
05_mwe_cartesian_mesh_network- configurable 2D/3D mesh-like pore networks, flow solve, Plotly visualization, and HDF5 export
06_mwe_real_porespy_extraction- real segmented Ketton image, PoreSpy extraction,
voidsimport, solve, and diagnostics
- real segmented Ketton image, PoreSpy extraction,
07_mwe_synthetic_vug_case- grayscale synthetic vug volume preprocessing, extraction, solve, and pruning comparison
08_mwe_image_based_vug_shape_sensitivity- controlled baseline vs spherical/ellipsoidal vug study with porosity,
Kabs, and network statistics
- controlled baseline vs spherical/ellipsoidal vug study with porosity,
09_mwe_image_based_vug_sensitivity_2d- simplified 2D image-based baseline vs circular/elliptical vug study with porosity,
Kabs, andK/K0distributions
- simplified 2D image-based baseline vs circular/elliptical vug study with porosity,
10_mwe_lattice_based_vug_sensitivity- lattice-based stochastic baselines with spherical/ellipsoidal vug insertion,
Kabs/porosity sensitivity, andK/K0distributions
- lattice-based stochastic baselines with spherical/ellipsoidal vug insertion,
11_mwe_lattice_based_vug_sensitivity_2d- simplified 2D lattice counterpart with circular/elliptical vugs, multi-baseline sensitivity, and
K/K0frequency distributions
- simplified 2D lattice counterpart with circular/elliptical vugs, multi-baseline sensitivity, and
12_mwe_synthetic_volume_openpnm_benchmark- synthetic spanning volumes, synthetic grayscale segmentation,
snow2extraction, andKabscross-checks betweenvoidsand OpenPNM
- synthetic spanning volumes, synthetic grayscale segmentation,
13_mwe_synthetic_volume_xlb_benchmark- synthetic segmented volumes, direct-image XLB solves, extracted-network
voidssolves, andKabscomparison between voxel-scale LBM and PNM
- synthetic segmented volumes, direct-image XLB solves, extracted-network
14_mwe_shape_factor_conductance_comparison- synthetic and extracted-network comparison of conductance closures (
generic_poiseuille,valvatne_blunt_throat, andvalvatne_blunt) and permeability sensitivity to shape factors
- synthetic and extracted-network comparison of conductance closures (
15_mwe_external_pnflow_benchmark- committed external
pnextract/pnflowreference cases compared against the currentvoidsextraction + solve workflow
- committed external
16_mwe_viscosity_model_kabs_benchmark- benchmark of
Kabsusing constant viscosity versus pressure-dependent thermodynamic viscosity
- benchmark of
17_mwe_solver_options_benchmark- benchmark of the available linear and nonlinear solver options, including
pyamg-preconditioned Krylov solves
- benchmark of the available linear and nonlinear solver options, including
18_mwe_drp317_berea_raw_porosity_perm- DRP-317 Berea validation notebook against experimental porosity and permeability
19_mwe_drp317_bentheimer_raw_porosity_perm- DRP-317 Bentheimer validation notebook against experimental porosity and permeability
20_mwe_drp317_banderagray_raw_porosity_perm- DRP-317 Bandera Gray validation notebook against experimental porosity and permeability
21_mwe_drp317_banderabrown_raw_porosity_perm- DRP-317 Bandera Brown notebook against the Table 1 experimental porosity and permeability values
22_mwe_drp317_bereasistergray_raw_porosity_perm- DRP-317 Berea Sister Gray notebook against the Table 1 experimental porosity and permeability values
23_mwe_drp317_bereauppergray_raw_porosity_perm- DRP-317 Berea Upper Gray notebook against the Table 1 experimental porosity and permeability values
24_mwe_drp317_buffberea_raw_porosity_perm- DRP-317 Buff Berea notebook against the Table 1 experimental porosity and permeability values
25_mwe_drp317_castlegate_raw_porosity_perm- DRP-317 Castlegate notebook against the Table 1 experimental porosity and permeability values
26_mwe_drp317_kirby_raw_porosity_perm- DRP-317 Kirby notebook against the Table 1 experimental porosity and permeability values
27_mwe_drp317_leopard_raw_porosity_perm- DRP-317 Leopard notebook against the Table 1 experimental porosity and permeability values
28_mwe_drp317_parker_raw_porosity_perm- DRP-317 Parker notebook against the Table 1 experimental porosity and permeability values
Example data under examples/data/ includes a deterministic manufactured void image and
generated artifacts from the extraction/mesh notebooks.
The project documentation now separates two kinds of evidence:
- Verification: benchmarks against software references and controlled numerical workflows
- Validation: benchmarks against experimental data
Software-verification reports live under docs/verification/.
Experimental-validation reports for the DRP-317 sandstones live under
docs/validation/.
The DRP-317 notebooks and validation reports use the following sources:
- Dataset: Neumann, R., ANDREETA, M., Lucas-Oliveira, E. (2020, October 7). 11 Sandstones: raw, filtered and segmented data [Dataset]. Digital Porous Media Portal. https://www.doi.org/10.17612/f4h1-w124
- Experimental reference paper: Neumann, R. F., Barsi-Andreeta, M., Lucas-Oliveira, E., Barbalho, H., Trevizan, W. A., Bonagamba, T. J., & Steiner, M. B. (2021). High accuracy capillary network representation in digital rock reveals permeability scaling functions. Scientific Reports, 11, 11370. https://doi.org/10.1038/s41598-021-90090-0
The full Table 1 sample references used by the DRP-317 notebooks are committed in
examples/data/drp-317/drp317_experimental_references.csv.
Several assumptions are deliberate and should be stated explicitly:
- extracted-network predictions depend strongly on upstream segmentation and extraction quality
- imported geometry fields may be incomplete or model-dependent across tools
- single-phase OpenPNM cross-checks compare solver/assembly consistency, not universal physical truth
- throat visualization may use arithmetic averaging of pore scalars when no throat scalar field is provided; that is a visualization choice, not a constitutive model
If any of those assumptions are inappropriate for a study, the corresponding workflow should be tightened before using results quantitatively.
Useful commands:
pixi run test
pixi run test-cov
pixi run lint
pixi run typecheck
pixi run precommit
pixi run notebooks-smokeVersion updates are handled with:
pixi run bump-version <new-version>voids is still pre-alpha. The codebase is already useful for controlled PNM experiments,
solver validation, and interoperability studies, but it should not be described as a
complete pore-network simulation platform yet.
voids receives institutional support from the
Laboratório Nacional de Computação Científica (LNCC),
a research unit of the Ministério da Ciência, Tecnologia e Inovação (MCTI), Brazil.
