function [A,g,xmesh,ucomp,uval] = fe_quadratic(M,a,c,f) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % function [A,g,xmesh,ucomp,uval] = fe_quadratic(M,a,c,f) % This function uses a Galerkin finite element method with % quadratic elements to form an approximate solution to the % differential equation % -(a(x) u'(x))' + c(x) u(x) = f(x) for x in (0,1) % with u(0)=u(1)=0. % % The function a should satisfy a(x) \ge a_0 > 0 on (0,1), % and the function c should satisfy c(x) \ge 0 on (0,1). % % Inputs: % M defines the number of unknowns, 2 floor(M/2)-1. % a, c, and f are user-defined Matlab functions. % Their input is a row or column vector of x coordinates % in the interval [0,1], and their output is a vector of % values of a(x), c(x), or f(x). % The function a also has a second output argument, a vector of % values of a'(x). % % Outputs: % A is the matrix from which the coefficients of the solution are % computed. % g is the right-hand side of the matrix problem. % xmesh contains the endpoints of the intervals interior to % [0,1] and also the midpoints of the intervals. % ucomp is the vector of coefficients of the solution in the % finite element basis. % uval is the vector of values of the computed u at % the points h/2, h, 3h/2, ... 1-h/2, where h = 1/m. % % The method uses the weak formulation of the equation % to compute an approximate solution: % a(u,v) = (f,v) for all piecewise quadratic functions v % where u(x) = ucomp(1) psi_1(x) + ucomp(2) phi_1(x) + ... % + ucomp(2(m-1)-1) psi_{m-1}(x) % + ucomp(2(m-1)) phi_{m-1}(x) + ucomp(2m-1) psi_m(x) . % Here, % a(u,v) = int(a(x) u'(x) v'(x) + c(x) u(x) v(x)) dx, % (f,v) = int(f(x) v(x)) dx, % and the limits of integration are [0,1]. % % The phi basis functions are linear hat-functions: % phi_j (x_j) = 1, phi_j (x_k) = 0 for j not equal to k, % and phi_j is zero outside the interval [x_{j-1},x_{j+1}]. % The psi basis functions are quadratic hat-functions: % psi_j(x_j) = 0, psi_j(x_{j-1}) = 0, psi_j((x_j + x_{j-1})/2) = 1, % and psi_j is zero outside the interval [x_{j-1},x_{j}]. % The number of intervals is m. % The vector x contains the endpoints of the intervals, % each of length h. % fe_quadratic.m Dianne P. O'Leary January 2005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Initialize some parameters. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% m = floor(M/2); x = linspace(0,1,m+1); h = x(2); h2inv = 1/h^2; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % The vector xmesh contains the endpoints of the intervals % interior to [0,1] and also the midpoints of the intervals. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% xmesh = linspace(h/2,1-h/2,2*m-1)'; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % We order the basis functions as % psi_1, phi_1 , ... psi_{m-1}, phi_{m-1}, psi_m. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Compute the matrix and the right-hand side in order % to solve for the coefficients ucomp of the approximate solution. % The matrix is symmetric, made up of 5 diagonals. % The (j,k) element is a(v_k,v_j), where v_k is the % k-th basis function. % The j-th element of the right-hand side is (f,v_j). % % The data for the main diagonal is stored in diag0. % The data for the first superdiagonal is stored in diag1. % The data for the second super diagonal is stored in diag2. % The data for the right-hand side is stored in rhs. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diag0 = zeros(2*m-1,1); diag1 = zeros(2*m-1,1); diag2 = zeros(2*m-1,1); rhs = zeros(2*m-1,1); for i=1:m rhs (2*i-1) = quad(@fxquad,x(i ),x(i+1),1.e-6,0, h,x(i)); %(f,psi_i) diag0(2*i-1) = quad(@axquad,x(i ),x(i+1),1.e-6,0, h,x(i)); %a(psi_i,psi_i) if (i < m) rhs (2*i ) = quad(@fxlin,x(i ),x(i+1),1.e-6,0, h,x(i )) ... + quad(@fxlin,x(i+1),x(i+2),1.e-6,0,-h,x(i+2)); %(f,phi_i) diag0(2*i ) = quad(@axlin,x(i ),x(i+1),1.e-6,0, h,x(i)) ... + quad(@axlin,x(i+1),x(i+2),1.e-6,0,-h,x(i+2)); %a(phi_i,phi_i) diag1(2*i-1) = quad(@axliqu,x(i ),x(i+1),1.e-6,0, h,x(i)); %a(psi_i,phi_{i}) diag1(2*i ) = quad(@axliqu,x(i+1),x(i+2),1.e-6,0,-h,x(i+1)); %a(psi_{i+1},phi_{i}) end if (i < m-1) diag2(2*i ) = quad(@bxlin,x(i+1),x(i+2),1.e-6,0, h,x(i+1),x(i+2)); %a(phi_i,phi_{i+1}) end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Form the matrix and solve the linear system. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diag1u = [0; diag1(1:2*m-2)]; diag2u = [0;0;diag2(1:2*m-3)]; A = spdiags([diag2,diag1,diag0,diag1u,diag2u],-2:2,2*m-1,2*m-1); g = rhs; ucomp = A \ g; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Compute the function value at the m-1 interior mesh points and % the midpoints of each of the intervals. % The value at the midpoint of an interval is the coefficient of % the quadratic basis function plus the values contributed by the % one or two linear basis functions that are nonzero there. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% uval= ucomp; uval(1) = uval(1) + .5*uval(2); for i=3:2:2*m-3, uval(i) = uval(i) + .5*(uval(i-1)+uval(i+1)); end uval(2*m-1) = uval(2*m-1) + .5*uval(2*m-2);