wellpaths: Generation of wells using general curves

Functionality for defining wells following curvilinear trajectories. By defining each well trajectory as a series of points, this module can combine multiple trajectories and determine which cells are penetrated by the well path. The trajectories can be interpolated using any of Matlab’s built-in routines (splines, piecewise linear functions, etc).

Contents

UTILS

Files
combineWellPaths - Combine multiple simple paths into a full tree findWellPathCells - Convert well path to the intersected cells getWellFromPath - Convert well path to MRST well. makeSingleWellpath - Create well path from points (and optional connectivity and active flag) plotWellPath - Plot a well path refineSpline - Refine a curve to higher resolution using spline interpolation
combineWellPaths(wellpaths)

Combine multiple simple paths into a full tree

Synopsis:

wellpath = combineWellPaths({wp1, wp2, wp3});

Description:

Given multiple simple well paths this function assembles a single well tree from the inputs. For this to work we assume that:

  • The paths are ordered by depth in the tree. This is not the

vertical depth, but rather that a path will always be connected to one of the curves preceding it in the list. - Paths (aside from the first one) always start with a point that also exists in one of the preceding paths. This is used to connect the paths.

Parameters:wellpaths – Cell array of simple well paths to be assembled together. A simple well path is assumed to contain a single list of points (i.e. it will only represent a line segment).
Returns:wellpath – Composite wellpath made from the simple wellpaths. The topology will be tree-like in nature.
findWellPathCells(G, wellpath, varargin)

Convert well path to the intersected cells

Synopsis:

cells = findWellPaths(G, wellpath);

Description:

By creating a triangulation and mapping perforations to the closest cells, this routine realizes the continuous well path into discrete cells, making it possible to build simulation wells from it.

Parameters:
  • G – The grid structure we want to realize the wells on.
  • wellpath – Well path. See “makeSingleWellpath” for spec.
Keyword Arguments:
 
  • interpType – The type of interpolation used to extend the curve between points. Supports the same types as MATLAB builtin interp1. Default: Spline.
  • triangulation – The triangulation (typically from delaunayTriangulation) used to determine proximity in the grid.
  • refinement – Refinement number used to further refine the well curve before computing which cells it intersect. Default: 100.
Returns:
  • cells – The list of cells the well intersects.
  • segment – Segment indicator for each cell, indicating which wellpath segment produced that specific completion. If multiple choices are possible, the segment which comes first in wellpath.points is used.
  • ptsind – Point indicator, indicating which point in the segment was the closest to a given cell.
  • DT – Triangulation used to produce the results.
getWellFromPath(W0, G, rock, wellpath, varargin)

Convert well path to MRST well.

Synopsis:

W = getWellFromPath(W, G, rock, wellpath);

Description:

This routine converts a well path (representing curves and points) into a well (represented by cells and connectivity).

Parameters:
  • W0 – Well array to be extended with the new well.
  • G – The grid the well is to be placed in.
  • rock – Rock structure which defines permeability and porosity.
  • wellpath
    Well path as procued by makeSingleWellPath or
    combineWellPaths.

    OPTIONAL PARAMETERS:

    This function calls addWell. Any keyword arguments are passed onto addWell.
Returns:

W – Updated wells

Note

Currently no special effort is made to ensure correct well indices for the well.

SEE ALSO:

makeSingleWellpath(pts, conn, active)

Create well path from points (and optional connectivity and active flag)

Synopsis:

wellpath = makeSingleWellpath(pts);
wellpath = makeSingleWellpath(pts, conn)
wellpath = makeSingleWellpath(pts, conn, active)

Description:

Create a well path from lists of points. The resulting structure will be a single struct with fields:

  • points:

    Cell array, each consisting of N x Dim arrays of n points. Each entry contains the points for one segment that are assumed to be connected as a line according to their ordering. The first entry is assumed to be closest to the starting point of the well (closest here means along the well bore).

  • connectivity:

    Array of size M x 2 where M is the number of entries in the .points cell array. If entry number 5 of connectivity is [2 7] it means that segment number 5 is connected to segment 2, at point number 7 of segment 2’s internal ordering. In effect, segment 5 branches off from segment 2 from the coordinate .points{2}(7, :).

  • active:

    Cell array, containing active flags for the segments between points. If points{i} contains N x dim entries, active{i} should contain (N-1) x 1 entries, indicating if the subsegments are active.

    If points is of size 6 x 3 and active looks like this: [1; % 1 -> 2

    1; % 2 -> 3 0; % 3 -> 4 1; % 4 -> 5 1] % 5 -> 6

    it means that the part of the segment will be disabled from point 3 to point 4.

