diff --git a/.github/workflows/pypi-wheels-cpu.yml b/.github/workflows/pypi-wheels-cpu.yml index 9fd6762..242dfe4 100644 --- a/.github/workflows/pypi-wheels-cpu.yml +++ b/.github/workflows/pypi-wheels-cpu.yml @@ -18,6 +18,13 @@ jobs: submodules: recursive # Fetches Catch2, nlohmann/json, or pybind11 if needed fetch-depth: 0 + - name: Extract version from tag + id: version + run: | + # Strip leading 'v' from tag (e.g. v4.0.2 -> 4.0.2) + VERSION="${GITHUB_REF_NAME#v}" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + - name: Set up Python uses: actions/setup-python@v5 with: @@ -130,6 +137,7 @@ jobs: CMAKE_CXX_COMPILER="mpicxx" CMAKE_PREFIX_PATH="/usr/local" CMAKE_GENERATOR="Unix Makefiles" + SETUPTOOLS_SCM_PRETEND_VERSION="${{ steps.version.outputs.version }}" # Vendor libraries into the wheel, but exclude host-specific MPI and # runtime libraries that users must provide on their system. diff --git a/.github/workflows/pypi-wheels-gpu.yml b/.github/workflows/pypi-wheels-gpu.yml index f7023bf..0b663ff 100644 --- a/.github/workflows/pypi-wheels-gpu.yml +++ b/.github/workflows/pypi-wheels-gpu.yml @@ -18,6 +18,13 @@ jobs: submodules: recursive fetch-depth: 0 + - name: Extract version from tag + id: version + run: | + # Strip leading 'v' from tag (e.g. v4.0.2 -> 4.0.2) + VERSION="${GITHUB_REF_NAME#v}" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + - name: Set up Python uses: actions/setup-python@v5 with: @@ -143,6 +150,7 @@ jobs: CMAKE_PREFIX_PATH="/usr/local" CMAKE_GENERATOR="Unix Makefiles" CMAKE_ARGS="-DGPU_BACKEND=CUDA '-DCMAKE_CUDA_ARCHITECTURES=60;70;75;80;86;89;90' -DCMAKE_CUDA_HOST_COMPILER=/opt/rh/gcc-toolset-13/root/usr/bin/g++" + SETUPTOOLS_SCM_PRETEND_VERSION="${{ steps.version.outputs.version }}" # Vendor libraries but exclude host-specific MPI, OpenMP, Fortran runtime, # and CUDA runtime libraries (users must have CUDA toolkit installed). diff --git a/figure.pdf b/figure.pdf new file mode 100644 index 0000000..4a6c32a Binary files /dev/null and b/figure.pdf differ diff --git a/figure.png b/figure.png new file mode 100644 index 0000000..74f7037 Binary files /dev/null and b/figure.png differ diff --git a/figure.py b/figure.py new file mode 100644 index 0000000..f108d35 --- /dev/null +++ b/figure.py @@ -0,0 +1,112 @@ +"""Generate the architecture figure for the JOSS paper. + +Run: python figure.py +Output: figure.png +""" + +import matplotlib.pyplot as plt +import matplotlib.patches as mpatches +from matplotlib.patches import FancyBboxPatch, FancyArrowPatch + +fig, ax = plt.subplots(1, 1, figsize=(10, 6.5)) +ax.set_xlim(0, 10) +ax.set_ylim(0, 7) +ax.axis("off") + +# Colours +c_io = "#3498db" +c_solver = "#e74c3c" +c_output = "#2ecc71" +c_python = "#9b59b6" +c_bg = "#ecf0f1" + +def box(x, y, w, h, text, color, fontsize=9, bold=False): + rect = FancyBboxPatch( + (x, y), w, h, boxstyle="round,pad=0.15", + facecolor=color, edgecolor="white", linewidth=2, alpha=0.9 + ) + ax.add_patch(rect) + weight = "bold" if bold else "normal" + ax.text(x + w / 2, y + h / 2, text, ha="center", va="center", + fontsize=fontsize, color="white", fontweight=weight, + linespacing=1.4) + +def arrow(x1, y1, x2, y2): + ax.annotate("", xy=(x2, y2), xytext=(x1, y1), + arrowprops=dict(arrowstyle="->,head_width=0.3,head_length=0.15", + color="#7f8c8d", lw=2)) + +# Title +ax.text(5, 6.7, "OpenImpala Architecture", ha="center", va="center", + fontsize=14, fontweight="bold", color="#2c3e50") + +# ---- Python API layer (top) ---- +box(1.5, 5.8, 7, 0.7, "Python API: import openimpala\n" + "Session | tortuosity() | volume_fraction() | percolation_check()", + c_python, fontsize=9, bold=True) + +# Arrow down +arrow(5, 5.8, 5, 5.4) + +# ---- I/O Layer ---- +box(0.3, 4.2, 2.4, 1.1, + "I/O Layer\n\nTIFF | HDF5\nRAW | DAT", + c_io, fontsize=9, bold=False) + +# ---- Solver Layer ---- +box(3.1, 4.2, 3.8, 1.1, + "Physics Solvers\n\nHYPRE (Krylov + AMG)\nAMReX MLMG (matrix-free)", + c_solver, fontsize=9, bold=False) + +# ---- Output Layer ---- +box(7.3, 4.2, 2.4, 1.1, + "Output Layer\n\nJSON (BPX)\nCSV | Plotfiles", + c_output, fontsize=9, bold=False) + +# Arrows between layers +arrow(2.7, 4.75, 3.1, 4.75) +arrow(6.9, 4.75, 7.3, 4.75) + +# ---- Transport Properties (middle) ---- +box(0.3, 2.6, 4.3, 1.2, + "Transport Properties\n\n" + "Tortuosity factor | D_eff tensor\n" + "Multi-phase transport | Percolation", + "#e67e22", fontsize=9) + +box(5.0, 2.6, 4.7, 1.2, + "Microstructural Metrics\n\n" + "Volume fraction | SSA | PSD\n" + "Connected components | REV study", + "#e67e22", fontsize=9) + +# Arrows down from solvers +arrow(3.5, 4.2, 2.5, 3.8) +arrow(5.0, 4.2, 5.0, 3.8) +arrow(6.5, 4.2, 7.3, 3.8) + +# ---- AMReX / HPC layer (bottom) ---- +box(0.3, 1.0, 9.4, 1.1, + "AMReX Infrastructure: MPI + OpenMP + CUDA\n" + "iMultiFab (voxel data) | BoxArray (domain decomposition) | " + "Geometry | BL_PROFILE timers", + "#34495e", fontsize=9, bold=True) + +# Arrows down to AMReX +arrow(2.5, 2.6, 2.5, 2.1) +arrow(7.3, 2.6, 7.3, 2.1) + +# ---- External data (left of I/O) ---- +ax.text(0.15, 5.55, "3D voxel\nimages", ha="center", va="center", + fontsize=8, color="#7f8c8d", style="italic") +arrow(0.15, 5.3, 0.8, 4.9) + +# ---- Downstream (right of output) ---- +ax.text(9.85, 5.55, "PyBaMM\nBPX", ha="center", va="center", + fontsize=8, color="#7f8c8d", style="italic") +arrow(9.2, 4.9, 9.85, 5.3) + +plt.tight_layout() +plt.savefig("figure.png", dpi=300, bbox_inches="tight", facecolor="white") +plt.savefig("figure.pdf", bbox_inches="tight", facecolor="white") +print("Saved figure.png and figure.pdf") diff --git a/paper.bib b/paper.bib index 999e855..bfddc38 100644 --- a/paper.bib +++ b/paper.bib @@ -1,5 +1,5 @@ @article{LeHoux2021OpenImpala, - title = {{{OpenImpala}}: {{OPEN}} source {{IMage}} based {{PArallisable}} {{Linear}} {{Algebra}} solver}, + title = {{OpenImpala}: {OPEN} source {IMage} based {PArallisable} {Linear} {Algebra} solver}, author = {Le Houx, James and Kramer, Denis}, year = {2021}, journal = {SoftwareX}, @@ -10,64 +10,132 @@ @article{LeHoux2021OpenImpala } @article{le2023statistical, - title={Statistical Effective Diffusivity Estimation in Porous Media Using an Integrated On-site Imaging Workflow for Synchrotron Users}, - author={Le Houx, James and Ruiz, Siul and McKay Fletcher, Daniel and Ahmed, Sharif and Roose, Tiina}, - journal={Transport in Porous Media}, - volume={150}, - number={1}, - pages={71--88}, - year={2023}, - publisher={Springer}, - doi={10.1007/s11242-023-01993-7} + title = {Statistical Effective Diffusivity Estimation in Porous Media Using an Integrated On-site Imaging Workflow for Synchrotron Users}, + author = {Le Houx, James and Ruiz, Siul and McKay Fletcher, Daniel and Ahmed, Sharif and Roose, Tiina}, + journal = {Transport in Porous Media}, + volume = {150}, + number = {1}, + pages = {71--88}, + year = {2023}, + publisher = {Springer}, + doi = {10.1007/s11242-023-01993-7} } @article{amrex2019, - title={AMReX: a framework for block-structured adaptive mesh refinement}, - author={Zhang, Weiqun and Almgren, Ann and Beckner, Vince and Bell, John and Blaschke, Johannes and Chan, Cy and Day, Marcus and Friesen, Brian and Gott, Kevin and Graves, Daniel and others}, - journal={Journal of Open Source Software}, - volume={4}, - number={37}, - pages={1370}, - year={2019}, - doi={10.21105/joss.01370} -} - -@article{lu2025immersed, - title={An immersed interface Adaptive Mesh Refinement algorithm for Li-ion battery simulations. II. Multi-dimensional extension and separator modeling}, - author={Lu, Jiawei and Nikiforakis, Nikolaos and Gokhale, Nandan}, - journal={Journal of Applied Physics}, - volume={138}, - number={4}, - pages={045002}, - year={2025}, - publisher={AIP Publishing}, - doi={10.1063/5.0281626} + title = {{AMReX}: a framework for block-structured adaptive mesh refinement}, + author = {Zhang, Weiqun and Almgren, Ann and Beckner, Vince and Bell, John and Blaschke, Johannes and Chan, Cy and Day, Marcus and Friesen, Brian and Gott, Kevin and Graves, Daniel and others}, + journal = {Journal of Open Source Software}, + volume = {4}, + number = {37}, + pages = {1370}, + year = {2019}, + doi = {10.21105/joss.01370} } @article{sulzer2021python, - title={{Python Battery Mathematical Modelling (PyBaMM)}}, - author={Sulzer, Valentin and Marquis, Scott G and Timms, Robert and Robinson, Martin and Chapman, S Jon}, - journal={Journal of Open Research Software}, - volume={9}, - number={1}, - year={2021}, - publisher={Ubiquity Press}, - doi={10.5334/jors.309} + title = {{Python Battery Mathematical Modelling (PyBaMM)}}, + author = {Sulzer, Valentin and Marquis, Scott G and Timms, Robert and Robinson, Martin and Chapman, S Jon}, + journal = {Journal of Open Research Software}, + volume = {9}, + number = {1}, + year = {2021}, + publisher = {Ubiquity Press}, + doi = {10.5334/jors.309} } @inproceedings{falgout2002hypre, - title={hypre: A library of high performance preconditioners}, - author={Falgout, Robert D and Yang, Ulrike Meier}, - booktitle={International Conference on Computational Science}, - pages={632--641}, - year={2002}, - organization={Springer}, - doi={10.1007/3-540-47789-6_66} + title = {hypre: A library of high performance preconditioners}, + author = {Falgout, Robert D and Yang, Ulrike Meier}, + booktitle = {International Conference on Computational Science}, + pages = {632--641}, + year = {2002}, + organization = {Springer}, + doi = {10.1007/3-540-47789-6_66} } @misc{jakob2017pybind11, - author = {Wenzel Jakob and Jason Rhinelander and Dean Moldovan}, - year = {2017}, - note = {https://github.com/pybind/pybind11}, - title = {pybind11 -- Seamless operability between C++11 and Python} + author = {Wenzel Jakob and Jason Rhinelander and Dean Moldovan}, + year = {2017}, + title = {pybind11 -- Seamless operability between {C}++11 and {Python}}, + url = {https://github.com/pybind/pybind11} +} + +@article{cooper2016taufactor, + title = {{TauFactor}: An open-source application for calculating tortuosity factors from tomographic data}, + author = {Cooper, Samuel J and Bertei, Antonio and Shearing, Paul R and Kilner, John A and Brandon, Nigel P}, + journal = {SoftwareX}, + volume = {5}, + pages = {203--210}, + year = {2016}, + publisher = {Elsevier}, + doi = {10.1016/j.softx.2016.09.002} +} + +@article{gostick2019porespy, + title = {{PoreSpy}: A {Python} Toolkit for Quantitative Analysis of Porous Media Images}, + author = {Gostick, Jeff T and Khan, Zohaib A and Tranter, Thomas G and Kok, Matthew D R and Agnaou, Mehrez and Sadeghi, Mohammadamin and Jervis, Rhodri}, + journal = {Journal of Open Source Software}, + volume = {4}, + number = {37}, + pages = {1296}, + year = {2019}, + doi = {10.21105/joss.01296} +} + +@article{ferguson2018puma, + title = {{PuMA}: the Porous Microstructure Analysis software}, + author = {Ferguson, Joseph C and Panerai, Francesco and Borner, Arnaud and Mansour, Nagi N}, + journal = {SoftwareX}, + volume = {7}, + pages = {81--87}, + year = {2018}, + publisher = {Elsevier}, + doi = {10.1016/j.softx.2018.03.001} +} + +@article{lu2025immersed, + title = {An immersed interface Adaptive Mesh Refinement algorithm for {Li}-ion battery simulations. {II}. Multi-dimensional extension and separator modeling}, + author = {Lu, Jiawei and Nikiforakis, Nikolaos and Gokhale, Nandan}, + journal = {Journal of Applied Physics}, + volume = {138}, + number = {4}, + pages = {045002}, + year = {2025}, + publisher = {AIP Publishing}, + doi = {10.1063/5.0281626} +} + +@article{tjaden2016origin, + title = {On the origin and application of the {Bruggeman} correlation for analysing transport phenomena in electrochemical systems}, + author = {Tjaden, Bernhard and Cooper, Samuel J and Brett, Daniel JL and Kramer, Denis and Shearing, Paul R}, + journal = {Current Opinion in Chemical Engineering}, + volume = {12}, + pages = {44--51}, + year = {2016}, + publisher = {Elsevier}, + doi = {10.1016/j.coche.2016.02.006} +} + +@article{epstein1989tortuosity, + title = {On tortuosity and the tortuosity factor in flow and diffusion through porous media}, + author = {Epstein, Norman}, + journal = {Chemical Engineering Science}, + volume = {44}, + number = {3}, + pages = {777--779}, + year = {1989}, + publisher = {Elsevier}, + doi = {10.1016/0009-2509(89)85053-5} +} + +@article{withers2021xray, + title = {X-ray computed tomography}, + author = {Withers, Philip J and Bouman, Charles and Carmignato, Simone and Cnudde, Veerle and Grimaldi, David and Hagen, Charlotte K and Maire, Eric and Manber, Mariam and Martini, Fabrizio and Stock, Stuart R}, + journal = {Nature Reviews Methods Primers}, + volume = {1}, + number = {1}, + pages = {18}, + year = {2021}, + publisher = {Nature Publishing Group}, + doi = {10.1038/s43586-021-00015-4} } diff --git a/paper.md b/paper.md index 5df46ce..7787b95 100644 --- a/paper.md +++ b/paper.md @@ -1,5 +1,5 @@ --- -title: 'OpenImpala: A High-Performance, Image-Based Microstructural Parameterisation Engine for Porous Media' +title: 'OpenImpala: Scalable Transport Property Computation on 3D Voxel Images of Porous Media' tags: - C++ - Python @@ -8,6 +8,7 @@ tags: - battery modelling - AMReX - tortuosity + - effective diffusivity authors: - name: James Le Houx orcid: 0000-0002-1576-0673 @@ -15,7 +16,7 @@ authors: email: james.le-houx@stfc.ac.uk affiliation: "1, 2, 3" - name: Denis Kramer - orcid: 0000-0003-0605-1047 + orcid: 0000-0003-0605-1047 affiliation: 4 affiliations: - name: University of Greenwich, Old Royal Naval College, Park Row, London, SE10 9LS, United Kingdom @@ -29,31 +30,77 @@ affiliations: date: 29 March 2026 bibliography: paper.bib --- + # Summary -`OpenImpala` is a high-performance computing (HPC) framework built upon the AMReX library, designed for the direct evaluation of effective transport properties—such as tortuosity and effective electrical conductivity—from three-dimensional microstructural imaging data (e.g., X-ray Computed Tomography). By formulating the discrete governing equations directly on Cartesian voxel grids, `OpenImpala` circumvents the computationally prohibitive mesh-generation bottlenecks typically associated with conventional finite element methods (FEM). The framework couples a highly scalable, distributed-memory C++ computational backend with a flexible Python interface, facilitating the automated parameterisation of complex porous media for downstream systems-level continuum modelling. +`OpenImpala` is a high-performance computing framework for evaluating effective transport properties — tortuosity, effective diffusivity tensors, and effective conductivity — directly from three-dimensional microstructural imaging data such as X-ray CT reconstructions [@withers2021xray]. Built upon the AMReX adaptive mesh refinement library [@amrex2019], `OpenImpala` formulates the governing partial differential equations on the Cartesian voxel grid, eliminating the mesh-generation step that limits conventional finite element approaches. The framework couples a scalable, distributed-memory C++ backend with the HYPRE linear solver library [@falgout2002hypre] and a Python interface via pybind11 [@jakob2017pybind11], enabling automated microstructural parameterisation for downstream continuum modelling. + +An earlier version of the software was described in @LeHoux2021OpenImpala. Since that publication the codebase has been redesigned with the following major additions: GPU acceleration via CUDA, a matrix-free geometric multigrid solver (AMReX MLMG), full effective diffusivity tensor computation via homogenisation, multi-phase transport, microstructural characterisation modules, and a high-level Python API distributed through PyPI. # Statement of Need -High-resolution three-dimensional microstructural imaging is increasingly utilized across battery research, geosciences, and materials engineering to characterize internal transport phenomena. However, the extraction of bulk effective physical parameters from billion-voxel datasets represents a significant computational challenge. Conventional finite element tools often encounter tractability limits during the mesh-generation phase when applied to complex, highly tortuous microstructures. Conversely, existing open-source voxel-based solvers, while highly accessible, generally lack the distributed-memory Message Passing Interface (MPI) scalability required to process massive, out-of-core datasets on HPC architectures. +High-resolution three-dimensional microstructural imaging is increasingly utilised across battery research, geosciences, and materials engineering to characterise internal transport phenomena [@withers2021xray]. Extracting bulk effective physical parameters — particularly the tortuosity factor [@epstein1989tortuosity; @tjaden2016origin] — from billion-voxel datasets represents a significant computational challenge. + +Several open-source tools address this problem. TauFactor [@cooper2016taufactor] pioneered accessible tortuosity computation through an intuitive MATLAB interface and has seen widespread adoption in the battery community. However, TauFactor operates on a single compute node with an iterative relaxation scheme that does not leverage distributed-memory parallelism. PoreSpy [@gostick2019porespy] provides a comprehensive Python toolkit for morphological image analysis but does not include PDE-based transport solvers. PuMA [@ferguson2018puma] offers voxel-based effective property computation in C++ with multi-threading support, but lacks distributed-memory (MPI) scalability for out-of-core datasets. -`OpenImpala` addresses this methodological gap by providing a natively parallelised (MPI, OpenMP, and CUDA) matrix-free AMReX backend capable of scaling across thousands of compute cores. Through its modern Python application programming interface (API), `OpenImpala` serves as a robust upstream microstructural parameterisation engine. It is capable of ingesting raw or segmented tomographic data and seamlessly exporting computed effective macroscopic properties to downstream continuum models, such as the widely adopted PyBaMM battery modelling framework. +`OpenImpala` addresses these limitations by combining MPI, OpenMP, and CUDA parallelism in a single solver backend capable of scaling across hundreds of compute cores and GPU accelerators. Through its Python API (`import openimpala`), the framework serves as an upstream microstructural parameterisation engine: it ingests raw or segmented tomographic data and exports computed effective properties to downstream continuum models such as PyBaMM [@sulzer2021python]. The methodology has been validated in synchrotron imaging workflows for statistical effective diffusivity estimation [@le2023statistical], and the AMReX-based infrastructure opens a pathway toward multi-scale battery simulation approaches [@lu2025immersed]. # Software Architecture and Capabilities -`OpenImpala` is engineered to achieve exascale readiness on heterogeneous hardware, enable seamless interoperability with the broader scientific Python ecosystem, and ensure long-term software sustainability. To address the computational demands of increasingly massive tomographic datasets, the core architecture is built upon a pure C++ infrastructure utilizing native AMReX Lambdas. This design facilitates native GPU acceleration via CUDA, allowing the solver to fully leverage modern heterogeneous supercomputing architectures. Furthermore, to optimize memory utilization during massive out-of-core computations, the framework utilizes intelligent solver routing driven by AMReX’s Matrix-Free Multi-Level Multi-Grid (MLMG) infrastructure, all managed by a modern, modular CMake build system. +\autoref{fig:architecture} illustrates the architecture of `OpenImpala`. The framework is organised into three layers: an I/O layer that reads TIFF, HDF5, and raw binary volumetric images into AMReX distributed data structures; a physics solver layer that computes transport properties on the voxel grid; and an output layer that exports structured results in JSON format compatible with battery parameterisation standards such as BPX and BattINFO. + +![High-level architecture of OpenImpala. The I/O layer reads 3D voxel images into AMReX distributed data structures. The physics layer solves steady-state diffusion equations via HYPRE (Krylov + algebraic multigrid) or AMReX MLMG (geometric multigrid). The output layer exports tortuosity, effective diffusivity tensors, and microstructural metrics in structured JSON format.\label{fig:architecture}](figure.png) + +## Solver Infrastructure + +The primary physics solver discretises the steady-state diffusion equation $\nabla \cdot (D \nabla \phi) = 0$ on a seven-point finite difference stencil, with Dirichlet boundary conditions at the inlet and outlet faces and zero-flux Neumann conditions on the lateral boundaries. Inter-cell face diffusivities are computed as the harmonic mean of adjacent cell values, which is physically correct for the series resistance analogy. Two solver backends are available: + +- **HYPRE** [@falgout2002hypre]: Krylov solvers (PCG, FlexGMRES, BiCGSTAB) with algebraic multigrid preconditioning (SMG, PFMG). Supports CUDA-accelerated solves via HYPRE's device execution policy. +- **AMReX MLMG**: A matrix-free geometric multigrid solver that operates without explicit matrix assembly, reducing memory consumption by approximately $3\times$ compared to the HYPRE structured matrix approach. + +## Transport Properties + +`OpenImpala` computes the following effective transport properties: + +- **Tortuosity factor**: Defined as $\tau = \varepsilon / D_{\text{eff}}$, where $\varepsilon$ is the connected volume fraction and $D_{\text{eff}}$ is the normalised effective diffusivity obtained from the flux integral across the domain. +- **Effective diffusivity tensor**: The full $3\times 3$ symmetric tensor $\mathbf{D}_{\text{eff}}$ is computed via a homogenisation cell problem $\nabla \cdot (D \nabla \chi_j) = -\nabla \cdot (D \hat{e}_j)$, solved independently for each Cartesian direction $j \in \{x, y, z\}$. +- **Multi-phase transport**: Arbitrary numbers of solid and pore phases can be assigned distinct transport coefficients, enabling simulation of composite electrode microstructures with heterogeneous material properties. + +## Microstructural Characterisation + +Beyond transport properties, the framework includes modules for: + +- **Volume fraction** and **percolation checking** via parallel flood-fill with MPI ghost-cell exchange. +- **Connected component labelling** for identifying distinct pore or particle clusters. +- **Particle size distribution** computed from equivalent sphere radii of labelled connected components. +- **Specific surface area** via voxel face counting with Cauchy–Crofton stereological correction. +- **Through-thickness profiles** of phase fraction along any Cartesian direction. +- **Representative elementary volume (REV) convergence studies** that extract random sub-volumes of increasing size and track tensor convergence. + +## Python API and Distribution + +The Python interface exposes the core solver capabilities through a high-level facade: + +```python +import openimpala as oi +with oi.Session(): + result = oi.tortuosity(data, phase=0, direction="z") + print(f"Tortuosity: {result.tortuosity:.4f}") +``` + +Pre-compiled CPU and CUDA GPU wheels are distributed via PyPI (`pip install openimpala` or `pip install openimpala-cuda`), built using `cibuildwheel` with statically linked dependencies. Interactive tutorial notebooks are provided for Google Colab, covering workflows from basic tortuosity computation to digital twin parameterisation with PyBaMM. -Beyond raw computational performance, the framework functions as an accessible, upstream parameterisation engine for modern continuum modelling workflows. Recognizing that the battery and geoscience modelling communities operate predominantly within Python, `OpenImpala` acts as a fully importable Python library (`import openimpala`) via `pybind11`. Distribution is handled using `pyproject.toml` and `cibuildwheel` to enable standard package manager installations (e.g., `pip`). This community-accessible library is supported by a comprehensive Sphinx and ReadTheDocs infrastructure, featuring extensive tutorial series and Doxygen-generated API references. +## Testing and Quality Assurance -Finally, the physical fidelity and scientific rigor of the framework are a primary focus. `OpenImpala` supports complex multi-phase computations, allowing users to map specific phase identifiers to unique transport coefficients. It also features an integrated microstructural parameterisation engine capable of extracting macroscopic metrics such as Specific Surface Area (SSA), Representative Elementary Volumes (REV), and Pore Size Distributions (PSD). To guarantee the mathematical correctness of these physics modules, rigorous software engineering practices are enforced. This includes comprehensive input validation to prevent silent numerical failures in complex HPC environments, synthetic analytical benchmarking, integrated Catch2 testing, and automated CI/CD GitHub Actions pipelines for code formatting (`clang-format`), static analysis (`clang-tidy`), and test coverage reporting via Codecov. +The test suite includes three analytical regression benchmarks — uniform block, series layers (Reuss bound), and parallel layers (Voigt bound) — each with exact discrete solutions that verify solver correctness to machine precision. Integration tests exercise the full pipeline on real tomographic data via CTest, and Catch2 unit tests cover configuration parsing and JSON output modules. Continuous integration enforces `clang-format` style checking, `clang-tidy` static analysis, and code coverage reporting via Codecov. # Future Directions -Active development is focused on deepening integration with the broader scientific Python ecosystem. This includes the implementation of a direct memory-coupling API for PyBaMM, enabling researchers to perform 3D microstructural parameterisation and 1D electrochemical simulation in a single, zero-copy Python script. +Active development is focused on three areas. First, GPU-accelerated solves via CUDA are now available through dedicated PyPI wheels, and profiling infrastructure (AMReX TinyProfiler integration, NVIDIA Nsight Systems workflows) has been established to guide further kernel-level optimisation. Second, embedded boundary (cut-cell) methods via AMReX's EB2 infrastructure are being investigated to achieve sub-voxel geometric accuracy without mesh generation. Third, direct memory-coupling with PyBaMM [@sulzer2021python] is planned to enable researchers to perform 3D microstructural parameterisation and 1D electrochemical simulation in a single, zero-copy Python script. # Acknowledgements -This work was financially supported by the EPSRC Centre for Doctoral Training (CDT) in Energy Storage and its Applications [grant ref: EP/R021295/1]; the Ada Lovelace Centre (ALC) STFC project, CANVAS-NXtomo; the EPSRC prosperity partnership with Imperial College, INFUSE [grant ref: EP/V038044/1]; the Rutherford Appleton Laboratory; The Faraday Institution through James Le Houx's Emerging Leader Fellowship [Grant No. FIELF001]; and Research England’s ‘Expanding Excellence in England’ grant at the University of Greenwich via the “Multi-scale Multi-disciplinary Modelling for Impact” (M34Impact) programme. +This work was financially supported by the EPSRC Centre for Doctoral Training (CDT) in Energy Storage and its Applications [grant ref: EP/R021295/1]; the Ada Lovelace Centre (ALC) STFC project, CANVAS-NXtomo; the EPSRC prosperity partnership with Imperial College, INFUSE [grant ref: EP/V038044/1]; the Rutherford Appleton Laboratory; The Faraday Institution through James Le Houx's Emerging Leader Fellowship [Grant No. FIELF001]; and Research England's 'Expanding Excellence in England' grant at the University of Greenwich via the "Multi-scale Multi-disciplinary Modelling for Impact" (M34Impact) programme. The authors acknowledge the use of the IRIDIS High Performance Computing Facility, Diamond Light Source's Wilson HPC cluster, STFC's SCARF cluster, and the University of Greenwich's M34Impact HPC Cluster. We also thank the developers of AMReX, HYPRE, libtiff, and HDF5, upon which OpenImpala relies.