• LINE3: Continue your 1D finite element program. Write "program3", which adds new stuff to program2. Add a function called BASIS, to evaluate any finite element basis function.
                function value = basis ( t, x, n, j )
                T is a position between BCLEFT and BCRIGHT.
                X is the list of nodes you defined earlier.
                N is the number of nodes.
                J is an index between 1 and N (or 0 and N-1).
              
    Depending on the language you use, the details will differ, but the idea will be roughly that you have to handle the first and last values of J separately; you have to determine which two values of X surround the value of T, and then evaluate the appropriate linear function (up, down, or zero).
                value = 0
                if J = 1, then:
                  if T < X(2),            value = ( X(2) - T ) / ( X(2) - X(1) );
                if 1 < J < N then:
                  if X(J-1) <  T <= X(J), value = ( T - X(J-1) ) / ( X(J) - X(J-1) ),
                  if X(J)   <= T < X(J+1) value = (X(J+1) - T ) / ( X(J+1) - X(J) );
                if J = N then:
                  if X(N-1) <  T <= X(N), value = ( T - X(N-1) ) / ( X(N) - X(N-1) ).
              
    Verify that your function is working correctly by having program 3 creating a plot of the values of basis function number J=4, using N = 11 points for the mesh, and 101 equally spaced points T in [BCLEFT,BCRIGHT] for the plot.
  • LINE4: Continue your 1D finite element program. Write "program4", which adds new stuff to program 3. Evaluate the interpolant to sin(2*pi*t). We still have BCLEFT=0, BCRIGHT=1, N=11 and our points X. Define a vector C of length N, and set C(J) to be the value of sin(2*pi*X(J)). Our interpolant is
                s(t) = c(1) * b(1)(t) + c(2) * b(2)(t) + ...+ c(n) * b(n)(t).  
              
    where b(1)(t) is the first basis function, evaluated at t, and so on. Compare s(t) and sin(2*pi*t) at 101 equally spaced points in [0,1], with a plot or a table.
  • LINE5: Continue your 1D finite element program. Make a copy of program4 and call it program5. We are going to add another tool to the program, which can compute the derivative of any basis function. In program5, make a copy of the basis function code, and call it BASISP. It will look almost the same as basis:
                function value = basisp ( t, x, n, j )
              
    but now we want it to evaluate the derivative of a basis function. Because we are only using piecewise linear functions so far, the derivatives will be very simple to compute:
                if J = 1, then:
                  if T < X(2),            value = -1 / ( X(2) - X(1) );
                if 1 < J < N then:
                  if X(J-1) <  T <= X(J), value = +1 / ( X(J) - X(J-1) ),
                  if X(J)   <= T < X(J+1) value = -1 / ( X(J+1) - X(J) );
                if J = N then:
                  if X(N-1) <  T <= X(N), value = +1 / ( X(N) - X(N-1) ).
              
    Verify that your function is working correctly by creating a plot of the derivative of basis function number J=4, using N = 11 points for the mesh, and 101 equally spaced points T in [BCLEFT,BCRIGHT] for the plot.
  • LINE6: Numerical integration for 1D. Make a copy of program5 and call it program 6 The linear system that will define our solution involves integrals. We will approximate those integrals using a 2 point quadrature rule:
                integral(a<=x<=b) f(x) dx = (b-a) * ( w1 * f(x1) + w2 * f(x2) ).
              
    Here, Using this rule, and assuming we use N=11 equally spaced nodes on [0,1] as usual, estimate the following integrals, printing your answer each time:
    1. integral ( 0 <= x <= 1 ) cos(2*pi*x) dx;
    2. integral ( ELEMENT #3 ) cos(2*pi*x) dx;
    3. integral ( ELEMENT #3 ) basis(#4) dx;
    4. integral ( ELEMENT #3 ) basisp(#3) dx.
    5. integral ( ELEMENT #3 ) basis(#3) * basis(#4) dx;
    Except for the first integral, we only want to consider the integral over the region that "belongs" to element 3.
  • LINE7: The Stiffness Matrix. Make a copy of program6 and call it program 7. Set up a matrix A of size N by N, where N is the number of nodes. We want A(i,j) to be the integral over the whole region of the product of the derivatives of basis functions i and j:
                A(i,j) = integral basisp(i,x) * basisp(j,x) dx
              
    It can be tricky to handle the cases when I=1 and I=N. The cleanest way is to do the following:
                For each ELEMENT
                  For I = E(1:2,ELEMENT)
                    For J = E(1:2,ELEMENT)
                      A(i,j) = A(i,j) 
                        + integral ( x in ELEMENT ) basisp(i,x) * basisp(j,x) dx
              
    In other words, do the integral one element at a time. Most of the entries of A(i,j) will be zero. Most of the other entries will be simple, especially if you use N = 11.
  • LINE8: The Right Hand Side. Make a new program called program 8, which is a copy of program 7, plus some new stuff. Supposing the right hand side of our differential equation is f(x), we now need to compute a vector called RHS, again using integration. Define a vector RHS of size (N) or, in MATLAB, of size (N,1). We want to compute
                RHS(i) = integral ( 0 <= x <= 1 ) f(x) * basis(i,x) dx
              
    Again, we fill in the values by considering each element:
                For each ELEMENT
                  For I = E(1:2,ELEMENT)
                    RHS(i) = RHS(i) 
                      + integral ( x in ELEMENT ) f(x) * basisp(i,x) dx
              
    Use F(X) = -exp(x), use N = 11, compute RHS, and print it.
  • LINE9: Boundary conditions. You now have a matrix A and right hand side vector RHS. However, we need to adjust A and RHS to account for boundary conditions at the first node, X(1), and the last node, X(N). All the entries in row 1 of A should be zeroed out, except that A(1,1) should be set to 1. RHS(1) should be set to the boundary value. For this problem, that value is 0. Similarly, set all the entries in row N of the matrix A to zero, except that A(N,N) is 1, and set RHS(N) to 0. Print A and RHS.
  • LINE10: Solve the system. Make a new program #10 which is a copy of program #9. We want to solve the linear system
                A*C=RHS
              
    for C, the coefficients of the finite element basis functions. If you are working in MATLAB, this solution step is easy. If you are working in C/C++ or Fortran, you need to locate a linear solver you can use. Print out the 11 entries of your solution vector C.
  • LINE11: Tabulate the solution. Copy your previous program and call it program 11. We want to display the solution as a table, and as a graph. Given the coefficients C, the finite element estimate of the solution at any point X is
                UHAT(X) = sum ( 1 <= I <= N ) C(I) * BASIS(I,X)
              
    Use 25 equally spaced points to print a table of UHAT(X). Use 101 equally spaced points to create a plot.
  • LINE12: Compare computed and exact solution at nodes. Copy your previous program and call it program 12. Our finite element program was solving the following problem:
                -u'' = - exp(x), u(0) = u(1) = 0.
              
    The exact solution to this problem is
                u(x) = exp(x) + x - x exp(1) - 1
              
    Use 101 equally spaced points to create a "line" plot of your solution, AND a "dot" plot of the exact solution. Expect the line to go right through the dots. The error at the nodes is easy to compute, because at those special places, we have that uhat(x(i)) = c(i), so:
                error = u(x(i)) - uhat(x(i)) = u(x(i)) - c(i)
              
    Print the error at the N=11 nodes.
  • LINE13: Compare computed and exact solution as an integral. Copy your previous program and call it program 13. Estimate the following integral:
                L2 = sqrt ( integral ( 0 <= X <= 1 ) ( U(X) - UHAT(X) )^2 dx )
              
    This is a complicated operation. Think about it in small steps, starting with the idea of integrating over a single element.
  • LINE14: We want to solve a new problem of the form
                - u'' + 2 * u = 6x^2 - 8x + 4, for 0 <= x <= 1
              
    with boundary conditions
                u(0) = 5, u(1) = 4.
              
    In order to do this, we have to modify our finite element system:
                integral [ u'*b' + 2*u*b ] dx = integral [ (6x^2-8x+4)*b ] dx
              
    We have new boundary conditions and a different right hand side, but the big change is that our matrix A now includes something called the "mass matrix". To set up this new matrix, do the following:
                For each ELEMENT
                  For I = E(1:2,ELEMENT)
                    For J = E(1:2,ELEMENT)
                      A(i,j) = A(i,j) 
                        + integral ( x in ELEMENT )     basisp(i,x) * basisp(j,x) dx
                        + integral ( x in ELEMENT ) 2 * basis(i,x)  * basis(j,x)  dx
              
    Using N=11 nodes on [0,1] as usual, set up and solve this new linear system. Compare your computed answer UHAT to the exact answer U(X)=3x^2-4x+5.
  • LINE15: Ordinarily, in MATLAB, you solve a linear system A*x=b by writing x=A\b. In other computer languages, you have to write out the instructions to do the solution, or find a prewritten library routine. For the finite element method, one alternative is to use a simple iterative method. The Jacobi iterative method starts with an approximate solution x0 to the linear system, and tries to return an improved estimate x1. The formula is:
                x1(i) = ( b(i) - sum ( j =/= i ) A(i,j) * x0(j) ) / A(i,i)  
              
    Write a function like this: function x1 = jacobi ( A, x0, b ) which does one step of the Jacobi iteration. Let A be the 11x11 matrix which looks like this: [ 2 -1 0 0 0 ...0 0 ] [ -1 2 -1 0 0 ...0 0 ] [ 0 -1 2 -1 0 ...0 0 ] ... [ 0 0 0 0 0 ..-1 2 ] let b be the vector [ 0, 0, 0, ..., 0, 11 ] and let the starting vector x0 be [ 1, 1, 1, ..., 1 ]. The norm of the residual r is the maximum value of |A * x - b|. What is the residual for x0? Compute the improved Jacobi estimate x1. What is the residual for x1? Use x1 as the input to jacobi to get x2, and repeat this process 10 times, so that you get x10. Print the residuals for x0 through x10.
  • LINE16: Write a program which starts with the matrix A, right hand side b, and initial guess x0 that we used in the previous example. But now the program must repeatedly call jacobi until the norm of the residual is less than 0.00001. When you satisfy this tolerance, print out the number of iterations you took, and the estimated solution.
  • LINE17: Make a copy of PROGRAM14, but now use your Jacobi function to solve the linear system, instead of Matlab's solver. Again, try to get an answer for which the residual is less than 0.00001. How many times did you have to call jacobi?