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
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.
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.
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.
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.
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.
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.
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.
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.8sBring your simulator
Reservoir models, CFD or seismic imaging: talk to an engineer about running your scientific codes on GPUs in your own cloud.