| --- |
| license: apache-2.0 |
| language: |
| - en |
| tags: |
| - geothermal |
| - reservoir-simulation |
| - physics-informed |
| - surrogate-model |
| - energy |
| - cnn |
| - pytorch |
| - geoscience |
| - indonesia |
| library_name: pytorch |
| pipeline_tag: other |
| metrics: |
| - r_squared |
| - mse |
| datasets: |
| - ForceX-AI/geothermal-reservoir-dataset |
| model-index: |
| - name: GeoForce-CNN-v1.1 |
| results: |
| - task: |
| type: other |
| name: Geothermal Reservoir Prediction |
| metrics: |
| - name: Temperature RMSE |
| type: rmse |
| value: 3.31 |
| - name: Temperature R² |
| type: r_squared |
| value: 0.994 |
| - name: Pressure RMSE (MPa) |
| type: rmse |
| value: 0.354 |
| - name: Pressure R² |
| type: r_squared |
| value: 0.997 |
| - name: Inference Time (ms) |
| type: latency |
| value: 3.19 |
| - name: Speedup vs Simulator |
| type: speedup |
| value: 282350 |
| --- |
| |
| # GeoForce-CNN v1.1: Physics-Informed CNN Surrogate for Geothermal Reservoir Prediction |
|
|
| **GeoForce** is a physics-informed convolutional neural network (CNN) that predicts temperature and pressure field evolution in geothermal reservoirs. It replaces computationally expensive numerical simulators with a compact 57,802-parameter model that runs in **3.2ms on CPU** — a **282,350x speedup** over finite-difference simulation. |
|
|
| <div align="center"> |
|
|
| | Metric | Value | |
| |--------|-------| |
| | Temperature RMSE | **3.31°C** | |
| | Temperature R² | **0.994** | |
| | Pressure RMSE | **0.354 MPa** | |
| | Pressure R² | **0.997** | |
| | Physics Violations | **0.0%** | |
| | Inference Time | **3.19 ms** (CPU) | |
| | Speedup vs Simulator | **282,350x** | |
| | Parameters | **57,802** | |
|
|
| </div> |
|
|
| ## Model Description |
|
|
| GeoForce maps static reservoir properties (temperature, permeability, porosity, depth, well locations, pressure) directly to spatiotemporal temperature and pressure fields over a 20-year production horizon. It was designed for rapid uncertainty quantification and well placement optimization in Indonesian geothermal systems. |
|
|
| ### Architecture |
|
|
| Encoder-Residual-Decoder CNN: |
|
|
| ``` |
| Input (batch, 6, 32, 32) |
| ↓ |
| [Encoder] |
| ConvBlock: Conv2d(6→32, 3×3) + BatchNorm + ReLU |
| ConvBlock: Conv2d(32→32, 3×3) + BatchNorm + ReLU |
| ↓ |
| [Middle] |
| ResidualBlock: Conv→BN→ReLU→Conv→BN + skip → ReLU |
| ResidualBlock: Conv→BN→ReLU→Conv→BN + skip → ReLU |
| ↓ |
| [Decoder] |
| ConvBlock: Conv2d(32→32, 3×3) + BatchNorm + ReLU |
| Conv2d(32→10, 1×1) + Sigmoid |
| ↓ |
| Output (batch, 10, 32, 32) |
| → Channels 0-4: Temperature at years 4, 8, 12, 16, 20 |
| → Channels 5-9: Pressure at years 4, 8, 12, 16, 20 |
| ``` |
|
|
| ### Input Channels (6) |
|
|
| | Channel | Content | Normalization | |
| |---------|---------|---------------| |
| | 0 | Initial temperature field (°C) | (T - 25) / 325 | |
| | 1 | Log₁₀ permeability (m²) | (log_k + 16) / 4 | |
| | 2 | Well mask (Gaussian decay) | [0, 1] | |
| | 3 | Base pressure (Pa) | (P - 5e6) / 20e6 | |
| | 4 | Porosity | (φ - 0.01) / 0.14 | |
| | 5 | Depth (m) | (z - 800) / 1700 | |
| |
| ### Physics-Informed Loss |
| |
| The training loss combines data-driven MSE with three physics constraints: |
| |
| ``` |
| L_total = L_data + 0.1 × L_physics |
| L_physics = 0.1 × L_temporal + 0.01 × L_spatial + 0.001 × L_darcy |
| ``` |
| |
| - **Temporal smoothness**: Penalizes non-physical jumps between timesteps (energy conservation proxy) |
| - **Spatial smoothness**: Discrete Laplacian penalty enforcing diffusion behavior |
| - **Darcy coupling**: Constrains pressure gradients in high-permeability zones |
| |
| ## Training |
| |
| - **Data**: 1,000 synthetic reservoir simulations via implicit finite-difference solver (coupled heat + Darcy flow) |
| - **Parameter ranges**: Calibrated to Indonesian geothermal fields (Kamojang, Wayang Windu, Darajat) |
| - **Split**: 800 train / 100 val / 100 test (seed=42) |
| - **Optimizer**: Adam (lr=1e-3, ReduceLROnPlateau) |
| - **Training time**: 44.9 minutes on CPU (no GPU required) |
| - **Best epoch**: 352 / 402 (early stopped, patience=50) |
| - **Best validation loss**: 0.000382 |
| |
| ## Quick Start |
| |
| ```python |
| import torch |
| import numpy as np |
| from reservoir_cnn import ReservoirCNN |
| |
| # Load model |
| model = ReservoirCNN(in_channels=6, n_time_steps=5, base_filters=32) |
| checkpoint = torch.load("geoforce_cnn_v1.1.pt", map_location="cpu", weights_only=False) |
| model.load_state_dict(checkpoint["model_state_dict"]) |
| model.eval() |
| |
| # Prepare input: 6-channel tensor on 32×32 grid |
| # Example: Kamojang-like reservoir |
| base_temp = 245.0 # °C |
| log_perm = -14.0 # log10(m²) |
| base_pressure = 15e6 # Pa (15 MPa) |
| porosity = 0.08 |
| depth = 1500.0 # m |
| n_wells = 3 |
| |
| # Normalize inputs |
| inp = torch.zeros(1, 6, 32, 32) |
| inp[0, 0] = (base_temp - 25) / 325 # Temperature |
| inp[0, 1] = (log_perm + 16) / 4 # Permeability |
| # Channel 2: well mask (place wells with Gaussian decay) |
| for _ in range(n_wells): |
| wx, wy = np.random.randint(4, 28, size=2) |
| for i in range(32): |
| for j in range(32): |
| d = ((i - wy)**2 + (j - wx)**2) / 50.0 |
| inp[0, 2, i, j] = max(inp[0, 2, i, j].item(), np.exp(-d)) |
| inp[0, 3] = (base_pressure - 5e6) / 20e6 # Pressure |
| inp[0, 4] = (porosity - 0.01) / 0.14 # Porosity |
| inp[0, 5] = (depth - 800) / 1700 # Depth |
|
|
| # Run inference |
| with torch.no_grad(): |
| output = model(inp) # (1, 10, 32, 32) normalized [0,1] |
| |
| # Denormalize to physical units |
| temperature = output[0, :5] * 350.0 # °C, shape (5, 32, 32) |
| pressure = output[0, 5:] * 50e6 # Pa, shape (5, 32, 32) |
| |
| print(f"Year 20 avg temperature: {temperature[4].mean():.1f}°C") |
| print(f"Year 20 avg pressure: {pressure[4].mean()/1e6:.2f} MPa") |
| ``` |
| |
| ## Validation Results |
| |
| ### Per-Timestep Accuracy |
| |
| | Year | Temp RMSE (°C) | Pressure RMSE (MPa) | |
| |------|---------------|---------------------| |
| | 4 | 4.025 | 0.356 | |
| | 8 | 3.262 | 0.364 | |
| | 12 | 3.333 | 0.326 | |
| | 16 | 3.005 | 0.332 | |
| | 20 | 2.811 | 0.390 | |
| |
| ### Benchmark Comparison |
| |
| | Method | Temp Accuracy | Inference | Hardware | |
| |--------|--------------|-----------|----------| |
| | TOUGH2 (full physics) | Exact | 15-30 min | CPU | |
| | USGS Brady Hot Springs ML | < 3.68% relative | 0.9 s | GPU | |
| | Fourier Neural Operator | ~1-3% error | ~10 ms | GPU required | |
| | **GeoForce v1.1** | **3.31°C RMSE (1.3%)** | **3.2 ms** | **CPU only** | |
| |
| ## Version History |
| |
| | Version | Params | Temp R² | Pressure R² | Status | |
| |---------|--------|---------|-------------|--------| |
| | v1.0 | 56,938 | 0.975 | -0.003 | Retired (pressure prediction failed) | |
| | **v1.1** | **57,802** | **0.994** | **0.997** | **Current — all thresholds pass** | |
| |
| The v1.0 failure was caused by compressing three physical parameters (pressure, porosity, depth) into a single input channel. Each parameter now has its own dedicated channel in v1.1. Full failure analysis is documented in the [technical report](technical-report.md). |
| |
| ## Limitations |
| |
| 1. **2D grid only** (32×32 horizontal slice) — no vertical flow or gravity convection |
| 2. **Single-phase** liquid water — no steam-water phase transitions |
| 3. **Homogeneous permeability** per scenario — no fracture networks |
| 4. **Synthetic training data** — not yet validated against real field measurements |
| 5. **Max error of 47.3°C** in extreme edge cases near training distribution boundaries |
| |
| ## Use Cases |
| |
| - **Uncertainty quantification**: Run 10,000+ Monte Carlo samples in < 1 minute |
| - **Well placement optimization**: Evaluate hundreds of configurations in seconds |
| - **Screening studies**: Rapidly assess reservoir viability before committing to full simulation |
| - **Education**: Demonstrate reservoir physics concepts with instant feedback |
| |
| ## Files |
| |
| | File | Description | |
| |------|-------------| |
| | `geoforce_cnn_v1.1.pt` | PyTorch checkpoint (244 KB) | |
| | `reservoir_cnn.py` | Model architecture (ReservoirCNN class) | |
| | `validation_metrics_v1.1.json` | Full validation results on 100 test samples | |
| | `hyperparams.yaml` | Training configuration | |
| | `training_log.json` | Complete training history (402 epochs) | |
| | `technical-report.md` | Full technical report with methodology and failure analysis | |
|
|
| ## Citation |
|
|
| ```bibtex |
| @software{geoforce2026, |
| title={GeoForce: Physics-Informed CNN Surrogate for Geothermal Reservoir Prediction}, |
| author={Riupassa, Robi Dany}, |
| year={2026}, |
| publisher={ForceX AI}, |
| url={https://huggingface.co/ForceX-AI/GeoForce-CNN-v1.1}, |
| version={1.1.0} |
| } |
| ``` |
|
|
| ## About ForceX AI |
|
|
| ForceX AI builds AI-powered tools for the energy industry — geothermal, renewable, oil & gas, and nuclear. Our models are trained on real simulation data and validated against industry benchmarks. |
|
|
| - Platform: [platform.forcex-ai.com](https://platform.forcex-ai.com) |
| - Website: [forcex-ai.com](https://forcex-ai.com) |
|
|