$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/fe_interface.h" 00022 #include "libmesh/elem.h" 00023 #include "libmesh/fe.h" 00024 #include "libmesh/fe_compute_data.h" 00025 #include "libmesh/dof_map.h" 00026 00027 namespace libMesh 00028 { 00029 00030 //------------------------------------------------------------ 00031 //FEInterface class members 00032 FEInterface::FEInterface() 00033 { 00034 libmesh_error_msg("ERROR: Do not define an object of this type."); 00035 } 00036 00037 00038 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 00039 #define fe_family_switch(dim, func_and_args, prefix, suffix) \ 00040 do { \ 00041 switch (fe_t.family) \ 00042 { \ 00043 case CLOUGH: \ 00044 prefix FE<dim,CLOUGH>::func_and_args suffix \ 00045 case HERMITE: \ 00046 prefix FE<dim,HERMITE>::func_and_args suffix \ 00047 case HIERARCHIC: \ 00048 prefix FE<dim,HIERARCHIC>::func_and_args suffix \ 00049 case L2_HIERARCHIC: \ 00050 prefix FE<dim,L2_HIERARCHIC>::func_and_args suffix \ 00051 case LAGRANGE: \ 00052 prefix FE<dim,LAGRANGE>::func_and_args suffix \ 00053 case L2_LAGRANGE: \ 00054 prefix FE<dim,L2_LAGRANGE>::func_and_args suffix \ 00055 case MONOMIAL: \ 00056 prefix FE<dim,MONOMIAL>::func_and_args suffix \ 00057 case SCALAR: \ 00058 prefix FE<dim,SCALAR>::func_and_args suffix \ 00059 case BERNSTEIN: \ 00060 prefix FE<dim,BERNSTEIN>::func_and_args suffix \ 00061 case SZABAB: \ 00062 prefix FE<dim,SZABAB>::func_and_args suffix \ 00063 case XYZ: \ 00064 prefix FEXYZ<dim>::func_and_args suffix \ 00065 case SUBDIVISION: \ 00066 libmesh_assert_equal_to (dim, 2); \ 00067 prefix FE<2,SUBDIVISION>::func_and_args suffix \ 00068 default: \ 00069 libmesh_error_msg("Unsupported family = " << fe_t.family); \ 00070 } \ 00071 } while (0) 00072 00073 #define fe_family_with_vec_switch(dim, func_and_args, prefix, suffix) \ 00074 do { \ 00075 switch (fe_t.family) \ 00076 { \ 00077 case CLOUGH: \ 00078 prefix FE<dim,CLOUGH>::func_and_args suffix \ 00079 case HERMITE: \ 00080 prefix FE<dim,HERMITE>::func_and_args suffix \ 00081 case HIERARCHIC: \ 00082 prefix FE<dim,HIERARCHIC>::func_and_args suffix \ 00083 case L2_HIERARCHIC: \ 00084 prefix FE<dim,L2_HIERARCHIC>::func_and_args suffix \ 00085 case LAGRANGE: \ 00086 prefix FE<dim,LAGRANGE>::func_and_args suffix \ 00087 case LAGRANGE_VEC: \ 00088 prefix FELagrangeVec<dim>::func_and_args suffix \ 00089 case L2_LAGRANGE: \ 00090 prefix FE<dim,L2_LAGRANGE>::func_and_args suffix \ 00091 case MONOMIAL: \ 00092 prefix FE<dim,MONOMIAL>::func_and_args suffix \ 00093 case SCALAR: \ 00094 prefix FE<dim,SCALAR>::func_and_args suffix \ 00095 case BERNSTEIN: \ 00096 prefix FE<dim,BERNSTEIN>::func_and_args suffix \ 00097 case SZABAB: \ 00098 prefix FE<dim,SZABAB>::func_and_args suffix \ 00099 case XYZ: \ 00100 prefix FEXYZ<dim>::func_and_args suffix \ 00101 case SUBDIVISION: \ 00102 libmesh_assert_equal_to (dim, 2); \ 00103 prefix FE<2,SUBDIVISION>::func_and_args suffix \ 00104 case NEDELEC_ONE: \ 00105 prefix FENedelecOne<dim>::func_and_args suffix \ 00106 default: \ 00107 libmesh_error_msg("Unsupported family = " << fe_t.family); \ 00108 } \ 00109 } while (0) 00110 00111 #define fe_scalar_vec_error_switch(dim, func_and_args, prefix, suffix) \ 00112 do { \ 00113 switch (fe_t.family) \ 00114 { \ 00115 case CLOUGH: \ 00116 prefix FE<dim,CLOUGH>::func_and_args suffix \ 00117 case HERMITE: \ 00118 prefix FE<dim,HERMITE>::func_and_args suffix \ 00119 case HIERARCHIC: \ 00120 prefix FE<dim,HIERARCHIC>::func_and_args suffix \ 00121 case L2_HIERARCHIC: \ 00122 prefix FE<dim,L2_HIERARCHIC>::func_and_args suffix \ 00123 case LAGRANGE: \ 00124 prefix FE<dim,LAGRANGE>::func_and_args suffix \ 00125 case L2_LAGRANGE: \ 00126 prefix FE<dim,L2_LAGRANGE>::func_and_args suffix \ 00127 case MONOMIAL: \ 00128 prefix FE<dim,MONOMIAL>::func_and_args suffix \ 00129 case SCALAR: \ 00130 prefix FE<dim,SCALAR>::func_and_args suffix \ 00131 case BERNSTEIN: \ 00132 prefix FE<dim,BERNSTEIN>::func_and_args suffix \ 00133 case SZABAB: \ 00134 prefix FE<dim,SZABAB>::func_and_args suffix \ 00135 case XYZ: \ 00136 prefix FEXYZ<dim>::func_and_args suffix \ 00137 case SUBDIVISION: \ 00138 libmesh_assert_equal_to (dim, 2); \ 00139 prefix FE<2,SUBDIVISION>::func_and_args suffix \ 00140 case LAGRANGE_VEC: \ 00141 case NEDELEC_ONE: \ 00142 libmesh_error_msg("Error: Can only request scalar valued elements for Real FEInterface::func_and_args"); \ 00143 default: \ 00144 libmesh_error_msg("Unsupported family = " << fe_t.family); \ 00145 } \ 00146 } while(0) 00147 00148 00149 #define fe_vector_scalar_error_switch(dim, func_and_args, prefix, suffix) \ 00150 do { \ 00151 switch (fe_t.family) \ 00152 { \ 00153 case LAGRANGE_VEC: \ 00154 prefix FELagrangeVec<dim>::func_and_args suffix \ 00155 case NEDELEC_ONE: \ 00156 prefix FENedelecOne<dim>::func_and_args suffix \ 00157 case HERMITE: \ 00158 case HIERARCHIC: \ 00159 case L2_HIERARCHIC: \ 00160 case LAGRANGE: \ 00161 case L2_LAGRANGE: \ 00162 case MONOMIAL: \ 00163 case SCALAR: \ 00164 case BERNSTEIN: \ 00165 case SZABAB: \ 00166 case XYZ: \ 00167 case SUBDIVISION: \ 00168 libmesh_error_msg("Error: Can only request vector valued elements for RealGradient FEInterface::shape"); \ 00169 default: \ 00170 libmesh_error_msg("Unsupported family = " << fe_t.family); \ 00171 } \ 00172 } while(0) 00173 00174 #else 00175 #define fe_family_switch(dim, func_and_args, prefix, suffix) \ 00176 do { \ 00177 switch (fe_t.family) \ 00178 { \ 00179 case CLOUGH: \ 00180 prefix FE<dim,CLOUGH>::func_and_args suffix \ 00181 case HERMITE: \ 00182 prefix FE<dim,HERMITE>::func_and_args suffix \ 00183 case HIERARCHIC: \ 00184 prefix FE<dim,HIERARCHIC>::func_and_args suffix \ 00185 case L2_HIERARCHIC: \ 00186 prefix FE<dim,L2_HIERARCHIC>::func_and_args suffix \ 00187 case LAGRANGE: \ 00188 prefix FE<dim,LAGRANGE>::func_and_args suffix \ 00189 case L2_LAGRANGE: \ 00190 prefix FE<dim,L2_LAGRANGE>::func_and_args suffix \ 00191 case MONOMIAL: \ 00192 prefix FE<dim,MONOMIAL>::func_and_args suffix \ 00193 case SCALAR: \ 00194 prefix FE<dim,SCALAR>::func_and_args suffix \ 00195 case XYZ: \ 00196 prefix FEXYZ<dim>::func_and_args suffix \ 00197 case SUBDIVISION: \ 00198 libmesh_assert_equal_to (dim, 2); \ 00199 prefix FE<2,SUBDIVISION>::func_and_args suffix \ 00200 default: \ 00201 libmesh_error_msg("Unsupported family = " << fe_t.family); \ 00202 } \ 00203 } while (0) 00204 00205 #define fe_family_with_vec_switch(dim, func_and_args, prefix, suffix) \ 00206 do { \ 00207 switch (fe_t.family) \ 00208 { \ 00209 case CLOUGH: \ 00210 prefix FE<dim,CLOUGH>::func_and_args suffix \ 00211 case HERMITE: \ 00212 prefix FE<dim,HERMITE>::func_and_args suffix \ 00213 case HIERARCHIC: \ 00214 prefix FE<dim,HIERARCHIC>::func_and_args suffix \ 00215 case L2_HIERARCHIC: \ 00216 prefix FE<dim,L2_HIERARCHIC>::func_and_args suffix \ 00217 case LAGRANGE: \ 00218 prefix FE<dim,LAGRANGE>::func_and_args suffix \ 00219 case LAGRANGE_VEC: \ 00220 prefix FELagrangeVec<dim>::func_and_args suffix \ 00221 case L2_LAGRANGE: \ 00222 prefix FE<dim,L2_LAGRANGE>::func_and_args suffix \ 00223 case MONOMIAL: \ 00224 prefix FE<dim,MONOMIAL>::func_and_args suffix \ 00225 case SCALAR: \ 00226 prefix FE<dim,SCALAR>::func_and_args suffix \ 00227 case XYZ: \ 00228 prefix FEXYZ<dim>::func_and_args suffix \ 00229 case SUBDIVISION: \ 00230 libmesh_assert_equal_to (dim, 2); \ 00231 prefix FE<2,SUBDIVISION>::func_and_args suffix \ 00232 case NEDELEC_ONE: \ 00233 prefix FENedelecOne<dim>::func_and_args suffix \ 00234 default: \ 00235 libmesh_error_msg("Unsupported family = " << fe_t.family); \ 00236 } \ 00237 } while (0) 00238 00239 #define fe_scalar_vec_error_switch(dim, func_and_args, prefix, suffix) \ 00240 do { \ 00241 switch (fe_t.family) \ 00242 { \ 00243 case CLOUGH: \ 00244 prefix FE<dim,CLOUGH>::func_and_args suffix \ 00245 case HERMITE: \ 00246 prefix FE<dim,HERMITE>::func_and_args suffix \ 00247 case HIERARCHIC: \ 00248 prefix FE<dim,HIERARCHIC>::func_and_args suffix \ 00249 case L2_HIERARCHIC: \ 00250 prefix FE<dim,L2_HIERARCHIC>::func_and_args suffix \ 00251 case LAGRANGE: \ 00252 prefix FE<dim,LAGRANGE>::func_and_args suffix \ 00253 case L2_LAGRANGE: \ 00254 prefix FE<dim,L2_LAGRANGE>::func_and_args suffix \ 00255 case MONOMIAL: \ 00256 prefix FE<dim,MONOMIAL>::func_and_args suffix \ 00257 case SCALAR: \ 00258 prefix FE<dim,SCALAR>::func_and_args suffix \ 00259 case XYZ: \ 00260 prefix FEXYZ<dim>::func_and_args suffix \ 00261 case SUBDIVISION: \ 00262 libmesh_assert_equal_to (dim, 2); \ 00263 prefix FE<2,SUBDIVISION>::func_and_args suffix \ 00264 case LAGRANGE_VEC: \ 00265 case NEDELEC_ONE: \ 00266 libmesh_error_msg("Error: Can only request scalar valued elements for Real FEInterface::func_and_args"); \ 00267 default: \ 00268 libmesh_error_msg("Unsupported family = " << fe_t.family); \ 00269 } \ 00270 } while(0) 00271 00272 00273 #define fe_vector_scalar_error_switch(dim, func_and_args, prefix, suffix) \ 00274 do { \ 00275 switch (fe_t.family) \ 00276 { \ 00277 case LAGRANGE_VEC: \ 00278 prefix FELagrangeVec<dim>::func_and_args suffix \ 00279 case NEDELEC_ONE: \ 00280 prefix FENedelecOne<dim>::func_and_args suffix \ 00281 case HERMITE: \ 00282 case HIERARCHIC: \ 00283 case L2_HIERARCHIC: \ 00284 case LAGRANGE: \ 00285 case L2_LAGRANGE: \ 00286 case MONOMIAL: \ 00287 case SCALAR: \ 00288 case XYZ: \ 00289 case SUBDIVISION: \ 00290 libmesh_error_msg("Error: Can only request vector valued elements for RealGradient FEInterface::func_and_args"); \ 00291 default: \ 00292 libmesh_error_msg("Unsupported family = " << fe_t.family); \ 00293 } \ 00294 } while(0) 00295 #endif 00296 00297 00298 #define fe_switch(func_and_args) \ 00299 do { \ 00300 switch (dim) \ 00301 { \ 00302 /* 0D */ \ 00303 case 0: \ 00304 fe_family_switch (0, func_and_args, return, ;); \ 00305 /* 1D */ \ 00306 case 1: \ 00307 fe_family_switch (1, func_and_args, return, ;); \ 00308 /* 2D */ \ 00309 case 2: \ 00310 fe_family_switch (2, func_and_args, return, ;); \ 00311 /* 3D */ \ 00312 case 3: \ 00313 fe_family_switch (3, func_and_args, return, ;); \ 00314 default: \ 00315 libmesh_error_msg("Invalid dim = " << dim); \ 00316 } \ 00317 } while (0) 00318 00319 #define fe_with_vec_switch(func_and_args) \ 00320 do { \ 00321 switch (dim) \ 00322 { \ 00323 /* 0D */ \ 00324 case 0: \ 00325 fe_family_with_vec_switch (0, func_and_args, return, ;); \ 00326 /* 1D */ \ 00327 case 1: \ 00328 fe_family_with_vec_switch (1, func_and_args, return, ;); \ 00329 /* 2D */ \ 00330 case 2: \ 00331 fe_family_with_vec_switch (2, func_and_args, return, ;); \ 00332 /* 3D */ \ 00333 case 3: \ 00334 fe_family_with_vec_switch (3, func_and_args, return, ;); \ 00335 default: \ 00336 libmesh_error_msg("Invalid dim = " << dim); \ 00337 } \ 00338 } while (0) 00339 00340 00341 #define void_fe_switch(func_and_args) \ 00342 do { \ 00343 switch (dim) \ 00344 { \ 00345 /* 0D */ \ 00346 case 0: \ 00347 fe_family_switch (0, func_and_args, ;, ; return;); \ 00348 /* 1D */ \ 00349 case 1: \ 00350 fe_family_switch (1, func_and_args, ;, ; return;); \ 00351 /* 2D */ \ 00352 case 2: \ 00353 fe_family_switch (2, func_and_args, ;, ; return;); \ 00354 /* 3D */ \ 00355 case 3: \ 00356 fe_family_switch (3, func_and_args, ;, ; return;); \ 00357 default: \ 00358 libmesh_error_msg("Invalid dim = " << dim); \ 00359 } \ 00360 } while (0) 00361 00362 #define void_fe_with_vec_switch(func_and_args) \ 00363 do { \ 00364 switch (dim) \ 00365 { \ 00366 /* 0D */ \ 00367 case 0: \ 00368 fe_family_with_vec_switch (0, func_and_args, ;, ; return;); \ 00369 /* 1D */ \ 00370 case 1: \ 00371 fe_family_with_vec_switch (1, func_and_args, ;, ; return;); \ 00372 /* 2D */ \ 00373 case 2: \ 00374 fe_family_with_vec_switch (2, func_and_args, ;, ; return;); \ 00375 /* 3D */ \ 00376 case 3: \ 00377 fe_family_with_vec_switch (3, func_and_args, ;, ; return;); \ 00378 default: \ 00379 libmesh_error_msg("Invalid dim = " << dim); \ 00380 } \ 00381 } while (0) 00382 00383 00384 00385 unsigned int FEInterface::n_shape_functions(const unsigned int dim, 00386 const FEType& fe_t, 00387 const ElemType t) 00388 { 00389 00390 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00391 /* 00392 * Since the FEType, stored in DofMap/(some System child), has to 00393 * be the _same_ for InfFE and FE, we have to catch calls 00394 * to infinite elements through the element type. 00395 */ 00396 00397 if ( is_InfFE_elem(t) ) 00398 return ifem_n_shape_functions(dim, fe_t, t); 00399 00400 #endif 00401 00402 const Order o = fe_t.order; 00403 00404 fe_with_vec_switch(n_shape_functions(t, o)); 00405 00406 libmesh_error_msg("We'll never get here!"); 00407 return 0; 00408 } 00409 00410 00411 00412 00413 00414 unsigned int FEInterface::n_dofs(const unsigned int dim, 00415 const FEType& fe_t, 00416 const ElemType t) 00417 { 00418 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00419 00420 if ( is_InfFE_elem(t) ) 00421 return ifem_n_dofs(dim, fe_t, t); 00422 00423 #endif 00424 00425 const Order o = fe_t.order; 00426 00427 fe_with_vec_switch(n_dofs(t, o)); 00428 00429 libmesh_error_msg("We'll never get here!"); 00430 return 0; 00431 } 00432 00433 00434 00435 00436 unsigned int FEInterface::n_dofs_at_node(const unsigned int dim, 00437 const FEType& fe_t, 00438 const ElemType t, 00439 const unsigned int n) 00440 { 00441 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00442 00443 if ( is_InfFE_elem(t) ) 00444 return ifem_n_dofs_at_node(dim, fe_t, t, n); 00445 00446 #endif 00447 00448 const Order o = fe_t.order; 00449 00450 fe_with_vec_switch(n_dofs_at_node(t, o, n)); 00451 00452 libmesh_error_msg("We'll never get here!"); 00453 return 0; 00454 } 00455 00456 00457 00458 00459 00460 unsigned int FEInterface::n_dofs_per_elem(const unsigned int dim, 00461 const FEType& fe_t, 00462 const ElemType t) 00463 { 00464 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00465 00466 if ( is_InfFE_elem(t) ) 00467 return ifem_n_dofs_per_elem(dim, fe_t, t); 00468 00469 #endif 00470 00471 const Order o = fe_t.order; 00472 00473 fe_with_vec_switch(n_dofs_per_elem(t, o)); 00474 00475 libmesh_error_msg("We'll never get here!"); 00476 return 0; 00477 } 00478 00479 00480 00481 00482 void FEInterface::dofs_on_side(const Elem* const elem, 00483 const unsigned int dim, 00484 const FEType& fe_t, 00485 unsigned int s, 00486 std::vector<unsigned int>& di) 00487 { 00488 const Order o = fe_t.order; 00489 00490 void_fe_with_vec_switch(dofs_on_side(elem, o, s, di)); 00491 00492 libmesh_error_msg("We'll never get here!"); 00493 } 00494 00495 00496 00497 void FEInterface::dofs_on_edge(const Elem* const elem, 00498 const unsigned int dim, 00499 const FEType& fe_t, 00500 unsigned int e, 00501 std::vector<unsigned int>& di) 00502 { 00503 const Order o = fe_t.order; 00504 00505 void_fe_with_vec_switch(dofs_on_edge(elem, o, e, di)); 00506 00507 libmesh_error_msg("We'll never get here!"); 00508 } 00509 00510 00511 00512 00513 void FEInterface::nodal_soln(const unsigned int dim, 00514 const FEType& fe_t, 00515 const Elem* elem, 00516 const std::vector<Number>& elem_soln, 00517 std::vector<Number>& nodal_soln) 00518 { 00519 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00520 00521 if ( is_InfFE_elem(elem->type()) ) 00522 { 00523 ifem_nodal_soln(dim, fe_t, elem, elem_soln, nodal_soln); 00524 return; 00525 } 00526 00527 #endif 00528 00529 const Order order = fe_t.order; 00530 00531 void_fe_with_vec_switch(nodal_soln(elem, order, elem_soln, nodal_soln)); 00532 } 00533 00534 00535 00536 00537 Point FEInterface::map(unsigned int dim, 00538 const FEType& fe_t, 00539 const Elem* elem, 00540 const Point& p) 00541 { 00542 fe_with_vec_switch(map(elem, p)); 00543 00544 libmesh_error_msg("We'll never get here!"); 00545 return Point(); 00546 } 00547 00548 00549 00550 00551 00552 Point FEInterface::inverse_map (const unsigned int dim, 00553 const FEType& fe_t, 00554 const Elem* elem, 00555 const Point& p, 00556 const Real tolerance, 00557 const bool secure) 00558 { 00559 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00560 00561 if ( is_InfFE_elem(elem->type()) ) 00562 return ifem_inverse_map(dim, fe_t, elem, p,tolerance, secure); 00563 00564 #endif 00565 00566 fe_with_vec_switch(inverse_map(elem, p, tolerance, secure)); 00567 00568 libmesh_error_msg("We'll never get here!"); 00569 return Point(); 00570 } 00571 00572 00573 00574 00575 void FEInterface::inverse_map (const unsigned int dim, 00576 const FEType& fe_t, 00577 const Elem* elem, 00578 const std::vector<Point>& physical_points, 00579 std::vector<Point>& reference_points, 00580 const Real tolerance, 00581 const bool secure) 00582 { 00583 const std::size_t n_pts = physical_points.size(); 00584 00585 // Resize the vector 00586 reference_points.resize(n_pts); 00587 00588 if (n_pts == 0) 00589 { 00590 libMesh::err << "WARNING: empty vector physical_points!" 00591 << std::endl; 00592 libmesh_here(); 00593 return; 00594 } 00595 00596 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00597 00598 if ( is_InfFE_elem(elem->type()) ) 00599 { 00600 ifem_inverse_map(dim, fe_t, elem, physical_points, reference_points, tolerance, secure); 00601 return; 00602 // libmesh_not_implemented(); 00603 } 00604 00605 #endif 00606 00607 void_fe_with_vec_switch(inverse_map(elem, physical_points, reference_points, tolerance, secure)); 00608 00609 libmesh_error_msg("We'll never get here!"); 00610 } 00611 00612 00613 00614 bool FEInterface::on_reference_element(const Point& p, 00615 const ElemType t, 00616 const Real eps) 00617 { 00618 return FEBase::on_reference_element(p,t,eps); 00619 } 00620 00621 00622 00623 00624 Real FEInterface::shape(const unsigned int dim, 00625 const FEType& fe_t, 00626 const ElemType t, 00627 const unsigned int i, 00628 const Point& p) 00629 { 00630 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00631 00632 if ( is_InfFE_elem(t) ) 00633 return ifem_shape(dim, fe_t, t, i, p); 00634 00635 #endif 00636 00637 const Order o = fe_t.order; 00638 00639 fe_switch(shape(t,o,i,p)); 00640 00641 libmesh_error_msg("We'll never get here!"); 00642 return 0.; 00643 } 00644 00645 Real FEInterface::shape(const unsigned int dim, 00646 const FEType& fe_t, 00647 const Elem* elem, 00648 const unsigned int i, 00649 const Point& p) 00650 { 00651 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00652 00653 if ( elem && is_InfFE_elem(elem->type()) ) 00654 return ifem_shape(dim, fe_t, elem, i, p); 00655 00656 #endif 00657 00658 const Order o = fe_t.order; 00659 00660 fe_switch(shape(elem,o,i,p)); 00661 00662 libmesh_error_msg("We'll never get here!"); 00663 return 0.; 00664 } 00665 00666 template<> 00667 void FEInterface::shape<Real>(const unsigned int dim, 00668 const FEType& fe_t, 00669 const ElemType t, 00670 const unsigned int i, 00671 const Point& p, 00672 Real& phi) 00673 { 00674 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00675 00676 if ( is_InfFE_elem(t) ) 00677 phi = ifem_shape(dim, fe_t, t, i, p); 00678 00679 #endif 00680 00681 const Order o = fe_t.order; 00682 00683 switch(dim) 00684 { 00685 case 0: 00686 fe_scalar_vec_error_switch(0, shape(t,o,i,p), phi = , ; break;); 00687 break; 00688 case 1: 00689 fe_scalar_vec_error_switch(1, shape(t,o,i,p), phi = , ; break;); 00690 break; 00691 case 2: 00692 fe_scalar_vec_error_switch(2, shape(t,o,i,p), phi = , ; break;); 00693 break; 00694 case 3: 00695 fe_scalar_vec_error_switch(3, shape(t,o,i,p), phi = , ; break;); 00696 break; 00697 default: 00698 libmesh_error_msg("Invalid dimension = " << dim); 00699 } 00700 00701 return; 00702 } 00703 00704 template<> 00705 void FEInterface::shape<Real>(const unsigned int dim, 00706 const FEType& fe_t, 00707 const Elem* elem, 00708 const unsigned int i, 00709 const Point& p, 00710 Real& phi) 00711 { 00712 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00713 00714 if ( elem && is_InfFE_elem(elem->type()) ) 00715 phi = ifem_shape(dim, fe_t, elem, i, p); 00716 00717 #endif 00718 00719 const Order o = fe_t.order; 00720 00721 switch(dim) 00722 { 00723 case 0: 00724 fe_scalar_vec_error_switch(0, shape(elem,o,i,p), phi = , ; break;); 00725 break; 00726 case 1: 00727 fe_scalar_vec_error_switch(1, shape(elem,o,i,p), phi = , ; break;); 00728 break; 00729 case 2: 00730 fe_scalar_vec_error_switch(2, shape(elem,o,i,p), phi = , ; break;); 00731 break; 00732 case 3: 00733 fe_scalar_vec_error_switch(3, shape(elem,o,i,p), phi = , ; break;); 00734 break; 00735 default: 00736 libmesh_error_msg("Invalid dimension = " << dim); 00737 } 00738 00739 return; 00740 } 00741 00742 template<> 00743 void FEInterface::shape<RealGradient>(const unsigned int dim, 00744 const FEType& fe_t, 00745 const ElemType t, 00746 const unsigned int i, 00747 const Point& p, 00748 RealGradient& phi) 00749 { 00750 const Order o = fe_t.order; 00751 00752 switch(dim) 00753 { 00754 case 0: 00755 fe_vector_scalar_error_switch(0, shape(t,o,i,p), phi = , ; break;); 00756 break; 00757 case 1: 00758 fe_vector_scalar_error_switch(1, shape(t,o,i,p), phi = , ; break;); 00759 break; 00760 case 2: 00761 fe_vector_scalar_error_switch(2, shape(t,o,i,p), phi = , ; break;); 00762 break; 00763 case 3: 00764 fe_vector_scalar_error_switch(3, shape(t,o,i,p), phi = , ; break;); 00765 break; 00766 default: 00767 libmesh_error_msg("Invalid dimension = " << dim); 00768 } 00769 00770 return; 00771 } 00772 00773 template<> 00774 void FEInterface::shape<RealGradient>(const unsigned int dim, 00775 const FEType& fe_t, 00776 const Elem* elem, 00777 const unsigned int i, 00778 const Point& p, 00779 RealGradient& phi) 00780 { 00781 const Order o = fe_t.order; 00782 00783 switch(dim) 00784 { 00785 case 0: 00786 fe_vector_scalar_error_switch(0, shape(elem,o,i,p), phi = , ; break;); 00787 break; 00788 case 1: 00789 fe_vector_scalar_error_switch(1, shape(elem,o,i,p), phi = , ; break;); 00790 break; 00791 case 2: 00792 fe_vector_scalar_error_switch(2, shape(elem,o,i,p), phi = , ; break;); 00793 break; 00794 case 3: 00795 fe_vector_scalar_error_switch(3, shape(elem,o,i,p), phi = , ; break;); 00796 break; 00797 default: 00798 libmesh_error_msg("Invalid dimension = " << dim); 00799 } 00800 00801 return; 00802 } 00803 00804 void FEInterface::compute_data(const unsigned int dim, 00805 const FEType& fe_t, 00806 const Elem* elem, 00807 FEComputeData& data) 00808 { 00809 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00810 00811 if ( elem && is_InfFE_elem(elem->type()) ) 00812 { 00813 data.init(); 00814 ifem_compute_data(dim, fe_t, elem, data); 00815 return; 00816 } 00817 00818 #endif 00819 00820 FEType p_refined = fe_t; 00821 p_refined.order = static_cast<Order>(p_refined.order + elem->p_level()); 00822 00823 const unsigned int n_dof = n_dofs (dim, p_refined, elem->type()); 00824 const Point& p = data.p; 00825 data.shape.resize(n_dof); 00826 00827 // set default values for all the output fields 00828 data.init(); 00829 00830 for (unsigned int n=0; n<n_dof; n++) 00831 data.shape[n] = shape(dim, p_refined, elem, n, p); 00832 00833 return; 00834 } 00835 00836 00837 00838 #ifdef LIBMESH_ENABLE_AMR 00839 00840 void FEInterface::compute_constraints (DofConstraints &constraints, 00841 DofMap &dof_map, 00842 const unsigned int variable_number, 00843 const Elem* elem) 00844 { 00845 libmesh_assert(elem); 00846 00847 const FEType& fe_t = dof_map.variable_type(variable_number); 00848 00849 switch (elem->dim()) 00850 { 00851 case 0: 00852 case 1: 00853 { 00854 // No constraints in 0D/1D. 00855 return; 00856 } 00857 00858 00859 case 2: 00860 { 00861 switch (fe_t.family) 00862 { 00863 case CLOUGH: 00864 FE<2,CLOUGH>::compute_constraints (constraints, 00865 dof_map, 00866 variable_number, 00867 elem); return; 00868 00869 case HERMITE: 00870 FE<2,HERMITE>::compute_constraints (constraints, 00871 dof_map, 00872 variable_number, 00873 elem); return; 00874 00875 case LAGRANGE: 00876 FE<2,LAGRANGE>::compute_constraints (constraints, 00877 dof_map, 00878 variable_number, 00879 elem); return; 00880 00881 case HIERARCHIC: 00882 FE<2,HIERARCHIC>::compute_constraints (constraints, 00883 dof_map, 00884 variable_number, 00885 elem); return; 00886 00887 case L2_HIERARCHIC: 00888 FE<2,L2_HIERARCHIC>::compute_constraints (constraints, 00889 dof_map, 00890 variable_number, 00891 elem); return; 00892 00893 case LAGRANGE_VEC: 00894 FE<2,LAGRANGE_VEC>::compute_constraints (constraints, 00895 dof_map, 00896 variable_number, 00897 elem); return; 00898 00899 00900 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 00901 case SZABAB: 00902 FE<2,SZABAB>::compute_constraints (constraints, 00903 dof_map, 00904 variable_number, 00905 elem); return; 00906 00907 case BERNSTEIN: 00908 FE<2,BERNSTEIN>::compute_constraints (constraints, 00909 dof_map, 00910 variable_number, 00911 elem); return; 00912 00913 #endif 00914 default: 00915 return; 00916 } 00917 } 00918 00919 00920 case 3: 00921 { 00922 switch (fe_t.family) 00923 { 00924 case HERMITE: 00925 FE<3,HERMITE>::compute_constraints (constraints, 00926 dof_map, 00927 variable_number, 00928 elem); return; 00929 00930 case LAGRANGE: 00931 FE<3,LAGRANGE>::compute_constraints (constraints, 00932 dof_map, 00933 variable_number, 00934 elem); return; 00935 00936 case HIERARCHIC: 00937 FE<3,HIERARCHIC>::compute_constraints (constraints, 00938 dof_map, 00939 variable_number, 00940 elem); return; 00941 00942 case L2_HIERARCHIC: 00943 FE<3,L2_HIERARCHIC>::compute_constraints (constraints, 00944 dof_map, 00945 variable_number, 00946 elem); return; 00947 00948 case LAGRANGE_VEC: 00949 FE<3,LAGRANGE_VEC>::compute_constraints (constraints, 00950 dof_map, 00951 variable_number, 00952 elem); return; 00953 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 00954 case SZABAB: 00955 FE<3,SZABAB>::compute_constraints (constraints, 00956 dof_map, 00957 variable_number, 00958 elem); return; 00959 00960 case BERNSTEIN: 00961 FE<3,BERNSTEIN>::compute_constraints (constraints, 00962 dof_map, 00963 variable_number, 00964 elem); return; 00965 00966 #endif 00967 default: 00968 return; 00969 } 00970 } 00971 00972 00973 default: 00974 libmesh_error_msg("Invalid dimension = " << elem->dim()); 00975 } 00976 } 00977 00978 #endif // #ifdef LIBMESH_ENABLE_AMR 00979 00980 00981 00982 #ifdef LIBMESH_ENABLE_PERIODIC 00983 00984 void FEInterface::compute_periodic_constraints (DofConstraints &constraints, 00985 DofMap &dof_map, 00986 const PeriodicBoundaries &boundaries, 00987 const MeshBase &mesh, 00988 const PointLocatorBase* point_locator, 00989 const unsigned int variable_number, 00990 const Elem* elem) 00991 { 00992 // No element-specific optimizations currently exist 00993 FEBase::compute_periodic_constraints (constraints, 00994 dof_map, 00995 boundaries, 00996 mesh, 00997 point_locator, 00998 variable_number, 00999 elem); 01000 } 01001 01002 #endif // #ifdef LIBMESH_ENABLE_PERIODIC 01003 01004 01005 01006 unsigned int FEInterface::max_order(const FEType& fe_t, 01007 const ElemType& el_t) 01008 { 01009 // Yeah, I know, infinity is much larger than 11, but our 01010 // solvers don't seem to like high degree polynomials, and our 01011 // quadrature rules and number_lookups tables 01012 // need to go up higher. 01013 const unsigned int unlimited = 11; 01014 01015 // If we used 0 as a default, then elements missing from this 01016 // table (e.g. infinite elements) would be considered broken. 01017 const unsigned int unknown = unlimited; 01018 01019 switch (fe_t.family) 01020 { 01021 case LAGRANGE: 01022 case L2_LAGRANGE: // TODO: L2_LAGRANGE can have higher "max_order" than LAGRANGE 01023 case LAGRANGE_VEC: 01024 switch (el_t) 01025 { 01026 case EDGE2: 01027 case EDGE3: 01028 case EDGE4: 01029 return 3; 01030 case TRI3: 01031 return 1; 01032 case TRI6: 01033 return 2; 01034 case QUAD4: 01035 return 1; 01036 case QUAD8: 01037 case QUAD9: 01038 return 2; 01039 case TET4: 01040 return 1; 01041 case TET10: 01042 return 2; 01043 case HEX8: 01044 return 1; 01045 case HEX20: 01046 case HEX27: 01047 return 2; 01048 case PRISM6: 01049 return 1; 01050 case PRISM15: 01051 case PRISM18: 01052 return 2; 01053 case PYRAMID5: 01054 return 1; 01055 case PYRAMID13: 01056 case PYRAMID14: 01057 return 2; 01058 default: 01059 return unknown; 01060 } 01061 break; 01062 case MONOMIAL: 01063 switch (el_t) 01064 { 01065 case EDGE2: 01066 case EDGE3: 01067 case EDGE4: 01068 case TRI3: 01069 case TRI6: 01070 case QUAD4: 01071 case QUAD8: 01072 case QUAD9: 01073 case TET4: 01074 case TET10: 01075 case HEX8: 01076 case HEX20: 01077 case HEX27: 01078 case PRISM6: 01079 case PRISM15: 01080 case PRISM18: 01081 case PYRAMID5: 01082 case PYRAMID13: 01083 case PYRAMID14: 01084 return unlimited; 01085 default: 01086 return unknown; 01087 } 01088 break; 01089 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 01090 case BERNSTEIN: 01091 switch (el_t) 01092 { 01093 case EDGE2: 01094 case EDGE3: 01095 case EDGE4: 01096 return unlimited; 01097 case TRI3: 01098 return 0; 01099 case TRI6: 01100 return 6; 01101 case QUAD4: 01102 return 0; 01103 case QUAD8: 01104 case QUAD9: 01105 return unlimited; 01106 case TET4: 01107 return 1; 01108 case TET10: 01109 return 2; 01110 case HEX8: 01111 return 0; 01112 case HEX20: 01113 return 2; 01114 case HEX27: 01115 return 4; 01116 case PRISM6: 01117 case PRISM15: 01118 case PRISM18: 01119 case PYRAMID5: 01120 case PYRAMID13: 01121 case PYRAMID14: 01122 return 0; 01123 default: 01124 return unknown; 01125 } 01126 break; 01127 case SZABAB: 01128 switch (el_t) 01129 { 01130 case EDGE2: 01131 case EDGE3: 01132 case EDGE4: 01133 return 7; 01134 case TRI3: 01135 return 0; 01136 case TRI6: 01137 return 7; 01138 case QUAD4: 01139 return 0; 01140 case QUAD8: 01141 case QUAD9: 01142 return 7; 01143 case TET4: 01144 case TET10: 01145 case HEX8: 01146 case HEX20: 01147 case HEX27: 01148 case PRISM6: 01149 case PRISM15: 01150 case PRISM18: 01151 case PYRAMID5: 01152 case PYRAMID13: 01153 case PYRAMID14: 01154 return 0; 01155 default: 01156 return unknown; 01157 } 01158 break; 01159 #endif 01160 case XYZ: 01161 switch (el_t) 01162 { 01163 case EDGE2: 01164 case EDGE3: 01165 case EDGE4: 01166 case TRI3: 01167 case TRI6: 01168 case QUAD4: 01169 case QUAD8: 01170 case QUAD9: 01171 case TET4: 01172 case TET10: 01173 case HEX8: 01174 case HEX20: 01175 case HEX27: 01176 case PRISM6: 01177 case PRISM15: 01178 case PRISM18: 01179 case PYRAMID5: 01180 case PYRAMID13: 01181 case PYRAMID14: 01182 return unlimited; 01183 default: 01184 return unknown; 01185 } 01186 break; 01187 case CLOUGH: 01188 switch (el_t) 01189 { 01190 case EDGE2: 01191 case EDGE3: 01192 return 3; 01193 case EDGE4: 01194 case TRI3: 01195 return 0; 01196 case TRI6: 01197 return 3; 01198 case QUAD4: 01199 case QUAD8: 01200 case QUAD9: 01201 case TET4: 01202 case TET10: 01203 case HEX8: 01204 case HEX20: 01205 case HEX27: 01206 case PRISM6: 01207 case PRISM15: 01208 case PRISM18: 01209 case PYRAMID5: 01210 case PYRAMID13: 01211 case PYRAMID14: 01212 return 0; 01213 default: 01214 return unknown; 01215 } 01216 break; 01217 case HERMITE: 01218 switch (el_t) 01219 { 01220 case EDGE2: 01221 case EDGE3: 01222 return unlimited; 01223 case EDGE4: 01224 case TRI3: 01225 case TRI6: 01226 return 0; 01227 case QUAD4: 01228 return 3; 01229 case QUAD8: 01230 case QUAD9: 01231 return unlimited; 01232 case TET4: 01233 case TET10: 01234 return 0; 01235 case HEX8: 01236 return 3; 01237 case HEX20: 01238 case HEX27: 01239 return unlimited; 01240 case PRISM6: 01241 case PRISM15: 01242 case PRISM18: 01243 case PYRAMID5: 01244 case PYRAMID13: 01245 case PYRAMID14: 01246 return 0; 01247 default: 01248 return unknown; 01249 } 01250 break; 01251 case HIERARCHIC: 01252 switch (el_t) 01253 { 01254 case EDGE2: 01255 case EDGE3: 01256 case EDGE4: 01257 return unlimited; 01258 case TRI3: 01259 return 1; 01260 case TRI6: 01261 return unlimited; 01262 case QUAD4: 01263 return 1; 01264 case QUAD8: 01265 case QUAD9: 01266 return unlimited; 01267 case TET4: 01268 case TET10: 01269 return 0; 01270 case HEX8: 01271 case HEX20: 01272 return 1; 01273 case HEX27: 01274 return unlimited; 01275 case PRISM6: 01276 case PRISM15: 01277 case PRISM18: 01278 case PYRAMID5: 01279 case PYRAMID13: 01280 case PYRAMID14: 01281 return 0; 01282 default: 01283 return unknown; 01284 } 01285 break; 01286 case L2_HIERARCHIC: 01287 switch (el_t) 01288 { 01289 case EDGE2: 01290 case EDGE3: 01291 case EDGE4: 01292 return unlimited; 01293 case TRI3: 01294 return 1; 01295 case TRI6: 01296 return unlimited; 01297 case QUAD4: 01298 return 1; 01299 case QUAD8: 01300 case QUAD9: 01301 return unlimited; 01302 case TET4: 01303 case TET10: 01304 return 0; 01305 case HEX8: 01306 case HEX20: 01307 return 1; 01308 case HEX27: 01309 return unlimited; 01310 case PRISM6: 01311 case PRISM15: 01312 case PRISM18: 01313 case PYRAMID5: 01314 case PYRAMID13: 01315 case PYRAMID14: 01316 return 0; 01317 default: 01318 return unknown; 01319 } 01320 break; 01321 case SUBDIVISION: 01322 switch (el_t) 01323 { 01324 case TRI3SUBDIVISION: 01325 return unlimited; 01326 default: 01327 return unknown; 01328 } 01329 break; 01330 case NEDELEC_ONE: 01331 switch (el_t) 01332 { 01333 case TRI6: 01334 case QUAD8: 01335 case QUAD9: 01336 case HEX20: 01337 case HEX27: 01338 return 1; 01339 default: 01340 return 0; 01341 } 01342 break; 01343 default: 01344 return 0; 01345 break; 01346 } 01347 } 01348 01349 01350 01351 bool FEInterface::extra_hanging_dofs(const FEType& fe_t) 01352 { 01353 switch (fe_t.family) 01354 { 01355 case LAGRANGE: 01356 case L2_LAGRANGE: 01357 case MONOMIAL: 01358 case L2_HIERARCHIC: 01359 case XYZ: 01360 case SUBDIVISION: 01361 case LAGRANGE_VEC: 01362 case NEDELEC_ONE: 01363 return false; 01364 case CLOUGH: 01365 case HERMITE: 01366 case HIERARCHIC: 01367 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 01368 case BERNSTEIN: 01369 case SZABAB: 01370 #endif 01371 default: 01372 return true; 01373 } 01374 } 01375 01376 FEFieldType FEInterface::field_type( const FEType& fe_type ) 01377 { 01378 return FEInterface::field_type( fe_type.family ); 01379 } 01380 01381 FEFieldType FEInterface::field_type( const FEFamily& fe_family ) 01382 { 01383 switch (fe_family) 01384 { 01385 case LAGRANGE_VEC: 01386 case NEDELEC_ONE: 01387 return TYPE_VECTOR; 01388 default: 01389 return TYPE_SCALAR; 01390 } 01391 } 01392 01393 unsigned int FEInterface::n_vec_dim( const MeshBase& mesh, const FEType& fe_type ) 01394 { 01395 switch (fe_type.family) 01396 { 01397 //FIXME: We currently assume that the number of vector components is tied 01398 // to the mesh dimension. This will break for mixed-dimension meshes. 01399 case LAGRANGE_VEC: 01400 case NEDELEC_ONE: 01401 return mesh.mesh_dimension(); 01402 default: 01403 return 1; 01404 } 01405 } 01406 01407 } // namespace libMesh