Contents

Vertical-Averaged Simulation: Sloping Aquifer

In this example we consider a synthetic sloping aquifer. The topography of the top surface and the geological layers in the model is generated by combining the membrane function (MATLAB logo) and a sinusoidal surface with random perturbations.

Here, CO2 is injected in the aquifer for a period of 30 years. Thereafter we simulate the migration of the CO2 in a post-injection period of 720 years.

The simulation is done using the vertical average/equilibrium framework.

%require vertical-equil

Write header

disp('================================================================');
disp('   Vertical averaging applied to a synthetic sloping aquifer');
disp('   using C++ accelleration in the transport solver');
disp('================================================================');
disp(' ');
================================================================
   Vertical averaging applied to a synthetic sloping aquifer
   using C++ accelleration in the transport solver
================================================================
 

Construct stratigraphic and petrophysical model

We construct a slightly sloping aquifer with a wavy top surface that allows for structural trapping

[G, Gt, rock, rock2D, bcIxVE] = makeSlopingAquifer();
 -> Reading SlopingAquifer.mat

Set time and fluid parameters

Inject CO2 for 30 years and study subsequent migration until 750 years after injection started. The fluid data are chosen so that they are resonable at p = 300 bar

gravity on
T          = 110*year();
stopInject = 30*year();
dT         = 2*year();
dTplot     = 2*dT;
fluidVE    = initVEFluidHForm(Gt, 'mu' , [0.056641 0.30860] .* centi*poise, ...
                         'rho', [686.54 975.86] .* kilogram/meter^3, ...
                         'sr', 0.2, 'sw', 0.1, 'kwm', [0.2142 0.85]);

Set well and boundary conditions

We use one well placed down the flank of the model, perforated in the bottom layer. Injection rate is 1.4e3 m^3/day of supercritical CO2. Hydrostatic boundary conditions are specified on all outer boundaries.

% Set well in 3D model
wellIx = [G.cartDims(1:2)/5, G.cartDims([3 3])];
rate   = 2.8e3*meter^3/day;
W      = verticalWell([], G, rock, wellIx(1), wellIx(2), ...
                      wellIx(3):wellIx(4), 'Type', 'rate', 'Val', rate, ...
                      'Radius', 0.1, 'comp_i', [1,0], 'name', 'I');

% Well and BC in 2D model
WVE = convertwellsVE(W, G, Gt, rock2D);

bcVE     = addBC([], bcIxVE, 'pressure', ...
                 Gt.faces.z(bcIxVE)*fluidVE.rho(2)*norm(gravity));
bcVE     = rmfield(bcVE,'sat');
bcVE.h   = zeros(size(bcVE.face));

Prepare simulations

Compute inner products and instantiate solution structure

SVE = computeMimeticIPVE(Gt, rock2D, 'Innerproduct','ip_simple');
preComp = initTransportVE(Gt, rock2D);
sol = initResSolVE(Gt, 0, 0);
sol.wellSol = initWellSol(W, 300*barsa());
sol.s = height2Sat(sol, Gt, fluidVE);

% Use C++ acceleration for the transport calculation
% NB: requires that the VEmex module has been compiled
try
   mtransportVE();
   cpp_accel = true;
catch me
   d = fileparts(mfilename('fullpath'));
   disp('mex-file for C++ acceleration not found');
   disp(['See ', fullfile(VEROOTDIR,'VEmex','README'), ' for building instructions']);
   disp('Using matlab ve-transport');
   cpp_accel = false;
end
mex-file for C++ acceleration not found
See /home/moyner/simmatlab/branches/mrst-releases/2012b/modules/vertical-equil/VEmex/README for building instructions
Using matlab ve-transport

Prepare plotting

We will make a composite plot that consists of several parts, a 3D plot of the plume, a pie chart of trapped versus free volume, a plane view of the plume from above, and two cross-sections in the x/y directions through the well

opts = {'slice', wellIx,  'maxH', 15, 'Saxis', [0 1-fluidVE.sw], ...
   'view', [-7, 25], 'Wadd', 100};
plotPanelVE(G, Gt, W, sol, 0.0, [0 0 1], opts{:});

Main loop

Run the simulation using a sequential splitting with pressure and transport computed in separate steps. The transport solver is formulated with the height of the CO2 plume as the primary unknown and the relative height (or saturation) must therefore be reconstructed.

t = 0;
fprintf(1,'\nSimulating %d years of injection',convertTo(stopInject,year));
fprintf(1,' and %d years of migration\n', convertTo(T-stopInject,year));
fprintf(1,'Time: %4d years', convertTo(t,year));

sol_mex   = sol;

while t<T
   % Advance solution: compute pressure and then transport
   sol = solveIncompFlowVE(  sol, Gt, SVE, rock, fluidVE, ...
                             'bc', bcVE, 'wells', WVE);


   if cpp_accel
      [sol.h, sol.h_max] = mtransportVE(sol, Gt, dT, rock, ...
                                fluidVE, 'bc', bcVE, 'wells', WVE, ...
                               'gravity', norm(gravity), 'verbose', false);
   else
      sol = explicitTransportVE(sol, Gt, dT, rock, fluidVE, ...
                             'bc', bcVE, 'wells', WVE, 'preComp', preComp);
   end
   % Reconstruct 'saturation' defined as s=h/H, where h is the height of
   % the CO2 plume and H is the total height of the formation
   sol.s = height2Sat(sol, Gt, fluidVE);
   assert( max(sol.s(:,1))<1+eps && min(sol.s(:,1))>-eps );
   t = t + dT;

   % Check if we are to stop injecting
   if t>= stopInject
      WVE  = []; bcVE = [];
   end

   % Compute trapped and free volumes of CO2
   fprintf(1,'\b\b\b\b\b\b\b\b\b\b%4d years', convertTo(t,year));
   freeVol = ...
      sum(sol.h.*rock2D.poro.*Gt.cells.volumes)*(1-fluidVE.sw);
   trappedVol = ...
      sum((sol.h_max-sol.h).*rock2D.poro.*Gt.cells.volumes)*fluidVE.sr;
   totVol = trappedVol + freeVol;

   % Plotting
   if mod(t,dTplot)~= 0 && (t<T),
      continue
   else
      plotPanelVE(G, Gt, W, sol, t, [freeVol trappedVol totVol], opts{:});
      drawnow
   end

end
fprintf(1,'\n\n');
% delete C++ simulator
if cpp_accel, mtransportVE(); end
Simulating 30 years of injection and 80 years of migration
Time:  110 years