Sie sind auf Seite 1von 17

Part 1: Geological Models and Grids

2. Modelling Reservoir Rocks


2.1. Formation of sedimentary rocks

2.2. Creation of crude oil and natural gas

2.3. Multiscale modelling of permeable rocks

2.3.1. Macroscopic models

2.3.2. Representative elementary volumes

2.3.3. Microscopic models: the pore scale

2.3.4. Mesoscopic models

2.4. Modelling rocks properties

A geological model is a conceptual, three-dimensional representation of a reservoir, whose main


purpose is therefore to provide the distribution of petrophysical parameters, besides giving location and
geometry of the reservoir. The rock body itself is modelled in terms of a volumetric grid, in which the
layered structure of sedimentary beds and the geometry of faults and largescale fractures in the
reservoir are represented by the geometry and topology of the grid cells. The size of a cell in a typical
geological grid-model is in the range of 0.1-1 meters in the vertical direction and 10-50 meters in the
horizontal direction. The petrophysical properties of the rock are represented as constant values inside
each grid cell (porosity and permeability) or as values attached to cell faces (fault multipliers, fracture
apertures, etc.)

2.4.1. Porosity

For non-rigid rocks, the porosity is usually modelled as a pressure-dependent parameter. That is, one
says that the rock is compressible, having a rock compressibility defined by

1 𝑑∅ 𝑑(ln ∅)
𝑐𝑟 = = (2.1)
∅ 𝑑𝑝 𝑑𝑝

Where 𝑝 is the overall reservoir pressure. For a rock with constant compressibility (2.1) can be
integrated to give

∅(𝑝) = ∅0 𝑒 𝑐𝑟 (𝑝−𝑝0 ) (2.2)

And for simplified models, it is common to use a linearization so that:

∅ = ∅0 [1 + 𝑐𝑟 (𝑝 − 𝑝0 )] (2.4)
Because the dimension of the pores is very small compared to any interesting scale for reservoir
simulation, one normally assumes that porosity is a piecewise continuous spatial function. However,
ongoing research aims to understand better the relation between flow models on pore scale and on
reservoir scale.

2.4.2. Permeability

The precise definition of the (absolute, specific, or intrinsic) permeability 𝐾 is as the proportionality
factor between the flow rate and an applied pressure or potential gradient ∇Ф,

𝐾
𝑢
⃗ =− ∇Ф (2.4)
𝜇

Where 𝜇 is the fluid viscosity and 𝑢


⃗ is the superficial velocity, i.e., the flow rate divided by the cross-
sectional area perpendicular to the flow. This should not be confused with the interstitial velocity 𝑣 =

𝑢
, i.e., the rate at which an actual fluid particle moves through the medium.

In (2.4), we assumed that the permeability 𝐾 is a scalar quantity. However, the permeability will
generally be a full tensor,

𝐾𝑥𝑥 𝐾𝑥𝑦 𝐾𝑥𝑧


K= [𝐾𝑦𝑥 𝐾𝑦𝑦 𝐾𝑦𝑧 ] (2.5)
𝐾𝑧𝑥 𝐾𝑧𝑦 𝐾𝑧𝑧

If the permeability can be represented by a scalar function 𝐾(𝑥), we say that the permeability is
isotropic as opposed to the anisotropic case where we need a full tensor K(𝑥). To model a physical
system, the anisotropic permeability tensor must be symmetric.

Since the porous medium is formed by deposition of sediments over thousands of years, there is often a
significant different between permeability in the vertical and lateral directions, but no difference
between the permeabilities in the two lateral directions. The permeability is obviously also a function of
porosity. Assuming a laminar flow (low Reynolds numbers) in a set of capillary tubes, one can derive
the Carman-Kozeny relation, which relates permeability to porosity ∅, but also shows that the
permeability depends on local rock texture described by tortuosity 𝜏 and specific surface area 𝐴𝑣 .

1 ∅3
𝐾= (2.6)
8 𝜏 𝐴𝑣2 (1 − ∅)2

Permeability is generally heterogeneous in space because of different sorting of particles, degree of