Parameters:pts
Maps directly to points (see above). If pts is a numeric
array, it will be interpreted as a cell array with a single entry.

connectivity - Maps directly into connectivity.

active - Maps directly into active.

Returns:wellpath – Wellpath suitable for plotting or producing well completions.
plotWellPath(wellpaths, varargin)

Plot a well path

Synopsis:

plotWellPath(wellpath)
h = plotWellPath(wellpath, 'color', 'r')

Description:

Plots a given well path, using colors and showing control points along the curve.

Parameters:

wellpath – Well path to be plotted. See makeSingleWellpath.

Keyword Arguments:
 
  • interpType – Interpolation type used. Same possible values as for MATLAB builtin interp1. Default: Spline.
  • LineWidth – Line width of curve used to draw wellpath segments.
  • MarkerColor – Used to colorize the control points.
  • Color – Color of the line segments themselves.
  • Refinement – The path is refined using interpolation to produce nice curves. Entering a positive number here will refine the curve by a number of points. Interpreted as a multiplicative factor.
Returns:

h – Two-column array of handles. The first column contains handles for the line segments and the second for the control point markers.

refineSpline(points, n_refine, interpType)

Refine a curve to higher resolution using spline interpolation

Synopsis:

pts = refineSpline(points, 10, 'spline');
pts = refineSpline(points, 5);

Description:

Refine a given curve given as a array of points into

Parameters:
  • points – A npts x dim array of points giving the curve to be refined. Implicitly assumed to be ordered.
  • n_refine – The refinement factor. If the original entries in points contained n points, the output will have n_refine*n total points.
  • interpType – Type of interpolation. Supports the same values as the fourth argument to MATLABs interp1 function. If omitted, it defaults to ‘spline’.
Returns:
  • pts – Refined points.
  • v – Parametrization of the new points. Continuous values from 1 to npts indicating how far along interpolated values are on the original trajectory.

Examples

Define a model

Generated from wellTrajectoryExample.m

mrstModule add ad-core ad-blackoil diagnostics wellpaths
km = kilo*meter;
pdims = [5, 4, 0.01]'*km;

% dims = [50, 40, 10];
dims = [25, 20, 5];

G = cartGrid(dims, pdims);
G = computeGeometry(G);

Define a forked well

We define four curves, with some common points to combine them into a single well path.

p1 = [0.25, 0.5, 0.9, 1.5]'*km;

n = numel(p1);

z = [.25, 0.5, 0.75, .80]'*pdims(3);

a = [p1(1)*ones(n, 1), p1];
b = [p1,               p1(1)*ones(n, 1)];
c = [p1,               p1];

origin = [0, 0, 0; a(1, :), z(1)];

% First foru well paths.
wellpath0 = makeSingleWellpath(origin);
wellpath1 = makeSingleWellpath([a, z]);
wellpath2 = makeSingleWellpath([b, z]);
wellpath3 = makeSingleWellpath([c, z]);
% Combine into single well path
wellpath_fork = combineWellPaths({wellpath0, wellpath1, wellpath2, wellpath3});

% Plotting
clf;
plotWellPath(wellpath_fork);
_images/wellTrajectoryExample_01.png

Make a comb-like well

x = [3, 3.5, 4, 4.5]'*km;
y = [3.5, 3, 2.5, 2]'*km;

y0 = [3.75*km; y];
x0 = x(end)*ones(numel(y)+1, 1);

dz = 1/numel(y);
z0 = (0:dz:1)'*pdims(3);

wp0 = [x0, y0, z0];

n0 = numel(x0);

wellpaths = cell(5, 1);

wellpaths{1} = makeSingleWellpath(wp0);

for i = 1:4
    n = numel(x);
    wp = [x, repmat(y(i), n, 1), repmat(z0(i+1), n, 1)];
    wellpaths{i+1} = makeSingleWellpath(wp(end:-1:1, :));
end

wellpath_comb = combineWellPaths(wellpaths);

Determine the cells

