Live demo · Reservoir simulation

Simulate reservoir waterfloods on Chalk GPUs

This demo shows how to run GEOS on a Chalk GPU to simulate water injection through the SPE10 reservoir benchmark. Change the injection rate to try it, then explore the code to see how it works.

Follow injected water through two rock layers

Inject water into the center of a reservoir and watch it push oil toward four corner wells. Replay the recorded run, then change an input to run GEOS on Chalk yourself.

Try this experiment · expected results

  1. 1Compare saturation with permeability

    Pause or scrub the recording, then switch between Water saturation and Permeability at the same step.

    Expected: Water follows channels where rock lets fluid pass more easily. Compare the two layers to see how the rock changes its path.

  2. 2Read the production result

    Follow oil and water production over time, then change one input for a live run.

    Expected: The recorded run recovers about 47% of the oil after 1,500 simulated days. Use the same duration when comparing your run.

Recorded run

Water saturation is the share of pore space filled with water. Follow the water from the center injector toward the corner wells; the production chart below measures the oil recovered.

Loading the recorded run…
—
Cumulative production Oil Water
Oil produced—
Oil recovered—of oil in place
Water share of output—
Avg pressure—
Re-run it on the GPU
Water injection
Producer pressure
Permeability
Simulated time

Built on Chalk

GEOS solves the two-phase flow equations. The Python application writes the input deck and parses the output; Chalk runs its CUDA image, provides the endpoint and checks readiness.

  • Run an existing CUDA image

    Chalk runs the prebuilt GEOS image on an NVIDIA L4. The application launches the unmodified C++ solver for each simulation.

  • Specify the runtime in Python

    The scaling group requests an L4, four CPUs and 16 GiB of memory. Chalk schedules the replica with those resources.

  • Check the solver before serving

    The application runs a short warm-up simulation before its status endpoint responds. Chalk uses that endpoint to decide when the replica is ready.

  • Stream simulation output

    The application parses GEOS report files into pressure, saturation and production results. Chalk exposes the API that streams those updates.

Performance details

This demo shows GEOS running on Chalk. In these measurements, a GPU takes longer than multiple CPU cores to finish the same simulation.

Simulation runtime in seconds · lower is faster

Cells are pieces of the reservoir model; days are time inside the simulation. Each group below is a separate workload. Compare devices within a group.

26,400 cells, 1,500 days (the recorded run)
One NVIDIA L4, on Chalk102 s
One NVIDIA H10089 s
1 CPU core116 s
4 CPU cores (MPI)35 s
8 CPU cores (MPI)22 s
422,400 cells (each cell split 4 × 4), 300 days
One NVIDIA H1001,286 s
4 CPU cores (MPI)979 s

The default deck uses the same GEOS commit and recovers about 47% of the oil by day 1,500 across these devices. On this case one GPU runs about as fast as one CPU core. GEOS's GPU solver uses GPU-friendly multigrid settings that need two to six times more Krylov iterations per Newton step than its CPU solver, and on grids this small that cancels out the faster iterations. The demo runs on an L4 to show a CUDA build of GEOS served from Chalk, not to claim a speedup.

The recorded run is the same stream the button produces, saved from the deployed API. Production is a mass balance over GEOS's cell outputs (the producers are held at a fixed bottom-hole pressure), reported at surface conditions. The SPE10 data is the two-layer extract that ships with GEOS. Times are wall-clock for the whole run, including GEOS start-up and writing output.

Deploy your own

Run it on your own

You need uv, Chalk credentials, an L4-capable environment, Docker, and a registry that your environment can pull from. Build GEOS and its dependencies into a CUDA image, push it, and set GEOS_IMAGE before deploying.

GEOS is C++ with MPI, RAJA and hypre; it has no Python wheel. The snippets show the deployment pattern around the unmodified solver. Adapt the input deck and output parser for your case, and use a build compatible with your GPU.

GEOS-DEV/GEOS on GitHub
import json, httpx

params = {
    "injection_bbl_per_day": 400,    # water injector at the centre
    "producer_bhp_mpa": 27.58,       # four corner producers, 4,000 psi
    "perm_multiplier": 1.0,          # scale the SPE10 permeability field
    "days": 1500, "frames": 40,
}
with httpx.stream("POST", f"{URL}/api/run", json=params, timeout=None) as r:
    for line in r.iter_lines():
        msg = json.loads(line)
        if msg["type"] == "frame":
            print(f"day {msg['t_days']:6.0f}  oil {msg['oil_bbl']:9,.0f} bbl"
                  f"  recovery {msg['recovery']:.1%}  wall {msg['wall_s']:.1f}s")

# day    375  oil   110,046 bbl  recovery 29.4%  wall 60.2s
# day    750  oil   143,556 bbl  recovery 38.4%  wall 76.8s
# day   1125  oil   162,917 bbl  recovery 43.5%  wall 90.7s
# day   1500  oil   176,611 bbl  recovery 47.2%  wall 101.8s

Bring your simulator

Reservoir models, CFD or seismic imaging: talk to an engineer about running your scientific codes on GPUs in your own cloud.