$extrastylesheet
inf_fe_boundary.C
Go to the documentation of this file.
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