sem2d_0.m
来自「spectral element method」· M 代码 · 共 209 行
M
209 行
% SEM2D applies the Spectral Element Method% to solve the 2D SH wave equation, % with stress free boundary conditions,% zero initial conditions% and a time dependent force source,% in a structured undeformed grid.%% Version 0: domain = square box (aspect ratio=1)% medium = homogeneous %% This script is intended for tutorial purposes.%% Jean-Paul Ampuero jampuero@princeton.edu%%------------------------------------------% STEP 1: SPECTRAL ELEMENT MESH GENERATION% This is usually done in two steps:% the interval [0,LX]*[0,LY] is divided into NELX*NELY quadrangular elements% (that's basically a quadrangular finite element mesh),% then each element is sub-grided with (P+1)^2 Gauss-Lobatto-Legendre points % (GLL nodes) where P is the polynomial order of the spectral elements.% Actually, in this example the mesh is so simple % that we do it in a single step without storing intermediate data.%**** Set here the parameters of the square box domain and mesh : ****LX=10; % side-lengthNELX = 10; % number of elements along each sideP = 6; % polynomial degree (inside each element, along each direction)%********LY=LX;NELY = NELX;dxe = LX/NELX;dye = dxe;NEL = NELX*NELY;NGLL = P+1; % number of GLL nodes per element% Generate the Spectral Element mesh% The domain is partitioned into elements,% each element contains a cartesian GLL subgrid[iglob,x,y]=MeshBox(LX,LY,NELX,NELY,NGLL);nglob = length(x);% The global numbering of the elements follows this convention:%% ... ... ... ... NELX*NELY% ^ ... ... ... ... ...% | NELX+1 ... ... ... 2*NELX% | 1 2 ... ... NELX % --->% The local numbering of GLL nodes follows this convention:% % (1,NGLL)... (NGLL,NGLL)% ^ ... ... ... % | (1,1) ... (NGLL,1)% --->%------------------------------------------% STEP 2: INITIALIZATION% The Gauss-Lobatto-Legendre points and weights% and derivatives of the Lagrange polynomials H_ij = h'_i(xgll(j))% were pre-tabulated for the usual range of NGLL (3 to 10).% xgll = location of the GLL nodes inside the reference segment [-1:1][xgll,wgll,H] = GetGLL(NGLL);Ht = H';wgll2 = wgll * wgll' ;%**** Set here the parameters of the time solver : ****NT = 900; % number of timestepsCFL = 0.6; % stability number = CFL_1D / sqrt(2)%********%**** Set here the physical properties of the homogeneous medium : ****rho = 1;mu = 1;vs = sqrt(mu/rho); %********% The timestep dt is set by the stability condition% dt = CFL*min(dx/vs)dxmin = x(2)-x(1);dt = CFL*dxmin/vs;% For this simple mesh the global-local coordinate map (x,y)->(xi,eta)% is linear, its jacobian is constant jac = (0.5*dxe)^2;% dx_dxi = dy_deta% coefint = jac/dx_dxi^2 = jac/dy_deta^2 = 1% The diagonal mass matrix is stored in a global array. % It is assembled here, from its local contributions% Nodes at the boundary between two or more elements get % contributions from all of them.M = zeros(nglob,1);for e=1:NEL, ig = iglob(:,:,e); M(ig) = M(ig) + wgll2 *rho *jac;end% The stiffness matrix K is not pre-assembled% We only store coefficients needed for its local contributionsW = wgll2 .* mu;%-- Initialize kinematic fields, stored in global arraysd = zeros(nglob,1);v = zeros(nglob,1);a = zeros(nglob,1);time = (1:NT)'*dt;%-- SOURCE TERM: point force, time function = Ricker wavelet%**** Set here the source location : ****Fx = 5; Fy = 5;%********[Fx,Fy,Fig] = FindNearestNode(Fx,Fy,x,y);Ff0 = 0.5; % fundamental frequencyFt0 = 1.5/Ff0; % delay% source time function (at mid-steps)Ft = ricker( time-0.5*dt, Ff0,Ft0);%-- initialize data for output seismograms%**** Set here receiver locations : ****OUTxseis = [0:0.5:10]'; % x coord of receiversOUTnseis = length(OUTxseis); % total number of receiversOUTyseis = repmat(3.5,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 = 50;OUTit = 0;OUTindx = Init2dSnapshot(iglob);%------------------------------------------% STEP 3: SOLVER M*a = -K*d +F% Explicit Newmark-alpha scheme with% alpha=1/2, beta=1/2, gamma=1%half_dt = 0.5*dt;for it=1:NT, % prediction of mid-step displacement: % d_mid = d_old + 0.5*dt*v_old d = d + half_dt*v; % internal forces at mid-step -K*d(t+1/2): a(:) = 0; % store -K*d in a global array for e=1:NEL, %switch to local (element) representation ig = iglob(:,:,e); local = d(ig); %gradients wrt local variables (xi,eta) d_xi = Ht*local; d_eta = local*H; %element contribution to internal forces d_xi = W.*d_xi; d_eta = W.*d_eta; local = H*d_xi + d_eta*Ht ; %assemble into global vector a(ig) = a(ig) -local; end % add external forces a(Fig) = a(Fig) + Ft(it); % acceleration: a = (-K*d +F)/M a = a ./M ; % update % v_new = v_old + dt*a_new; % d_new = d_old + dt*v_old + 0.5*dt^2*a_new % = d_mid + 0.5*dt*v_new v = v + dt*a; d = d + half_dt*v;%------------------------------------------% 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.5 0.5]); hold on plot(OUTxseis,OUTyseis,'^',Fx,Fy,'*') hold off drawnow endend % ... of time loop
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?