cementation (filling of clay), and transitions between different rock formations. Indeed, the
permeability may vary rapidly over several orders of magnitude, local variations in the range 1 mD to
10 D are not unusual in a typical field.
Production of fluids may also change the permeability. When temperature and pressure is changed,
microfractures may open and significantly change the permeability.

2.4.3. Other parameters

Not all rocks in a reservoir zone are reservoir rocks. To account for the fact that some portion of a cell
may consist of impermeable shale, it is common to introduce the so-called “net-to-gross” (N/G)
property, which is a number in the range 0 to 1 that represents the fraction of reservoir rock in the cell.
To get the effective porosity of a given cell, one must multiply the porosity and N/G value of the cell. A
zero value means that the corresponding cell only contains shale and such cells are by convention
typically not included in the active model.

Faults can either act as conduits for fluid flow in subsurface reservoirs or create flow barriers and
introduce compartmentalization that severely affects fluid distribution and/or reduces recovery. To
model the hydraulic properties of faults, it is common to introduce so-called multipliers that alter the
ability to transmit fluid between two neighboring cells.

2.5. Property modelling in MRST

All flow and transport solvers in MRST assume that the rock parameters are represented as fields in a
structure. Our naming convention is that this structure is called rock, but this is not a requirement. The
fields for porosity and permeability, however, must be called poro and perm, respectively. The
porosity field rock.poro is a vector with one value for each active cell in the corresponding grid model.
The permeability field rock.perm can either contain a single column for an isotropic permeability, two
or three columns for a diagonal permeability (in two and three spatial dimensions, respectively, or six
columns for a symmetric, full-tensor permeability). In the latter case, cell number 𝑖 has the permeability
tensor

𝐾1 (𝑖) 𝐾2 (𝑖) 𝐾3 (𝑖)


𝐾 (𝑖) 𝐾2 (𝑖)
Ki= [ 1 ] Ki= [𝐾2 (𝑖) 𝐾4 (𝑖) 𝐾5 (𝑖)]
𝐾2 (𝑖) 𝐾1 (𝑖)
𝐾3 (𝑖) 𝐾5 (𝑖) 𝐾6 (𝑖)

where 𝐾𝑗 (𝑖) is the entry in column 𝑗 and row 𝑖 of rock.perm. Full-tensor, non-symmetric
permeabilities are currently not supported in MRST. In addition to porosity and permeability, MRST
supports a field called ntg that represents the net-to-gross ratio and consists of either a scalar or a single
column with one value per active cell.

2.5.1. Homogeneous models

Homogeneous models are very simple to specify, as illustrated by a simple example. We consider a
square 10 x 10 grid model with a uniform porosity of 0.2 and isotropic permeability equal of 200 mD:

G=cartGrid([10 10 10]);
rock=makeRock(G, 200*milli*darcy, 0.2);
plotGrid(G); view(3)
Because MRST works in SI units, it is important to convert from the field units ‘darcy’ to the SI unit
‘meters2’. Here, we did this by multiplying with milli and darcy, which are two functions that return the
corresponding conversion factors. Alternatively, we could use the conversion function
convertFrom(200, milli*darcy). Homogeneous, anisotropic permeability can be specified in the same
way:

G=cartGrid([10 10 10]);
rock=makeRock(G, [100 100 100].*milli*darcy, 0.2);
plotGrid(G); view(3)

cartGrid: construct 2d or 3d Cartesian grid in physical space


G=cartGrid(celldim);
G=cartGrid(celldim, physdim);

% Make a 10-by-5-by-2 grid on the unit cube


nx=10; ny=5; nz=2;
G=cartGrid([nx, ny, nz], [1, 1, 1]);

% Plot the grid in 3D-view


f=plotGrid(G); view(3);

plotGrid: plots exterior grid faces to current axes


plotGrid(G)
plotGrid(G, 'pn1', pv1, …)
plotGrid(G, cells)
plotGrid(G, cells, 'pn1', pv1, …)
h=plotGrid(…)

G=cartGrid([10, 10, 5]);


% 1) Plot grid with yellow colour on faces (default):
figure, plotGrid(G, 'EdgeAlpha', 0.1); view(3)
% 2) Plot grid with no colour on faces (transparent faces):
figure, plotGrid(G, 'FaceColor', 'none'); view(3)

