SyFi  0.3
CrouzeixRaviart.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 "CrouzeixRaviart.h"
00019 
00020 #include "tools.h"
00021 
00022 using std::cout;
00023 using std::endl;
00024 using std::string;
00025 
00026 namespace SyFi
00027 {
00028 
00029         CrouzeixRaviart:: CrouzeixRaviart() : StandardFE()
00030         {
00031                 order = 1;
00032         }
00033 
00034         CrouzeixRaviart:: CrouzeixRaviart (Polygon& p, unsigned int order) : StandardFE(p, order)
00035         {
00036                 compute_basis_functions();
00037         }
00038 
00039         void CrouzeixRaviart:: compute_basis_functions()
00040         {
00041 
00042                 // remove previously computed basis functions and dofs
00043                 Ns.clear();
00044                 dofs.clear();
00045 
00046                 if ( p == NULL )
00047                 {
00048                         throw(std::logic_error("You need to set a polygon before the basisfunctions can be computed"));
00049                 }
00050 
00051                 if (order != 1)
00052                 {
00053                         throw(std::logic_error("Only Crouziex-Raviart elements of order 1 is possible"));
00054                 }
00055 
00056                 // see e.g. Brezzi and Fortin book page 116 for the definition
00057 
00058                 if ( p->str().find("ReferenceLine") != string::npos )
00059                 {
00060                         cout <<"Can not define the Raviart-Thomas element on a line"<<endl;
00061                 }
00062                 else if ( p->str().find("Triangle") != string::npos )
00063                 {
00064 
00065                         description = "CrouzeixRaviart_2D";
00066 
00067                         Triangle& triangle = (Triangle&)(*p);
00068 
00069                         // create the polynomial space
00070                         GiNaC::ex polynom_space = bernstein(1, triangle, "a");
00071                         GiNaC::ex polynom = polynom_space.op(0);
00072                         GiNaC::lst variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
00073                         GiNaC::ex basis = polynom_space.op(2);
00074 
00075                         // create the dofs
00076                         GiNaC::symbol t("t");
00077                         for (int j=0; j< 3; j++)
00078                         {
00079 
00080                                 // solve the linear system to compute
00081                                 // each of the basis functions
00082                                 GiNaC::lst equations;
00083                                 for (int i=0; i< 3; i++)
00084                                 {
00085 
00086                                         Line line = triangle.line(i);
00087                                         //                          GiNaC::ex dofi = line.integrate(polynom);
00088                                         GiNaC::lst midpoint = GiNaC::lst(
00089                                                 (line.vertex(0).op(0) +  line.vertex(1).op(0))/2,
00090                                                 (line.vertex(0).op(1) +  line.vertex(1).op(1))/2);
00091                                         dofs.insert(dofs.end(), midpoint);
00092 
00093                                         //                          GiNaC::ex dofi = polynom.subs( x == midpoint.op(0)).subs( y == midpoint.op(1));
00094                                         GiNaC::ex dofi = line.integrate(polynom);
00095                                         equations.append( dofi == dirac(i,j));
00096 
00097                                         if (j == 1)
00098                                         {
00099                                                 //                                  GiNaC::lst d = GiNaC::lst(line.vertex(0) ,  line.vertex(1));
00100                                                 dofs.insert(dofs.end(), midpoint);
00101                                         }
00102 
00103                                 }
00104                                 GiNaC::ex sub = lsolve(equations, variables);
00105                                 GiNaC::ex Ni = polynom.subs(sub);
00106                                 Ns.insert(Ns.end(),Ni);
00107                         }
00108 
00109                 }
00110                 else if ( p->str().find("Tetrahedron") != string::npos )
00111                 {
00112 
00113                         description = "CrouzeixRaviart_3D";
00114 
00115                         Tetrahedron& tetrahedron = (Tetrahedron&)(*p);
00116                         GiNaC::ex polynom_space = bernstein(1, tetrahedron, "a");
00117                         GiNaC::ex polynom = polynom_space.op(0);
00118                         GiNaC::lst variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1));
00119                         GiNaC::ex basis = polynom_space.op(2);
00120 
00121                         GiNaC::ex bernstein_pol;
00122 
00123                         GiNaC::symbol t("t");
00124                         // dofs related to edges
00125                         for (int j=0; j< 4; j++)
00126                         {
00127 
00128                                 GiNaC::lst equations;
00129                                 for (int i=0; i< 4; i++)
00130                                 {
00131                                         Triangle triangle = tetrahedron.triangle(i);
00132                                         GiNaC::lst midpoint = GiNaC::lst(
00133                                                 (triangle.vertex(0).op(0) + triangle.vertex(1).op(0) + triangle.vertex(2).op(0))/3,
00134                                                 (triangle.vertex(0).op(1) + triangle.vertex(1).op(1) + triangle.vertex(2).op(1))/3,
00135                                                 (triangle.vertex(0).op(2) + triangle.vertex(1).op(2) + triangle.vertex(2).op(2))/3
00136                                                 );
00137 
00138                                         GiNaC::ex dofi = polynom.subs(x == midpoint.op(0)).subs(y == midpoint.op(1)).subs(z == midpoint.op(2));
00139                                         equations.append( dofi == dirac(i,j));
00140 
00141                                         if ( j == 1 )
00142                                         {
00143                                                 //                                  GiNaC::lst d = GiNaC::lst(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2));
00144                                                 dofs.insert(dofs.end(), midpoint);
00145                                         }
00146                                 }
00147                                 GiNaC::ex sub = lsolve(equations, variables);
00148                                 GiNaC::ex Ni = polynom.subs(sub);
00149                                 Ns.insert(Ns.end(),Ni);
00150 
00151                         }
00152                 }
00153         }
00154 
00155         // ------------VectorCrouzeixRaviart ---
00156 
00157         VectorCrouzeixRaviart:: VectorCrouzeixRaviart (Polygon& p, unsigned int order, unsigned int size_) : StandardFE(p, order)
00158         {
00159                 size = size_ < 0 ? nsd: size_;
00160                 compute_basis_functions();
00161         }
00162 
00163         VectorCrouzeixRaviart:: VectorCrouzeixRaviart() : StandardFE()
00164         {
00165                 description = "VectorCrouzeixRaviart";
00166                 order = 1;
00167         }
00168 
00169         void VectorCrouzeixRaviart:: compute_basis_functions()
00170         {
00171 
00172                 if (order != 1)
00173                 {
00174                         throw(std::logic_error("Only Crouziex-Raviart elements of order 1 is possible"));
00175                 }
00176 
00177                 CrouzeixRaviart fe;
00178                 fe.set_polygon(*p);
00179                 fe.compute_basis_functions();
00180 
00181                 description = "Vector" + fe.str();
00182 
00183                 GiNaC::lst zero_list;
00184                 for (unsigned int s=1; s<= size ; s++)
00185                 {
00186                         zero_list.append(0);
00187                 }
00188 
00189                 for (unsigned int s=0; s< size ; s++)
00190                 {
00191                         for (unsigned int i=0; i< fe.nbf() ; i++)
00192                         {
00193                                 GiNaC::lst Nis = zero_list;
00194                                 Nis.let_op(s) = fe.N(i);
00195                                 GiNaC::ex Nmat = GiNaC::matrix(size,1,Nis);
00196                                 Ns.insert(Ns.end(), Nmat);
00197 
00198                                 GiNaC::lst dof = GiNaC::lst(fe.dof(i), s) ;
00199                                 dofs.insert(dofs.end(), dof);
00200                         }
00201                 }
00202         }
00203 
00204         void VectorCrouzeixRaviart:: set_size(unsigned int size_)
00205         {
00206                 size = size_;
00207         }
00208 
00209 }                                                                // namespace SyFi
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator