$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 00022 00023 // Local includes 00024 #include "libmesh/libmesh_config.h" 00025 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 00026 #include "libmesh/inf_fe.h" 00027 #include "libmesh/inf_fe_macro.h" 00028 #include "libmesh/quadrature.h" 00029 #include "libmesh/elem.h" 00030 00031 namespace libMesh 00032 { 00033 00034 00035 00036 00037 //------------------------------------------------------- 00038 // Method for 2D, 3D -- see inf_fe_1D.C for a 1D version of this 00039 template <unsigned int Dim, FEFamily T_radial, InfMapType T_base> 00040 void InfFE<Dim,T_radial,T_base>::reinit(const Elem* inf_elem, 00041 const unsigned int s, 00042 const Real tolerance, 00043 const std::vector<Point>* const pts, 00044 const std::vector<Real>* const weights) 00045 { 00046 if (weights != NULL) 00047 libmesh_not_implemented_msg("ERROR: User-specified weights for infinite elements are not implemented!"); 00048 00049 if (pts != NULL) 00050 libmesh_not_implemented_msg("ERROR: User-specified points for infinite elements are not implemented!"); 00051 00052 // We don't do this for 1D elements! 00053 libmesh_assert_not_equal_to (Dim, 1); 00054 00055 libmesh_assert(inf_elem); 00056 libmesh_assert(qrule); 00057 00058 // Don't do this for the base 00059 libmesh_assert_not_equal_to (s, 0); 00060 00061 // Build the side of interest 00062 const UniquePtr<Elem> side(inf_elem->build_side(s)); 00063 00064 // set the element type 00065 elem_type = inf_elem->type(); 00066 00067 // eventually initialize radial quadrature rule 00068 bool radial_qrule_initialized = false; 00069 00070 if (current_fe_type.radial_order != fe_type.radial_order) 00071 { 00072 current_fe_type.radial_order = fe_type.radial_order; 00073 radial_qrule->init(EDGE2, inf_elem->p_level()); 00074 radial_qrule_initialized = true; 00075 } 00076 00077 // Initialize the face shape functions 00078 if (this->get_type() != inf_elem->type() || 00079 base_fe->shapes_need_reinit() || 00080 radial_qrule_initialized) 00081 this->init_face_shape_functions (qrule->get_points(), side.get()); 00082 00083 00084 // compute the face map 00085 this->_fe_map->compute_face_map(this->dim, _total_qrule_weights, side.get()); 00086 00087 // make a copy of the Jacobian for integration 00088 const std::vector<Real> JxW_int(this->_fe_map->get_JxW()); 00089 00090 // Find where the integration points are located on the 00091 // full element. 00092 std::vector<Point> qp; this->inverse_map (inf_elem, this->_fe_map->get_xyz(), 00093 qp, tolerance); 00094 00095 // compute the shape function and derivative values 00096 // at the points qp 00097 this->reinit (inf_elem, &qp); 00098 00099 // copy back old data 00100 this->_fe_map->get_JxW() = JxW_int; 00101 00102 } 00103 00104 00105 00106 //------------------------------------------------------- 00107 // Method for 2D, 3D -- see inf_fe_1D.C for a 1D version of this 00108 template <unsigned int Dim, FEFamily T_radial, InfMapType T_base> 00109 void InfFE<Dim,T_radial,T_base>::edge_reinit(const Elem*, 00110 const unsigned int, 00111 const Real, 00112 const std::vector<Point>* const pts, 00113 const std::vector<Real>* const /*weights*/) 00114 { 00115 // We don't do this for 1D elements! 00116 //libmesh_assert_not_equal_to (Dim, 1); 00117 libmesh_not_implemented_msg("ERROR: Edge conditions for infinite elements not implemented!"); 00118 00119 if (pts != NULL) 00120 libmesh_not_implemented_msg("ERROR: User-specified points for infinite elements not implemented!"); 00121 } 00122 00123 00124 00125 00126 template <unsigned int Dim, FEFamily T_radial, InfMapType T_base> 00127 void InfFE<Dim,T_radial,T_base>::init_face_shape_functions(const std::vector<Point>&, 00128 const Elem* inf_side) 00129 { 00130 libmesh_assert(inf_side); 00131 00132 // Currently, this makes only sense in 3-D! 00133 libmesh_assert_equal_to (Dim, 3); 00134 00135 // Initialiize the radial shape functions 00136 this->init_radial_shape_functions(inf_side); 00137 00138 // Initialize the base shape functions 00139 this->update_base_elem(inf_side); 00140 00141 // Initialize the base quadratur rule 00142 base_qrule->init(base_elem->type(), inf_side->p_level()); 00143 00144 // base_fe still corresponds to the (dim-1)-dimensional base of the InfFE object, 00145 // so update the fe_base. 00146 { 00147 libmesh_assert_equal_to (Dim, 3); 00148 00149 UniquePtr<FEBase> ap_fb(FEBase::build(Dim-2, this->fe_type)); 00150 00151 delete base_fe; 00152 base_fe = ap_fb.release(); 00153 base_fe->attach_quadrature_rule(base_qrule); 00154 } 00155 00156 // initialize the shape functions on the base 00157 base_fe->init_base_shape_functions(base_fe->qrule->get_points(), 00158 base_elem); 00159 00160 // the number of quadrature points 00161 const unsigned int n_radial_qp = 00162 cast_int<unsigned int>(som.size()); 00163 const unsigned int n_base_qp = base_qrule->n_points(); 00164 const unsigned int n_total_qp = n_radial_qp * n_base_qp; 00165 00166 // the quadratur weigths 00167 _total_qrule_weights.resize(n_total_qp); 00168 00169 // now inite the shapes for boundary work 00170 { 00171 00172 // The element type and order to use in the base map 00173 const Order base_mapping_order ( base_elem->default_order() ); 00174 const ElemType base_mapping_elem_type ( base_elem->type() ); 00175 00176 // the number of mapping shape functions 00177 // (Lagrange shape functions are used for mapping in the base) 00178 const unsigned int n_radial_mapping_sf = 00179 cast_int<unsigned int>(radial_map.size()); 00180 const unsigned int n_base_mapping_shape_functions = Base::n_base_mapping_sf(base_mapping_elem_type, 00181 base_mapping_order); 00182 00183 const unsigned int n_total_mapping_shape_functions = 00184 n_radial_mapping_sf * n_base_mapping_shape_functions; 00185 00186 00187 // initialize the node and shape numbering maps 00188 { 00189 _radial_node_index.resize (n_total_mapping_shape_functions); 00190 _base_node_index.resize (n_total_mapping_shape_functions); 00191 00192 const ElemType inf_face_elem_type (inf_side->type()); 00193 00194 // fill the node index map 00195 for (unsigned int n=0; n<n_total_mapping_shape_functions; n++) 00196 { 00197 compute_node_indices (inf_face_elem_type, 00198 n, 00199 _base_node_index[n], 00200 _radial_node_index[n]); 00201 00202 libmesh_assert_less (_base_node_index[n], n_base_mapping_shape_functions); 00203 libmesh_assert_less (_radial_node_index[n], n_radial_mapping_sf); 00204 } 00205 00206 } 00207 00208 // rezise map data fields 00209 { 00210 std::vector<std::vector<Real> >& psi_map = this->_fe_map->get_psi(); 00211 std::vector<std::vector<Real> >& dpsidxi_map = this->_fe_map->get_dpsidxi(); 00212 std::vector<std::vector<Real> >& d2psidxi2_map = this->_fe_map->get_d2psidxi2(); 00213 psi_map.resize (n_total_mapping_shape_functions); 00214 dpsidxi_map.resize (n_total_mapping_shape_functions); 00215 d2psidxi2_map.resize (n_total_mapping_shape_functions); 00216 00217 // if (Dim == 3) 00218 { 00219 std::vector<std::vector<Real> >& dpsideta_map = this->_fe_map->get_dpsideta(); 00220 std::vector<std::vector<Real> >& d2psidxideta_map = this->_fe_map->get_d2psidxideta(); 00221 std::vector<std::vector<Real> >& d2psideta2_map = this->_fe_map->get_d2psideta2(); 00222 dpsideta_map.resize (n_total_mapping_shape_functions); 00223 d2psidxideta_map.resize (n_total_mapping_shape_functions); 00224 d2psideta2_map.resize (n_total_mapping_shape_functions); 00225 } 00226 00227 for (unsigned int i=0; i<n_total_mapping_shape_functions; i++) 00228 { 00229 psi_map[i].resize (n_total_qp); 00230 dpsidxi_map[i].resize (n_total_qp); 00231 d2psidxi2_map[i].resize (n_total_qp); 00232 00233 // if (Dim == 3) 00234 { 00235 std::vector<std::vector<Real> >& dpsideta_map = this->_fe_map->get_dpsideta(); 00236 std::vector<std::vector<Real> >& d2psidxideta_map = this->_fe_map->get_d2psidxideta(); 00237 std::vector<std::vector<Real> >& d2psideta2_map = this->_fe_map->get_d2psideta2(); 00238 dpsideta_map[i].resize (n_total_qp); 00239 d2psidxideta_map[i].resize (n_total_qp); 00240 d2psideta2_map[i].resize (n_total_qp); 00241 } 00242 } 00243 } 00244 00245 00246 // compute shape maps 00247 { 00248 const std::vector<std::vector<Real> >& S_map = (base_fe->get_fe_map()).get_phi_map(); 00249 const std::vector<std::vector<Real> >& Ss_map = (base_fe->get_fe_map()).get_dphidxi_map(); 00250 00251 std::vector<std::vector<Real> >& psi_map = this->_fe_map->get_psi(); 00252 std::vector<std::vector<Real> >& dpsidxi_map = this->_fe_map->get_dpsidxi(); 00253 std::vector<std::vector<Real> >& dpsideta_map = this->_fe_map->get_dpsideta(); 00254 00255 for (unsigned int rp=0; rp<n_radial_qp; rp++) // over radial qp's 00256 for (unsigned int bp=0; bp<n_base_qp; bp++) // over base qp's 00257 for (unsigned int ti=0; ti<n_total_mapping_shape_functions; ti++) // over all mapping shapes 00258 { 00259 // let the index vectors take care of selecting the appropriate base/radial mapping shape 00260 const unsigned int bi = _base_node_index [ti]; 00261 const unsigned int ri = _radial_node_index[ti]; 00262 psi_map [ti][bp+rp*n_base_qp] = S_map [bi][bp] * radial_map [ri][rp]; 00263 dpsidxi_map [ti][bp+rp*n_base_qp] = Ss_map[bi][bp] * radial_map [ri][rp]; 00264 dpsideta_map [ti][bp+rp*n_base_qp] = S_map [bi][bp] * dradialdv_map[ri][rp]; 00265 00266 // second derivatives are not implemented for infinite elements 00267 // d2psidxi2_map [ti][bp+rp*n_base_qp] = 0.; 00268 // d2psidxideta_map [ti][bp+rp*n_base_qp] = 0.; 00269 // d2psideta2_map [ti][bp+rp*n_base_qp] = 0.; 00270 } 00271 00272 } 00273 00274 } 00275 00276 // quadrature rule weights 00277 { 00278 const std::vector<Real>& radial_qw = radial_qrule->get_weights(); 00279 const std::vector<Real>& base_qw = base_qrule->get_weights(); 00280 00281 libmesh_assert_equal_to (radial_qw.size(), n_radial_qp); 00282 libmesh_assert_equal_to (base_qw.size(), n_base_qp); 00283 00284 for (unsigned int rp=0; rp<n_radial_qp; rp++) 00285 for (unsigned int bp=0; bp<n_base_qp; bp++) 00286 { 00287 _total_qrule_weights[ bp+rp*n_base_qp ] = radial_qw[rp] * base_qw[bp]; 00288 } 00289 } 00290 00291 } 00292 00293 00294 00295 00296 //-------------------------------------------------------------- 00297 // Explicit instantiations - doesn't make sense in 1D, but as 00298 // long as we only return errors, we are fine... ;-) 00299 //#include "libmesh/inf_fe_instantiate_1D.h" 00300 //#include "libmesh/inf_fe_instantiate_2D.h" 00301 //#include "libmesh/inf_fe_instantiate_3D.h" 00302 INSTANTIATE_INF_FE_MBRF(1,CARTESIAN,void,reinit(const Elem*,const unsigned int, const Real, const std::vector<Point>* const, const std::vector<Real>* const)); 00303 INSTANTIATE_INF_FE_MBRF(2,CARTESIAN,void,reinit(const Elem*,const unsigned int, const Real, const std::vector<Point>* const, const std::vector<Real>* const)); 00304 INSTANTIATE_INF_FE_MBRF(3,CARTESIAN,void,reinit(const Elem*,const unsigned int, const Real, const std::vector<Point>* const, const std::vector<Real>* const)); 00305 INSTANTIATE_INF_FE_MBRF(1,CARTESIAN,void,edge_reinit(const Elem*,const unsigned int, const Real, const std::vector<Point>* const, const std::vector<Real>* const)); 00306 INSTANTIATE_INF_FE_MBRF(2,CARTESIAN,void,edge_reinit(const Elem*,const unsigned int, const Real, const std::vector<Point>* const, const std::vector<Real>* const)); 00307 INSTANTIATE_INF_FE_MBRF(3,CARTESIAN,void,edge_reinit(const Elem*,const unsigned int, const Real, const std::vector<Point>* const, const std::vector<Real>* const)); 00308 INSTANTIATE_INF_FE_MBRF(1,CARTESIAN,void,init_face_shape_functions(const std::vector<Point>&,const Elem*)); 00309 INSTANTIATE_INF_FE_MBRF(2,CARTESIAN,void,init_face_shape_functions(const std::vector<Point>&,const Elem*)); 00310 INSTANTIATE_INF_FE_MBRF(3,CARTESIAN,void,init_face_shape_functions(const std::vector<Point>&,const Elem*)); 00311 00312 } // namespace libMesh 00313 00314 #endif //ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS