fem_context.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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 #include "libmesh/boundary_info.h" 00021 #include "libmesh/dof_map.h" 00022 #include "libmesh/elem.h" 00023 #include "libmesh/fe_base.h" 00024 #include "libmesh/fe_interface.h" 00025 #include "libmesh/fem_context.h" 00026 #include "libmesh/libmesh_logging.h" 00027 #include "libmesh/mesh_base.h" 00028 #include "libmesh/quadrature.h" 00029 #include "libmesh/system.h" 00030 #include "libmesh/time_solver.h" 00031 #include "libmesh/unsteady_solver.h" // For euler_residual 00032 00033 namespace libMesh 00034 { 00035 00036 FEMContext::FEMContext (const System &sys) 00037 : DiffContext(sys), 00038 element_qrule(NULL), side_qrule(NULL), 00039 edge_qrule(NULL), 00040 _mesh_sys(NULL), 00041 _mesh_x_var(0), 00042 _mesh_y_var(0), 00043 _mesh_z_var(0), 00044 elem(NULL), 00045 side(0), edge(0), dim(sys.get_mesh().mesh_dimension()), 00046 _boundary_info(sys.get_mesh().boundary_info.get()) 00047 { 00048 // We need to know which of our variables has the hardest 00049 // shape functions to numerically integrate. 00050 00051 unsigned int nv = sys.n_vars(); 00052 00053 libmesh_assert (nv); 00054 FEType hardest_fe_type = sys.variable_type(0); 00055 00056 for (unsigned int i=0; i != nv; ++i) 00057 { 00058 FEType fe_type = sys.variable_type(i); 00059 00060 // FIXME - we don't yet handle mixed finite elements from 00061 // different families which require different quadrature rules 00062 // libmesh_assert_equal_to (fe_type.family, hardest_fe_type.family); 00063 00064 if (fe_type.order > hardest_fe_type.order) 00065 hardest_fe_type = fe_type; 00066 } 00067 00068 // Create an adequate quadrature rule 00069 element_qrule = hardest_fe_type.default_quadrature_rule 00070 (dim, sys.extra_quadrature_order).release(); 00071 side_qrule = hardest_fe_type.default_quadrature_rule 00072 (dim-1, sys.extra_quadrature_order).release(); 00073 if (dim == 3) 00074 edge_qrule = hardest_fe_type.default_quadrature_rule 00075 (1, sys.extra_quadrature_order).release(); 00076 00077 // Next, create finite element objects 00078 // Preserving backward compatibility here for now 00079 // Should move to the protected/FEAbstract interface 00080 element_fe_var.resize(nv); 00081 side_fe_var.resize(nv); 00082 if (dim == 3) 00083 edge_fe_var.resize(nv); 00084 00085 _element_fe_var.resize(nv); 00086 _side_fe_var.resize(nv); 00087 if (dim == 3) 00088 _edge_fe_var.resize(nv); 00089 00090 for (unsigned int i=0; i != nv; ++i) 00091 { 00092 FEType fe_type = sys.variable_type(i); 00093 00094 // Preserving backward compatibility here for now 00095 // Should move to the protected/FEAbstract interface 00096 if( FEInterface::field_type( fe_type ) == TYPE_SCALAR ) 00097 { 00098 if( element_fe[fe_type] == NULL ) 00099 { 00100 element_fe[fe_type] = FEBase::build(dim, fe_type).release(); 00101 element_fe[fe_type]->attach_quadrature_rule(element_qrule); 00102 side_fe[fe_type] = FEBase::build(dim, fe_type).release(); 00103 side_fe[fe_type]->attach_quadrature_rule(side_qrule); 00104 00105 if (dim == 3) 00106 { 00107 edge_fe[fe_type] = FEBase::build(dim, fe_type).release(); 00108 edge_fe[fe_type]->attach_quadrature_rule(edge_qrule); 00109 } 00110 } 00111 element_fe_var[i] = element_fe[fe_type]; 00112 side_fe_var[i] = side_fe[fe_type]; 00113 if (dim == 3) 00114 edge_fe_var[i] = edge_fe[fe_type]; 00115 } 00116 00117 if ( _element_fe[fe_type] == NULL ) 00118 { 00119 _element_fe[fe_type] = FEAbstract::build(dim, fe_type).release(); 00120 _element_fe[fe_type]->attach_quadrature_rule(element_qrule); 00121 _side_fe[fe_type] = FEAbstract::build(dim, fe_type).release(); 00122 _side_fe[fe_type]->attach_quadrature_rule(side_qrule); 00123 00124 if (dim == 3) 00125 { 00126 _edge_fe[fe_type] = FEAbstract::build(dim, fe_type).release(); 00127 _edge_fe[fe_type]->attach_quadrature_rule(edge_qrule); 00128 } 00129 } 00130 _element_fe_var[i] = _element_fe[fe_type]; 00131 _side_fe_var[i] = _side_fe[fe_type]; 00132 if (dim == 3) 00133 _edge_fe_var[i] = _edge_fe[fe_type]; 00134 00135 } 00136 } 00137 00138 00139 FEMContext::~FEMContext() 00140 { 00141 // We don't want to store AutoPtrs in STL containers, but we don't 00142 // want to leak memory either 00143 // Preserving backward compatibility here for now 00144 // Should move to the protected/FEAbstract interface 00145 for (std::map<FEType, FEBase *>::iterator i = element_fe.begin(); 00146 i != element_fe.end(); ++i) 00147 delete i->second; 00148 element_fe.clear(); 00149 00150 for (std::map<FEType, FEBase *>::iterator i = side_fe.begin(); 00151 i != side_fe.end(); ++i) 00152 delete i->second; 00153 side_fe.clear(); 00154 00155 for (std::map<FEType, FEBase *>::iterator i = edge_fe.begin(); 00156 i != edge_fe.end(); ++i) 00157 delete i->second; 00158 edge_fe.clear(); 00159 00160 00161 for (std::map<FEType, FEAbstract *>::iterator i = _element_fe.begin(); 00162 i != _element_fe.end(); ++i) 00163 delete i->second; 00164 _element_fe.clear(); 00165 00166 for (std::map<FEType, FEAbstract *>::iterator i = _side_fe.begin(); 00167 i != _side_fe.end(); ++i) 00168 delete i->second; 00169 _side_fe.clear(); 00170 00171 for (std::map<FEType, FEAbstract *>::iterator i = _edge_fe.begin(); 00172 i != _edge_fe.end(); ++i) 00173 delete i->second; 00174 _edge_fe.clear(); 00175 00176 00177 delete element_qrule; 00178 element_qrule = NULL; 00179 00180 delete side_qrule; 00181 side_qrule = NULL; 00182 00183 if (edge_qrule) 00184 delete edge_qrule; 00185 side_qrule = NULL; 00186 } 00187 00188 00189 00190 bool FEMContext::has_side_boundary_id(boundary_id_type id) const 00191 { 00192 return _boundary_info->has_boundary_id(elem, side, id); 00193 } 00194 00195 00196 std::vector<boundary_id_type> FEMContext::side_boundary_ids() const 00197 { 00198 return _boundary_info->boundary_ids(elem, side); 00199 } 00200 00201 00202 00203 Number FEMContext::interior_value(unsigned int var, unsigned int qp) const 00204 { 00205 Number u = 0.; 00206 00207 this->interior_value( var, qp, u ); 00208 00209 return u; 00210 } 00211 00212 template<typename OutputType> 00213 void FEMContext::interior_value(unsigned int var, unsigned int qp, 00214 OutputType& u) const 00215 { 00216 typedef typename TensorTools::MakeReal<OutputType>::type OutputShape; 00217 00218 // Get local-to-global dof index lookup 00219 libmesh_assert_greater (dof_indices.size(), var); 00220 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00221 (dof_indices_var[var].size()); 00222 00223 // Get current local coefficients 00224 libmesh_assert_greater (elem_subsolutions.size(), var); 00225 libmesh_assert(elem_subsolutions[var]); 00226 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00227 00228 // Get finite element object 00229 FEGenericBase<OutputShape>* fe = NULL; 00230 this->get_element_fe<OutputShape>( var, fe ); 00231 00232 // Get shape function values at quadrature point 00233 const std::vector<std::vector<OutputShape> > &phi = fe->get_phi(); 00234 00235 // Accumulate solution value 00236 u = 0.; 00237 00238 for (unsigned int l=0; l != n_dofs; l++) 00239 u += phi[l][qp] * coef(l); 00240 00241 return; 00242 } 00243 00244 00245 template<typename OutputType> 00246 void FEMContext::interior_values (unsigned int var, 00247 const NumericVector<Number> & _system_vector, 00248 std::vector<OutputType>& u_vals) const 00249 { 00250 typedef typename TensorTools::MakeReal<OutputType>::type OutputShape; 00251 00252 // Get local-to-global dof index lookup 00253 libmesh_assert_greater (dof_indices.size(), var); 00254 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00255 (dof_indices_var[var].size()); 00256 00257 // Get current local coefficients 00258 const DenseSubVector<Number> &coef = get_localized_subvector(_system_vector, var); 00259 00260 // Get the finite element object 00261 FEGenericBase<OutputShape>* fe = NULL; 00262 this->get_element_fe<OutputShape>( var, fe ); 00263 00264 // Get shape function values at quadrature point 00265 const std::vector<std::vector<OutputShape> > &phi = fe->get_phi(); 00266 00267 // Loop over all the q_points on this element 00268 for (unsigned int qp=0; qp != u_vals.size(); qp++) 00269 { 00270 OutputType &u = u_vals[qp]; 00271 00272 // Compute the value at this q_point 00273 u = 0.; 00274 00275 for (unsigned int l=0; l != n_dofs; l++) 00276 u += phi[l][qp] * coef(l); 00277 } 00278 00279 return; 00280 } 00281 00282 Gradient FEMContext::interior_gradient(unsigned int var, unsigned int qp) const 00283 { 00284 Gradient du; 00285 00286 this->interior_gradient( var, qp, du ); 00287 00288 return du; 00289 } 00290 00291 00292 00293 template<typename OutputType> 00294 void FEMContext::interior_gradient(unsigned int var, unsigned int qp, 00295 OutputType& du) const 00296 { 00297 typedef typename TensorTools::MakeReal 00298 <typename TensorTools::DecrementRank<OutputType>::type>::type 00299 OutputShape; 00300 00301 // Get local-to-global dof index lookup 00302 libmesh_assert_greater (dof_indices.size(), var); 00303 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00304 (dof_indices_var[var].size()); 00305 00306 // Get current local coefficients 00307 libmesh_assert_greater (elem_subsolutions.size(), var); 00308 libmesh_assert(elem_subsolutions[var]); 00309 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00310 00311 // Get finite element object 00312 FEGenericBase<OutputShape>* fe = NULL; 00313 this->get_element_fe<OutputShape>( var, fe ); 00314 00315 // Get shape function values at quadrature point 00316 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient> > &dphi = fe->get_dphi(); 00317 00318 // Accumulate solution derivatives 00319 du = 0; 00320 00321 for (unsigned int l=0; l != n_dofs; l++) 00322 du.add_scaled(dphi[l][qp], coef(l)); 00323 00324 return; 00325 } 00326 00327 00328 00329 template<typename OutputType> 00330 void FEMContext::interior_gradients 00331 (unsigned int var, 00332 const NumericVector<Number> & _system_vector, 00333 std::vector<OutputType>& du_vals) const 00334 { 00335 typedef typename TensorTools::MakeReal 00336 <typename TensorTools::DecrementRank<OutputType>::type>::type 00337 OutputShape; 00338 00339 // Get local-to-global dof index lookup 00340 libmesh_assert_greater (dof_indices.size(), var); 00341 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00342 (dof_indices_var[var].size()); 00343 00344 // Get current local coefficients 00345 const DenseSubVector<Number> &coef = get_localized_subvector(_system_vector, var); 00346 00347 // Get finite element object 00348 FEGenericBase<OutputShape>* fe = NULL; 00349 this->get_element_fe<OutputShape>( var, fe ); 00350 00351 // Get shape function values at quadrature point 00352 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient> > &dphi = fe->get_dphi(); 00353 00354 // Loop over all the q_points in this finite element 00355 for (unsigned int qp=0; qp != du_vals.size(); qp++) 00356 { 00357 OutputType &du = du_vals[qp]; 00358 00359 // Compute the gradient at this q_point 00360 du = 0; 00361 00362 for (unsigned int l=0; l != n_dofs; l++) 00363 du.add_scaled(dphi[l][qp], coef(l)); 00364 } 00365 00366 return; 00367 } 00368 00369 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 00370 Tensor FEMContext::interior_hessian(unsigned int var, unsigned int qp) const 00371 { 00372 Tensor d2u; 00373 00374 this->interior_hessian( var, qp, d2u ); 00375 00376 return d2u; 00377 } 00378 00379 template<typename OutputType> 00380 void FEMContext::interior_hessian(unsigned int var, unsigned int qp, 00381 OutputType& d2u) const 00382 { 00383 typedef typename TensorTools::MakeReal< 00384 typename TensorTools::DecrementRank< 00385 typename TensorTools::DecrementRank< 00386 OutputType>::type>::type>::type 00387 OutputShape; 00388 00389 // Get local-to-global dof index lookup 00390 libmesh_assert_greater (dof_indices.size(), var); 00391 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00392 (dof_indices_var[var].size()); 00393 00394 // Get current local coefficients 00395 libmesh_assert_greater (elem_subsolutions.size(), var); 00396 libmesh_assert(elem_subsolutions[var]); 00397 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00398 00399 // Get finite element object 00400 FEGenericBase<OutputShape>* fe = NULL; 00401 this->get_element_fe<OutputShape>( var, fe ); 00402 00403 // Get shape function values at quadrature point 00404 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor> > &d2phi = fe->get_d2phi(); 00405 00406 // Accumulate solution second derivatives 00407 d2u = 0.0; 00408 00409 for (unsigned int l=0; l != n_dofs; l++) 00410 d2u.add_scaled(d2phi[l][qp], coef(l)); 00411 00412 return; 00413 } 00414 00415 00416 template<typename OutputType> 00417 void FEMContext::interior_hessians 00418 (unsigned int var, 00419 const NumericVector<Number> & _system_vector, 00420 std::vector<OutputType>& d2u_vals) const 00421 { 00422 typedef typename TensorTools::MakeReal< 00423 typename TensorTools::DecrementRank< 00424 typename TensorTools::DecrementRank< 00425 OutputType>::type>::type>::type 00426 OutputShape; 00427 00428 // Get local-to-global dof index lookup 00429 libmesh_assert_greater (dof_indices.size(), var); 00430 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00431 (dof_indices_var[var].size()); 00432 00433 // Get current local coefficients 00434 const DenseSubVector<Number> &coef = get_localized_subvector(_system_vector, var); 00435 00436 // Get finite element object 00437 FEGenericBase<OutputShape>* fe = NULL; 00438 this->get_element_fe<OutputShape>( var, fe ); 00439 00440 // Get shape function values at quadrature point 00441 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor> > &d2phi = fe->get_d2phi(); 00442 00443 // Loop over all the q_points in this finite element 00444 for (unsigned int qp=0; qp != d2u_vals.size(); qp++) 00445 { 00446 OutputType &d2u = d2u_vals[qp]; 00447 00448 // Compute the gradient at this q_point 00449 d2u = 0; 00450 00451 for (unsigned int l=0; l != n_dofs; l++) 00452 d2u.add_scaled(d2phi[l][qp], coef(l)); 00453 } 00454 00455 return; 00456 } 00457 00458 00459 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 00460 00461 00462 template<typename OutputType> 00463 void FEMContext::interior_curl(unsigned int var, unsigned int qp, 00464 OutputType& curl_u) const 00465 { 00466 typedef typename TensorTools::MakeReal<OutputType>::type OutputShape; 00467 00468 // Get local-to-global dof index lookup 00469 libmesh_assert_greater (dof_indices.size(), var); 00470 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00471 (dof_indices_var[var].size()); 00472 00473 // Get current local coefficients 00474 libmesh_assert_greater (elem_subsolutions.size(), var); 00475 libmesh_assert(elem_subsolutions[var]); 00476 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00477 00478 // Get finite element object 00479 FEGenericBase<OutputShape>* fe = NULL; 00480 this->get_element_fe<OutputShape>( var, fe ); 00481 00482 // Get shape function values at quadrature point 00483 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputShape> > &curl_phi = fe->get_curl_phi(); 00484 00485 // Accumulate solution curl 00486 curl_u = 0.; 00487 00488 for (unsigned int l=0; l != n_dofs; l++) 00489 curl_u.add_scaled(curl_phi[l][qp], coef(l)); 00490 00491 return; 00492 } 00493 00494 00495 template<typename OutputType> 00496 void FEMContext::interior_div(unsigned int var, unsigned int qp, 00497 OutputType& div_u) const 00498 { 00499 typedef typename 00500 TensorTools::IncrementRank 00501 <typename TensorTools::MakeReal<OutputType>::type>::type OutputShape; 00502 00503 // Get local-to-global dof index lookup 00504 libmesh_assert_greater (dof_indices.size(), var); 00505 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00506 (dof_indices_var[var].size()); 00507 00508 // Get current local coefficients 00509 libmesh_assert_greater (elem_subsolutions.size(), var); 00510 libmesh_assert(elem_subsolutions[var]); 00511 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00512 00513 // Get finite element object 00514 FEGenericBase<OutputShape>* fe = NULL; 00515 this->get_element_fe<OutputShape>( var, fe ); 00516 00517 // Get shape function values at quadrature point 00518 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputDivergence> > &div_phi = fe->get_div_phi(); 00519 00520 // Accumulate solution curl 00521 div_u = 0.; 00522 00523 for (unsigned int l=0; l != n_dofs; l++) 00524 div_u += div_phi[l][qp] * coef(l); 00525 00526 return; 00527 } 00528 00529 00530 Number FEMContext::side_value(unsigned int var, unsigned int qp) const 00531 { 00532 Number u = 0.; 00533 00534 this->side_value( var, qp, u ); 00535 00536 return u; 00537 } 00538 00539 00540 template<typename OutputType> 00541 void FEMContext::side_value(unsigned int var, unsigned int qp, 00542 OutputType& u) const 00543 { 00544 typedef typename TensorTools::MakeReal<OutputType>::type OutputShape; 00545 00546 // Get local-to-global dof index lookup 00547 libmesh_assert_greater (dof_indices.size(), var); 00548 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00549 (dof_indices_var[var].size()); 00550 00551 // Get current local coefficients 00552 libmesh_assert_greater (elem_subsolutions.size(), var); 00553 libmesh_assert(elem_subsolutions[var]); 00554 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00555 00556 // Get finite element object 00557 FEGenericBase<OutputShape>* the_side_fe = NULL; 00558 this->get_side_fe<OutputShape>( var, the_side_fe ); 00559 00560 // Get shape function values at quadrature point 00561 const std::vector<std::vector<OutputShape> > &phi = the_side_fe->get_phi(); 00562 00563 // Accumulate solution value 00564 u = 0.; 00565 00566 for (unsigned int l=0; l != n_dofs; l++) 00567 u += phi[l][qp] * coef(l); 00568 00569 return; 00570 } 00571 00572 00573 template<typename OutputType> 00574 void FEMContext::side_values 00575 (unsigned int var, 00576 const NumericVector<Number> & _system_vector, 00577 std::vector<OutputType>& u_vals) const 00578 { 00579 typedef typename TensorTools::MakeReal<OutputType>::type OutputShape; 00580 00581 // Get local-to-global dof index lookup 00582 libmesh_assert_greater (dof_indices.size(), var); 00583 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00584 (dof_indices_var[var].size()); 00585 00586 // Get current local coefficients 00587 const DenseSubVector<Number> &coef = get_localized_subvector(_system_vector, var); 00588 00589 // Get the finite element object 00590 FEGenericBase<OutputShape>* the_side_fe = NULL; 00591 this->get_side_fe<OutputShape>( var, the_side_fe ); 00592 00593 // Get shape function values at quadrature point 00594 const std::vector<std::vector<OutputShape> > &phi = the_side_fe->get_phi(); 00595 00596 // Loop over all the q_points on this element 00597 for (unsigned int qp=0; qp != u_vals.size(); qp++) 00598 { 00599 OutputType &u = u_vals[qp]; 00600 00601 // Compute the value at this q_point 00602 u = 0.; 00603 00604 for (unsigned int l=0; l != n_dofs; l++) 00605 u += phi[l][qp] * coef(l); 00606 } 00607 00608 return; 00609 } 00610 00611 Gradient FEMContext::side_gradient(unsigned int var, unsigned int qp) const 00612 { 00613 Gradient du; 00614 00615 this->side_gradient( var, qp, du ); 00616 00617 return du; 00618 } 00619 00620 00621 template<typename OutputType> 00622 void FEMContext::side_gradient(unsigned int var, unsigned int qp, 00623 OutputType& du) const 00624 { 00625 typedef typename TensorTools::MakeReal 00626 <typename TensorTools::DecrementRank<OutputType>::type>::type 00627 OutputShape; 00628 00629 // Get local-to-global dof index lookup 00630 libmesh_assert_greater (dof_indices.size(), var); 00631 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00632 (dof_indices_var[var].size()); 00633 00634 // Get current local coefficients 00635 libmesh_assert_greater (elem_subsolutions.size(), var); 00636 libmesh_assert(elem_subsolutions[var]); 00637 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00638 00639 // Get finite element object 00640 FEGenericBase<OutputShape>* the_side_fe = NULL; 00641 this->get_side_fe<OutputShape>( var, the_side_fe ); 00642 00643 // Get shape function values at quadrature point 00644 const std::vector<std::vector< typename FEGenericBase<OutputShape>::OutputGradient> > &dphi = the_side_fe->get_dphi(); 00645 00646 // Accumulate solution derivatives 00647 du = 0.; 00648 00649 for (unsigned int l=0; l != n_dofs; l++) 00650 du.add_scaled(dphi[l][qp], coef(l)); 00651 00652 return; 00653 } 00654 00655 00656 00657 template<typename OutputType> 00658 void FEMContext::side_gradients 00659 (unsigned int var, 00660 const NumericVector<Number> & _system_vector, 00661 std::vector<OutputType>& du_vals) const 00662 { 00663 typedef typename TensorTools::MakeReal 00664 <typename TensorTools::DecrementRank<OutputType>::type>::type 00665 OutputShape; 00666 00667 // Get local-to-global dof index lookup 00668 libmesh_assert_greater (dof_indices.size(), var); 00669 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00670 (dof_indices_var[var].size()); 00671 00672 // Get current local coefficients 00673 const DenseSubVector<Number> &coef = get_localized_subvector(_system_vector, var); 00674 00675 // Get finite element object 00676 FEGenericBase<OutputShape>* the_side_fe = NULL; 00677 this->get_side_fe<OutputShape>( var, the_side_fe ); 00678 00679 // Get shape function values at quadrature point 00680 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient> > &dphi = the_side_fe->get_dphi(); 00681 00682 // Loop over all the q_points in this finite element 00683 for (unsigned int qp=0; qp != du_vals.size(); qp++) 00684 { 00685 OutputType &du = du_vals[qp]; 00686 00687 du = 0; 00688 00689 // Compute the gradient at this q_point 00690 for (unsigned int l=0; l != n_dofs; l++) 00691 du.add_scaled(dphi[l][qp], coef(l)); 00692 } 00693 00694 return; 00695 } 00696 00697 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 00698 Tensor FEMContext::side_hessian(unsigned int var, unsigned int qp) const 00699 { 00700 Tensor d2u; 00701 00702 this->side_hessian( var, qp, d2u ); 00703 00704 return d2u; 00705 } 00706 00707 template<typename OutputType> 00708 void FEMContext::side_hessian(unsigned int var, unsigned int qp, 00709 OutputType& d2u) const 00710 { 00711 typedef typename TensorTools::MakeReal< 00712 typename TensorTools::DecrementRank< 00713 typename TensorTools::DecrementRank< 00714 OutputType>::type>::type>::type 00715 OutputShape; 00716 00717 // Get local-to-global dof index lookup 00718 libmesh_assert_greater (dof_indices.size(), var); 00719 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00720 (dof_indices_var[var].size()); 00721 00722 // Get current local coefficients 00723 libmesh_assert_greater (elem_subsolutions.size(), var); 00724 libmesh_assert(elem_subsolutions[var]); 00725 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00726 00727 // Get finite element object 00728 FEGenericBase<OutputShape>* the_side_fe = NULL; 00729 this->get_side_fe<OutputShape>( var, the_side_fe ); 00730 00731 // Get shape function values at quadrature point 00732 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor> > &d2phi = the_side_fe->get_d2phi(); 00733 00734 // Accumulate solution second derivatives 00735 d2u = 0.0; 00736 00737 for (unsigned int l=0; l != n_dofs; l++) 00738 d2u.add_scaled(d2phi[l][qp], coef(l)); 00739 00740 return; 00741 } 00742 00743 00744 template<typename OutputType> 00745 void FEMContext::side_hessians 00746 (unsigned int var, 00747 const NumericVector<Number> & _system_vector, 00748 std::vector<OutputType>& d2u_vals) const 00749 { 00750 typedef typename TensorTools::MakeReal< 00751 typename TensorTools::DecrementRank< 00752 typename TensorTools::DecrementRank< 00753 OutputType>::type>::type>::type 00754 OutputShape; 00755 00756 // Get local-to-global dof index lookup 00757 libmesh_assert_greater (dof_indices.size(), var); 00758 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00759 (dof_indices_var[var].size()); 00760 00761 // Get current local coefficients 00762 const DenseSubVector<Number> &coef = get_localized_subvector(_system_vector, var); 00763 00764 // Get finite element object 00765 FEGenericBase<OutputShape>* the_side_fe = NULL; 00766 this->get_side_fe<OutputShape>( var, the_side_fe ); 00767 00768 // Get shape function values at quadrature point 00769 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor> > &d2phi = the_side_fe->get_d2phi(); 00770 00771 // Loop over all the q_points in this finite element 00772 for (unsigned int qp=0; qp != d2u_vals.size(); qp++) 00773 { 00774 OutputType &d2u = d2u_vals[qp]; 00775 00776 // Compute the gradient at this q_point 00777 d2u = 0; 00778 00779 for (unsigned int l=0; l != n_dofs; l++) 00780 d2u.add_scaled(d2phi[l][qp], coef(l)); 00781 } 00782 00783 return; 00784 } 00785 00786 00787 00788 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 00789 00790 00791 00792 Number FEMContext::point_value(unsigned int var, const Point &p) const 00793 { 00794 Number u = 0.; 00795 00796 this->point_value( var, p, u ); 00797 00798 return u; 00799 } 00800 00801 template<typename OutputType> 00802 void FEMContext::point_value(unsigned int var, const Point &p, 00803 OutputType& u) const 00804 { 00805 typedef typename TensorTools::MakeReal<OutputType>::type OutputShape; 00806 00807 // Get local-to-global dof index lookup 00808 libmesh_assert_greater (dof_indices.size(), var); 00809 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00810 (dof_indices_var[var].size()); 00811 00812 // Get current local coefficients 00813 libmesh_assert_greater (elem_subsolutions.size(), var); 00814 libmesh_assert(elem_subsolutions[var]); 00815 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00816 00817 // Get finite element object 00818 FEGenericBase<OutputShape>* fe = NULL; 00819 this->get_element_fe<OutputShape>( var, fe ); 00820 00821 // Build a FE for calculating u(p) 00822 AutoPtr<FEGenericBase<OutputShape> > fe_new = this->build_new_fe( fe, p ); 00823 00824 // Get the values of the shape function derivatives 00825 const std::vector<std::vector<OutputShape> >& phi = fe_new->get_phi(); 00826 00827 u = 0.; 00828 00829 for (unsigned int l=0; l != n_dofs; l++) 00830 u += phi[l][0] * coef(l); 00831 00832 return; 00833 } 00834 00835 00836 00837 Gradient FEMContext::point_gradient(unsigned int var, const Point &p) const 00838 { 00839 Gradient grad_u; 00840 00841 this->point_gradient( var, p, grad_u ); 00842 00843 return grad_u; 00844 } 00845 00846 00847 00848 template<typename OutputType> 00849 void FEMContext::point_gradient(unsigned int var, const Point &p, 00850 OutputType& grad_u) const 00851 { 00852 typedef typename TensorTools::MakeReal 00853 <typename TensorTools::DecrementRank<OutputType>::type>::type 00854 OutputShape; 00855 00856 // Get local-to-global dof index lookup 00857 libmesh_assert_greater (dof_indices.size(), var); 00858 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00859 (dof_indices_var[var].size()); 00860 00861 // Get current local coefficients 00862 libmesh_assert_greater (elem_subsolutions.size(), var); 00863 libmesh_assert(elem_subsolutions[var]); 00864 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00865 00866 // Get finite element object 00867 FEGenericBase<OutputShape>* fe = NULL; 00868 this->get_element_fe<OutputShape>( var, fe ); 00869 00870 // Build a FE for calculating u(p) 00871 AutoPtr<FEGenericBase<OutputShape> > fe_new = this->build_new_fe( fe, p ); 00872 00873 // Get the values of the shape function derivatives 00874 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient> >& dphi = fe_new->get_dphi(); 00875 00876 grad_u = 0.0; 00877 00878 for (unsigned int l=0; l != n_dofs; l++) 00879 grad_u.add_scaled(dphi[l][0], coef(l)); 00880 00881 return; 00882 } 00883 00884 00885 00886 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 00887 00888 Tensor FEMContext::point_hessian(unsigned int var, const Point &p) const 00889 { 00890 Tensor hess_u; 00891 00892 this->point_hessian( var, p, hess_u ); 00893 00894 return hess_u; 00895 } 00896 00897 00898 template<typename OutputType> 00899 void FEMContext::point_hessian(unsigned int var, const Point &p, 00900 OutputType& hess_u) const 00901 { 00902 typedef typename TensorTools::MakeReal< 00903 typename TensorTools::DecrementRank< 00904 typename TensorTools::DecrementRank< 00905 OutputType>::type>::type>::type 00906 OutputShape; 00907 00908 // Get local-to-global dof index lookup 00909 libmesh_assert_greater (dof_indices.size(), var); 00910 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00911 (dof_indices_var[var].size()); 00912 00913 // Get current local coefficients 00914 libmesh_assert_greater (elem_subsolutions.size(), var); 00915 libmesh_assert(elem_subsolutions[var]); 00916 DenseSubVector<Number> &coef = *elem_subsolutions[var]; 00917 00918 // Get finite element object 00919 FEGenericBase<OutputShape>* fe = NULL; 00920 this->get_element_fe<OutputShape>( var, fe ); 00921 00922 // Build a FE for calculating u(p) 00923 AutoPtr<FEGenericBase<OutputShape> > fe_new = this->build_new_fe( fe, p ); 00924 00925 // Get the values of the shape function derivatives 00926 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor> >& d2phi = fe_new->get_d2phi(); 00927 00928 hess_u = 0.0; 00929 00930 for (unsigned int l=0; l != n_dofs; l++) 00931 hess_u.add_scaled(d2phi[l][0], coef(l)); 00932 00933 return; 00934 } 00935 00936 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES 00937 00938 00939 00940 00941 Number FEMContext::fixed_interior_value(unsigned int var, unsigned int qp) const 00942 { 00943 Number u = 0.; 00944 00945 this->fixed_interior_value( var, qp, u ); 00946 00947 return u; 00948 } 00949 00950 00951 00952 template<typename OutputType> 00953 void FEMContext::fixed_interior_value(unsigned int var, unsigned int qp, 00954 OutputType& u) const 00955 { 00956 typedef typename TensorTools::MakeReal<OutputType>::type OutputShape; 00957 00958 // Get local-to-global dof index lookup 00959 libmesh_assert_greater (dof_indices.size(), var); 00960 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 00961 (dof_indices_var[var].size()); 00962 00963 // Get current local coefficients 00964 libmesh_assert_greater (elem_fixed_subsolutions.size(), var); 00965 libmesh_assert(elem_fixed_subsolutions[var]); 00966 DenseSubVector<Number> &coef = *elem_fixed_subsolutions[var]; 00967 00968 // Get finite element object 00969 FEGenericBase<OutputShape>* fe = NULL; 00970 this->get_element_fe<OutputShape>( var, fe ); 00971 00972 // Get shape function values at quadrature point 00973 const std::vector<std::vector<OutputShape> > &phi = fe->get_phi(); 00974 00975 // Accumulate solution value 00976 u = 0.0; 00977 00978 for (unsigned int l=0; l != n_dofs; l++) 00979 u += phi[l][qp] * coef(l); 00980 00981 return; 00982 } 00983 00984 00985 00986 Gradient FEMContext::fixed_interior_gradient(unsigned int var, unsigned int qp) const 00987 { 00988 Gradient du; 00989 00990 this->fixed_interior_gradient( var, qp, du ); 00991 00992 return du; 00993 } 00994 00995 00996 template<typename OutputType> 00997 void FEMContext::FEMContext::fixed_interior_gradient(unsigned int var, unsigned int qp, 00998 OutputType& du) const 00999 { 01000 typedef typename TensorTools::MakeReal 01001 <typename TensorTools::DecrementRank<OutputType>::type>::type 01002 OutputShape; 01003 01004 // Get local-to-global dof index lookup 01005 libmesh_assert_greater (dof_indices.size(), var); 01006 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 01007 (dof_indices_var[var].size()); 01008 01009 // Get current local coefficients 01010 libmesh_assert_greater (elem_fixed_subsolutions.size(), var); 01011 libmesh_assert(elem_fixed_subsolutions[var]); 01012 DenseSubVector<Number> &coef = *elem_fixed_subsolutions[var]; 01013 01014 // Get finite element object 01015 FEGenericBase<OutputShape>* fe = NULL; 01016 this->get_element_fe<OutputShape>( var, fe ); 01017 01018 // Get shape function values at quadrature point 01019 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient> > &dphi = fe->get_dphi(); 01020 01021 // Accumulate solution derivatives 01022 du = 0.0; 01023 01024 for (unsigned int l=0; l != n_dofs; l++) 01025 du.add_scaled(dphi[l][qp], coef(l)); 01026 01027 return; 01028 } 01029 01030 01031 01032 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01033 Tensor FEMContext::fixed_interior_hessian(unsigned int var, unsigned int qp) const 01034 { 01035 Tensor d2u; 01036 01037 this->fixed_interior_hessian( var, qp, d2u ); 01038 01039 return d2u; 01040 } 01041 01042 01043 template<typename OutputType> 01044 void FEMContext::fixed_interior_hessian(unsigned int var, unsigned int qp, 01045 OutputType& d2u) const 01046 { 01047 typedef typename TensorTools::MakeReal< 01048 typename TensorTools::DecrementRank< 01049 typename TensorTools::DecrementRank< 01050 OutputType>::type>::type>::type 01051 OutputShape; 01052 01053 // Get local-to-global dof index lookup 01054 libmesh_assert_greater (dof_indices.size(), var); 01055 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 01056 (dof_indices_var[var].size()); 01057 01058 // Get current local coefficients 01059 libmesh_assert_greater (elem_fixed_subsolutions.size(), var); 01060 libmesh_assert(elem_fixed_subsolutions[var]); 01061 DenseSubVector<Number> &coef = *elem_fixed_subsolutions[var]; 01062 01063 // Get finite element object 01064 FEGenericBase<OutputShape>* fe = NULL; 01065 this->get_element_fe<OutputShape>( var, fe ); 01066 01067 // Get shape function values at quadrature point 01068 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor> > &d2phi = fe->get_d2phi(); 01069 01070 // Accumulate solution second derivatives 01071 d2u = 0.0; 01072 01073 for (unsigned int l=0; l != n_dofs; l++) 01074 d2u.add_scaled(d2phi[l][qp], coef(l)); 01075 01076 return; 01077 } 01078 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01079 01080 01081 01082 Number FEMContext::fixed_side_value(unsigned int var, unsigned int qp) const 01083 { 01084 Number u = 0.; 01085 01086 this->fixed_side_value( var, qp, u ); 01087 01088 return u; 01089 } 01090 01091 01092 template<typename OutputType> 01093 void FEMContext::fixed_side_value(unsigned int var, unsigned int qp, 01094 OutputType& u) const 01095 { 01096 typedef typename TensorTools::MakeReal<OutputType>::type OutputShape; 01097 01098 // Get local-to-global dof index lookup 01099 libmesh_assert_greater (dof_indices.size(), var); 01100 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 01101 (dof_indices_var[var].size()); 01102 01103 // Get current local coefficients 01104 libmesh_assert_greater (elem_fixed_subsolutions.size(), var); 01105 libmesh_assert(elem_fixed_subsolutions[var]); 01106 DenseSubVector<Number> &coef = *elem_fixed_subsolutions[var]; 01107 01108 // Get finite element object 01109 FEGenericBase<OutputShape>* the_side_fe = NULL; 01110 this->get_side_fe<OutputShape>( var, the_side_fe ); 01111 01112 // Get shape function values at quadrature point 01113 const std::vector<std::vector<OutputShape> > &phi = the_side_fe->get_phi(); 01114 01115 // Accumulate solution value 01116 u = 0.0; 01117 01118 for (unsigned int l=0; l != n_dofs; l++) 01119 u += phi[l][qp] * coef(l); 01120 01121 return; 01122 } 01123 01124 01125 01126 Gradient FEMContext::fixed_side_gradient(unsigned int var, unsigned int qp) const 01127 { 01128 Gradient du; 01129 01130 this->fixed_side_gradient( var, qp, du ); 01131 01132 return du; 01133 } 01134 01135 01136 template<typename OutputType> 01137 void FEMContext::fixed_side_gradient(unsigned int var, unsigned int qp, 01138 OutputType& du) const 01139 { 01140 typedef typename TensorTools::MakeReal 01141 <typename TensorTools::DecrementRank<OutputType>::type>::type 01142 OutputShape; 01143 01144 // Get local-to-global dof index lookup 01145 libmesh_assert_greater (dof_indices.size(), var); 01146 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 01147 (dof_indices_var[var].size()); 01148 01149 // Get current local coefficients 01150 libmesh_assert_greater (elem_fixed_subsolutions.size(), var); 01151 libmesh_assert(elem_fixed_subsolutions[var]); 01152 DenseSubVector<Number> &coef = *elem_fixed_subsolutions[var]; 01153 01154 // Get finite element object 01155 FEGenericBase<OutputShape>* the_side_fe = NULL; 01156 this->get_side_fe<OutputShape>( var, the_side_fe ); 01157 01158 // Get shape function values at quadrature point 01159 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient> > &dphi = the_side_fe->get_dphi(); 01160 01161 // Accumulate solution derivatives 01162 du = 0.0; 01163 01164 for (unsigned int l=0; l != n_dofs; l++) 01165 du.add_scaled(dphi[l][qp], coef(l)); 01166 01167 return; 01168 } 01169 01170 01171 01172 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01173 Tensor FEMContext::fixed_side_hessian(unsigned int var, unsigned int qp) const 01174 { 01175 Tensor d2u; 01176 01177 this->fixed_side_hessian( var, qp, d2u ); 01178 01179 return d2u; 01180 } 01181 01182 template<typename OutputType> 01183 void FEMContext::fixed_side_hessian(unsigned int var, unsigned int qp, 01184 OutputType& d2u) const 01185 { 01186 typedef typename TensorTools::MakeReal< 01187 typename TensorTools::DecrementRank< 01188 typename TensorTools::DecrementRank< 01189 OutputType>::type>::type>::type 01190 OutputShape; 01191 01192 // Get local-to-global dof index lookup 01193 libmesh_assert_greater (dof_indices.size(), var); 01194 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 01195 (dof_indices_var[var].size()); 01196 01197 // Get current local coefficients 01198 libmesh_assert_greater (elem_fixed_subsolutions.size(), var); 01199 libmesh_assert(elem_fixed_subsolutions[var]); 01200 DenseSubVector<Number> &coef = *elem_fixed_subsolutions[var]; 01201 01202 // Get finite element object 01203 FEGenericBase<OutputShape>* the_side_fe = NULL; 01204 this->get_side_fe<OutputShape>( var, the_side_fe ); 01205 01206 // Get shape function values at quadrature point 01207 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor> > &d2phi = the_side_fe->get_d2phi(); 01208 01209 // Accumulate solution second derivatives 01210 d2u = 0.0; 01211 01212 for (unsigned int l=0; l != n_dofs; l++) 01213 d2u.add_scaled(d2phi[l][qp], coef(l)); 01214 01215 return; 01216 } 01217 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01218 01219 01220 01221 Number FEMContext::fixed_point_value(unsigned int var, const Point &p) const 01222 { 01223 Number u = 0.; 01224 01225 this->fixed_point_value( var, p, u ); 01226 01227 return u; 01228 } 01229 01230 template<typename OutputType> 01231 void FEMContext::fixed_point_value(unsigned int var, const Point &p, 01232 OutputType& u) const 01233 { 01234 typedef typename TensorTools::MakeReal<OutputType>::type OutputShape; 01235 01236 // Get local-to-global dof index lookup 01237 libmesh_assert_greater (dof_indices.size(), var); 01238 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 01239 (dof_indices_var[var].size()); 01240 01241 // Get current local coefficients 01242 libmesh_assert_greater (elem_fixed_subsolutions.size(), var); 01243 libmesh_assert(elem_fixed_subsolutions[var]); 01244 DenseSubVector<Number> &coef = *elem_fixed_subsolutions[var]; 01245 01246 // Get finite element object 01247 FEGenericBase<OutputShape>* fe = NULL; 01248 this->get_element_fe<OutputShape>( var, fe ); 01249 01250 // Build a FE for calculating u(p) 01251 AutoPtr<FEGenericBase<OutputShape> > fe_new = this->build_new_fe( fe, p ); 01252 01253 // Get the values of the shape function derivatives 01254 const std::vector<std::vector<OutputShape> >& phi = fe_new->get_phi(); 01255 01256 u = 0.; 01257 01258 for (unsigned int l=0; l != n_dofs; l++) 01259 u += phi[l][0] * coef(l); 01260 01261 return; 01262 } 01263 01264 01265 01266 Gradient FEMContext::fixed_point_gradient(unsigned int var, const Point &p) const 01267 { 01268 Gradient grad_u; 01269 01270 this->fixed_point_gradient( var, p, grad_u ); 01271 01272 return grad_u; 01273 } 01274 01275 01276 01277 template<typename OutputType> 01278 void FEMContext::fixed_point_gradient(unsigned int var, const Point &p, 01279 OutputType& grad_u) const 01280 { 01281 typedef typename TensorTools::MakeReal 01282 <typename TensorTools::DecrementRank<OutputType>::type>::type 01283 OutputShape; 01284 01285 // Get local-to-global dof index lookup 01286 libmesh_assert_greater (dof_indices.size(), var); 01287 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 01288 (dof_indices_var[var].size()); 01289 01290 // Get current local coefficients 01291 libmesh_assert_greater (elem_fixed_subsolutions.size(), var); 01292 libmesh_assert(elem_fixed_subsolutions[var]); 01293 DenseSubVector<Number> &coef = *elem_fixed_subsolutions[var]; 01294 01295 // Get finite element object 01296 FEGenericBase<OutputShape>* fe = NULL; 01297 this->get_element_fe<OutputShape>( var, fe ); 01298 01299 // Build a FE for calculating u(p) 01300 AutoPtr<FEGenericBase<OutputShape> > fe_new = this->build_new_fe( fe, p ); 01301 01302 // Get the values of the shape function derivatives 01303 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient> >& dphi = fe_new->get_dphi(); 01304 01305 grad_u = 0.0; 01306 01307 for (unsigned int l=0; l != n_dofs; l++) 01308 grad_u.add_scaled(dphi[l][0], coef(l)); 01309 01310 return; 01311 } 01312 01313 01314 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01315 01316 Tensor FEMContext::fixed_point_hessian(unsigned int var, const Point &p) const 01317 { 01318 Tensor hess_u; 01319 01320 this->fixed_point_hessian( var, p, hess_u ); 01321 01322 return hess_u; 01323 } 01324 01325 01326 01327 template<typename OutputType> 01328 void FEMContext::fixed_point_hessian(unsigned int var, const Point &p, 01329 OutputType& hess_u) const 01330 { 01331 typedef typename TensorTools::MakeReal< 01332 typename TensorTools::DecrementRank< 01333 typename TensorTools::DecrementRank< 01334 OutputType>::type>::type>::type 01335 OutputShape; 01336 01337 // Get local-to-global dof index lookup 01338 libmesh_assert_greater (dof_indices.size(), var); 01339 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 01340 (dof_indices_var[var].size()); 01341 01342 // Get current local coefficients 01343 libmesh_assert_greater (elem_fixed_subsolutions.size(), var); 01344 libmesh_assert(elem_fixed_subsolutions[var]); 01345 DenseSubVector<Number> &coef = *elem_fixed_subsolutions[var]; 01346 01347 // Get finite element object 01348 FEGenericBase<OutputShape>* fe = NULL; 01349 this->get_element_fe<OutputShape>( var, fe ); 01350 01351 // Build a FE for calculating u(p) 01352 AutoPtr<FEGenericBase<OutputShape> > fe_new = this->build_new_fe( fe, p ); 01353 01354 // Get the values of the shape function derivatives 01355 const std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputTensor> >& d2phi = fe_new->get_d2phi(); 01356 01357 hess_u = 0.0; 01358 01359 for (unsigned int l=0; l != n_dofs; l++) 01360 hess_u.add_scaled(d2phi[l][0], coef(l)); 01361 01362 return; 01363 } 01364 01365 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES 01366 01367 01368 01369 01370 01371 void FEMContext::elem_reinit(Real theta) 01372 { 01373 // Update the "time" variable of this context object 01374 this->_update_time_from_system(theta); 01375 01376 // Handle a moving element if necessary. 01377 if (_mesh_sys) 01378 // We assume that the ``default'' state 01379 // of the mesh is its final, theta=1.0 01380 // position, so we don't bother with 01381 // mesh motion in that case. 01382 if (theta != 1.0) 01383 { 01384 // FIXME - ALE is not threadsafe yet! 01385 libmesh_assert_equal_to (libMesh::n_threads(), 1); 01386 01387 elem_position_set(theta); 01388 } 01389 elem_fe_reinit(); 01390 } 01391 01392 01393 void FEMContext::elem_side_reinit(Real theta) 01394 { 01395 // Update the "time" variable of this context object 01396 this->_update_time_from_system(theta); 01397 01398 // Handle a moving element if necessary 01399 if (_mesh_sys) 01400 { 01401 // FIXME - not threadsafe yet! 01402 elem_position_set(theta); 01403 side_fe_reinit(); 01404 } 01405 } 01406 01407 01408 void FEMContext::elem_edge_reinit(Real theta) 01409 { 01410 // Update the "time" variable of this context object 01411 this->_update_time_from_system(theta); 01412 01413 // Handle a moving element if necessary 01414 if (_mesh_sys) 01415 { 01416 // FIXME - not threadsafe yet! 01417 elem_position_set(theta); 01418 edge_fe_reinit(); 01419 } 01420 } 01421 01422 01423 void FEMContext::elem_fe_reinit () 01424 { 01425 // Initialize all the interior FE objects on elem. 01426 // Logging of FE::reinit is done in the FE functions 01427 std::map<FEType, FEBase *>::iterator fe_end = element_fe.end(); 01428 for (std::map<FEType, FEBase *>::iterator i = element_fe.begin(); 01429 i != fe_end; ++i) 01430 { 01431 i->second->reinit(elem); 01432 } 01433 01434 01435 std::map<FEType, FEAbstract *>::iterator local_fe_end = _element_fe.end(); 01436 for (std::map<FEType, FEAbstract *>::iterator i = _element_fe.begin(); 01437 i != local_fe_end; ++i) 01438 { 01439 i->second->reinit(elem); 01440 } 01441 } 01442 01443 01444 void FEMContext::side_fe_reinit () 01445 { 01446 // Initialize all the side FE objects on elem/side. 01447 // Logging of FE::reinit is done in the FE functions 01448 std::map<FEType, FEBase *>::iterator fe_end = side_fe.end(); 01449 for (std::map<FEType, FEBase *>::iterator i = side_fe.begin(); 01450 i != fe_end; ++i) 01451 { 01452 i->second->reinit(elem, side); 01453 } 01454 01455 std::map<FEType, FEAbstract *>::iterator local_fe_end = _side_fe.end(); 01456 for (std::map<FEType, FEAbstract *>::iterator i = _side_fe.begin(); 01457 i != local_fe_end; ++i) 01458 { 01459 i->second->reinit(elem, side); 01460 } 01461 } 01462 01463 01464 01465 void FEMContext::edge_fe_reinit () 01466 { 01467 libmesh_assert_equal_to (dim, 3); 01468 01469 // Initialize all the interior FE objects on elem/edge. 01470 // Logging of FE::reinit is done in the FE functions 01471 std::map<FEType, FEBase *>::iterator fe_end = edge_fe.end(); 01472 for (std::map<FEType, FEBase *>::iterator i = edge_fe.begin(); 01473 i != fe_end; ++i) 01474 { 01475 i->second->edge_reinit(elem, edge); 01476 } 01477 01478 std::map<FEType, FEAbstract *>::iterator local_fe_end = _edge_fe.end(); 01479 for (std::map<FEType, FEAbstract *>::iterator i = _edge_fe.begin(); 01480 i != local_fe_end; ++i) 01481 { 01482 i->second->edge_reinit(elem, edge); 01483 } 01484 } 01485 01486 01487 01488 void FEMContext::elem_position_get() 01489 { 01490 // This is too expensive to call unless we've been asked to move the mesh 01491 libmesh_assert (_mesh_sys); 01492 01493 // This will probably break with threading when two contexts are 01494 // operating on elements which share a node 01495 libmesh_assert_equal_to (libMesh::n_threads(), 1); 01496 01497 // If the coordinate data is in our own system, it's already 01498 // been set up for us 01499 // if (_mesh_sys == this->number()) 01500 // { 01501 unsigned int n_nodes = elem->n_nodes(); 01502 // For simplicity we demand that mesh coordinates be stored 01503 // in a format that allows a direct copy 01504 libmesh_assert(_mesh_x_var == libMesh::invalid_uint || 01505 (element_fe_var[_mesh_x_var]->get_fe_type().family 01506 == LAGRANGE && 01507 element_fe_var[_mesh_x_var]->get_fe_type().order 01508 == elem->default_order())); 01509 libmesh_assert(_mesh_y_var == libMesh::invalid_uint || 01510 (element_fe_var[_mesh_y_var]->get_fe_type().family 01511 == LAGRANGE && 01512 element_fe_var[_mesh_y_var]->get_fe_type().order 01513 == elem->default_order())); 01514 libmesh_assert(_mesh_z_var == libMesh::invalid_uint || 01515 (element_fe_var[_mesh_z_var]->get_fe_type().family 01516 == LAGRANGE && 01517 element_fe_var[_mesh_z_var]->get_fe_type().order 01518 == elem->default_order())); 01519 01520 // Get degree of freedom coefficients from point coordinates 01521 if (_mesh_x_var != libMesh::invalid_uint) 01522 for (unsigned int i=0; i != n_nodes; ++i) 01523 (*elem_subsolutions[_mesh_x_var])(i) = elem->point(i)(0); 01524 01525 if (_mesh_y_var != libMesh::invalid_uint) 01526 for (unsigned int i=0; i != n_nodes; ++i) 01527 (*elem_subsolutions[_mesh_y_var])(i) = elem->point(i)(1); 01528 01529 if (_mesh_z_var != libMesh::invalid_uint) 01530 for (unsigned int i=0; i != n_nodes; ++i) 01531 (*elem_subsolutions[_mesh_z_var])(i) = elem->point(i)(2); 01532 // } 01533 // FIXME - If the coordinate data is not in our own system, someone 01534 // had better get around to implementing that... - RHS 01535 // else 01536 // { 01537 // libmesh_not_implemented(); 01538 // } 01539 } 01540 01541 01542 01543 // We can ignore the theta argument in the current use of this 01544 // function, because elem_subsolutions will already have been set to 01545 // the theta value. 01546 // 01547 // To enable loose mesh movement coupling things will need to change. 01548 void FEMContext::_do_elem_position_set(Real) 01549 { 01550 // This is too expensive to call unless we've been asked to move the mesh 01551 libmesh_assert (_mesh_sys); 01552 01553 // This will probably break with threading when two contexts are 01554 // operating on elements which share a node 01555 libmesh_assert_equal_to (libMesh::n_threads(), 1); 01556 01557 // If the coordinate data is in our own system, it's already 01558 // been set up for us, and we can ignore our input parameter theta 01559 // if (_mesh_sys == this->number()) 01560 // { 01561 unsigned int n_nodes = elem->n_nodes(); 01562 // For simplicity we demand that mesh coordinates be stored 01563 // in a format that allows a direct copy 01564 libmesh_assert(_mesh_x_var == libMesh::invalid_uint || 01565 (element_fe_var[_mesh_x_var]->get_fe_type().family 01566 == LAGRANGE && 01567 elem_subsolutions[_mesh_x_var]->size() == n_nodes)); 01568 libmesh_assert(_mesh_y_var == libMesh::invalid_uint || 01569 (element_fe_var[_mesh_y_var]->get_fe_type().family 01570 == LAGRANGE && 01571 elem_subsolutions[_mesh_y_var]->size() == n_nodes)); 01572 libmesh_assert(_mesh_z_var == libMesh::invalid_uint || 01573 (element_fe_var[_mesh_z_var]->get_fe_type().family 01574 == LAGRANGE && 01575 elem_subsolutions[_mesh_z_var]->size() == n_nodes)); 01576 01577 // Set the new point coordinates 01578 if (_mesh_x_var != libMesh::invalid_uint) 01579 for (unsigned int i=0; i != n_nodes; ++i) 01580 const_cast<Elem*>(elem)->point(i)(0) = 01581 libmesh_real((*elem_subsolutions[_mesh_x_var])(i)); 01582 01583 if (_mesh_y_var != libMesh::invalid_uint) 01584 for (unsigned int i=0; i != n_nodes; ++i) 01585 const_cast<Elem*>(elem)->point(i)(1) = 01586 libmesh_real((*elem_subsolutions[_mesh_y_var])(i)); 01587 01588 if (_mesh_z_var != libMesh::invalid_uint) 01589 for (unsigned int i=0; i != n_nodes; ++i) 01590 const_cast<Elem*>(elem)->point(i)(2) = 01591 libmesh_real((*elem_subsolutions[_mesh_z_var])(i)); 01592 // } 01593 // FIXME - If the coordinate data is not in our own system, someone 01594 // had better get around to implementing that... - RHS 01595 // else 01596 // { 01597 // libmesh_not_implemented(); 01598 // } 01599 } 01600 01601 01602 01603 01604 01605 /* 01606 void FEMContext::reinit(const FEMSystem &sys, Elem *e) 01607 { 01608 // Initialize our elem pointer, algebraic objects 01609 this->pre_fe_reinit(e); 01610 01611 // Moving the mesh may be necessary 01612 // Reinitializing the FE objects is definitely necessary 01613 this->elem_reinit(1.); 01614 } 01615 */ 01616 01617 01618 01619 void FEMContext::pre_fe_reinit(const System &sys, const Elem *e) 01620 { 01621 elem = e; 01622 01623 // Initialize the per-element data for elem. 01624 sys.get_dof_map().dof_indices (elem, dof_indices); 01625 const unsigned int n_dofs = libmesh_cast_int<unsigned int> 01626 (dof_indices.size()); 01627 const std::size_t n_qoi = sys.qoi.size(); 01628 01629 elem_solution.resize(n_dofs); 01630 if (sys.use_fixed_solution) 01631 elem_fixed_solution.resize(n_dofs); 01632 01633 for (unsigned int i=0; i != n_dofs; ++i) 01634 elem_solution(i) = sys.current_solution(dof_indices[i]); 01635 01636 // These resize calls also zero out the residual and jacobian 01637 elem_residual.resize(n_dofs); 01638 elem_jacobian.resize(n_dofs, n_dofs); 01639 01640 elem_qoi_derivative.resize(n_qoi); 01641 elem_qoi_subderivatives.resize(n_qoi); 01642 for (std::size_t q=0; q != n_qoi; ++q) 01643 elem_qoi_derivative[q].resize(n_dofs); 01644 01645 // Initialize the per-variable data for elem. 01646 { 01647 unsigned int sub_dofs = 0; 01648 for (unsigned int i=0; i != sys.n_vars(); ++i) 01649 { 01650 sys.get_dof_map().dof_indices (elem, dof_indices_var[i], i); 01651 01652 const unsigned int n_dofs_var = libmesh_cast_int<unsigned int> 01653 (dof_indices_var[i].size()); 01654 01655 elem_subsolutions[i]->reposition 01656 (sub_dofs, n_dofs_var); 01657 01658 if (sys.use_fixed_solution) 01659 elem_fixed_subsolutions[i]->reposition 01660 (sub_dofs, n_dofs_var); 01661 01662 elem_subresiduals[i]->reposition 01663 (sub_dofs, n_dofs_var); 01664 01665 for (std::size_t q=0; q != n_qoi; ++q) 01666 elem_qoi_subderivatives[q][i]->reposition 01667 (sub_dofs, n_dofs_var); 01668 01669 for (unsigned int j=0; j != i; ++j) 01670 { 01671 const unsigned int n_dofs_var_j = 01672 libmesh_cast_int<unsigned int> 01673 (dof_indices_var[j].size()); 01674 01675 elem_subjacobians[i][j]->reposition 01676 (sub_dofs, elem_subresiduals[j]->i_off(), 01677 n_dofs_var, n_dofs_var_j); 01678 elem_subjacobians[j][i]->reposition 01679 (elem_subresiduals[j]->i_off(), sub_dofs, 01680 n_dofs_var_j, n_dofs_var); 01681 } 01682 elem_subjacobians[i][i]->reposition 01683 (sub_dofs, sub_dofs, 01684 n_dofs_var, 01685 n_dofs_var); 01686 sub_dofs += n_dofs_var; 01687 } 01688 libmesh_assert_equal_to (sub_dofs, n_dofs); 01689 } 01690 01691 // Now do the localization for the user requested vectors 01692 DiffContext::localized_vectors_iterator localized_vec_it = localized_vectors.begin(); 01693 const DiffContext::localized_vectors_iterator localized_vec_end = localized_vectors.end(); 01694 01695 for(; localized_vec_it != localized_vec_end; ++localized_vec_it) 01696 { 01697 const NumericVector<Number> * current_localized_vector = localized_vec_it->first; 01698 01699 DenseVector<Number>& target_vector = localized_vec_it->second.first; 01700 01701 target_vector.resize(n_dofs); 01702 01703 for (unsigned int i=0; i != n_dofs; ++i) 01704 target_vector(i) = (*current_localized_vector)(dof_indices[i]); 01705 01706 // Initialize the per-variable data for elem. 01707 unsigned int sub_dofs = 0; 01708 for (unsigned int i=0; i != sys.n_vars(); ++i) 01709 { 01710 const unsigned int n_dofs_var = libmesh_cast_int<unsigned int> 01711 (dof_indices_var[i].size()); 01712 sys.get_dof_map().dof_indices (elem, dof_indices_var[i], i); 01713 01714 localized_vec_it->second.second[i]->reposition 01715 (sub_dofs, n_dofs_var); 01716 01717 sub_dofs += n_dofs_var; 01718 } 01719 libmesh_assert_equal_to (sub_dofs, n_dofs); 01720 } 01721 } 01722 01723 01724 01725 void FEMContext::_update_time_from_system(Real theta) 01726 { 01727 // Update the "time" variable based on the value of theta. For this 01728 // to work, we need to know the value of deltat, a pointer to which is now 01729 // stored by our parent DiffContext class. Note: get_deltat_value() will 01730 // assert in debug mode if the requested pointer is NULL. 01731 const Real deltat = this->get_deltat_value(); 01732 01733 this->time = theta*(this->system_time + deltat) + (1.-theta)*this->system_time; 01734 } 01735 01736 01737 01738 template<typename OutputShape> 01739 AutoPtr<FEGenericBase<OutputShape> > FEMContext::build_new_fe( const FEGenericBase<OutputShape>* fe, 01740 const Point &p ) const 01741 { 01742 FEType fe_type = fe->get_fe_type(); 01743 AutoPtr<FEGenericBase<OutputShape> > fe_new(FEGenericBase<OutputShape>::build(elem->dim(), fe_type)); 01744 01745 // Map the physical co-ordinates to the master co-ordinates using the inverse_map from fe_interface.h 01746 // Build a vector of point co-ordinates to send to reinit 01747 std::vector<Point> coor(1, FEInterface::inverse_map(dim, fe_type, elem, p)); 01748 01749 // Reinitialize the element and compute the shape function values at coor 01750 fe_new->reinit (elem, &coor); 01751 01752 return fe_new; 01753 } 01754 01755 01756 01757 01758 01759 // Instantiate member function templates 01760 template void FEMContext::interior_value<Number>(unsigned int, unsigned int, Number&) const; 01761 template void FEMContext::interior_values<Number>(unsigned int, const NumericVector<Number> &, 01762 std::vector<Number>&) const; 01763 template void FEMContext::interior_value<Gradient>(unsigned int, unsigned int, Gradient&) const; 01764 template void FEMContext::interior_values<Gradient>(unsigned int, const NumericVector<Number> &, 01765 std::vector<Gradient>&) const; 01766 01767 template void FEMContext::interior_gradient<Gradient>(unsigned int, unsigned int, Gradient&) const; 01768 template void FEMContext::interior_gradients<Gradient>(unsigned int, const NumericVector<Number> &, 01769 std::vector<Gradient>&) const; 01770 template void FEMContext::interior_gradient<Tensor>(unsigned int, unsigned int, Tensor&) const; 01771 template void FEMContext::interior_gradients<Tensor>(unsigned int, const NumericVector<Number> &, 01772 std::vector<Tensor>&) const; 01773 01774 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01775 template void FEMContext::interior_hessian<Tensor>(unsigned int, unsigned int, Tensor&) const; 01776 template void FEMContext::interior_hessians<Tensor>(unsigned int, const NumericVector<Number> &, 01777 std::vector<Tensor>&) const; 01778 //FIXME: Not everything is implemented yet for second derivatives of RealGradients 01779 //template void FEMContext::interior_hessian<??>(unsigned int, unsigned int, ??&) const; 01780 //template void FEMContext::interior_hessians<??>(unsigned int, const NumericVector<Number> &, 01781 // std::vector<??>&) const; 01782 #endif 01783 01784 template void FEMContext::interior_curl<Gradient>(unsigned int, unsigned int, Gradient&) const; 01785 01786 template void FEMContext::interior_div<Number>(unsigned int, unsigned int, Number&) const; 01787 01788 template void FEMContext::side_value<Number>(unsigned int, unsigned int, Number&) const; 01789 template void FEMContext::side_value<Gradient>(unsigned int, unsigned int, Gradient&) const; 01790 template void FEMContext::side_values<Number>(unsigned int, const NumericVector<Number> &, 01791 std::vector<Number>&) const; 01792 template void FEMContext::side_values<Gradient>(unsigned int, const NumericVector<Number> &, 01793 std::vector<Gradient>&) const; 01794 01795 template void FEMContext::side_gradient<Gradient>(unsigned int, unsigned int, Gradient&) const; 01796 template void FEMContext::side_gradients<Gradient>(unsigned int, const NumericVector<Number> &, 01797 std::vector<Gradient>&) const; 01798 template void FEMContext::side_gradient<Tensor>(unsigned int, unsigned int, Tensor&) const; 01799 template void FEMContext::side_gradients<Tensor>(unsigned int, const NumericVector<Number> &, 01800 std::vector<Tensor>&) const; 01801 01802 01803 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01804 template void FEMContext::side_hessian<Tensor>(unsigned int, unsigned int, Tensor&) const; 01805 template void FEMContext::side_hessians<Tensor>(unsigned int, const NumericVector<Number> &, 01806 std::vector<Tensor>&) const; 01807 //FIXME: Not everything is implemented yet for second derivatives of RealGradients 01808 //template void FEMContext::side_hessian<??>(unsigned int, unsigned int, 01809 // ??&) const; 01810 //template void FEMContext::side_hessians<??>(unsigned int, const NumericVector<Number> &, 01811 // std::vector<??>&) const; 01812 #endif 01813 01814 template void FEMContext::point_value<Number>(unsigned int, const Point&, Number&) const; 01815 template void FEMContext::point_value<Gradient>(unsigned int, const Point&, Gradient&) const; 01816 01817 template void FEMContext::point_gradient<Gradient>(unsigned int, const Point&, Gradient&) const; 01818 template void FEMContext::point_gradient<Tensor>(unsigned int, const Point&, Tensor&) const; 01819 01820 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01821 template void FEMContext::point_hessian<Tensor>(unsigned int, const Point&, Tensor&) const; 01822 //FIXME: Not everything is implemented yet for second derivatives of RealGradients 01823 //template void FEMContext::point_hessian<??>(unsigned int, const Point&, ??&) const; 01824 #endif 01825 01826 template void FEMContext::fixed_interior_value<Number>(unsigned int, unsigned int, Number&) const; 01827 template void FEMContext::fixed_interior_value<Gradient>(unsigned int, unsigned int, Gradient&) const; 01828 01829 template void FEMContext::fixed_interior_gradient<Gradient>(unsigned int, unsigned int, Gradient&) const; 01830 template void FEMContext::fixed_interior_gradient<Tensor>(unsigned int, unsigned int, Tensor&) const; 01831 01832 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01833 template void FEMContext::fixed_interior_hessian<Tensor>(unsigned int, unsigned int, Tensor&) const; 01834 //FIXME: Not everything is implemented yet for second derivatives of RealGradients 01835 //template void FEMContext::fixed_interior_hessian<??>(unsigned int, unsigned int, ??&) const; 01836 #endif 01837 01838 template void FEMContext::fixed_side_value<Number>(unsigned int, unsigned int, Number&) const; 01839 template void FEMContext::fixed_side_value<Gradient>(unsigned int, unsigned int, Gradient&) const; 01840 01841 template void FEMContext::fixed_side_gradient<Gradient>(unsigned int, unsigned int, Gradient&) const; 01842 template void FEMContext::fixed_side_gradient<Tensor>(unsigned int, unsigned int, Tensor&) const; 01843 01844 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01845 template void FEMContext::fixed_side_hessian<Tensor>(unsigned int, unsigned int, Tensor&) const; 01846 //FIXME: Not everything is implemented yet for second derivatives of RealGradients 01847 //template void FEMContext::fixed_side_hessian<??>(unsigned int, unsigned int, ??&) const; 01848 #endif 01849 01850 template void FEMContext::fixed_point_value<Number>(unsigned int, const Point&, Number&) const; 01851 template void FEMContext::fixed_point_value<Gradient>(unsigned int, const Point&, Gradient&) const; 01852 01853 template void FEMContext::fixed_point_gradient<Gradient>(unsigned int, const Point&, Gradient&) const; 01854 template void FEMContext::fixed_point_gradient<Tensor>(unsigned int, const Point&, Tensor&) const; 01855 01856 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 01857 template void FEMContext::fixed_point_hessian<Tensor>(unsigned int, const Point&, Tensor&) const; 01858 //FIXME: Not everything is implemented yet for second derivatives of RealGradients 01859 //template void FEMContext::fixed_point_hessian<??>(unsigned int, const Point&, ??&) const; 01860 #endif 01861 01862 template AutoPtr<FEGenericBase<Real> > FEMContext::build_new_fe( const FEGenericBase<Real>*, const Point & ) const; 01863 template AutoPtr<FEGenericBase<RealGradient> > FEMContext::build_new_fe( const FEGenericBase<RealGradient>*, const Point & ) const; 01864 01865 01866 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:47 UTC
Hosted By: