$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 // Local includes 00021 #include "libmesh/dof_map.h" 00022 #include "libmesh/fe.h" 00023 #include "libmesh/fe_interface.h" 00024 #include "libmesh/elem.h" 00025 #include "libmesh/threads.h" 00026 #include "libmesh/tensor_value.h" 00027 00028 namespace libMesh 00029 { 00030 00031 // ------------------------------------------------------------ 00032 // Lagrange-specific implementations 00033 00034 00035 // Anonymous namespace for local helper functions 00036 namespace { 00037 void lagrange_vec_nodal_soln(const Elem* elem, 00038 const Order order, 00039 const std::vector<Number>& elem_soln, 00040 const int dim, 00041 std::vector<Number>& nodal_soln) 00042 { 00043 const unsigned int n_nodes = elem->n_nodes(); 00044 const ElemType type = elem->type(); 00045 00046 const Order totalorder = static_cast<Order>(order+elem->p_level()); 00047 00048 nodal_soln.resize(dim*n_nodes); 00049 00050 switch (totalorder) 00051 { 00052 // linear Lagrange shape functions 00053 case FIRST: 00054 { 00055 switch (type) 00056 { 00057 case TRI6: 00058 { 00059 libmesh_assert_equal_to (elem_soln.size(), 2*3); 00060 libmesh_assert_equal_to (nodal_soln.size(), 2*6); 00061 00062 // node 0 components 00063 nodal_soln[0] = elem_soln[0]; 00064 nodal_soln[1] = elem_soln[1]; 00065 00066 // node 1 components 00067 nodal_soln[2] = elem_soln[2]; 00068 nodal_soln[3] = elem_soln[3]; 00069 00070 // node 2 components 00071 nodal_soln[4] = elem_soln[4]; 00072 nodal_soln[5] = elem_soln[5]; 00073 00074 // node 3 components 00075 nodal_soln[6] = .5*(elem_soln[0] + elem_soln[2]); 00076 nodal_soln[7] = .5*(elem_soln[1] + elem_soln[3]); 00077 00078 // node 4 components 00079 nodal_soln[8] = .5*(elem_soln[2] + elem_soln[4]); 00080 nodal_soln[9] = .5*(elem_soln[3] + elem_soln[5]); 00081 00082 // node 5 components 00083 nodal_soln[10] = .5*(elem_soln[0] + elem_soln[4]); 00084 nodal_soln[11] = .5*(elem_soln[1] + elem_soln[5]); 00085 00086 return; 00087 } 00088 00089 00090 case QUAD8: 00091 case QUAD9: 00092 { 00093 libmesh_assert_equal_to (elem_soln.size(), 2*4); 00094 00095 if (type == QUAD8) 00096 libmesh_assert_equal_to (nodal_soln.size(), 2*8); 00097 else 00098 libmesh_assert_equal_to (nodal_soln.size(), 2*9); 00099 00100 // node 0 components 00101 nodal_soln[0] = elem_soln[0]; 00102 nodal_soln[1] = elem_soln[1]; 00103 00104 // node 1 components 00105 nodal_soln[2] = elem_soln[2]; 00106 nodal_soln[3] = elem_soln[3]; 00107 00108 // node 2 components 00109 nodal_soln[4] = elem_soln[4]; 00110 nodal_soln[5] = elem_soln[5]; 00111 00112 // node 3 components 00113 nodal_soln[6] = elem_soln[6]; 00114 nodal_soln[7] = elem_soln[7]; 00115 00116 // node 4 components 00117 nodal_soln[8] = .5*(elem_soln[0] + elem_soln[2]); 00118 nodal_soln[9] = .5*(elem_soln[1] + elem_soln[3]); 00119 00120 // node 5 components 00121 nodal_soln[10] = .5*(elem_soln[2] + elem_soln[4]); 00122 nodal_soln[11] = .5*(elem_soln[3] + elem_soln[5]); 00123 00124 // node 6 components 00125 nodal_soln[12] = .5*(elem_soln[4] + elem_soln[6]); 00126 nodal_soln[13] = .5*(elem_soln[5] + elem_soln[7]); 00127 00128 // node 7 components 00129 nodal_soln[14] = .5*(elem_soln[6] + elem_soln[0]); 00130 nodal_soln[15] = .5*(elem_soln[7] + elem_soln[1]); 00131 00132 if (type == QUAD9) 00133 { 00134 // node 8 components 00135 nodal_soln[16] = .25*(elem_soln[0] + elem_soln[2] + elem_soln[4] + elem_soln[6]); 00136 nodal_soln[17] = .25*(elem_soln[1] + elem_soln[3] + elem_soln[5] + elem_soln[7]); 00137 } 00138 00139 return; 00140 } 00141 00142 00143 case TET10: 00144 { 00145 libmesh_assert_equal_to (elem_soln.size(), 3*4); 00146 libmesh_assert_equal_to (nodal_soln.size(), 3*10); 00147 00148 // node 0 components 00149 nodal_soln[0] = elem_soln[0]; 00150 nodal_soln[1] = elem_soln[1]; 00151 nodal_soln[2] = elem_soln[2]; 00152 00153 // node 1 components 00154 nodal_soln[3] = elem_soln[3]; 00155 nodal_soln[4] = elem_soln[4]; 00156 nodal_soln[5] = elem_soln[5]; 00157 00158 // node 2 components 00159 nodal_soln[6] = elem_soln[6]; 00160 nodal_soln[7] = elem_soln[7]; 00161 nodal_soln[8] = elem_soln[8]; 00162 00163 // node 3 components 00164 nodal_soln[9] = elem_soln[9]; 00165 nodal_soln[10] = elem_soln[10]; 00166 nodal_soln[11] = elem_soln[11]; 00167 00168 // node 4 components 00169 nodal_soln[12] = .5*(elem_soln[0] + elem_soln[3]); 00170 nodal_soln[13] = .5*(elem_soln[1] + elem_soln[4]); 00171 nodal_soln[14] = .5*(elem_soln[2] + elem_soln[5]); 00172 00173 // node 5 components 00174 nodal_soln[15] = .5*(elem_soln[3] + elem_soln[6]); 00175 nodal_soln[16] = .5*(elem_soln[4] + elem_soln[7]); 00176 nodal_soln[17] = .5*(elem_soln[5] + elem_soln[8]); 00177 00178 // node 6 components 00179 nodal_soln[18] = .5*(elem_soln[6] + elem_soln[0]); 00180 nodal_soln[19] = .5*(elem_soln[7] + elem_soln[1]); 00181 nodal_soln[20] = .5*(elem_soln[8] + elem_soln[2]); 00182 00183 // node 7 components 00184 nodal_soln[21] = .5*(elem_soln[9] + elem_soln[0]); 00185 nodal_soln[22] = .5*(elem_soln[10] + elem_soln[1]); 00186 nodal_soln[23] = .5*(elem_soln[11] + elem_soln[2]); 00187 00188 // node 8 components 00189 nodal_soln[24] = .5*(elem_soln[9] + elem_soln[3]); 00190 nodal_soln[25] = .5*(elem_soln[10] + elem_soln[4]); 00191 nodal_soln[26] = .5*(elem_soln[11] + elem_soln[5]); 00192 00193 // node 9 components 00194 nodal_soln[27] = .5*(elem_soln[9] + elem_soln[6]); 00195 nodal_soln[28] = .5*(elem_soln[10] + elem_soln[7]); 00196 nodal_soln[29] = .5*(elem_soln[11] + elem_soln[8]); 00197 00198 return; 00199 } 00200 00201 00202 case HEX20: 00203 case HEX27: 00204 { 00205 libmesh_assert_equal_to (elem_soln.size(), 3*8); 00206 00207 if (type == HEX20) 00208 libmesh_assert_equal_to (nodal_soln.size(), 3*20); 00209 else 00210 libmesh_assert_equal_to (nodal_soln.size(), 3*27); 00211 00212 // node 0 components 00213 nodal_soln[0] = elem_soln[0]; 00214 nodal_soln[1] = elem_soln[1]; 00215 nodal_soln[2] = elem_soln[2]; 00216 00217 // node 1 components 00218 nodal_soln[3] = elem_soln[3]; 00219 nodal_soln[4] = elem_soln[4]; 00220 nodal_soln[5] = elem_soln[5]; 00221 00222 // node 2 components 00223 nodal_soln[6] = elem_soln[6]; 00224 nodal_soln[7] = elem_soln[7]; 00225 nodal_soln[8] = elem_soln[8]; 00226 00227 // node 3 components 00228 nodal_soln[9] = elem_soln[9]; 00229 nodal_soln[10] = elem_soln[10]; 00230 nodal_soln[11] = elem_soln[11]; 00231 00232 // node 4 components 00233 nodal_soln[12] = elem_soln[12]; 00234 nodal_soln[13] = elem_soln[13]; 00235 nodal_soln[14] = elem_soln[14]; 00236 00237 // node 5 components 00238 nodal_soln[15] = elem_soln[15]; 00239 nodal_soln[16] = elem_soln[16]; 00240 nodal_soln[17] = elem_soln[17]; 00241 00242 // node 6 components 00243 nodal_soln[18] = elem_soln[18]; 00244 nodal_soln[19] = elem_soln[19]; 00245 nodal_soln[20] = elem_soln[20]; 00246 00247 // node 7 components 00248 nodal_soln[21] = elem_soln[21]; 00249 nodal_soln[22] = elem_soln[22]; 00250 nodal_soln[23] = elem_soln[23]; 00251 00252 // node 8 components 00253 nodal_soln[24] = .5*(elem_soln[0] + elem_soln[3]); 00254 nodal_soln[25] = .5*(elem_soln[1] + elem_soln[4]); 00255 nodal_soln[26] = .5*(elem_soln[2] + elem_soln[5]); 00256 00257 // node 9 components 00258 nodal_soln[27] = .5*(elem_soln[3] + elem_soln[6]); 00259 nodal_soln[28] = .5*(elem_soln[4] + elem_soln[7]); 00260 nodal_soln[29] = .5*(elem_soln[5] + elem_soln[8]); 00261 00262 // node 10 components 00263 nodal_soln[30] = .5*(elem_soln[6] + elem_soln[9]); 00264 nodal_soln[31] = .5*(elem_soln[7] + elem_soln[10]); 00265 nodal_soln[32] = .5*(elem_soln[8] + elem_soln[11]); 00266 00267 // node 11 components 00268 nodal_soln[33] = .5*(elem_soln[9] + elem_soln[0]); 00269 nodal_soln[34] = .5*(elem_soln[10] + elem_soln[1]); 00270 nodal_soln[35] = .5*(elem_soln[11] + elem_soln[2]); 00271 00272 // node 12 components 00273 nodal_soln[36] = .5*(elem_soln[0] + elem_soln[12]); 00274 nodal_soln[37] = .5*(elem_soln[1] + elem_soln[13]); 00275 nodal_soln[38] = .5*(elem_soln[2] + elem_soln[14]); 00276 00277 // node 13 components 00278 nodal_soln[39] = .5*(elem_soln[3] + elem_soln[15]); 00279 nodal_soln[40] = .5*(elem_soln[4] + elem_soln[16]); 00280 nodal_soln[41] = .5*(elem_soln[5] + elem_soln[17]); 00281 00282 // node 14 components 00283 nodal_soln[42] = .5*(elem_soln[6] + elem_soln[18]); 00284 nodal_soln[43] = .5*(elem_soln[7] + elem_soln[19]); 00285 nodal_soln[44] = .5*(elem_soln[8] + elem_soln[20]); 00286 00287 // node 15 components 00288 nodal_soln[45] = .5*(elem_soln[9] + elem_soln[21]); 00289 nodal_soln[46] = .5*(elem_soln[10] + elem_soln[22]); 00290 nodal_soln[47] = .5*(elem_soln[11] + elem_soln[23]); 00291 00292 // node 16 components 00293 nodal_soln[48] = .5*(elem_soln[12] + elem_soln[15]); 00294 nodal_soln[49] = .5*(elem_soln[13] + elem_soln[16]); 00295 nodal_soln[50] = .5*(elem_soln[14] + elem_soln[17]); 00296 00297 // node 17 components 00298 nodal_soln[51] = .5*(elem_soln[15] + elem_soln[18]); 00299 nodal_soln[52] = .5*(elem_soln[16] + elem_soln[19]); 00300 nodal_soln[53] = .5*(elem_soln[17] + elem_soln[20]); 00301 00302 // node 18 components 00303 nodal_soln[54] = .5*(elem_soln[18] + elem_soln[21]); 00304 nodal_soln[55] = .5*(elem_soln[19] + elem_soln[22]); 00305 nodal_soln[56] = .5*(elem_soln[20] + elem_soln[23]); 00306 00307 // node 19 components 00308 nodal_soln[57] = .5*(elem_soln[12] + elem_soln[21]); 00309 nodal_soln[58] = .5*(elem_soln[13] + elem_soln[22]); 00310 nodal_soln[59] = .5*(elem_soln[14] + elem_soln[23]); 00311 00312 if (type == HEX27) 00313 { 00314 // node 20 components 00315 nodal_soln[60] = .25*(elem_soln[0] + elem_soln[3] + elem_soln[6] + elem_soln[9]); 00316 nodal_soln[61] = .25*(elem_soln[1] + elem_soln[4] + elem_soln[7] + elem_soln[10]); 00317 nodal_soln[62] = .25*(elem_soln[2] + elem_soln[5] + elem_soln[8] + elem_soln[11]); 00318 00319 // node 21 components 00320 nodal_soln[63] = .25*(elem_soln[0] + elem_soln[3] + elem_soln[12] + elem_soln[15]); 00321 nodal_soln[64] = .25*(elem_soln[1] + elem_soln[4] + elem_soln[13] + elem_soln[16]); 00322 nodal_soln[65] = .25*(elem_soln[2] + elem_soln[5] + elem_soln[14] + elem_soln[17]); 00323 00324 // node 22 components 00325 nodal_soln[66] = .25*(elem_soln[3] + elem_soln[6] + elem_soln[15] + elem_soln[18]); 00326 nodal_soln[67] = .25*(elem_soln[4] + elem_soln[7] + elem_soln[16] + elem_soln[19]); 00327 nodal_soln[68] = .25*(elem_soln[5] + elem_soln[8] + elem_soln[17] + elem_soln[20]); 00328 00329 // node 23 components 00330 nodal_soln[69] = .25*(elem_soln[6] + elem_soln[9] + elem_soln[18] + elem_soln[21]); 00331 nodal_soln[70] = .25*(elem_soln[7] + elem_soln[10] + elem_soln[19] + elem_soln[22]); 00332 nodal_soln[71] = .25*(elem_soln[8] + elem_soln[11] + elem_soln[20] + elem_soln[23]); 00333 00334 // node 24 components 00335 nodal_soln[72] = .25*(elem_soln[9] + elem_soln[0] + elem_soln[21] + elem_soln[12]); 00336 nodal_soln[73] = .25*(elem_soln[10] + elem_soln[1] + elem_soln[22] + elem_soln[13]); 00337 nodal_soln[74] = .25*(elem_soln[11] + elem_soln[2] + elem_soln[23] + elem_soln[14]); 00338 00339 // node 25 components 00340 nodal_soln[75] = .25*(elem_soln[12] + elem_soln[15] + elem_soln[18] + elem_soln[21]); 00341 nodal_soln[76] = .25*(elem_soln[13] + elem_soln[16] + elem_soln[19] + elem_soln[22]); 00342 nodal_soln[77] = .25*(elem_soln[14] + elem_soln[17] + elem_soln[20] + elem_soln[23]); 00343 00344 // node 26 components 00345 nodal_soln[78] = .125*(elem_soln[0] + elem_soln[3] + elem_soln[6] + elem_soln[9] + 00346 elem_soln[12] + elem_soln[15] + elem_soln[18] + elem_soln[21]); 00347 00348 nodal_soln[79] = .125*(elem_soln[1] + elem_soln[4] + elem_soln[7] + elem_soln[10] + 00349 elem_soln[13] + elem_soln[16] + elem_soln[19] + elem_soln[22]); 00350 00351 nodal_soln[80] = .125*(elem_soln[2] + elem_soln[5] + elem_soln[8] + elem_soln[11] + 00352 elem_soln[14] + elem_soln[17] + elem_soln[20] + elem_soln[23]); 00353 } 00354 00355 return; 00356 } 00357 00358 00359 case PRISM15: 00360 case PRISM18: 00361 { 00362 libmesh_assert_equal_to (elem_soln.size(), 3*6); 00363 00364 if (type == PRISM15) 00365 libmesh_assert_equal_to (nodal_soln.size(), 3*15); 00366 else 00367 libmesh_assert_equal_to (nodal_soln.size(), 3*18); 00368 00369 // node 0 components 00370 nodal_soln[0] = elem_soln[0]; 00371 nodal_soln[1] = elem_soln[1]; 00372 nodal_soln[2] = elem_soln[2]; 00373 00374 // node 1 components 00375 nodal_soln[3] = elem_soln[3]; 00376 nodal_soln[4] = elem_soln[4]; 00377 nodal_soln[5] = elem_soln[5]; 00378 00379 // node 2 components 00380 nodal_soln[6] = elem_soln[6]; 00381 nodal_soln[7] = elem_soln[7]; 00382 nodal_soln[8] = elem_soln[8]; 00383 00384 // node 3 components 00385 nodal_soln[9] = elem_soln[9]; 00386 nodal_soln[10] = elem_soln[10]; 00387 nodal_soln[11] = elem_soln[11]; 00388 00389 // node 4 components 00390 nodal_soln[12] = elem_soln[12]; 00391 nodal_soln[13] = elem_soln[13]; 00392 nodal_soln[14] = elem_soln[14]; 00393 00394 // node 5 components 00395 nodal_soln[15] = elem_soln[15]; 00396 nodal_soln[16] = elem_soln[16]; 00397 nodal_soln[17] = elem_soln[17]; 00398 00399 // node 6 components 00400 nodal_soln[18] = .5*(elem_soln[0] + elem_soln[3]); 00401 nodal_soln[19] = .5*(elem_soln[1] + elem_soln[4]); 00402 nodal_soln[20] = .5*(elem_soln[2] + elem_soln[5]); 00403 00404 // node 7 components 00405 nodal_soln[21] = .5*(elem_soln[3] + elem_soln[6]); 00406 nodal_soln[22] = .5*(elem_soln[4] + elem_soln[7]); 00407 nodal_soln[23] = .5*(elem_soln[5] + elem_soln[8]); 00408 00409 // node 8 components 00410 nodal_soln[24] = .5*(elem_soln[0] + elem_soln[6]); 00411 nodal_soln[25] = .5*(elem_soln[1] + elem_soln[7]); 00412 nodal_soln[26] = .5*(elem_soln[2] + elem_soln[8]); 00413 00414 // node 9 components 00415 nodal_soln[27] = .5*(elem_soln[0] + elem_soln[9]); 00416 nodal_soln[28] = .5*(elem_soln[1] + elem_soln[10]); 00417 nodal_soln[29] = .5*(elem_soln[2] + elem_soln[11]); 00418 00419 // node 10 components 00420 nodal_soln[30] = .5*(elem_soln[3] + elem_soln[12]); 00421 nodal_soln[31] = .5*(elem_soln[4] + elem_soln[13]); 00422 nodal_soln[32] = .5*(elem_soln[5] + elem_soln[14]); 00423 00424 // node 11 components 00425 nodal_soln[33] = .5*(elem_soln[6] + elem_soln[15]); 00426 nodal_soln[34] = .5*(elem_soln[7] + elem_soln[16]); 00427 nodal_soln[35] = .5*(elem_soln[8] + elem_soln[17]); 00428 00429 // node 12 components 00430 nodal_soln[36] = .5*(elem_soln[9] + elem_soln[12]); 00431 nodal_soln[37] = .5*(elem_soln[10] + elem_soln[13]); 00432 nodal_soln[38] = .5*(elem_soln[11] + elem_soln[14]); 00433 00434 // node 13 components 00435 nodal_soln[39] = .5*(elem_soln[12] + elem_soln[15]); 00436 nodal_soln[40] = .5*(elem_soln[13] + elem_soln[16]); 00437 nodal_soln[41] = .5*(elem_soln[14] + elem_soln[17]); 00438 00439 // node 14 components 00440 nodal_soln[42] = .5*(elem_soln[12] + elem_soln[15]); 00441 nodal_soln[43] = .5*(elem_soln[13] + elem_soln[16]); 00442 nodal_soln[44] = .5*(elem_soln[14] + elem_soln[17]); 00443 00444 if (type == PRISM18) 00445 { 00446 // node 15 components 00447 nodal_soln[45] = .25*(elem_soln[0] + elem_soln[3] + elem_soln[12] + elem_soln[9]); 00448 nodal_soln[46] = .25*(elem_soln[1] + elem_soln[4] + elem_soln[13] + elem_soln[10]); 00449 nodal_soln[47] = .25*(elem_soln[2] + elem_soln[5] + elem_soln[14] + elem_soln[11]); 00450 00451 // node 16 components 00452 nodal_soln[48] = .25*(elem_soln[3] + elem_soln[6] + elem_soln[15] + elem_soln[12]); 00453 nodal_soln[49] = .25*(elem_soln[4] + elem_soln[7] + elem_soln[16] + elem_soln[13]); 00454 nodal_soln[50] = .25*(elem_soln[5] + elem_soln[8] + elem_soln[17] + elem_soln[14]); 00455 00456 // node 17 components 00457 nodal_soln[51] = .25*(elem_soln[6] + elem_soln[0] + elem_soln[9] + elem_soln[15]); 00458 nodal_soln[52] = .25*(elem_soln[7] + elem_soln[1] + elem_soln[10] + elem_soln[16]); 00459 nodal_soln[53] = .25*(elem_soln[8] + elem_soln[2] + elem_soln[11] + elem_soln[17]); 00460 } 00461 00462 return; 00463 } 00464 00465 default: 00466 { 00467 // By default the element solution _is_ nodal, 00468 // so just copy it. 00469 nodal_soln = elem_soln; 00470 00471 return; 00472 } 00473 } 00474 } 00475 00476 case SECOND: 00477 { 00478 switch (type) 00479 { 00480 default: 00481 { 00482 // By default the element solution _is_ nodal, 00483 // so just copy it. 00484 nodal_soln = elem_soln; 00485 00486 return; 00487 } 00488 } 00489 } 00490 00491 default: 00492 { 00493 00494 } 00495 00496 } // switch(totalorder) 00497 00498 }// void lagrange_vec_nodal_soln 00499 00500 } // anonymous namespace 00501 00502 00503 // Do full-specialization for every dimension, instead 00504 // of explicit instantiation at the end of this file. 00505 // This could be macro-ified so that it fits on one line... 00506 template <> 00507 void FE<0,LAGRANGE_VEC>::nodal_soln(const Elem* elem, 00508 const Order order, 00509 const std::vector<Number>& elem_soln, 00510 std::vector<Number>& nodal_soln) 00511 { FE<0,LAGRANGE>::nodal_soln(elem, order, elem_soln, nodal_soln); } 00512 00513 template <> 00514 void FE<1,LAGRANGE_VEC>::nodal_soln(const Elem* elem, 00515 const Order order, 00516 const std::vector<Number>& elem_soln, 00517 std::vector<Number>& nodal_soln) 00518 { FE<1,LAGRANGE>::nodal_soln(elem, order, elem_soln, nodal_soln); } 00519 00520 template <> 00521 void FE<2,LAGRANGE_VEC>::nodal_soln(const Elem* elem, 00522 const Order order, 00523 const std::vector<Number>& elem_soln, 00524 std::vector<Number>& nodal_soln) 00525 { lagrange_vec_nodal_soln(elem, order, elem_soln, 2 /*dimension*/, nodal_soln); } 00526 00527 template <> 00528 void FE<3,LAGRANGE_VEC>::nodal_soln(const Elem* elem, 00529 const Order order, 00530 const std::vector<Number>& elem_soln, 00531 std::vector<Number>& nodal_soln) 00532 { lagrange_vec_nodal_soln(elem, order, elem_soln, 3 /*dimension*/, nodal_soln); } 00533 00534 00535 // Specialize for shape function routines by leveraging scalar LAGRANGE elements 00536 00537 // 0-D 00538 template <> RealGradient FE<0,LAGRANGE_VEC>::shape(const ElemType type, const Order order, 00539 const unsigned int i, const Point& p) 00540 { 00541 Real value = FE<0,LAGRANGE>::shape( type, order, i, p ); 00542 return libMesh::RealGradient( value ); 00543 } 00544 template <> RealGradient FE<0,LAGRANGE_VEC>::shape_deriv(const ElemType type, const Order order, 00545 const unsigned int i, const unsigned int j, 00546 const Point& p) 00547 { 00548 Real value = FE<0,LAGRANGE>::shape_deriv( type, order, i, j, p ); 00549 return libMesh::RealGradient( value ); 00550 } 00551 template <> RealGradient FE<0,LAGRANGE_VEC>::shape_second_deriv(const ElemType type, const Order order, 00552 const unsigned int i, const unsigned int j, 00553 const Point& p) 00554 { 00555 Real value = FE<0,LAGRANGE>::shape_second_deriv( type, order, i, j, p ); 00556 return libMesh::RealGradient( value ); 00557 } 00558 00559 // 1-D 00560 template <> RealGradient FE<1,LAGRANGE_VEC>::shape(const ElemType type, const Order order, 00561 const unsigned int i, const Point& p) 00562 { 00563 Real value = FE<1,LAGRANGE>::shape( type, order, i, p ); 00564 return libMesh::RealGradient( value ); 00565 } 00566 template <> RealGradient FE<1,LAGRANGE_VEC>::shape_deriv(const ElemType type, const Order order, 00567 const unsigned int i, const unsigned int j, 00568 const Point& p) 00569 { 00570 Real value = FE<1,LAGRANGE>::shape_deriv( type, order, i, j, p ); 00571 return libMesh::RealGradient( value ); 00572 } 00573 template <> RealGradient FE<1,LAGRANGE_VEC>::shape_second_deriv(const ElemType type, const Order order, 00574 const unsigned int i, const unsigned int j, 00575 const Point& p) 00576 { 00577 Real value = FE<1,LAGRANGE>::shape_second_deriv( type, order, i, j, p ); 00578 return libMesh::RealGradient( value ); 00579 } 00580 00581 // 2-D 00582 template <> RealGradient FE<2,LAGRANGE_VEC>::shape(const ElemType type, const Order order, 00583 const unsigned int i, const Point& p) 00584 { 00585 Real value = FE<2,LAGRANGE>::shape( type, order, i/2, p ); 00586 00587 switch( i%2 ) 00588 { 00589 case 0: 00590 return libMesh::RealGradient( value ); 00591 00592 case 1: 00593 return libMesh::RealGradient( Real(0), value ); 00594 00595 default: 00596 libmesh_error_msg("i%2 must be either 0 or 1!"); 00597 } 00598 00599 //dummy 00600 return libMesh::RealGradient(); 00601 } 00602 template <> RealGradient FE<2,LAGRANGE_VEC>::shape_deriv(const ElemType type, const Order order, 00603 const unsigned int i, const unsigned int j, 00604 const Point& p) 00605 { 00606 Real value = FE<2,LAGRANGE>::shape_deriv( type, order, i/2, j, p ); 00607 00608 switch( i%2 ) 00609 { 00610 case 0: 00611 return libMesh::RealGradient( value ); 00612 00613 case 1: 00614 return libMesh::RealGradient( Real(0), value ); 00615 00616 default: 00617 libmesh_error_msg("i%2 must be either 0 or 1!"); 00618 } 00619 00620 //dummy 00621 return libMesh::RealGradient(); 00622 } 00623 template <> RealGradient FE<2,LAGRANGE_VEC>::shape_second_deriv(const ElemType type, const Order order, 00624 const unsigned int i, const unsigned int j, 00625 const Point& p) 00626 { 00627 Real value = FE<2,LAGRANGE>::shape_second_deriv( type, order, i/2, j, p ); 00628 00629 switch( i%2 ) 00630 { 00631 case 0: 00632 return libMesh::RealGradient( value ); 00633 00634 case 1: 00635 return libMesh::RealGradient( Real(0), value ); 00636 00637 default: 00638 libmesh_error_msg("i%2 must be either 0 or 1!"); 00639 } 00640 00641 //dummy 00642 return libMesh::RealGradient(); 00643 } 00644 00645 00646 // 3-D 00647 template <> RealGradient FE<3,LAGRANGE_VEC>::shape(const ElemType type, const Order order, 00648 const unsigned int i, const Point& p) 00649 { 00650 Real value = FE<3,LAGRANGE>::shape( type, order, i/3, p ); 00651 00652 switch( i%3 ) 00653 { 00654 case 0: 00655 return libMesh::RealGradient( value ); 00656 00657 case 1: 00658 return libMesh::RealGradient( Real(0), value ); 00659 00660 case 2: 00661 return libMesh::RealGradient( Real(0), Real(0), value ); 00662 00663 default: 00664 libmesh_error_msg("i%3 must be 0, 1, or 2!"); 00665 } 00666 00667 //dummy 00668 return libMesh::RealGradient(); 00669 } 00670 template <> RealGradient FE<3,LAGRANGE_VEC>::shape_deriv(const ElemType type, const Order order, 00671 const unsigned int i, const unsigned int j, 00672 const Point& p) 00673 { 00674 Real value = FE<3,LAGRANGE>::shape_deriv( type, order, i/3, j, p ); 00675 00676 switch( i%3 ) 00677 { 00678 case 0: 00679 return libMesh::RealGradient( value ); 00680 00681 case 1: 00682 return libMesh::RealGradient( Real(0), value ); 00683 00684 case 2: 00685 return libMesh::RealGradient( Real(0), Real(0), value ); 00686 00687 default: 00688 libmesh_error_msg("i%3 must be 0, 1, or 2!"); 00689 } 00690 00691 //dummy 00692 return libMesh::RealGradient(); 00693 } 00694 template <> RealGradient FE<3,LAGRANGE_VEC>::shape_second_deriv(const ElemType type, const Order order, 00695 const unsigned int i, const unsigned int j, 00696 const Point& p) 00697 { 00698 Real value = FE<3,LAGRANGE>::shape_second_deriv( type, order, i/3, j, p ); 00699 00700 switch( i%3 ) 00701 { 00702 case 0: 00703 return libMesh::RealGradient( value ); 00704 00705 case 1: 00706 return libMesh::RealGradient( Real(0), value ); 00707 00708 case 2: 00709 return libMesh::RealGradient( Real(0), Real(0), value ); 00710 00711 default: 00712 libmesh_error_msg("i%3 must be 0, 1, or 2!"); 00713 } 00714 00715 //dummy 00716 return libMesh::RealGradient(); 00717 } 00718 00719 00720 00721 // 0-D 00722 template <> RealGradient FE<0,LAGRANGE_VEC>::shape(const Elem* elem, const Order order, 00723 const unsigned int i, const Point& p) 00724 { 00725 Real value = FE<0,LAGRANGE>::shape( elem->type(), static_cast<Order>(order + elem->p_level()), i, p); 00726 return libMesh::RealGradient( value ); 00727 } 00728 template <> RealGradient FE<0,LAGRANGE_VEC>::shape_deriv(const Elem* elem, const Order order, 00729 const unsigned int i, const unsigned int j, 00730 const Point& p) 00731 { 00732 Real value = FE<0,LAGRANGE>::shape_deriv( elem->type(), static_cast<Order>(order + elem->p_level()), i, j, p); 00733 return libMesh::RealGradient( value ); 00734 } 00735 template <> RealGradient FE<0,LAGRANGE_VEC>::shape_second_deriv(const Elem* elem, const Order order, 00736 const unsigned int i, const unsigned int j, 00737 const Point& p) 00738 { 00739 Real value = FE<0,LAGRANGE>::shape_second_deriv( elem->type(), static_cast<Order>(order + elem->p_level()), i, j, p); 00740 return libMesh::RealGradient( value ); 00741 } 00742 00743 // 1-D 00744 template <> RealGradient FE<1,LAGRANGE_VEC>::shape(const Elem* elem, const Order order, 00745 const unsigned int i, const Point& p) 00746 { 00747 Real value = FE<1,LAGRANGE>::shape( elem->type(), static_cast<Order>(order + elem->p_level()), i, p); 00748 return libMesh::RealGradient( value ); 00749 } 00750 template <> RealGradient FE<1,LAGRANGE_VEC>::shape_deriv(const Elem* elem, const Order order, 00751 const unsigned int i, const unsigned int j, 00752 const Point& p) 00753 { 00754 Real value = FE<1,LAGRANGE>::shape_deriv( elem->type(), static_cast<Order>(order + elem->p_level()), i, j, p); 00755 return libMesh::RealGradient( value ); 00756 } 00757 template <> RealGradient FE<1,LAGRANGE_VEC>::shape_second_deriv(const Elem* elem, const Order order, 00758 const unsigned int i, const unsigned int j, 00759 const Point& p) 00760 { 00761 Real value = FE<1,LAGRANGE>::shape_second_deriv( elem->type(), static_cast<Order>(order + elem->p_level()), i, j, p); 00762 return libMesh::RealGradient( value ); 00763 } 00764 00765 // 2-D 00766 template <> RealGradient FE<2,LAGRANGE_VEC>::shape(const Elem* elem, const Order order, 00767 const unsigned int i, const Point& p) 00768 { 00769 Real value = FE<2,LAGRANGE>::shape( elem->type(), static_cast<Order>(order + elem->p_level()), i/2, p ); 00770 00771 switch( i%2 ) 00772 { 00773 case 0: 00774 return libMesh::RealGradient( value ); 00775 00776 case 1: 00777 return libMesh::RealGradient( Real(0), value ); 00778 00779 default: 00780 libmesh_error_msg("i%2 must be either 0 or 1!"); 00781 } 00782 00783 //dummy 00784 return libMesh::RealGradient(); 00785 } 00786 template <> RealGradient FE<2,LAGRANGE_VEC>::shape_deriv(const Elem* elem, const Order order, 00787 const unsigned int i, const unsigned int j, 00788 const Point& p) 00789 { 00790 Real value = FE<2,LAGRANGE>::shape_deriv( elem->type(), static_cast<Order>(order + elem->p_level()), i/2, j, p ); 00791 00792 switch( i%2 ) 00793 { 00794 case 0: 00795 return libMesh::RealGradient( value ); 00796 00797 case 1: 00798 return libMesh::RealGradient( Real(0), value ); 00799 00800 default: 00801 libmesh_error_msg("i%2 must be either 0 or 1!"); 00802 } 00803 00804 //dummy 00805 return libMesh::RealGradient(); 00806 } 00807 template <> RealGradient FE<2,LAGRANGE_VEC>::shape_second_deriv(const Elem* elem, const Order order, 00808 const unsigned int i, const unsigned int j, 00809 const Point& p) 00810 { 00811 Real value = FE<2,LAGRANGE>::shape_second_deriv( elem->type(), static_cast<Order>(order + elem->p_level()), i/2, j, p ); 00812 00813 switch( i%2 ) 00814 { 00815 case 0: 00816 return libMesh::RealGradient( value ); 00817 00818 case 1: 00819 return libMesh::RealGradient( Real(0), value ); 00820 00821 default: 00822 libmesh_error_msg("i%2 must be either 0 or 1!"); 00823 } 00824 00825 //dummy 00826 return libMesh::RealGradient(); 00827 } 00828 00829 // 3-D 00830 template <> RealGradient FE<3,LAGRANGE_VEC>::shape(const Elem* elem, const Order order, 00831 const unsigned int i, const Point& p) 00832 { 00833 Real value = FE<3,LAGRANGE>::shape( elem->type(), static_cast<Order>(order + elem->p_level()), i/3, p ); 00834 00835 switch( i%3 ) 00836 { 00837 case 0: 00838 return libMesh::RealGradient( value ); 00839 00840 case 1: 00841 return libMesh::RealGradient( Real(0), value ); 00842 00843 case 2: 00844 return libMesh::RealGradient( Real(0), Real(0), value ); 00845 00846 default: 00847 libmesh_error_msg("i%3 must be 0, 1, or 2!"); 00848 } 00849 00850 //dummy 00851 return libMesh::RealGradient(); 00852 } 00853 template <> RealGradient FE<3,LAGRANGE_VEC>::shape_deriv(const Elem* elem, const Order order, 00854 const unsigned int i, const unsigned int j, 00855 const Point& p) 00856 { 00857 Real value = FE<3,LAGRANGE>::shape_deriv( elem->type(), static_cast<Order>(order + elem->p_level()), i/3, j, p ); 00858 00859 switch( i%3 ) 00860 { 00861 case 0: 00862 return libMesh::RealGradient( value ); 00863 00864 case 1: 00865 return libMesh::RealGradient( Real(0), value ); 00866 00867 case 2: 00868 return libMesh::RealGradient( Real(0), Real(0), value ); 00869 00870 default: 00871 libmesh_error_msg("i%3 must be 0, 1, or 2!"); 00872 } 00873 00874 //dummy 00875 return libMesh::RealGradient(); 00876 } 00877 template <> RealGradient FE<3,LAGRANGE_VEC>::shape_second_deriv(const Elem* elem, const Order order, 00878 const unsigned int i, const unsigned int j, 00879 const Point& p) 00880 { 00881 Real value = FE<3,LAGRANGE>::shape_second_deriv( elem->type(), static_cast<Order>(order + elem->p_level()), i/3, j, p ); 00882 00883 switch( i%3 ) 00884 { 00885 case 0: 00886 return libMesh::RealGradient( value ); 00887 00888 case 1: 00889 return libMesh::RealGradient( Real(0), value ); 00890 00891 case 2: 00892 return libMesh::RealGradient( Real(0), Real(0), value ); 00893 00894 default: 00895 libmesh_error_msg("i%3 must be 0, 1, or 2!"); 00896 } 00897 00898 //dummy 00899 return libMesh::RealGradient(); 00900 } 00901 00902 // Do full-specialization for every dimension, instead 00903 // of explicit instantiation at the end of this function. 00904 // This could be macro-ified. 00905 template <> unsigned int FE<0,LAGRANGE_VEC>::n_dofs(const ElemType t, const Order o) { return FE<0,LAGRANGE>::n_dofs(t,o); } 00906 template <> unsigned int FE<1,LAGRANGE_VEC>::n_dofs(const ElemType t, const Order o) { return FE<1,LAGRANGE>::n_dofs(t,o); } 00907 template <> unsigned int FE<2,LAGRANGE_VEC>::n_dofs(const ElemType t, const Order o) { return 2*FE<2,LAGRANGE>::n_dofs(t,o); } 00908 template <> unsigned int FE<3,LAGRANGE_VEC>::n_dofs(const ElemType t, const Order o) { return 3*FE<3,LAGRANGE>::n_dofs(t,o); } 00909 00910 00911 // Do full-specialization for every dimension, instead 00912 // of explicit instantiation at the end of this function. 00913 template <> unsigned int FE<0,LAGRANGE_VEC>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return FE<0,LAGRANGE>::n_dofs_at_node(t,o,n); } 00914 template <> unsigned int FE<1,LAGRANGE_VEC>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return FE<1,LAGRANGE>::n_dofs_at_node(t,o,n); } 00915 template <> unsigned int FE<2,LAGRANGE_VEC>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return 2*FE<2,LAGRANGE>::n_dofs_at_node(t,o,n); } 00916 template <> unsigned int FE<3,LAGRANGE_VEC>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return 3*FE<2,LAGRANGE>::n_dofs_at_node(t,o,n); } 00917 00918 00919 // Lagrange elements have no dofs per element 00920 // (just at the nodes) 00921 template <> unsigned int FE<0,LAGRANGE_VEC>::n_dofs_per_elem(const ElemType, const Order) { return 0; } 00922 template <> unsigned int FE<1,LAGRANGE_VEC>::n_dofs_per_elem(const ElemType, const Order) { return 0; } 00923 template <> unsigned int FE<2,LAGRANGE_VEC>::n_dofs_per_elem(const ElemType, const Order) { return 0; } 00924 template <> unsigned int FE<3,LAGRANGE_VEC>::n_dofs_per_elem(const ElemType, const Order) { return 0; } 00925 00926 // Lagrange FEMs are always C^0 continuous 00927 template <> FEContinuity FE<0,LAGRANGE_VEC>::get_continuity() const { return C_ZERO; } 00928 template <> FEContinuity FE<1,LAGRANGE_VEC>::get_continuity() const { return C_ZERO; } 00929 template <> FEContinuity FE<2,LAGRANGE_VEC>::get_continuity() const { return C_ZERO; } 00930 template <> FEContinuity FE<3,LAGRANGE_VEC>::get_continuity() const { return C_ZERO; } 00931 00932 // Lagrange FEMs are not hierarchic 00933 template <> bool FE<0,LAGRANGE_VEC>::is_hierarchic() const { return false; } 00934 template <> bool FE<1,LAGRANGE_VEC>::is_hierarchic() const { return false; } 00935 template <> bool FE<2,LAGRANGE_VEC>::is_hierarchic() const { return false; } 00936 template <> bool FE<3,LAGRANGE_VEC>::is_hierarchic() const { return false; } 00937 00938 // Lagrange FEM shapes do not need reinit (is this always true?) 00939 template <> bool FE<0,LAGRANGE_VEC>::shapes_need_reinit() const { return false; } 00940 template <> bool FE<1,LAGRANGE_VEC>::shapes_need_reinit() const { return false; } 00941 template <> bool FE<2,LAGRANGE_VEC>::shapes_need_reinit() const { return false; } 00942 template <> bool FE<3,LAGRANGE_VEC>::shapes_need_reinit() const { return false; } 00943 00944 // Methods for computing Lagrange constraints. Note: we pass the 00945 // dimension as the last argument to the anonymous helper function. 00946 // Also note: we only need instantiations of this function for 00947 // Dim==2 and 3. 00948 #ifdef LIBMESH_ENABLE_AMR 00949 template <> 00950 void FE<2,LAGRANGE_VEC>::compute_constraints (DofConstraints &constraints, 00951 DofMap &dof_map, 00952 const unsigned int variable_number, 00953 const Elem* elem) 00954 { //libmesh_not_implemented(); 00955 FEVectorBase::compute_proj_constraints(constraints, dof_map, variable_number, elem); 00956 } 00957 00958 template <> 00959 void FE<3,LAGRANGE_VEC>::compute_constraints (DofConstraints &constraints, 00960 DofMap &dof_map, 00961 const unsigned int variable_number, 00962 const Elem* elem) 00963 { //libmesh_not_implemented(); 00964 FEVectorBase::compute_proj_constraints(constraints, dof_map, variable_number, elem); 00965 } 00966 #endif // LIBMESH_ENABLE_AMR 00967 00968 } // namespace libMesh