00001 #include "HermiteFE.h"
00002
00003 int HermiteFE:: nbf() {
00004 return StandardFE::nbf();
00005 }
00006
00007 void HermiteFE:: compute_basis_functions() {
00008
00009 if ( p == NULL ) {
00010 cout <<"You need to set a polygon before the basisfunctions can be computed"<<endl;
00011 return;
00012 }
00013
00014
00015 if (p->str() == "ReferenceTriangle" || p->str() == "Triangle") {
00016 GiNaC::ex polynom_space = pol(3, 2, "a");
00017 GiNaC::ex polynom = polynom_space.op(0);
00018 GiNaC::lst variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
00019 GiNaC::lst equations;
00020
00021 for (int i=0; i<= 2; i++) {
00022 GiNaC::ex v = p->vertex(i);
00023 GiNaC::ex dofv = polynom.subs(GiNaC::lst(x == v.op(0), y == v.op(1)));
00024 GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0), y == v.op(1)));
00025 GiNaC::ex dofvdy = diff(polynom,y).subs(GiNaC::lst(x == v.op(0), y == v.op(1)));
00026
00027 equations.append( dofv == GiNaC::numeric(0));
00028 equations.append( dofvdx == GiNaC::numeric(0));
00029 equations.append( dofvdy == GiNaC::numeric(0));
00030
00031 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 0));
00032 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 1));
00033 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 2));
00034 }
00035 GiNaC::ex midpoint = GiNaC::lst((p->vertex(0).op(0) + p->vertex(1).op(0) + p->vertex(2).op(0))/3,
00036 (p->vertex(0).op(1) + p->vertex(1).op(1) + p->vertex(2).op(1))/3);
00037 GiNaC::ex dofm = polynom.subs(GiNaC::lst(x == midpoint.op(0), y == midpoint.op(1)));
00038 dofs.insert(dofs.end(), midpoint );
00039 equations.append( dofm == GiNaC::numeric(0));
00040
00041 GiNaC::matrix b; GiNaC::matrix A;
00042 matrix_from_equations(equations, variables, A, b);
00043
00044 int ncols = A.cols();
00045 GiNaC::matrix vars_sq(ncols, ncols);
00046
00047
00048 for (unsigned r=0; r<ncols; ++r)
00049 for (unsigned c=0; c<ncols; ++c)
00050 vars_sq(r, c) = GiNaC::symbol();
00051
00052 GiNaC::matrix id(ncols, ncols);
00053
00054
00055 const GiNaC::ex _ex1(1);
00056 for (unsigned i=0; i<ncols; ++i)
00057 id(i, i) = _ex1;
00058
00059
00060
00061 GiNaC::matrix m_inv(ncols, ncols);
00062 m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00063
00064 for (int i=0; i<dofs.size(); i++) {
00065 b.let_op(i) = GiNaC::numeric(1);
00066 GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b));
00067
00068 GiNaC::lst subs;
00069 for (int ii=0; ii<xx.nops(); ii++) {
00070 subs.append(variables.op(ii) == xx.op(ii));
00071 }
00072 GiNaC::ex Nj= polynom.subs(subs);
00073 Ns.insert(Ns.end(), Nj);
00074 b.let_op(i) = GiNaC::numeric(0);
00075 }
00076 } else if (p->str() == "ReferenceTetrahedron" || p->str() == "Tetrahedron") {
00077 GiNaC::ex polynom_space = pol(3, 3, "a");
00078 GiNaC::ex polynom = polynom_space.op(0);
00079 GiNaC::lst variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
00080 GiNaC::lst equations;
00081
00082 cout <<"polynom "<<polynom<<endl;
00083
00084 for (int i=0; i<= 3; i++) {
00085 GiNaC::ex v = p->vertex(i);
00086 GiNaC::ex dofv = polynom.subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00087 GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00088 GiNaC::ex dofvdy = diff(polynom,y).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00089 GiNaC::ex dofvdz = diff(polynom,z).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00090
00091 equations.append( dofv == GiNaC::numeric(0));
00092 equations.append( dofvdx == GiNaC::numeric(0));
00093 equations.append( dofvdy == GiNaC::numeric(0));
00094 equations.append( dofvdz == GiNaC::numeric(0));
00095
00096 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 0));
00097 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 1));
00098 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 2));
00099 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 3));
00100
00101 }
00102 GiNaC::ex midpoint1 = GiNaC::lst(
00103 (p->vertex(0).op(0)*2 + p->vertex(1).op(0) + p->vertex(2).op(0) + p->vertex(3).op(0))/5,
00104 (p->vertex(0).op(1)*2 + p->vertex(1).op(1) + p->vertex(2).op(1) + p->vertex(3).op(1))/5,
00105 (p->vertex(0).op(2)*2 + p->vertex(1).op(2) + p->vertex(2).op(2) + p->vertex(3).op(2))/5);
00106
00107 GiNaC::ex midpoint2 = GiNaC::lst(
00108 (p->vertex(0).op(0) + p->vertex(1).op(0)*2 + p->vertex(2).op(0) + p->vertex(3).op(0))/5,
00109 (p->vertex(0).op(1) + p->vertex(1).op(1)*2 + p->vertex(2).op(1) + p->vertex(3).op(1))/5,
00110 (p->vertex(0).op(2) + p->vertex(1).op(2)*2 + p->vertex(2).op(2) + p->vertex(3).op(2))/5);
00111
00112 GiNaC::ex midpoint3 = GiNaC::lst(
00113 (p->vertex(0).op(0) + p->vertex(1).op(0) + p->vertex(2).op(0)*2 + p->vertex(3).op(0))/5,
00114 (p->vertex(0).op(1) + p->vertex(1).op(1) + p->vertex(2).op(1)*2 + p->vertex(3).op(1))/5,
00115 (p->vertex(0).op(2) + p->vertex(1).op(2) + p->vertex(2).op(2)*2 + p->vertex(3).op(2))/5);
00116
00117 GiNaC::ex midpoint4 = GiNaC::lst(
00118 (p->vertex(0).op(0) + p->vertex(1).op(0) + p->vertex(2).op(0) + p->vertex(3).op(0)*2)/5,
00119 (p->vertex(0).op(1) + p->vertex(1).op(1) + p->vertex(2).op(1) + p->vertex(3).op(1)*2)/5,
00120 (p->vertex(0).op(2) + p->vertex(1).op(2) + p->vertex(2).op(2) + p->vertex(3).op(2)*2)/5);
00121
00122
00123 GiNaC::ex dofm1 = polynom.subs(GiNaC::lst(x == midpoint1.op(0), y == midpoint1.op(1), z == midpoint1.op(2)));
00124 GiNaC::ex dofm2 = polynom.subs(GiNaC::lst(x == midpoint2.op(0), y == midpoint2.op(1), z == midpoint2.op(2)));
00125 GiNaC::ex dofm3 = polynom.subs(GiNaC::lst(x == midpoint3.op(0), y == midpoint3.op(1), z == midpoint3.op(2)));
00126 GiNaC::ex dofm4 = polynom.subs(GiNaC::lst(x == midpoint4.op(0), y == midpoint4.op(1), z == midpoint4.op(2)));
00127
00128 dofs.insert(dofs.end(), midpoint1 );
00129 dofs.insert(dofs.end(), midpoint2 );
00130 dofs.insert(dofs.end(), midpoint3 );
00131 dofs.insert(dofs.end(), midpoint4 );
00132
00133 equations.append( dofm1 == GiNaC::numeric(0));
00134 equations.append( dofm2 == GiNaC::numeric(0));
00135 equations.append( dofm3 == GiNaC::numeric(0));
00136 equations.append( dofm4 == GiNaC::numeric(0));
00137
00138 GiNaC::matrix b; GiNaC::matrix A;
00139 matrix_from_equations(equations, variables, A, b);
00140 cout <<"A "<<A<<endl;
00141
00142 int ncols = A.cols();
00143 int nrows = A.rows();
00144 GiNaC::matrix vars_sq(ncols, ncols);
00145
00146 cout <<"ncols "<<ncols<<endl;
00147 cout <<"nrows "<<nrows<<endl;
00148
00149
00150 for (unsigned r=0; r<ncols; ++r)
00151 for (unsigned c=0; c<ncols; ++c)
00152 vars_sq(r, c) = GiNaC::symbol();
00153
00154 GiNaC::matrix id(ncols, ncols);
00155
00156
00157 const GiNaC::ex _ex1(1);
00158 for (unsigned i=0; i<ncols; ++i)
00159 id(i, i) = _ex1;
00160
00161
00162
00163 GiNaC::matrix m_inv(ncols, ncols);
00164 m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00165
00166 for (int i=0; i<dofs.size(); i++) {
00167 b.let_op(i) = GiNaC::numeric(1);
00168 GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b));
00169
00170 GiNaC::lst subs;
00171 for (int ii=0; ii<xx.nops(); ii++) {
00172 subs.append(variables.op(ii) == xx.op(ii));
00173 }
00174 GiNaC::ex Nj= polynom.subs(subs);
00175 Ns.insert(Ns.end(), Nj);
00176 b.let_op(i) = GiNaC::numeric(0);
00177 }
00178 }
00179 }
00180
00181 void HermiteFE:: set(Polygon& p_) {
00182 StandardFE::set(p_);
00183 }
00184
00185
00186 GiNaC::ex HermiteFE:: dof(int i) {
00187 return StandardFE::dof(i);
00188 }
00189
00190
00191 GiNaC::ex HermiteFE::N(int i) {
00192 return StandardFE::N(i);
00193 }
00194