While that's still an excellent book that I recommend to people who are starting out, it has a very serious flaw in its discussion of nonlinear problems. Trefethen's p27.m example, which simulates KdV solitons does not include a de-aliasing step. Early in my career, this led me to think that de-aliasing was unnecessary. That was, until, I started looking at problems with cubic nonlinearities; the p27.m example is only quadratic.
Consider focusing, cubic NLS on the torus, \(\mathbb{T}\),
\[
i u_t + u_{xx} + |u|^2 u = 0, \quad u: \mathbb{T} \times \mathbb{R} \to \mathbb{C}.
\]
When posed on the whole real line, instead of the torus, it admits soliton solutions,
\[
\Phi(x,t) = e^{i \lambda^2 t} \sqrt{2} \lambda {\rm sech}(\lambda x), \quad \lambda \neq 0.
\]
Since they are exponentially localized, if we take \( \lambda \) sufficiently large, we can approximately simulate it on the finite domain size.
Modifying p27.m for NLS, we have:
% Set discretization parameters N = 512; dt = .1/N; x = (2*pi/N)*(-N/2:N/2-1)'; % Set initial condition lam = 10; u = sqrt(2) * lam * sech(lam * x); v = fft(u); % Construct integration operators k = [0:N/2-1 0 -N/2+1:-1]'; E = exp(-.5i * dt * k.^2); E2 = E.^2; g = 1i * dt; % Set simulation parameters tmax = 5; nplt = floor((tmax/50)/dt); nmax = round(tmax/dt); udata = u; tdata = 0; % Integrate using the Integrating Factor method for n = 1:nmax t = n*dt; a = g.*fft(abs( ifft( v ) ).^2 .* ifft(v)); b = g.*fft(abs( ifft(E.*(v+a/2)) ).^2 .* ifft(E.*(v+a/2)) ); c = g.*fft(abs( ifft(E.*v + b/2) ).^2 .* ifft(E.*v + b/2) ); d = g.*fft(abs( ifft(E2.*v+E.*c) ).^2 .* ifft(E2.*v+E.*c)); v = E2.*v + (E2.*a + 2*E.*(b+c) + d)/6; if mod(n,nplt) == 0 u = ifft(v); udata = [udata u]; tdata = [tdata t]; end end % Plot and save figure; for n = 1:length(tdata) plot(x, abs(udata(:,n)),... x, real(udata(:,n)), x, imag(udata(:,n)),... x,abs(udata(:,1)), 'linewidth',2); xlim([-pi, pi]); ylim([-16,16]); set(gca,'fontsize',16); xlabel('x'); legend('|u|', 'Re. u', 'Im. u', '|u_0|'); title(sprintf(' t = %g', tdata(n))); drawnow; saveas(gcf,sprintf('frame%i.png', n)); end
This generates the following output:
Notice the appearance of very high frequency oscillations. These are aliasing errors. De-aliasing them, by zeroing out the upper half of the frequencies in Fourier, produces the following, desired, output:
This is the result of the following code. Notice that I doubled the number of grid points to compensate for the de-aliasing.
While I still recommend Trefethen's book to people, I would supplement it with another text that addresses the aliasing problem. Two books I like are Boyd's, Chebyshev and Fourier Spectral Methods, and Canuto et al's, Spectral Methods: Fundamentals in Single Domains.% Set discretization parameters N = 1024; dt = .1/N; x = (2*pi/N)*(-N/2:N/2-1)'; % Set initial condition lam = 10; u = sqrt(2) * lam * sech(lam * x); v = fft(u); v(N/4+2:end - N/4+1) = 0; % Construct integration operators k = [0:N/2-1 0 -N/2+1:-1]'; E = exp(-.5i * dt * k.^2); E2 = E.^2; g = 1i * dt; % Set simulation parameters tmax = 5; nplt = floor((tmax/50)/dt); nmax = round(tmax/dt); udata = u; tdata = 0; % Integrate using the Integrating Factor method for n = 1:nmax t = n*dt; a = g.*fft(abs( ifft( v ) ).^2 .* ifft(v)); a(N/4+2:end - N/4+1) = 0; b = g.*fft(abs( ifft(E.*(v+a/2)) ).^2 .* ifft(E.*(v+a/2)) ); b(N/4+2:end - N/4+1) = 0; c = g.*fft(abs( ifft(E.*v + b/2) ).^2 .* ifft(E.*v + b/2) ); c(N/4+2:end - N/4+1) = 0; d = g.*fft(abs( ifft(E2.*v+E.*c) ).^2 .* ifft(E2.*v+E.*c)); d(N/4+2:end - N/4+1) = 0; v = E2.*v + (E2.*a + 2*E.*(b+c) + d)/6; if mod(n,nplt) == 0 u = ifft(v); udata = [udata u]; tdata = [tdata t]; end end % Plot and save figure; for n = 1:length(tdata) plot(x, abs(udata(:,n)),... x, real(udata(:,n)), x, imag(udata(:,n))... , 'linewidth',2); xlim([-pi, pi]); ylim([-16,16]); set(gca,'fontsize',16); xlabel('x'); legend('|u|', 'Re. u', 'Im. u'); title(sprintf(' t = %g', tdata(n))); drawnow; saveas(gcf,sprintf('frame%i.png', n)); end
This is a nice example. Aliasing is typically a problem for marginally resolved simulations. If one increases the spatial resolution in the first code to more than 1024 grid points, the high frequency oscillations are eliminated.
ReplyDeleteHi Benson. Yeah, I totally agree that pushing the resolution high enough fixes these problems. Boyd says something about that in his book. But it irks me people are picking up bad habits for nonlinear problems (though perfectly good for the linear case) from Trefethen's book.
ReplyDelete