sem1d_implicit.m
来自「spectral element method」· M 代码 · 共 218 行
M
218 行
% SEM1D applies the Spectral Element Method% to solve the 1D SH wave equation, % with stress free boundary conditions,% zero initial conditions% and a time dependent force source.%% This script is intended for tutorial purposes.%% Jean-Paul Ampuero jampuero@princeton.edu%% THIS VERSION: implicit generalized alpha scheme% (J. Chung and G.M. Hulbert, JAM 1993)% which allows for a user-controlled dissipation at high-frequency % while mantaining low dissipation at low-frequency.% As it is an implicit scheme, large timesteps are allowed.% However, it introduces dispersion. % In this version the inversion of the dynamic matrix % is done by brute force.%------------------------------------------% STEP 1: MESH GENERATION% The interval [0,L] is divided into NEL non overlapping elements% The elements are defined by their "control nodes" XL=20;NEL = 20;X = [0:NEL]'*L/NEL;%------------------------------------------% STEP 2: INITIALIZATIONP = 6; % polynomial degreeNGLL = P+1; % number of GLL nodes per elementNT = 125; % number of timestepsABSO_TOP = 0;ABSO_BOTTOM =0;% 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.% The xgll are in [-1,1][xgll,wgll,H] = GetGLL(NGLL);iglob = zeros(NGLL,NEL); % local to global index mappingrho = zeros(NGLL,NEL); % densitymu = zeros(NGLL,NEL); % shear modulusnglob = NEL*(NGLL-1) + 1; % number of global nodescoor = zeros(nglob,1); % coordinates of GLL nodesM = zeros(nglob,1); % global mass matrix, diagonalK = zeros(nglob,nglob); % global stiffness matrixKloc = zeros(NGLL,NGLL,NEL); % local stiffness matrixCFL = 4; % stability number, can be high (but introduces dispersion)dt = Inf; % timestep (set later)r = 1.; % dissipation parameter of the generalized-alpha scheme % 1 = no dissipation % 0 = maximal high-frequency dissipationalpha_m = (2*r-1)/(r+1);alpha_f = r/(1+r);beta = 1/4*(1-alpha_m+alpha_f)^2;gamma = 0.5-alpha_m+alpha_f;for e=1:NEL, % FOR EACH ELEMENT ... % The table I = iglob(i,e) maps the local numbering of the % computational nodes (i,e) to their global numbering I. % 'iglob' is used to build global data % from local data (contributions from each element) iglob(:,e) = (e-1)*(NGLL-1)+(1:NGLL)'; % Coordinates of the computational (GLL) nodes dxe = X(e+1)-X(e); coor(iglob(:,e)) = 0.5*(X(e)+X(e+1)) + 0.5*dxe*xgll ; % Physical properties of the medium % can be heterogeneous inside the elements % and/or discontinuous across elements rho(:,e) = 1; mu(:,e) = 1; % For this simple mesh the jacobian of the global-local % coordinate map is a constant dx_dxi = 0.5*dxe; % The diagonal mass matrix is stored in a global array. % It is assembled here, from its local contributions % Nodes at the boundary between two elements get % contributions from both. ig = iglob(:,e); M(ig) = M(ig) + wgll .*rho(:,e) *dx_dxi;% The stiffness matrix K is not assembled at this point% (it is sparse, block-diagonal)% We only store its local contributions W = mu(:,e).*wgll/dx_dxi;% K(:,:,e) = H * diag(W)* H'; Kloc(:,:,e) = H * ( repmat(W,1,NGLL).* H'); K(ig,ig) = K(ig,ig) + Kloc(:,:,e);% The timestep dt is set by the stability condition% dt = CFL*min(dx/vs) vs = sqrt(mu(:,e)./rho(:,e)); vs = max( vs(1:NGLL-1), vs(2:NGLL) ); dx = abs(diff( coor(iglob(:,e)) )); dt = min(dt, min(dx./vs));end %... of element loopdt = CFL*dt;half_dt = 0.5*dt;D = (1-alpha_m)*diag(M) + ((1-alpha_f)*beta*dt^2)*K ;%invD = inv( (1-alpha_m)*diag(M) + ((1-alpha_f)*beta*dt^2)*K );% absorbing boundaries% The mass matrix needs to be modified at the boundary% for the implicit treatment of the term C*v.if ABSO_TOP BcTopC = sqrt(rho(NGLL,NEL)*mu(NGLL,NEL)); M(nglob) = M(nglob)+half_dt*BcTopC;endif ABSO_BOTTOM BcBottomC = sqrt(rho(1,1)*mu(1,1)); M(1) = M(1)+half_dt*BcBottomC;end% Initialize kinematic fields, stored in global arraysd = zeros(nglob,1);v = zeros(nglob,1);a = zeros(nglob,1);lhs = zeros(nglob,1);dlhs = zeros(nglob,1);% External force (SOURCE TERM), a Ricker wavelet% or velocity amplitude of an incoming waveF_IS_WAVE = 0;if ~F_IS_WAVE, Fx = L/2; [Fdist,Fix] = min( abs(coor-Fx) );endFf0 = 0.25; % fundamental frequencyFt0 = 1.5/Ff0; % delay% source time function (at mid-steps)Ft = ricker( (1:NT)'*dt-0.5*dt, Ff0,Ft0);% output arraysOUTdt = 1; % output every OUTdt timestepsOUTit = 0; % a counterOUTnt = NT/OUTdt; % number of output timesteps% output receivers at these locationsOUTx = [0:dxe:L]';OUTnx = length(OUTx);OUTix = zeros(OUTnx,1);% relocate to nearest GLL nodeOUTdist = zeros(OUTnx,1);for i=1:OUTnx, [OUTdist(i),OUTix(i)] = min( abs(coor-OUTx(i)) );endOUTx = coor(OUTix);OUTd = zeros(OUTnx,OUTnt);OUTv = zeros(OUTnx,OUTnt);OUTa = zeros(OUTnx,OUTnt);%------------------------------------------% STEP 3: SOLVER M*a = -K*d +F%for it=1:NT, dlhs = d; d = d +dt*v + (dt^2*(0.5-beta))*a; dlhs = (1-alpha_f)*d + alpha_f*dlhs; v = v +(dt*(1-gamma))*a; % internal forces at mid-step -K*d(t+1/2) lhs(:) = 0; % store -K*d in a global array for e=1:NEL, ix = iglob(:,e); lhs(ix) = lhs(ix) - Kloc(:,:,e)*dlhs(ix) ; end lhs = lhs - alpha_m*M.*a; % add external forces if ~F_IS_WAVE, lhs(Fix) = lhs(Fix) + Ft(it); end% % absorbing boundary% if ABSO_TOP, a(nglob) = a(nglob) -BcTopC*v(nglob); end% if ABSO_BOTTOM, % if F_IS_WAVE % incident wave, from bottom% %boundary term = -impedance*v_outgoing + impedance*v_incoming% a(1) = a(1) -BcBottomC*( v(1) -Ft(it) ) + BcBottomC*Ft(it);% else% a(1) = a(1) -BcBottomC*v(1);% end% end % acceleration: a = (-K*d +F)/M %a = invD*lhs ; a = D\lhs ; % update v = v + (gamma*dt)*a; d = d + (beta*dt^2)*a;%------------------------------------------% STEP 4: OUTPUT if mod(it,OUTdt) == 0 OUTit = OUTit+1; OUTd(:,OUTit) = d(OUTix); OUTv(:,OUTit) = v(OUTix); OUTa(:,OUTit) = a(OUTix); endend % of time loopt = (1:OUTit) *OUTdt*dt;PlotSeisTrace(OUTx,t,OUTv);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?