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 "ElementComputations.h" 00019 #include "tools.h" 00020 00021 using std::cout; 00022 using std::endl; 00023 00024 namespace SyFi 00025 { 00026 00027 void usage(FE& fe) 00028 { 00029 for (unsigned int i=0; i< fe.nbf(); i++) 00030 { 00031 cout <<"fe.N("<<i<<") = "<<fe.N(i)<<endl; 00032 cout <<"grad(fe.N("<<i<<")) = "<<grad(fe.N(i))<<endl; 00033 cout <<"fe.dof("<<i<<") = "<<fe.dof(i)<<endl; 00034 } 00035 } 00036 00037 void usage(FE& v_fe, FE& p_fe) 00038 { 00039 for (unsigned int i=0; i< v_fe.nbf(); i++) 00040 { 00041 cout <<"v_fe.N("<<i<<") = "<<v_fe.N(i)<<endl; 00042 cout <<"grad(v_fe.N("<<i<<")) = "<<grad(v_fe.N(i))<<endl; 00043 cout <<"v_fe.dof("<<i<<") = "<<v_fe.dof(i)<<endl; 00044 } 00045 for (unsigned int i=0; i< p_fe.nbf(); i++) 00046 { 00047 cout <<"p_fe.N("<<i<<")= "<<p_fe.N(i)<<endl; 00048 cout <<"p_fe.dof("<<i<<")= "<<p_fe.dof(i)<<endl; 00049 } 00050 } 00051 00052 void compute_Poisson_element_matrix( 00053 FE& fe, 00054 Dof& dof, 00055 std::map<std::pair<unsigned int,unsigned int>, GiNaC::ex>& A) 00056 { 00057 std::pair<unsigned int,unsigned int> index; 00058 00059 // Insert the local degrees of freedom into the global Dof 00060 for (unsigned int i=0; i< fe.nbf(); i++) 00061 { 00062 dof.insert_dof(1,i,fe.dof(i)); 00063 } 00064 00065 Polygon& domain = fe.get_polygon(); 00066 00067 // The term (grad u, grad v) 00068 for (unsigned int i=0; i< fe.nbf(); i++) 00069 { 00070 // fetch the global dof for Ni 00071 index.first = dof.glob_dof(fe.dof(i)); 00072 for (unsigned int j=0; j< fe.nbf(); j++) 00073 { 00074 // fetch the global dof for Nj 00075 index.second = dof.glob_dof(fe.dof(j)); 00076 // compute the integrand 00077 GiNaC::ex nabla = inner(grad(fe.N(i)), 00078 grad(fe.N(j))); 00079 // compute the integral 00080 GiNaC::ex Aij = domain.integrate(nabla); 00081 A[index] += Aij; // add to global matrix 00082 } 00083 } 00084 } 00085 00086 void compute_Stokes_element_matrix( 00087 FE& v_fe, 00088 FE& p_fe, 00089 Dof& dof, 00090 std::map<std::pair<unsigned int,unsigned int>, GiNaC::ex>& A) 00091 { 00092 std::pair<unsigned int,unsigned int> index; 00093 std::pair<unsigned int,unsigned int> index2; 00094 00095 // FIXME: need to check that p_fe 00096 // contains the same domain 00097 Polygon& domain = v_fe.get_polygon(); 00098 00099 // Insert the local degrees of freedom into the global Dof 00100 for (unsigned int i=0; i< v_fe.nbf(); i++) 00101 { 00102 dof.insert_dof(1,i,v_fe.dof(i)); 00103 } 00104 for (unsigned int i=0; i< p_fe.nbf(); i++) 00105 { 00106 dof.insert_dof(1,v_fe.nbf()+i,p_fe.dof(i)); 00107 } 00108 00109 // The term (grad u, grad v) 00110 for (unsigned int i=0; i< v_fe.nbf(); i++) 00111 { 00112 // fetch the global dof for v_i 00113 index.first = dof.glob_dof(v_fe.dof(i)); 00114 for (unsigned int j=0; j< v_fe.nbf(); j++) 00115 { 00116 // fetch the global dof for v_j 00117 index.second = dof.glob_dof(v_fe.dof(j)); 00118 GiNaC::ex nabla = inner(grad(v_fe.N(i)), 00119 grad(v_fe.N(j)));// compute the integrand 00120 // compute the integral 00121 GiNaC::ex Aij = domain.integrate(nabla); 00122 A[index] += Aij; // add to global matrix 00123 } 00124 } 00125 00126 // The term -(div u, q) 00127 for (unsigned int i=0; i< p_fe.nbf(); i++) 00128 { 00129 // fetch the global dof for p_i 00130 index.first = dof.glob_dof(p_fe.dof(i)); 00131 for (unsigned int j=0; j< v_fe.nbf(); j++) 00132 { 00133 // fetch the global dof for v_j 00134 index.second=dof.glob_dof(v_fe.dof(j)); 00135 // compute the integrand 00136 GiNaC::ex divV= -p_fe.N(i)*div(v_fe.N(j)); 00137 // compute the integral 00138 GiNaC::ex Aij = domain.integrate(divV); 00139 A[index] += Aij; // add to global matrix 00140 00141 // Do not need to compute the term (grad(p),v), since the system is 00142 // symmetric. We simply set Aji = Aij 00143 index2.first = index.second; 00144 index2.second = index.first; 00145 A[index2] += Aij; 00146 } 00147 } 00148 } 00149 00150 void compute_mixed_Poisson_element_matrix( 00151 FE& v_fe, 00152 FE& p_fe, 00153 Dof& dof, 00154 std::map<std::pair<unsigned int,unsigned int>, GiNaC::ex>& A) 00155 { 00156 std::pair<unsigned int,unsigned int> index; 00157 std::pair<unsigned int,unsigned int> index2; 00158 00159 // FIXME: need to check that p_fe 00160 // contains the same domain 00161 Polygon& domain = v_fe.get_polygon(); 00162 00163 // Insert the local degrees of freedom into the global Dof 00164 for (unsigned int i=0; i< v_fe.nbf(); i++) 00165 { 00166 dof.insert_dof(1,i,v_fe.dof(i)); 00167 } 00168 for (unsigned int i=0; i< p_fe.nbf(); i++) 00169 { 00170 dof.insert_dof(1,v_fe.nbf()+i+1,p_fe.dof(i)); 00171 } 00172 00173 // The term (u,v) 00174 for (unsigned int i=0; i< v_fe.nbf(); i++) 00175 { 00176 // fetch the global dof related to i and v 00177 index.first = dof.glob_dof(v_fe.dof(i)); 00178 for (unsigned int j=0; j< v_fe.nbf(); j++) 00179 { 00180 // fetch the global dof related to j and p 00181 index.second = dof.glob_dof(v_fe.dof(j)); 00182 // compute the integrand 00183 GiNaC::ex mass = inner(v_fe.N(i),v_fe.N(j)); 00184 // compute the integral 00185 GiNaC::ex Aij = domain.integrate(mass); 00186 A[index] += Aij; // add to global matrix 00187 } 00188 } 00189 00190 // The term -(div u, q) 00191 for (unsigned int i=0; i< p_fe.nbf(); i++) 00192 { 00193 // fetch the global dof for p_i 00194 index.first = dof.glob_dof(p_fe.dof(i)); 00195 for (unsigned int j=0; j< v_fe.nbf(); j++) 00196 { 00197 // fetch the global dof for v_j 00198 index.second=dof.glob_dof(v_fe.dof(j)); 00199 // compute the integrand 00200 GiNaC::ex divV= -p_fe.N(i)*div(v_fe.N(j)); 00201 // compute the integral 00202 GiNaC::ex Aij = domain.integrate(divV); 00203 A[index] += Aij; // add to global matrix 00204 00205 // Do not need to compute the term (grad(p),v), since the system is 00206 // symmetric we simply set Aji = Aij 00207 index2.first = index.second; 00208 index2.second = index.first; 00209 A[index2] += Aij; 00210 } 00211 } 00212 } 00213 00214 }