The following code is designed to create a simulation of a fault occurring across two 4km thick porous layers seperated by an almost impermeable seal. Depending on the user's choice, it can either output a matrix represented by a 2-D Contour Map with either static or flux boundaries.
The following code is designed to create a simulation of a fault occurring across two 4km thick porous layers seperated by an almost impermeable seal. Depending on the user's choice, it can either output a matrix represented by a 2-D Contour Map with either static or flux boundaries.
Direitos autorais:
Attribution Non-Commercial (BY-NC)
Formatos disponíveis
Baixe no formato TXT, PDF, TXT ou leia online no Scribd
The following code is designed to create a simulation of a fault occurring across two 4km thick porous layers seperated by an almost impermeable seal. Depending on the user's choice, it can either output a matrix represented by a 2-D Contour Map with either static or flux boundaries.
Direitos autorais:
Attribution Non-Commercial (BY-NC)
Formatos disponíveis
Baixe no formato TXT, PDF, TXT ou leia online no Scribd
% The following code is designed to create a simulation of a fault
% occuring across two 4km thick porous layers seperated by an almost
% impermeable seal and the pressure variations that it entails. Depending % on the user's choice, it can either output a matrix represented by a 2-D % Color Map with either static or flux boundaries or a matrix represented % by a 2-D Contour Map with either static or flux boundaries. clear % to clear the memory of all previous data % Data of physical properties kfault = 1e-13; % permeability in the fault kseal = 10^-20; % permeability in the seal kelse = 10^-16; % permeability everywhere else Psty = 0.05; % porosity Beta = 10^-8; % fluid compressibility n = 10^-4; % fluid viscosity kappa_k = kfault/(Psty*Beta*n); % hydraulic diffusivity TopP = 0; % Pressure in the upper layer BottomP = 70e6; % Pressure in the lower layer % Data of spatial properties dx = 84*4; % discretization step in m dz = 100*4; % discretization step in m h = 8400; % total height of area in m w = 10000; % total width of area in m % Data used to create the matrix nx = ceil(h/dx+1); % total number of horizontal matrix points nz = ceil(w/dz+1); % total number of vertical matrix points x = 0:dx:h; % finite difference mesh z = 0:dz:w; % finite difference mesh [zz,xx] = meshgrid(z,x); % combines two 1-D arrays into 2-D % arrays for both x and z % Initial Pressure distribution: P = ones(nx,nz); K = ones(nx,nz); % Creation of user options: % choices include either 'contour' or 'color' and 'fux' or 'static' whichplot = input('Which plot would you like, contour or color? > ','s'); while (strcmp('color',whichplot)==false) && (strcmp('contour',whichplot)==false ) whichplot = input('Which plot would you like, contour or color? > ','s'); end whichborder = input('Which boundaries would you prefer, flux or static? > ', 's' ); while (strcmp('flux',whichborder)==false) && (strcmp('static',whichborder)==fals e) whichborder = input('Which boundaries would you prefer, flux or static? > ' , 's'); end % Loop to populate the matrix with the appropriate permeability values % (without consideration of the fault) for i = 1:nx for j = 1:ceil(nz*(4/8.4)) P(j,i)=BottomP; K(j,i)=kelse; end for j = (ceil(nz*(4/8.4))):(nz*(4.4/8.4)) P(j,i)=0; K(j,i)=kseal; end for j = (ceil(nz*(4.4/8.4))):nz P(j,i)=TopP; K(j,i)=kelse; end end X=0; % Spacial counter X2=ceil(nx*(0.4/8.4)); % Spacial counter % Loop to populate the matrix with the appropriate permeability values of % the fault for j = 1:nz for i = 1:nx if(i>X) if(i<X2) K(j,i)=kfault; end end end X=X+1; X2=X2+1; end % Code to output a 2-D representation of the permeability values figure(1), clf pcolor (zz,xx,log10(K)) set(gca, 'CLim', [-21,-12]); shading interp; colorbar('location','southoutside') colormap(flipud(hot)); xlabel('x [km]') ylabel('1000-z [km]') zlabel('P [^oC]') drawnow % Initializations: Pnew = ones(nz,nx); % New martix to populate with pressure values dtMAX = (dx*dx/(4*kappa_k)); % maximal timestep in seconds dt = dtMAX*0.8; % chosen timestep % unit conversion to SI: secinhour=60*60; % conversion from seconds to hours secinday=secinhour*24; % conversion from seconds to days secin365days=secinhour*24*365; % conversion from seconds to yeas nt = secin365days/dt; % number of timesteps to reach a year t = 0; % initial timestep r = dt*(1/(Psty*Beta*n)); % data to simplify future calculations % Time-stepping: for it=1:nt % Boundary conditions if strcmp('flux',whichborder) % if the user wants flux boundary conditions % Corner points % P(1,1) K_right = (K(1, 2)+K(1, 1))/2; K_top = (K(2, 1)+K(1, 1))/2; PghostBOTTOM = P(2,1); PghostLEFT = P(1,2); DeltaPZ= ((K_top*(P(1+1,1)-P(1,1))/dz)-(K_top*((P(1,1)-Pghos tBOTTOM)/dz)))/dz; DeltaPX= ((K_right*(P(1,1+1)-P(1,1))/dx)-(K_right*((P(1,1)-P ghostLEFT)/dx)))/dx; Pnew(1,1)= P(1,1)+r*(DeltaPX+DeltaPZ); % P(nx,1) K_right = (K(nx, 1+1)+K(nx, 1))/2; K_bott = (K(nx-1, 1)+K(nx, 1))/2; PghostTOP = P(nx-1,1); PghostLEFT = P(nx,2); DeltaPZ= ((K_bott*(PghostTOP-P(nx,1))/dz)-(K_bott*((P(nx,1)- P(nx-1,1))/dz)))/dz; DeltaPX= ((K_right*(P(nx,1+1)-P(nx,1))/dx)-(K_right*((P(nx,1 )-PghostLEFT)/dx)))/dx; Pnew(nx,1)= P(nx,1)+r*(DeltaPX+DeltaPZ); % P(1,nx) K_left = (K(1, nx-1)+K(1, nx))/2; K_top = (K(1+1, nx)+K(1, nx))/2; PghostBOTTOM = P(1+1,nx); PghostRIGHT = P(1,nx-1); DeltaPZ= ((K_top*(P(1+1,nx)-P(1,nx))/dz)-(K_top*((P(1,nx)-Pg hostBOTTOM)/dz)))/dz; DeltaPX= ((K_left*(PghostRIGHT-P(1,nx))/dx)-(K_left*((P(1,nx )-P(1,nx-1))/dx)))/dx; Pnew(1,nx)= P(1,nx)+r*(DeltaPX+DeltaPZ); % P(nx,nx) K_left = (K(nx, nx-1)+K(nx, nx))/2; K_bott = (K(nx-1, nx)+K(nx, nx))/2; PghostTOP = P(nx-1,nx); PghostRIGHT = P(nx,nx-1); DeltaPZ= ((K_bott*(PghostTOP-P(nx,nx))/dz)-(K_bott*((P(nx,nx )-P(nx-1,nx))/dz)))/dz; DeltaPX= ((K_left*(PghostRIGHT-P(nx,nx))/dx)-(K_left*((P(nx, nx)-P(nx,nx-1))/dx)))/dx; Pnew(nx,nx)= P(nx,nx)+r*(DeltaPX+DeltaPZ); % Border points % Bottom border for ii = 2:nx-1 K_left = (K(1, ii-1)+K(1, ii))/2; K_right = (K(1, ii+1)+K(1, ii))/2; K_top = (K(2, ii)+K(1, ii))/2; PghostB = P(2,ii); DeltaPZ= (K_top*(P(1+1,ii)-P(1,ii))/dz-(K_top*(P(1,ii)-Pghos tB)/dz))/dz; DeltaPX= (K_right*(P(1,ii+1)-P(1,ii))/dx-(K_left*(P(1,ii)-P( 1,ii-1))/dx))/dx; Pnew(1,ii)= P(1,ii)+r*(DeltaPX+DeltaPZ); end % Top border for iii = 2:nx-1 K_left = (K(nx, iii-1)+K(nx, iii))/2; K_right = (K(nx, iii+1)+K(nx, iii))/2; K_bott = (K(nx-1, iii)+K(nx, iii))/2; PghostT = P(nx-1,iii); DeltaPZ= (K_bott*(PghostT-P(nx,iii))/dz-(K_bott*(P(nx,iii)-P (nx-1,iii))/dz))/dz; DeltaPX= (K_right*(P(nx,iii+1)-P(nx,iii))/dx-(K_left*(P(nx,i ii)-P(nx,iii-1))/dx))/dx; Pnew(nx,iii)= P(nx,iii)+r*(DeltaPX+DeltaPZ); end % Left border for jj = 2:nz-1 K_right = (K(jj, 1+1)+K(jj, 1))/2; K_top = (K(jj+1, 1)+K(jj, 1))/2; K_bott = (K(jj-1, 1)+K(jj, 1))/2; PghostLEFT = P(jj,2); DeltaPZ= (K_top*(P(jj+1,1)-P(jj,1))/dz-(K_bott*(P(jj,1)-P(jj -1,1))/dz))/dz; DeltaPX= (K_right*(P(jj,1+1)-P(jj,1))/dx-(K_right*(P(jj,1)-P ghostLEFT)/dx))/dx; Pnew(jj,1)= P(jj,1)+r*(DeltaPX+DeltaPZ); end % Right border for jjj = 2:nz-1 K_left = (K(jjj, nz-1)+K(jjj, nz))/2; K_top = (K(jjj+1, nz)+K(jjj, nz))/2; K_bott = (K(jjj-1, nz)+K(jjj, nz))/2; PghostRIGHT = P(jjj,nz-1); DeltaPZ= (K_top*(P(jjj+1,nz)-P(jjj,nz))/dz-(K_bott*(P(jjj,nz )-P(jjj-1,nz))/dz))/dz; DeltaPX= (K_left*(PghostRIGHT-P(jjj,nz))/dx-(K_left*(P(jjj,n z)-P(jjj,nz-1))/dx))/dx; Pnew(jjj,nz)= P(jjj,nz)+r*(DeltaPX+DeltaPZ); end end if strcmp('static',whichborder) % if the user wants static boundary conditions for i = 1:nx Pnew(1,i)= BottomP; Pnew(nz,i)= TopP; end for j = 1:nz if(j<(nz*(4/8.4))) Pnew(j,1)=BottomP; Pnew(j,nx)=BottomP; end if(j>(nz*(4.4/8.4))) Pnew(j,1)=TopP; Pnew(j,nx)=TopP; end end end % Internal points for i = 2:nx-1 for j = 2:nz-1 K_left = (K(j, i-1)+K(j, i))/2; K_right = (K(j, i+1)+K(j, i))/2; K_top = (K(j+1, i)+K(j, i))/2; K_bott = (K(j-1, i)+K(j, i))/2; DeltaPZ= (K_top*(P(j+1,i)-P(j,i))/dz-(K_bott*(P(j,i)-P(j-1,i))/dz))/ dz; DeltaPX= (K_right*(P(j,i+1)-P(j,i))/dx-(K_left*(P(j,i)-P(j,i-1))/dx) )/dx; Pnew(j,i)= P(j,i)+r*(DeltaPX+DeltaPZ); end end % Code to output a 2-D representation of the pressure values on a color % map if strcmp('color',whichplot) % if the user wants to output the color map if mod(it,10)==0 % to speed up the simulation, only certain stages will be outputted figure(2), clf pcolor (zz,xx,P) set(gca, 'CLim', [0, 10^8]); shading interp; colorbar('location','southoutside') colormap (flipud(jet)); xlabel('x [km]') ylabel('1000-z [km]') zlabel('P [^oC]') title(['P [Pa] at ',num2str(floor(t/secinday)),' days']) end end
% Code to output a 2-D representation of the pressure values on a contour
% map if strcmp('contour',whichplot) % if the user wants to output the contour map if mod(it,10)==0 % to speed up the simulation, only certain stages will be outputted figure(3), clf [DX,DY] = gradient(-P); DX=DX.*kseal; DY=DY.*kseal; contour (zz,xx,P) hold on quiver(zz,xx,DX,DY) colormap(flipud(jet)); hold off set(gca, 'CLim', [0, 10^8]); shading interp; colorbar('location','southoutside') xlabel('x [km]') ylabel('1000-z [km]') zlabel('P [^oC]') title(['P [Pa] at ',num2str(floor(t/secinday)),' days']) end end drawnow % output the graph t=t+dt; % Increase time step P = Pnew; % Copy new P-field to old one for next timestep end