RaviartThomas Class Reference

#include <RaviartThomas.h>

Inheritance diagram for RaviartThomas:

StandardFE FE List of all members.

Public Member Functions

 RaviartThomas ()
virtual ~RaviartThomas ()
virtual void set (int order)
virtual void set (Polygon &p)
virtual void compute_basis_functions ()
virtual int nbf ()
virtual GiNaC::ex N (int i)
virtual GiNaC::ex dof (int i)

Detailed Description

Definition at line 8 of file RaviartThomas.h.


Constructor & Destructor Documentation

RaviartThomas::RaviartThomas  )  [inline]
 

Definition at line 10 of file RaviartThomas.h.

00010 {}

virtual RaviartThomas::~RaviartThomas  )  [inline, virtual]
 

Definition at line 11 of file RaviartThomas.h.

00011 {}


Member Function Documentation

void RaviartThomas::compute_basis_functions  )  [virtual]
 

Reimplemented from StandardFE.

Definition at line 9 of file RaviartThomas.cpp.

References bernstein(), bernsteinv(), collapse(), StandardFE::dofs, inner(), Tetrahedron::integrate(), Triangle::integrate(), Line::integrate(), istr(), Triangle::line(), matrix_from_equations(), normal(), StandardFE::Ns, StandardFE::order, StandardFE::p, Polygon::str(), Tetrahedron::triangle(), x, y, and z.

Referenced by check_RaviartThomas(), and main().

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

GiNaC::ex RaviartThomas::dof int  i  )  [virtual]
 

Reimplemented from StandardFE.

Definition at line 306 of file RaviartThomas.cpp.

References StandardFE::dof().

00306                                  {
00307   return StandardFE::dof(i);  
00308 }

GiNaC::ex RaviartThomas::N int  i  )  [virtual]
 

Reimplemented from StandardFE.

Definition at line 311 of file RaviartThomas.cpp.

References StandardFE::N().

Referenced by main().

00311                               {  
00312   return StandardFE::N(i); 
00313 }

int RaviartThomas::nbf  )  [virtual]
 

Reimplemented from StandardFE.

Definition at line 5 of file RaviartThomas.cpp.

References StandardFE::Ns.

Referenced by main().

00005                         {
00006   return Ns.size();  
00007 }

void RaviartThomas::set Polygon p  )  [virtual]
 

Reimplemented from StandardFE.

Definition at line 296 of file RaviartThomas.cpp.

References StandardFE::set().

00296                                     {
00297   StandardFE:: set(p_); 
00298 }

void RaviartThomas::set int  order  )  [virtual]
 

Reimplemented from StandardFE.

Definition at line 301 of file RaviartThomas.cpp.

References StandardFE::set().

Referenced by check_RaviartThomas(), and main().

00301                                    { 
00302   StandardFE:: set(order_); 
00303 }


The documentation for this class was generated from the following files:
Generated on Tue Jun 13 13:18:43 2006 for SyFi by  doxygen 1.4.4