$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 // C++ includes 00021 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC 00022 #include <cmath> // for std::sqrt 00023 00024 00025 // Local includes 00026 #include "libmesh/libmesh_common.h" 00027 #include "libmesh/fe.h" 00028 #include "libmesh/quadrature.h" 00029 #include "libmesh/elem.h" 00030 #include "libmesh/libmesh_logging.h" 00031 #include "libmesh/tensor_value.h" // May be necessary if destructors 00032 // get instantiated here 00033 00034 namespace libMesh 00035 { 00036 00037 //------------------------------------------------------- 00038 // Full specializations for useless methods in 0D, 1D 00039 #define REINIT_ERROR(_dim, _type, _func) \ 00040 template <> \ 00041 void FE<_dim,_type>::_func(const Elem*, \ 00042 const unsigned int, \ 00043 const Real, \ 00044 const std::vector<Point>* const, \ 00045 const std::vector<Real>* const) \ 00046 { \ 00047 libmesh_error_msg("ERROR: This method makes no sense for low-D elements!"); \ 00048 } 00049 00050 #define SIDEMAP_ERROR(_dim, _type, _func) \ 00051 template <> \ 00052 void FE<_dim,_type>::_func(const Elem*, \ 00053 const Elem*, \ 00054 const unsigned int, \ 00055 const std::vector<Point>&, \ 00056 std::vector<Point>&) \ 00057 { \ 00058 libmesh_error_msg("ERROR: This method makes no sense for low-D elements!"); \ 00059 } 00060 00061 #define FACE_EDGE_SHAPE_ERROR(_dim, _func) \ 00062 template <> \ 00063 void FEMap::_func<_dim>(const std::vector<Point>&, \ 00064 const Elem* ) \ 00065 { \ 00066 libmesh_error_msg("ERROR: This method makes no sense for low-D elements!"); \ 00067 } 00068 00069 00070 REINIT_ERROR(0, CLOUGH, reinit) 00071 REINIT_ERROR(0, CLOUGH, edge_reinit) 00072 SIDEMAP_ERROR(0, CLOUGH, side_map) 00073 REINIT_ERROR(0, HERMITE, reinit) 00074 REINIT_ERROR(0, HERMITE, edge_reinit) 00075 SIDEMAP_ERROR(0, HERMITE, side_map) 00076 REINIT_ERROR(0, HIERARCHIC, reinit) 00077 REINIT_ERROR(0, HIERARCHIC, edge_reinit) 00078 SIDEMAP_ERROR(0, HIERARCHIC, side_map) 00079 REINIT_ERROR(0, L2_HIERARCHIC, reinit) 00080 REINIT_ERROR(0, L2_HIERARCHIC, edge_reinit) 00081 SIDEMAP_ERROR(0, L2_HIERARCHIC, side_map) 00082 REINIT_ERROR(0, LAGRANGE, reinit) 00083 REINIT_ERROR(0, LAGRANGE, edge_reinit) 00084 SIDEMAP_ERROR(0, LAGRANGE, side_map) 00085 REINIT_ERROR(0, LAGRANGE_VEC, reinit) 00086 REINIT_ERROR(0, LAGRANGE_VEC, edge_reinit) 00087 SIDEMAP_ERROR(0, LAGRANGE_VEC, side_map) 00088 REINIT_ERROR(0, L2_LAGRANGE, reinit) 00089 REINIT_ERROR(0, L2_LAGRANGE, edge_reinit) 00090 SIDEMAP_ERROR(0, L2_LAGRANGE, side_map) 00091 REINIT_ERROR(0, MONOMIAL, reinit) 00092 REINIT_ERROR(0, MONOMIAL, edge_reinit) 00093 SIDEMAP_ERROR(0, MONOMIAL, side_map) 00094 REINIT_ERROR(0, SCALAR, reinit) 00095 REINIT_ERROR(0, SCALAR, edge_reinit) 00096 SIDEMAP_ERROR(0, SCALAR, side_map) 00097 REINIT_ERROR(0, XYZ, reinit) 00098 REINIT_ERROR(0, XYZ, edge_reinit) 00099 SIDEMAP_ERROR(0, XYZ, side_map) 00100 REINIT_ERROR(0, NEDELEC_ONE, reinit) 00101 REINIT_ERROR(0, NEDELEC_ONE, edge_reinit) 00102 SIDEMAP_ERROR(0, NEDELEC_ONE, side_map) 00103 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 00104 REINIT_ERROR(0, BERNSTEIN, reinit) 00105 REINIT_ERROR(0, BERNSTEIN, edge_reinit) 00106 SIDEMAP_ERROR(0, BERNSTEIN, side_map) 00107 REINIT_ERROR(0, SZABAB, reinit) 00108 REINIT_ERROR(0, SZABAB, edge_reinit) 00109 SIDEMAP_ERROR(0, SZABAB, side_map) 00110 #endif 00111 00112 REINIT_ERROR(1, CLOUGH, edge_reinit) 00113 REINIT_ERROR(1, HERMITE, edge_reinit) 00114 REINIT_ERROR(1, HIERARCHIC, edge_reinit) 00115 REINIT_ERROR(1, L2_HIERARCHIC, edge_reinit) 00116 REINIT_ERROR(1, LAGRANGE, edge_reinit) 00117 REINIT_ERROR(1, LAGRANGE_VEC, edge_reinit) 00118 REINIT_ERROR(1, L2_LAGRANGE, edge_reinit) 00119 REINIT_ERROR(1, XYZ, edge_reinit) 00120 REINIT_ERROR(1, MONOMIAL, edge_reinit) 00121 REINIT_ERROR(1, SCALAR, edge_reinit) 00122 REINIT_ERROR(1, NEDELEC_ONE, reinit) 00123 REINIT_ERROR(1, NEDELEC_ONE, edge_reinit) 00124 SIDEMAP_ERROR(1, NEDELEC_ONE, side_map) 00125 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 00126 REINIT_ERROR(1, BERNSTEIN, edge_reinit) 00127 REINIT_ERROR(1, SZABAB, edge_reinit) 00128 #endif 00129 00130 00131 //------------------------------------------------------- 00132 // Methods for 2D, 3D 00133 template <unsigned int Dim, FEFamily T> 00134 void FE<Dim,T>::reinit(const Elem* elem, 00135 const unsigned int s, 00136 const Real /* tolerance */, 00137 const std::vector<Point>* const pts, 00138 const std::vector<Real>* const weights) 00139 { 00140 libmesh_assert(elem); 00141 libmesh_assert (this->qrule != NULL || pts != NULL); 00142 // We now do this for 1D elements! 00143 // libmesh_assert_not_equal_to (Dim, 1); 00144 00145 // Build the side of interest 00146 const UniquePtr<Elem> side(elem->build_side(s)); 00147 00148 // Find the max p_level to select 00149 // the right quadrature rule for side integration 00150 unsigned int side_p_level = elem->p_level(); 00151 if (elem->neighbor(s) != NULL) 00152 side_p_level = std::max(side_p_level, elem->neighbor(s)->p_level()); 00153 00154 // Initialize the shape functions at the user-specified 00155 // points 00156 if (pts != NULL) 00157 { 00158 // The shape functions do not correspond to the qrule 00159 this->shapes_on_quadrature = false; 00160 00161 // Initialize the face shape functions 00162 this->_fe_map->template init_face_shape_functions<Dim>(*pts, side.get()); 00163 00164 // Compute the Jacobian*Weight on the face for integration 00165 if (weights != NULL) 00166 { 00167 this->_fe_map->compute_face_map (Dim, *weights, side.get()); 00168 } 00169 else 00170 { 00171 std::vector<Real> dummy_weights (pts->size(), 1.); 00172 this->_fe_map->compute_face_map (Dim, dummy_weights, side.get()); 00173 } 00174 } 00175 // If there are no user specified points, we use the 00176 // quadrature rule 00177 else 00178 { 00179 // initialize quadrature rule 00180 this->qrule->init(side->type(), side_p_level); 00181 00182 if(this->qrule->shapes_need_reinit()) 00183 this->shapes_on_quadrature = false; 00184 00185 // FIXME - could this break if the same FE object was used 00186 // for both volume and face integrals? - RHS 00187 // We might not need to reinitialize the shape functions 00188 if ((this->get_type() != elem->type()) || 00189 (side->type() != last_side) || 00190 (this->get_p_level() != side_p_level) || 00191 this->shapes_need_reinit() || 00192 !this->shapes_on_quadrature) 00193 { 00194 // Set the element type and p_level 00195 this->elem_type = elem->type(); 00196 00197 // Set the last_side 00198 last_side = side->type(); 00199 00200 // Set the last p level 00201 this->_p_level = side_p_level; 00202 00203 // Initialize the face shape functions 00204 this->_fe_map->template init_face_shape_functions<Dim>(this->qrule->get_points(), side.get()); 00205 } 00206 00207 // Compute the Jacobian*Weight on the face for integration 00208 this->_fe_map->compute_face_map (Dim, this->qrule->get_weights(), side.get()); 00209 00210 // The shape functions correspond to the qrule 00211 this->shapes_on_quadrature = true; 00212 } 00213 00214 // make a copy of the Jacobian for integration 00215 const std::vector<Real> JxW_int(this->_fe_map->get_JxW()); 00216 00217 // make a copy of shape on quadrature info 00218 bool shapes_on_quadrature_side = this->shapes_on_quadrature; 00219 00220 // Find where the integration points are located on the 00221 // full element. 00222 const std::vector<Point>* ref_qp; 00223 if (pts != NULL) 00224 ref_qp = pts; 00225 else 00226 ref_qp = &this->qrule->get_points(); 00227 00228 std::vector<Point> qp; 00229 this->side_map(elem, side.get(), s, *ref_qp, qp); 00230 00231 // compute the shape function and derivative values 00232 // at the points qp 00233 this->reinit (elem, &qp); 00234 00235 this->shapes_on_quadrature = shapes_on_quadrature_side; 00236 00237 // copy back old data 00238 this->_fe_map->get_JxW() = JxW_int; 00239 } 00240 00241 00242 00243 template <unsigned int Dim, FEFamily T> 00244 void FE<Dim,T>::edge_reinit(const Elem* elem, 00245 const unsigned int e, 00246 const Real tolerance, 00247 const std::vector<Point>* const pts, 00248 const std::vector<Real>* const weights) 00249 { 00250 libmesh_assert(elem); 00251 libmesh_assert (this->qrule != NULL || pts != NULL); 00252 // We don't do this for 1D elements! 00253 libmesh_assert_not_equal_to (Dim, 1); 00254 00255 // Build the side of interest 00256 const UniquePtr<Elem> edge(elem->build_edge(e)); 00257 00258 // Initialize the shape functions at the user-specified 00259 // points 00260 if (pts != NULL) 00261 { 00262 // The shape functions do not correspond to the qrule 00263 this->shapes_on_quadrature = false; 00264 00265 // Initialize the edge shape functions 00266 this->_fe_map->template init_edge_shape_functions<Dim> (*pts, edge.get()); 00267 00268 // Compute the Jacobian*Weight on the face for integration 00269 if (weights != NULL) 00270 { 00271 this->_fe_map->compute_edge_map (Dim, *weights, edge.get()); 00272 } 00273 else 00274 { 00275 std::vector<Real> dummy_weights (pts->size(), 1.); 00276 this->_fe_map->compute_edge_map (Dim, dummy_weights, edge.get()); 00277 } 00278 } 00279 // If there are no user specified points, we use the 00280 // quadrature rule 00281 else 00282 { 00283 // initialize quadrature rule 00284 this->qrule->init(edge->type(), elem->p_level()); 00285 00286 if(this->qrule->shapes_need_reinit()) 00287 this->shapes_on_quadrature = false; 00288 00289 // We might not need to reinitialize the shape functions 00290 if ((this->get_type() != elem->type()) || 00291 (edge->type() != static_cast<int>(last_edge)) || // Comparison between enum and unsigned, cast the unsigned to int 00292 this->shapes_need_reinit() || 00293 !this->shapes_on_quadrature) 00294 { 00295 // Set the element type 00296 this->elem_type = elem->type(); 00297 00298 // Set the last_edge 00299 last_edge = edge->type(); 00300 00301 // Initialize the edge shape functions 00302 this->_fe_map->template init_edge_shape_functions<Dim> (this->qrule->get_points(), edge.get()); 00303 } 00304 00305 // Compute the Jacobian*Weight on the face for integration 00306 this->_fe_map->compute_edge_map (Dim, this->qrule->get_weights(), edge.get()); 00307 00308 // The shape functions correspond to the qrule 00309 this->shapes_on_quadrature = true; 00310 } 00311 00312 // make a copy of the Jacobian for integration 00313 const std::vector<Real> JxW_int(this->_fe_map->get_JxW()); 00314 00315 // Find where the integration points are located on the 00316 // full element. 00317 std::vector<Point> qp; 00318 this->inverse_map (elem, this->_fe_map->get_xyz(), qp, tolerance); 00319 00320 // compute the shape function and derivative values 00321 // at the points qp 00322 this->reinit (elem, &qp); 00323 00324 // copy back old data 00325 this->_fe_map->get_JxW() = JxW_int; 00326 } 00327 00328 template <unsigned int Dim, FEFamily T> 00329 void FE<Dim,T>::side_map (const Elem* elem, 00330 const Elem* side, 00331 const unsigned int s, 00332 const std::vector<Point>& reference_side_points, 00333 std::vector<Point>& reference_points) 00334 { 00335 unsigned int side_p_level = elem->p_level(); 00336 if (elem->neighbor(s) != NULL) 00337 side_p_level = std::max(side_p_level, elem->neighbor(s)->p_level()); 00338 00339 if (side->type() != last_side || 00340 side_p_level != this->_p_level || 00341 !this->shapes_on_quadrature) 00342 { 00343 // Set the element type 00344 this->elem_type = elem->type(); 00345 this->_p_level = side_p_level; 00346 00347 // Set the last_side 00348 last_side = side->type(); 00349 00350 // Initialize the face shape functions 00351 this->_fe_map->template init_face_shape_functions<Dim>(reference_side_points, side); 00352 } 00353 00354 const unsigned int n_points = 00355 cast_int<unsigned int>(reference_side_points.size()); 00356 reference_points.resize(n_points); 00357 for (unsigned int i = 0; i < n_points; i++) 00358 reference_points[i].zero(); 00359 00360 std::vector<unsigned int> elem_nodes_map; 00361 elem_nodes_map.resize(side->n_nodes()); 00362 for (unsigned int j = 0; j < side->n_nodes(); j++) 00363 for (unsigned int i = 0; i < elem->n_nodes(); i++) 00364 if (side->node(j) == elem->node(i)) 00365 elem_nodes_map[j] = i; 00366 std::vector<Point> refspace_nodes; 00367 this->get_refspace_nodes(elem->type(), refspace_nodes); 00368 00369 const std::vector<std::vector<Real> >& psi_map = this->_fe_map->get_psi(); 00370 00371 for (unsigned int i=0; i<psi_map.size(); i++) // sum over the nodes 00372 { 00373 const Point& side_node = refspace_nodes[elem_nodes_map[i]]; 00374 for (unsigned int p=0; p<n_points; p++) 00375 reference_points[p].add_scaled (side_node, psi_map[i][p]); 00376 } 00377 } 00378 00379 template<unsigned int Dim> 00380 void FEMap::init_face_shape_functions(const std::vector<Point>& qp, 00381 const Elem* side) 00382 { 00383 libmesh_assert(side); 00384 00388 START_LOG("init_face_shape_functions()", "FEMap"); 00389 00390 // The element type and order to use in 00391 // the map 00392 const Order mapping_order (side->default_order()); 00393 const ElemType mapping_elem_type (side->type()); 00394 00395 // The number of quadrature points. 00396 const unsigned int n_qp = cast_int<unsigned int>(qp.size()); 00397 00398 const unsigned int n_mapping_shape_functions = 00399 FE<Dim,LAGRANGE>::n_shape_functions (mapping_elem_type, 00400 mapping_order); 00401 00402 // resize the vectors to hold current data 00403 // Psi are the shape functions used for the FE mapping 00404 this->psi_map.resize (n_mapping_shape_functions); 00405 00406 if (Dim > 1) 00407 { 00408 this->dpsidxi_map.resize (n_mapping_shape_functions); 00409 this->d2psidxi2_map.resize (n_mapping_shape_functions); 00410 } 00411 00412 if (Dim == 3) 00413 { 00414 this->dpsideta_map.resize (n_mapping_shape_functions); 00415 this->d2psidxideta_map.resize (n_mapping_shape_functions); 00416 this->d2psideta2_map.resize (n_mapping_shape_functions); 00417 } 00418 00419 for (unsigned int i=0; i<n_mapping_shape_functions; i++) 00420 { 00421 // Allocate space to store the values of the shape functions 00422 // and their first and second derivatives at the quadrature points. 00423 this->psi_map[i].resize (n_qp); 00424 if (Dim > 1) 00425 { 00426 this->dpsidxi_map[i].resize (n_qp); 00427 this->d2psidxi2_map[i].resize (n_qp); 00428 } 00429 if (Dim == 3) 00430 { 00431 this->dpsideta_map[i].resize (n_qp); 00432 this->d2psidxideta_map[i].resize (n_qp); 00433 this->d2psideta2_map[i].resize (n_qp); 00434 } 00435 00436 // Compute the value of shape function i, and its first and 00437 // second derivatives at quadrature point p 00438 // (Lagrange shape functions are used for the mapping) 00439 for (unsigned int p=0; p<n_qp; p++) 00440 { 00441 this->psi_map[i][p] = FE<Dim-1,LAGRANGE>::shape (mapping_elem_type, mapping_order, i, qp[p]); 00442 if (Dim > 1) 00443 { 00444 this->dpsidxi_map[i][p] = FE<Dim-1,LAGRANGE>::shape_deriv (mapping_elem_type, mapping_order, i, 0, qp[p]); 00445 this->d2psidxi2_map[i][p] = FE<Dim-1,LAGRANGE>::shape_second_deriv(mapping_elem_type, mapping_order, i, 0, qp[p]); 00446 } 00447 // libMesh::out << "this->d2psidxi2_map["<<i<<"][p]=" << d2psidxi2_map[i][p] << std::endl; 00448 00449 // If we are in 3D, then our sides are 2D faces. 00450 // For the second derivatives, we must also compute the cross 00451 // derivative d^2() / dxi deta 00452 if (Dim == 3) 00453 { 00454 this->dpsideta_map[i][p] = FE<Dim-1,LAGRANGE>::shape_deriv (mapping_elem_type, mapping_order, i, 1, qp[p]); 00455 this->d2psidxideta_map[i][p] = FE<Dim-1,LAGRANGE>::shape_second_deriv(mapping_elem_type, mapping_order, i, 1, qp[p]); 00456 this->d2psideta2_map[i][p] = FE<Dim-1,LAGRANGE>::shape_second_deriv(mapping_elem_type, mapping_order, i, 2, qp[p]); 00457 } 00458 } 00459 } 00460 00461 00465 STOP_LOG("init_face_shape_functions()", "FEMap"); 00466 } 00467 00468 template<unsigned int Dim> 00469 void FEMap::init_edge_shape_functions(const std::vector<Point>& qp, 00470 const Elem* edge) 00471 { 00472 libmesh_assert(edge); 00473 00477 START_LOG("init_edge_shape_functions()", "FEMap"); 00478 00479 // The element type and order to use in 00480 // the map 00481 const Order mapping_order (edge->default_order()); 00482 const ElemType mapping_elem_type (edge->type()); 00483 00484 // The number of quadrature points. 00485 const unsigned int n_qp = cast_int<unsigned int>(qp.size()); 00486 00487 const unsigned int n_mapping_shape_functions = 00488 FE<Dim,LAGRANGE>::n_shape_functions (mapping_elem_type, 00489 mapping_order); 00490 00491 // resize the vectors to hold current data 00492 // Psi are the shape functions used for the FE mapping 00493 this->psi_map.resize (n_mapping_shape_functions); 00494 this->dpsidxi_map.resize (n_mapping_shape_functions); 00495 this->d2psidxi2_map.resize (n_mapping_shape_functions); 00496 00497 for (unsigned int i=0; i<n_mapping_shape_functions; i++) 00498 { 00499 // Allocate space to store the values of the shape functions 00500 // and their first and second derivatives at the quadrature points. 00501 this->psi_map[i].resize (n_qp); 00502 this->dpsidxi_map[i].resize (n_qp); 00503 this->d2psidxi2_map[i].resize (n_qp); 00504 00505 // Compute the value of shape function i, and its first and 00506 // second derivatives at quadrature point p 00507 // (Lagrange shape functions are used for the mapping) 00508 for (unsigned int p=0; p<n_qp; p++) 00509 { 00510 this->psi_map[i][p] = FE<1,LAGRANGE>::shape (mapping_elem_type, mapping_order, i, qp[p]); 00511 this->dpsidxi_map[i][p] = FE<1,LAGRANGE>::shape_deriv (mapping_elem_type, mapping_order, i, 0, qp[p]); 00512 this->d2psidxi2_map[i][p] = FE<1,LAGRANGE>::shape_second_deriv(mapping_elem_type, mapping_order, i, 0, qp[p]); 00513 } 00514 } 00515 00519 STOP_LOG("init_edge_shape_functions()", "FEMap"); 00520 } 00521 00522 00523 00524 void FEMap::compute_face_map(int dim, const std::vector<Real>& qw, 00525 const Elem* side) 00526 { 00527 libmesh_assert(side); 00528 00529 START_LOG("compute_face_map()", "FEMap"); 00530 00531 // The number of quadrature points. 00532 const unsigned int n_qp = cast_int<unsigned int>(qw.size()); 00533 00534 switch (dim) 00535 { 00536 case 1: 00537 { 00538 // A 1D finite element, currently assumed to be in 1D space 00539 // This means the boundary is a "0D finite element", a 00540 // NODEELEM. 00541 00542 // Resize the vectors to hold data at the quadrature points 00543 { 00544 this->xyz.resize(n_qp); 00545 normals.resize(n_qp); 00546 00547 this->JxW.resize(n_qp); 00548 } 00549 00550 // If we have no quadrature points, there's nothing else to do 00551 if (!n_qp) 00552 break; 00553 00554 // We need to look back at the full edge to figure out the normal 00555 // vector 00556 const Elem *elem = side->parent(); 00557 libmesh_assert (elem); 00558 if (side->node(0) == elem->node(0)) 00559 normals[0] = Point(-1.); 00560 else 00561 { 00562 libmesh_assert_equal_to (side->node(0), elem->node(1)); 00563 normals[0] = Point(1.); 00564 } 00565 00566 // Calculate x at the point 00567 libmesh_assert_equal_to (this->psi_map.size(), 1); 00568 // In the unlikely event we have multiple quadrature 00569 // points, they'll be in the same place 00570 for (unsigned int p=0; p<n_qp; p++) 00571 { 00572 this->xyz[p].zero(); 00573 this->xyz[p].add_scaled (side->point(0), this->psi_map[0][p]); 00574 normals[p] = normals[0]; 00575 this->JxW[p] = 1.0*qw[p]; 00576 } 00577 00578 // done computing the map 00579 break; 00580 } 00581 00582 case 2: 00583 { 00584 // A 2D finite element living in either 2D or 3D space. 00585 // This means the boundary is a 1D finite element, i.e. 00586 // and EDGE2 or EDGE3. 00587 // Resize the vectors to hold data at the quadrature points 00588 { 00589 this->xyz.resize(n_qp); 00590 this->dxyzdxi_map.resize(n_qp); 00591 this->d2xyzdxi2_map.resize(n_qp); 00592 this->tangents.resize(n_qp); 00593 this->normals.resize(n_qp); 00594 this->curvatures.resize(n_qp); 00595 00596 this->JxW.resize(n_qp); 00597 } 00598 00599 // Clear the entities that will be summed 00600 // Compute the tangent & normal at the quadrature point 00601 for (unsigned int p=0; p<n_qp; p++) 00602 { 00603 this->tangents[p].resize(LIBMESH_DIM-1); // 1 Tangent in 2D, 2 in 3D 00604 this->xyz[p].zero(); 00605 this->dxyzdxi_map[p].zero(); 00606 this->d2xyzdxi2_map[p].zero(); 00607 } 00608 00609 // compute x, dxdxi at the quadrature points 00610 for (unsigned int i=0; i<this->psi_map.size(); i++) // sum over the nodes 00611 { 00612 const Point& side_point = side->point(i); 00613 00614 for (unsigned int p=0; p<n_qp; p++) // for each quadrature point... 00615 { 00616 this->xyz[p].add_scaled (side_point, this->psi_map[i][p]); 00617 this->dxyzdxi_map[p].add_scaled (side_point, this->dpsidxi_map[i][p]); 00618 this->d2xyzdxi2_map[p].add_scaled(side_point, this->d2psidxi2_map[i][p]); 00619 } 00620 } 00621 00622 // Compute the tangent & normal at the quadrature point 00623 for (unsigned int p=0; p<n_qp; p++) 00624 { 00625 // The first tangent comes from just the edge's Jacobian 00626 this->tangents[p][0] = this->dxyzdxi_map[p].unit(); 00627 00628 #if LIBMESH_DIM == 2 00629 // For a 2D element living in 2D, the normal is given directly 00630 // from the entries in the edge Jacobian. 00631 this->normals[p] = (Point(this->dxyzdxi_map[p](1), -this->dxyzdxi_map[p](0), 0.)).unit(); 00632 00633 #elif LIBMESH_DIM == 3 00634 // For a 2D element living in 3D, there is a second tangent. 00635 // For the second tangent, we need to refer to the full 00636 // element's (not just the edge's) Jacobian. 00637 const Elem *elem = side->parent(); 00638 libmesh_assert(elem); 00639 00640 // Inverse map xyz[p] to a reference point on the parent... 00641 Point reference_point = FE<2,LAGRANGE>::inverse_map(elem, this->xyz[p]); 00642 00643 // Get dxyz/dxi and dxyz/deta from the parent map. 00644 Point dx_dxi = FE<2,LAGRANGE>::map_xi (elem, reference_point); 00645 Point dx_deta = FE<2,LAGRANGE>::map_eta(elem, reference_point); 00646 00647 // The second tangent vector is formed by crossing these vectors. 00648 tangents[p][1] = dx_dxi.cross(dx_deta).unit(); 00649 00650 // Finally, the normal in this case is given by crossing these 00651 // two tangents. 00652 normals[p] = tangents[p][0].cross(tangents[p][1]).unit(); 00653 #endif 00654 00655 00656 // The curvature is computed via the familiar Frenet formula: 00657 // curvature = [d^2(x) / d (xi)^2] dot [normal] 00658 // For a reference, see: 00659 // F.S. Merritt, Mathematics Manual, 1962, McGraw-Hill, p. 310 00660 // 00661 // Note: The sign convention here is different from the 00662 // 3D case. Concave-upward curves (smiles) have a positive 00663 // curvature. Concave-downward curves (frowns) have a 00664 // negative curvature. Be sure to take that into account! 00665 const Real numerator = this->d2xyzdxi2_map[p] * this->normals[p]; 00666 const Real denominator = this->dxyzdxi_map[p].size_sq(); 00667 libmesh_assert_not_equal_to (denominator, 0); 00668 curvatures[p] = numerator / denominator; 00669 } 00670 00671 // compute the jacobian at the quadrature points 00672 for (unsigned int p=0; p<n_qp; p++) 00673 { 00674 const Real the_jac = this->dxyzdxi_map[p].size(); 00675 00676 libmesh_assert_greater (the_jac, 0.); 00677 00678 this->JxW[p] = the_jac*qw[p]; 00679 } 00680 00681 // done computing the map 00682 break; 00683 } 00684 00685 00686 00687 case 3: 00688 { 00689 // A 3D finite element living in 3D space. 00690 // Resize the vectors to hold data at the quadrature points 00691 { 00692 this->xyz.resize(n_qp); 00693 this->dxyzdxi_map.resize(n_qp); 00694 this->dxyzdeta_map.resize(n_qp); 00695 this->d2xyzdxi2_map.resize(n_qp); 00696 this->d2xyzdxideta_map.resize(n_qp); 00697 this->d2xyzdeta2_map.resize(n_qp); 00698 this->tangents.resize(n_qp); 00699 this->normals.resize(n_qp); 00700 this->curvatures.resize(n_qp); 00701 00702 this->JxW.resize(n_qp); 00703 } 00704 00705 // Clear the entities that will be summed 00706 for (unsigned int p=0; p<n_qp; p++) 00707 { 00708 this->tangents[p].resize(LIBMESH_DIM-1); // 1 Tangent in 2D, 2 in 3D 00709 this->xyz[p].zero(); 00710 this->dxyzdxi_map[p].zero(); 00711 this->dxyzdeta_map[p].zero(); 00712 this->d2xyzdxi2_map[p].zero(); 00713 this->d2xyzdxideta_map[p].zero(); 00714 this->d2xyzdeta2_map[p].zero(); 00715 } 00716 00717 // compute x, dxdxi at the quadrature points 00718 for (unsigned int i=0; i<this->psi_map.size(); i++) // sum over the nodes 00719 { 00720 const Point& side_point = side->point(i); 00721 00722 for (unsigned int p=0; p<n_qp; p++) // for each quadrature point... 00723 { 00724 this->xyz[p].add_scaled (side_point, this->psi_map[i][p]); 00725 this->dxyzdxi_map[p].add_scaled (side_point, this->dpsidxi_map[i][p]); 00726 this->dxyzdeta_map[p].add_scaled(side_point, this->dpsideta_map[i][p]); 00727 this->d2xyzdxi2_map[p].add_scaled (side_point, this->d2psidxi2_map[i][p]); 00728 this->d2xyzdxideta_map[p].add_scaled(side_point, this->d2psidxideta_map[i][p]); 00729 this->d2xyzdeta2_map[p].add_scaled (side_point, this->d2psideta2_map[i][p]); 00730 } 00731 } 00732 00733 // Compute the tangents, normal, and curvature at the quadrature point 00734 for (unsigned int p=0; p<n_qp; p++) 00735 { 00736 const Point n = this->dxyzdxi_map[p].cross(this->dxyzdeta_map[p]); 00737 this->normals[p] = n.unit(); 00738 this->tangents[p][0] = this->dxyzdxi_map[p].unit(); 00739 this->tangents[p][1] = n.cross(this->dxyzdxi_map[p]).unit(); 00740 00741 // Compute curvature using the typical nomenclature 00742 // of the first and second fundamental forms. 00743 // For reference, see: 00744 // 1) http://mathworld.wolfram.com/MeanCurvature.html 00745 // (note -- they are using inward normal) 00746 // 2) F.S. Merritt, Mathematics Manual, 1962, McGraw-Hill 00747 const Real L = -this->d2xyzdxi2_map[p] * this->normals[p]; 00748 const Real M = -this->d2xyzdxideta_map[p] * this->normals[p]; 00749 const Real N = -this->d2xyzdeta2_map[p] * this->normals[p]; 00750 const Real E = this->dxyzdxi_map[p].size_sq(); 00751 const Real F = this->dxyzdxi_map[p] * this->dxyzdeta_map[p]; 00752 const Real G = this->dxyzdeta_map[p].size_sq(); 00753 00754 const Real numerator = E*N -2.*F*M + G*L; 00755 const Real denominator = E*G - F*F; 00756 libmesh_assert_not_equal_to (denominator, 0.); 00757 curvatures[p] = 0.5*numerator/denominator; 00758 } 00759 00760 // compute the jacobian at the quadrature points, see 00761 // http://sp81.msi.umn.edu:999/fluent/fidap/help/theory/thtoc.htm 00762 for (unsigned int p=0; p<n_qp; p++) 00763 { 00764 const Real g11 = (dxdxi_map(p)*dxdxi_map(p) + 00765 dydxi_map(p)*dydxi_map(p) + 00766 dzdxi_map(p)*dzdxi_map(p)); 00767 00768 const Real g12 = (dxdxi_map(p)*dxdeta_map(p) + 00769 dydxi_map(p)*dydeta_map(p) + 00770 dzdxi_map(p)*dzdeta_map(p)); 00771 00772 const Real g21 = g12; 00773 00774 const Real g22 = (dxdeta_map(p)*dxdeta_map(p) + 00775 dydeta_map(p)*dydeta_map(p) + 00776 dzdeta_map(p)*dzdeta_map(p)); 00777 00778 00779 const Real the_jac = std::sqrt(g11*g22 - g12*g21); 00780 00781 libmesh_assert_greater (the_jac, 0.); 00782 00783 this->JxW[p] = the_jac*qw[p]; 00784 } 00785 00786 // done computing the map 00787 break; 00788 } 00789 00790 00791 default: 00792 libmesh_error_msg("Invalid dimension dim = " << dim); 00793 } 00794 STOP_LOG("compute_face_map()", "FEMap"); 00795 } 00796 00797 00798 00799 00800 void FEMap::compute_edge_map(int dim, 00801 const std::vector<Real>& qw, 00802 const Elem* edge) 00803 { 00804 libmesh_assert(edge); 00805 00806 if (dim == 2) 00807 { 00808 // A 2D finite element living in either 2D or 3D space. 00809 // The edges here are the sides of the element, so the 00810 // (misnamed) compute_face_map function does what we want 00811 this->compute_face_map(dim, qw, edge); 00812 return; 00813 } 00814 00815 libmesh_assert_equal_to (dim, 3); // 1D is unnecessary and currently unsupported 00816 00817 START_LOG("compute_edge_map()", "FEMap"); 00818 00819 // The number of quadrature points. 00820 const unsigned int n_qp = cast_int<unsigned int>(qw.size()); 00821 00822 // Resize the vectors to hold data at the quadrature points 00823 this->xyz.resize(n_qp); 00824 this->dxyzdxi_map.resize(n_qp); 00825 this->dxyzdeta_map.resize(n_qp); 00826 this->d2xyzdxi2_map.resize(n_qp); 00827 this->d2xyzdxideta_map.resize(n_qp); 00828 this->d2xyzdeta2_map.resize(n_qp); 00829 this->tangents.resize(n_qp); 00830 this->normals.resize(n_qp); 00831 this->curvatures.resize(n_qp); 00832 00833 this->JxW.resize(n_qp); 00834 00835 // Clear the entities that will be summed 00836 for (unsigned int p=0; p<n_qp; p++) 00837 { 00838 this->tangents[p].resize(1); 00839 this->xyz[p].zero(); 00840 this->dxyzdxi_map[p].zero(); 00841 this->dxyzdeta_map[p].zero(); 00842 this->d2xyzdxi2_map[p].zero(); 00843 this->d2xyzdxideta_map[p].zero(); 00844 this->d2xyzdeta2_map[p].zero(); 00845 } 00846 00847 // compute x, dxdxi at the quadrature points 00848 for (unsigned int i=0; i<this->psi_map.size(); i++) // sum over the nodes 00849 { 00850 const Point& edge_point = edge->point(i); 00851 00852 for (unsigned int p=0; p<n_qp; p++) // for each quadrature point... 00853 { 00854 this->xyz[p].add_scaled (edge_point, this->psi_map[i][p]); 00855 this->dxyzdxi_map[p].add_scaled (edge_point, this->dpsidxi_map[i][p]); 00856 this->d2xyzdxi2_map[p].add_scaled (edge_point, this->d2psidxi2_map[i][p]); 00857 } 00858 } 00859 00860 // Compute the tangents at the quadrature point 00861 // FIXME: normals (plural!) and curvatures are uncalculated 00862 for (unsigned int p=0; p<n_qp; p++) 00863 { 00864 const Point n = this->dxyzdxi_map[p].cross(this->dxyzdeta_map[p]); 00865 this->tangents[p][0] = this->dxyzdxi_map[p].unit(); 00866 00867 // compute the jacobian at the quadrature points 00868 const Real the_jac = std::sqrt(this->dxdxi_map(p)*this->dxdxi_map(p) + 00869 this->dydxi_map(p)*this->dydxi_map(p) + 00870 this->dzdxi_map(p)*this->dzdxi_map(p)); 00871 00872 libmesh_assert_greater (the_jac, 0.); 00873 00874 this->JxW[p] = the_jac*qw[p]; 00875 } 00876 00877 STOP_LOG("compute_edge_map()", "FEMap"); 00878 } 00879 00880 00881 // Explicit FEMap Instantiations 00882 FACE_EDGE_SHAPE_ERROR(0,init_face_shape_functions) 00883 template void FEMap::init_face_shape_functions<1>(const std::vector<Point>&,const Elem*); 00884 template void FEMap::init_face_shape_functions<2>(const std::vector<Point>&,const Elem*); 00885 template void FEMap::init_face_shape_functions<3>(const std::vector<Point>&,const Elem*); 00886 00887 FACE_EDGE_SHAPE_ERROR(0,init_edge_shape_functions) 00888 template void FEMap::init_edge_shape_functions<1>(const std::vector<Point>&, const Elem*); 00889 template void FEMap::init_edge_shape_functions<2>(const std::vector<Point>&, const Elem*); 00890 template void FEMap::init_edge_shape_functions<3>(const std::vector<Point>&, const Elem*); 00891 00892 //-------------------------------------------------------------- 00893 // Explicit FE instantiations 00894 template void FE<1,LAGRANGE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00895 template void FE<1,LAGRANGE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00896 template void FE<1,LAGRANGE_VEC>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00897 template void FE<1,LAGRANGE_VEC>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00898 template void FE<1,L2_LAGRANGE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00899 template void FE<1,L2_LAGRANGE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00900 template void FE<1,HIERARCHIC>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00901 template void FE<1,HIERARCHIC>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00902 template void FE<1,L2_HIERARCHIC>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00903 template void FE<1,L2_HIERARCHIC>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00904 template void FE<1,CLOUGH>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00905 template void FE<1,CLOUGH>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00906 template void FE<1,HERMITE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00907 template void FE<1,HERMITE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00908 template void FE<1,MONOMIAL>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00909 template void FE<1,MONOMIAL>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00910 template void FE<1,SCALAR>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00911 template void FE<1,SCALAR>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00912 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 00913 template void FE<1,BERNSTEIN>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00914 template void FE<1,BERNSTEIN>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00915 template void FE<1,SZABAB>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00916 template void FE<1,SZABAB>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00917 #endif 00918 template void FE<1,XYZ>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00919 template void FE<1,XYZ>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00920 00921 template void FE<2,LAGRANGE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00922 template void FE<2,LAGRANGE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00923 template void FE<2,LAGRANGE>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00924 template void FE<2,LAGRANGE_VEC>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00925 template void FE<2,LAGRANGE_VEC>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00926 template void FE<2,LAGRANGE_VEC>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00927 template void FE<2,L2_LAGRANGE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00928 template void FE<2,L2_LAGRANGE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00929 template void FE<2,L2_LAGRANGE>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00930 template void FE<2,HIERARCHIC>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00931 template void FE<2,HIERARCHIC>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00932 template void FE<2,HIERARCHIC>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00933 template void FE<2,L2_HIERARCHIC>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00934 template void FE<2,L2_HIERARCHIC>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00935 template void FE<2,L2_HIERARCHIC>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00936 template void FE<2,CLOUGH>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00937 template void FE<2,CLOUGH>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00938 template void FE<2,CLOUGH>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00939 template void FE<2,HERMITE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00940 template void FE<2,HERMITE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00941 template void FE<2,HERMITE>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00942 template void FE<2,MONOMIAL>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00943 template void FE<2,MONOMIAL>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00944 template void FE<2,MONOMIAL>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00945 template void FE<2,SCALAR>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00946 template void FE<2,SCALAR>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00947 template void FE<2,SCALAR>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00948 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 00949 template void FE<2,BERNSTEIN>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00950 template void FE<2,BERNSTEIN>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00951 template void FE<2,BERNSTEIN>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00952 template void FE<2,SZABAB>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00953 template void FE<2,SZABAB>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00954 template void FE<2,SZABAB>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00955 #endif 00956 template void FE<2,SUBDIVISION>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00957 template void FE<2,XYZ>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00958 template void FE<2,XYZ>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00959 template void FE<2,XYZ>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00960 template void FE<2,NEDELEC_ONE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00961 template void FE<2,NEDELEC_ONE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00962 template void FE<2,NEDELEC_ONE>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00963 00964 // Intel 9.1 complained it needed this in devel mode. 00965 //template void FE<2,XYZ>::init_face_shape_functions(const std::vector<Point>&, const Elem*); 00966 00967 template void FE<3,LAGRANGE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00968 template void FE<3,LAGRANGE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00969 template void FE<3,LAGRANGE>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00970 template void FE<3,LAGRANGE_VEC>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00971 template void FE<3,LAGRANGE_VEC>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00972 template void FE<3,LAGRANGE_VEC>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00973 template void FE<3,L2_LAGRANGE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00974 template void FE<3,L2_LAGRANGE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00975 template void FE<3,L2_LAGRANGE>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00976 template void FE<3,HIERARCHIC>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00977 template void FE<3,HIERARCHIC>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00978 template void FE<3,HIERARCHIC>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00979 template void FE<3,L2_HIERARCHIC>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00980 template void FE<3,L2_HIERARCHIC>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00981 template void FE<3,L2_HIERARCHIC>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00982 template void FE<3,CLOUGH>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00983 template void FE<3,CLOUGH>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00984 template void FE<3,CLOUGH>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00985 template void FE<3,HERMITE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00986 template void FE<3,HERMITE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00987 template void FE<3,HERMITE>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00988 template void FE<3,MONOMIAL>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00989 template void FE<3,MONOMIAL>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00990 template void FE<3,MONOMIAL>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00991 template void FE<3,SCALAR>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00992 template void FE<3,SCALAR>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00993 template void FE<3,SCALAR>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00994 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 00995 template void FE<3,BERNSTEIN>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00996 template void FE<3,BERNSTEIN>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 00997 template void FE<3,BERNSTEIN>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00998 template void FE<3,SZABAB>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 00999 template void FE<3,SZABAB>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 01000 template void FE<3,SZABAB>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 01001 #endif 01002 template void FE<3,XYZ>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 01003 template void FE<3,XYZ>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 01004 template void FE<3,XYZ>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 01005 template void FE<3,NEDELEC_ONE>::reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 01006 template void FE<3,NEDELEC_ONE>::side_map(Elem const*, Elem const*, const unsigned int, const std::vector<Point>&, std::vector<Point>&); 01007 template void FE<3,NEDELEC_ONE>::edge_reinit(Elem const*, unsigned int, Real, const std::vector<Point>* const, const std::vector<Real>* const); 01008 01009 // Intel 9.1 complained it needed this in devel mode. 01010 //template void FE<3,XYZ>::init_face_shape_functions(const std::vector<Point>&, const Elem*); 01011 01012 } // namespace libMesh