Nedelec.cpp

Go to the documentation of this file.
00001 #include "Nedelec.h" 
00002 #include <fstream>
00003 
00004 
00005 int Nedelec:: nbf() {
00006   return Ns.size();  
00007 }
00008 
00009 void Nedelec:: compute_basis_functions() {
00010 
00011   if ( order < 1 ) {
00012     cout <<"Nedelec elements must be of order 1 or higher."<<endl; 
00013     return; 
00014   }
00015 
00016 
00017   if ( p == NULL ) {
00018     cout <<"You need to set a polygon before the basisfunctions can be computed"<<endl; 
00019     return; 
00020   }
00021  
00022 
00023   
00024   if (p->str() == "ReferenceLine" || p->str() == "Line" ) { 
00025 
00026     cout <<"Can not define the Nedelec element on a line"<<endl;  
00027 
00028   } else if (p->str() == "ReferenceTriangle" || p->str() == "Triangle" ) { 
00029 
00030     int k = order; 
00031     int removed_dofs=0; 
00032 
00033     Triangle& triangle = (Triangle&)(*p); 
00034     GiNaC::lst equations; 
00035     GiNaC::lst variables; 
00036 
00037     // create r
00038     GiNaC::ex R_k = homogenous_polv(2,k+1, 2, "a"); 
00039     GiNaC::ex R_k_x = R_k.op(0).op(0); 
00040     GiNaC::ex R_k_y = R_k.op(0).op(1); 
00041 
00042 
00043     // Equations that make sure that r*x = 0
00044     GiNaC::ex rx = (R_k_x*x + R_k_y*y).expand(); 
00045     ex_ex_map pol_map = pol2basisandcoeff(rx); 
00046     ex_ex_it iter; 
00047     for (iter = pol_map.begin(); iter != pol_map.end(); iter++) { 
00048       if ((*iter).second != 0 ) { 
00049         equations.append((*iter).second == 0 ); 
00050         removed_dofs++; 
00051       }
00052     }
00053 
00054 
00055 
00056     // create p   
00057     GiNaC::ex P_k = bernsteinv(2,k, triangle, "b"); 
00058     GiNaC::ex P_k_x = P_k.op(0).op(0); 
00059     GiNaC::ex P_k_y = P_k.op(0).op(1); 
00060 
00061 
00062 
00063     // collect the variables of r and p  in one list
00064     variables = collapse(GiNaC::lst(collapse(GiNaC::ex_to<GiNaC::lst>(R_k.op(1))), 
00065                                     collapse(GiNaC::ex_to<GiNaC::lst>(P_k.op(1)))));
00066 
00067     // create the polynomial space
00068     GiNaC::lst pspace = GiNaC::lst( R_k_x + P_k_x, 
00069                                     R_k_y + P_k_y);   
00070 
00071     int counter = 0; 
00072     GiNaC::symbol t("t"); 
00073     GiNaC::ex dofi; 
00074     // dofs related to edges  
00075     for (int i=1; i<= 3; i++) {
00076       Line line = triangle.line(i); 
00077       GiNaC::lst tangent_vec = tangent(triangle, i); 
00078       GiNaC::ex bernstein_pol = bernstein(order, line, istr("a",i));
00079       GiNaC::ex basis_space = bernstein_pol.op(2); 
00080       GiNaC::ex pspace_t = inner(pspace, tangent_vec);  
00081 
00082       GiNaC::ex basis; 
00083       for (int j=0; j< basis_space.nops(); j++) {
00084         counter++; 
00085         basis = basis_space.op(j); 
00086         GiNaC::ex integrand = pspace_t*basis; 
00087         dofi =  line.integrate(integrand);  
00088         dofs.insert(dofs.end(), dofi); 
00089         GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00090         equations.append(eq); 
00091       }
00092     }
00093 
00094     // dofs related to the whole triangle
00095     GiNaC::lst bernstein_polv; 
00096     if ( order > 0) {
00097       counter++; 
00098       bernstein_polv = bernsteinv(2,order-1, triangle, "a");
00099       GiNaC::ex basis_space = bernstein_polv.op(2); 
00100       for (int i=0; i< basis_space.nops(); i++) {
00101         GiNaC::lst basis = GiNaC::ex_to<GiNaC::lst>(basis_space.op(i)); 
00102         GiNaC::ex integrand = inner(pspace, basis);  
00103         dofi = triangle.integrate(integrand);  
00104         dofs.insert(dofs.end(), dofi); 
00105         GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00106         equations.append(eq); 
00107       }
00108     }
00109 
00110 
00111 
00112     // invert the matrix: 
00113     // GiNaC has a bit strange way to invert a matrix. 
00114     // It solves the system AA^{-1} = Id. 
00115     // It seems that this way is the only way to do
00116     // properly with the solve_algo::gauss flag.  
00117     GiNaC::matrix b; GiNaC::matrix A; 
00118     matrix_from_equations(equations, variables, A, b); 
00119 
00120     int ncols = A.cols();  
00121     GiNaC::matrix vars_sq(ncols, ncols);
00122 
00123     // matrix of symbols 
00124     for (unsigned r=0; r<ncols; ++r)
00125       for (unsigned c=0; c<ncols; ++c)
00126         vars_sq(r, c) = GiNaC::symbol();
00127 
00128     GiNaC::matrix id(ncols, ncols);
00129 
00130     // identity 
00131     const GiNaC::ex _ex1(1);
00132     for (unsigned i=0; i<ncols; ++i)
00133       id(i, i) = _ex1;
00134 
00135 
00136     // invert the matrix 
00137     GiNaC::matrix m_inv(ncols, ncols);
00138     m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00139 
00140 
00141     for (int i=0; i<dofs.size(); i++) {
00142       b.let_op(removed_dofs + i) = GiNaC::numeric(1); 
00143       GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b)); 
00144   
00145       GiNaC::lst subs;  
00146       for (int ii=0; ii<xx.nops(); ii++) { 
00147         subs.append(variables.op(ii) == xx.op(ii)); 
00148       }
00149       GiNaC::ex Nj1 = pspace.op(0).subs(subs);   
00150       GiNaC::ex Nj2 = pspace.op(1).subs(subs);   
00151       Ns.insert(Ns.end(), GiNaC::matrix(1,2,GiNaC::lst(Nj1,Nj2))); 
00152       b.let_op(removed_dofs + i) = GiNaC::numeric(0); 
00153     }
00154 
00155   } else if ( p->str() == "ReferenceTetrahedron" || p->str() == "Tetrahedron" ) { 
00156 
00157     int k = order; 
00158     int removed_dofs=0; 
00159 
00160     Tetrahedron& tetrahedron= (Tetrahedron&)(*p); 
00161     GiNaC::lst equations; 
00162     GiNaC::lst variables; 
00163 
00164     // create r
00165     GiNaC::ex R_k = homogenous_polv(3,k+1, 3, "a"); 
00166     GiNaC::ex R_k_x = R_k.op(0).op(0); 
00167     GiNaC::ex R_k_y = R_k.op(0).op(1); 
00168     GiNaC::ex R_k_z = R_k.op(0).op(2); 
00169 
00170     // Equations that make sure that r*x = 0
00171     GiNaC::ex rx = (R_k_x*x + R_k_y*y + R_k_z*z).expand(); 
00172     ex_ex_map pol_map = pol2basisandcoeff(rx); 
00173     ex_ex_it iter; 
00174     for (iter = pol_map.begin(); iter != pol_map.end(); iter++) { 
00175       if ((*iter).second != 0 ) { 
00176         equations.append((*iter).second == 0 ); 
00177         removed_dofs++; 
00178       }
00179     }
00180 
00181 
00182     // create p   
00183     GiNaC::ex P_k = bernsteinv(3,k, tetrahedron, "b"); 
00184     GiNaC::ex P_k_x = P_k.op(0).op(0); 
00185     GiNaC::ex P_k_y = P_k.op(0).op(1); 
00186     GiNaC::ex P_k_z = P_k.op(0).op(2); 
00187 
00188     // collect the variables of r and p  in one list
00189     variables = collapse(GiNaC::lst(collapse(GiNaC::ex_to<GiNaC::lst>(R_k.op(1))), 
00190                                     collapse(GiNaC::ex_to<GiNaC::lst>(P_k.op(1)))));
00191 
00192 
00193 
00194     // create the polynomial space
00195     GiNaC::lst pspace = GiNaC::lst( R_k_x + P_k_x, 
00196                                     R_k_y + P_k_y,   
00197                                     R_k_z + P_k_z);   
00198 
00199 
00200     int counter = 0; 
00201     GiNaC::symbol t("t"); 
00202     GiNaC::ex dofi; 
00203 
00204     // dofs related to edges  
00205     for (int i=1; i<= 6; i++) {
00206       Line line = tetrahedron.line(i); 
00207       GiNaC::ex line_repr = line.repr(t); 
00208       GiNaC::lst tangent_vec = GiNaC::lst(line_repr.op(0).rhs().coeff(t,1),  
00209                                           line_repr.op(1).rhs().coeff(t,1),  
00210                                           line_repr.op(2).rhs().coeff(t,1));  
00211 
00212 
00213       GiNaC::ex bernstein_pol = bernstein(order, line, istr("a",i));
00214       GiNaC::ex basis_space = bernstein_pol.op(2); 
00215       GiNaC::ex pspace_t = inner(pspace, tangent_vec);  
00216 
00217       GiNaC::ex basis; 
00218       for (int j=0; j< basis_space.nops(); j++) {
00219         counter++; 
00220         basis = basis_space.op(j); 
00221         GiNaC::ex integrand = pspace_t*basis; 
00222         dofi =  line.integrate(integrand);  
00223         dofs.insert(dofs.end(), dofi); 
00224         GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00225         equations.append(eq); 
00226       }
00227     }
00228 
00229 
00230     // dofs related to faces
00231     if ( order > 0 ) {
00232       for (int i=1; i<= 4; i++){
00233         Triangle triangle = tetrahedron.triangle(i); 
00234         GiNaC::ex bernstein_pol = bernsteinv(3,order-1, triangle, istr("b", i));
00235         GiNaC::ex basis_space = bernstein_pol.op(2); 
00236   
00237         GiNaC::ex basis; 
00238         GiNaC::lst normal_vec = normal(tetrahedron, i); 
00239         GiNaC::ex pspace_n = cross(pspace, normal_vec);  
00240         if ( normal_vec.op(0) != GiNaC::numeric(0) && 
00241              normal_vec.op(1) != GiNaC::numeric(0) && 
00242              normal_vec.op(2) != GiNaC::numeric(0) )    
00243         {
00244           for (int j=0; j<basis_space.nops(); j++) {
00245             basis = basis_space.op(j); 
00246             if ( basis.op(0) != 0 || basis.op(1) != 0 ) {
00247               GiNaC::ex integrand = inner(pspace_n,basis);   
00248               if ( integrand != GiNaC::numeric(0) ) { 
00249                 dofi = triangle.integrate(integrand); 
00250                 GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00251                 equations.append(eq); 
00252               }
00253             }
00254           }
00255 
00256         } else {
00257           for (int j=0; j<basis_space.nops(); j++) {
00258             basis = basis_space.op(j); 
00259             GiNaC::ex integrand = inner(pspace_n,basis);   
00260             if ( integrand != GiNaC::numeric(0) ) { 
00261               dofi = triangle.integrate(integrand); 
00262               GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00263               equations.append(eq); 
00264             }
00265           }
00266         }
00267       }
00268     }
00269 
00270     // dofs related to tetrahedron 
00271     if ( order > 1 ) {
00272       GiNaC::ex bernstein_pol = bernsteinv(3,order-2, tetrahedron, istr("c", 0));
00273       GiNaC::ex basis_space = bernstein_pol.op(2); 
00274       GiNaC::ex basis; 
00275       for (int j=0; j<basis_space.nops(); j++) {
00276         basis = basis_space.op(j); 
00277         GiNaC::ex integrand = inner(pspace,basis);   
00278         dofi = tetrahedron.integrate(integrand); 
00279         GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00280         equations.append(eq); 
00281       }
00282     }
00283 
00284 
00285     // invert the matrix: 
00286     // GiNaC has a bit strange way to invert a matrix. 
00287     // It solves the system AA^{-1} = Id. 
00288     // It seems that this way is the only way to do
00289     // properly with the solve_algo::gauss flag.  
00290     GiNaC::matrix b; GiNaC::matrix A; 
00291     matrix_from_equations(equations, variables, A, b); 
00292 
00293     int ncols = A.cols();  
00294     GiNaC::matrix vars_sq(ncols, ncols);
00295 
00296     // matrix of symbols 
00297     for (unsigned r=0; r<ncols; ++r)
00298       for (unsigned c=0; c<ncols; ++c)
00299         vars_sq(r, c) = GiNaC::symbol();
00300 
00301     GiNaC::matrix id(ncols, ncols);
00302 
00303     // identity 
00304     const GiNaC::ex _ex1(1);
00305     for (unsigned i=0; i<ncols; ++i)
00306       id(i, i) = _ex1;
00307 
00308 
00309     // invert the matrix 
00310     GiNaC::matrix m_inv(ncols, ncols);
00311     m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00312 
00313 
00314     for (int i=0; i<dofs.size(); i++) {
00315       b.let_op(removed_dofs + i) = GiNaC::numeric(1); 
00316       GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b)); 
00317   
00318       GiNaC::lst subs;  
00319       for (int ii=0; ii<xx.nops(); ii++) { 
00320         subs.append(variables.op(ii) == xx.op(ii)); 
00321       }
00322       GiNaC::ex Nj1 = pspace.op(0).subs(subs);   
00323       GiNaC::ex Nj2 = pspace.op(1).subs(subs);   
00324       GiNaC::ex Nj3 = pspace.op(2).subs(subs);   
00325       Ns.insert(Ns.end(), GiNaC::matrix(1,3,GiNaC::lst(Nj1,Nj2,Nj3))); 
00326       b.let_op(removed_dofs + i) = GiNaC::numeric(0); 
00327     }
00328 
00329 
00330 
00331 
00332 
00333   }
00334 
00335 }
00336 
00337 
00338 void Nedelec:: set(Polygon& p_) {
00339   StandardFE:: set(p_); 
00340 }
00341 
00342 
00343 void Nedelec:: set(int order_) { 
00344   StandardFE:: set(order_); 
00345 }
00346 
00347 
00348 GiNaC::ex Nedelec:: dof(int i) {
00349   return StandardFE::dof(i);  
00350 }
00351 
00352 
00353 GiNaC::ex Nedelec::N(int i) {  
00354   return StandardFE::N(i); 
00355 }
00356 
00357 
00358 

Generated on Tue Jun 13 13:18:39 2006 for SyFi by  doxygen 1.4.4