RaviartThomas.cpp

Go to the documentation of this file.
00001 #include <RaviartThomas.h> 
00002 #include <fstream>
00003 
00004 
00005 int RaviartThomas:: nbf() {
00006   return Ns.size();  
00007 }
00008 
00009 void RaviartThomas:: compute_basis_functions() {
00010 
00011   // see e.g. Brezzi and Fortin book page 116 for the definition
00012   
00013   if (p->str() == "ReferenceLine" || p->str() == "Line" ) { 
00014 
00015     cout <<"Can not define the Raviart-Thomas element on a line"<<endl;  
00016 
00017   } else if (p->str() == "ReferenceTriangle" || p->str() == "Triangle" ) { 
00018 
00019     Triangle& triangle = (Triangle&)(*p); 
00020     GiNaC::lst equations; 
00021     GiNaC::lst variables; 
00022     GiNaC::ex polynom_space1 = bernstein(order-1, triangle, "a"); 
00023     GiNaC::ex polynom1 = polynom_space1.op(0); 
00024     GiNaC::ex polynom1_vars = polynom_space1.op(1); 
00025     GiNaC::ex polynom1_basis = polynom_space1.op(2); 
00026 
00027     GiNaC::lst polynom_space2 = bernsteinv(order-1, triangle, "b"); 
00028     GiNaC::ex polynom2 = polynom_space2.op(0).op(0); 
00029     GiNaC::ex polynom3 = polynom_space2.op(0).op(1); 
00030 
00031 
00032     GiNaC::lst pspace = GiNaC::lst( polynom2 + polynom1*x, 
00033                       polynom3 + polynom1*y);   
00034     GiNaC::lst v2 = collapse(GiNaC::ex_to<GiNaC::lst>(polynom_space2.op(1))); 
00035 
00036 
00037     variables = collapse(GiNaC::lst(polynom_space1.op(1), v2));   
00038 
00039     // remove multiple dofs 
00040     if ( order >= 2) {
00041       GiNaC::ex expanded_pol = GiNaC::expand(polynom1);
00042       for (int c1=0; c1<= order-2;c1++) { 
00043         for (int c2=0; c2<= order-2;c2++) { 
00044           for (int c3=0; c3<= order-2;c3++) {
00045             if ( c1 + c2 + c3 <= order -2 ) {
00046               GiNaC::ex eq =  expanded_pol.coeff(x,c1).coeff(y,c2).coeff(z,c3);  
00047               if ( eq != GiNaC::numeric(0) ) { 
00048                 equations.append(eq == 0); 
00049               }
00050             }
00051           }
00052         }
00053       }
00054     }
00055 
00056     int removed_dofs = equations.nops(); 
00057 
00058 
00059 
00060     GiNaC::ex bernstein_pol; 
00061 
00062     int counter = 0; 
00063     GiNaC::symbol t("t"); 
00064     GiNaC::ex dofi; 
00065     // dofs related to edges  
00066     for (int i=1; i<= 3; i++) {
00067       Line line = triangle.line(i); 
00068       GiNaC::lst normal_vec = normal(triangle, i); 
00069       bernstein_pol = bernstein(order-1, line, istr("a",i));
00070       GiNaC::ex basis_space = bernstein_pol.op(2); 
00071       GiNaC::ex pspace_n = inner(pspace, normal_vec);  
00072 
00073       GiNaC::ex basis; 
00074       for (int i=0; i< basis_space.nops(); i++) {
00075         counter++; 
00076         basis = basis_space.op(i); 
00077         GiNaC::ex integrand = pspace_n*basis; 
00078         dofi =  line.integrate(integrand);  
00079         dofs.insert(dofs.end(), dofi); 
00080         GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00081         equations.append(eq); 
00082 
00083       }
00084     }
00085 
00086     // dofs related to the whole triangle
00087     GiNaC::lst bernstein_polv; 
00088     if ( order > 1) {
00089       counter++; 
00090       bernstein_polv = bernsteinv(order-2, triangle, "a");
00091       GiNaC::ex basis_space = bernstein_polv.op(2); 
00092       for (int i=0; i< basis_space.nops(); i++) {
00093         GiNaC::lst basis = GiNaC::ex_to<GiNaC::lst>(basis_space.op(i)); 
00094         GiNaC::ex integrand = inner(pspace, basis);  
00095         dofi = triangle.integrate(integrand);  
00096         dofs.insert(dofs.end(), dofi); 
00097         GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00098         equations.append(eq); 
00099       }
00100     }
00101     // invert the matrix: 
00102     // GiNaC has a bit strange way to invert a matrix. 
00103     // It solves the system AA^{-1} = Id. 
00104     // It seems that this way is the only way to do
00105     // properly with the solve_algo::gauss flag.  
00106     //
00107     GiNaC::matrix b; GiNaC::matrix A; 
00108     matrix_from_equations(equations, variables, A, b); 
00109 
00110     int ncols = A.cols();  
00111     GiNaC::matrix vars_sq(ncols, ncols);
00112 
00113     // matrix of symbols 
00114     for (unsigned r=0; r<ncols; ++r)
00115       for (unsigned c=0; c<ncols; ++c)
00116         vars_sq(r, c) = GiNaC::symbol();
00117 
00118     GiNaC::matrix id(ncols, ncols);
00119 
00120     // identity 
00121     const GiNaC::ex _ex1(1);
00122     for (unsigned i=0; i<ncols; ++i)
00123       id(i, i) = _ex1;
00124 
00125 
00126     // invert the matrix 
00127     GiNaC::matrix m_inv(ncols, ncols);
00128     m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00129 
00130 
00131     for (int i=0; i<dofs.size(); i++) {
00132       b.let_op(removed_dofs + i) = GiNaC::numeric(1); 
00133       GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b)); 
00134   
00135       GiNaC::lst subs;  
00136       for (int ii=0; ii<xx.nops(); ii++) { 
00137         subs.append(variables.op(ii) == xx.op(ii)); 
00138       }
00139       GiNaC::ex Nj1 = pspace.op(0).subs(subs);   
00140       GiNaC::ex Nj2 = pspace.op(1).subs(subs);   
00141       Ns.insert(Ns.end(), GiNaC::matrix(1,2,GiNaC::lst(Nj1,Nj2))); 
00142       b.let_op(removed_dofs + i) = GiNaC::numeric(0); 
00143     }
00144 
00145   } else if ( p->str() == "ReferenceTetrahedron" || p->str() == "Tetrahedron" ) { 
00146 
00147 
00148     Tetrahedron& tetrahedron = (Tetrahedron&)(*p); 
00149     GiNaC::lst equations; 
00150     GiNaC::lst variables; 
00151     GiNaC::ex polynom_space1 = bernstein(order-1, tetrahedron, "a"); 
00152     GiNaC::ex polynom1 = polynom_space1.op(0); 
00153     GiNaC::ex polynom1_vars = polynom_space1.op(1); 
00154     GiNaC::ex polynom1_basis = polynom_space1.op(2); 
00155 
00156 
00157     GiNaC::lst polynom_space2 = bernsteinv(order-1, tetrahedron, "b"); 
00158     GiNaC::ex polynom2 = polynom_space2.op(0).op(0); 
00159     GiNaC::ex polynom3 = polynom_space2.op(0).op(1); 
00160     GiNaC::ex polynom4 = polynom_space2.op(0).op(2); 
00161 
00162 
00163 
00164     GiNaC::lst pspace = GiNaC::lst( polynom2 + polynom1*x, 
00165                                     polynom3 + polynom1*y,   
00166                                     polynom4 + polynom1*z);   
00167 
00168     GiNaC::lst v2 = collapse(GiNaC::ex_to<GiNaC::lst>(polynom_space2.op(1))); 
00169 
00170 
00171     variables = collapse(GiNaC::lst(polynom_space1.op(1), v2));   
00172 
00173     GiNaC::ex bernstein_pol; 
00174 
00175 
00176     // remove multiple dofs 
00177     if ( order >= 2) {
00178       GiNaC::ex expanded_pol = GiNaC::expand(polynom1);
00179       for (int c1=0; c1<= order-2;c1++) { 
00180         for (int c2=0; c2<= order-2;c2++) { 
00181           for (int c3=0; c3<= order-2;c3++) {
00182             if ( c1 + c2 + c3 <= order -2 ) {
00183               GiNaC::ex eq =  expanded_pol.coeff(x,c1).coeff(y,c2).coeff(z,c3);  
00184               if ( eq != GiNaC::numeric(0) ) { 
00185                 equations.append(eq == 0); 
00186               }
00187             }
00188           }
00189         }
00190       }
00191     }
00192 
00193     int removed_dofs = equations.nops(); 
00194 
00195 
00196 
00197     int counter = 0; 
00198     GiNaC::symbol t("t"); 
00199     GiNaC::ex dofi; 
00200     // dofs related to edges  
00201     for (int i=1; i<= 4; i++) {
00202       Triangle triangle = tetrahedron.triangle(i); 
00203       GiNaC::lst normal_vec = normal(tetrahedron, i); 
00204       bernstein_pol = bernstein(order-1, triangle, istr("a",i));
00205       GiNaC::ex basis_space = bernstein_pol.op(2); 
00206       GiNaC::ex pspace_n = inner(pspace, normal_vec);  
00207 
00208       GiNaC::ex basis; 
00209       for (int i=0; i< basis_space.nops(); i++) {
00210         counter++; 
00211         basis = basis_space.op(i); 
00212         GiNaC::ex integrand = pspace_n*basis; 
00213         dofi =  triangle.integrate(integrand);  
00214         dofs.insert(dofs.end(), dofi); 
00215         GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00216         equations.append(eq); 
00217 
00218       }
00219     }
00220 
00221     // dofs related to the whole tetrahedron 
00222     GiNaC::lst bernstein_polv; 
00223     if ( order > 1) {
00224       counter++; 
00225       bernstein_polv = bernsteinv(order-2, tetrahedron, "a");
00226       GiNaC::ex basis_space = bernstein_polv.op(2); 
00227       for (int i=0; i< basis_space.nops(); i++) {
00228         GiNaC::lst basis = GiNaC::ex_to<GiNaC::lst>(basis_space.op(i)); 
00229         GiNaC::ex integrand = inner(pspace, basis);  
00230         dofi = tetrahedron.integrate(integrand);  
00231         dofs.insert(dofs.end(), dofi); 
00232         GiNaC::ex eq = dofi == GiNaC::numeric(0); 
00233         equations.append(eq); 
00234       }
00235     }
00236     // invert the matrix: 
00237     // GiNaC has a bit strange way to invert a matrix. 
00238     // It solves the system AA^{-1} = Id. 
00239     // It seems that this way is the only way to do
00240     // properly with the solve_algo::gauss flag.  
00241     //
00242     GiNaC::matrix b; GiNaC::matrix A; 
00243     matrix_from_equations(equations, variables, A, b); 
00244 
00245     int ncols = A.cols();  
00246     GiNaC::matrix vars_sq(ncols, ncols);
00247 
00248     // matrix of symbols 
00249     for (unsigned r=0; r<ncols; ++r)
00250       for (unsigned c=0; c<ncols; ++c)
00251         vars_sq(r, c) = GiNaC::symbol();
00252 
00253     GiNaC::matrix id(ncols, ncols);
00254 
00255     // identity 
00256     const GiNaC::ex _ex1(1);
00257     for (unsigned i=0; i<ncols; ++i)
00258       id(i, i) = _ex1;
00259 
00260 
00261     // invert the matrix 
00262     GiNaC::matrix m_inv(ncols, ncols);
00263     m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00264 
00265 
00266     for (int i=0; i<dofs.size(); i++) {
00267       b.let_op(removed_dofs + i) = GiNaC::numeric(1); 
00268       GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b)); 
00269   
00270       GiNaC::lst subs;  
00271       for (int ii=0; ii<xx.nops(); ii++) { 
00272         subs.append(variables.op(ii) == xx.op(ii)); 
00273       }
00274       GiNaC::ex Nj1 = pspace.op(0).subs(subs);   
00275       GiNaC::ex Nj2 = pspace.op(1).subs(subs);   
00276       Ns.insert(Ns.end(), GiNaC::matrix(1,2,GiNaC::lst(Nj1,Nj2))); 
00277       b.let_op(removed_dofs + i) = GiNaC::numeric(0); 
00278     }
00279   }
00280 }
00281 
00282 
00283 void RaviartThomas:: set(Polygon& p_) {
00284   StandardFE:: set(p_); 
00285 }
00286 
00287 
00288 void RaviartThomas:: set(int order_) { 
00289   StandardFE:: set(order_); 
00290 }
00291 
00292 
00293 GiNaC::ex RaviartThomas:: dof(int i) {
00294   return StandardFE::dof(i);  
00295 }
00296 
00297 
00298 GiNaC::ex RaviartThomas::N(int i) {  
00299   return StandardFE::N(i); 
00300 }
00301 
00302 
00303 

Generated on Mon Jan 9 18:08:08 2006 for SyFi by  doxygen 1.4.4