--- 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.
| 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** |
## 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)