$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 // C++ includes 00020 00021 // Local includes 00022 #include "libmesh/fe.h" 00023 #include "libmesh/elem.h" 00024 #include "libmesh/number_lookups.h" 00025 00026 namespace libMesh 00027 { 00028 00029 // anonymous namespace for local helper functions 00030 namespace 00031 { 00032 00033 Point get_min_point(const Elem *elem, 00034 unsigned int a, 00035 unsigned int b, 00036 unsigned int c, 00037 unsigned int d) 00038 { 00039 return std::min(std::min(elem->point(a),elem->point(b)), 00040 std::min(elem->point(c),elem->point(d))); 00041 } 00042 00043 void cube_indices(const Elem *elem, 00044 const unsigned int totalorder, 00045 const unsigned int i, 00046 Real &xi, Real &eta, Real &zeta, 00047 unsigned int &i0, 00048 unsigned int &i1, 00049 unsigned int &i2) 00050 { 00051 // The only way to make any sense of this 00052 // is to look at the mgflo/mg2/mgf documentation 00053 // and make the cut-out cube! 00054 // Example i0 and i1 values for totalorder = 3: 00055 // FIXME - these examples are incorrect now that we've got truly 00056 // hierarchic basis functions 00057 // Nodes 0 1 2 3 4 5 6 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 20 20 21 21 21 21 22 22 22 22 23 23 23 23 24 24 24 24 25 25 25 25 26 26 26 26 26 26 26 26 00058 // DOFS 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 18 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 60 62 63 00059 // static const unsigned int i0[] = {0, 1, 1, 0, 0, 1, 1, 0, 2, 3, 1, 1, 2, 3, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 2, 3, 1, 1, 2, 3, 0, 0, 2, 3, 2, 3, 2, 3, 2, 3, 1, 1, 1, 1, 2, 3, 2, 3, 0, 0, 0, 0, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3}; 00060 // static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 3, 1, 1, 2, 3, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 2, 3, 1, 1, 2, 3, 2, 2, 3, 3, 0, 0, 0, 0, 2, 3, 2, 3, 1, 1, 1, 1, 2, 3, 2, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3}; 00061 // static const unsigned int i2[] = {0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 2, 3, 2, 3, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3}; 00062 00063 // the number of DoFs per edge appears everywhere: 00064 const unsigned int e = totalorder - 1u; 00065 00066 libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u)*(totalorder+1u)); 00067 00068 Real xi_saved = xi, eta_saved = eta, zeta_saved = zeta; 00069 00070 // Vertices: 00071 if (i == 0) 00072 { 00073 i0 = 0; 00074 i1 = 0; 00075 i2 = 0; 00076 } 00077 else if (i == 1) 00078 { 00079 i0 = 1; 00080 i1 = 0; 00081 i2 = 0; 00082 } 00083 else if (i == 2) 00084 { 00085 i0 = 1; 00086 i1 = 1; 00087 i2 = 0; 00088 } 00089 else if (i == 3) 00090 { 00091 i0 = 0; 00092 i1 = 1; 00093 i2 = 0; 00094 } 00095 else if (i == 4) 00096 { 00097 i0 = 0; 00098 i1 = 0; 00099 i2 = 1; 00100 } 00101 else if (i == 5) 00102 { 00103 i0 = 1; 00104 i1 = 0; 00105 i2 = 1; 00106 } 00107 else if (i == 6) 00108 { 00109 i0 = 1; 00110 i1 = 1; 00111 i2 = 1; 00112 } 00113 else if (i == 7) 00114 { 00115 i0 = 0; 00116 i1 = 1; 00117 i2 = 1; 00118 } 00119 // Edge 0 00120 else if (i < 8 + e) 00121 { 00122 i0 = i - 6; 00123 i1 = 0; 00124 i2 = 0; 00125 if (elem->point(0) > elem->point(1)) 00126 xi = -xi_saved; 00127 } 00128 // Edge 1 00129 else if (i < 8 + 2*e) 00130 { 00131 i0 = 1; 00132 i1 = i - e - 6; 00133 i2 = 0; 00134 if (elem->point(1) > elem->point(2)) 00135 eta = -eta_saved; 00136 } 00137 // Edge 2 00138 else if (i < 8 + 3*e) 00139 { 00140 i0 = i - 2*e - 6; 00141 i1 = 1; 00142 i2 = 0; 00143 if (elem->point(3) > elem->point(2)) 00144 xi = -xi_saved; 00145 } 00146 // Edge 3 00147 else if (i < 8 + 4*e) 00148 { 00149 i0 = 0; 00150 i1 = i - 3*e - 6; 00151 i2 = 0; 00152 if (elem->point(0) > elem->point(3)) 00153 eta = -eta_saved; 00154 } 00155 // Edge 4 00156 else if (i < 8 + 5*e) 00157 { 00158 i0 = 0; 00159 i1 = 0; 00160 i2 = i - 4*e - 6; 00161 if (elem->point(0) > elem->point(4)) 00162 zeta = -zeta_saved; 00163 } 00164 // Edge 5 00165 else if (i < 8 + 6*e) 00166 { 00167 i0 = 1; 00168 i1 = 0; 00169 i2 = i - 5*e - 6; 00170 if (elem->point(1) > elem->point(5)) 00171 zeta = -zeta_saved; 00172 } 00173 // Edge 6 00174 else if (i < 8 + 7*e) 00175 { 00176 i0 = 1; 00177 i1 = 1; 00178 i2 = i - 6*e - 6; 00179 if (elem->point(2) > elem->point(6)) 00180 zeta = -zeta_saved; 00181 } 00182 // Edge 7 00183 else if (i < 8 + 8*e) 00184 { 00185 i0 = 0; 00186 i1 = 1; 00187 i2 = i - 7*e - 6; 00188 if (elem->point(3) > elem->point(7)) 00189 zeta = -zeta_saved; 00190 } 00191 // Edge 8 00192 else if (i < 8 + 9*e) 00193 { 00194 i0 = i - 8*e - 6; 00195 i1 = 0; 00196 i2 = 1; 00197 if (elem->point(4) > elem->point(5)) 00198 xi = -xi_saved; 00199 } 00200 // Edge 9 00201 else if (i < 8 + 10*e) 00202 { 00203 i0 = 1; 00204 i1 = i - 9*e - 6; 00205 i2 = 1; 00206 if (elem->point(5) > elem->point(6)) 00207 eta = -eta_saved; 00208 } 00209 // Edge 10 00210 else if (i < 8 + 11*e) 00211 { 00212 i0 = i - 10*e - 6; 00213 i1 = 1; 00214 i2 = 1; 00215 if (elem->point(7) > elem->point(6)) 00216 xi = -xi_saved; 00217 } 00218 // Edge 11 00219 else if (i < 8 + 12*e) 00220 { 00221 i0 = 0; 00222 i1 = i - 11*e - 6; 00223 i2 = 1; 00224 if (elem->point(4) > elem->point(7)) 00225 eta = -eta_saved; 00226 } 00227 // Face 0 00228 else if (i < 8 + 12*e + e*e) 00229 { 00230 unsigned int basisnum = i - 8 - 12*e; 00231 i0 = square_number_row[basisnum] + 2; 00232 i1 = square_number_column[basisnum] + 2; 00233 i2 = 0; 00234 const Point min_point = get_min_point(elem, 1, 2, 0, 3); 00235 00236 if (elem->point(0) == min_point) 00237 if (elem->point(1) == std::min(elem->point(1), elem->point(3))) 00238 { 00239 // Case 1 00240 xi = xi_saved; 00241 eta = eta_saved; 00242 } 00243 else 00244 { 00245 // Case 2 00246 xi = eta_saved; 00247 eta = xi_saved; 00248 } 00249 00250 else if (elem->point(3) == min_point) 00251 if (elem->point(0) == std::min(elem->point(0), elem->point(2))) 00252 { 00253 // Case 3 00254 xi = -eta_saved; 00255 eta = xi_saved; 00256 } 00257 else 00258 { 00259 // Case 4 00260 xi = xi_saved; 00261 eta = -eta_saved; 00262 } 00263 00264 else if (elem->point(2) == min_point) 00265 if (elem->point(3) == std::min(elem->point(3), elem->point(1))) 00266 { 00267 // Case 5 00268 xi = -xi_saved; 00269 eta = -eta_saved; 00270 } 00271 else 00272 { 00273 // Case 6 00274 xi = -eta_saved; 00275 eta = -xi_saved; 00276 } 00277 00278 else if (elem->point(1) == min_point) 00279 { 00280 if (elem->point(2) == std::min(elem->point(2), elem->point(0))) 00281 { 00282 // Case 7 00283 xi = eta_saved; 00284 eta = -xi_saved; 00285 } 00286 else 00287 { 00288 // Case 8 00289 xi = -xi_saved; 00290 eta = eta_saved; 00291 } 00292 } 00293 } 00294 // Face 1 00295 else if (i < 8 + 12*e + 2*e*e) 00296 { 00297 unsigned int basisnum = i - 8 - 12*e - e*e; 00298 i0 = square_number_row[basisnum] + 2; 00299 i1 = 0; 00300 i2 = square_number_column[basisnum] + 2; 00301 const Point min_point = get_min_point(elem, 0, 1, 5, 4); 00302 00303 if (elem->point(0) == min_point) 00304 if (elem->point(1) == std::min(elem->point(1), elem->point(4))) 00305 { 00306 // Case 1 00307 xi = xi_saved; 00308 zeta = zeta_saved; 00309 } 00310 else 00311 { 00312 // Case 2 00313 xi = zeta_saved; 00314 zeta = xi_saved; 00315 } 00316 00317 else if (elem->point(1) == min_point) 00318 if (elem->point(5) == std::min(elem->point(5), elem->point(0))) 00319 { 00320 // Case 3 00321 xi = zeta_saved; 00322 zeta = -xi_saved; 00323 } 00324 else 00325 { 00326 // Case 4 00327 xi = -xi_saved; 00328 zeta = zeta_saved; 00329 } 00330 00331 else if (elem->point(5) == min_point) 00332 if (elem->point(4) == std::min(elem->point(4), elem->point(1))) 00333 { 00334 // Case 5 00335 xi = -xi_saved; 00336 zeta = -zeta_saved; 00337 } 00338 else 00339 { 00340 // Case 6 00341 xi = -zeta_saved; 00342 zeta = -xi_saved; 00343 } 00344 00345 else if (elem->point(4) == min_point) 00346 { 00347 if (elem->point(0) == std::min(elem->point(0), elem->point(5))) 00348 { 00349 // Case 7 00350 xi = -xi_saved; 00351 zeta = zeta_saved; 00352 } 00353 else 00354 { 00355 // Case 8 00356 xi = xi_saved; 00357 zeta = -zeta_saved; 00358 } 00359 } 00360 } 00361 // Face 2 00362 else if (i < 8 + 12*e + 3*e*e) 00363 { 00364 unsigned int basisnum = i - 8 - 12*e - 2*e*e; 00365 i0 = 1; 00366 i1 = square_number_row[basisnum] + 2; 00367 i2 = square_number_column[basisnum] + 2; 00368 const Point min_point = get_min_point(elem, 1, 2, 6, 5); 00369 00370 if (elem->point(1) == min_point) 00371 if (elem->point(2) == std::min(elem->point(2), elem->point(5))) 00372 { 00373 // Case 1 00374 eta = eta_saved; 00375 zeta = zeta_saved; 00376 } 00377 else 00378 { 00379 // Case 2 00380 eta = zeta_saved; 00381 zeta = eta_saved; 00382 } 00383 00384 else if (elem->point(2) == min_point) 00385 if (elem->point(6) == std::min(elem->point(6), elem->point(1))) 00386 { 00387 // Case 3 00388 eta = zeta_saved; 00389 zeta = -eta_saved; 00390 } 00391 else 00392 { 00393 // Case 4 00394 eta = -eta_saved; 00395 zeta = zeta_saved; 00396 } 00397 00398 else if (elem->point(6) == min_point) 00399 if (elem->point(5) == std::min(elem->point(5), elem->point(2))) 00400 { 00401 // Case 5 00402 eta = -eta_saved; 00403 zeta = -zeta_saved; 00404 } 00405 else 00406 { 00407 // Case 6 00408 eta = -zeta_saved; 00409 zeta = -eta_saved; 00410 } 00411 00412 else if (elem->point(5) == min_point) 00413 { 00414 if (elem->point(1) == std::min(elem->point(1), elem->point(6))) 00415 { 00416 // Case 7 00417 eta = -zeta_saved; 00418 zeta = eta_saved; 00419 } 00420 else 00421 { 00422 // Case 8 00423 eta = eta_saved; 00424 zeta = -zeta_saved; 00425 } 00426 } 00427 } 00428 // Face 3 00429 else if (i < 8 + 12*e + 4*e*e) 00430 { 00431 unsigned int basisnum = i - 8 - 12*e - 3*e*e; 00432 i0 = square_number_row[basisnum] + 2; 00433 i1 = 1; 00434 i2 = square_number_column[basisnum] + 2; 00435 const Point min_point = get_min_point(elem, 2, 3, 7, 6); 00436 00437 if (elem->point(3) == min_point) 00438 if (elem->point(2) == std::min(elem->point(2), elem->point(7))) 00439 { 00440 // Case 1 00441 xi = xi_saved; 00442 zeta = zeta_saved; 00443 } 00444 else 00445 { 00446 // Case 2 00447 xi = zeta_saved; 00448 zeta = xi_saved; 00449 } 00450 00451 else if (elem->point(7) == min_point) 00452 if (elem->point(3) == std::min(elem->point(3), elem->point(6))) 00453 { 00454 // Case 3 00455 xi = -zeta_saved; 00456 zeta = xi_saved; 00457 } 00458 else 00459 { 00460 // Case 4 00461 xi = xi_saved; 00462 zeta = -zeta_saved; 00463 } 00464 00465 else if (elem->point(6) == min_point) 00466 if (elem->point(7) == std::min(elem->point(7), elem->point(2))) 00467 { 00468 // Case 5 00469 xi = -xi_saved; 00470 zeta = -zeta_saved; 00471 } 00472 else 00473 { 00474 // Case 6 00475 xi = -zeta_saved; 00476 zeta = -xi_saved; 00477 } 00478 00479 else if (elem->point(2) == min_point) 00480 { 00481 if (elem->point(6) == std::min(elem->point(3), elem->point(6))) 00482 { 00483 // Case 7 00484 xi = zeta_saved; 00485 zeta = -xi_saved; 00486 } 00487 else 00488 { 00489 // Case 8 00490 xi = -xi_saved; 00491 zeta = zeta_saved; 00492 } 00493 } 00494 } 00495 // Face 4 00496 else if (i < 8 + 12*e + 5*e*e) 00497 { 00498 unsigned int basisnum = i - 8 - 12*e - 4*e*e; 00499 i0 = 0; 00500 i1 = square_number_row[basisnum] + 2; 00501 i2 = square_number_column[basisnum] + 2; 00502 const Point min_point = get_min_point(elem, 3, 0, 4, 7); 00503 00504 if (elem->point(0) == min_point) 00505 if (elem->point(3) == std::min(elem->point(3), elem->point(4))) 00506 { 00507 // Case 1 00508 eta = eta_saved; 00509 zeta = zeta_saved; 00510 } 00511 else 00512 { 00513 // Case 2 00514 eta = zeta_saved; 00515 zeta = eta_saved; 00516 } 00517 00518 else if (elem->point(4) == min_point) 00519 if (elem->point(0) == std::min(elem->point(0), elem->point(7))) 00520 { 00521 // Case 3 00522 eta = -zeta_saved; 00523 zeta = eta_saved; 00524 } 00525 else 00526 { 00527 // Case 4 00528 eta = eta_saved; 00529 zeta = -zeta_saved; 00530 } 00531 00532 else if (elem->point(7) == min_point) 00533 if (elem->point(4) == std::min(elem->point(4), elem->point(3))) 00534 { 00535 // Case 5 00536 eta = -eta_saved; 00537 zeta = -zeta_saved; 00538 } 00539 else 00540 { 00541 // Case 6 00542 eta = -zeta_saved; 00543 zeta = -eta_saved; 00544 } 00545 00546 else if (elem->point(3) == min_point) 00547 { 00548 if (elem->point(7) == std::min(elem->point(7), elem->point(0))) 00549 { 00550 // Case 7 00551 eta = zeta_saved; 00552 zeta = -eta_saved; 00553 } 00554 else 00555 { 00556 // Case 8 00557 eta = -eta_saved; 00558 zeta = zeta_saved; 00559 } 00560 } 00561 } 00562 // Face 5 00563 else if (i < 8 + 12*e + 6*e*e) 00564 { 00565 unsigned int basisnum = i - 8 - 12*e - 5*e*e; 00566 i0 = square_number_row[basisnum] + 2; 00567 i1 = square_number_column[basisnum] + 2; 00568 i2 = 1; 00569 const Point min_point = get_min_point(elem, 4, 5, 6, 7); 00570 00571 if (elem->point(4) == min_point) 00572 if (elem->point(5) == std::min(elem->point(5), elem->point(7))) 00573 { 00574 // Case 1 00575 xi = xi_saved; 00576 eta = eta_saved; 00577 } 00578 else 00579 { 00580 // Case 2 00581 xi = eta_saved; 00582 eta = xi_saved; 00583 } 00584 00585 else if (elem->point(5) == min_point) 00586 if (elem->point(6) == std::min(elem->point(6), elem->point(4))) 00587 { 00588 // Case 3 00589 xi = eta_saved; 00590 eta = -xi_saved; 00591 } 00592 else 00593 { 00594 // Case 4 00595 xi = -xi_saved; 00596 eta = eta_saved; 00597 } 00598 00599 else if (elem->point(6) == min_point) 00600 if (elem->point(7) == std::min(elem->point(7), elem->point(5))) 00601 { 00602 // Case 5 00603 xi = -xi_saved; 00604 eta = -eta_saved; 00605 } 00606 else 00607 { 00608 // Case 6 00609 xi = -eta_saved; 00610 eta = -xi_saved; 00611 } 00612 00613 else if (elem->point(7) == min_point) 00614 { 00615 if (elem->point(4) == std::min(elem->point(4), elem->point(6))) 00616 { 00617 // Case 7 00618 xi = -eta_saved; 00619 eta = xi_saved; 00620 } 00621 else 00622 { 00623 // Case 8 00624 xi = xi_saved; 00625 eta = eta_saved; 00626 } 00627 } 00628 } 00629 00630 // Internal DoFs 00631 else 00632 { 00633 unsigned int basisnum = i - 8 - 12*e - 6*e*e; 00634 i0 = cube_number_column[basisnum] + 2; 00635 i1 = cube_number_row[basisnum] + 2; 00636 i2 = cube_number_page[basisnum] + 2; 00637 } 00638 } 00639 } // end anonymous namespace 00640 00641 00642 00643 00644 template <> 00645 Real FE<3,HIERARCHIC>::shape(const ElemType, 00646 const Order, 00647 const unsigned int, 00648 const Point&) 00649 { 00650 libmesh_error_msg("Hierarchic polynomials require the element type \nbecause edge and face orientation is needed."); 00651 return 0.; 00652 } 00653 00654 00655 00656 template <> 00657 Real FE<3,HIERARCHIC>::shape(const Elem* elem, 00658 const Order order, 00659 const unsigned int i, 00660 const Point& p) 00661 { 00662 #if LIBMESH_DIM == 3 00663 00664 libmesh_assert(elem); 00665 const ElemType type = elem->type(); 00666 00667 const Order totalorder = static_cast<Order>(order+elem->p_level()); 00668 00669 switch (type) 00670 { 00671 case HEX8: 00672 case HEX20: 00673 libmesh_assert_less (totalorder, 2); 00674 case HEX27: 00675 { 00676 libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u)*(totalorder+1u)); 00677 00678 // Compute hex shape functions as a tensor-product 00679 Real xi = p(0); 00680 Real eta = p(1); 00681 Real zeta = p(2); 00682 00683 unsigned int i0, i1, i2; 00684 00685 cube_indices(elem, totalorder, i, xi, eta, zeta, i0, i1, i2); 00686 00687 return (FE<1,HIERARCHIC>::shape(EDGE3, totalorder, i0, xi)* 00688 FE<1,HIERARCHIC>::shape(EDGE3, totalorder, i1, eta)* 00689 FE<1,HIERARCHIC>::shape(EDGE3, totalorder, i2, zeta)); 00690 } 00691 00692 default: 00693 libmesh_error_msg("Invalid element type = " << type); 00694 } 00695 00696 #endif 00697 00698 libmesh_error_msg("We'll never get here!"); 00699 return 0.; 00700 } 00701 00702 00703 00704 00705 template <> 00706 Real FE<3,HIERARCHIC>::shape_deriv(const ElemType, 00707 const Order, 00708 const unsigned int, 00709 const unsigned int, 00710 const Point& ) 00711 { 00712 libmesh_error_msg("Hierarchic polynomials require the element type \nbecause edge and face orientation is needed."); 00713 return 0.; 00714 } 00715 00716 00717 00718 template <> 00719 Real FE<3,HIERARCHIC>::shape_deriv(const Elem* elem, 00720 const Order order, 00721 const unsigned int i, 00722 const unsigned int j, 00723 const Point& p) 00724 { 00725 #if LIBMESH_DIM == 3 00726 libmesh_assert(elem); 00727 00728 libmesh_assert_less (j, 3); 00729 00730 // cheat by using finite difference approximations: 00731 const Real eps = 1.e-6; 00732 Point pp, pm; 00733 00734 switch (j) 00735 { 00736 // d()/dxi 00737 case 0: 00738 { 00739 pp = Point(p(0)+eps, p(1), p(2)); 00740 pm = Point(p(0)-eps, p(1), p(2)); 00741 break; 00742 } 00743 00744 // d()/deta 00745 case 1: 00746 { 00747 pp = Point(p(0), p(1)+eps, p(2)); 00748 pm = Point(p(0), p(1)-eps, p(2)); 00749 break; 00750 } 00751 00752 // d()/dzeta 00753 case 2: 00754 { 00755 pp = Point(p(0), p(1), p(2)+eps); 00756 pm = Point(p(0), p(1), p(2)-eps); 00757 break; 00758 } 00759 00760 default: 00761 libmesh_error_msg("Invalid derivative index j = " << j); 00762 } 00763 00764 return (FE<3,HIERARCHIC>::shape(elem, order, i, pp) - 00765 FE<3,HIERARCHIC>::shape(elem, order, i, pm))/2./eps; 00766 #endif 00767 00768 libmesh_error_msg("We'll never get here!"); 00769 return 0.; 00770 } 00771 00772 00773 00774 template <> 00775 Real FE<3,HIERARCHIC>::shape_second_deriv(const ElemType, 00776 const Order, 00777 const unsigned int, 00778 const unsigned int, 00779 const Point& ) 00780 { 00781 libmesh_error_msg("Hierarchic polynomials require the element type \nbecause edge and face orientation is needed."); 00782 return 0.; 00783 } 00784 00785 00786 00787 template <> 00788 Real FE<3,HIERARCHIC>::shape_second_deriv(const Elem* elem, 00789 const Order order, 00790 const unsigned int i, 00791 const unsigned int j, 00792 const Point& p) 00793 { 00794 libmesh_assert(elem); 00795 00796 const Real eps = 1.e-6; 00797 Point pp, pm; 00798 unsigned int prevj = libMesh::invalid_uint; 00799 00800 switch (j) 00801 { 00802 // d^2()/dxi^2 00803 case 0: 00804 { 00805 pp = Point(p(0)+eps, p(1), p(2)); 00806 pm = Point(p(0)-eps, p(1), p(2)); 00807 prevj = 0; 00808 break; 00809 } 00810 00811 // d^2()/dxideta 00812 case 1: 00813 { 00814 pp = Point(p(0), p(1)+eps, p(2)); 00815 pm = Point(p(0), p(1)-eps, p(2)); 00816 prevj = 0; 00817 break; 00818 } 00819 00820 // d^2()/deta^2 00821 case 2: 00822 { 00823 pp = Point(p(0), p(1)+eps, p(2)); 00824 pm = Point(p(0), p(1)-eps, p(2)); 00825 prevj = 1; 00826 break; 00827 } 00828 00829 // d^2()/dxidzeta 00830 case 3: 00831 { 00832 pp = Point(p(0), p(1), p(2)+eps); 00833 pm = Point(p(0), p(1), p(2)-eps); 00834 prevj = 0; 00835 break; 00836 } 00837 00838 // d^2()/detadzeta 00839 case 4: 00840 { 00841 pp = Point(p(0), p(1), p(2)+eps); 00842 pm = Point(p(0), p(1), p(2)-eps); 00843 prevj = 1; 00844 break; 00845 } 00846 00847 // d^2()/dzeta^2 00848 case 5: 00849 { 00850 pp = Point(p(0), p(1), p(2)+eps); 00851 pm = Point(p(0), p(1), p(2)-eps); 00852 prevj = 2; 00853 break; 00854 } 00855 default: 00856 libmesh_error_msg("Invalid derivative index j = " << j); 00857 } 00858 00859 return (FE<3,HIERARCHIC>::shape_deriv(elem, order, i, prevj, pp) - 00860 FE<3,HIERARCHIC>::shape_deriv(elem, order, i, prevj, pm)) 00861 / 2. / eps; 00862 } 00863 00864 } // namespace libMesh