makeRock: create rock structure from given permeability and porosity values
rock=makeRock(G, perm, poro)
rock=makeRock(G, perm, poro, ‘pn1’, pv1, …)

G=computeGeometry(cartGrid([10, 20, 30], [1, 1, 1]));


r1=makeRock(G, 100*milli*darcy, 0.3);
r2=makeRock(G, [100, 100, 10]*milli*darcy, 0.3);
K=logNormLayers(G.cartDims, repmat([400, 0.1, 20], [1, 2]));
phi=gaussianField(G.cartDims, [0.2, 0.4]);
ntg=rand([G.cells.num, 1]);
r3=makeRock(G, convertFrom(K(:), milli*darcy), phi(:),'ntg ', ntg);
plotCellData(G, poreVolume(G, r3)), view(3), axis tight
2.5.2. Random and lognormal models

Given the difficulty of measuring rock properties, it is common to use geostatistical method to make
realizations of porosity and permeability. MRST contains two very simplified methods for generating
geostatistical realizations. For more realistic geostatistics, the reader should use GSLIB (Deutsch and
Journel 1998)or a commercial geomodelling software.

In our first example, we will generate the porosity ∅ as a Gaussian field. To get a crude approximation
to the permeability-porosity relationship, we assume that our medium is made up of uniform spherical
6
grains of diameter 𝑑𝑝 = 10 μm, for which the specific surface aea is 𝐴𝑣 = 𝑑 . Using the Carman-
𝑝
Kozeny relation (equation 2.6), we can then calculate the isotropic permeability 𝐾 from

1 ∅3 𝑑𝑝2
𝐾=
72 𝜏 (1 − ∅)2

Where we further assume that 𝜏 = 0.81. As a simple approximation to a Gaussian field, we generate a
field of independent normally distributed variables and convolve it with a Gaussian kernel.

G=cartGrid([50 20]);
p=gaussianField(G.cartDims, [0.2 0.4], [11 3], 2.5);
K=p.^3.*(1e-5)^2./(0.81*72*(1-p).^2);
rock=makeRock(G, K(:), p(:));
plotCellData(G, rock.poro, 'EdgeColor', 'none');
colorbar('horiz'); axis equal tight;

gaussianField: compute realization of lognormal, isotropic permeability field


p=gaussianField(N)
p=gaussianField(N, vals)
p=gaussianField(N, vals, size)
p=gaussianField(N, vals, size, std)

plotCellData: plot exterior grid faces, coloured by given data, to current axes
plotCellData(G, data)
plotCellData(G, data, ‘pn1’, pv1, …)
plotCellData(G, data, cells
plotCellData(G, data, cells, ‘pn1’, pv1, …)
h=plotCellData(…)

G=cartGrid([50 20]);
p=gaussianField(G.cartDims, [0.2 0.4], [11 3], 2.5);
K=p.^3.*(1e-5)^2./(0.81*72*(1-p).^2);
rock=makeRock(G, K(:), p(:));
plotCellData(G, convertTo(rock.perm, milli*darcy));
colorbar('horiz'); axis equal tight; view(3);
convertTo: convert physical quantity from SI to equivalent given unit
q=convertTo(q, unit)

press=convertTo(press, barsa()) % Pascal -> bar


rate=convertTo(rate, stb()/day()) % m^3/s -> stb/day
mu=convertTo(mu, Pa()*sec()) % Pa s -> Pa s (identity)
press2=convertTo(convertFrom(press, atm()), psia()) % Atm -> psia

G=processGRDECL(simpleGrdecl([50 30 10], 0.12));


K=logNormLayers(G.cartDims, [100 400 50 350], 'indices', [1 2 5 7 11]);
plotCellData(G, log10(K), 'EdgeColor', 'k'); view (45, 30);
axis tight off, set(gca, 'DataAspect', [0.5 1 1]);
h=colorbar('horiz'); ticks=25*2.^[0:5];
set(h, 'XTick', log10(ticks), 'XTickLabel', ticks);

Here, we have specified four geological layers of different thickness. From top to bottom (stratigraphic
grids are often numbered from the top and downward), the first layer is one cell thick and has a mean
permeability value of 100 mD, the second layer is three cells thick and has mean permeability of 400
mD, and the fourth layer is four cells thick and has mean value 50 mD, and the fourth layer is four cells
thick and has mean value 350 mD. To specify this, we have used an indirection map. That is, if Km is
the n-vector of mean permeabilities and L is the (n+1)-vector of indices, the value Km(i) is assigned to
vertical layers number L(i) to L(i+1)-1. The resulting permeability is shown in Figure 2.11.

Figure 2.11: A stratigraphic grid with a single fault and four geological layers, each with a lognormal permeability
distribution
2.5.3. 10th SPE Comparative Solution Project: Model 2

The SPE developed a series of benchmarks that can be used to independently compare methods and
simulators. The model is structurally simple but is highly heterogeneous which means that streamline
methods will be particularly efficient for this model (www.spe.org/web/csp)

MRST supplies a module called spe10 that downloads, reorganizes, and stores the data set in a file for
later use. The module also contains routines that extract (subsets of) the petrophysical data and setup
simulation models and appropriate data structure representing grids and wells. Alternatively, the data
set can be downloaded using mrstDatasetGUI.

Because the geometry is a simple Catesian grid, we can use standard MATLAB functionality to
visualize the heterogeneity in the permeability and porosity (full details can be found in the script
rocks/showSPE10.m)

% load SPE 10 data set


mrstModule add spe10;
rock=SPE10_rock(); p=rock.poro; K=rock.perm;

% show p
slice (reshape(p, 60, 220, 85), [1 220], 60, [1, 85]);
shading flat, axis equal off, set(gca, 'zdir', 'reverse'), box on;
colorbar('horiz');

% show Kx
slice(reshape(log10(K(:, 1)), 60, 220, 85), [1 220], 60, [1 85]);
shading flat, axis equal off, set(gca, 'zdir', 'reverse'), box on;
h=colorbar('horiz');
set(h, 'XTickLabel', 10.^[get(h, 'XTick')]);
set(h, 'YTick', mean(get(h, 'YLim')), 'YTickLabel', 'mD'); (Still doesn’t work)

Figure 2: Rock properties for the SPE 10 model (porosity)


Figure 3: Rock properties for the SPE 10 model (horizontal permeability, which is shown using a logarithmic
color scale)

mrstModule: Query or modify list of activated add-on MRST modules

slice: slice Volumetric slice plot

% To visualize the function x*exp(-x^2-y^2-z^2) over the range -2<x<2, -2<y<2, -2<z<2

[x, y, z]=meshgrid(-2:.2:2, -2:.25:2, -2:.16:2);


v=x.*exp(-x.^2-y.^2-z.^2);
slice(x, y, z, v, [-1.2 .8 2], 2, [-2 -.2])

reshape: reshape array

2.5.4. The Johansen Formation

2.5.5. SAIGUP: shallow-marine reservoirs

3. Grids in subsurface modelling


3.1. Structured grids

1. Structured grids
1.a) Rectilinear grids
2D grid that covers the domain [-1, 1] x [0, 1] and is graded toward 𝑥 = 0 and 𝑦 = 1
dx = 1-0.5*cos((-1:0.1:1)*pi);
x = -1.15+0.1*cumsum(dx);
y = 0:0.05:1;
G=tensorGrid(x, sqrt(y));
plotGrid(G); axis([-1.05 1.05 -0.05 1.05]);
1.b) Curvilinear grids
Rough grid by perturbing all internal nodes of a regular Cartesian grid
nx=6; ny=12;
G=cartGrid([nx, ny]);
subplot(1,2,1); plotGrid(G);
c=G.nodes.coords;
I=any(c==0,2) | any(c(:,1)==nx,2) | any(c(:,2)==ny,2);
G.nodes.coords(~I,:)=c(~I,:)+0.6*rand(sum(~I),2)-0.3;
subplot(1,2,2); plotGrid(G);
Use of the routine twister to perturb the internal vertices
G=cartGrid([30, 20]);
G.nodes.coords = twister(G.nodes.coords);
G=computeGeometry(G);
plotCellData(G, G.cells.volumes, 'EdgeColor', 'k'), colorbar

