Skip to content

Model coarsening

Running a model at full resolution can be computationally expensive. In many cases, it is possible to coarsen the model to reduce the computational cost. This example demonstrates how to coarsen a model using JutulDarcy.jl. The example uses the Egg model, which is a small oil-water model with heterogeneous permeability. The model is coarsened using different methods and partition sizes, and the results are compared to the fine-scale model. The example demonstrates how to coarsen a model and simulate it using JutulDarcy.jl. The example also demonstrates how to compare the results of the coarse-scale model to the fine-scale model.

The example is intended to show the workflow of coarsening a model, and represents a starting point for more advanced techniques like upscaling, coarse-model calibration and history matching. The model is therefore intentionally simple and very coarse for quick simulations, and not necessarily accurate model responses.

julia
using Jutul, JutulDarcy, HYPRE
using GLMakie
using GeoEnergyIO
data_dir = GeoEnergyIO.test_input_file_path("EGG")
data_pth = joinpath(data_dir, "EGG.DATA")
fine_case = setup_case_from_data_file(data_pth);

Simulate the base case

We simulate the fine case to get a reference solution to compare against. We also extract the mesh and reservoir for plotting.

julia
fine_model = fine_case.model
fine_reservoir = reservoir_domain(fine_model)
fine_mesh = physical_representation(fine_reservoir)
ws, states = simulate_reservoir(fine_case, info_level = 1);
Jutul: Simulating 9 years, 44.69 weeks as 135 report steps
Step   1/135: Solving start to 1 day, Δt = 1 day
Step   2/135: Solving 1 day to 5 days, Δt = 4 days
Step   3/135: Solving 5 days to 1 week, 3 days, Δt = 5 days
Step   4/135: Solving 1 week, 3 days to 2 weeks, 6 days, Δt = 1 week, 3 days
Step   5/135: Solving 2 weeks, 6 days to 4 weeks, 2 days, Δt = 1 week, 3 days
Step   6/135: Solving 4 weeks, 2 days to 5 weeks, 5 days, Δt = 1 week, 3 days
Step   7/135: Solving 5 weeks, 5 days to 7 weeks, 1 day, Δt = 1 week, 3 days
Step   8/135: Solving 7 weeks, 1 day to 8 weeks, 4 days, Δt = 1 week, 3 days
Step   9/135: Solving 8 weeks, 4 days to 10 weeks, Δt = 1 week, 3 days
Step  10/135: Solving 10 weeks to 11 weeks, 3 days, Δt = 1 week, 3 days
Step  11/135: Solving 11 weeks, 3 days to 12 weeks, 6 days, Δt = 1 week, 3 days
Step  12/135: Solving 12 weeks, 6 days to 15 weeks, Δt = 2 weeks, 1 day
Step  13/135: Solving 15 weeks to 17 weeks, 1 day, Δt = 2 weeks, 1 day
Step  14/135: Solving 17 weeks, 1 day to 19 weeks, 2 days, Δt = 2 weeks, 1 day
Step  15/135: Solving 19 weeks, 2 days to 21 weeks, 3 days, Δt = 2 weeks, 1 day
Step  16/135: Solving 21 weeks, 3 days to 23 weeks, 4 days, Δt = 2 weeks, 1 day
Step  17/135: Solving 23 weeks, 4 days to 25 weeks, 5 days, Δt = 2 weeks, 1 day
Step  18/135: Solving 25 weeks, 5 days to 27 weeks, 6 days, Δt = 2 weeks, 1 day
Step  19/135: Solving 27 weeks, 6 days to 30 weeks, Δt = 2 weeks, 1 day
Step  20/135: Solving 30 weeks to 32 weeks, 1 day, Δt = 2 weeks, 1 day
Step  21/135: Solving 32 weeks, 1 day to 34 weeks, 2 days, Δt = 2 weeks, 1 day
Step  22/135: Solving 34 weeks, 2 days to 36 weeks, 3 days, Δt = 2 weeks, 1 day
Step  23/135: Solving 36 weeks, 3 days to 38 weeks, 4 days, Δt = 2 weeks, 1 day
Step  24/135: Solving 38 weeks, 4 days to 40 weeks, 5 days, Δt = 2 weeks, 1 day
Step  25/135: Solving 40 weeks, 5 days to 42 weeks, 6 days, Δt = 2 weeks, 1 day
Step  26/135: Solving 42 weeks, 6 days to 47 weeks, 1 day, Δt = 4 weeks, 2 days
Step  27/135: Solving 47 weeks, 1 day to 51 weeks, 3 days, Δt = 4 weeks, 2 days
Step  28/135: Solving 51 weeks, 3 days to 1 year, 3.537 weeks, Δt = 4 weeks, 2 days
Step  29/135: Solving 1 year, 3.537 weeks to 1 year, 7.822 weeks, Δt = 4 weeks, 2 days
Step  30/135: Solving 1 year, 7.822 weeks to 1 year, 12.11 weeks, Δt = 4 weeks, 2 days
Step  31/135: Solving 1 year, 12.11 weeks to 1 year, 16.39 weeks, Δt = 4 weeks, 2 days
Step  32/135: Solving 1 year, 16.39 weeks to 1 year, 20.68 weeks, Δt = 4 weeks, 2 days
Step  33/135: Solving 1 year, 20.68 weeks to 1 year, 24.97 weeks, Δt = 4 weeks, 2 days
Step  34/135: Solving 1 year, 24.97 weeks to 1 year, 29.25 weeks, Δt = 4 weeks, 2 days
Step  35/135: Solving 1 year, 29.25 weeks to 1 year, 33.54 weeks, Δt = 4 weeks, 2 days
Step  36/135: Solving 1 year, 33.54 weeks to 1 year, 37.82 weeks, Δt = 4 weeks, 2 days
Step  37/135: Solving 1 year, 37.82 weeks to 1 year, 42.11 weeks, Δt = 4 weeks, 2 days
Step  38/135: Solving 1 year, 42.11 weeks to 1 year, 46.39 weeks, Δt = 4 weeks, 2 days
Step  39/135: Solving 1 year, 46.39 weeks to 1 year, 50.68 weeks, Δt = 4 weeks, 2 days
Step  40/135: Solving 1 year, 50.68 weeks to 2 years, 2.788 weeks, Δt = 4 weeks, 2 days
Step  41/135: Solving 2 years, 2.788 weeks to 2 years, 7.074 weeks, Δt = 4 weeks, 2 days
Step  42/135: Solving 2 years, 7.074 weeks to 2 years, 11.36 weeks, Δt = 4 weeks, 2 days
Step  43/135: Solving 2 years, 11.36 weeks to 2 years, 15.64 weeks, Δt = 4 weeks, 2 days
Step  44/135: Solving 2 years, 15.64 weeks to 2 years, 19.93 weeks, Δt = 4 weeks, 2 days
Step  45/135: Solving 2 years, 19.93 weeks to 2 years, 24.22 weeks, Δt = 4 weeks, 2 days
Step  46/135: Solving 2 years, 24.22 weeks to 2 years, 28.5 weeks, Δt = 4 weeks, 2 days
Step  47/135: Solving 2 years, 28.5 weeks to 2 years, 32.79 weeks, Δt = 4 weeks, 2 days
Step  48/135: Solving 2 years, 32.79 weeks to 2 years, 37.07 weeks, Δt = 4 weeks, 2 days
Step  49/135: Solving 2 years, 37.07 weeks to 2 years, 41.36 weeks, Δt = 4 weeks, 2 days
Step  50/135: Solving 2 years, 41.36 weeks to 2 years, 45.65 weeks, Δt = 4 weeks, 2 days
Step  51/135: Solving 2 years, 45.65 weeks to 2 years, 49.93 weeks, Δt = 4 weeks, 2 days
Step  52/135: Solving 2 years, 49.93 weeks to 3 years, 2.039 weeks, Δt = 4 weeks, 2 days
Step  53/135: Solving 3 years, 2.039 weeks to 3 years, 6.325 weeks, Δt = 4 weeks, 2 days
Step  54/135: Solving 3 years, 6.325 weeks to 3 years, 10.61 weeks, Δt = 4 weeks, 2 days
Step  55/135: Solving 3 years, 10.61 weeks to 3 years, 14.9 weeks, Δt = 4 weeks, 2 days
Step  56/135: Solving 3 years, 14.9 weeks to 3 years, 19.18 weeks, Δt = 4 weeks, 2 days
Step  57/135: Solving 3 years, 19.18 weeks to 3 years, 23.47 weeks, Δt = 4 weeks, 2 days
Step  58/135: Solving 3 years, 23.47 weeks to 3 years, 27.75 weeks, Δt = 4 weeks, 2 days
Step  59/135: Solving 3 years, 27.75 weeks to 3 years, 32.04 weeks, Δt = 4 weeks, 2 days
Step  60/135: Solving 3 years, 32.04 weeks to 3 years, 36.32 weeks, Δt = 4 weeks, 2 days
Step  61/135: Solving 3 years, 36.32 weeks to 3 years, 40.61 weeks, Δt = 4 weeks, 2 days
Step  62/135: Solving 3 years, 40.61 weeks to 3 years, 44.9 weeks, Δt = 4 weeks, 2 days
Step  63/135: Solving 3 years, 44.9 weeks to 3 years, 49.18 weeks, Δt = 4 weeks, 2 days
Step  64/135: Solving 3 years, 49.18 weeks to 4 years, 1.29 week, Δt = 4 weeks, 2 days
Step  65/135: Solving 4 years, 1.29 week to 4 years, 5.576 weeks, Δt = 4 weeks, 2 days
Step  66/135: Solving 4 years, 5.576 weeks to 4 years, 9.861 weeks, Δt = 4 weeks, 2 days
Step  67/135: Solving 4 years, 9.861 weeks to 4 years, 14.15 weeks, Δt = 4 weeks, 2 days
Step  68/135: Solving 4 years, 14.15 weeks to 4 years, 18.43 weeks, Δt = 4 weeks, 2 days
Step  69/135: Solving 4 years, 18.43 weeks to 4 years, 22.72 weeks, Δt = 4 weeks, 2 days
Step  70/135: Solving 4 years, 22.72 weeks to 4 years, 27 weeks, Δt = 4 weeks, 2 days
Step  71/135: Solving 4 years, 27 weeks to 4 years, 31.29 weeks, Δt = 4 weeks, 2 days
Step  72/135: Solving 4 years, 31.29 weeks to 4 years, 35.58 weeks, Δt = 4 weeks, 2 days
Step  73/135: Solving 4 years, 35.58 weeks to 4 years, 39.86 weeks, Δt = 4 weeks, 2 days
Step  74/135: Solving 4 years, 39.86 weeks to 4 years, 44.15 weeks, Δt = 4 weeks, 2 days
Step  75/135: Solving 4 years, 44.15 weeks to 4 years, 48.43 weeks, Δt = 4 weeks, 2 days
Step  76/135: Solving 4 years, 48.43 weeks to 5 years, 3.788 days, Δt = 4 weeks, 2 days
Step  77/135: Solving 5 years, 3.788 days to 5 years, 4.827 weeks, Δt = 4 weeks, 2 days
Step  78/135: Solving 5 years, 4.827 weeks to 5 years, 9.113 weeks, Δt = 4 weeks, 2 days
Step  79/135: Solving 5 years, 9.113 weeks to 5 years, 13.4 weeks, Δt = 4 weeks, 2 days
Step  80/135: Solving 5 years, 13.4 weeks to 5 years, 17.68 weeks, Δt = 4 weeks, 2 days
Step  81/135: Solving 5 years, 17.68 weeks to 5 years, 21.97 weeks, Δt = 4 weeks, 2 days
Step  82/135: Solving 5 years, 21.97 weeks to 5 years, 26.26 weeks, Δt = 4 weeks, 2 days
Step  83/135: Solving 5 years, 26.26 weeks to 5 years, 30.54 weeks, Δt = 4 weeks, 2 days
Step  84/135: Solving 5 years, 30.54 weeks to 5 years, 34.83 weeks, Δt = 4 weeks, 2 days
Step  85/135: Solving 5 years, 34.83 weeks to 5 years, 39.11 weeks, Δt = 4 weeks, 2 days
Step  86/135: Solving 5 years, 39.11 weeks to 5 years, 43.4 weeks, Δt = 4 weeks, 2 days
Step  87/135: Solving 5 years, 43.4 weeks to 5 years, 47.68 weeks, Δt = 4 weeks, 2 days
Step  88/135: Solving 5 years, 47.68 weeks to 5 years, 51.97 weeks, Δt = 4 weeks, 2 days
Step  89/135: Solving 5 years, 51.97 weeks to 6 years, 4.078 weeks, Δt = 4 weeks, 2 days
Step  90/135: Solving 6 years, 4.078 weeks to 6 years, 8.364 weeks, Δt = 4 weeks, 2 days
Step  91/135: Solving 6 years, 8.364 weeks to 6 years, 12.65 weeks, Δt = 4 weeks, 2 days
Step  92/135: Solving 6 years, 12.65 weeks to 6 years, 16.93 weeks, Δt = 4 weeks, 2 days
Step  93/135: Solving 6 years, 16.93 weeks to 6 years, 21.22 weeks, Δt = 4 weeks, 2 days
Step  94/135: Solving 6 years, 21.22 weeks to 6 years, 25.51 weeks, Δt = 4 weeks, 2 days
Step  95/135: Solving 6 years, 25.51 weeks to 6 years, 29.79 weeks, Δt = 4 weeks, 2 days
Step  96/135: Solving 6 years, 29.79 weeks to 6 years, 34.08 weeks, Δt = 4 weeks, 2 days
Step  97/135: Solving 6 years, 34.08 weeks to 6 years, 38.36 weeks, Δt = 4 weeks, 2 days
Step  98/135: Solving 6 years, 38.36 weeks to 6 years, 42.65 weeks, Δt = 4 weeks, 2 days
Step  99/135: Solving 6 years, 42.65 weeks to 6 years, 46.94 weeks, Δt = 4 weeks, 2 days
Step 100/135: Solving 6 years, 46.94 weeks to 6 years, 51.22 weeks, Δt = 4 weeks, 2 days
Step 101/135: Solving 6 years, 51.22 weeks to 7 years, 3.329 weeks, Δt = 4 weeks, 2 days
Step 102/135: Solving 7 years, 3.329 weeks to 7 years, 7.615 weeks, Δt = 4 weeks, 2 days
Step 103/135: Solving 7 years, 7.615 weeks to 7 years, 11.9 weeks, Δt = 4 weeks, 2 days
Step 104/135: Solving 7 years, 11.9 weeks to 7 years, 16.19 weeks, Δt = 4 weeks, 2 days
Step 105/135: Solving 7 years, 16.19 weeks to 7 years, 20.47 weeks, Δt = 4 weeks, 2 days
Step 106/135: Solving 7 years, 20.47 weeks to 7 years, 24.76 weeks, Δt = 4 weeks, 2 days
Step 107/135: Solving 7 years, 24.76 weeks to 7 years, 29.04 weeks, Δt = 4 weeks, 2 days
Step 108/135: Solving 7 years, 29.04 weeks to 7 years, 33.33 weeks, Δt = 4 weeks, 2 days
Step 109/135: Solving 7 years, 33.33 weeks to 7 years, 37.61 weeks, Δt = 4 weeks, 2 days
Step 110/135: Solving 7 years, 37.61 weeks to 7 years, 41.9 weeks, Δt = 4 weeks, 2 days
Step 111/135: Solving 7 years, 41.9 weeks to 7 years, 46.19 weeks, Δt = 4 weeks, 2 days
Step 112/135: Solving 7 years, 46.19 weeks to 7 years, 50.47 weeks, Δt = 4 weeks, 2 days
Step 113/135: Solving 7 years, 50.47 weeks to 8 years, 2.58 weeks, Δt = 4 weeks, 2 days
Step 114/135: Solving 8 years, 2.58 weeks to 8 years, 6.866 weeks, Δt = 4 weeks, 2 days
Step 115/135: Solving 8 years, 6.866 weeks to 8 years, 11.15 weeks, Δt = 4 weeks, 2 days
Step 116/135: Solving 8 years, 11.15 weeks to 8 years, 15.44 weeks, Δt = 4 weeks, 2 days
Step 117/135: Solving 8 years, 15.44 weeks to 8 years, 19.72 weeks, Δt = 4 weeks, 2 days
Step 118/135: Solving 8 years, 19.72 weeks to 8 years, 24.01 weeks, Δt = 4 weeks, 2 days
Step 119/135: Solving 8 years, 24.01 weeks to 8 years, 28.29 weeks, Δt = 4 weeks, 2 days
Step 120/135: Solving 8 years, 28.29 weeks to 8 years, 32.58 weeks, Δt = 4 weeks, 2 days
Step 121/135: Solving 8 years, 32.58 weeks to 8 years, 36.87 weeks, Δt = 4 weeks, 2 days
Step 122/135: Solving 8 years, 36.87 weeks to 8 years, 41.15 weeks, Δt = 4 weeks, 2 days
Step 123/135: Solving 8 years, 41.15 weeks to 8 years, 45.44 weeks, Δt = 4 weeks, 2 days
Step 124/135: Solving 8 years, 45.44 weeks to 8 years, 49.72 weeks, Δt = 4 weeks, 2 days
Step 125/135: Solving 8 years, 49.72 weeks to 9 years, 1.831 week, Δt = 4 weeks, 2 days
Step 126/135: Solving 9 years, 1.831 week to 9 years, 6.117 weeks, Δt = 4 weeks, 2 days
Step 127/135: Solving 9 years, 6.117 weeks to 9 years, 10.4 weeks, Δt = 4 weeks, 2 days
Step 128/135: Solving 9 years, 10.4 weeks to 9 years, 14.69 weeks, Δt = 4 weeks, 2 days
Step 129/135: Solving 9 years, 14.69 weeks to 9 years, 18.97 weeks, Δt = 4 weeks, 2 days
Step 130/135: Solving 9 years, 18.97 weeks to 9 years, 23.26 weeks, Δt = 4 weeks, 2 days
Step 131/135: Solving 9 years, 23.26 weeks to 9 years, 27.55 weeks, Δt = 4 weeks, 2 days
Step 132/135: Solving 9 years, 27.55 weeks to 9 years, 31.83 weeks, Δt = 4 weeks, 2 days
Step 133/135: Solving 9 years, 31.83 weeks to 9 years, 36.12 weeks, Δt = 4 weeks, 2 days
Step 134/135: Solving 9 years, 36.12 weeks to 9 years, 40.4 weeks, Δt = 4 weeks, 2 days
Step 135/135: Solving 9 years, 40.4 weeks to 9 years, 44.69 weeks, Δt = 4 weeks, 2 days
Simulation complete: Completed 135 report steps in 29 seconds, 449 milliseconds, 221.5 microseconds and 543 iterations.
╭────────────────┬───────────┬───────────────┬──────────╮
│ Iteration type │  Avg/step │  Avg/ministep │    Total │
│                │ 135 steps │ 162 ministeps │ (wasted) │
├────────────────┼───────────┼───────────────┼──────────┤
│ Newton         │   4.02222 │       3.35185 │  543 (0) │
│ Linearization  │   5.22222 │       4.35185 │  705 (0) │
│ Linear solver  │   18.5556 │        15.463 │ 2505 (0) │
│ Precond apply  │   37.1111 │       30.9259 │ 5010 (0) │
╰────────────────┴───────────┴───────────────┴──────────╯
╭───────────────┬─────────┬────────────┬─────────╮
│ Timing type   │    Each │   Relative │   Total │
│               │      ms │ Percentage │       s │
├───────────────┼─────────┼────────────┼─────────┤
│ Properties    │  1.8374 │     3.39 % │  0.9977 │
│ Equations     │  2.4192 │     5.79 % │  1.7055 │
│ Assembly      │  2.3860 │     5.71 % │  1.6821 │
│ Linear solve  │  3.0713 │     5.66 % │  1.6677 │
│ Linear setup  │ 22.4250 │    41.35 % │ 12.1768 │
│ Precond apply │  1.7604 │    29.95 % │  8.8197 │
│ Update        │  0.4438 │     0.82 % │  0.2410 │
│ Convergence   │  0.2866 │     0.69 % │  0.2021 │
│ Input/Output  │  0.7204 │     0.40 % │  0.1167 │
│ Other         │  3.3885 │     6.25 % │  1.8400 │
├───────────────┼─────────┼────────────┼─────────┤
│ Total         │ 54.2343 │   100.00 % │ 29.4492 │
╰───────────────┴─────────┴────────────┴─────────╯

