SyFi
0.3
|
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