#include <RaviartThomas.h>
Inheritance diagram for RaviartThomas:
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) |
Definition at line 8 of file RaviartThomas.h.
|
Definition at line 10 of file RaviartThomas.h.
|
|
Definition at line 11 of file RaviartThomas.h.
|
|
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 Ns.insert(Ns.end(), GiNaC::matrix(1,2,GiNaC::lst(Nj1,Nj2))); 00289 b.let_op(removed_dofs + i) = GiNaC::numeric(0); 00290 } 00291 } 00292 }
|
|
Reimplemented from StandardFE. Definition at line 305 of file RaviartThomas.cpp. References StandardFE::dof(). 00305 { 00306 return StandardFE::dof(i); 00307 }
|
|
Reimplemented from StandardFE. Definition at line 310 of file RaviartThomas.cpp. References StandardFE::N(). Referenced by main(). 00310 { 00311 return StandardFE::N(i); 00312 }
|
|
Reimplemented from StandardFE. Definition at line 5 of file RaviartThomas.cpp. References StandardFE::Ns. Referenced by main(). 00005 { 00006 return Ns.size(); 00007 }
|
|
Reimplemented from StandardFE. Definition at line 295 of file RaviartThomas.cpp. References StandardFE::set(). 00295 { 00296 StandardFE:: set(p_); 00297 }
|
|
Reimplemented from StandardFE. Definition at line 300 of file RaviartThomas.cpp. References StandardFE::set(). Referenced by check_RaviartThomas(), and main(). 00300 { 00301 StandardFE:: set(order_); 00302 }
|