Coarsen the model and plot partition

We coarsen the model using a partition size of 20x20x2 and the IJK method where the underlying structure of the mesh is used to subdivide the blocks. This function automatically handles inactive cells and disconnected blocks and can therefore also work on more complex models.

We pass a triplet of integers to specify the partition size. This will give an essentially structured partition. Later on, we we will look at graph partitioners.

julia
coarse_case = coarsen_reservoir_case(fine_case, (20, 20, 2), method = :ijk)
coarse_model = coarse_case.model
coarse_reservoir = reservoir_domain(coarse_case)
coarse_mesh = physical_representation(coarse_reservoir)

p = coarse_mesh.partition

fig, = plot_cell_data(fine_mesh, p, colormap = :lipariS)
fig

Compare fine-scale and coarse-scale permeability

The fine-scale and coarse-scale permeability fields are compared visually. The coarsening uses a static upscaling, where the permeability is harmonically averaged per direction when coarsening. This is a simple method that can be effective enough for many cases.

The fine-scale permeability is shown on the left, and the coarse-scale is shown on the right, with the same color axis.

julia
K_f = fine_reservoir[:permeability][1, :]
K_c = coarse_reservoir[:permeability][1, :]

kcaxis = extrema(K_f)

fig = Figure(size = (1200, 500))
axf = Axis3(fig[1, 1], title = "Fine scale permeability", zreversed = true)
plot_cell_data!(axf, fine_mesh, K_f, colorrange = kcaxis, colormap = :turbo)

