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
00012
00013 if (p->str() == "ReferenceLine" || p->str() == "Line" ) {
00014
00015 cout <<"Can not define the Raviart-Thomas element on a line"<<endl;
00016
00017 } else if (p->str() == "ReferenceTriangle" || p->str() == "Triangle" ) {
00018
00019 Triangle& triangle = (Triangle&)(*p);
00020 GiNaC::lst equations;
00021 GiNaC::lst variables;
00022 GiNaC::ex polynom_space1 = bernstein(order-1, triangle, "a");
00023 GiNaC::ex polynom1 = polynom_space1.op(0);
00024 GiNaC::ex polynom1_vars = polynom_space1.op(1);
00025 GiNaC::ex polynom1_basis = polynom_space1.op(2);
00026
00027 GiNaC::lst polynom_space2 = bernsteinv(order-1, triangle, "b");
00028 GiNaC::ex polynom2 = polynom_space2.op(0).op(0);
00029 GiNaC::ex polynom3 = polynom_space2.op(0).op(1);
00030
00031
00032 GiNaC::lst pspace = GiNaC::lst( polynom2 + polynom1*x,
00033 polynom3 + polynom1*y);
00034 GiNaC::lst v2 = collapse(GiNaC::ex_to<GiNaC::lst>(polynom_space2.op(1)));
00035
00036
00037 variables = collapse(GiNaC::lst(polynom_space1.op(1), v2));
00038
00039
00040 if ( order >= 2) {
00041 GiNaC::ex expanded_pol = GiNaC::expand(polynom1);
00042 for (int c1=0; c1<= order-2;c1++) {
00043 for (int c2=0; c2<= order-2;c2++) {
00044 for (int c3=0; c3<= order-2;c3++) {
00045 if ( c1 + c2 + c3 <= order -2 ) {
00046 GiNaC::ex eq = expanded_pol.coeff(x,c1).coeff(y,c2).coeff(z,c3);
00047 if ( eq != GiNaC::numeric(0) ) {
00048 equations.append(eq == 0);
00049 }
00050 }
00051 }
00052 }
00053 }
00054 }
00055
00056 int removed_dofs = equations.nops();
00057
00058
00059
00060 GiNaC::ex bernstein_pol;
00061
00062 int counter = 0;
00063 GiNaC::symbol t("t");
00064 GiNaC::ex dofi;
00065
00066 for (int i=1; i<= 3; i++) {
00067 Line line = triangle.line(i);
00068 GiNaC::lst normal_vec = normal(triangle, i);
00069 bernstein_pol = bernstein(order-1, line, istr("a",i));
00070 GiNaC::ex basis_space = bernstein_pol.op(2);
00071 GiNaC::ex pspace_n = inner(pspace, normal_vec);
00072
00073 GiNaC::ex basis;
00074 for (int i=0; i< basis_space.nops(); i++) {
00075 counter++;
00076 basis = basis_space.op(i);
00077 GiNaC::ex integrand = pspace_n*basis;
00078 dofi = line.integrate(integrand);
00079 dofs.insert(dofs.end(), dofi);
00080 GiNaC::ex eq = dofi == GiNaC::numeric(0);
00081 equations.append(eq);
00082
00083 }
00084 }
00085
00086
00087 GiNaC::lst bernstein_polv;
00088 if ( order > 1) {
00089 counter++;
00090 bernstein_polv = bernsteinv(order-2, triangle, "a");
00091 GiNaC::ex basis_space = bernstein_polv.op(2);
00092 for (int i=0; i< basis_space.nops(); i++) {
00093 GiNaC::lst basis = GiNaC::ex_to<GiNaC::lst>(basis_space.op(i));
00094 GiNaC::ex integrand = inner(pspace, basis);
00095 dofi = triangle.integrate(integrand);
00096 dofs.insert(dofs.end(), dofi);
00097 GiNaC::ex eq = dofi == GiNaC::numeric(0);
00098 equations.append(eq);
00099 }
00100 }
00101
00102
00103
00104
00105
00106
00107 GiNaC::matrix b; GiNaC::matrix A;
00108 matrix_from_equations(equations, variables, A, b);
00109
00110 int ncols = A.cols();
00111 GiNaC::matrix vars_sq(ncols, ncols);
00112
00113
00114 for (unsigned r=0; r<ncols; ++r)
00115 for (unsigned c=0; c<ncols; ++c)
00116 vars_sq(r, c) = GiNaC::symbol();
00117
00118 GiNaC::matrix id(ncols, ncols);
00119
00120
00121 const GiNaC::ex _ex1(1);
00122 for (unsigned i=0; i<ncols; ++i)
00123 id(i, i) = _ex1;
00124
00125
00126
00127 GiNaC::matrix m_inv(ncols, ncols);
00128 m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00129
00130
00131 for (int i=0; i<dofs.size(); i++) {
00132 b.let_op(removed_dofs + i) = GiNaC::numeric(1);
00133 GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b));
00134
00135 GiNaC::lst subs;
00136 for (int ii=0; ii<xx.nops(); ii++) {
00137 subs.append(variables.op(ii) == xx.op(ii));
00138 }
00139 GiNaC::ex Nj1 = pspace.op(0).subs(subs);
00140 GiNaC::ex Nj2 = pspace.op(1).subs(subs);
00141 Ns.insert(Ns.end(), GiNaC::matrix(1,2,GiNaC::lst(Nj1,Nj2)));
00142 b.let_op(removed_dofs + i) = GiNaC::numeric(0);
00143 }
00144
00145 } else if ( p->str() == "ReferenceTetrahedron" || p->str() == "Tetrahedron" ) {
00146
00147
00148 Tetrahedron& tetrahedron = (Tetrahedron&)(*p);
00149 GiNaC::lst equations;
00150 GiNaC::lst variables;
00151 GiNaC::ex polynom_space1 = bernstein(order-1, tetrahedron, "a");
00152 GiNaC::ex polynom1 = polynom_space1.op(0);
00153 GiNaC::ex polynom1_vars = polynom_space1.op(1);
00154 GiNaC::ex polynom1_basis = polynom_space1.op(2);
00155
00156
00157 GiNaC::lst polynom_space2 = bernsteinv(order-1, tetrahedron, "b");
00158 GiNaC::ex polynom2 = polynom_space2.op(0).op(0);
00159 GiNaC::ex polynom3 = polynom_space2.op(0).op(1);
00160 GiNaC::ex polynom4 = polynom_space2.op(0).op(2);
00161
00162
00163
00164 GiNaC::lst pspace = GiNaC::lst( polynom2 + polynom1*x,
00165 polynom3 + polynom1*y,
00166 polynom4 + polynom1*z);
00167
00168 GiNaC::lst v2 = collapse(GiNaC::ex_to<GiNaC::lst>(polynom_space2.op(1)));
00169
00170
00171 variables = collapse(GiNaC::lst(polynom_space1.op(1), v2));
00172
00173 GiNaC::ex bernstein_pol;
00174
00175
00176
00177 if ( order >= 2) {
00178 GiNaC::ex expanded_pol = GiNaC::expand(polynom1);
00179 for (int c1=0; c1<= order-2;c1++) {
00180 for (int c2=0; c2<= order-2;c2++) {
00181 for (int c3=0; c3<= order-2;c3++) {
00182 if ( c1 + c2 + c3 <= order -2 ) {
00183 GiNaC::ex eq = expanded_pol.coeff(x,c1).coeff(y,c2).coeff(z,c3);
00184 if ( eq != GiNaC::numeric(0) ) {
00185 equations.append(eq == 0);
00186 }
00187 }
00188 }
00189 }
00190 }
00191 }
00192
00193 int removed_dofs = equations.nops();
00194
00195
00196
00197 int counter = 0;
00198 GiNaC::symbol t("t");
00199 GiNaC::ex dofi;
00200
00201 for (int i=1; i<= 4; i++) {
00202 Triangle triangle = tetrahedron.triangle(i);
00203 GiNaC::lst normal_vec = normal(tetrahedron, i);
00204 bernstein_pol = bernstein(order-1, triangle, istr("a",i));
00205 GiNaC::ex basis_space = bernstein_pol.op(2);
00206 GiNaC::ex pspace_n = inner(pspace, normal_vec);
00207
00208 GiNaC::ex basis;
00209 for (int i=0; i< basis_space.nops(); i++) {
00210 counter++;
00211 basis = basis_space.op(i);
00212 GiNaC::ex integrand = pspace_n*basis;
00213 dofi = triangle.integrate(integrand);
00214 dofs.insert(dofs.end(), dofi);
00215 GiNaC::ex eq = dofi == GiNaC::numeric(0);
00216 equations.append(eq);
00217
00218 }
00219 }
00220
00221
00222 GiNaC::lst bernstein_polv;
00223 if ( order > 1) {
00224 counter++;
00225 bernstein_polv = bernsteinv(order-2, tetrahedron, "a");
00226 GiNaC::ex basis_space = bernstein_polv.op(2);
00227 for (int i=0; i< basis_space.nops(); i++) {
00228 GiNaC::lst basis = GiNaC::ex_to<GiNaC::lst>(basis_space.op(i));
00229 GiNaC::ex integrand = inner(pspace, basis);
00230 dofi = tetrahedron.integrate(integrand);
00231 dofs.insert(dofs.end(), dofi);
00232 GiNaC::ex eq = dofi == GiNaC::numeric(0);
00233 equations.append(eq);
00234 }
00235 }
00236
00237
00238
00239
00240
00241
00242 GiNaC::matrix b; GiNaC::matrix A;
00243 matrix_from_equations(equations, variables, A, b);
00244
00245 int ncols = A.cols();
00246 GiNaC::matrix vars_sq(ncols, ncols);
00247
00248
00249 for (unsigned r=0; r<ncols; ++r)
00250 for (unsigned c=0; c<ncols; ++c)
00251 vars_sq(r, c) = GiNaC::symbol();
00252
00253 GiNaC::matrix id(ncols, ncols);
00254
00255
00256 const GiNaC::ex _ex1(1);
00257 for (unsigned i=0; i<ncols; ++i)
00258 id(i, i) = _ex1;
00259
00260
00261
00262 GiNaC::matrix m_inv(ncols, ncols);
00263 m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00264
00265
00266 for (int i=0; i<dofs.size(); i++) {
00267 b.let_op(removed_dofs + i) = GiNaC::numeric(1);
00268 GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b));
00269
00270 GiNaC::lst subs;
00271 for (int ii=0; ii<xx.nops(); ii++) {
00272 subs.append(variables.op(ii) == xx.op(ii));
00273 }
00274 GiNaC::ex Nj1 = pspace.op(0).subs(subs);
00275 GiNaC::ex Nj2 = pspace.op(1).subs(subs);
00276 Ns.insert(Ns.end(), GiNaC::matrix(1,2,GiNaC::lst(Nj1,Nj2)));
00277 b.let_op(removed_dofs + i) = GiNaC::numeric(0);
00278 }
00279 }
00280 }
00281
00282
00283 void RaviartThomas:: set(Polygon& p_) {
00284 StandardFE:: set(p_);
00285 }
00286
00287
00288 void RaviartThomas:: set(int order_) {
00289 StandardFE:: set(order_);
00290 }
00291
00292
00293 GiNaC::ex RaviartThomas:: dof(int i) {
00294 return StandardFE::dof(i);
00295 }
00296
00297
00298 GiNaC::ex RaviartThomas::N(int i) {
00299 return StandardFE::N(i);
00300 }
00301
00302
00303