00001 #include <Nedelec.h>
00002 #include <fstream>
00003
00004
00005 int Nedelec:: nbf() {
00006 return Ns.size();
00007 }
00008
00009 void Nedelec:: compute_basis_functions() {
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
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
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
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
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
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
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
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
00113
00114
00115
00116
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
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
00131 const GiNaC::ex _ex1(1);
00132 for (unsigned i=0; i<ncols; ++i)
00133 id(i, i) = _ex1;
00134
00135
00136
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
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
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
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
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
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
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
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
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
00286
00287
00288
00289
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
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
00304 const GiNaC::ex _ex1(1);
00305 for (unsigned i=0; i<ncols; ++i)
00306 id(i, i) = _ex1;
00307
00308
00309
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,2,GiNaC::lst(Nj1,Nj2,Nj3)));
00326 b.let_op(removed_dofs + i) = GiNaC::numeric(0);
00327 }
00328
00329
00330
00331
00332
00333 }
00334
00335 }
00336
00337
00338 void Nedelec:: set(Polygon& p_) {
00339 StandardFE:: set(p_);
00340 }
00341
00342
00343 void Nedelec:: set(int order_) {
00344 StandardFE:: set(order_);
00345 }
00346
00347
00348 GiNaC::ex Nedelec:: dof(int i) {
00349 return StandardFE::dof(i);
00350 }
00351
00352
00353 GiNaC::ex Nedelec::N(int i) {
00354 return StandardFE::N(i);
00355 }
00356
00357
00358