Nedelec2Hdiv.cpp

Go to the documentation of this file.
00001 #include "Nedelec2Hdiv.h" 
00002 #include <fstream>
00003 
00004 using namespace GiNaC;  
00005 
00006 int Nedelec2Hdiv:: nbf() {
00007   return Ns.size();  
00008 }
00009 
00010 void Nedelec2Hdiv:: compute_basis_functions() {
00011 
00012   if ( order < 1 ) {
00013     cout <<"Nedelec2Hdiv elements must be of order 1 or higher."<<endl; 
00014     return; 
00015   }
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   
00025   if (p->str() == "ReferenceLine" || p->str() == "Line" ) { 
00026 
00027     cout <<"Can not define the Nedelec2Hdiv element on a line"<<endl;  
00028 
00029   } else if (p->str() == "ReferenceTriangle" || p->str() == "Triangle" ) { 
00030 
00031     cout <<"Can not define the Nedelec2Hdiv element on a Triangle "<<endl;  
00032 
00033   } else if (p->str() == "ReferenceTetrahedron" || p->str() == "Tetrahedron" ) { 
00034     int k = order; 
00035 
00036     Tetrahedron& tetrahedron= (Tetrahedron&)(*p); 
00037     GiNaC::lst equations; 
00038     GiNaC::lst variables; 
00039 
00040     // create p   
00041     GiNaC::ex P_k = bernsteinv(3,k, tetrahedron, "b"); 
00042     GiNaC::ex P_k_x = P_k.op(0).op(0); 
00043     GiNaC::ex P_k_y = P_k.op(0).op(1); 
00044     GiNaC::ex P_k_z = P_k.op(0).op(2); 
00045 
00046 
00047     GiNaC::lst pspace = GiNaC::lst( P_k_x, P_k_y, P_k_z);  
00048 
00049     variables = collapse(GiNaC::ex_to<GiNaC::lst>(P_k.op(1)));  
00050 
00051     int counter = 0; 
00052     GiNaC::symbol t("t"); 
00053     GiNaC::ex dofi; 
00054     GiNaC::ex bernstein_pol; 
00055 
00056     // dofs related to edges  
00057     for (int i=1; i<= 4; i++) {
00058       Triangle triangle = tetrahedron.triangle(i); 
00059       GiNaC::lst normal_vec = normal(tetrahedron, i); 
00060       bernstein_pol = bernstein(order, triangle, istr("a",i));
00061       GiNaC::ex basis_space = bernstein_pol.op(2); 
00062       GiNaC::ex pspace_n = inner(pspace, normal_vec);  
00063 
00064       GiNaC::ex basis; 
00065       for (int j=0; j< basis_space.nops(); j++) {
00066             counter++; 
00067         basis = basis_space.op(j); 
00068         GiNaC::ex integrand = pspace_n*basis; 
00069         dofi =  triangle.integrate(integrand);  
00070         GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00071         equations.append(eq); 
00072 //        GiNaC::lst d = GiNaC::lst(triangle.integrate(x*basis), 
00073 //                                  triangle.integrate(y*basis), 
00074 //                                  triangle.integrate(z*basis));  
00075         GiNaC::lst d = GiNaC::lst(triangle.vertex(0), 
00076                                   triangle.vertex(1),
00077                                   triangle.vertex(2),j);  
00078 
00079         dofs.insert(dofs.end(), d); 
00080 
00081       }
00082     }
00083 
00084 
00085 
00086     // dofs related to tetrahedron 
00087 
00088     int tetradofs = 0;  
00089     if ( order > 1 ) {
00090       GiNaC::ex bernstein_pol = bernsteinv(3,k-2, tetrahedron, istr("c", 0));
00091       GiNaC::ex basis_space = bernstein_pol.op(2); 
00092       GiNaC::ex basis; 
00093       tetradofs += basis_space.nops(); 
00094       for (int j=0; j<basis_space.nops(); j++) {
00095         basis = basis_space.op(j); 
00096         GiNaC::ex integrand = inner(pspace,basis);   
00097         dofi = tetrahedron.integrate(integrand); 
00098         GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00099         equations.append(eq); 
00100 
00101 //        GiNaC::lst d = GiNaC::lst(tetrahedron.integrate(x*basis.op(0)), 
00102 //                                  tetrahedron.integrate(y*basis.op(1)), 
00103 //                                  tetrahedron.integrate(z*basis.op(2)));  
00104 
00105         GiNaC::lst d = GiNaC::lst(tetrahedron.vertex(0),
00106                                   tetrahedron.vertex(1),
00107                                   tetrahedron.vertex(2),
00108                                   tetrahedron.vertex(3),j);  
00109 
00110 
00111         dofs.insert(dofs.end(), d); 
00112 
00113       }
00114     }
00115 
00116 
00117     // Construction of S_k 
00118     //
00119     //
00120     if ( order >= 1 ) {
00121       GiNaC::ex H_k = homogenous_polv(3,k-1, 3, "a"); 
00122       GiNaC::ex H_k_x = H_k.op(0).op(0); 
00123       GiNaC::ex H_k_y = H_k.op(0).op(1); 
00124       GiNaC::ex H_k_z = H_k.op(0).op(2); 
00125 
00126       GiNaC::lst H_variables = collapse(GiNaC::ex_to<GiNaC::lst>(H_k.op(1))); 
00127 
00128 
00129       // Equations that make sure that r*x = 0
00130 
00131       GiNaC::ex rx = (H_k_x*x + H_k_y*y + H_k_z*z).expand(); 
00132       ex_ex_map pol_map = pol2basisandcoeff(rx); 
00133       ex_ex_it iter; 
00134       GiNaC::lst S_k; 
00135       GiNaC::lst S_k_equations; 
00136 
00137       GiNaC::lst null_eqs; 
00138       for (int i=0; i<H_variables.nops(); i++) { 
00139         null_eqs.append( H_variables.op(i) == 0);  
00140       }
00141 
00142       for (iter = pol_map.begin(); iter != pol_map.end(); iter++) { 
00143         GiNaC::ex coeff = (*iter).second;
00144         GiNaC::ex basis; 
00145         if (coeff.nops() > 1  ) { 
00146           if (coeff.nops()  == 2) {  
00147             S_k_equations.remove_all(); 
00148             S_k_equations.append(coeff.op(0) == GiNaC::numeric(1)); 
00149             S_k_equations.append(coeff.op(1) == GiNaC::numeric(-1)); 
00150             basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);;  
00151             S_k.append(basis); 
00152           } else if ( coeff.nops() == 3 )  {
00153             // 2 basis functions is added 
00154                 // The first: 
00155              
00156             S_k_equations.remove_all(); 
00157             S_k_equations.append(coeff.op(0) == GiNaC::numeric(-1,2)); 
00158             S_k_equations.append(coeff.op(1) == GiNaC::numeric(1)); 
00159             S_k_equations.append(coeff.op(2) == GiNaC::numeric(-1,2)); 
00160             basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);;  
00161             S_k.append(basis); 
00162 
00163                 // The second: 
00164             S_k_equations.remove_all(); 
00165             S_k_equations.append(coeff.op(0) == GiNaC::numeric(-1,2)); 
00166             S_k_equations.append(coeff.op(1) == GiNaC::numeric(-1,2)); 
00167             S_k_equations.append(coeff.op(2) == GiNaC::numeric(1)); 
00168             basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);;  
00169             S_k.append(basis); 
00170           }
00171         }
00172       }
00173 
00174 
00175     // dofs related to tetrahedron 
00176       if ( order >= 1 ) {
00177             GiNaC::ex basis; 
00178             for (int j=0; j<S_k.nops(); j++) {
00179           basis = S_k.op(j); 
00180           GiNaC::ex integrand = inner(pspace,basis);   
00181           dofi = tetrahedron.integrate(integrand); 
00182           GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00183           equations.append(eq); 
00184 
00185           GiNaC::lst d = GiNaC::lst(tetrahedron.vertex(0),
00186                                     tetrahedron.vertex(1),
00187                                     tetrahedron.vertex(2),
00188                                     tetrahedron.vertex(3), tetradofs + j); 
00189 
00190 
00191           dofs.insert(dofs.end(), d); 
00192 
00193         }
00194       }
00195     }
00196 
00197 
00198     // invert the matrix: 
00199     // GiNaC has a bit strange way to invert a matrix. 
00200     // It solves the system AA^{-1} = Id. 
00201     // It seems that this way is the only way to do
00202     // properly with the solve_algo::gauss flag.  
00203     //
00204     GiNaC::matrix b; GiNaC::matrix A; 
00205     matrix_from_equations(equations, variables, A, b); 
00206 
00207     int ncols = A.cols();  
00208     GiNaC::matrix vars_sq(ncols, ncols);
00209 
00210     // matrix of symbols 
00211     for (unsigned r=0; r<ncols; ++r)
00212       for (unsigned c=0; c<ncols; ++c)
00213         vars_sq(r, c) = GiNaC::symbol();
00214 
00215     GiNaC::matrix id(ncols, ncols);
00216 
00217     // identity 
00218     const GiNaC::ex _ex1(1);
00219     for (unsigned i=0; i<ncols; ++i)
00220       id(i, i) = _ex1;
00221 
00222 
00223     // invert the matrix 
00224     GiNaC::matrix m_inv(ncols, ncols);
00225     m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00226 
00227 
00228     for (int i=0; i<dofs.size(); i++) {
00229       b.let_op(i) = GiNaC::numeric(1); 
00230       GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b)); 
00231   
00232       GiNaC::lst subs;  
00233       for (int ii=0; ii<xx.nops(); ii++) { 
00234         subs.append(variables.op(ii) == xx.op(ii)); 
00235       }
00236       GiNaC::ex Nj1 = pspace.op(0).subs(subs);   
00237       GiNaC::ex Nj2 = pspace.op(1).subs(subs);   
00238       GiNaC::ex Nj3 = pspace.op(2).subs(subs);   
00239       Ns.insert(Ns.end(), GiNaC::matrix(1,3,GiNaC::lst(Nj1,Nj2,Nj3))); 
00240       b.let_op(i) = GiNaC::numeric(0); 
00241     }
00242   }
00243 }
00244 
00245 
00246 void Nedelec2Hdiv:: set(Polygon& p_) {
00247   StandardFE:: set(p_); 
00248 }
00249 
00250 
00251 void Nedelec2Hdiv:: set(int order_) { 
00252   StandardFE:: set(order_); 
00253 }
00254 
00255 
00256 GiNaC::ex Nedelec2Hdiv:: dof(int i) {
00257   return StandardFE::dof(i);  
00258 }
00259 
00260 
00261 GiNaC::ex Nedelec2Hdiv::N(int i) {  
00262   return StandardFE::N(i); 
00263 }
00264 
00265 
00266 

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