SyFi  0.3
Hermite.cpp
Go to the documentation of this file.
00001 // Copyright (C) 2006-2009 Kent-Andre Mardal and Simula Research Laboratory
00002 //
00003 // This file is part of SyFi.
00004 //
00005 // SyFi is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // SyFi is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with SyFi. If not, see <http://www.gnu.org/licenses/>.
00017 
00018 #include "Hermite.h"
00019 #include "tools.h"
00020 
00021 using std::cout;
00022 using std::endl;
00023 using std::string;
00024 
00025 namespace SyFi
00026 {
00027 
00028         Hermite:: Hermite() : StandardFE()
00029         {
00030                 description = "Hermite";
00031         }
00032 
00033         Hermite:: Hermite(Polygon& p, int order) : StandardFE(p,order)
00034         {
00035                 compute_basis_functions();
00036         }
00037 
00038         void Hermite:: compute_basis_functions()
00039         {
00040 
00041                 // remove previously computed basis functions and dofs
00042                 Ns.clear();
00043                 dofs.clear();
00044 
00045                 if ( p == NULL )
00046                 {
00047                         throw(std::logic_error("You need to set a polygon before the basisfunctions can be computed"));
00048                 }
00049 
00050                 GiNaC::ex polynom_space;
00051                 GiNaC::ex polynom;
00052                 GiNaC::lst variables;
00053                 GiNaC::lst equations;
00054 
00055                 if ( p->str().find("Line") != string::npos )
00056                 {
00057 
00058                         description = "Hermite_1D";
00059 
00060                         polynom_space = legendre(3, 1, "a");
00061                         polynom = polynom_space.op(0);
00062                         variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
00063 
00064                         for (int i=0; i< 2; i++)
00065                         {
00066                                 GiNaC::ex v = p->vertex(i);
00067                                 GiNaC::ex dofv   = polynom.subs(GiNaC::lst(x == v.op(0)));
00068                                 GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0)));
00069                                 equations.append( dofv   == GiNaC::numeric(0));
00070                                 equations.append( dofvdx == GiNaC::numeric(0));
00071 
00072                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), 0));
00073                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), 1));
00074                         }
00075 
00076                 }
00077 
00078                 if ( p->str().find("Triangle") != string::npos )
00079                 {
00080 
00081                         description = "Hermite_2D";
00082 
00083                         polynom_space = pol(3, 2, "a");
00084                         polynom = polynom_space.op(0);
00085                         variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
00086 
00087                         for (int i=0; i<= 2; i++)
00088                         {
00089                                 GiNaC::ex v = p->vertex(i);
00090                                 GiNaC::ex dofv = polynom.subs(GiNaC::lst(x == v.op(0), y == v.op(1)));
00091                                 GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0), y == v.op(1)));
00092                                 GiNaC::ex dofvdy = diff(polynom,y).subs(GiNaC::lst(x == v.op(0), y == v.op(1)));
00093 
00094                                 equations.append( dofv   == GiNaC::numeric(0));
00095                                 equations.append( dofvdx == GiNaC::numeric(0));
00096                                 equations.append( dofvdy == GiNaC::numeric(0));
00097 
00098                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 0));
00099                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 1));
00100                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 2));
00101                         }
00102                         GiNaC::ex midpoint = GiNaC::lst((p->vertex(0).op(0) + p->vertex(1).op(0) + p->vertex(2).op(0))/3,
00103                                 (p->vertex(0).op(1) + p->vertex(1).op(1) + p->vertex(2).op(1))/3);
00104                         GiNaC::ex dofm = polynom.subs(GiNaC::lst(x == midpoint.op(0), y == midpoint.op(1)));
00105                         dofs.insert(dofs.end(), midpoint );
00106                         equations.append( dofm == GiNaC::numeric(0));
00107 
00108                 }
00109 
00110                 else if ( p->str().find("Rectangle") != string::npos )
00111                 {
00112 
00113                         description = "Hermite_2D";
00114 
00115                         polynom_space = legendre(3, 2, "a");
00116                         polynom = polynom_space.op(0);
00117                         variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
00118 
00119                         for (int i=0; i< 4; i++)
00120                         {
00121                                 GiNaC::ex v = p->vertex(i);
00122                                 GiNaC::ex dofv   = polynom.subs(GiNaC::lst(x == v.op(0), y == v.op(1)));
00123                                 GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0), y == v.op(1)));
00124                                 GiNaC::ex dofvdy = diff(polynom,y).subs(GiNaC::lst(x == v.op(0), y == v.op(1)));
00125                                 GiNaC::ex dofvdyx = diff(diff(polynom,y),x).subs(GiNaC::lst(x == v.op(0), y == v.op(1)));
00126                                 equations.append( dofv   == GiNaC::numeric(0));
00127                                 equations.append( dofvdx == GiNaC::numeric(0));
00128                                 equations.append( dofvdy == GiNaC::numeric(0));
00129                                 equations.append( dofvdyx == GiNaC::numeric(0));
00130 
00131                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 0));
00132                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 1));
00133                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 2));
00134                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 3));
00135                         }
00136 
00137                 }
00138                 else if ( p->str().find("Tetrahedron") != string::npos )
00139                 {
00140 
00141                         description = "Hermite_3D";
00142 
00143                         polynom_space = pol(3, 3, "a");
00144                         polynom = polynom_space.op(0);
00145                         variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
00146 
00147                         for (int i=0; i<= 3; i++)
00148                         {
00149                                 GiNaC::ex v = p->vertex(i);
00150                                 GiNaC::ex dofv   = polynom.subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00151                                 GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00152                                 GiNaC::ex dofvdy = diff(polynom,y).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00153                                 GiNaC::ex dofvdz = diff(polynom,z).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00154 
00155                                 equations.append( dofv   == GiNaC::numeric(0));
00156                                 equations.append( dofvdx == GiNaC::numeric(0));
00157                                 equations.append( dofvdy == GiNaC::numeric(0));
00158                                 equations.append( dofvdz == GiNaC::numeric(0));
00159 
00160                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 0));
00161                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 1));
00162                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 2));
00163                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 3));
00164 
00165                         }
00166                         GiNaC::ex midpoint1 = GiNaC::lst(
00167                                 (p->vertex(0).op(0)*2 + p->vertex(1).op(0) + p->vertex(2).op(0) + p->vertex(3).op(0))/5,
00168                                 (p->vertex(0).op(1)*2 + p->vertex(1).op(1) + p->vertex(2).op(1) + p->vertex(3).op(1))/5,
00169                                 (p->vertex(0).op(2)*2 + p->vertex(1).op(2) + p->vertex(2).op(2) + p->vertex(3).op(2))/5);
00170 
00171                         GiNaC::ex midpoint2 = GiNaC::lst(
00172                                 (p->vertex(0).op(0) + p->vertex(1).op(0)*2 + p->vertex(2).op(0) + p->vertex(3).op(0))/5,
00173                                 (p->vertex(0).op(1) + p->vertex(1).op(1)*2 + p->vertex(2).op(1) + p->vertex(3).op(1))/5,
00174                                 (p->vertex(0).op(2) + p->vertex(1).op(2)*2 + p->vertex(2).op(2) + p->vertex(3).op(2))/5);
00175 
00176                         GiNaC::ex midpoint3 = GiNaC::lst(
00177                                 (p->vertex(0).op(0) + p->vertex(1).op(0) + p->vertex(2).op(0)*2 + p->vertex(3).op(0))/5,
00178                                 (p->vertex(0).op(1) + p->vertex(1).op(1) + p->vertex(2).op(1)*2 + p->vertex(3).op(1))/5,
00179                                 (p->vertex(0).op(2) + p->vertex(1).op(2) + p->vertex(2).op(2)*2 + p->vertex(3).op(2))/5);
00180 
00181                         GiNaC::ex midpoint4 = GiNaC::lst(
00182                                 (p->vertex(0).op(0) + p->vertex(1).op(0) + p->vertex(2).op(0) + p->vertex(3).op(0)*2)/5,
00183                                 (p->vertex(0).op(1) + p->vertex(1).op(1) + p->vertex(2).op(1) + p->vertex(3).op(1)*2)/5,
00184                                 (p->vertex(0).op(2) + p->vertex(1).op(2) + p->vertex(2).op(2) + p->vertex(3).op(2)*2)/5);
00185 
00186                         GiNaC::ex dofm1 = polynom.subs(GiNaC::lst(x == midpoint1.op(0), y == midpoint1.op(1), z == midpoint1.op(2)));
00187                         GiNaC::ex dofm2 = polynom.subs(GiNaC::lst(x == midpoint2.op(0), y == midpoint2.op(1), z == midpoint2.op(2)));
00188                         GiNaC::ex dofm3 = polynom.subs(GiNaC::lst(x == midpoint3.op(0), y == midpoint3.op(1), z == midpoint3.op(2)));
00189                         GiNaC::ex dofm4 = polynom.subs(GiNaC::lst(x == midpoint4.op(0), y == midpoint4.op(1), z == midpoint4.op(2)));
00190 
00191                         dofs.insert(dofs.end(), midpoint1 );
00192                         dofs.insert(dofs.end(), midpoint2 );
00193                         dofs.insert(dofs.end(), midpoint3 );
00194                         dofs.insert(dofs.end(), midpoint4 );
00195 
00196                         equations.append( dofm1 == GiNaC::numeric(0));
00197                         equations.append( dofm2 == GiNaC::numeric(0));
00198                         equations.append( dofm3 == GiNaC::numeric(0));
00199                         equations.append( dofm4 == GiNaC::numeric(0));
00200 
00201                 }
00202                 else if ( p->str().find("Box") != string::npos )
00203                 {
00204 
00205                         description = "Hermite_3D";
00206 
00207                         polynom_space = legendre(3, 3, "a");
00208                         polynom = polynom_space.op(0);
00209                         variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
00210 
00211                         for (int i=0; i<= 7; i++)
00212                         {
00213                                 GiNaC::ex v = p->vertex(i);
00214                                 GiNaC::ex dofv   = polynom.subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00215                                 GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00216                                 GiNaC::ex dofvdy = diff(polynom,y).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00217                                 GiNaC::ex dofvdyx = diff(diff(polynom,y),x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00218                                 GiNaC::ex dofvdz = diff(polynom,z).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00219                                 GiNaC::ex dofvdzy = diff(diff(polynom,z),y).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00220                                 GiNaC::ex dofvdzx = diff(diff(polynom,z),x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00221                                 GiNaC::ex dofvdzyx = diff(diff(diff(polynom,z),y),x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) ));
00222 
00223                                 equations.append( dofv   == GiNaC::numeric(0));
00224                                 equations.append( dofvdx == GiNaC::numeric(0));
00225                                 equations.append( dofvdy == GiNaC::numeric(0));
00226                                 equations.append( dofvdyx == GiNaC::numeric(0));
00227                                 equations.append( dofvdz == GiNaC::numeric(0));
00228                                                                  // FIXME check Andrew/Ola numbering
00229                                 equations.append( dofvdzy == GiNaC::numeric(0));
00230                                                                  // FIXME check Andrew/Ola numbering
00231                                 equations.append( dofvdzx == GiNaC::numeric(0));
00232                                 equations.append( dofvdzyx == GiNaC::numeric(0));
00233 
00234                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 0));
00235                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 1));
00236                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 2));
00237                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 3));
00238                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 4));
00239                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 5));
00240                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 6));
00241                                 dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 7));
00242 
00243                         }
00244 
00245                 }
00246 
00247                 GiNaC::matrix b; GiNaC::matrix A;
00248                 matrix_from_equations(equations, variables, A, b);
00249 
00250                 unsigned int ncols = A.cols();
00251                 GiNaC::matrix vars_sq(ncols, ncols);
00252 
00253                 // matrix of symbols
00254                 for (unsigned r=0; r<ncols; ++r)
00255                         for (unsigned c=0; c<ncols; ++c)
00256                                 vars_sq(r, c) = GiNaC::symbol();
00257 
00258                 GiNaC::matrix id(ncols, ncols);
00259 
00260                 // identity
00261                 const GiNaC::ex _ex1(1);
00262                 for (unsigned i=0; i<ncols; ++i)
00263                         id(i, i) = _ex1;
00264 
00265                 // invert the matrix
00266                 GiNaC::matrix m_inv(ncols, ncols);
00267                 m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss);
00268 
00269                 for (unsigned int i=0; i<dofs.size(); i++)
00270                 {
00271                         b.let_op(i) = GiNaC::numeric(1);
00272                         GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b));
00273 
00274                         GiNaC::lst subs;
00275                         for (unsigned int ii=0; ii<xx.nops(); ii++)
00276                         {
00277                                 subs.append(variables.op(ii) == xx.op(ii));
00278                         }
00279                         GiNaC::ex Nj= polynom.subs(subs).expand();
00280                         Ns.insert(Ns.end(), Nj);
00281                         b.let_op(i) = GiNaC::numeric(0);
00282                 }
00283 
00284         }
00285 
00286 }                                                                // namespace SyFi
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator