sem2d_unsplitpml_scec2.m

来自「spectral element method」· M 代码 · 共 382 行

M
382
字号
% SEM2D	applies the Spectral Element Method% to solve the 2D SH wave equation, % dynamic fault with slip weakening,% with Perfectly Matched Layers% and zero initial conditions% in a structured undeformed grid.%% Version 3: domain = rectangular (+symmetry => only right half of the domain)%            medium = general (heterogeneous)%            boundaries = 1 fault + 2 PML + 1 free %	     time scheme = leapfrog%% This script is intended for tutorial purposes.%% Jean-Paul Ampuero	jampuero@princeton.edu%%------------------------------------------% STEP 1: SPECTRAL ELEMENT MESH GENERATION%**** Set here the parameters of the square box domain and mesh : ****LX=12.5e3;LY=7.5e3;%NELX = 50; NELY = 25; P = 8; % polynomial degreeNELX = 25; NELY = 15; P = 4; % polynomial degreeABC_B = 0;ABC_R = 2;ABC_T = 2;ABC_L = 0;%********dxe = LX/NELX;dye = LY/NELY;NEL = NELX*NELY;NGLL = P+1; % number of GLL nodes per element[iglob,x,y]=MeshBox(LX,LY,NELX,NELY,NGLL);nglob = length(x);RHO = 2670.;VS  = 3464.;MU = RHO*VS^2;ETA = 0.1;PML_A = 10;PML_N = 2;%------------------------------------------% STEP 2: INITIALIZATION[xgll,wgll,H] = GetGLL(NGLL);Ht = H';W = wgll * wgll' ;M     = zeros(nglob,1);		% global mass matrix, diagonalrho   = zeros(NGLL,NGLL);	% density will not be storedmu    = zeros(NGLL,NGLL);	% shear modulus will not be stored%**** Set here the parameters of the time solver : ****%NT = 2200; TT=0; % number of timestepsNT=0; TT = 12; % total time in secondsCFL   = 0.6; 			% stability number = CFL_1D / sqrt(2)%********dt    = Inf;  			% timestep (set later)% For this simple mesh the global-local coordinate map (x,y)->(xi,eta)% is linear, its jacobian is constantdx_dxi  = 0.5*dxe;dy_deta = 0.5*dye;jac = dx_dxi*dy_deta;coefint1 = jac/dx_dxi ;coefint2 = jac/dy_deta ;% FOR EACH ELEMENT ...for ey=1:NELY, for ex=1:NELX,   e = (ey-1)*NELX+ex;  ig = iglob(:,:,e);%**** Set here the physical properties of the heterogeneous medium : ****  rho(:,:) = RHO;  mu(:,:)  = MU;%******** % Diagonal mass matrix  M(ig) = M(ig) + W .*rho *jac; % The timestep dt is set by the stability condition %   dt = CFL*min(dx/vs)  vs = sqrt(mu./rho);   if dxe<dye    vs = max( vs(1:NGLL-1,:), vs(2:NGLL,:) );    dx = repmat( diff(xgll)*0.5*dxe ,1,NGLL);   else    vs = max( vs(:,1:NGLL-1), vs(:,2:NGLL) );    dx = repmat( diff(xgll)'*0.5*dye ,NGLL,1);   end  dtloc = dx./vs;  dt = min( [dt dtloc(1:end)] );endend %... of element loopdt = CFL*dt;if ETA, dt=dt/sqrt(1+2*ETA); endhalf_dt = 0.5*dt;if NT==0, NT=ceil(TT/dt); end%-- Initialize kinematic fields, stored in global arrays%sx = zeros(NGLL,NGLL,NEL);%sy = zeros(NGLL,NGLL,NEL);f = zeros(nglob,1);v = zeros(nglob,1);d = zeros(nglob,1);time = (1:NT)'*dt;%-- Absorbing boundaries (first order): % The mass matrix needs to be modified at the boundary% for the IMPLICIT treatment of the term C*v.% Fortunately C is diagonal.impedance = RHO*VS;if ABC_L ==1 % Left  [BcLC,iBcL] = BoundaryMatrix(wgll,[NELX NELY],iglob,dy_deta,'L');  BcLC = impedance*BcLC;  M(iBcL)  = M(iBcL)  +half_dt*BcLC;endif ABC_R ==1 % Right  [BcRC,iBcR] = BoundaryMatrix(wgll,[NELX NELY],iglob,dy_deta,'R');  BcRC = impedance*BcRC;  M(iBcR) = M(iBcR) +half_dt*BcRC;endif ABC_T ==1  % Top  [BcTC,iBcT] = BoundaryMatrix(wgll,[NELX NELY],iglob,dx_dxi,'T');  BcTC = impedance*BcTC;  M(iBcT)   = M(iBcT)   +half_dt*BcTC;end%--- PMLanyPML = any([ABC_T ABC_R] ==2);if anyPML  ePML = [];  NEL_PML=0;  if ABC_R>1, ePML= [NELX:NELX:NEL]; end  if ABC_T>1, ePML= [ ePML [NEL-NELX+1:NEL] ]; end  ePML = unique(ePML); % +ordered  NEL_PML = length(ePML); %iPML(k) = global node index of the k-th PML node %iglob_PML(i,j,ePML) = PML node index of the (i,j,ePML) node  iglob_PML = iglob(:,:,ePML);  [iPML,dum,iglob_PML] = unique(iglob_PML(:));  iglob_PML = reshape(iglob_PML,[NGLL NGLL NEL_PML]);  nPML = length(iPML);  axPML=zeros(nPML,1);  ayPML=zeros(nPML,1);  xp = x(iPML);  yp = y(iPML);  lx = LX-dxe;  ly = LY-dye;  if ABC_R, axPML = PML_A*VS/dxe * ((xp-lx)/dxe).^PML_N .*(xp>=lx); end  if ABC_T, ayPML = PML_A*VS/dye * ((yp-ly)/dye).^PML_N .*(yp>=ly); end  clear xp yp  ahsumPML = 0.5*(axPML+ayPML);  aprodPML = axPML.*ayPML;  asinvPML = 1./( 1 + dt*ahsumPML );  s_x = zeros(NGLL,NGLL,NEL_PML);  s_y = zeros(NGLL,NGLL,NEL_PML);else  NEL_PML=0;  ePML =0;end%-- DYNAMIC FAULT at bottom boundary[FltB,iFlt] = BoundaryMatrix(wgll,[NELX NELY],iglob,dx_dxi,'B');FltN = length(iFlt);%FltZ = M(iFlt)./FltB /half_dt;  % if friction enforced at n+1/2 ==> dt/2 factorFltZ = M(iFlt)./FltB /dt;FltX = x(iFlt);FltV = zeros(FltN,NT);FltD = zeros(FltN,NT);% background stressFltNormalStress = 120e6;FltInitStress = repmat(70e6,FltN,1);% nucleation isel = find(abs(FltX)<=1.5e3);FltInitStress(isel) = 81.6e6;% frictionFltState = zeros(FltN,1);FltFriction.MUs = repmat(0.677,FltN,1);FltFriction.MUd = repmat(0.525,FltN,1);FltFriction.Dc  = 0.4;% barrierL_BARRIER = 15e3/2;isel = find(abs(FltX)>L_BARRIER);FltFriction.MUs(isel) = 1e4;FltFriction.MUd(isel) = 1e4;FltFriction.W = (FltFriction.MUs-FltFriction.MUd)./FltFriction.Dc;FltStrength = friction(FltState,FltFriction)*FltNormalStress ...                - FltInitStress; % strength excessif ETA,  % Kelvin-Voigt viscosity  NEL_ETA = min( NELX, ceil(L_BARRIER/dxe)+2 );  x1 = 0.5*(1+xgll');  eta_taper = exp(-pi*x1.^2);   eta = ETA*dt *repmat(eta_taper, NGLL,1 );else  NEL_ETA = 0;end%-- initialize data for output seismograms%**** Set here receiver locations : ****OUTxseis = [0:0.5e3:10e3]';		% x coord of receiversOUTnseis = length(OUTxseis);		% total number of receiversOUTyseis = repmat(2e3,OUTnseis,1);	% y coord of receivers%********% receivers are relocated to the nearest node% OUTdseis = distance between requested and relocated receivers[OUTxseis,OUTyseis,OUTiglob,OUTdseis] = FindNearestNode(OUTxseis,OUTyseis,x,y);OUTv = zeros(OUTnseis,NT);%-- initialize data for output snapshotsOUTdt = floor(0.5/dt);OUTit = 0;OUTindx = Init2dSnapshot(iglob);%------------------------------------------% STEP 3: SOLVER  M*a = -K*d +F% Leapfrog:%   d[n+1/2] = d[n-1/2] +dt*v[n]%   v[n+1] = v[n] + dt*( -K*d[n+1/2] +F[n+1/2] )%for it=1:NT, % update displacement and slip, at mid-step  d = d +dt*v;  FltD(:,it) = 2*d(iFlt);   % internal forces -K*d(t+1/2)  % stored in global array 'f'  f(:) = 0;  ep =1; % PML element counter  eep = ePML(ep); % next element that is PML  for e=1:NEL,    isPML = e==eep;    isETA = e<=NEL_ETA;    %switch to local (element) representation    ig = iglob(:,:,e);    if isPML      igPML = iglob_PML(:,:,ep);      ax = axPML(igPML);      ay = ayPML(igPML);      vloc = v(ig);      dloc = d(ig)-half_dt*vloc; % bring the (staggered) d to the same time as v      locx = vloc + ay.*dloc;      locy = vloc + ax.*dloc;      sx = MU* Ht*locx/dx_dxi ;	      sy = MU* locy*H /dy_deta ;      sx = ( dt*sx +(1-half_dt*ax).*s_x(:,:,ep) ) ./(1+half_dt*ax);      sy = ( dt*sy +(1-half_dt*ay).*s_y(:,:,ep) ) ./(1+half_dt*ay);      s_x(:,:,ep) = sx;      s_y(:,:,ep) = sy;      ep = ep+1;      if ep<=NEL_PML, eep = ePML(ep); else eep = 0; end    else      if isETA        local = d(ig) +eta.*v(ig); % Kelvin-Voigt viscosity      else        local = d(ig);      end     %gradients wrt local variables (xi,eta)     %stress = 2*mu* strain = mu*grad_displ      sx = MU* Ht*local/dx_dxi ;	      sy = MU* local*H /dy_deta ;    end   %element contribution to internal forces   %local = coefint1*H*( W.*sx ) + coefint2*( W.*sy )*Ht ;    d_xi = W.*sx;    d_xi = coefint1* H * d_xi;    d_eta = W.*sy;    d_eta = coefint2* d_eta *Ht;    local = d_xi  + d_eta ;   %assemble into global vector    f(ig) = f(ig) -local;  end % ... of element loop  % absorbing boundaries:  if ABC_L==1, f(iBcL) = f(iBcL) - BcLC.*v(iBcL); end  if ABC_R==1, f(iBcR) = f(iBcR) - BcRC.*v(iBcR); end  if ABC_T==1, f(iBcT) = f(iBcT) - BcTC.*v(iBcT); end  if anyPML    tmp = ahsumPML.*v(iPML) + aprodPML.*d(iPML) ;    f(iPML) = f(iPML) -M(iPML).*tmp;  end % fault boundary condition: slip weakening  FltState = max(FltD(:,it),FltState);  FltStrength = friction(FltState,FltFriction)*FltNormalStress ...                  -FltInitStress;  %NOTE: half_dt* to enforce friction at mid-step, see also FltZ  %FltVFree = v(iFlt) + half_dt*f(iFlt)./M(iFlt);   FltVFree = v(iFlt) + dt*f(iFlt)./M(iFlt);   TauStick = FltZ .*FltVFree; % TauStick = f(iFlt)./FltB;  Tau = min(TauStick,FltStrength);   f(iFlt) = f(iFlt) - FltB .*Tau; % update velocity  v = v + dt*f./M;  if anyPML, v(iPML) = asinvPML.*v(iPML); end % update slip rate  FltV(:,it) = 2*v(iFlt);%------------------------------------------% STEP 4: OUTPUT  OUTv(:,it) = v(OUTiglob);    if mod(it,OUTdt) == 0    OUTit = OUTit+1;    figure(1) % seismograms    PlotSeisTrace(OUTxseis,time,OUTv);    figure(2)    Plot2dSnapshot(x,y,v,OUTindx,[0 2]); % [0 2]    hold on    plot(OUTxseis,OUTyseis,'^')    hold off    drawnow  end  test(it) = max(abs(v));end % ... of time loopfigure(3)sdt=1;sdx=4;PlotSeisTrace(FltX(1:sdx:end),time(1:sdt:end),FltV(1:sdx:end,1:sdt:end));%surf(time(1:sdt:end),FltX(1:sdx:end),FltV(1:sdx:end,1:sdt:end))%xlabel('Time')%ylabel('Position along fault')%zlabel('Slip rate')

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?