axc = Axis3(fig[1, 2], title = "Coarse scale permeability", zreversed = true)
plt = plot_cell_data!(axc, coarse_mesh, K_c, colorrange = kcaxis, colormap = :turbo)
Colorbar(fig[1, 3], plt)
fig

Simulate the coarse-scale model

The coarse scale model can be simulated just as the fine-scale model was, but the runtime should be significantly reduced down to around a second.

julia
@time ws_c, states_c = simulate_reservoir(coarse_case, info_level = -1);
  1.191235 seconds (4.02 M allocations: 318.147 MiB, 6.96% gc time)

Plot and compare the coarse-scale and fine-scale solutions

We plot the pressure field for the fine-scale and coarse-scale models. The model has little pressure variation, but we see that there are substantial differences between our very coarse model and the original fine-scale.

julia
using Statistics
wells = JutulDarcy.get_model_wells(fine_model)

p_c = states_c[end][:Pressure]
p_f = states[end][:Pressure]

caxis = extrema([extrema(p_c)..., extrema(p_f)...])

fig = Figure(size = (1200, 500))
axf = Axis3(fig[1, 1], title = "Fine scale", zreversed = true)
plot_cell_data!(axf, fine_mesh, p_f, colorrange = caxis, colormap = :turbo)

for (k, w) in wells
    plot_well!(axf, fine_mesh, w, fontsize = 0)
