├── README.md ├── cheb.m ├── chebfft.m ├── clencurt.m ├── gauss.m ├── jupyter ├── p01.ipynb ├── p02.ipynb ├── p03.ipynb └── p04.ipynb ├── leg.m ├── p01.m ├── p02.m ├── p03.m ├── p04.m ├── p05.m ├── p06.m ├── p06u.m ├── p07.m ├── p08.m ├── p09.m ├── p10.m ├── p11.m ├── p12.m ├── p13.m ├── p14.m ├── p15.m ├── p16.m ├── p17.m ├── p18.m ├── p19.m ├── p20.m ├── p20u.m ├── p21.m ├── p22.m ├── p23.m ├── p23a.m ├── p24.m ├── p24fine.m ├── p25.m ├── p26.m ├── p27.m ├── p28.m ├── p28b.m ├── p29.m ├── p30.m ├── p30b.m ├── p30c.m ├── p31.m ├── p32.m ├── p33.m ├── p34.m ├── p35.m ├── p36.m ├── p37.m ├── p38.m ├── p39.m └── p40.m /README.md: -------------------------------------------------------------------------------- 1 | # Spectral methods in matlab 2 | 3 | These codes are taken from the book 4 | 5 | L. N. Trefethen, Spectral Methods in Matlab 6 | 7 | For Python version, see 8 | 9 | http://github.com/cpraveen/chebpy 10 | -------------------------------------------------------------------------------- /cheb.m: -------------------------------------------------------------------------------- 1 | % CHEB compute D = differentiation matrix, x = Chebyshev grid 2 | 3 | function [D,x] = cheb(N) 4 | if N==0, D=0; x=1; return, end 5 | x = cos(pi*(0:N)/N)'; 6 | c = [2; ones(N-1,1); 2].*(-1).^(0:N)'; 7 | X = repmat(x,1,N+1); 8 | dX = X-X'; 9 | D = (c*(1./c)')./(dX+(eye(N+1))); % off-diagonal entries 10 | D = D - diag(sum(D')); % diagonal entries 11 | 12 | -------------------------------------------------------------------------------- /chebfft.m: -------------------------------------------------------------------------------- 1 | % CHEBFFT Chebyshev differentiation via FFT. Simple, not optimal. 2 | % If v is complex, delete "real" commands. 3 | 4 | function w = chebfft(v) 5 | N = length(v)-1; if N==0, w=0; return, end 6 | x = cos((0:N)'*pi/N); 7 | ii = 0:N-1; 8 | v = v(:); V = [v; flipud(v(2:N))]; % transform x -> theta 9 | U = real(fft(V)); 10 | W = real(ifft(1i*[ii 0 1-N:-1]'.*U)); 11 | w = zeros(N+1,1); 12 | w(2:N) = -W(2:N)./sqrt(1-x(2:N).^2); % transform theta -> x 13 | w(1) = sum(ii'.^2.*U(ii+1))/N + .5*N*U(N+1); 14 | w(N+1) = sum((-1).^(ii+1)'.*ii'.^2.*U(ii+1))/N + ... 15 | .5*(-1)^(N+1)*N*U(N+1); 16 | -------------------------------------------------------------------------------- /clencurt.m: -------------------------------------------------------------------------------- 1 | % CLENCURT nodes x (Chebyshev points) and weights w 2 | % for Clenshaw-Curtis quadrature 3 | 4 | function [x,w] = clencurt(N) 5 | theta = pi*(0:N)'/N; x = cos(theta); 6 | w = zeros(1,N+1); ii = 2:N; v = ones(N-1,1); 7 | if mod(N,2)==0 8 | w(1) = 1/(N^2-1); w(N+1) = w(1); 9 | for k=1:N/2-1, v = v - 2*cos(2*k*theta(ii))/(4*k^2-1); end 10 | v = v - cos(N*theta(ii))/(N^2-1);; 11 | else 12 | w(1) = 1/N^2; w(N+1) = w(1); 13 | for k=1:(N-1)/2, v = v - 2*cos(2*k*theta(ii))/(4*k^2-1); end 14 | end 15 | w(ii) = 2*v/N; 16 | -------------------------------------------------------------------------------- /gauss.m: -------------------------------------------------------------------------------- 1 | % GAUSS nodes x (Legendre points) and weights w 2 | % for Gauss quadrature 3 | 4 | function [x,w] = gauss(N) 5 | beta = .5./sqrt(1-(2*(1:N-1)).^(-2)); 6 | T = diag(beta,1) + diag(beta,-1); 7 | [V,D] = eig(T); 8 | x = diag(D); [x,i] = sort(x); 9 | w = 2*V(1,i).^2; 10 | -------------------------------------------------------------------------------- /jupyter/p01.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "bfd1d128-df18-4aa6-b6c6-4c6d35eafefc", 6 | "metadata": { 7 | "tags": [] 8 | }, 9 | "source": [ 10 | "# p1.m - convergence of fourth-order finite differences" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "id": "9e75d0d3-2eb1-460a-b91e-a08306d320f9", 17 | "metadata": { 18 | "tags": [] 19 | }, 20 | "outputs": [ 21 | { 22 | "data": { 23 | "image/png": "iVBORw0KGgoAAAANSUhEUgAABGAAAANICAIAAAAHNA4rAAAAB3RJTUUH5wQLBzMnsTpmhQAAIABJREFUeJzs3Xt4VNW5+PGVhPtNQC4hAgYsCWDBgBGTAspYT0VA6ikqWG71gDAcoYi1oqIFVAqciAhJYbACgmhVUH+KgBRxUqROioNc2ohAIYFMwYMgBYEAIczvjz3sM2aSYWb2be2Z7+fx8ZmszF57zZp5Sd6svdeb5Pf7BQAAAABAiGSrBwAAAAAAsiBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAIAAEiQAAAAACCBBAgAAAICAWlYPAIA+Ll++vH///q+//rpNmzaZmZnXXHON1SMCAACwH1aQANsrKirq16/fNddc07lz53vvvffWW29t2rRp7969//KXv1g9NMTuwoULL7zwQo8ePZo2bdqsWbMlS5Zof6bu/H7/uSuC29u1a9egQYMGDRq4XC7TBhOhpk2bKmNbunSpcWcJfVO6d++unPd3v/tdVF1VObCmOdddlYmqdvzVfvYs/EACgC5YQQJs7PLly3PmzJk+ffqlS5eqfOvzzz/v16/ftGnTXnjhBUvGBo3GjRu3cuVK9cvvv/9e+zN1d/To0euuu0557Ha7+/Xrp46hvLxcCHH+/HnTBhOh8vLyixcvCiFCo0ZHoW/K+fPnlTmpqKiIqqsqB9Y057qrMlHVjr/az56FH0gA0AUJEmBjzz///IwZM4JbUlNTjx8/rv7mN2vWrE6dOo0ePdqCwUGDY8eOqb9itm7dOicnp2vXrhqfaTTll2mIGt6Ujh07VlZWKi1R9RbmQDPnPHQY1b5MeT6QABAzEiTArsrKyubOnat++dxzz40bN65169ZnzpyZNWvWnDlzlPann3561KhRSUlJFg0Tsdi3b5/6+J133rntttu0PxOmqfZNGTBgQGy9ffzxx/oMS5vQYVT7Mrdu3RraCAD2QoIE2NW0adOUK16EEHl5eY8//rjyuFGjRrNnzz516tTixYuFEEeOHPF6vbfccovy3UOHDr388su7du3as2dPy5Ytu3fvfs899wwdOjS450mTJp0+fVoI8eSTT3799dcrV67ctm1brVq1srOzZ86c+eMf/1gI8cgjj5w5c0YIcfvtt//Xf/2XcmBlZeX48eOVK3BGjRr105/+VAixa9euV1555csvvywpKenWrVtubu6YMWOuv/76ak936tSpWbNmbd++/YEHHnj55ZeFEEuWLFm3bt327dvbtGnzk5/85IUXXpgyZYqyRPbUU0917txZ7Sf8iSJ5UcEOHjxYUFCwY8eOPXv2NG/ePCMjY+zYsYMGDQp+zlVfWk3CvAsnT56cMmXK0aNH1ScvXLhw6dKlv/3tb6sM8qrPjOS9njJlynfffSeEGD58+M9+9jOl8S9/+cuyZcuEECkpKcqDat+jFi1adOzYUe1q9uzZb7zxxsCBAx944IHgU2zZsiU/P//zzz8PM9sxTJQi/IfH7/cvWbJk48aNX3zxRWpqat++fausuKo0fkojeVNef/31b775RggxaNCg+++/X0T8mZw6dap64ObNm5XHNc15bJ/JSCYqeBh33nln6MtcvHhxeXm5+o+SqO6jG3mQVjvJOsZ4JAEe4Xxu2bJl+fLlXq/32LFjdevWve666wYNGvTwww+3atUq/LQDkJcfgD2lpaUpUdyiRYvy8vIq3/3nP/856YqioiKlcenSpY0aNQr9d2DgwIEnTpxQj1V3wBs0aFCVpaf69etv377d7/f3799faenYsaN6YGFhofrMr776yu/3z5kzp06dOlVO16pVK4/HE3q6iRMnqk8ePnz4hQsXlN8jg916663q48LCQrWTq54okhelWrlyZbUTdc8991RU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M7SYtWrSpElX/agAkBOX2IVz4cKF5cuXd+nS5a233po6derq1atTU1NdLpfV4wICateuPXv27E8//TQ3N7fKvcjZ2dmff/75jBkz1Jbk5OSNGzfOnz8/eImgdu3agwYN+sc//hFcX6hawbcgB1OvshNC3Hrrre3bt1e/bNGixe7duydMmBB8R0Hjxo0nT568bt06tYxSTZKSkp5//vm//e1vL7744siRI59++ul169bNmDFDvfJH/WtuzCeq9kWlpKRs2rQpLy9PvRRHeeb48eMLCwubNGmi5YwRvgs1zXaELyHy9/q+++6bM2eOuhFCcnLywIEDV61aFeHZhRBvvfVWcG3QaIdaE40fVyFEhw4dtm3b1q9fP/W8DRs2XL58+Y033hg8Ho2f0mpV+0rVSa6y7cRVjw09sNo5j/mFRDhRocOo9mXW9C5rnGcdYzySAI/8jG+++eYzzzxTZWPD1NTU6dOnL1iwIPyLAiCtJD9brNTsiy++GDFixLRp00aNGqW05OXlvfrqq3/+85/V2nOAJCorK/fs2bN37962bdt26dJF/TFfraNHj3799dctW7bMzMwM/+uaLi5fvnzw4MHS0tLU1NQbbrghwn26nn32WaXky6233jp+/HilceXKleoVLEeOHGnTpo32E4Xh8/n27dvXunXrG264IXhjPV3OaM67EMlZzp49u2vXrosXL/bo0SO4WGfkysvL//3vfycnJ1977bVRJUKR0DhR586d+/LLL5s2bdqlS5cwO7Pp/uExWk1zHvMLiXCiNNI4z/q+TVcN8AjPeOnSpZKSEuWWsDZt2txwww3GTSAAE5AghfPBBx888cQTy5YtU/9a+d577z311FMrVqxQq7wDMMjIkSOVpYzk5ORFixb17t17w4YNCxcu9Pl8Qoif/vSnn3zyidVjBAAA8YZtvsNRanEE34OuPA6u0QHAIFOmTFm7du2pU6cuX77sdDqDv9WiRYu5c+daNTAAABDHuAcpHOXu8OAyHcqCG8tugAl69uxZWFh49913B+9C0bx58//8z//ctWvXzTffbOHYAABAvEqUFaSSkpKioqIBAwaEXl5/+vTpr7/+uqysLDU1tXPnzsF3bSoXu1+4cEFtKS8vF0LEdtsugGhlZWWtX7/++PHjBw4cOHfuXJcuXarcDA0AAKCvREmQFi5cuH79+oyMjCp/dX73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8eOXLVv2ta99rbKycvPmze3t7V/4whey7yMBAAClp5hO8/3MM8+sWrUq++fu7u7BwcGNGzcOH2I3MDAwe/bsgYGBrVu3VlVVZTf29/dfdtll/f39Ize+lYaGhqNHjz722GPDW9rb2++7776dO3cmSXLeeec1NDR89atfPfvss0+yk5tuumnkUXwAAJBTtbW1rsh8GhVTII20ZMmStra2kYHU2dl57bXXXnjhhc8+++zIey5cuPCFF174+c9/fsUVV5zac73yyit9fX1VVVXHXUYWAAAoMcV0iN3J9fb2JkkyefLk47ZPmjQpSZJ9+/ad8p4nTpw4msEAAIBiUXwnaXgr2csTnXj8W/ZUdQMDAynMBAAAFJVSC6QTDQ0NJUni6DgAAOB/Kp1AqqioSJLkyJEjx23v7+8fvhUAAOAkSieQsp816u7uPu60E52dncmbfTYJAADgOKUTSFVVVePGjevr69uxY8fwxt7e3u7u7rKyMld3BQAA/qfSCaTy8vI5c+YkSdLY2Dj8eaRVq1YNDQ3NnDnzggsuSHU6AACgCJTOab6TJFm6dOnWrVvb29vnzp1bW1v74osv9vT0lJWV3X777WmPBgAAFIFifQepvLz8xI0XX3zxhg0bLrnkkr17927evLmnp6eqqurBBx+sra3N/4QAAEDRKTvulAal4eDBg3v27KmsrHSNVwAA4O0rzUA606xYsWL37t3r1q1LexAoKUNDQ+vWrWtra3v55Zerq6vr6+uvvfbatIeCkjIwMPDTn/5027Zt+/fvr66u/vznP3/VVVelPRSUoEwm86UvfWloaGj9+vVpz1IEivUQO7IymcxTTz312GOPHThwIO1ZoNQsW7Zs9erV48aNq6ure/nll2+77bZNmzalPRSUlG9+85tr1qy56KKL5s6du2vXrltuueXpp59OeygoQQ8//PD27dv9uvg2ldRJGs40K1as2LJlS29vb9qDQAnavXt3a2trXV3d6tWrkyT58pe//IlPfGLDhg033HBD2qNBiejp6Xnqqaduuummu+++O0mShQsXfvrTn25tbb3yyivTHg1KSmdn5w9/+MMJEyakPUjREEhFbPr06RUVFUmStLa2lpWVpT0OlJRdu3ZlMpnPfOYz2S8nTJgwc+bM5557Lt2poJTs3LkzSZLhI1dnzJhx3nnnvfbaa6kOBaVmaGjojjvumD9//tGjR/fs2ZP2OMVBIBWx4X/J/vOf//z666+nOwyUmA984AMrV6784Ac/mP1yaGioo6Ojqqoq3amglHz84x//29/+lj0t7eDg4Jo1a44cOTJ//vy054KSsm7duq6urjVr1ixfvjztWYqGQAJ4E9XV1dXV1dk/ZzKZxsbGnp6eb3zjG+lOBSUmW0dNTU0PPfTQ0aNHFyxYMPy2LTB6HR0dzc3Nq1ateve73532LMVEIAGcTG9v77e//e22trb58+d/8YtfTHscKEGXX375+PHjn3nmmSeffPJ973vf0qVL054ISsHg4OC3vvWtOXPm1NXVpT1LkXEWu/R1dnb+8pe/fNPzihw8eLC9vX3Tpk3PPffcvn378j8blIDRLLHf/e53dXV127dvX7p06f333z9mjH9Ugjcxyh9kc+bM+cpXvrJx48bLLrts/fr1DhqH45zaElu3bt1LL71UX1/f0dHR0dFx8ODBvr6+jo6OI0eO5GvwYuWHffqam5u3bNlSU1Mze/bskds3bdq0cuXKQ4cOZb+sqKi49dZbFy9enMaMUMROeYn95je/ueOOOy699NLvf//773//+/M6NBSVU1tl69evb21t3bBhw/jx45MkKSsru/LKK3//+9//4x//mDlzZp5fAhSyU1tiHR0dx44dW7Ro0ciH1NXV/eQnP3FZv5MTSGk6fPjwunXrtmzZcuJNzz///F133ZXJZBYsWFBbW/v3v//9V7/61erVq9/znvdcd911+R8VitFolti+ffvuu+++D3/4w2vXrj3nnHPyPjsUh1H+IPvrX//629/+9vrrrx/+MkmSKVOm5G1+KHCjWWJLliz55Cc/OXz/lpaW7EHjl156af5eQHESSOnYtm1bU1NTV1fXWx1I0NLSkslk6uvr77nnnuyW6urqpqamlpYWgQT/0+iX2ObNmw8fPjx9+vTW1tbhR73rXe+65ppr8jA/FL7Rr7Jrrrkm+/HxnTt3fuQjH2lra2ttbZ03b97EiRPz9zKgUI1+iU2bNm3atGnD93/88cf7+/vnzJmTh+GLnc8gpSOTyQwODl500UVTp0498VMNAwMD7e3tSZLcfPPNwxsbGhrGjh27a9euf//73yfu8Kyz/K+EN4x+ie3YsSNJkocffvjOEb73ve/l8UVAQRv9KquqqmppaZk4ceLatWsXLVr06KOPXn/99U1N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BBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAfrf56wAAAR9JREFUAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAEEgAQAABIEEAAAQBBIAAEAQSAAAAOH/AWb0EiNvbEeOAAAAAElFTkSuQmCC" 24 | }, 25 | "execution_count": 1, 26 | "metadata": {}, 27 | "output_type": "execute_result" 28 | } 29 | ], 30 | "source": [ 31 | "% For various N, set up grid in [-pi,pi] and function u(x):\n", 32 | " Nvec = 2.^(3:12);\n", 33 | " clf, subplot('position',[.1 .4 .8 .5])\n", 34 | " for N = Nvec\n", 35 | " h = 2*pi/N; x = -pi + (1:N)'*h;\n", 36 | " u = exp(sin(x)); uprime = cos(x).*u;\n", 37 | "\n", 38 | " % Construct sparse fourth-order differentiation matrix:\n", 39 | " e = ones(N,1);\n", 40 | " D = sparse(1:N,[2:N 1],2*e/3,N,N)...\n", 41 | " - sparse(1:N,[3:N 1 2],e/12,N,N);\n", 42 | " D = (D-D')/h;\n", 43 | "\n", 44 | " % Plot max(abs(D*u-uprime)):\n", 45 | " error = norm(D*u-uprime,inf);\n", 46 | " loglog(N,error,'.','markersize',15), hold on\n", 47 | " end\n", 48 | " grid on, xlabel N, ylabel error\n", 49 | " title('Convergence of fourth-order finite differences')\n", 50 | " semilogy(Nvec,Nvec.^(-4),'--') \n", 51 | " text(105,5e-8,'N^{-4}','fontsize',18)" 52 | ] 53 | } 54 | ], 55 | "metadata": { 56 | "kernelspec": { 57 | "display_name": "MATLAB Kernel", 58 | "language": "matlab", 59 | "name": "jupyter_matlab_kernel" 60 | }, 61 | "language_info": { 62 | "file_extension": ".m", 63 | "mimetype": "text/x-matlab", 64 | "name": "matlab" 65 | } 66 | }, 67 | "nbformat": 4, 68 | "nbformat_minor": 5 69 | } 70 | -------------------------------------------------------------------------------- /jupyter/p02.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "3fd2453e-69d1-41e5-bb98-1b657c431634", 6 | "metadata": {}, 7 | "source": [ 8 | "# p2.m - convergence of periodic spectral method\n", 9 | "\n", 10 | "Compare this to p1." 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 1, 16 | "id": "31f1a9f3-1b7c-494f-83b5-89bb94352482", 17 | "metadata": { 18 | "tags": [] 19 | }, 20 | "outputs": [ 21 | { 22 | "data": { 23 | "image/png": "iVBORw0KGgoAAAANSUhEUgAABGAAAANICAIAAAAHNA4rAAAAB3RJTUUH5wQLBzUyir0l6AAAIABJREFUeJzs3Xl8FdXd+PETEvY9soSANMBjAlgQECIpIITaSiNQXg+yCUF5pCBKBNwFEVAj2IgoScGFRUFRWbSioEgFRCs0giAW2SQJBGN+EKTEkJCN+/tjhul4t9zczHrn837xx9xzJ2e+Z851XvP1zJwT5nK5BAAAAABAiFpmBwAAAAAAVkGCBAAAAAAyEiQAAAAAkJEgAQAAAICMBAkAAAAAZCRIAAAAACAjQQIAAAAAGQkSAAAAAMhIkAAAAABARoIEAAAAADISJAAAAACQkSABAAAAgIwECQAAAABkJEgAAAAAICNBAgAAAAAZCRIAAAAAyEiQAAAAAEBGggQAAAAAMhIkAAAAAJCRIAEAAACAjAQJAAAAAGQkSAAAAAAgI0ECAAAAABkJEgAAAADISJAAAAAAQEaCBAAAAAAyEiQAAAAAkJEgAQAAAICMBAkAAAAAZCRIAAAAACAjQQIAAAAAGQkSAAAAAMhIkAAAAABARoIEAAAAADISJAAAAACQkSABAAAAgIwECQAAAABkJEgAAAAAICNBAgAAAAAZCRIAAAAAyEiQAAAAAEBGggQAAAAAMhIkAAAAAJCRIAEAAACAjAQJAAAAAGQkSAAAAAAgI0ECAAAAABkJEgAAAADISJAAAAAAQEaCBAAAAAAyEiQAAAAAkJEgAQAAAICMBAkAAAAAZCRIAAAAACAjQQIAAAAAGQkSAAAAAMhIkAAAAABARoIEAAAAALIIswMAYEtXrlw5ceLE0aNH27RpExcX17RpU7MjAgAA0AAjSACqZ+/evYMGDWratGnnzp1HjBhx0003NWvWrF+/fp9//rnZoSF4paWlzzzzTM+ePZs1a9a8efNXXnnF7IiqweVyFV+lYbXdu3dv0KBBgwYNnnzyyer+bbNmzaS/Xblypa+qvJ5zi3eEr1Md3LnStjYA0AojSAACdeXKlUWLFs2bN6+iosLtq6+++mrQoEFz5sx55plnTIkNNTRlypQ1a9YoH3/55RcTg6mun376qW3bttL2zp07Bw0apEm1ly9fLikpEUKUl5dX929LSkrKysqEENJ/LF6r8nrOLd4Rvk51cOdK29oAQCskSAAC9fTTT8+fP19dEhUVVVBQoORLqamp11133Z133mlCcKiBs2fPKjflrVu37tu3b9euXc0NKWhSWmI1HTt2rKysFEK0bt1aKvF6zu3VEepT7dlAc2sDgJogQQIQkNzc3Oeee075+NRTT02ZMqV169ZFRUWpqamLFi2SymfPnj1x4sSwsDCTwkQwjh8/rmyvX7/+5ptvNjGYkPTJJ5+4lXg9519++aVnoS14NtA6tQFAdZEgAQjInDlzpIdehBBpaWkPPfSQtN2oUaOFCxdevHhx+fLlQoi8vLx9+/b16dNH+vbUqVMvvvjit99+e+TIkZYtW3bv3n3YsGFjxoxRqk1JSSksLBRCPPbYY0ePHl2zZk1mZmZERETv3r0XLFjw29/+Vghx3333FRUVCSEGDhz4f//3f9IfVlZWTp06VXoCZ+LEib///e+l8m+//fbVV1/95ptvsrOzu3XrlpCQcPfdd//mN7/xPNzFixdTU1P3798/evToF198UdrhlVde2bJly/79+9u0afO73/3umWeemTVrljRE9vjjj3fu3DmQowTYLkVWVlZGRsaBAweOHDkSGRkZGxs7efLkoUOHunVBlQf1yn8XXLhwYdasWT/99JOy/9KlS1euXPnwww+7BSnZvXv36tWr9+3bd/bs2bp167Zt23bo0KF/+ctfWrVq5dbwRx99dNeuXX//+9+/++67Tp069e3bNyUlxTPaQBrl//zcc889+fn5ys4LFy586623brvtttGjR/vp7osXL7711lubNm06derUhQsXmjZt2qFDh6SkpPvuu69evXr+T6kbl8v1yiuvbNu27euvv46KihowYIDbQKt0NqQghw4desstt3ie8+XLl5eUlCj/iXl2RLV+cp6/bU1+sX5OtbqBo0aNknbwf5KrW5vQ6HoCAFVzAUAAoqOjpYtGixYtSkpK3L794YcfUq7au3evVLhy5cpGjRp5XnZuu+228+fPS/so098NHTrUbdypfv36+/fvd7lcQ4YMkUo6duyoHHHXrl3Knt9//71UuGjRojp16rgdrlWrVnv27HE73PTp05U9x48f73K5SktL1bdikptuuknZ3rVrV4BHCbBdkjVr1ng9S8OGDSsvL1d2C+SgnqrsguzsbM9vhRCffPKJ19pq1fIytU9MTEx2drZbw3v27OkZ7VdffaWuMJBGVXl+vA5Xzpgxw093nzlzRsl13fTp0+fSpUvS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tFsaXBja29v37dtXVVXlPV4BAIB/7sIMpH7o5MmT69ata2pq2r9/f01NzcyZM2fMmJH1UAClpL6+fteuXWvWrMl6EIDSkMvl1qxZs3nz5gMHDtTU1MyaNevBBx/MeqgSUKqX2JWclStX1tfXd3d3T5s27ciRIwsXLvzoo4+yHgqgNOTz+S+//PKTTz75888/s54FoGQsXLhwxYoVQ4cOnT59+oEDB55//vmNGzdmPVQJ8ApSMZw4ceKuu+66/vrrN2zYMGjQoOPHj0+ZMiWl9P3332c9GkB/V19f39TU1NbWllK67bbbNmzYkPVEACVg165dU6dOnTZt2ooVK1JK7e3tU6ZMqays3LRpU9aj9XdeQSqGrVu3dnR0PPLII4MGDUopXXrppdOnTz948ODevXuzHg2gv6utrZ0xY8acOXOqqqrKysqyHgegNOzcuTOfzz/22GOFD4cNGzZu3Di/fP4TF9Rtvvut/fv3p5RGjx7dc1J4fODAgeuuuy6zsQBKwaOPPlp48Msvv5w4cSLbYQBKxc0337x06dJbb7218GEul9uxY0d1dXW2U5UEgVQMx48fTyldfvnlPSeFx4VzAAD4d9XU1NTU1BQe5/P5hoaG1tbWF154IdupSoJAKobCNSG5XK7npPCnX/4ADACA86qtrW3x4sWbN2+ePHnyk08+mfU4JUAgnZvdu3f/+OOPU6dOveKKK057qr29ffv27a2trVVVVbW1tVdeeWXPUxdddFFK6dQrQzo6OlJKF198cVGmBshe7/YnAH3Zn99+++2iRYuOHj06b968p59+urzcDQjOTiCdm7fffrupqemmm2664447Tj3fuHHj0qVLjx49Wvhw8ODBzz333Ny5cwsfjhgxIqW0Z8+eu+++u3CyZ8+ennOAgaB3+xOAXu/Pzz777MUXX7zlllvefPPNG2+8sahDlzKB9E8dO3ZszZo1TU1NZz71008/LVq0KJ/PT506ta6u7tdff12/fv2KFStGjhz50EMPpZTGjh1bXl7+xRdfPP744ymlXC73zTffDB069IYbbij2twFQdH3ZnwADWV/25+HDh5csWXLnnXe+9957rlo6JwLp7H744Yfly5fv3bv3/909afXq1fl8ftasWa+88krhpKamZvny5atXry78gFZWVk6ePPnrr79evHjxPffc89VXX+3YseOJJ54o3PUb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AIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAIJAAgAACAIJAAAgCCQAAIAgkAAAAMJ/AB4siVTnyP1UAAAAAElFTkSuQmCC" 24 | }, 25 | "execution_count": 1, 26 | "metadata": {}, 27 | "output_type": "execute_result" 28 | } 29 | ], 30 | "source": [ 31 | "% For various N (even), set up grid as before:\n", 32 | " clf, subplot('position',[.1 .4 .8 .5])\n", 33 | " for N = 2:2:100;\n", 34 | " h = 2*pi/N;\n", 35 | " x = -pi + (1:N)'*h;\n", 36 | " u = exp(sin(x)); uprime = cos(x).*u;\n", 37 | "\n", 38 | " % Construct spectral differentiation matrix:\n", 39 | " column = [0 .5*(-1).^(1:N-1).*cot((1:N-1)*h/2)];\n", 40 | " D = toeplitz(column,column([1 N:-1:2]));\n", 41 | "\n", 42 | " % Plot max(abs(D*u-uprime)):\n", 43 | " error = norm(D*u-uprime,inf);\n", 44 | " loglog(N,error,'.','markersize',15), hold on\n", 45 | " end\n", 46 | " grid on, xlabel N, ylabel error\n", 47 | " title('Convergence of spectral differentiation')" 48 | ] 49 | } 50 | ], 51 | "metadata": { 52 | "kernelspec": { 53 | "display_name": "MATLAB Kernel", 54 | "language": "matlab", 55 | "name": "jupyter_matlab_kernel" 56 | }, 57 | "language_info": { 58 | "file_extension": ".m", 59 | "mimetype": "text/x-matlab", 60 | "name": "matlab" 61 | } 62 | }, 63 | "nbformat": 4, 64 | "nbformat_minor": 5 65 | } 66 | -------------------------------------------------------------------------------- /jupyter/p03.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "579b9c51-c657-4fb7-81e5-0af54c83afe0", 6 | "metadata": {}, 7 | "source": [ 8 | "# p3.m - band-limited interpolation" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "id": "754bb27f-b673-42ac-9d40-656d3d2f92bb", 15 | "metadata": { 16 | "tags": [] 17 | }, 18 | "outputs": [ 19 | { 20 | "data": { 21 | "image/png": "iVBORw0KGgoAAAANSUhEUgAABGAAAANICAIAAAAHNA4rAAAAB3RJTUUH5wQLBzcwVoUmRgAAIABJREFUeJzs3V+MXGedJ/ynkxASbugOCSDnvXC7POnoFVL02qLDLlLcbSF3lN0I6b0ZUGyhFRJorI2YWeeGC6e6b9iL4H1fMTNeIcEwwdGwsmQklBkv7Qt3G5ldxkIO5GLB4HYZPGEuJtluEMk4Vuzai/P0Sbmq+3R115/nVNXnI190V5erfvXUqXOebz3Pec5YvV4PAAAAhHBP6gIAAADKQkACAACIBCQAAIBIQAIAAIgEJAAAgEhAAgAAiAQkAACASEACAACIBCQAAIBIQAIAAIgEJAAAgEhAAgAAiAQkAACASEACAACIBCQAAIBIQAIAAIgEJAAAgEhAAgAAiAQkAACASEACAACIBCQAAIBIQAIAAIgEJAAAgEhAAgAAiAQkAACASEACAACIBCQAAIBIQAIAAIgEJAAAgEhAAgAAiAQkAACASEACAACIBCQAAIBIQAIAAIgEJAAAgEhAAgAAiAQkAACASEACAACIBCQAAIBIQAIAAIgEJAAAgEhAAgAAiAQkAACASEACAACIBCQAAIBIQAIAAIgEJAAAgEhAAgAAiAQkAACASEACAACIBCQAAIBIQAIAAIgEJAAAgEhAAgAAiAQkAACASEACAACIBCQAAIBIQAIAAIgEJAAAgEhAAgAAiAQkAACASEACAACI7ktdADtx5MiRS5cupa4CAIAymp6ePnXqVOoqBpWANJAuXbp05cqV1FUAAFBGU1NTqUsYYKbYAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQglUWtVvve9773+9//PnUhAAAwuu5LXQDRN77xjbNnzz722GP79+9PXQsAAIwoASm9t99++9vf/vbZs2dTFwIweMaOnc9/rp84mLASAIaDgJTSj370o5deeuk3v/nNu+++m7oWgAHTGI0abxGTAOiEgJRSvV5/7733Hn300RDCb3/72/feey91RQAAMNIs0pDSgQMH/vu6p556KnU5AAOjdfio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RAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAET3pS6AnZienp6amkpdBQAAZTQ9PZ26hAE2Vq/XU9cAAABQCqbYAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAEQCEgAAQCQgAQAARAISAABAJCABAABEAhIAAEAkIAEAAPyf9utYAAAAAGCQv/WeYZRFEyQAAIAJEgAAwAQJAABgggQAADBBAgAAmCABAABMkAAAACZIAAAAEyQAAIAJEgAAwAQJAABgggQAADBBAgAAmCABAABMkAAAACZIAAAAEyQAAIAJEgAAwAQJAABgggQAADBBAgAAmCABAABMkAAAACZIAAAAEyQAAIAJEgAAwAQJAABgggQAADBBAgAAmCABAABMkAAAACZIAAAAEyQAAIAJEgAAwAQJAABgggQAADBBAgAAmCABAABMkAAAACZIAAAAEyQAAIAJEgAAwAQJAABgggQAADBBAgAAmCABAABMkAAAABbUApVrjuv13gAAAABJRU5ErkJggg==" 22 | }, 23 | "execution_count": 1, 24 | "metadata": {}, 25 | "output_type": "execute_result" 26 | } 27 | ], 28 | "source": [ 29 | "h = 1; xmax = 10; clf\n", 30 | "x = -xmax:h:xmax; % computational grid\n", 31 | "xx = -xmax-h/20:h/10:xmax+h/20; % plotting grid\n", 32 | "for plt = 1:3\n", 33 | "subplot(4,1,plt)\n", 34 | "switch plt\n", 35 | " case 1, v = (x==0); % delta function\n", 36 | " case 2, v = (abs(x)<=3); % square wave\n", 37 | " case 3, v = max(0,1-abs(x)/3); % hat function\n", 38 | "end\n", 39 | "plot(x,v,'.','markersize',14), grid on\n", 40 | "p = zeros(size(xx));\n", 41 | "for i = 1:length(x),\n", 42 | " p = p + v(i)*sin(pi*(xx-x(i))/h)./(pi*(xx-x(i))/h);\n", 43 | "end\n", 44 | "line(xx,p), axis([-xmax xmax -.5 1.5])\n", 45 | "set(gca,'xtick',[]), set(gca,'ytick',[0 1])\n", 46 | "end" 47 | ] 48 | } 49 | ], 50 | "metadata": { 51 | "kernelspec": { 52 | "display_name": "MATLAB Kernel", 53 | "language": "matlab", 54 | "name": "jupyter_matlab_kernel" 55 | }, 56 | "language_info": { 57 | "file_extension": ".m", 58 | "mimetype": "text/x-matlab", 59 | "name": "matlab" 60 | } 61 | }, 62 | "nbformat": 4, 63 | "nbformat_minor": 5 64 | } 65 | -------------------------------------------------------------------------------- /jupyter/p04.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "1d4b0024-5d20-48d6-a23c-76d1efa0fed0", 6 | "metadata": {}, 7 | "source": [ 8 | "# p4.m - periodic spectral differentiation" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "id": "0d0bc40b-f77e-474a-8116-b38f1129d0d5", 15 | "metadata": { 16 | "tags": [] 17 | }, 18 | "outputs": [ 19 | { 20 | "data": { 21 | "image/png": "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qffff//1118PCgpKT09v06bNpk2bCgsLx48f37lz5/vuu6/xh4ZTkSABAODxGEsJBZ05c2bBggUqlWr79u09e/YUQkycOHH8+PEffvhhTk7OJ598YvZVS5Ys2bNnT9++fXfs2NG0aVMhxEMPPTR48OC1a9e+++67KpVKeuGsWbNee+01IcT48ePT09PffffdVatWjR07tk2bNmvXrjXa54wZM4QQL7/8clJSkhDC+h4ac8r//Oc/Z86c+dNPP9XU1Jjd4PXXXxdCfPXVVwMHDhRCZGRk3Hfffbt37/7ss89IkNwfkzTAvVhpCGp8Fzin7hwA3JDZrsVW+hv7YDP7G2+8kZ6ertVq33vvvSeeeKJv377Tp08/ffq0EGLt2rWjRo3q1avXn//8508//dTwVeXl5bNnz37ooYd69uw5YMCA6dOnnzypn1j1H//4x9SpU1988UW5s5kQYs2aNVOnTn3vvfesRLJu3bqxY8fed99948aNW7lyZW1trVSemZk5e/ZsIcTXX389efJk6Ze92UJ5PxMnTvzDH/7wyCOPzJkzp7y8XH7KyqsaY+/evVqt9ve//72UHUlefvllIcRnn31maZjQmjVrhBDvv/++lB0JIR566KG8vLzMzEypW9r58+eFEPfee6/8kgEDBgghLl26ZHaHq1evfuutt4YOHZqTkyOV2LgHS1feCp1OV1dXFxkZmZCQ4O/vb/TsuXPnzp07Fx8fL2VHkr/85S9CCPl9AndGCxIAAJ7NSlYjzfxp+/Y+aMWKFaWlpadPn/7iiy/8/Py0Wu2//vWvb775pl+/flJHryZNmhQXF3/++ecffPDBM888I4Q4ePBgv379fvnlFyFEYGBgTU1NUVHRqlWr9u/fHx4eft999z377LM///xzixYtMjMzhRB79ux5+umn6+vrCwsLzcZQU1MzYsSIDRs2CCH8/Px27969dOnSdevWbdiwoVmzZsuWLbt+/frdd9+dlpYmhJDaH8wWXrt2bcSIEV9++aW0H61W++WXX77zzjurVq0aPHiwpVc13tmzZ4UQHTt2NCz83e9+J4Sora09f/58WFiY6Uv27dsXHR191113Xb16taSkpLa2tkePHhMnTpS3GThw4M6dOzdt2vSnP/1JKpHS1AceeMA0hnPnzj377LMtW7ZctmyZSqWycQ/Wr7yVUx48eLB0SYUQDz/88MaNGw2fbdq06ZIlSyIiIv5/e/ceXVV554//SVEuIhpUQGCqJNEAg1bEirZTJdDWLFnam7UdFfn1O8vSVertW7QXGUzi1AvVVFsotRU7eGnrtMuv1Xpp/LYS7QxaRrHeQNQQBNRpRYkIiEA4vz/29nzT5JxwS84+l9dr+Qfsc3L4uHPy5Lz3fp7P0/Hgo48+GkKoqanp5mXJE+4gkV8amlrrMy0s7qlp8Rlfp/60io4rmwGKRtT5s9N/NR80AiXtD3/4w1133bVp06aWlpYjjjjimWeemTdv3je+8Y3nnntuy5Yt0af2RYsWRU/+zne+884773z2s59duXLle++9t3r16mOOOeZvf/vbww8/HEL4h3/4h3//938PIfzbv/3bsmXLNm/efO65527fvv2qq6465ZRTMv7rc+fOvfvuuydOnPjcc89t27Zt2bJl48ePf+CBB6K7PSGEtra2Cy64YMyYMfPmzfvBD36Q7eDVV1997733Dhs27He/+9177723bt268847b8OGDeedd95bb73VzUvto8rKyhDCc8891/Hg888/H/0huh3XyWuvvRZCOPbYYy+77LLBgwd/8pOfPP3004cPHz59+vR0Q4UZM2ZMmDBh4cKFn/rUp77zne9MmDDhF7/4xdixYy+99NKuL/jd735306ZNl1122ZAhQ9IHd/kKuzzze2fIkCEzZsw444wzQghLliy59dZbTz/99Hvuuef4448/99xz9+WVyZEUBai6ujrpEnpFzY+fqv/9qkT+6frfr6r58VMdj7S2tiZSSUlxknNgL05ysY4weaVnT/LiVzaEb/4x43+dRrZIzY+fyvb8Hqwqcbv55h87dmwIYd68eekjV1xxRQjhwx/+cHt7e3Qk+og/cuTI6K8nnHDCkUce+fLLL6e/5Nvf/nYIob6+Pn3k4osvDiGMGzfu/PPPDyGcdtppO3fuzFjAxo0bBwwYcOCBB77xxhvpg2vWrBkwYMAhhxyydevW6EbECSecsGXLlvQTuh7csGFD//79Qwh/+MMfOr7+ySefHEL413/914xf1cmLL774oW6tWvV3v6ajk/zmm29GfecaGxuj4++++240mS2EcN9993X9h+6///4QQp8+fUIIn/rUp66++uqLL744epF//ud/jp6zY8eOaCVPR1deeWX6+5K2dOnSsrKyoUOHvvvuux2Pd/8KuzzzGU9RV2eeeWYI4U9/+lPGR0899dT0Px1NONwLRvIcM8WOfDF5wbIEr2vW1VZMahk8ecGyjJ3EAfJTc0tbQ1N3SxoyjmmLZ07I1tSh4eHWXfYHL0rRxf5IdAvii1/84oc+FE+0Oeyww0IIqQ/W0jz55JPRX1etWrVixYqlS5f+7Gc/6/SC3//+9//0pz89/fTTL7zwwvDhw++88870vK9Oli9f/t5771VVVUWZIa28vPyNN97485//HP31u9/97oABAzp9bceDy5cv37p165gxYz75yU92fM43vvGNJ554YtmyZRm/qpODDz74ggsuyPhQJOMXHnbYYVdcccW//uu/zpo16+67766oqHj00Uf/53/+55BDDnn77bcHDx7c9Us2bdoUQmhvb//617++YMGC6GC04uuuu+6aPXv2Mccc87Wvfe3WW2894IADLrzwwuOPP/7FF1+86aabrrrqqqeeeqrTufr+97+fSqUuvPDCAw88sOPx7l9hl2f+uOOO+853vtPpoWuvvbab89PV3LlzX3vttaeffnrevHlf+MIXvvnNbzY2Nu7RK5B7AhJ5Idl0FKmpKg+1lTISkFeybW2UjkbpwbNr5ulmcnLGXbZTjVMamlrLZj2yeOaEUpuGF917iURJ5uCDD8725FdffbWhoeHee+99++23oyN9+/bt9Jx+/fp997vf/dKXvhRCOPPMMzvO++rkpZdeCiG0tLREC5w6iaaihRDGjx/f9dGOB1evXh1CqKjonG+POuqo6PUzflUnhx9++E9/+tNsj3Zj9uzZQ4YMaWhoWLJkyZIlS8aMGfPLX/7y+uuvf/vttzNuzJpOTemGCiGEE044oba29sEHH3zqqadGjx7961//+kMf+tBDDz2Uvglz9tlnn3jiiQ888MBrr702cuTI6OCGDRuiJUDnnHNOx39i+/bt3b/CLs98RUXFzTff3PHgiBEj9jQgRXfwzjrrrDPOOOOf/umffvrTn1577bVd3zDkFQGJ5OVDOorISED+6Bpg6ptaU41TukajyC53ze4kY3yqq62IttV+9KjBpXkraZc2bdo0ZcqUVatWnXTSSdOnTz/22GOjMNBpYczmzZujNm4hhIULF5577rmTJk3K+IJRdho/fnynmxWRiRMnRn/o2ueg08Eo0UWtIzqKUtwhhxyS8at60IwZM2bMmLF+/fr3339/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fPLJ2bNnp1KpqVOnTpw4ccWKFb/+9a8bGxuHDx9+5plnJl0dALt21113XXvttfvtt9/06dOPPvropUuX3n///VdfffWQIUNOP/30pKsDYI9Zg5Skn/zkJ6lU6rzzzrvxxhvPOeecq6666rLLLouOJ10a4Y477ki6hOLnJOeAk9yr2tvb58+fH0K47rrrZs+e/aUvfemGG26YOXNmcObzgG9BDjjJueE855iAlJht27YtXbo0hHDBBRekD06bNq1///4tLS2vv/56cqURQgh33nln0iUUPyc5B5zkXrVu3br169ePGDHijDPOSB8866yzQggrVqxIri5C8ObPCSc5N5znHBOQEvPaa69t27ZtyJAhI0aMSB/s37//mDFjQgitra3JlQbAbtmyZUtlZeXHPvaxsrKy9MGNGzeGEAYNGpRcXQDsPWuQErN+/foQwrBhwzodHzp0aAjhrbfeSqAmAPbE2LFjH3rooU4Hb7vtthDCcccdl0RFAOwrASkxO3fuDCHsv//+nY7369cvhJDuhpTRxIkTR48e3Xu1EXGSc8BJzoE9PckTJ07spUqK3s6dO2+44YZ77rln//33v+SSS7p5pmE8N5zkHHCSc8NInksCUmKigNRVe3t7CKHjbI2urNUDyKV33323sbGx45FBgwbNmjWr45GWlpbZs2c//fTTAwYMmDdv3lFHHdXNCxrGAfKWgJSYvn37hhC2bNnS6fjWrVvTjwKQDzZt2vSrX/2q45GhQ4emA1J7e/vChQvnz5+/bdu28ePHz507d9SoUQlUCUBPEJASE601WrNmTSqV6ni/KGrP0HVtEgBJOfTQQ3/xi190PDJw4MDoD9u3b581a1ZTU9OgQYPmzJlz9tlndz8FAIA8JyAlZsSIEQMHDty8efMLL7xwzDHHRAfXr1+/Zs2asrKyysrKZMsDIK1v374f/ehHMz504403NjU1HX300bfccsvw4cNzXBgAPU6b78T06dPnlFNOCSHMnTs3vR7puuuua29v/8hHPnLYYYclWh0Au/bGG2/cfvvtBxxwwKJFi6QjgOJQlkqlkq6hdLW2tn72s599//33hwwZMnHixGeffXbt2rVlZWW333673iMA+e+3v/3tt7/97QEDBhx//PGdHho+fPg111yTSFUA7AtT7JJUUVGxaNGiK6+88uWXX37ggQdCCCNGjJgzZ450BFAQli9fHkJ47733lixZ0umhI488MomKANhX7iABAADErEECAACICUgAAAAxAQkAACAmIAEAAMT61NfXJ10Du2vjxo3PPPPME088sWHDhoEDBx5wwAFJV1SENm7c+Je//OWJJ5545513Dj744H79+iVdUTF7880377vvvrKysqFDhyZdSxF65513/vSnP0Vt1mytlicM4zlgGM8xI3mvMpInQpvvgnH33Xdfc801mzZtiv7at2/fiy66aMaMGclWVUxSqdRtt93W2Ni4bdu26MiBBx54ySWXTJ8+PdnCilUqlfrWt761ZMmSiy666Jhjjkm6nKLS1tY2c+bMZcuWpfuU1tTU3HTTTQMGDEi2sBJnGO9thvHcM5L3HiN5gtxBKgxPPvnkhRdeuG3btqlTp5533nnDhg177rnnlixZMmrUqNGjRyddXZG46667vve975WVlU2bNu2LX/zigQce+MILLzz22GNHHXXU0UcfnXR1ReiOO+745S9/GUI46aST7P3VgzZv3vyVr3zlmWeeGTdu3LnnnltdXb1mzZoXX3xx06ZNkyZNSrq60mUYzwHDeO4ZyXuJkTxhKQrBv/zLv1RXVzc0NKSP3HLLLdXV1aeffnqCVRWTHTt2fPzjH6+urr7vvvvSB3/4wx9WV1efc845CRZWrF566aVjjz12/Pjx1dXV8+bNS7qcorJw4cLq6upzzz13x44d0ZFHH320urr6pJNO2rlzZ7K1lTLDeG8zjOeekbz3GMmTpUlDAdi2bdvSpUtDCBdccEH64LRp0/r379/S0vL6668nV1rxWLdu3fr160eMGHHGGWekD5511lkhhBUrViRXV3Havn375ZdfPnDgwMsuuyzpWorQ/fffH0JoaGjo06dPdOTUU0+tr6+fOXPmzp07Ey2tdBnGc8AwnmNG8l5lJE+WNUgF4LXXXtu2bduQIUNGjBiRPti/f/8xY8b85S9/aW1t7XicvbNly5bKysrjjz++rKwsfXDjxo0hhEGDBiVXV3G66aabVqxYMX/+/B07diRdS7H529/+tnz58g9/+MNHHXXUpk2bnn/++e3bt48dO/acc85JurSSZhjPAcN4jhnJe4+RPHECUgFYv359CGHYsGGdjkftYt56660Eaio6Y8eOfeihhzodvO2220IIxx13XBIVFa2lS5f+/Oc//8xnPvPpT3+66zlnH/31r38NIVRXV8+dO3fRokXpC42f/exn6+rqBg4cmGh1pcswngOG8VwykvcqI3niBKQCEP1g7L///p2OR61L07166EE7d+684YYb7rnnnv333/+SSy5Jupzi8e677377298eMmTInDlzkq6lOEUftZubm9vb2z/+8Y+fdNJJb7311m9+85t77713x44dP/jBD5IusEQZxnPPMN57jOS9zUieOAGpAGSbbNre3h5C6DiXgB7R0tIye/bsp59+esCAAfPmzTvqqKOSrqh4XHXVVa+//vrChQsPOuigpGspTlu2bAkhtLe3n3POOekmpZ/73OfOPvvsBx544Otf/7peXokwjOeYYbxXGcl7m5E8cZo0FIC+ffuGD35aOtq6dWv6UXpEe3v7T3/608997nNPP/30+PHjf/vb355yyilJF1U8mpqa7rvvvjPOOGPChAmbN2/evHnz+++/H0LYvn375s2bzWLvEenPKxdffHH64Lhx4z7xiU+EEJ5//vlkyip5hvGcMYz3NiN5DhjJE+cOUgGIJqmvWbMmlUp1vNDY2toaMk1qZ+9s37591qxZTU1NgwYNmjNnztlnn+2ybs9atmxZCOH++++PmvOk3XzzzTfffHNdXd25556bUGnFY/DgwSGEAQMGHHLIIR2PRz0A3nzzzWTKKnmG8dwwjOeAkTwHjOSJE5AKwIgRIwYOHLh58+YXXnghvU31+vXr16xZU1ZWVllZmWx5RePGG29samo6+uijb7nlluHDhyddThE69thjP/3pT3c8snbt2hdffLGqqqqysvLDH/5wUoUVkzFjxhx00EEbN2584403Or6NX3nllRDCyJEjkyutpBnGc8MwngNG8hwwkicv6Y2Y2C0XX3xxdXX1tGnT2tvboyOzZs2qrq4+++yzky2saLz++uvjxo0bP378m2++mXQtJeTBBx+0vWCPu/zyy6urqy+++OLt27dHR/7whz9UV1cfd9xx3t4JMoz3NsN4UozkvcFInix3kArDpZdeunjx4qVLl5566qkTJ0589tln165dW1ZWZne2nvLnP/95+/bt++233+WXX97poeHDh19zzTWJVAV7YdasWf/93//9+9//vqWl5aSTTvrrX//6xz/+MYTwta997bDDDku6utJlGO9thnGKiZE8WQJSYaioqFi0aNGVV1758ssvP/DAAyGEESNGzJkzZ+LEiUmXViSWL18eQnjvvfeWLFnS6aEjjzwyiYpKQrRBeHqbcHrEsGHDFi5cOHfu3CeffPLOO+8MIYwcOfIb3/jGWWedlXRpJc0w3tsM40kxkvcGI3myylKpVNI1sAc2bty4bt26ww8/vNO6PYBO2tvbW1pahg0bdvDBByddC/+PYRzYfUbyRAhIAAAAMfsgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxATqiGlLAAAFq0lEQVQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACAmIAEAAAQE5AAAABiAhIAAEBMQAIAAIgJSAAAADEBCQAAICYgAQAAxAQkAACA2P8PxrHMHHIfLzkAAAAASUVORK5CYII=" 22 | }, 23 | "execution_count": 1, 24 | "metadata": {}, 25 | "output_type": "execute_result" 26 | } 27 | ], 28 | "source": [ 29 | "% Set up grid and differentiation matrix:\n", 30 | "N = 24; h = 2*pi/N; x = h*(1:N)';\n", 31 | "column = [0 .5*(-1).^(1:N-1).*cot((1:N-1)*h/2)]';\n", 32 | "D = toeplitz(column,column([1 N:-1:2]));\n", 33 | "\n", 34 | "% Differentiation of a hat function:\n", 35 | "v = max(0,1-abs(x-pi)/2); clf\n", 36 | "subplot(3,2,1), plot(x,v,'.-','markersize',13)\n", 37 | "axis([0 2*pi -.5 1.5]), grid on, title('function')\n", 38 | "subplot(3,2,2), plot(x,D*v,'.-','markersize',13)\n", 39 | "axis([0 2*pi -1 1]), grid on, title('spectral derivative')\n", 40 | "\n", 41 | "% Differentiation of exp(sin(x)):\n", 42 | "v = exp(sin(x)); vprime = cos(x).*v;\n", 43 | "subplot(3,2,3), plot(x,v,'.-','markersize',13)\n", 44 | "axis([0 2*pi 0 3]), grid on\n", 45 | "subplot(3,2,4), plot(x,D*v,'.-','markersize',13)\n", 46 | "axis([0 2*pi -2 2]), grid on\n", 47 | "error = norm(D*v-vprime,inf);\n", 48 | "text(2.2,1.4,['max error = ' num2str(error)])" 49 | ] 50 | } 51 | ], 52 | "metadata": { 53 | "kernelspec": { 54 | "display_name": "MATLAB Kernel", 55 | "language": "matlab", 56 | "name": "jupyter_matlab_kernel" 57 | }, 58 | "language_info": { 59 | "file_extension": ".m", 60 | "mimetype": "text/x-matlab", 61 | "name": "matlab" 62 | } 63 | }, 64 | "nbformat": 4, 65 | "nbformat_minor": 5 66 | } 67 | -------------------------------------------------------------------------------- /leg.m: -------------------------------------------------------------------------------- 1 | 2 | x = x(:); M = length(x); a = zeros(M,1); D = zeros(M,M); 3 | for k = 1:M; a(k) = prod(x(k)-x([1:k-1 k+1:M])); end 4 | for j = 1:M; t = x(:)-x(j); t(j) = 1; D(:,j) = 1./t; end 5 | A = diag(a); D = A*D/A; 6 | for j = 1:M 7 | sum = 0; 8 | for k = [1:j-1 j+1:M]; 9 | sum = sum + 1/(x(j)-x(k)); 10 | end 11 | D(j,j) = sum; 12 | end 13 | -------------------------------------------------------------------------------- /p01.m: -------------------------------------------------------------------------------- 1 | % p1.m - convergence of fourth-order finite differences 2 | 3 | % For various N, set up grid in [-pi,pi] and function u(x): 4 | Nvec = 2.^(3:12); 5 | clf, subplot('position',[.1 .4 .8 .5]) 6 | for N = Nvec 7 | h = 2*pi/N; x = -pi + (1:N)'*h; 8 | u = exp(sin(x)); uprime = cos(x).*u; 9 | 10 | % Construct sparse fourth-order differentiation matrix: 11 | e = ones(N,1); 12 | D = sparse(1:N,[2:N 1],2*e/3,N,N)... 13 | - sparse(1:N,[3:N 1 2],e/12,N,N); 14 | D = (D-D')/h; 15 | 16 | % Plot max(abs(D*u-uprime)): 17 | error = norm(D*u-uprime,inf); 18 | loglog(N,error,'.','markersize',15), hold on 19 | end 20 | grid on, xlabel N, ylabel error 21 | title('Convergence of fourth-order finite differences') 22 | semilogy(Nvec,Nvec.^(-4),'--') 23 | text(105,5e-8,'N^{-4}','fontsize',18) 24 | -------------------------------------------------------------------------------- /p02.m: -------------------------------------------------------------------------------- 1 | % p2.m - convergence of periodic spectral method (compare p1.m) 2 | 3 | % For various N (even), set up grid as before: 4 | clf, subplot('position',[.1 .4 .8 .5]) 5 | for N = 2:2:100; 6 | h = 2*pi/N; 7 | x = -pi + (1:N)'*h; 8 | u = exp(sin(x)); uprime = cos(x).*u; 9 | 10 | % Construct spectral differentiation matrix: 11 | column = [0 .5*(-1).^(1:N-1).*cot((1:N-1)*h/2)]; 12 | D = toeplitz(column,column([1 N:-1:2])); 13 | 14 | % Plot max(abs(D*u-uprime)): 15 | error = norm(D*u-uprime,inf); 16 | loglog(N,error,'.','markersize',15), hold on 17 | end 18 | grid on, xlabel N, ylabel error 19 | title('Convergence of spectral differentiation') 20 | -------------------------------------------------------------------------------- /p03.m: -------------------------------------------------------------------------------- 1 | % p3.m - band-limited interpolation 2 | 3 | h = 1; xmax = 10; clf 4 | x = -xmax:h:xmax; % computational grid 5 | xx = -xmax-h/20:h/10:xmax+h/20; % plotting grid 6 | for plt = 1:3 7 | subplot(4,1,plt) 8 | switch plt 9 | case 1, v = (x==0); % delta function 10 | case 2, v = (abs(x)<=3); % square wave 11 | case 3, v = max(0,1-abs(x)/3); % hat function 12 | end 13 | plot(x,v,'.','markersize',14), grid on 14 | p = zeros(size(xx)); 15 | for i = 1:length(x), 16 | p = p + v(i)*sin(pi*(xx-x(i))/h)./(pi*(xx-x(i))/h); 17 | end 18 | line(xx,p), axis([-xmax xmax -.5 1.5]) 19 | set(gca,'xtick',[]), set(gca,'ytick',[0 1]) 20 | end 21 | -------------------------------------------------------------------------------- /p04.m: -------------------------------------------------------------------------------- 1 | % p4.m - periodic spectral differentiation 2 | 3 | % Set up grid and differentiation matrix: 4 | N = 24; h = 2*pi/N; x = h*(1:N)'; 5 | column = [0 .5*(-1).^(1:N-1).*cot((1:N-1)*h/2)]'; 6 | D = toeplitz(column,column([1 N:-1:2])); 7 | 8 | % Differentiation of a hat function: 9 | v = max(0,1-abs(x-pi)/2); clf 10 | subplot(3,2,1), plot(x,v,'.-','markersize',13) 11 | axis([0 2*pi -.5 1.5]), grid on, title('function') 12 | subplot(3,2,2), plot(x,D*v,'.-','markersize',13) 13 | axis([0 2*pi -1 1]), grid on, title('spectral derivative') 14 | 15 | % Differentiation of exp(sin(x)): 16 | v = exp(sin(x)); vprime = cos(x).*v; 17 | subplot(3,2,3), plot(x,v,'.-','markersize',13) 18 | axis([0 2*pi 0 3]), grid on 19 | subplot(3,2,4), plot(x,D*v,'.-','markersize',13) 20 | axis([0 2*pi -2 2]), grid on 21 | error = norm(D*v-vprime,inf); 22 | text(2.2,1.4,['max error = ' num2str(error)]) 23 | -------------------------------------------------------------------------------- /p05.m: -------------------------------------------------------------------------------- 1 | % p5.m - repetition of p4.m via FFT 2 | % For complex v, delete "real" commands. 3 | 4 | % Differentiation of a hat function: 5 | N = 24; h = 2*pi/N; x = h*(1:N)'; 6 | v = max(0,1-abs(x-pi)/2); v_hat = fft(v); 7 | w_hat = 1i*[0:N/2-1 0 -N/2+1:-1]' .* v_hat; 8 | w = real(ifft(w_hat)); clf 9 | subplot(3,2,1), plot(x,v,'.-','markersize',13) 10 | axis([0 2*pi -.5 1.5]), grid on, title('function') 11 | subplot(3,2,2), plot(x,w,'.-','markersize',13) 12 | axis([0 2*pi -1 1]), grid on, title('spectral derivative') 13 | 14 | % Differentiation of exp(sin(x)): 15 | v = exp(sin(x)); vprime = cos(x).*v; 16 | v_hat = fft(v); 17 | w_hat = 1i*[0:N/2-1 0 -N/2+1:-1]' .* v_hat; 18 | w = real(ifft(w_hat)); 19 | subplot(3,2,3), plot(x,v,'.-','markersize',13) 20 | axis([0 2*pi 0 3]), grid on 21 | subplot(3,2,4), plot(x,w,'.-','markersize',13) 22 | axis([0 2*pi -2 2]), grid on 23 | error = norm(w-vprime,inf); 24 | text(2.2,1.4,['max error = ' num2str(error)]) 25 | -------------------------------------------------------------------------------- /p06.m: -------------------------------------------------------------------------------- 1 | % p6.m - variable coefficient wave equation 2 | 3 | % Grid, variable coefficient, and initial data: 4 | N = 128; h = 2*pi/N; x = h*(1:N); t = 0; dt = h/4; 5 | c = .2 + sin(x-1).^2; 6 | v = exp(-100*(x-1).^2); vold = exp(-100*(x+.2*dt-1).^2); 7 | 8 | % Time-stepping by leap frog formula: 9 | tmax = 8; tplot = .15; clf, drawnow, set(gcf,'renderer','zbuffer') 10 | plotgap = round(tplot/dt); dt = tplot/plotgap; 11 | nplots = round(tmax/tplot); 12 | data = [v; zeros(nplots,N)]; tdata = t; 13 | for i = 1:nplots 14 | for n = 1:plotgap 15 | t = t+dt; 16 | v_hat = fft(v); 17 | w_hat = 1i*[0:N/2-1 0 -N/2+1:-1] .* v_hat; 18 | w = real(ifft(w_hat)); 19 | vnew = vold - 2*dt*c.*w; vold = v; v = vnew; 20 | end 21 | data(i+1,:) = v; tdata = [tdata; t]; 22 | end 23 | waterfall(x,tdata,data), view(10,70), colormap(1e-6*[1 1 1]); 24 | axis([0 2*pi 0 tmax 0 5]), ylabel t, zlabel u, grid off 25 | -------------------------------------------------------------------------------- /p06u.m: -------------------------------------------------------------------------------- 1 | % p6u.m - variable coefficient wave equation - UNSTABLE VARIANT 2 | 3 | % Grid, variable coefficient, and initial data: 4 | N = 128; h = 2*pi/N; x = h*(1:N); 5 | c = .2 + sin(x-1).^2; 6 | t = 0; dt = 1.9/N; 7 | v = exp(-100*(x-1).^2); 8 | vold = exp(-100*(x+.2*dt-1).^2); 9 | 10 | % Time-stepping by leap frog formula: 11 | tmax = 8; tplot = .15; clf, set(gcf,'renderer','zbuffer') 12 | plotgap = round(tplot/dt); 13 | nplots = round(tmax/tplot); 14 | data = [v; zeros(nplots,N)]; tdata = t; 15 | for i = 1:nplots 16 | for n = 1:plotgap 17 | t = t+dt; 18 | v_hat = fft(v); 19 | w_hat = 1i*[0:N/2-1 0 -N/2+1:-1] .* v_hat; 20 | w = real(ifft(w_hat)); 21 | vnew = vold - 2*dt*c.*w; % leap frog formula 22 | vold = v; v = vnew; 23 | end 24 | data(i+1,:) = v; tdata = [tdata; t]; 25 | if max(abs(v)>2.5), data = data(1:i+1,:); break, end 26 | end 27 | 28 | % Plot results: 29 | waterfall(x,tdata,data) 30 | axis([0 2*pi 0 tmax -3. 3.]), view(10,70), grid off 31 | colormap(1e-6*[1 1 1]); xlabel x, ylabel t, zlabel u 32 | -------------------------------------------------------------------------------- /p07.m: -------------------------------------------------------------------------------- 1 | % p7.m - accuracy of periodic spectral differentiation 2 | 3 | % Compute derivatives for various values of N: 4 | Nmax = 50; E = zeros(3,Nmax/2-2); 5 | for N = 6:2:Nmax; 6 | h = 2*pi/N; x = h*(1:N)'; 7 | column = [0 .5*(-1).^(1:N-1).*cot((1:N-1)*h/2)]'; 8 | D = toeplitz(column,column([1 N:-1:2])); 9 | v = abs(sin(x)).^3; % 3rd deriv in BV 10 | vprime = 3*sin(x).*cos(x).*abs(sin(x)); 11 | E(1,N/2-2) = norm(D*v-vprime,inf); 12 | v = exp(-sin(x/2).^(-2)); % C-infinity 13 | vprime = .5*v.*sin(x)./sin(x/2).^4; 14 | E(2,N/2-2) = norm(D*v-vprime,inf); 15 | v = 1./(1+sin(x/2).^2); % analytic in a strip 16 | vprime = -sin(x/2).*cos(x/2).*v.^2; 17 | E(3,N/2-2) = norm(D*v-vprime,inf); 18 | v = sin(10*x); vprime = 10*cos(10*x); % band-limited 19 | E(4,N/2-2) = norm(D*v-vprime,inf); 20 | end 21 | 22 | % Plot results: 23 | titles = {'|sin(x)|^3','exp(-sin^{-2}(x/2))',... 24 | '1/(1+sin^2(x/2))','sin(10x)'}; clf 25 | for iplot = 1:4 26 | subplot(2,2,iplot) 27 | semilogy(6:2:Nmax,E(iplot,:),'.','markersize',12) 28 | line(6:2:Nmax,E(iplot,:)) 29 | axis([0 Nmax 1e-16 1e3]), grid on 30 | set(gca,'xtick',0:10:Nmax,'ytick',(10).^(-15:5:0)) 31 | xlabel N, ylabel error, title(titles(iplot)) 32 | end 33 | -------------------------------------------------------------------------------- /p08.m: -------------------------------------------------------------------------------- 1 | % p8.m - eigenvalues of harmonic oscillator -u"+x^2 u on R 2 | 3 | format long, format compact 4 | L = 8; % domain is [-L L], periodic 5 | for N = 6:6:36 6 | h = 2*pi/N; x = h*(1:N); x = L*(x-pi)/pi; 7 | column = [-pi^2/(3*h^2)-1/6 ... 8 | -.5*(-1).^(1:N-1)./sin(h*(1:N-1)/2).^2]; 9 | D2 = (pi/L)^2*toeplitz(column); % 2nd-order differentiation 10 | eigenvalues = sort(eig(-D2 + diag(x.^2))); 11 | N, eigenvalues(1:4) 12 | end 13 | -------------------------------------------------------------------------------- /p09.m: -------------------------------------------------------------------------------- 1 | % p9.m - polynomial interpolation in equispaced and Chebyshev pts 2 | 3 | N = 16; 4 | xx = -1.01:.005:1.01; clf 5 | for i = 1:2 6 | if i==1, s = 'equispaced points'; x = -1 + 2*(0:N)/N; end 7 | if i==2, s = 'Chebyshev points'; x = cos(pi*(0:N)/N); end 8 | subplot(2,2,i) 9 | u = 1./(1+16*x.^2); 10 | uu = 1./(1+16*xx.^2); 11 | p = polyfit(x,u,N); % interpolation 12 | pp = polyval(p,xx); % evaluation of interpolant 13 | plot(x,u,'.','markersize',13) 14 | line(xx,pp) 15 | axis([-1.1 1.1 -1 1.5]), title(s) 16 | error = norm(uu-pp,inf); 17 | text(-.5,-.5,['max error = ' num2str(error)]) 18 | end 19 | -------------------------------------------------------------------------------- /p10.m: -------------------------------------------------------------------------------- 1 | % p10.m - polynomials and corresponding equipotential curves 2 | 3 | N = 16; clf 4 | for i = 1:2 5 | if i==1, s = 'equispaced points'; x = -1 + 2*(0:N)/N; end 6 | if i==2, s = 'Chebyshev points'; x = cos(pi*(0:N)/N); end 7 | p = poly(x); 8 | 9 | % Plot p(x) over [-1,1]: 10 | xx = -1:.005:1; pp = polyval(p,xx); 11 | subplot(2,2,2*i-1) 12 | plot(x,0*x,'.','markersize',13), hold on 13 | plot(xx,pp), grid on 14 | set(gca,'xtick',-1:.5:1), title(s) 15 | 16 | % Plot equipotential curves: 17 | subplot(2,2,2*i) 18 | plot(real(x),imag(x),'.','markersize',13), hold on 19 | axis([-1.4 1.4 -1.12 1.12]) 20 | xgrid = -1.4:.02:1.4; ygrid = -1.12:.02:1.12; 21 | [xx,yy] = meshgrid(xgrid,ygrid); zz = xx+1i*yy; 22 | pp = polyval(p,zz); levels = 10.^(-4:0); 23 | contour(xx,yy,abs(pp),levels), title(s), colormap(1e-6*[1 1 1]); 24 | end 25 | -------------------------------------------------------------------------------- /p11.m: -------------------------------------------------------------------------------- 1 | % p11.m - Chebyshev differentation of a smooth function 2 | 3 | xx = -1:.01:1; uu = exp(xx).*sin(5*xx); clf 4 | for N = [10 20] 5 | [D,x] = cheb(N); u = exp(x).*sin(5*x); 6 | subplot('position',[.15 .66-.4*(N==20) .31 .28]) 7 | plot(x,u,'.','markersize',14), grid on 8 | line(xx,uu) 9 | title(['u(x), N=' int2str(N)]) 10 | error = D*u - exp(x).*(sin(5*x)+5*cos(5*x)); 11 | subplot('position',[.55 .66-.4*(N==20) .31 .28]) 12 | plot(x,error,'.','markersize',14), grid on 13 | line(x,error) 14 | title([' error in u''(x), N=' int2str(N)]) 15 | end 16 | -------------------------------------------------------------------------------- /p12.m: -------------------------------------------------------------------------------- 1 | % p12.m - accuracy of Chebyshev spectral differentiation 2 | % (compare p7.m) 3 | 4 | % Compute derivatives for various values of N: 5 | Nmax = 50; E = zeros(3,Nmax); 6 | for N = 1:Nmax; 7 | [D,x] = cheb(N); 8 | v = abs(x).^3; vprime = 3*x.*abs(x); % 3rd deriv in BV 9 | E(1,N) = norm(D*v-vprime,inf); 10 | v = exp(-x.^(-2)); vprime = 2.*v./x.^3; % C-infinity 11 | E(2,N) = norm(D*v-vprime,inf); 12 | v = 1./(1+x.^2); vprime = -2*x.*v.^2; % analytic in [-1,1] 13 | E(3,N) = norm(D*v-vprime,inf); 14 | v = x.^10; vprime = 10*x.^9; % polynomial 15 | E(4,N) = norm(D*v-vprime,inf); 16 | end 17 | 18 | % Plot results: 19 | titles = {'|x^3|','exp(-x^{-2})','1/(1+x^2)','x^{10}'}; clf 20 | for iplot = 1:4 21 | subplot(2,2,iplot) 22 | semilogy(1:Nmax,E(iplot,:),'.','markersize',12) 23 | line(1:Nmax,E(iplot,:)) 24 | axis([0 Nmax 1e-16 1e3]), grid on 25 | set(gca,'xtick',0:10:Nmax,'ytick',(10).^(-15:5:0)) 26 | xlabel N, ylabel error, title(titles(iplot)) 27 | end 28 | -------------------------------------------------------------------------------- /p13.m: -------------------------------------------------------------------------------- 1 | % p13.m - solve linear BVP u_xx = exp(4x), u(-1)=u(1)=0 2 | 3 | N = 16; 4 | [D,x] = cheb(N); 5 | D2 = D^2; 6 | D2 = D2(2:N,2:N); % boundary conditions 7 | f = exp(4*x(2:N)); 8 | u = D2\f; % Poisson eq. solved here 9 | u = [0;u;0]; 10 | clf, subplot('position',[.1 .4 .8 .5]) 11 | plot(x,u,'.','markersize',16) 12 | xx = -1:.01:1; 13 | uu = polyval(polyfit(x,u,N),xx); % interpolate grid data 14 | line(xx,uu) 15 | grid on 16 | exact = ( exp(4*xx) - sinh(4)*xx - cosh(4) )/16; 17 | title(['max err = ' num2str(norm(uu-exact,inf))],'fontsize',12) 18 | -------------------------------------------------------------------------------- /p14.m: -------------------------------------------------------------------------------- 1 | % p14.m - solve nonlinear BVP u_xx = exp(u), u(-1)=u(1)=0 2 | % (compare p13.m) 3 | 4 | N = 16; 5 | [D,x] = cheb(N); D2 = D^2; D2 = D2(2:N,2:N); 6 | u = zeros(N-1,1); 7 | change = 1; it = 0; 8 | while change > 1e-15 % fixed-point iteration 9 | unew = D2\exp(u); 10 | change = norm(unew-u,inf); 11 | u = unew; it = it+1; 12 | end 13 | u = [0;u;0]; 14 | clf, subplot('position',[.1 .4 .8 .5]) 15 | plot(x,u,'.','markersize',16) 16 | xx = -1:.01:1; 17 | uu = polyval(polyfit(x,u,N),xx); 18 | line(xx,uu), grid on 19 | title(sprintf('no. steps = %d u(0) =%18.14f',it,u(N/2+1))) 20 | -------------------------------------------------------------------------------- /p15.m: -------------------------------------------------------------------------------- 1 | % p15.m - solve eigenvalue BVP u_xx = lambda*u, u(-1)=u(1)=0 2 | 3 | N = 36; [D,x] = cheb(N); D2 = D^2; D2 = D2(2:N,2:N); 4 | [V,Lam] = eig(D2); lam = diag(Lam); 5 | [foo,ii] = sort(-lam); % sort eigenvalues and -vectors 6 | lam = lam(ii); V = V(:,ii); clf 7 | for j = 5:5:30 % plot 6 eigenvectors 8 | u = [0;V(:,j);0]; subplot(7,1,j/5) 9 | plot(x,u,'.','markersize',12), grid on 10 | xx = -1:.01:1; uu = polyval(polyfit(x,u,N),xx); 11 | line(xx,uu), axis off 12 | text(-.4,.5,sprintf('eig %d =%20.13f*4/pi^2',j,lam(j)*4/pi^2)) 13 | text(.7,.5,sprintf('%4.1f ppw', 4*N/(pi*j))) 14 | end 15 | -------------------------------------------------------------------------------- /p16.m: -------------------------------------------------------------------------------- 1 | % p16.m - Poisson eq. on [-1,1]x[-1,1] with u=0 on boundary 2 | 3 | % Set up grids and tensor product Laplacian and solve for u: 4 | N = 24; [D,x] = cheb(N); y = x; 5 | [xx,yy] = meshgrid(x(2:N),y(2:N)); 6 | xx = xx(:); yy = yy(:); % stretch 2D grids to 1D vectors 7 | f = 10*sin(8*xx.*(yy-1)); 8 | D2 = D^2; D2 = D2(2:N,2:N); I = eye(N-1); 9 | L = kron(I,D2) + kron(D2,I); % Laplacian 10 | figure(1), clf, spy(L), drawnow 11 | tic, u = L\f; toc % solve problem and watch the clock 12 | 13 | % Reshape long 1D results onto 2D grid: 14 | uu = zeros(N+1,N+1); uu(2:N,2:N) = reshape(u,N-1,N-1); 15 | [xx,yy] = meshgrid(x,y); 16 | value = uu(N/4+1,N/4+1); 17 | 18 | % Interpolate to finer grid and plot: 19 | [xxx,yyy] = meshgrid(-1:.04:1,-1:.04:1); 20 | uuu = interp2(xx,yy,uu,xxx,yyy,'cubic'); 21 | figure(2), clf, mesh(xxx,yyy,uuu), colormap(1e-6*[1 1 1]); 22 | xlabel x, ylabel y, zlabel u 23 | text(.4,-.3,-.3,sprintf('u(2^{-1/2},2^{-1/2}) = %14.11f',value)) 24 | -------------------------------------------------------------------------------- /p17.m: -------------------------------------------------------------------------------- 1 | % p17.m - Helmholtz eq. u_xx + u_yy + (k^2)u = f 2 | % on [-1,1]x[-1,1] (compare p16.m) 3 | 4 | % Set up spectral grid and tensor product Helmholtz operator: 5 | N = 24; [D,x] = cheb(N); y = x; 6 | [xx,yy] = meshgrid(x(2:N),y(2:N)); 7 | xx = xx(:); yy = yy(:); 8 | f = exp(-10*((yy-1).^2+(xx-.5).^2)); 9 | D2 = D^2; D2 = D2(2:N,2:N); I = eye(N-1); 10 | k = 9; 11 | L = kron(I,D2) + kron(D2,I) + k^2*eye((N-1)^2); 12 | 13 | % Solve for u, reshape to 2D grid, and plot: 14 | u = L\f; 15 | uu = zeros(N+1,N+1); uu(2:N,2:N) = reshape(u,N-1,N-1); 16 | [xx,yy] = meshgrid(x,y); 17 | [xxx,yyy] = meshgrid(-1:.0333:1,-1:.0333:1); 18 | uuu = interp2(xx,yy,uu,xxx,yyy,'cubic'); 19 | figure(1), clf, mesh(xxx,yyy,uuu), colormap(1e-6*[1 1 1]); 20 | xlabel x, ylabel y, zlabel u 21 | text(.2,1,.022,sprintf('u(0,0) = %13.11f',uu(N/2+1,N/2+1))) 22 | figure(2), clf, contour(xxx,yyy,uuu) 23 | colormap(1e-6*[1 1 1]); axis square 24 | -------------------------------------------------------------------------------- /p18.m: -------------------------------------------------------------------------------- 1 | % p18.m - Chebyshev differentiation via FFT (compare p11.m) 2 | 3 | xx = -1:.01:1; ff = exp(xx).*sin(5*xx); clf 4 | for N = [10 20] 5 | x = cos(pi*(0:N)'/N); f = exp(x).*sin(5*x); 6 | subplot('position',[.15 .66-.4*(N==20) .31 .28]) 7 | plot(x,f,'.','markersize',14), grid on 8 | line(xx,ff) 9 | title(['f(x), N=' int2str(N)]) 10 | error = chebfft(f) - exp(x).*(sin(5*x)+5*cos(5*x)); 11 | subplot('position',[.55 .66-.4*(N==20) .31 .28]) 12 | plot(x,error,'.','markersize',14), grid on 13 | line(x,error) 14 | title(['error in f''(x), N=' int2str(N)]) 15 | end 16 | 17 | 18 | -------------------------------------------------------------------------------- /p19.m: -------------------------------------------------------------------------------- 1 | % p19.m - 2nd-order wave eq. on Chebyshev grid (compare p6.m) 2 | 3 | % Time-stepping by leap frog formula: 4 | N = 80; x = cos(pi*(0:N)/N); dt = 8/N^2; 5 | v = exp(-200*x.^2); vold = exp(-200*(x-dt).^2); 6 | tmax = 4; tplot = .075; 7 | plotgap = round(tplot/dt); dt = tplot/plotgap; 8 | nplots = round(tmax/tplot); 9 | plotdata = [v; zeros(nplots,N+1)]; tdata = 0; 10 | clf, drawnow, h = waitbar(0,'please wait...'); 11 | set(gcf,'renderer','zbuffer') 12 | for i = 1:nplots, waitbar(i/nplots) 13 | for n = 1:plotgap 14 | w = chebfft(chebfft(v))'; w(1) = 0; w(N+1) = 0; 15 | vnew = 2*v - vold + dt^2*w; vold = v; v = vnew; 16 | end 17 | plotdata(i+1,:) = v; tdata = [tdata; dt*i*plotgap]; 18 | end 19 | 20 | % Plot results: 21 | clf, drawnow, waterfall(x,tdata,plotdata) 22 | axis([-1 1 0 tmax -2 2]), view(10,70), grid off 23 | colormap(1e-6*[1 1 1]); ylabel t, zlabel u, close(h) 24 | -------------------------------------------------------------------------------- /p20.m: -------------------------------------------------------------------------------- 1 | % p20.m - 2nd-order wave eq. in 2D via FFT (compare p19.m) 2 | 3 | % Grid and initial data: 4 | N = 24; x = cos(pi*(0:N)/N); y = x'; 5 | dt = 6/N^2; 6 | [xx,yy] = meshgrid(x,y); 7 | plotgap = round((1/3)/dt); dt = (1/3)/plotgap; 8 | vv = exp(-40*((xx-.4).^2 + yy.^2)); 9 | vvold = vv; 10 | 11 | % Time-stepping by leap frog formula: 12 | [ay,ax] = meshgrid([.56 .06],[.1 .55]); clf 13 | for n = 0:3*plotgap 14 | t = n*dt; 15 | if rem(n+.5,plotgap)<1 % plots at multiples of t=1/3 16 | i = n/plotgap+1; 17 | subplot('position',[ax(i) ay(i) .36 .36]) 18 | [xxx,yyy] = meshgrid(-1:1/16:1,-1:1/16:1); 19 | vvv = interp2(xx,yy,vv,xxx,yyy,'cubic'); 20 | mesh(xxx,yyy,vvv), axis([-1 1 -1 1 -0.15 1]) 21 | colormap(1e-6*[1 1 1]); title(['t = ' num2str(t)]), drawnow 22 | end 23 | uxx = zeros(N+1,N+1); uyy = zeros(N+1,N+1); 24 | ii = 2:N; 25 | for i = 2:N % 2nd derivs wrt x in each row 26 | v = vv(i,:); V = [v fliplr(v(ii))]; 27 | U = real(fft(V)); 28 | W1 = real(ifft(1i*[0:N-1 0 1-N:-1].*U)); % diff wrt theta 29 | W2 = real(ifft(-[0:N 1-N:-1].^2.*U)); % diff^2 wrt theta 30 | uxx(i,ii) = W2(ii)./(1-x(ii).^2) - x(ii).* ... 31 | W1(ii)./(1-x(ii).^2).^(3/2); 32 | end 33 | for j = 2:N % 2nd derivs wrt y in each column 34 | v = vv(:,j); V = [v; flipud(v(ii))]; 35 | U = real(fft(V)); 36 | W1 = real(ifft(1i*[0:N-1 0 1-N:-1]'.*U));% diff wrt theta 37 | W2 = real(ifft(-[0:N 1-N:-1]'.^2.*U)); % diff^2 wrt theta 38 | uyy(ii,j) = W2(ii)./(1-y(ii).^2) - y(ii).* ... 39 | W1(ii)./(1-y(ii).^2).^(3/2); 40 | end 41 | vvnew = 2*vv - vvold + dt^2*(uxx+uyy); 42 | vvold = vv; vv = vvnew; 43 | end 44 | -------------------------------------------------------------------------------- /p20u.m: -------------------------------------------------------------------------------- 1 | % p20u.m - 2nd-order wave eq. in 2D via FFT (compare p19.m) UNSTABLE 2 | 3 | % Grid and initial data: 4 | N = 24; x = cos(pi*(0:N)/N); y = x'; dt = 6.6/N^2; 5 | [xx,yy] = meshgrid(x,y); 6 | plotgap = round((1/3)/dt); 7 | vv = exp(-40*((xx-.4).^2 + yy.^2)); 8 | vvold = vv; vvnew = 0*vv; 9 | 10 | % Time-stepping by leap frog formula: 11 | [ay,ax] = meshgrid([.56 .06],[.1 .55]); 12 | for n = 0:3*plotgap 13 | t = n*dt; 14 | if rem(n+.5,plotgap)<1 % Plots at multiples of t=1/3 15 | i = n/plotgap+1; subplot('position',[ax(i) ay(i) .36 .36]) 16 | [xxx,yyy] = meshgrid(-1:.05:1,-1:.05:1); 17 | vvv = interp2(xx,yy,vv,xxx,yyy,'cubic'); 18 | mesh(xxx,yyy,vvv), axis([-1 1 -1 1 -0.15 1]) 19 | colormap(1e-6*[1 1 1]); title(['t = ' num2str(t)]), drawnow 20 | end 21 | uxx = zeros(N+1,N+1); uyy = zeros(N+1,N+1); 22 | ii = 2:N; 23 | for i = ii % 2nd derivs wrt x in each row 24 | v = vv(i,:); V = [v fliplr(v(ii))]; U = real(fft(V)); 25 | W1 = real(ifft(1i*[0:N-1 0 1-N:-1].*U)); % diff wrt theta 26 | W2 = real(ifft(-[0:N 1-N:-1].^2.*U)); % diff^2 wrt theta 27 | uxx(i,ii) = W2(ii)./(1-x(ii).^2) - x(ii).* ... 28 | W1(ii)./(1-x(ii).^2).^(3/2); 29 | end 30 | for j = ii % 2nd derivs wrt y in each column 31 | v = vv(:,j); V = [v; flipud(v(ii))]; U = real(fft(V)); 32 | W1 = real(ifft(1i*[0:N-1 0 1-N:-1]'.*U));% diff wrt theta 33 | W2 = real(ifft(-[0:N 1-N:-1]'.^2.*U)); % diff^2 wrt theta 34 | uyy(ii,j) = W2(ii)./(1-y(ii).^2) - y(ii).* ... 35 | W1(ii)./(1-y(ii).^2).^(3/2); 36 | end 37 | vvnew = 2*vv - vvold + dt^2*(uxx+uyy); 38 | vvold = vv; vv = vvnew; 39 | if max(max(abs(vv)))>2, break, end 40 | end 41 | 42 | close 43 | [xxx,yyy] = meshgrid(-1:.05:1,-1:.05:1); 44 | vvv = interp2(xx,yy,vv,xxx,yyy,'cubic'); 45 | mesh(xxx,yyy,vvv), colormap(1e-6*[1 1 1]); 46 | axis([-1 1 -1 1 -1 1]), title(['t = ' num2str(t)]), drawnow 47 | 48 | -------------------------------------------------------------------------------- /p21.m: -------------------------------------------------------------------------------- 1 | % p21.m - eigenvalues of Mathieu operator -u_xx + 2qcos(2x)u 2 | % (compare p8.m and p. 724 of Abramowitz & Stegun) 3 | 4 | N = 42; h = 2*pi/N; x = h*(1:N); 5 | D2 = toeplitz([-pi^2/(3*h^2)-1/6 ... 6 | -.5*(-1).^(1:N-1)./sin(h*(1:N-1)/2).^2]); 7 | qq = 0:.2:15; data = []; 8 | for q = qq; 9 | e = sort(eig(-D2 + 2*q*diag(cos(2*x))))'; 10 | data = [data; e(1:11)]; 11 | end 12 | clf, subplot(1,2,1) 13 | set(gca,'colororder',[0 0 1],'linestyleorder','-|--'), hold on 14 | plot(qq,data), xlabel q, ylabel \lambda 15 | axis([0 15 -24 32]), set(gca,'ytick',-24:4:32) 16 | -------------------------------------------------------------------------------- /p22.m: -------------------------------------------------------------------------------- 1 | % p22.m - 5th eigenvector of Airy equation u_xx = lambda*x*u 2 | 3 | clf 4 | for N = 12:12:48 5 | [D,x] = cheb(N); D2 = D^2; D2 = D2(2:N,2:N); 6 | [V,Lam] = eig(D2,diag(x(2:N))); % generalized ev problem 7 | Lam = diag(Lam); ii = find(Lam>0); 8 | V = V(:,ii); Lam = Lam(ii); 9 | [foo,ii] = sort(Lam); ii = ii(5); lambda = Lam(ii); 10 | v = [0;V(:,ii);0]; v = v/v(N/2+1)*airy(0); 11 | xx = -1:.01:1; vv = polyval(polyfit(x,v,N),xx); 12 | subplot(2,2,N/12), plot(xx,vv), grid on 13 | title(sprintf('N = %d eig = %15.10f',N,lambda)) 14 | end 15 | -------------------------------------------------------------------------------- /p23.m: -------------------------------------------------------------------------------- 1 | % p23.m - eigenvalues of perturbed Laplacian on [-1,1]x[-1,1] 2 | % (compare p16.m) 3 | 4 | % Set up tensor product Laplacian and compute 4 eigenmodes: 5 | N = 16; [D,x] = cheb(N); y = x; 6 | [xx,yy] = meshgrid(x(2:N),y(2:N)); xx = xx(:); yy = yy(:); 7 | D2 = D^2; D2 = D2(2:N,2:N); I = eye(N-1); 8 | L = -kron(I,D2) - kron(D2,I); % Laplacian 9 | L = L + diag(exp(20*(yy-xx-1))); % + perturbation 10 | [V,D] = eig(L); D = diag(D); 11 | [D,ii] = sort(D); ii = ii(1:4); V = V(:,ii); 12 | 13 | % Reshape them to 2D grid, interpolate to finer grid, and plot: 14 | [xx,yy] = meshgrid(x,y); 15 | fine = -1:.02:1; [xxx,yyy] = meshgrid(fine,fine); 16 | uu = zeros(N+1,N+1); 17 | [ay,ax] = meshgrid([.56 .04],[.1 .5]); clf 18 | for i = 1:4 19 | uu(2:N,2:N) = reshape(V(:,i),N-1,N-1); 20 | uu = uu/norm(uu(:),inf); 21 | uuu = interp2(xx,yy,uu,xxx,yyy,'cubic'); 22 | subplot('position',[ax(i) ay(i) .38 .38]) 23 | contour(fine,fine,uuu,-.9:.2:.9) 24 | colormap(1e-6*[1 1 1]); axis square 25 | title(['eig = ' num2str(D(i)/(pi^2/4),'%18.12f') '\pi^2/4']) 26 | end 27 | -------------------------------------------------------------------------------- /p23a.m: -------------------------------------------------------------------------------- 1 | % p23a.m - eigenvalues of UNperturbed Laplacian on [-1,1]x[-1,1] 2 | % (compare p16.m) 3 | 4 | % Set up tensor product Laplacian and compute 4 eigenmodes: 5 | N = 16; [D,x] = cheb(N); y = x; 6 | [xx,yy] = meshgrid(x(2:N),y(2:N)); xx = xx(:); yy = yy(:); 7 | D2 = D^2; D2 = D2(2:N,2:N); I = eye(N-1); 8 | L = -kron(I,D2) - kron(D2,I); % Laplacian 9 | % L = L + diag(exp(20*(yy-xx-1))); % + perturbation 10 | [V,D] = eig(L); D = diag(D); 11 | [D,ii] = sort(D); ii = ii(1:4); V = V(:,ii); 12 | 13 | % Reshape them to 2D grid, interpolate to finer grid, and plot: 14 | [xx,yy] = meshgrid(x,y); 15 | fine = -1:.02:1; [xxx,yyy] = meshgrid(fine,fine); 16 | uu = zeros(N+1,N+1); 17 | [ay,ax] = meshgrid([.56 .04],[.1 .5]); clf 18 | for i = 1:4 19 | uu(2:N,2:N) = reshape(V(:,i),N-1,N-1); 20 | uu = uu/norm(uu(:),inf); 21 | uuu = interp2(xx,yy,uu,xxx,yyy,'cubic'); 22 | subplot('position',[ax(i) ay(i) .38 .38]) 23 | contour(fine,fine,uuu,-.9:.2:.9) 24 | colormap(1e-6*[1 1 1]); axis square 25 | title(['eig = ' num2str(D(i)/(pi^2/4),'%18.12f') '\pi^2/4']) 26 | end 27 | -------------------------------------------------------------------------------- /p24.m: -------------------------------------------------------------------------------- 1 | % p24.m - pseudospectra of Davies's complex harmonic oscillator 2 | % (For finer, slower plot, change 0:2 to 0:.5.) 3 | 4 | % Eigenvalues: 5 | N = 70; [D,x] = cheb(N); x = x(2:N); 6 | L = 6; x = L*x; D = D/L; % rescale to [-L,L] 7 | A = -D^2; A = A(2:N,2:N) + (1+3i)*diag(x.^2); 8 | clf, plot(eig(A),'.','markersize',14) 9 | axis([0 50 0 40]), drawnow, hold on 10 | 11 | % Pseudospectra: 12 | x = 0:2:50; y = 0:2:40; [xx,yy] = meshgrid(x,y); zz = xx+1i*yy; 13 | I = eye(N-1); sigmin = zeros(length(y),length(x)); 14 | h = waitbar(0,'please wait...'); 15 | for j = 1:length(x), waitbar(j/length(x)) 16 | for i = 1:length(y), sigmin(i,j) = min(svd(zz(i,j)*I-A)); end 17 | end, close(h) 18 | contour(x,y,sigmin,10.^(-4:.5:-.5)), colormap(1e-6*[1 1 1]); 19 | -------------------------------------------------------------------------------- /p24fine.m: -------------------------------------------------------------------------------- 1 | % p24fine.m - pseudospectra of Davies's complex harmonic oscillator 2 | % (This is the finer, slower plot, with 0:2 changed to 0:.5.) 3 | 4 | % Eigenvalues: 5 | N = 70; [D,x] = cheb(N); x = x(2:N); 6 | L = 6; x = L*x; D = D/L; % rescale to [-L,L] 7 | A = -D^2; A = A(2:N,2:N) + (1+3i)*diag(x.^2); 8 | clf, plot(eig(A),'.','markersize',14) 9 | axis([0 50 0 40]), drawnow, hold on 10 | 11 | % Pseudospectra: 12 | x = 0:.5:50; y = 0:.5:40; [xx,yy] = meshgrid(x,y); zz = xx+1i*yy; 13 | I = eye(N-1); sigmin = zeros(length(y),length(x)); 14 | h = waitbar(0,'please wait...'); 15 | for j = 1:length(x), waitbar(j/length(x)) 16 | for i = 1:length(y), sigmin(i,j) = min(svd(zz(i,j)*I-A)); end 17 | end, close(h) 18 | contour(x,y,sigmin,10.^(-4:.5:-.5)), colormap(1e-6*[1 1 1]); 19 | -------------------------------------------------------------------------------- /p25.m: -------------------------------------------------------------------------------- 1 | % p25.m - stability regions for ODE formulas 2 | 3 | % Adams-Bashforth: 4 | clf, subplot('position',[.1 .56 .38 .38]) 5 | plot([-8 8],[0 0]), hold on, plot([0 0],[-8 8]) 6 | z = exp(1i*pi*(0:200)/100); r = z-1; 7 | s = 1; plot(r./s) % order 1 8 | s = (3-1./z)/2; plot(r./s) % order 2 9 | s = (23-16./z+5./z.^2)/12; plot(r./s) % order 3 10 | axis([-2.5 .5 -1.5 1.5]), axis square, grid on 11 | title Adams-Bashforth 12 | 13 | % Adams-Moulton: 14 | subplot('position',[.5 .56 .38 .38]) 15 | plot([-8 8],[0 0]), hold on, plot([0 0],[-8 8]) 16 | s = (5*z+8-1./z)/12; plot(r./s) % order 3 17 | s = (9*z+19-5./z+1./z.^2)/24; plot(r./s) % order 4 18 | s = (251*z+646-264./z+106./z.^2-19./z.^3)/720; plot(r./s) % 5 19 | d = 1-1./z; 20 | s = 1-d/2-d.^2/12-d.^3/24-19*d.^4/720-3*d.^5/160; plot(d./s) % 6 21 | axis([-7 1 -4 4]), axis square, grid on, title Adams-Moulton 22 | 23 | % Backward differentiation: 24 | subplot('position',[.1 .04 .38 .38]) 25 | plot([-40 40],[0 0]), hold on, plot([0 0],[-40 40]) 26 | r = 0; for i = 1:6, r = r+(d.^i)/i; plot(r), end % orders 1-6 27 | axis([-15 35 -25 25]), axis square, grid on 28 | title('backward differentiation') 29 | 30 | % Runge-Kutta: 31 | subplot('position',[.5 .04 .38 .38]) 32 | plot([-8 8],[0 0]), hold on, plot([0 0],[-8 8]) 33 | w = 0; W = w; for i = 2:length(z) % order 1 34 | w = w-(1+w-z(i)); W = [W; w]; end, plot(W) 35 | w = 0; W = w; for i = 2:length(z) % order 2 36 | w = w-(1+w+.5*w^2-z(i)^2)/(1+w); W = [W; w]; 37 | end, plot(W) 38 | w = 0; W = w; for i = 2:length(z) % order 3 39 | w = w-(1+w+.5*w^2+w^3/6-z(i)^3)/(1+w+w^2/2); W = [W; w]; 40 | end, plot(W) 41 | w = 0; W = w; for i = 2:length(z) % order 4 42 | w = w-(1+w+.5*w^2+w^3/6+w.^4/24-z(i)^4)/(1+w+w^2/2+w.^3/6); 43 | W = [W; w]; end, plot(W) 44 | axis([-5 2 -3.5 3.5]), axis square, grid on, title Runge-Kutta 45 | -------------------------------------------------------------------------------- /p26.m: -------------------------------------------------------------------------------- 1 | % p26.m - eigenvalues of 2nd-order Chebyshev diff. matrix 2 | 3 | N = 60; [D,x] = cheb(N); D2 = D^2; D2 = D2(2:N,2:N); 4 | [V,Lam] = eig(D2); 5 | [foo,ii] = sort(-diag(Lam)); e = diag(Lam(ii,ii)); V = V(:,ii); 6 | 7 | % Plot eigenvalues: 8 | clf, subplot('position',[.1 .62 .8 .3]) 9 | loglog(-e,'.','markersize',10), ylabel eigenvalue 10 | title(['N = ' int2str(N) ... 11 | ' max |\lambda| = ' num2str(max(-e)/N^4) 'N^4']) 12 | hold on, semilogy(2*N/pi*[1 1],[1 1e6],'--r') 13 | text(2.1*N/pi,24,'2\pi / N','fontsize',12) 14 | 15 | % Plot eigenmodes N/4 (physical) and N (nonphysical): 16 | vN4 = [0; V(:,N/4-1); 0]; 17 | xx = -1:.01:1; vv = polyval(polyfit(x,vN4,N),xx); 18 | subplot('position',[.1 .36 .8 .15]), plot(xx,vv), hold on 19 | plot(x,vN4,'.','markersize',9), title('eigenmode N/4') 20 | vN = V(:,N-1); 21 | subplot('position',[.1 .1 .8 .15]) 22 | semilogy(x(2:N),abs(vN)), axis([-1 1 5e-6 1]), hold on 23 | plot(x(2:N),abs(vN),'.','markersize',9) 24 | title('absolute value of eigenmode N (log scale)') 25 | -------------------------------------------------------------------------------- /p27.m: -------------------------------------------------------------------------------- 1 | % p27.m - Solve KdV eq. u_t + uu_x + u_xxx = 0 on [-pi,pi] by 2 | % FFT with integrating factor v = exp(-ik^3t)*u-hat. 3 | 4 | % Set up grid and two-soliton initial data: 5 | N = 256; dt = .4/N^2; x = (2*pi/N)*(-N/2:N/2-1)'; 6 | A = 25; B = 16; clf, drawnow, set(gcf,'renderer','zbuffer') 7 | u = 3*A^2*sech(.5*(A*(x+2))).^2 + 3*B^2*sech(.5*(B*(x+1))).^2; 8 | v = fft(u); k = [0:N/2-1 0 -N/2+1:-1]'; ik3 = 1i*k.^3; 9 | 10 | % Solve PDE and plot results: 11 | tmax = 0.006; nplt = floor((tmax/25)/dt); nmax = round(tmax/dt); 12 | udata = u; tdata = 0; h = waitbar(0,'please wait...'); 13 | for n = 1:nmax 14 | t = n*dt; g = -.5i*dt*k; 15 | E = exp(dt*ik3/2); E2 = E.^2; 16 | a = g.*fft(real( ifft( v ) ).^2); 17 | b = g.*fft(real( ifft(E.*(v+a/2)) ).^2); % 4th-order 18 | c = g.*fft(real( ifft(E.*v + b/2) ).^2); % Runge-Kutta 19 | d = g.*fft(real( ifft(E2.*v+E.*c) ).^2); 20 | v = E2.*v + (E2.*a + 2*E.*(b+c) + d)/6; 21 | if mod(n,nplt) == 0 22 | u = real(ifft(v)); waitbar(n/nmax) 23 | udata = [udata u]; tdata = [tdata t]; 24 | end 25 | end 26 | waterfall(x,tdata,udata'), colormap(1e-6*[1 1 1]); view(-20,25) 27 | xlabel x, ylabel t, axis([-pi pi 0 tmax 0 2000]), grid off 28 | set(gca,'ztick',[0 2000]), close(h), pbaspect([1 1 .13]) 29 | -------------------------------------------------------------------------------- /p28.m: -------------------------------------------------------------------------------- 1 | % p28.m - eigenmodes of Laplacian on the disk (compare p22.m) 2 | 3 | % r coordinate, ranging from -1 to 1 (N must be odd): 4 | N = 25; N2 = (N-1)/2; 5 | [D,r] = cheb(N); 6 | D2 = D^2; 7 | D1 = D2(2:N2+1,2:N2+1); D2 = D2(2:N2+1,N:-1:N2+2); 8 | E1 = D(2:N2+1,2:N2+1); E2 = D(2:N2+1,N:-1:N2+2); 9 | 10 | % t = theta coordinate, ranging from 0 to 2*pi (M must be even): 11 | M = 20; dt = 2*pi/M; t = dt*(1:M)'; M2 = M/2; 12 | D2t = toeplitz([-pi^2/(3*dt^2)-1/6 ... 13 | .5*(-1).^(2:M)./sin(dt*(1:M-1)/2).^2]); 14 | 15 | % Laplacian in polar coordinates: 16 | R = diag(1./r(2:N2+1)); 17 | Z = zeros(M2); I = eye(M2); 18 | L = kron(D1+R*E1,eye(M)) + kron(D2+R*E2,[Z I;I Z]) ... 19 | + kron(R^2,D2t); 20 | 21 | % Compute four eigenmodes: 22 | index = [1 3 6 10]; 23 | [V,Lam] = eig(-L); Lam = diag(Lam); [Lam,ii] = sort(Lam); 24 | ii = ii(index); V = V(:,ii); 25 | Lam = sqrt(Lam(index)/Lam(1)); 26 | 27 | % Plot eigenmodes with nodal lines underneath: 28 | [rr,tt] = meshgrid(r(1:N2+1),[0;t]); 29 | [xx,yy] = pol2cart(tt,rr); 30 | z = exp(1i*pi*(-100:100)/100); 31 | [ay,ax] = meshgrid([.58 .1],[.1 .5]); clf 32 | for i = 1:4 33 | u = reshape(real(V(:,i)),M,N2); 34 | u = [zeros(M+1,1) u([M 1:M],:)]; 35 | u = u/norm(u(:),inf); 36 | subplot('position',[ax(i) ay(i) .4 .4]) 37 | plot(z), axis(1.05*[-1 1 -1 1 -1 1]), axis off, hold on 38 | mesh(xx,yy,u) 39 | view(0,20), colormap(1e-6*[1 1 1]); axis square 40 | contour3(xx,yy,u-1,[-1 -1]) 41 | plot3(real(z),imag(z),-abs(z)) 42 | text(-.8,4,['Mode ' int2str(index(i))],'fontsize',9) 43 | text(-.8,3.5, ['\lambda = ', num2str(Lam(i),... 44 | '%16.10f')],'fontsize',9) 45 | end 46 | -------------------------------------------------------------------------------- /p28b.m: -------------------------------------------------------------------------------- 1 | % p28b.m - eigenmodes of Laplacian on the disk 2 | 3 | % r coordinate, ranging from -1 to 1 (N must be odd) 4 | N = 25; [D,r] = cheb(N); N2 = (N-1)/2; D2 = D^2; 5 | D1 = D2(2:N2+1,2:N2+1); D2 = D2(2:N2+1,N:-1:N2+2); 6 | E1 = D(2:N2+1,2:N2+1); E2 = D(2:N2+1,N:-1:N2+2); 7 | 8 | % t = theta coordinate, ranging from 0 to 2*pi (M must be even): 9 | M = 20; dt = 2*pi/M; t = dt*(1:M)'; M2 = M/2; 10 | D2t = toeplitz([-pi^2/(3*dt^2)-1/6 ... 11 | .5*(-1).^(2:M)./sin(dt*(1:M-1)/2).^2]); 12 | 13 | % Laplacian in polar coordinates: 14 | R = diag(1./r(2:N2+1)); Z = zeros(M2); I = eye(M2); 15 | L = kron(D1+R*E1,eye(M))+ kron(D2+R*E2,[Z I;I Z])+ kron(R^2,D2t); 16 | 17 | % Compute four eigenmodes: 18 | index = 1:25; 19 | [V,Lam] = eig(-L); Lam = diag(Lam); 20 | [Lam,ii] = sort(real(Lam)); ii = ii(index); V = real(V(:,ii)); 21 | Lam = sqrt(Lam(index)/Lam(1)); 22 | 23 | % Plot eigenmodes with nodal lines underneath: 24 | [rr,tt] = meshgrid(r(1:N2+1),[0;t]); [xx,yy] = pol2cart(tt,rr); 25 | z = exp(sqrt(-1)*pi*(-100:100)/100); 26 | [ay,ax] = meshgrid(.8:-.2:0,0:.16:.64); clf 27 | for i = 1:25 28 | u = reshape(real(V(:,i)),M,N2); 29 | u = [zeros(M+1,1) u([M 1:M],:)]; 30 | u = u/norm(u(:),inf); 31 | subplot('position',[ax(i) ay(i) .16 .2]), plot(z) 32 | axis(1.25*[-1 1 -1 1 -1 1]), axis off, hold on 33 | view(0,90), colormap(1e-6*[1 1 1]); axis square 34 | contour3(xx,yy,u-1,[-1 -1]), plot3(real(z),imag(z),-abs(z)) 35 | text(-.3,1.15,num2str(Lam(i)),'fontsize',7) 36 | end 37 | -------------------------------------------------------------------------------- /p29.m: -------------------------------------------------------------------------------- 1 | % p29.m - solve Poisson equation on the unit disk 2 | % (compare p16.m and p28.m) 3 | 4 | % Laplacian in polar coordinates: 5 | N = 31; [D,r] = cheb(N); N2 = (N-1)/2; D2 = D^2; 6 | D1 = D2(2:N2+1,2:N2+1); D2 = D2(2:N2+1,N:-1:N2+2); 7 | E1 = D(2:N2+1,2:N2+1); E2 = D(2:N2+1,N:-1:N2+2); 8 | M = 40; dt = 2*pi/M; t = dt*(1:M)'; M2 = M/2; 9 | D2t = toeplitz([-pi^2/(3*dt^2)-1/6 ... 10 | .5*(-1).^(2:M)./sin(dt*(1:M-1)/2).^2]); 11 | R = diag(1./r(2:N2+1)); Z = zeros(M2); I = eye(M2); 12 | L = kron(D1+R*E1,eye(M))+kron(D2+R*E2,[Z I;I Z])+kron(R^2,D2t); 13 | 14 | % Right-hand side and solution for u: 15 | [rr,tt] = meshgrid(r(2:N2+1),t); rr = rr(:); tt = tt(:); 16 | f = -rr.^2.*sin(tt/2).^4 + sin(6*tt).*cos(tt/2).^2; u = L\f; 17 | 18 | % Reshape results onto 2D grid and plot them: 19 | u = reshape(u,M,N2); u = [zeros(M+1,1) u([M 1:M],:)]; 20 | [rr,tt] = meshgrid(r(1:N2+1),t([M 1:M])); 21 | [xx,yy] = pol2cart(tt,rr); 22 | clf, subplot('position',[.1 .4 .8 .5]) 23 | mesh(xx,yy,u), view(20,40), colormap(1e-6*[1 1 1]); 24 | axis([-1 1 -1 1 -.01 .05]), xlabel x, ylabel y, zlabel u 25 | -------------------------------------------------------------------------------- /p30.m: -------------------------------------------------------------------------------- 1 | % p30.m - spectral integration, ODE style (compare p12.m) 2 | 3 | % Computation: various values of N, four functions: 4 | Nmax = 50; E = zeros(4,Nmax); clf 5 | for N = 1:Nmax; i = 1:N; 6 | [D,x] = cheb(N); x = x(i); Di = inv(D(i,i)); w = Di(1,:); 7 | f = abs(x).^3; E(1,N) = abs(w*f - .5); 8 | f = exp(-x.^(-2)); E(2,N) = abs(w*f - ... 9 | 2*(exp(-1)+sqrt(pi)*(erf(1)-1))); 10 | f = 1./(1+x.^2); E(3,N) = abs(w*f - pi/2); 11 | f = x.^10; E(4,N) = abs(w*f - 2/11); 12 | end 13 | 14 | % Plot results: 15 | labels = {'|x|^3','exp(-x^{-2})','1/(1+x^2)','x^{10}'}; 16 | for iplot = 1:4, 17 | subplot(3,2,iplot) 18 | semilogy(E(iplot,:)+1e-100,'.','markersize',12), hold on 19 | plot(E(iplot,:)+1e-100) 20 | axis([0 Nmax 1e-18 1e3]), grid on 21 | set(gca,'xtick',0:10:Nmax,'ytick',(10).^(-15:5:0)) 22 | ylabel error, text(32,.004,labels(iplot)) 23 | end 24 | -------------------------------------------------------------------------------- /p30b.m: -------------------------------------------------------------------------------- 1 | % p30b.m - spectral integration, Clenshaw-Curtis style (compare p30.m) 2 | 3 | % Computation: various values of N, four functions: 4 | Nmax = 50; E = zeros(4,Nmax); clf 5 | for N = 1:Nmax; 6 | [x,w] = clencurt(N); 7 | f = abs(x).^3; E(1,N) = abs(w*f - .5); 8 | f = exp(-x.^(-2)); E(2,N) = abs(w*f - ... 9 | 2*(exp(-1)+sqrt(pi)*(erf(1)-1))); 10 | f = 1./(1+x.^2); E(3,N) = abs(w*f - pi/2); 11 | f = x.^10; E(4,N) = abs(w*f - 2/11); 12 | end 13 | 14 | % Plot results: 15 | labels = {'|x|^3','exp(-x^{-2})','1/(1+x^2)','x^{10}'}; 16 | for iplot = 1:4, 17 | subplot(3,2,iplot) 18 | semilogy(E(iplot,:)+1e-100,'.','markersize',12), hold on 19 | semilogy(E(iplot,:)+1e-100) 20 | axis([0 Nmax 1e-18 1e3]), grid on 21 | set(gca,'xtick',0:10:Nmax,'ytick',(10).^(-15:5:0)) 22 | ylabel error, text(32,.004,labels(iplot)) 23 | end 24 | -------------------------------------------------------------------------------- /p30c.m: -------------------------------------------------------------------------------- 1 | % p30c.m - spectral integration, Gauss style (compare p30.m) 2 | 3 | % Computation: various values of N, four functions: 4 | Nmax = 50; E = zeros(4,Nmax); clf 5 | for N = 1:Nmax; 6 | [x,w] = gauss(N); 7 | f = abs(x).^3; E(1,N) = abs(w*f - .5); 8 | f = exp(-x.^(-2)); E(2,N) = abs(w*f - ... 9 | 2*(exp(-1)+sqrt(pi)*(erf(1)-1))); 10 | f = 1./(1+x.^2); E(3,N) = abs(w*f - pi/2); 11 | f = x.^10; E(4,N) = abs(w*f - 2/11); 12 | end 13 | 14 | % Plot results: 15 | labels = {'|x|^3','exp(-x^{-2})','1/(1+x^2)','x^{10}'}; 16 | for iplot = 1:4, 17 | subplot(3,2,iplot) 18 | semilogy(E(iplot,:)+1e-100,'.','markersize',12), hold on 19 | semilogy(E(iplot,:)+1e-100) 20 | axis([0 Nmax 1e-18 1e3]), grid on 21 | set(gca,'xtick',0:10:Nmax,'ytick',(10).^(-15:5:0)) 22 | ylabel error, text(32,.004,labels(iplot)) 23 | end 24 | -------------------------------------------------------------------------------- /p31.m: -------------------------------------------------------------------------------- 1 | % p31.m - gamma function via complex integral, trapezoid rule 2 | 3 | N = 70; theta = -pi + (2*pi/N)*(.5:N-.5)'; 4 | c = -11; % center of circle of integration 5 | r = 16; % radius of circle of integration 6 | x = -3.5:.1:4; y = -2.5:.1:2.5; 7 | [xx,yy] = meshgrid(x,y); zz = xx + 1i*yy; gaminv = 0*zz; 8 | for i = 1:N 9 | t = c + r*exp(1i*theta(i)); 10 | gaminv = gaminv + exp(t)*t.^(-zz)*(t-c); 11 | end 12 | gaminv = gaminv/N; gam = 1./gaminv; clf, mesh(xx,yy,abs(gam)) 13 | axis([-3.5 4 -2.5 2.5 0 6]), xlabel Re(z), ylabel Im(z) 14 | text(4,-1.4,5.5,'|\Gamma(z)|','fontsize',20), colormap(1e-6*[1 1 1]); 15 | -------------------------------------------------------------------------------- /p32.m: -------------------------------------------------------------------------------- 1 | % p32.m - solve u_xx = exp(4x), u(-1)=0, u(1)=1 (compare p13.m) 2 | 3 | N = 16; 4 | [D,x] = cheb(N); 5 | D2 = D^2; 6 | D2 = D2(2:N,2:N); 7 | f = exp(4*x(2:N)); 8 | u = D2\f; 9 | u = [0;u;0] + (x+1)/2; 10 | clf 11 | subplot('position',[.1 .4 .8 .5]) 12 | plot(x,u,'.','markersize',16) 13 | xx = -1:.01:1; 14 | uu = polyval(polyfit(x,u,N),xx); 15 | line(xx,uu), grid on 16 | exact = (exp(4*xx) - sinh(4)*xx - cosh(4))/16 + (xx+1)/2; 17 | title(['max err = ' num2str(norm(uu-exact,inf))],'fontsize',12) 18 | -------------------------------------------------------------------------------- /p33.m: -------------------------------------------------------------------------------- 1 | % p33.m - solve linear BVP u_xx = exp(4x), u'(-1)=u(1)=0 2 | 3 | N = 16; 4 | [D,x] = cheb(N); D2 = D^2; 5 | D2(N+1,:) = D(N+1,:); % Neumann condition at x = -1 6 | D2 = D2(2:N+1,2:N+1); 7 | f = exp(4*x(2:N)); 8 | u = D2\[f;0]; 9 | u = [0;u]; 10 | clf, subplot('position',[.1 .4 .8 .5]) 11 | plot(x,u,'.','markersize',16) 12 | axis([-1 1 -4 0]) 13 | xx = -1:.01:1; 14 | uu = polyval(polyfit(x,u,N),xx); 15 | line(xx,uu) 16 | grid on 17 | exact = (exp(4*xx) - 4*exp(-4)*(xx-1) - exp(4))/16; 18 | title(['max err = ' num2str(norm(uu-exact,inf))],'fontsize',12) 19 | -------------------------------------------------------------------------------- /p34.m: -------------------------------------------------------------------------------- 1 | % p34.m - Allen-Cahn eq. u_t = eps*u_xx+u-u^3, u(-1)=-1, u(1)=1 2 | % (compare p6.m and p32.m) 3 | 4 | % Differentiation matrix and initial data: 5 | N = 20; [D,x] = cheb(N); D2 = D^2; % use full-size matrix 6 | D2([1 N+1],:) = zeros(2,N+1); % for convenience 7 | eps = 0.01; dt = min([.01,50*N^(-4)/eps]); 8 | t = 0; v = .53*x + .47*sin(-1.5*pi*x); 9 | 10 | % Solve PDE by Euler formula and plot results: 11 | tmax = 100; tplot = 2; nplots = round(tmax/tplot); 12 | plotgap = round(tplot/dt); dt = tplot/plotgap; 13 | xx = -1:.025:1; vv = polyval(polyfit(x,v,N),xx); 14 | plotdata = [vv; zeros(nplots,length(xx))]; tdata = t; 15 | for i = 1:nplots 16 | for n = 1:plotgap 17 | t = t+dt; v = v + dt*(eps*D2*(v-x) + v - v.^3); % Euler 18 | end 19 | vv = polyval(polyfit(x,v,N),xx); 20 | plotdata(i+1,:) = vv; tdata = [tdata; t]; 21 | end 22 | clf, subplot('position',[.1 .4 .8 .5]) 23 | mesh(xx,tdata,plotdata), grid on, axis([-1 1 0 tmax -1 1]), 24 | view(-60,55), colormap(1e-6*[1 1 1]); xlabel x, ylabel t, zlabel u 25 | -------------------------------------------------------------------------------- /p35.m: -------------------------------------------------------------------------------- 1 | % p35.m - Allen-Cahn eq. as in p34.m, but with boundary condition 2 | % imposed explicitly ("method (II)") 3 | 4 | % Differentiation matrix and initial data: 5 | N = 20; [D,x] = cheb(N); D2 = D^2; 6 | eps = 0.01; dt = min([.01,50*N^(-4)/eps]); 7 | t = 0; v = .53*x + .47*sin(-1.5*pi*x); 8 | 9 | % Solve PDE by Euler formula and plot results: 10 | tmax = 100; tplot = 2; nplots = round(tmax/tplot); 11 | plotgap = round(tplot/dt); dt = tplot/plotgap; 12 | xx = -1:.025:1; vv = polyval(polyfit(x,v,N),xx); 13 | plotdata = [vv; zeros(nplots,length(xx))]; tdata = t; 14 | for i = 1:nplots 15 | for n = 1:plotgap 16 | t = t+dt; v = v + dt*(eps*D2*v + v - v.^3); % Euler 17 | v(1) = 1 + sin(t/5)^2; v(end) = -1; % BC 18 | end 19 | vv = polyval(polyfit(x,v,N),xx); 20 | plotdata(i+1,:) = vv; tdata = [tdata; t]; 21 | end 22 | clf, subplot('position',[.1 .4 .8 .5]) 23 | mesh(xx,tdata,plotdata), grid on, axis([-1 1 0 tmax -1 2]), 24 | view(-60,55), colormap(1e-6*[1 1 1]); xlabel x, ylabel t, zlabel u 25 | -------------------------------------------------------------------------------- /p36.m: -------------------------------------------------------------------------------- 1 | % p36.m - Laplace eq. on [-1,1]x[-1,1] with nonzero BCs 2 | 3 | % Set up grid and 2D Laplacian, boundary points included: 4 | N = 24; [D,x] = cheb(N); y = x; 5 | [xx,yy] = meshgrid(x,y); xx = xx(:); yy = yy(:); 6 | D2 = D^2; I = eye(N+1); L = kron(I,D2) + kron(D2,I); 7 | 8 | % Impose boundary conditions by replacing appropriate rows of L: 9 | b = find(abs(xx)==1 | abs(yy)==1); % boundary pts 10 | L(b,:) = zeros(4*N,(N+1)^2); L(b,b) = eye(4*N); 11 | rhs = zeros((N+1)^2,1); 12 | rhs(b) = (yy(b)==1).*(xx(b)<0).*sin(pi*xx(b)).^4 + ... 13 | .2*(xx(b)==1).*sin(3*pi*yy(b)); 14 | 15 | % Solve Laplace equation, reshape to 2D, and plot: 16 | u = L\rhs; uu = reshape(u,N+1,N+1); 17 | [xx,yy] = meshgrid(x,y); 18 | [xxx,yyy] = meshgrid(-1:.04:1,-1:.04:1); 19 | uuu = interp2(xx,yy,uu,xxx,yyy,'cubic'); 20 | clf, subplot('position',[.1 .4 .8 .5]) 21 | mesh(xxx,yyy,uuu), colormap(1e-6*[1 1 1]); 22 | axis([-1 1 -1 1 -.2 1]), view(-20,45) 23 | text(0,.8,.4,sprintf('u(0,0) = %12.10f',uu(N/2+1,N/2+1))) 24 | -------------------------------------------------------------------------------- /p37.m: -------------------------------------------------------------------------------- 1 | % p37.m - 2D "wave tank" with Neumann BCs for |y|=1 2 | 3 | % x variable in [-A,A], Fourier: 4 | A = 3; Nx = 50; dx = 2*A/Nx; x = -A+dx*(1:Nx)'; 5 | D2x = (pi/A)^2*toeplitz([-1/(3*(dx/A)^2)-1/6 ... 6 | .5*(-1).^(2:Nx)./sin((pi*dx/A)*(1:Nx-1)/2).^2]); 7 | 8 | % y variable in [-1,1], Chebyshev: 9 | Ny = 15; [Dy,y] = cheb(Ny); D2y = Dy^2; 10 | BC = -Dy([1 Ny+1],[1 Ny+1])\Dy([1 Ny+1],2:Ny); 11 | 12 | % Grid and initial data: 13 | [xx,yy] = meshgrid(x,y); 14 | vv = exp(-8*((xx+1.5).^2+yy.^2)); 15 | dt = 5/(Nx+Ny^2); 16 | vvold = exp(-8*((xx+dt+1.5).^2+yy.^2)); 17 | 18 | % Time-stepping by leap frog formula: 19 | clf, plotgap = round(2/dt); dt = 2/plotgap; 20 | for n = 0:2*plotgap 21 | t = n*dt; 22 | if rem(n+.5,plotgap)<1 23 | subplot(3,1,n/plotgap+1), mesh(xx,yy,vv), view(-10,60) 24 | axis([-A A -1 1 -0.15 1]), colormap(1e-6*[1 1 1]); 25 | text(-2.5,1,.5,['t = ' num2str(t)],'fontsize',18), 26 | set(gca,'ztick',[]), grid off, drawnow 27 | end 28 | vvnew = 2*vv - vvold + dt^2*(vv*D2x +D2y*vv); 29 | vvold = vv; vv = vvnew; 30 | vv([1 Ny+1],:) = BC*vv(2:Ny,:); % Neumann BCs for |y|=1 31 | end 32 | -------------------------------------------------------------------------------- /p38.m: -------------------------------------------------------------------------------- 1 | % p38.m - solve u_xxxx = exp(x), u(-1)=u(1)=u'(-1)=u'(1)=0 2 | % (compare p13.m) 3 | 4 | % Construct discrete biharmonic operator: 5 | N = 15; [D,x] = cheb(N); 6 | S = diag([0; 1 ./(1-x(2:N).^2); 0]); 7 | D4 = (diag(1-x.^2)*D^4 - 8*diag(x)*D^3 - 12*D^2)*S; 8 | D4 = D4(2:N,2:N); 9 | 10 | % Solve boundary-value problem and plot result: 11 | f = exp(x(2:N)); u = D4\f; u = [0;u;0]; 12 | clf, subplot('position',[.1 .4 .8 .5]) 13 | plot(x,u,'.','markersize',16) 14 | axis([-1 1 -.01 .06]), grid on 15 | xx = (-1:.01:1)'; 16 | uu = (1-xx.^2).*polyval(polyfit(x,S*u,N),xx); 17 | line(xx,uu) 18 | 19 | % Determine exact solution and print maximum error: 20 | A = [1 -1 1 -1; 0 1 -2 3; 1 1 1 1; 0 1 2 3]; 21 | V = vander(xx); V = V(:,end:-1:end-3); 22 | c = A\exp([-1 -1 1 1]'); exact = exp(xx) - V*c; 23 | title(['max err = ' num2str(norm(uu-exact,inf))],'fontsize',12) 24 | -------------------------------------------------------------------------------- /p39.m: -------------------------------------------------------------------------------- 1 | % p39.m - eigenmodes of biharmonic on a square with clamped BCs 2 | % (compare p38.m) 3 | 4 | % Construct spectral approximation to biharmonic operator: 5 | N = 17; [D,x] = cheb(N); D2 = D^2; D2 = D2(2:N,2:N); 6 | S = diag([0; 1 ./(1-x(2:N).^2); 0]); 7 | D4 = (diag(1-x.^2)*D^4 - 8*diag(x)*D^3 - 12*D^2)*S; 8 | D4 = D4(2:N,2:N); I = eye(N-1); 9 | L = kron(I,D4) + kron(D4,I) + 2*kron(D2,I)*kron(I,D2); 10 | 11 | % Find and plot 25 eigenmodes: 12 | [V,Lam] = eig(-L); Lam = -real(diag(Lam)); 13 | [Lam,ii] = sort(Lam); ii = ii(1:25); V = real(V(:,ii)); 14 | Lam = sqrt(Lam/Lam(1)); 15 | [xx,yy] = meshgrid(x,x); 16 | [xxx,yyy] = meshgrid(-1:.01:1,-1:.01:1); 17 | [ay,ax] = meshgrid(.8:-.2:0,0:.16:.64); 18 | sq = [1+1i -1+1i -1-1i 1-1i 1+1i]; clf 19 | for i = 1:25 20 | uu = zeros(N+1,N+1); uu(2:N,2:N) = reshape(V(:,i),N-1,N-1); 21 | subplot('position',[ax(i) ay(i) .16 .2]), plot(sq) 22 | uuu = interp2(xx,yy,uu,xxx,yyy,'cubic'); 23 | hold on, contour(xxx,yyy,uuu,[0 0]), axis square 24 | axis (1.25*[-1 1 -1 1]), axis off, colormap(1e-6*[1 1 1]); 25 | text(-.3,1.15,num2str(Lam(i)),'fontsize',7) 26 | end 27 | -------------------------------------------------------------------------------- /p40.m: -------------------------------------------------------------------------------- 1 | % p40.m - eigenvalues of Orr-Sommerfeld operator (compare p38.m) 2 | 3 | R = 5772; clf, [ay,ax] = meshgrid([.56 .04],[.1 .5]); 4 | for N = 40:20:100 5 | 6 | % 2nd- and 4th-order differentiation matrices: 7 | [D,x] = cheb(N); D2 = D^2; D2 = D2(2:N,2:N); 8 | S = diag([0; 1 ./(1-x(2:N).^2); 0]); 9 | D4 = (diag(1-x.^2)*D^4 - 8*diag(x)*D^3 - 12*D^2)*S; 10 | D4 = D4(2:N,2:N); 11 | 12 | % Orr-Sommerfeld operators A,B and generalized eigenvalues: 13 | I = eye(N-1); 14 | A = (D4-2*D2+I)/R - 2i*I - 1i*diag(1-x(2:N).^2)*(D2-I); 15 | B = D2-I; 16 | ee = eig(A,B); 17 | i = N/20-1; subplot('position',[ax(i) ay(i) .38 .38]) 18 | plot(ee,'.','markersize',12) 19 | grid on, axis([-.8 .2 -1 0]), axis square 20 | title(['N = ' int2str(N) ' \lambda_{max} = ' ... 21 | num2str(max(real(ee)),'%16.12f')]), drawnow 22 | end 23 | --------------------------------------------------------------------------------