Download tools/predict_solver.py from robiriu/geoforce: direct link, hf CLI and curl.
- Browser
- Download file 3.8 kB
-
https://huggingface.co/spaces/robiriu/geoforce/resolve/main/tools/predict_solver.py
- Command line
-
hf download hf://spaces/robiriu/geoforce/tools/predict_solver.py
-
curl -L -o predict_solver.py https://huggingface.co/spaces/robiriu/geoforce/resolve/main/tools/predict_solver.py
3.8 kB
| """Unified `predict(scenario)` wrapper around GeoForce-Solver. | |
| The agent calls this with a plain dict describing the reservoir + wells + | |
| time stepping, and gets back a common schema: | |
| { | |
| "temperature": np.ndarray, # (nx, ny) deg C, final time step | |
| "pressure": np.ndarray, # (nx, ny) Pa, final time step | |
| "grid": { | |
| "nx": int, "ny": int, | |
| "dx": float, "dy": float, # meters | |
| "extent_x": [x_min, x_max], # meters (cell edges) | |
| "extent_y": [y_min, y_max], | |
| }, | |
| "engine": "solver", | |
| "elapsed_seconds": float, | |
| } | |
| The scenario dict may omit most keys; sensible defaults match the Indonesian | |
| geothermal scenarios we demo. | |
| """ | |
| from __future__ import annotations | |
| import time | |
| from typing import Any | |
| import numpy as np | |
| from solver.coupled import run_coupled_transient | |
| from solver.grid import Grid | |
| from solver.properties import WaterProperties | |
| from solver.wells import WellSpec | |
| DEFAULTS: dict[str, Any] = { | |
| "nx": 40, | |
| "ny": 20, | |
| "dx": 10.0, | |
| "dy": 10.0, | |
| "porosity": 0.12, | |
| "permeability": 5.0e-13, | |
| "rho_rock": 2500.0, | |
| "cp_rock": 1000.0, | |
| "lam_rock": 2.5, | |
| "T_initial": 200.0, | |
| "P_initial": 1.5e7, | |
| "dt": 5.0e5, | |
| "n_steps": 60, | |
| "wells": [], | |
| } | |
| def _coerce_wells(raw: list[dict[str, Any]]) -> list[WellSpec]: | |
| out: list[WellSpec] = [] | |
| for w in raw: | |
| out.append( | |
| WellSpec( | |
| i=int(w["i"]), | |
| j=int(w["j"]), | |
| mass_rate=float(w["mass_rate"]), | |
| injection_temperature=( | |
| float(w["injection_temperature"]) | |
| if w.get("injection_temperature") is not None | |
| else None | |
| ), | |
| ) | |
| ) | |
| return out | |
| def predict(scenario: dict[str, Any]) -> dict[str, Any]: | |
| """Run the coupled GeoForce solver on a scenario dict. | |
| Args: | |
| scenario: dict with any subset of the DEFAULTS keys overridden. | |
| Special keys: | |
| - ``wells``: list of {i, j, mass_rate, injection_temperature?}. | |
| Returns: | |
| Dict with final-time T/P fields + grid metadata + ``engine``. | |
| """ | |
| cfg = {**DEFAULTS, **scenario} | |
| grid = Grid(nx=int(cfg["nx"]), ny=int(cfg["ny"]), dx=float(cfg["dx"]), dy=float(cfg["dy"])) | |
| props = WaterProperties.at_reference(t_c=float(cfg["T_initial"]), p_pa=float(cfg["P_initial"])) | |
| phi = float(cfg["porosity"]) | |
| rho_cp_eff = (1.0 - phi) * float(cfg["rho_rock"]) * float(cfg["cp_rock"]) + phi * props.rho * props.cp | |
| lam_eff = (1.0 - phi) * float(cfg["lam_rock"]) + phi * 0.68 # water lam ~0.68 W/m/K | |
| t0 = np.full(grid.shape, float(cfg["T_initial"]), dtype=np.float64) | |
| p0 = np.full(grid.shape, float(cfg["P_initial"]), dtype=np.float64) | |
| wells = _coerce_wells(list(cfg["wells"])) | |
| start = time.perf_counter() | |
| p_hist, t_hist = run_coupled_transient( | |
| grid=grid, | |
| p_initial=p0, | |
| t_initial=t0, | |
| permeability=float(cfg["permeability"]), | |
| porosity=phi, | |
| total_compressibility=props.c_f + 1.0e-9, | |
| mu=props.mu, | |
| rho=props.rho, | |
| cp_water=props.cp, | |
| thermal_conductivity=lam_eff, | |
| volumetric_heat_capacity=rho_cp_eff, | |
| dt=float(cfg["dt"]), | |
| n_steps=int(cfg["n_steps"]), | |
| wells=wells, | |
| ) | |
| elapsed = time.perf_counter() - start | |
| return { | |
| "temperature": t_hist[-1], | |
| "pressure": p_hist[-1], | |
| "grid": { | |
| "nx": grid.nx, | |
| "ny": grid.ny, | |
| "dx": grid.dx, | |
| "dy": grid.dy, | |
| "extent_x": [0.0, grid.nx * grid.dx], | |
| "extent_y": [0.0, grid.ny * grid.dy], | |
| }, | |
| "engine": "solver", | |
| "elapsed_seconds": elapsed, | |
| } | |