2D constant-density acoustic frequency-domain modeling, linearized modeling and imaging: Testing
This script presents some basic tests of the modeling code.
Contents
Analytic solution for constant medium
We test the code against the analytic solution for a constant velocity and plot the error as a function of the gridspacing to verify the order of accuracy of the discretization. The 9-point mixed-grid discretization of [1] uses a regular and rotated 5-point discretization of the Laplace operator, which makes it technically a second-order scheme. It is optimized to minimize numerical dispersion, though, and hence expected to be more accurate than a regular 5-point discretization.
% velocity [m/s] v0 = 2000; % size of domain LxL m L = 1000; % sponge boundary size B m B = 250; % frequency [1/s] f = 10; % gridspacings h = [20:-2:2]; e = 0*h; % loop for k = 1:length(h) % grid paramets model.o = [0 0]; model.d = [h(k) h(k)]; model.n = [floor(L/h(k)) + 1 floor(L/h(k)) + 1]; % source and receiver setup model.zsrc = 500; model.xsrc = 500; model.zrec = 0:h(k):L; model.xrec = 0:h(k):L; % absorbing boundary model.nb = [floor(B/h(k)) + 1 floor(B/h(k))]; % frequency model.freq = f; % ricker wavelet model.f0 = 0; model.t0 = 0; % source matrix Q = 1; % slowness-squares model [km^2/s^2] m = 1e6*ones(prod(model.n),1)./v0.^2; % analytic solution D1 = G([v0;0],Q,model); % numerical solution D2 = F(m,Q,model,1); % error e(k) = norm(D1 - D2); end
The figure below confirms that the scheme is second order.
% plot error figure; loglog(h,e,h,h.^2,'k--'); xlabel('h');ylabel('error');legend('error','h^2'); % plot z = 0:h(k):1000; x = 0:h(k):1000; D1 = reshape(D1,model.n); D2 = reshape(D2,model.n); iz = floor(length(z)/2) + 1; figure; plot(x,real(D1(iz,:)),'k',x,real(D2(iz,:)),'r',x,imag(D1(iz,:)),'k--',x,imag(D2(iz,:)),'r--'); legend('Re(numerical)','Re(analytic)','Im(numerical)','Im(analytic)'); xlabel('x [m]');ylabel('z [m]'); title(['solutions at z = ' num2str(z(iz)) 'm']);
Analytic solution for linear velocity profile
The analytic Greens function for a linear velocity profile \(v = v_0 + \alpha z\) is presented by [2]. An example is shown below.
% velocity profile v0 = 2000; alpha = 0.7; % grid z = 0:10:1000; x = 0:10:5000; [o,d,n] = grid2odn(z,x); % gridded slowness-squared m = vec((1e6./(v0+alpha*z').^2)*ones(size(x))); % frequency f = 10; % modeling parameters model.o = o; model.d = d; model.n = n; model.nb = [50 50]; model.freq = f; model.f0 = 0; model.t0 = 0; model.zsrc = 10; model.xsrc = mean(x); model.zrec = z; model.xrec = x; % source Q = 1; % analytic solution G1 = G([v0;alpha],Q,model); % numerical solution G2 = F(m,Q,model,1); % plot figure; imagesc(x,z,reshape(real(G1),n),[-10 10]);axis equal tight; title('Real part of analytic solution'); xlabel('x [m]');ylabel('z [m]'); figure; imagesc(x,z,reshape(real(G2),n),[-10 10]);axis equal tight; title('Real part of numerical solution'); xlabel('x [m]');ylabel('z [m]');
Jacobian test
The Jacobian of the modeling operator is derived by linearizing the discretized system. We can test the accuracy by considering the Taylor approximation
\(F(\mathbf{m} + h\delta\mathbf{m}) = F(\mathbf{m}) + hJ\delta\mathbf{m} + \mathcal{O}(h^2).\)
% setup model parameters model.o = [0 0]; model.d = [10 10]; model.n = [101 101]; model.nb = [20 20]; model.freq = [10 15]; model.f0 = 10; model.t0 = 0.01; model.zsrc = 15; model.xsrc = 0:100:1000; model.zrec = 10; model.xrec = 0:5:1000; % source matrix Q = speye(length(model.xsrc)); % constant velocicty v0 = 2000; m = 1e6/v0.^2*ones(prod(model.n),1); % random perturbation, set values close to the edge to zero. dm = randn(model.n); dm([1:20 end-20:end],:) = 0; dm(:,[1:20 end-20:end]) = 0; dm = dm(:); % data and Jacobian [D0, J0] = F(m,Q,model); % linearized data dD = J0*dm; % stepsizes h = 10.^[0:-1:-6]; e = 0*h; for k = 1:length(h) D1 = F(m+h(k)*dm,Q,model); e(k) = norm(D1 - D0 - h(k)*dD); end % plot error figure; loglog(h,e,h,h.^2,'k--'); xlabel('h');ylabel('error');legend('error','h^2');
The figure confirms the error decreases as \(h^2\).
Adjoint test
The adjoint test will ensure that our implementation of the adjoint satisfies the formal definition of the adjoint:
\(\langle A\mathbf{x},\mathbf{y}\rangle = \langle \mathbf{x},A^*\mathbf{y}\rangle\)
% setup model parameters model.o = [0 0]; model.d = [10 10]; model.n = [51 51]; model.nb = [10 10]; model.freq = [10 15]; model.f0 = 10; model.t0 = 0.01; model.zsrc = 15; model.xsrc = 0:100:1000; model.zrec = 10; model.xrec = 0:5:1000; % source matrix Q = speye(length(model.xsrc)); % constant velocicty v0 = 2000; m = 1e6/v0.^2*ones(prod(model.n),1); % Jacobian operator J = oppDF(m,Q,model); % test for 10 random vectors for k = 1:10 x = randn(prod(model.n),1); y = J*x; left(k) = gather((J*x)'*y); right(k) = gather(x'*(J'*y)); end
The quantities left and right should be the same up to numerical precision, which we can easily verify by looking at the relative error:
% error
abs(left - right)./max(abs(left),abs(right))
ans = 1.0e-15 * Columns 1 through 7 0.1689 0.1655 0 0 0 0.2010 0.1802 Columns 8 through 10 0.1255 0.5508 0.1557
References
[1] C-H Jo,* C. Shin,* and J.H. Suh, 1996. An optimal 9-point, finite-difference, frequency-space, 2-D scalar wave extrapolator Geophysics 61(2), 529-537.
[2] B.N. Kuvshinov, W.A. Mulder. The exact solution of the time-harmonic wave equation for a linear velocity profile Geophysical Journal International 167(2), 659–662, 2006.