end

axc = Axis3(fig[1, 2], title = "Coarse scale", zreversed = true)
plt = plot_cell_data!(axc, coarse_mesh, p_c, colorrange = caxis, colormap = :turbo)

for (k, w) in wells
    plot_well!(axc, fine_mesh, w, fontsize = 0)
end
Colorbar(fig[1, 3], plt)
fig

Plot and compare the saturation fields

We observe that the saturation fields are quite different between the coarse-scale and fine scale, with the coarse-scale model showing a more uniform saturation field as the leading shock is smeared away.

julia
s_c = states_c[end][:Saturations][1, :]
s_f = states[end][:Saturations][1, :]

scaxis = extrema([extrema(s_c)..., extrema(s_f)...])

fig = Figure(size = (1200, 500))
axf = Axis3(fig[1, 1], title = "Fine scale", zreversed = true)
plot_cell_data!(axf, fine_mesh, s_f, colorrange = scaxis, colormap = :turbo)

for (k, w) in wells
    plot_well!(axf, fine_mesh, w, fontsize = 0)
end

axc = Axis3(fig[1, 2], title = "Coarse scale", zreversed = true)
plt = plot_cell_data!(axc, coarse_mesh, s_c, colorrange = scaxis, colormap = :turbo)

for (k, w) in wells
    plot_well!(axc, fine_mesh, w, fontsize = 0)
