00001 #include "Nedelec2Hdiv.h"
00002 #include <fstream>
00003
00004 using namespace GiNaC;
00005
00006 int Nedelec2Hdiv:: nbf() {
00007 return Ns.size();
00008 }
00009
00010 void Nedelec2Hdiv:: compute_basis_functions() {
00011
00012 if ( order < 1 ) {
00013 cout <<"Nedelec2Hdiv elements must be of order 1 or higher."<<endl;
00014 return;
00015 }
00016
00017
00018 if ( p == NULL ) {
00019 cout <<"You need to set a polygon before the basisfunctions can be computed"<<endl;
00020 return;
00021 }
00022
00023
00024
00025 if (p->str() == "ReferenceLine" || p->str() == "Line" ) {
00026
00027 cout <<"Can not define the Nedelec2Hdiv element on a line"<<endl;
00028
00029 } else if (p->str() == "ReferenceTriangle" || p->str() == "Triangle" ) {
00030
00031 cout <<"Can not define the Nedelec2Hdiv element on a Triangle "<<endl;
00032
00033 } else if (p->str() == "ReferenceTetrahedron" || p->str() == "Tetrahedron" ) {
00034 int k = order;
00035
00036 Tetrahedron& tetrahedron= (Tetrahedron&)(*p);
00037 GiNaC::lst equations;
00038 GiNaC::lst variables;
00039
00040
00041 GiNaC::ex P_k = bernsteinv(3,k, tetrahedron, "b");
00042 GiNaC::ex P_k_x = P_k.op(0).op(0);
00043 GiNaC::ex P_k_y = P_k.op(0).op(1);
00044 GiNaC::ex P_k_z = P_k.op(0).op(2);
00045
00046
00047 GiNaC::lst pspace = GiNaC::lst( P_k_x, P_k_y, P_k_z);
00048
00049 variables = collapse(GiNaC::ex_to<GiNaC::lst>(P_k.op(1)));
00050
00051 int counter = 0;
00052 GiNaC::symbol t("t");
00053 GiNaC::ex dofi;
00054 GiNaC::ex bernstein_pol;
00055
00056
00057 for (int i=1; i<= 4; i++) {
00058 Triangle triangle = tetrahedron.triangle(i);
00059 GiNaC::lst normal_vec = normal(tetrahedron, i);
00060 bernstein_pol = bernstein(order, triangle, istr("a",i));
00061 GiNaC::ex basis_space = bernstein_pol.op(2);
00062 GiNaC::ex pspace_n = inner(pspace, normal_vec);
00063
00064 GiNaC::ex basis;
00065 for (int j=0; j< basis_space.nops(); j++) {
00066 counter++;
00067 basis = basis_space.op(j);
00068 GiNaC::ex integrand = pspace_n*basis;
00069 dofi = triangle.integrate(integrand);
00070 GiNaC::ex eq = dofi == GiNaC::numeric(0);
00071 equations.append(eq);
00072
00073
00074
00075 GiNaC::lst d = GiNaC::lst(triangle.vertex(0),
00076 triangle.vertex(1),
00077 triangle.vertex(2),j);
00078
00079 dofs.insert(dofs.end(), d);
00080
00081 }
00082 }
00083
00084
00085
00086
00087
00088 int tetradofs = 0;
00089 if ( order > 1 ) {
00090 GiNaC::ex bernstein_pol = bernsteinv(3,k-2, tetrahedron, istr("c", 0));
00091 GiNaC::ex basis_space = bernstein_pol.op(2);
00092 GiNaC::ex basis;
00093 tetradofs += basis_space.nops();
00094 for (int j=0; j<basis_space.nops(); j++) {
00095 basis = basis_space.op(j);
00096 GiNaC::ex integrand = inner(pspace,basis);
00097 dofi = tetrahedron.integrate(integrand);
00098 GiNaC::ex eq = dofi == GiNaC::numeric(0);
00099 equations.append(eq);
00100
00101
00102
00103
00104
00105 GiNaC::lst d = GiNaC::lst(tetrahedron.vertex(0),
00106 tetrahedron.vertex(1),
00107 tetrahedron.vertex(2),
00108 tetrahedron.vertex(3),j);
00109
00110
00111 dofs.insert(dofs.end(), d);
00112
00113 }
00114 }
00115
00116
00117
00118
00119
00120 if ( order >= 1 ) {
00121 GiNaC::ex H_k = homogenous_polv(3,k-1, 3, "a");
00122 GiNaC::ex H_k_x = H_k.op(0).op(0);
00123 GiNaC::ex H_k_y = H_k.op(0).op(1);
00124 GiNaC::ex H_k_z = H_k.op(0).op(2);
00125
00126 GiNaC::lst H_variables = collapse(GiNaC::ex_to<GiNaC::lst>(H_k.op(1)));
00127
00128
00129
00130
00131 GiNaC::ex rx = (H_k_x*x + H_k_y*y + H_k_z*z).expand();
00132 ex_ex_map pol_map = pol2basisandcoeff(rx);
00133 ex_ex_it iter;
00134 GiNaC::lst S_k;
00135 GiNaC::lst S_k_equations;
00136
00137 GiNaC::lst null_eqs;
00138 for (int i=0; i<H_variables.nops(); i++) {
00139 null_eqs.append( H_variables.op(i) == 0);
00140 }
00141
00142 for (iter = pol_map.begin(); iter != pol_map.end(); iter++) {
00143 GiNaC::ex coeff = (*iter).second;
00144 GiNaC::ex basis;
00145 if (coeff.nops() > 1 ) {
00146 if (coeff.nops() == 2) {
00147 S_k_equations.remove_all();
00148 S_k_equations.append(coeff.op(0) == GiNaC::numeric(1));
00149 S_k_equations.append(coeff.op(1) == GiNaC::numeric(-1));
00150 basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);;
00151 S_k.append(basis);
00152 } else if ( coeff.nops() == 3 ) {
00153
00154
00155
00156 S_k_equations.remove_all();
00157 S_k_equations.append(coeff.op(0) == GiNaC::numeric(-1,2));
00158 S_k_equations.append(coeff.op(1) == GiNaC::numeric(1));
00159 S_k_equations.append(coeff.op(2) == GiNaC::numeric(-1,2));
00160 basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);;
00161 S_k.append(basis);
00162
00163
00164 S_k_equations.remove_all();
00165 S_k_equations.append(coeff.op(0) == GiNaC::numeric(-1,2));
00166 S_k_equations.append(coeff.op(1) == GiNaC::numeric(-1,2));
00167 S_k_equations.append(coeff.op(2) == GiNaC::numeric(1));
00168 basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);;
00169 S_k.append(basis);
00170 }
00171 }
00172 }
00173
00174
00175
00176 if ( order >= 1 ) {
00177 GiNaC::ex basis;
00178 for (int j=0; j<S_k.nops(); j++) {
00179 basis = S_k.op(j);
00180 GiNaC::ex integrand = inner(pspace,basis);
00181 dofi = tetrahedron.integrate(integrand);
00182 GiNaC::ex eq = dofi == GiNaC::numeric(0);
00183 equations.append(eq);
00184
00185 GiNaC::lst d = GiNaC::lst(tetrahedron.vertex(0),
00186 tetrahedron.vertex(1),
00187 tetrahedron.vertex(2),
00188 tetrahedron.vertex(3), tetradofs + j);
00189
00190
00191 dofs.insert(dofs.end(), d);
00192
00193 }
00194 }
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204 GiNaC::matrix b; GiNaC::matrix A;
00205 matrix_from_equations(equations, variables, A, b);
00206
00207 int ncols = A.cols();
00208 GiNaC::matrix vars_sq(ncols, ncols);
00209
00210
00211 for (unsigned r=0; r<ncols; ++r)
00212 for (unsigned c=0; c<ncols; ++c)
00213 vars_sq(r, c) = GiNaC::symbol();
00214
00215 GiNaC::matrix id(ncols, ncols);
00216
00217
00218 const GiNaC::ex _ex1(1);
00219 for (unsigned i=0; i<ncols; ++i)
00220 id(i, i) = _ex1;
00221
00222
00223
00224 GiNaC::matrix m_inv(ncols, ncols);
00225 m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00226
00227
00228 for (int i=0; i<dofs.size(); i++) {
00229 b.let_op(i) = GiNaC::numeric(1);
00230 GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b));
00231
00232 GiNaC::lst subs;
00233 for (int ii=0; ii<xx.nops(); ii++) {
00234 subs.append(variables.op(ii) == xx.op(ii));
00235 }
00236 GiNaC::ex Nj1 = pspace.op(0).subs(subs);
00237 GiNaC::ex Nj2 = pspace.op(1).subs(subs);
00238 GiNaC::ex Nj3 = pspace.op(2).subs(subs);
00239 Ns.insert(Ns.end(), GiNaC::matrix(1,3,GiNaC::lst(Nj1,Nj2,Nj3)));
00240 b.let_op(i) = GiNaC::numeric(0);
00241 }
00242 }
00243 }
00244
00245
00246 void Nedelec2Hdiv:: set(Polygon& p_) {
00247 StandardFE:: set(p_);
00248 }
00249
00250
00251 void Nedelec2Hdiv:: set(int order_) {
00252 StandardFE:: set(order_);
00253 }
00254
00255
00256 GiNaC::ex Nedelec2Hdiv:: dof(int i) {
00257 return StandardFE::dof(i);
00258 }
00259
00260
00261 GiNaC::ex Nedelec2Hdiv::N(int i) {
00262 return StandardFE::N(i);
00263 }
00264
00265
00266