[cells_fork, segInd_fork, ~, ~, DT] = findWellPathCells(G, wellpath_fork);
[cells_comb, segInd_comb] = findWellPathCells(G, wellpath_comb, 'triangulation', DT);

Plot the well trajectories

clf;
plotWellPath(wellpath_comb);
plotWellPath(wellpath_fork);

plotGrid(G, 'facec', 'none', 'edgea', .1)
view(40, 56)
_images/wellTrajectoryExample_02.png

Plot wells individually + realized cell perforations

close all
for i = 1:2
    if i == 1
        wp = wellpath_comb;
        si = segInd_comb;
        c = cells_comb;
        v = [30, 12];
    else
        wp = wellpath_fork;
        si = segInd_fork;
        c = cells_fork;
        v = [160, 40];
    end

    figure;
    subplot(2, 1, 1)
    plotWellPath(wp);
    view(v);
    title('Well trajectory with segment indicators')
    axis tight off

    subplot(2, 1, 2)
    plotCellData(G, si, c)
    view(v);
    title('Cells with segment indicators')
    axis tight off
end
_images/wellTrajectoryExample_03.png
_images/wellTrajectoryExample_04.png

Set up actual simulation wells from the well paths

Initial reservoir state

initSat = [.1, .9];
state = initResSol(G, 200*barsa, initSat);
% Rock
rock = makeRock(G, 300*milli*darcy, 0.5);

time = 10*year;
rate = .25*sum(poreVolume(G, rock))/time;

segInd = cell(2, 1);
W = [];
[W, segInd{1}]  = getWellFromPath(W, G, rock, wellpath_fork, ...
    'comp_i', [1 0], 'val', 300*barsa, 'type', 'bhp', 'sign', -1, 'Name', 'Producer');
[W, segInd{2}] = getWellFromPath(W, G, rock, wellpath_comb,...
    'comp_i', [1 0], 'val', rate, 'type', 'rate', 'sign', 1, 'Name', 'Injector');

Set up simulation model

mrstModule add ad-core ad-blackoil ad-props

fluid = initSimpleADIFluid('rho', [1000, 700, 100]*kilogram/meter^3, ...
                           'mu', [1, 10 1]*centi*poise);

model = TwoPhaseOilWaterModel(G, rock, fluid);

model.extraStateOutput = true;
model.extraWellSolOutput = true;

Build a schedule

n = 50;
dt = time/n;
timesteps = repmat(dt, n, 1);
schedule = simpleSchedule(timesteps, 'W', W);

[ws, states] = simulateScheduleAD(state, model, schedule);
Solving timestep 01/50:          -> 73 Days
Solving timestep 02/50: 73 Days  -> 146 Days
Solving timestep 03/50: 146 Days -> 219 Days
Solving timestep 04/50: 219 Days -> 292 Days
Solving timestep 05/50: 292 Days -> 1 Year
Solving timestep 06/50: 1 Year   -> 1 Year, 73 Days
Solving timestep 07/50: 1 Year, 73 Days -> 1 Year, 146 Days
Solving timestep 08/50: 1 Year, 146 Days -> 1 Year, 219 Days
...

Plot well curves + reservoir properties

mrstModule add mrst-gui
figure;
plotToolbar(G, states);
axis tight off
view(40, 56);
T = cumsum(schedule.step.val);

plotWellSols(ws, T)
_images/wellTrajectoryExample_05.png
_images/wellTrajectoryExample_06.png

Plot the saturation front

close all
plotWellPath(wellpath_comb);
plotWellPath(wellpath_fork);

plotGrid(G, 'facec', 'none', 'edgea', .2);
view(-60, 60);
h = nan;
for i = 1:numel(states)
    if ishandle(h); delete(h); end

    s = states{i}.s(:, 1);
    h = plotCellData(G, s, s > 0.2, 'edgea', .2);
    title(formatTimeRange(T(i)));
    pause(0.25)
end
_images/wellTrajectoryExample_07.png

Apply some flow diagnostics…

diagstate = states{end};
[state_split, Wc] = expandWellCompletions(diagstate, W, segInd);
D  = computeTOFandTracer(state_split, G, rock, 'wells', Wc);
WP = computeWellPairs(state_split, G, rock, Wc, D);

Plot results

figure; plotToolbar(G, D)
plotWellPath(wellpath_comb);
plotWellPath(wellpath_fork);
_images/wellTrajectoryExample_08.png