end
Colorbar(fig[1, 3], plt)
fig

Plot the average field scale pressure evolution

julia
fig = Figure()
axf_p = Axis(fig[1, 1], ylabel = "Avg. pressure / bar")
lines!(axf_p, map(x -> mean(x[:Pressure])/1e5, states), label = "Fine")
lines!(axf_p, map(x -> mean(x[:Pressure])/1e5, states_c), label = "Coarse")
axislegend()
fig

Plot the wells interactively

We can plot the well results in the interactive viewer using the comparison feature that allows multiple results to be superimposed in the same figure.

julia
plot_well_results([ws, ws_c], names = ["Fine", "Coarse"], field = :orat, accumulated = true)

Plot field scale measurables over time interactively

The field-scale quantities match fairly well between the coarse-scale and fine-scale models. There is always a trade-off between accuracy and quality in numerical simulations, where the goal is to find the right balance between accuracy in quantities of interest and computational cost.

julia
fine_m = reservoir_measurables(fine_case, ws, states)
coarse_m = reservoir_measurables(coarse_case, ws_c, states_c)
m = copy(fine_m)
for (k, v) in pairs(coarse_m)
    if k != :time
        m[Symbol("coarse_$k")] = v
    end
end

plot_reservoir_measurables(m, left = :fopr, right = :coarse_fopr, accumulated = true)

