Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Search for

# LagrangeFE.cpp

Go to the documentation of this file.

    00001 #include <LagrangeFE.h>
    00002 #include <ElementComputations.h>
    00003
    00004 int LagrangeFE:: nbf() {
    00005   return StandardFE::nbf();
    00006 }
    00007
    00008 void LagrangeFE:: compute_basis_functions() {
    00009
    00010   // NOTE: in the below code dof(i) is not used to
    00011   // determine the basis functions
    00012
    00013   if ( order < 1 ) {
    00014     cout <<"Lagrangian elements must be of order 1 or higher."<<endl;
    00015     return;
    00016   }
    00017
    00018   if ( p == NULL ) {
    00019     cout <<"You need to set a polygon before the basisfunctions can be computed"<<endl;
    00020     return;
    00021   }
    00022
    00023
    00024   if (p->str() == "ReferenceLine") {
    00025     // Look at the case with the Triangle for a documented code
    00026     GiNaC::ex polynom;
    00027     GiNaC::lst variables;
    00028
    00029 //    polynom = pol(order, 1, "a");
    00030 //    variables = coeffs(polynom);
    00031     GiNaC::ex polynom_space = bernstein(order, *p, "a");
    00032 //    GiNaC::ex polynom_space = pol(order, 1, "a");
    00033     polynom = polynom_space.op(0);
    00034     variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
    00035
    00036     GiNaC::ex increment = GiNaC::numeric(1,order);
    00037
    00038     GiNaC::ex Nj;
    00039     for (int j=1; j <= order+1; j++) {
    00040       GiNaC::lst equations;
    00041       int i=0;
    00042       for (GiNaC::ex p=0; p<= 1 ; p += increment ) {
    00043         i++;
    00044         GiNaC::ex eq = polynom == dirac(i,j);
    00045         equations.append(eq.subs(x == p));
    00046         if (j == 1) dofs.insert(dofs.end(), p);
    00047       }
    00048
    00049       GiNaC::ex subs = lsolve(equations, variables);
    00050       Nj = polynom.subs(subs);
    00051       Ns.insert(Ns.end(), Nj);
    00052     }
    00053
    00054
    00055   } else if (p->str() == "ReferenceTriangle" ) {
    00056     // Look at the case with the Triangle for a documented code
    00057     GiNaC::ex polynom;
    00058     GiNaC::lst variables;
    00059
    00060 //    polynom = pol(order, 2, "b");
    00061 //    variables = coeffs(polynom);
    00062     GiNaC::ex polynom_space = bernstein(order, *p, "b");
    00063 //    GiNaC::ex polynom_space = pol(order, 2, "a");
    00064     polynom = polynom_space.op(0);
    00065     variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
    00066
    00067     GiNaC::ex increment = GiNaC::numeric(1,order);
    00068
    00069     GiNaC::ex Nj;
    00070     for (int j=1; j <= (order+1)*(order+2)/2; j++) {
    00071       GiNaC::lst equations;
    00072       int i=0;
    00073       GiNaC::numeric one = 1;
    00074       for (GiNaC::ex q=0; q<= one  ; q += increment ) {
    00075         for (GiNaC::ex p=0; p<= one-q ; p += increment ) {
    00076           i++;
    00077           GiNaC::ex eq = polynom == dirac(i,j);
    00078           equations.append(eq.subs(GiNaC::lst(x == p, y == q)));
    00079           if ( j == 1) dofs.insert(dofs.end(), GiNaC::lst(p,q));
    00080         }
    00081       }
    00082
    00083
    00084       GiNaC::ex subs = lsolve(equations, variables);
    00085       Nj = polynom.subs(subs);
    00086       Ns.insert(Ns.end(), Nj);
    00087     }
    00088   }
    00089   else if ( p->str() == "Triangle" ){
    00090     // Look HERE for the documented code
    00091     GiNaC::ex polynom;
    00092     GiNaC::lst variables;
    00093
    00094     GiNaC::ex polynom_space = pol(order, 2, "a");
    00095     // the polynomial spaces on the form:
    00096     // first item:     a0 + a1*x + a2*y + a3*x^2 + a4*x*y ...     the polynom
    00097     // second item:    a0, a1, a2, ...                            the coefficents
    00098     // third  item     1, x, y, x^2, ..                           the basis
    00099     // Could also do:
    00100     // GiNaC::ex polynom_space = bernstein(order, t, "a");
    00101
    00102
    00103     polynom = polynom_space.op(0);
    00104     variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
    00105
    00106     GiNaC::ex Nj;
    00107     Polygon& pp = *p;
    00108     Triangle& t = (Triangle&) pp;
    00109     // The bezier ordinates (in which the basis function should be either 0 or 1)
    00110     GiNaC::lst points = bezier_ordinates(t,order);
    00111
    00112     // Loop over all basis functions Nj and all points.
    00113     // Each basis function Nj is determined by a set of linear equations:
    00114     //   Nj(xi) = dirac(i,j)
    00115     // This system of equations is then solved by lsolve
    00116     for (int j=1; j <= points.nops(); j++) {
    00117       GiNaC::lst equations;
    00118       int i=0;
    00119       for (int i=1; i<= points.nops() ; i++ ) {
    00120         // The point xi
    00121         GiNaC::ex point = points.op(i-1);
    00122         // The equation Nj(xi) = dirac(i,j)
    00123         GiNaC::ex eq = polynom == dirac(i,j);
    00124         // The equation is appended to the list of equations
    00125         equations.append(eq.subs(GiNaC::lst(x == point.op(0) , y == point.op(1))));
    00126         // Creation of dof(j)
    00127         if ( j == 1) dofs.insert(dofs.end(), GiNaC::lst(point.op(0),point.op(1)));
    00128       }
    00129
    00130 //      print(equations);
    00131 //      print(variables);
    00132       // We solve the linear system
    00133       GiNaC::ex subs = lsolve(equations, variables);
    00134       // Substitute to get the Nj
    00135       Nj = polynom.subs(subs);
    00136       // Append Nj to the list of basis functions
    00137       Ns.insert(Ns.end(), Nj);
    00138
    00139       // NOTE: In this case we create a linear system and solve it for each Nj.
    00140       // However, the matrix is always the same, it is only the right-hand side
    00141       // that changes. Hence, it is possible to optimize here.
    00142
    00143     }
    00144
    00145   } else if ( p->str() == "ReferenceTetrahedron" ) {
    00146     // Look at the case with the Triangle for a documented code
    00147     GiNaC::ex polynom;
    00148     GiNaC::lst variables;
    00149
    00150 //    polynom = pol(order, 3, "b");
    00151 //    GiNaC::ex polynom_space = pol(order, 3, "a");
    00152     GiNaC::ex polynom_space = bernstein(order, *p, "b");
    00153     polynom = polynom_space.op(0);
    00154     variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
    00155
    00156
    00157     int nno =0;
    00158     for (int j=0; j<= order; j++) {
    00159       nno += (j+1)*(j+2)/2;
    00160     }
    00161
    00162     GiNaC::ex increment = GiNaC::numeric(1,order);
    00163
    00164     GiNaC::ex Nj;
    00165     for (int j=1; j <= nno; j++) {
    00166       GiNaC::lst equations;
    00167       int i=0;
    00168       for (GiNaC::ex r=0; r<= 1 ; r += increment ) {
    00169         for (GiNaC::ex q=0; q<= 1-r ; q += increment ) {
    00170           for (GiNaC::ex p=0; p<= 1-r-q ; p += increment ) {
    00171             i++;
    00172             GiNaC::ex eq = polynom == dirac(i,j);
    00173             equations.append(eq.subs(GiNaC::lst(x == p, y == q, z == r )));
    00174             if (j == 1) dofs.insert(dofs.end(), GiNaC::lst(p,q,r));
    00175           }
    00176         }
    00177       }
    00178
    00179       GiNaC::ex subs = lsolve(equations, variables);
    00180       Nj = polynom.subs(subs);
    00181       Ns.insert(Ns.end(), Nj);
    00182     }
    00183   }
    00184   else if ( p->str() == "Tetrahedron" ){
    00185     // Look at the case with the Triangle for a documented code
    00186     GiNaC::ex polynom;
    00187     GiNaC::lst variables;
    00188
    00189
    00190     GiNaC::ex polynom_space = pol(order, 3, "a");
    00191 //    GiNaC::ex polynom_space = bernstein(order, *p, "b");
    00192     polynom = polynom_space.op(0);
    00193     variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
    00194
    00195
    00196     GiNaC::ex increment = GiNaC::numeric(1,order);
    00197
    00198     GiNaC::ex Nj;
    00199     Polygon& pp = *p;
    00200     Tetrahedron& t = (Tetrahedron&) pp;
    00201     GiNaC::lst points = bezier_ordinates(t,order);
    00202     for (int j=1; j <= points.nops(); j++) {
    00203       GiNaC::lst equations;
    00204       int i=0;
    00205       for (int i=1; i<= points.nops() ; i++ ) {
    00206         GiNaC::ex point = points.op(i-1);
    00207         GiNaC::ex eq = polynom == dirac(i,j);
    00208         equations.append(eq.subs(GiNaC::lst(x == point.op(0) , y == point.op(1), z == point.op(2))));
    00209         if ( j == 1) dofs.insert(dofs.end(), GiNaC::lst(point.op(0),point.op(1),point.op(2)));
    00210       }
    00211
    00212       GiNaC::ex subs = lsolve(equations, variables);
    00213       Nj = polynom.subs(subs);
    00214       Ns.insert(Ns.end(), Nj);
    00215     }
    00216   }
    00217 }
    00218
    00219
    00220
    00221 void LagrangeFE:: set(Polygon& p_) {
    00222   StandardFE::set(p_);
    00223 }
    00224
    00225
    00226 void LagrangeFE:: set(int order_) {
    00227   StandardFE::set(order_);
    00228 }
    00229
    00230
    00231 GiNaC::ex LagrangeFE:: dof(int i) {
    00232   return StandardFE::dof(i);
    00233 }
    00234
    00235
    00236 GiNaC::ex LagrangeFE::N(int i) {
    00237   return StandardFE::N(i);
    00238 }
    00239
    00240 // ------------VectorLagrangeFE ---
    00241
    00242 int VectorLagrangeFE:: nbf() {
    00243   return StandardFE::nbf();
    00244 }
    00245
    00246 void VectorLagrangeFE:: compute_basis_functions() {
    00247
    00248   if ( order < 1 ) {
    00249     cout <<"Lagrangian elements must be of order 1 or higher."<<endl;
    00250     return;
    00251   }
    00252
    00253
    00254   if ( p == NULL ) {
    00255     cout <<"You need to set a polygon before the basisfunctions can be computed"<<endl;
    00256     return;
    00257   }
    00258
    00259
    00260   LagrangeFE fe;
    00261   fe.set(order);
    00262   fe.set(*p);
    00263   fe.compute_basis_functions();
    00264   GiNaC::lst zero_list;
    00265   for (int s=1; s<= size ; s++) {
    00266     zero_list.append(0);
    00267   }
    00268
    00269   for (int i=0; i< fe.nbf() ; i++) {
    00270     for (int s=0; s< size ; s++) {
    00271       GiNaC::lst Nis = zero_list;
    00272       Nis.let_op(s) = fe.N(i);
    00273       GiNaC::ex Nmat = GiNaC::matrix(size,1,Nis);
    00274       Ns.insert(Ns.end(), Nmat);
    00275
    00276       GiNaC::lst dof = GiNaC::lst(fe.dof(i), s) ;
    00277       dofs.insert(dofs.end(), dof);
    00278     }
    00279   }
    00280 }
    00281
    00282
    00283 void VectorLagrangeFE:: set_size(int size_) {
    00284   size = size_;
    00285 }
    00286
    00287
    00288 void VectorLagrangeFE:: set(Polygon& p_) {
    00289   StandardFE::set(p_);
    00290 }
    00291
    00292
    00293 void VectorLagrangeFE:: set(int order_) {
    00294   StandardFE::set(order_);
    00295 }
    00296
    00297
    00298 GiNaC::ex VectorLagrangeFE:: dof(int i) {
    00299   return StandardFE::dof(i);
    00300 }
    00301
    00302
    00303 GiNaC::ex VectorLagrangeFE::N(int i) {
    00304   return StandardFE::N(i);
    00305 }
    00306
    00307
    00308
    00309
    00310