Metadata-Version: 2.4
Name: dgfn
Version: 0.1.0
Summary: Discrete Graph Fracture Network: graph-based flow and transport modeling for fractured subsurface systems
Author-email: Christopher Zahasky <czahasky@wisc.edu>, Collin Sutton <collin.sutton@wisc.edu>
Maintainer-email: Christopher Zahasky <czahasky@wisc.edu>
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/czahasky/dgfn
Project-URL: Repository, https://github.com/czahasky/dgfn
Project-URL: Issues, https://github.com/czahasky/dgfn/issues
Project-URL: Documentation, https://github.com/czahasky/dgfn#readme
Keywords: fracture-network,subsurface,transport,graph,DFN,DFM,TDRW,particle-tracking,porous-media
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Hydrology
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.22
Requires-Dist: scipy>=1.9
Requires-Dist: matplotlib>=3.5
Requires-Dist: networkx>=2.8
Requires-Dist: pandas>=1.4
Requires-Dist: scikit-learn>=1.0
Requires-Dist: openpyxl>=3.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: ipykernel; extra == "dev"
Requires-Dist: nbstripout; extra == "dev"
Requires-Dist: jupyter; extra == "dev"
Provides-Extra: viz
Requires-Dist: cmcrameri; extra == "viz"
Provides-Extra: all
Requires-Dist: dgfn[dev,viz]; extra == "all"
Dynamic: license-file

# dgfn — Discrete Graph Fracture Network

[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
[![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)

`dgfn` is a Python package for **graph-based flow and transport modeling in fractured subsurface systems**. It complements the established Discrete Fracture Network (DFN) and Discrete Fracture Matrix (DFM) modeling traditions by representing fractures as graphs of nodes (with apertures) connected by edges (with geometric and hydraulic properties).

The package combines:

- **Steady-state flow** on graph networks via Laplacian assembly with mixed Dirichlet/Neumann boundary conditions.
- **Time Domain Random Walk (TDRW)** transport with Péclet-based edge transitions, matrix diffusion, retardation, deposition, and first-order decay.
- **Aperture calibration** against pressure observations using nonlinear least squares.
- **Experimental data integration** for breakthrough curve (BTC) analysis from radiotracer or other concentration measurements.

## Installation

```bash
pip install dgfn
```

To include the scientific colormaps used in some example workflows:

```bash
pip install "dgfn[viz]"
```

### Verify the install

After installation, run:

```python
import dgfn
print(dgfn.__version__)
```

You should see `0.1.0` (or whatever the current version is). The Quickstart below is fully self-contained — if it runs without errors, your install is healthy.

## Quickstart

This example is self-contained: it builds a small synthetic graph, solves flow, runs TDRW transport, and produces a breakthrough curve — no external data files required.

```python
import numpy as np
import pandas as pd
from dgfn import GraphNetwork, FlowSimulator, TransportSimulator

# 1. Build a small synthetic graph: a 4x3 grid of nodes with one
#    injection node (Neumann) and one pressure-fixed outlet (Dirichlet).
xs = np.linspace(0.0, 0.05, 4)      # 5 cm in x
zs = np.linspace(0.0, 0.03, 3)      # 3 cm in z
X, Z = np.meshgrid(xs, zs, indexing='ij')
n = X.size

df = pd.DataFrame({
    'x': X.ravel(), 'y': np.zeros(n), 'z': Z.ravel(),
    'cluster_id': np.nan, 'cmax': np.nan,
    'aperture': np.full(n, 5e-5),                 # 50 micron initial guess
    'bc_type': pd.Series([None] * n, dtype=object),
    'bc_value': np.nan, 'cal_point': np.nan,
})
df.loc[0, ['bc_type', 'bc_value']] = ['injection', 1e-7]    # inlet, ~0.1 mL/min
df.loc[n - 1, ['bc_type', 'bc_value']] = ['pressure', 0.0]  # outlet at 0 Pa

G = GraphNetwork(df, mu=8.9e-4, dy=0.005)
G.build_knn_graph(k=3)

# 2. Solve steady-state flow
sim_flow = FlowSimulator(G)
Gf = sim_flow.solve(rescale_injection_nodes=True)
print(Gf)                 # flow / mass-balance summary

# 3. Run TDRW transport with a short synthetic injection pulse
exp_t = pd.Series(np.linspace(0, 200, 1000))
exp_c = pd.Series(np.where(exp_t < 10, 1.0, 0.0))   # 10 s square pulse
sim = TransportSimulator(G, Gf, Dm=6.7e-10)
sim.initiate_particles(2000, exp_t, exp_c, seed=42)
sol = sim.solve(model_run_time=300.0, alpha=0.005)

# 4. Inspect the breakthrough curve
print(sol)                # transport / mass-balance summary
btc = sol.btc             # (time, concentration) array
```

For real workflows, graph definitions are typically loaded from tabular data
(one row per node, with `x`/`y`/`z`, boundary conditions, and optional
calibration values), apertures are calibrated against measured pressures with
`ApertureBuilder.tune()`, and experimental breakthrough data is read in with
`dgfn.data_processing.input_exp_data`. More detailed, runnable example
notebooks — covering aperture calibration, parallel transport, and fitting to
experimental core-flood data — are being collected in a separate documentation
site (link forthcoming).

## Module overview

| Module | Purpose |
|---|---|
| `dgfn.graph_model` | `GraphNetwork` (nodes + connectivity) and `ApertureBuilder` (parameterization and calibration). |
| `dgfn.flow` | Steady-state flow solver (`FlowSimulator`) and result container (`FlowSolution`). |
| `dgfn.transport` | TDRW particle tracker (`TransportSimulator`) with matrix diffusion, retardation, decay, and deposition options. |
| `dgfn.data_processing` | Read experimental BTC data (`input_exp_data`) into a tidy DataFrame. |
| `dgfn.plotting` | Quick-look plots for BTCs, aperture distributions, graphs, and pressure fields. |
| `dgfn.utils` | Quantile calculations, analytical 1-D ADE solutions, and the `BTC` dataclass. |

## Public API

The most common entry points are available as top-level imports:

```python
from dgfn import (
    GraphNetwork, ApertureBuilder,      # build and parameterize graphs
    FlowSimulator, FlowSolution,        # steady-state flow
    TransportSimulator, TransportSolution,  # TDRW particle tracking
    input_exp_data,                     # read experimental BTC data
    plot_graph, plot_btc, plot_ap_histogram,  # visualization
)
```

Less common functions are reachable through the submodules directly, e.g.
`dgfn.utils.quantile_calc` or `dgfn.graph_model.GraphNetwork.build_gabriel_graph`.

## Citing dgfn

If you use `dgfn` in published work, please cite this repository (a `CITATION.cff` file with full citation metadata is forthcoming).

## License

`dgfn` is released under the BSD 3-Clause License. You're free to use, modify, and redistribute the code, including in commercial products, as long as you preserve the copyright notice and don't use the authors' names to endorse derivative work without permission.
