Homework #4. (Due Oct. 8.) Math. 610:600 (Last modified on 2015-10-01 10:45) In this assignment, we shall investigate the implementation of finite elements. The goal will be to keep things as simple as possible while keeping a reasonable amount of generality. The key to the understanding (or the developing) of a finite element code is the role played by the elements and the degrees of freedom. In the simplest case (one dimension, piecewise linear approximation) the elements consist of linear functions on intervals [xi , xi+1 ]. The global degrees of freedom are the values of the finite element functions on the nodes. The finite element method employs degrees of freedom to impose continuity conditions on the approximation subspace. For example, continuity of the global finite element functions is forced by selecting the end points as degrees of freedom so that the left and right limits are the same. The pseudo code below is mean to illustrate concepts in FE programming. It has to be converted into whatever language you plan to use to do the assignment. There is a distinction between “local” and “global” properties (or data structure). For the one dimensional problem, these are as follows: Local finite element attributes, EL[j]. (a) Element geometry, i.e., the endpoints of the interval. (b) An integer, ndof l setting the number of local DOFS, in this case, ndof l = k + 1 where k is the degree of the piecewise polynomial over the interval. This determines the set of shape function, namely, P k , the set of polynomials of degree at most k. (c) Local to global node list: an integer array loc global of ndof l values indexing into the global node list. Associated function routines. (a) We require a routine that generates quadrature information for the element. In more general situations the quadrature routines can depend on the element. For this assignment, you can use the same quadrature generator idependent of the polynomial degrees: [weighs, nodes, nq] = QU AD GEN (EL[j]); 1 2 Here and below, we use the matlab notation [...] indicating return values. In addition, nq is the number of quadrature nodes for this element, weights and nodes give the list of weights and nodes. Initially, we will use the two point Gaussian quadrature: Z 1 √ f (x) dx ≈ f (η) + f (−η), η = 1/ 3. −1 The routine QU AD GEN needs to translate the quadrature to the j’th element interval and pass the appropriate node and weight information. (This will be discussed in recitation). (b) A basis function evaluation routine: [P hi] = EV AL P HI(nodes, nq, EL[j]); The array P hi is nq × EL[j].ndof l and P hi[q][m] gives the value at the q’th quadrature node of the m’th basis function. (c) A basis function derivative evaluation routine: [P hip] = EV AL P HI DER(nodes, nq, EL[j]); The array P hip is also nq × EL[j].ndof l. (d) A routine which computes the local stiffness matrix: [lstif f ] = LOC ST IF F (weights, nodes, nq, mxeval, bxeval, axeval, P hi, P hip, ndof l); See below for mxeval, bxeval, axeval. (e) A routine which computes the local RHS contributions [lrhs] = LOC RHS(weights, nodes, nq, f xeval, P hi, ndof l); The problem which we are considering is m(x)u + b(x)u′ − (a(x)u′ )′ = f on (0, 1), u′ (0) = u′ (1) = 0. Problem attributes. (a) Coefficient routines for evaluating coefficients in the equation: [mx] = mxeval(node), [bx1] = bxeval(node), and [ax] = axeval(node). For higher dimensional problems, bxeval returns a vector. (b) Coefficient routines for providing boundary data although not in the first assignment. (c) A coefficient routine for evaluation of f , i.e., [f x] = f xeval(node). 3 As discussed in class and recitation, the matrix and right had side assembly is done by looping through the list of finite elements EL[j]. The code looks like: for (j=0;j<M;j++) // M is the number of finite elements { // compute quadrature nodes,weights, shape functions and derivatives [weights,nodes,nq]=QUAD_GEN(EL[j]); [Phi] = EVAL_PHI(nodes,nq,EL[j]); [Phip] = EVAL_PHI_DER(nodes,nq,EL[j]); [lstiff]=LOC_STIFF(weights,nodes,nq,mxeval,bxeval, axeval,Phi,Phip,EL[j].ndofl); [lrhs]=LOC_RHS(weights,nodes,nq,fxeval,Phi,EL[j].ndofl); // add in the increments to the sparse global matrix and rhs vector. for (m=0;m<EL[j].ndofl;m++) { for (l=0;l<EL[j].ndofl;l++) { // add the increment to the appropriate entry in the sparse matrix tA. add_increment(tA,EL[j].loc_global[l],EL[j].loc_global[m],lstiff[m][l]); // initially, when using full matrices, the above line becomes tA[EL[j].loc_global[l]][EL[j].loc_global[m]]+=lstiff[m][l]; } // add the local contributions into rhs rhs[EL[j].loc_global[m]]+=lrhs[m]; } } // end of the j loop 4 The computation of the local stiffness matrix looks like [lstiff]=LOC_STIFF(weights,nodes,nq,mxeval,bxeval,axeval,Phi,Phip,ndofl); Initialize lstiff to zero; for (q=0;q<nq;q++) // quad node loop { mx=mxeval(nodes[q]); bx1=bxeval(nodes[q]); ax=axeval(nodes[q]); for (l=0;l<ndofl;l++) for (m=0;m<ndofl;m++) lstiff[l][m]+=(mx*Phi[q][l]*Phi[q][m]+bx1*Phip[q][l]*Phi[q][m] +ax*Phip[q][l]*Phip[q][m])*weights[q]; } Problem 1. Compute the approximation to the solution of u − ((x + 1)u′ )′ = f, ′ ′ x ∈ (0, 1) u (0) = u (1) = 0 with f (x) = cos(πx)(1 + π 2 (x + 1)) + π sin(πx). The analytic solution is u(x) = cos(πx). Use a mesh of N + 1 equally space points xj = (j − 1)/N , j = 1, 2, . . . , N + 1. For N = 4, 8, 16, 32, 64, 128, compute the approximate solution uh using continuous piecewise linears. For each N , report the discrete L2 error, ǫN = kuh − uk := [(e21 + 2e22 + . . . 2e2N + e2N +1 )/(2N )]1/2 . Here ej := uh (xj ) − u(xj ). You should be able to see the asymptotic rate by computing RAT E = ln(ǫN /ǫN +1 )/ln(2); (report this as well). This number will settle down as N gets large. 5 Problem 2. Switch to continuous piecewise quadratic approximation keeping the intervals as above. You will need to change ndof l, the global node list, and the loc global lists. You will have to create new EV AL P HI and EV AL P HIP routines. You will also have to modify the error routine computation (still using the above formula and interval endpoints). All other routines should remain unchanged. Make the same runs as in Problem 1 above but with quadratics. Problem 3. Repeat the above two problems but instead approximate the solution of u + u′ − u′′ = f, x ∈ (0, 1) u′ (0) = u′ (1) = 0 with f = cos(πx)(1+π 2 )−π sin(πx). The solution is again given by cos(πx). This problem no longer results in a symmetric matrix but the bilinear form is still coercive. Of course, to switch to this problem, you need only change the coefficient routines. You will have to be careful invert the stiffness matrix (and not its transpose).