1.c) Fictitious domain

MRST has support for fictitious domain methods through the function removeCells, which we will
demonstrate in the next example, where we create a regular Cartesian grid that fills the volume of an
ellipsoid:

x = linspace(-2,2,21);
G = tensorGrid(x,x,x);
subplot(1,2,1); plotGrid(G);view(3); axis equal
subplot(1,2,2); plotGrid(G,'FaceColor','none');
G = computeGeometry(G);
c = G.cells.centroids;
r = c(:,1).^2 + 0.25*c(:,2).^2+0.25*c(:,3).^2;
G = removeCells(G, r>1);
plotGrid(G); view(-70,70); axis equal;

2. Unstructured grids

a) Delaunay tessellation

We use routines from MatLab’s polyfun toolbox to triangulate a rectangular mesh and convert the
result using the MRST routine triangleGrid

[x,y] = meshgrid(1:10,1:8);
t = delaunay(x(:),y(:));
G = triangleGrid([x(:) y(:)],t);
plot(x(:),y (:), 'o' , 'MarkerSize',8);
plotGrid(G,'FaceColor', 'none');

load seamount;
plot(x(:),y (:), 'o' );
G = triangleGrid([x(:) y(:)]);
plotGrid(G,'FaceColor',[.8 .8 .8 ]); axis off;

N=7; M=5; K=3;


[x,y,z] = ndgrid(0:N,0:M,0:K);
x(2:N,2:M,:) = x(2:N,2:M,:) + 0.3*randn(N-1,M-1,K+1);
y(2:N,2:M,:) = y(2:N,2:M,:) + 0.3*randn(N-1,M-1,K+1);
G = tetrahedralGrid([x(:) y(:) z(:)]);
plotGrid(G, 'FaceColor',[0.8 0.8 0.8 ]); view(-40,60); axis tight off

b) Voronoi diagrams

[x,y] = meshgrid([0:4]*2*cos(pi/6),0:3);
x = [x(:); x(:)+cos(pi/6)];
y = [y(:); y(:)+sin(pi/6)];
G = triangleGrid([x,y]);
plotGrid(pebi(G), 'FaceColor','none'); axis equal off

% Valid for MatLab only


load seamount
V = pebi(triangleGrid([x y]));
plotGrid(V,'FaceColor',[.8 .8 .8 ]); axis off;

Stratigraphic grids

a) Corner-point grids

grdecl=simpleGrdecl([4,2,3], .12, 'flat', true);