Compare different partitioning methods

We have only so far tested a single partitioning method. We can quickly generate a few other coarse models using different partitioning methods and coarsening values. We highlight that we can also use the centroids instead of the IJK indices to partition, for when the mesh may not have a structured background mesh. In addition, we can call different graph partitioners by passing the desired number of blocks. Here, we call a simple METIS-based transmissibility coarsening, but the code contains options to use other weights and partitioners.

julia
partition_variants = [
    (:centroids, (3, 3, 2)),
    (:ijk, (5, 5, 1)),
    (:metis, 10),
    (:metis, 50)
]

fig = Figure(size = (1200, 600))
layout = GridLayout()
fig[1, 1] = layout
rowwidth = Int(floor(length(partition_variants)/2))
for (no, variant) in enumerate(partition_variants)
    if no > rowwidth
        row = 2
        pix = no - rowwidth
    else
        row = 1
        pix = no
    end
    cmethod, cdim = variant
    variant_case = coarsen_reservoir_case(fine_case, cdim, method = cmethod)
    r = reservoir_domain(variant_case)
    m = physical_representation(r)
    p = m.partition

    ax = Axis3(fig, title = "$cmethod - $cdim", azimuth = 0.3, elevation = 1.0, zreversed = true)
    plot_cell_data!(ax, fine_mesh, p, colormap = :lipariS)
    layout[row, 2*(pix-1) + 1] = ax

    _, variant_states = simulate_reservoir(variant_case, info_level = -1)
    pres = variant_states[end][:Pressure]
    axp = Axis3(fig, title = "Pressure", azimuth = 0.3, elevation = 1.0, zreversed = true)
    for (k, w) in wells
        plot_well!(axp, fine_mesh, w, fontsize = 0)
    end
    plot_cell_data!(axp, m, pres, colorrange = caxis, colormap = :turbo)

    layout[row, 2*(pix-1) + 2] = axp
end
fig

Example on GitHub

If you would like to run this example yourself, it can be downloaded from the JutulDarcy.jl GitHub repository as a script, or as a Jupyter Notebook


This page was generated using Literate.jl.