#include <Nedelec.h>
Inheritance diagram for Nedelec:
Public Member Functions | |
Nedelec () | |
virtual | ~Nedelec () |
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 Nedelec.h.
|
Definition at line 10 of file Nedelec.h.
|
|
Definition at line 11 of file Nedelec.h.
|
|
Reimplemented from StandardFE. Definition at line 9 of file Nedelec.cpp. References bernstein(), bernsteinv(), collapse(), cross(), StandardFE::dofs, homogenous_polv(), inner(), Tetrahedron::integrate(), Triangle::integrate(), Line::integrate(), istr(), Tetrahedron::line(), Triangle::line(), matrix_from_equations(), normal(), StandardFE::Ns, StandardFE::order, StandardFE::p, pol2basisandcoeff(), Line::repr(), Polygon::str(), tangent(), Tetrahedron::triangle(), x, y, and z. Referenced by main(). 00009 { 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 }
|
|
Reimplemented from StandardFE. Definition at line 348 of file Nedelec.cpp. References StandardFE::dof(). 00348 { 00349 return StandardFE::dof(i); 00350 }
|
|
Reimplemented from StandardFE. Definition at line 353 of file Nedelec.cpp. References StandardFE::N(). 00353 { 00354 return StandardFE::N(i); 00355 }
|
|
Reimplemented from StandardFE. Definition at line 5 of file Nedelec.cpp. References StandardFE::Ns. 00005 { 00006 return Ns.size(); 00007 }
|
|
Reimplemented from StandardFE. Definition at line 338 of file Nedelec.cpp. References StandardFE::set(). 00338 { 00339 StandardFE:: set(p_); 00340 }
|
|
Reimplemented from StandardFE. Definition at line 343 of file Nedelec.cpp. References StandardFE::set(). Referenced by main(). 00343 { 00344 StandardFE:: set(order_); 00345 }
|