[X,Y,Z] = buildCornerPtPillars(grdecl,'Scale',true);
[x,y,z] = buildCornerPtNodes(grdecl);
plot3(X',Y', Z', 'k');
set(gca,'zdir','reverse'), view(35,35), axis off, zoom(1.2);
hold on; I=[3 8 13];
hpr = plot3(X(I,:)',Y(I ,:)', Z(I ,:)', 'r' , 'LineWidth',2);
hpt = plot3(x(:),y (:), z (:), 'o' ); hold off;
3.1.1. Regular Cartesian grids

3.1.2. Rectilinear grids

3.1.3. Curvilinear grids

3.1.4. Fictitious domains

3.2. Unstructured grids

3.2.1. Delaunay tessellation

3.2.2. Voronoi diagrams

3.2.3. Other types of tessellations

3.2.4. Using an external mesh generator

3.3. Stratigraphic grids

3.3.1. Corner-point grids

3.3.2. 2.5D unstructured grids

3.4. Grid structure in MRST

3.5. Examples of more complex grids

Part 2: Single-Phase Flow


4. Mathematical Models and Basic Discretization
4.1. Fundamental concept: Darcy’s law
In modern differential notation, Darcy’s law for a single-phase fluid reads:

K
𝑣=− (∇𝑝 − 𝑔 𝜌 ∇𝑧) (4.2.)
𝜇

4.2. General flow equations for single-phase flow


From the fundamental law of mass conservation, we know that the accumulation of mass inside this
volume must equal the net flux over the boundaries,

𝜕
∫ ∅ 𝜌 𝑑𝑥 + ∫ 𝜌 𝑣 ∙ 𝑛⃗ 𝑑𝑠 = ∫ 𝜌 𝑞 𝑑𝑥 (4.3.)
𝜕𝑥
𝛺 𝜕𝛺 𝛺
Where 𝜌 is the density of the fluid, ∅ is the rock porosity, 𝑣 is the macroscopic Darcy velocity, 𝑛⃗
denotes the normal at the boundary 𝜕𝛺 of the computational domain 𝛺, and 𝑞 denotes fluid sources and
sinks, i.e., outflow and inflow of fluids per volume at certain locations.

4.3. Auxiliary conditions and equations

4.3.1. Boundary and initial conditions


In reservoir simulation one is often interested in describing closed flow systems that have no fluid flow
across its external boundaries. This is a natural assumption when studying full reservoirs that have
trapped and contained petroleum fluids for millions of years. Mathematically, no-flow conditions
across external boundaries are modeled by specifying homogeneous Neumann conditions.

𝑣 ∙ 𝑛⃗ = 0 for 𝑥 ∈ 𝜕𝛺 (4.23)

4.3.2. Injection and production wells

4.3.3. Field lines and time-of-flight

4.3.4. Tracers and volume partitions

4.4. Basic finite-volume discretization

4.4.1. Two-point flux-approximation

4.4.2. Discrete div and grad operators

4.4.3. Time-of-flight and tracer

5. Incompressible solvers

6. Single-Phase Flow and Rapid Prototyping

Part 3: Multi-Phase Flow


7. Mathematical Models for Multiphase Flow

10. Solvers for Incompressible Immiscible Flow

Part 4: Reservoir Engineering Workflows


12. Flow diagnostics
% Exercise: Unstructured Triangular Grid
% This script will plot a triangular grid and number cells, faces, and nodes.
% Moreover, the script lists the contents of selected fields of the grid structure to file.
clf;
p = sortrows([0.0, 1.0, 0.9, 0.1, 0.6, 0.3, 0.75; 0.0, 0.0, 0.8, 0.9, 0.2, 0.6, 0.45]');
G = triangleGrid(p);
G = computeGeometry(G);

newplot;
plotGrid(G,'FaceColor',[0.95 0.95 0.95]); axis off;
hold on;

% centroids
text(G.cells.centroids(:,1)-0.01, G.cells.centroids(:,2)-0.01, num2str((1:G.cells.num)'),
'FontSize',20);
plot(G.cells.centroids(:,1), G.cells.centroids(:,2), 'ok', 'MarkerSize', 24);

% faces
text(G.faces.centroids(:,1)-0.02, G.faces.centroids(:,2)-0.01,
num2str((1:G.faces.num)'),'FontSize',16);

% vertices
text(G.nodes.coords(:,1)-0.01, G.nodes.coords(:,2)-0.01,
num2str((1:G.nodes.num)'),'FontSize',18);
plot(G.nodes.coords(:,1), G.nodes.coords(:,2), 'sk', 'MarkerSize', 24);
hold off;

% Output content of cells.faces, faces.nodes, and faces.neighbors to file


fp = fopen('G-unstructured.txt', 'w');
faces =[rldecode(1 : G.cells.num,diff(G.cells.facePos), 2).' G.cells.faces];
fprintf(fp, 'cells.faces =\n');
fprintf(fp, '%3d %3d\n', faces');
nodes = [ rldecode(1:G.faces.num,diff(G.faces.nodePos), 2).' G.faces.nodes];
fprintf(fp, '\n\nfaces.nodes =\n');
fprintf(fp, '%3d %3d\n', nodes');
fprintf(fp, '\n\nfaces.neighbors =\n');
fprintf(fp, '%3d %3d\n', G.faces.neighbors');
fclose(fp);
Two-Phase MsFV Example

% A simple two phase problem solved using the Multiscale Finite Volume method
% Add coarsegrid msfvm Module for Incompressible Flow
mrstModule add coarsegrid msfvm
% Add MRST Module for Incompressible Flow
mrstModule add incomp

% Construct simple 2D Cartesian test case


nx=5; ny=50;
Nx=5; Ny=5;
G=cartGrid([nx ny]);
G=computeGeometry(G);

% Plot each time step


doPlot=true;
p=partitionUI(G, [Nx, Ny]);
CG=generateCoarseGrid(G, p);

% Generate dual grid


DG=partitionUIdual(CG, [Nx, Ny]);

% Visualize
clf;
plotDual(G, DG) % Revisar con archivo de internet

% Uniform permeability
rock.perm=repmat(100*milli*darcy, [G.cells.num, 1]);
rock.poro=repmat(0.3, [G.cells.num, 1]);
T=computeTrans(G, rock);

% Define a simple two phase fluid


fluid=initSimpleFluid('mu', [1, 10]*centi*poise, 'rho', [1014, 859]*kilogram/meter^3, 'n', [2
2]);

% Setup a producer/injector pair of wells


rate=10*meter^3/day;
bhp=1*barsa;
radius=0.05;

% Injector in lower right corner


W=addWell([], G, rock, round(nx/8)+nx*round(ny/8), 'Type', 'rate', 'Val', rate, 'Radius', radius,
'InnerProduct', 'ip_tpf', 'Comp_i', [1, 0]);

% Producer in upper right corner


W=addWell(W, G, rock, round(7*nx/8)+nx*round(7*ny/8), 'Type', 'bhp', 'Val', bhp, 'Radius',
radius, 'InnerProduct', 'ip_tpf', 'Comp_i', [0, 1]);

% Setup solution structures with only one phase


refSol=initState(G, W, 0, [0, 1]);
msSol=initState(G, W, 0, [0, 1]);
gravity off
verbose=false;

% Setup pressure and transport solvers


% Reference TPFA
r_psolve=@(state) incompTPFA(state, G, T, fluid, 'wells', W);

% MsFV using a few iterations to improve flux error


psolve=@(state) solveMSFV_TPFA_Incomp(state, G, CG, T, fluid, 'Reconstruct', true, 'Dual',
DG, 'wells', W, 'Update', true, 'Iterations', 5, 'Iterator', 'msfvm', 'Subiterations', 10, 'Smoother',
'dms', 'Omega', 1);

% Implicit transport solver


tsolve=@(state, dT) implicitTransport(state, G, dT, rock, fluid, 'wells', W, 'verbose', verbose);

% Solve initial pressure in reservoir


refSol=r_psolve(refSol);
msSol=psolve(msSol); % Parece que el error fuera aquí
subplot(2,1,1)
plotCellData(G, refSol.pressure); axis tight; colorbar;
title('Pressure Ref')
cbar=caxis();
subplot(2,1,2)
plotCellData(G, msSol.pressure); axis tight; colorbar;
title('Pressure MS')
caxis(cbar)

% Transport loop
T=20*day();
dT=T/60;

% Start the main loop


t=0;
while t<T,
% Solve transport equations using the transport solver
msSol=tsolve(msSol, dT);
refSol=tsolve(refSol, dT);

% Update the pressure based on the new saturations


msSol=psolve(msSol);
refSol=r_psolve(refSol);

% Increase time and continue if we do not want to plot saturations


if doPlot
clf;

% Saturation plot
subplot(2,2,1)
plotGrid(G, 'FaceColor', 'None', 'EdgeAlpha', 0)
plotCellData(G, refSol.s(:,1), refSol.s(:,1)>0); axis tight; colorbar;
title('Saturation Ref')
cbar=caxis();
subplot(2,2,2)
plotGrid(G, 'Facecolor', 'None', 'EdgeAlpha', 0)
plotCellData(G, msSol.s(:,1), msSol.s(:,1)>0); axis tight; colorbar;
title('Saturation MSFV')

% Align colorbars
caxis(cbar)

% Pressure plot
subplot(2,2,3)
plotCellData(G, refSol.pressure); axis tight; colorbar;
title('Pressure Ref')
cbar=caxis();
subplot(2,2,4)
hs=plotCellData(G, msSol.pressure); axis tight; colorbar;
title('Pressure MSFV')
caxis(cbar)
drawnow
end
t=t+dT;
end

Das könnte Ihnen auch gefallen