00001 #include <RaviartThomas.h>
00002 #include <fstream>
00003
00004
00005 int RaviartThomas:: nbf() {
00006 return Ns.size();
00007 }
00008
00009 void RaviartThomas:: compute_basis_functions() {
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
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
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
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
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
00114
00115
00116
00117
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
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
00133 const GiNaC::ex _ex1(1);
00134 for (unsigned i=0; i<ncols; ++i)
00135 id(i, i) = _ex1;
00136
00137
00138
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
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
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
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
00249
00250
00251
00252
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
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
00268 const GiNaC::ex _ex1(1);
00269 for (unsigned i=0; i<ncols; ++i)
00270 id(i, i) = _ex1;
00271
00272
00273
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 }
00293
00294
00295 void RaviartThomas:: set(Polygon& p_) {
00296 StandardFE:: set(p_);
00297 }
00298
00299
00300 void RaviartThomas:: set(int order_) {
00301 StandardFE:: set(order_);
00302 }
00303
00304
00305 GiNaC::ex RaviartThomas:: dof(int i) {
00306 return StandardFE::dof(i);
00307 }
00308
00309
00310 GiNaC::ex RaviartThomas::N(int i) {
00311 return StandardFE::N(i);
00312 }
00313
00314
00315