$extrastylesheet
inf_fe.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 // Local includes
00021 #include "libmesh/libmesh_config.h"
00022 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
00023 #include "libmesh/inf_fe.h"
00024 #include "libmesh/quadrature_gauss.h"
00025 #include "libmesh/elem.h"
00026 #include "libmesh/libmesh_logging.h"
00027 
00028 namespace libMesh
00029 {
00030 
00031 
00032 
00033 // ------------------------------------------------------------
00034 // InfFE class members
00035 
00036 
00037 
00038 // Constructor
00039 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
00040 InfFE<Dim,T_radial,T_map>::InfFE (const FEType& fet) :
00041   FEBase       (Dim, fet),
00042 
00043   _n_total_approx_sf (0),
00044   _n_total_qp        (0),
00045 
00046   base_qrule   (NULL),
00047   radial_qrule (NULL),
00048   base_elem    (NULL),
00049   base_fe      (NULL),
00050 
00051   // initialize the current_fe_type to all the same
00052   // values as \p fet (since the FE families and coordinate
00053   // map type should @e not change), but use an invalid order
00054   // for the radial part (since this is the only order
00055   // that may change!).
00056   // the data structures like \p phi etc are not initialized
00057   // through the constructor, but throught reinit()
00058   current_fe_type ( FEType(fet.order,
00059                            fet.family,
00060                            INVALID_ORDER,
00061                            fet.radial_family,
00062                            fet.inf_map) )
00063 
00064 {
00065   // Sanity checks
00066   libmesh_assert_equal_to (T_radial, fe_type.radial_family);
00067   libmesh_assert_equal_to (T_map, fe_type.inf_map);
00068 
00069   // build the base_fe object, handle the UniquePtr
00070   if (Dim != 1)
00071     {
00072       UniquePtr<FEBase> ap_fb(FEBase::build(Dim-1, fet));
00073       base_fe = ap_fb.release();
00074     }
00075 }
00076 
00077 
00078 
00079 
00080 // Destructor
00081 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
00082 InfFE<Dim,T_radial,T_map>::~InfFE ()
00083 {
00084   // delete pointers, if necessary
00085   delete base_qrule;
00086   base_qrule = NULL;
00087 
00088   delete radial_qrule;
00089   radial_qrule = NULL;
00090 
00091   delete base_elem;
00092   base_elem = NULL;
00093 
00094   delete base_fe;
00095   base_fe = NULL;
00096 }
00097 
00098 
00099 
00100 
00101 
00102 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
00103 void InfFE<Dim,T_radial,T_map>:: attach_quadrature_rule (QBase* q)
00104 {
00105   libmesh_assert(q);
00106   libmesh_assert(base_fe);
00107 
00108   const Order base_int_order   = q->get_order();
00109   const Order radial_int_order = static_cast<Order>(2 * (static_cast<unsigned int>(fe_type.radial_order) + 1) +2);
00110   const unsigned int qrule_dim = q->get_dim();
00111 
00112   if (Dim != 1)
00113     {
00114       // build a Dim-1 quadrature rule of the type that we received
00115       UniquePtr<QBase> apq( QBase::build(q->type(), qrule_dim-1, base_int_order) );
00116       base_qrule = apq.release();
00117       base_fe->attach_quadrature_rule(base_qrule);
00118     }
00119 
00120   // in radial direction, always use Gauss quadrature
00121   radial_qrule = new QGauss(1, radial_int_order);
00122 
00123   // currently not used. But maybe helpful to store the QBase*
00124   // with which we initialized our own quadrature rules
00125   qrule = q;
00126 }
00127 
00128 
00129 
00130 
00131 
00132 template <unsigned int Dim, FEFamily T_radial, InfMapType T_base>
00133 void InfFE<Dim,T_radial,T_base>::update_base_elem (const Elem* inf_elem)
00134 {
00135   if (base_elem != NULL)
00136     delete base_elem;
00137   base_elem = Base::build_elem(inf_elem);
00138 }
00139 
00140 
00141 
00142 
00143 
00144 
00145 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
00146 void InfFE<Dim,T_radial,T_map>::reinit(const Elem* inf_elem,
00147                                        const std::vector<Point>* const pts,
00148                                        const std::vector<Real>* const weights)
00149 {
00150   libmesh_assert(base_fe);
00151   libmesh_assert(base_fe->qrule);
00152   libmesh_assert_equal_to (base_fe->qrule, base_qrule);
00153   libmesh_assert(radial_qrule);
00154   libmesh_assert(inf_elem);
00155 
00156   if (pts == NULL)
00157     {
00158       bool init_shape_functions_required = false;
00159 
00160       // -----------------------------------------------------------------
00161       // init the radial data fields only when the radial order changes
00162       if (current_fe_type.radial_order != fe_type.radial_order)
00163         {
00164           current_fe_type.radial_order = fe_type.radial_order;
00165 
00166           // Watch out: this call to QBase->init() only works for
00167           // current_fe_type = const!   To allow variable Order,
00168           // the init() of QBase has to be modified...
00169           radial_qrule->init(EDGE2);
00170 
00171           // initialize the radial shape functions
00172           this->init_radial_shape_functions(inf_elem);
00173 
00174           init_shape_functions_required=true;
00175         }
00176 
00177 
00178       bool update_base_elem_required=true;
00179 
00180       // -----------------------------------------------------------------
00181       // update the type in accordance to the current cell
00182       // and reinit if the cell type has changed or (as in
00183       // the case of the hierarchics) the shape functions
00184       // depend on the particular element and need a reinit
00185       if (  ( Dim != 1) &&
00186             (  (this->get_type() != inf_elem->type())  ||
00187                (base_fe->shapes_need_reinit())  )  )
00188         {
00189           // store the new element type, update base_elem
00190           // here.  Through \p update_base_elem_required,
00191           // remember whether it has to be updated (see below).
00192           elem_type = inf_elem->type();
00193           this->update_base_elem(inf_elem);
00194           update_base_elem_required=false;
00195 
00196           // initialize the base quadrature rule for the new element
00197           base_qrule->init(base_elem->type());
00198 
00199           // initialize the shape functions in the base
00200           base_fe->init_base_shape_functions(base_fe->qrule->get_points(),
00201                                              base_elem);
00202 
00203           init_shape_functions_required=true;
00204         }
00205 
00206 
00207       // when either the radial or base part change,
00208       // we have to init the whole fields
00209       if (init_shape_functions_required)
00210         this->init_shape_functions (inf_elem);
00211 
00212       // computing the distance only works when we have the current
00213       // base_elem stored.  This happens when fe_type is const,
00214       // the inf_elem->type remains the same.  Then we have to
00215       // update the base elem _here_.
00216       if (update_base_elem_required)
00217         this->update_base_elem(inf_elem);
00218 
00219       // compute dist (depends on geometry, therefore has to be updated for
00220       // each and every new element), throw radial and base part together
00221       this->combine_base_radial (inf_elem);
00222 
00223       this->_fe_map->compute_map (this->dim,_total_qrule_weights, inf_elem);
00224 
00225       // Compute the shape functions and the derivatives
00226       // at all quadrature points.
00227       this->compute_shape_functions (inf_elem,base_fe->qrule->get_points());
00228     }
00229 
00230   else // if pts != NULL
00231     {
00232       // update the elem_type
00233       elem_type = inf_elem->type();
00234 
00235       // init radial shapes
00236       this->init_radial_shape_functions(inf_elem);
00237 
00238       // update the base
00239       this->update_base_elem(inf_elem);
00240 
00241       // the finite element on the ifem base
00242       {
00243         UniquePtr<FEBase> ap_fb(FEBase::build(Dim-1, this->fe_type));
00244         if (base_fe != NULL)
00245           delete base_fe;
00246         base_fe = ap_fb.release();
00247       }
00248 
00249       // inite base shapes
00250       base_fe->init_base_shape_functions(*pts,
00251                                          base_elem);
00252 
00253       this->init_shape_functions (inf_elem);
00254 
00255       // combine the base and radial shapes
00256       this->combine_base_radial (inf_elem);
00257 
00258       // weights
00259       if (weights != NULL)
00260         {
00261           this->_fe_map->compute_map (this->dim, *weights, inf_elem);
00262         }
00263       else
00264         {
00265           std::vector<Real> dummy_weights (pts->size(), 1.);
00266           this->_fe_map->compute_map (this->dim, dummy_weights, inf_elem);
00267         }
00268 
00269       // finally compute the ifem shapes
00270       this->compute_shape_functions (inf_elem,*pts);
00271     }
00272 
00273 }
00274 
00275 
00276 
00277 
00278 
00279 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
00280 void InfFE<Dim,T_radial,T_map>::init_radial_shape_functions(const Elem* libmesh_dbg_var(inf_elem))
00281 {
00282   libmesh_assert(radial_qrule);
00283   libmesh_assert(inf_elem);
00284 
00285 
00289   START_LOG("init_radial_shape_functions()", "InfFE");
00290 
00291 
00292   // -----------------------------------------------------------------
00293   // initialize most of the things related to mapping
00294 
00295   // The order to use in the radial map (currently independent of the element type)
00296   const Order        radial_mapping_order             (Radial::mapping_order());
00297   const unsigned int n_radial_mapping_shape_functions (Radial::n_dofs(radial_mapping_order));
00298 
00299 
00300 
00301   // -----------------------------------------------------------------
00302   // initialize most of the things related to physical approximation
00303 
00304   const Order        radial_approx_order             (fe_type.radial_order);
00305   const unsigned int n_radial_approx_shape_functions (Radial::n_dofs(radial_approx_order));
00306 
00307   const unsigned int        n_radial_qp = radial_qrule->n_points();
00308   const std::vector<Point>&   radial_qp = radial_qrule->get_points();
00309 
00310 
00311 
00312   // -----------------------------------------------------------------
00313   // resize the radial data fields
00314 
00315   mode.resize      (n_radial_approx_shape_functions);       // the radial polynomials (eval)
00316   dmodedv.resize   (n_radial_approx_shape_functions);
00317 
00318   som.resize       (n_radial_qp);                           // the (1-v)/2 weight
00319   dsomdv.resize    (n_radial_qp);
00320 
00321   radial_map.resize    (n_radial_mapping_shape_functions);  // the radial map
00322   dradialdv_map.resize (n_radial_mapping_shape_functions);
00323 
00324 
00325   for (unsigned int i=0; i<n_radial_mapping_shape_functions; i++)
00326     {
00327       radial_map[i].resize    (n_radial_qp);
00328       dradialdv_map[i].resize (n_radial_qp);
00329     }
00330 
00331 
00332   for (unsigned int i=0; i<n_radial_approx_shape_functions; i++)
00333     {
00334       mode[i].resize    (n_radial_qp);
00335       dmodedv[i].resize (n_radial_qp);
00336     }
00337 
00338 
00339   // compute scalar values at radial quadrature points
00340   for (unsigned int p=0; p<n_radial_qp; p++)
00341     {
00342       som[p]       = Radial::decay       (radial_qp[p](0));
00343       dsomdv[p]    = Radial::decay_deriv (radial_qp[p](0));
00344     }
00345 
00346 
00347   // evaluate the mode shapes in radial direction at radial quadrature points
00348   for (unsigned int i=0; i<n_radial_approx_shape_functions; i++)
00349     for (unsigned int p=0; p<n_radial_qp; p++)
00350       {
00351         mode[i][p]    = InfFE<Dim,T_radial,T_map>::eval       (radial_qp[p](0), radial_approx_order, i);
00352         dmodedv[i][p] = InfFE<Dim,T_radial,T_map>::eval_deriv (radial_qp[p](0), radial_approx_order, i);
00353       }
00354 
00355 
00356   // evaluate the mapping functions in radial direction at radial quadrature points
00357   for (unsigned int i=0; i<n_radial_mapping_shape_functions; i++)
00358     for (unsigned int p=0; p<n_radial_qp; p++)
00359       {
00360         radial_map[i][p]    = InfFE<Dim,INFINITE_MAP,T_map>::eval       (radial_qp[p](0), radial_mapping_order, i);
00361         dradialdv_map[i][p] = InfFE<Dim,INFINITE_MAP,T_map>::eval_deriv (radial_qp[p](0), radial_mapping_order, i);
00362       }
00363 
00367   STOP_LOG("init_radial_shape_functions()", "InfFE");
00368 
00369 }
00370 
00371 
00372 
00373 
00374 
00375 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
00376 void InfFE<Dim,T_radial,T_map>::init_shape_functions(const Elem* inf_elem)
00377 {
00378   libmesh_assert(inf_elem);
00379 
00380 
00381   // Start logging the radial shape function initialization
00382   START_LOG("init_shape_functions()", "InfFE");
00383 
00384 
00385   // -----------------------------------------------------------------
00386   // fast access to some const int's for the radial data
00387   const unsigned int n_radial_mapping_sf =
00388     cast_int<unsigned int>(radial_map.size());
00389   const unsigned int n_radial_approx_sf  =
00390     cast_int<unsigned int>(mode.size());
00391   const unsigned int n_radial_qp         =
00392     cast_int<unsigned int>(som.size());
00393 
00394 
00395   // -----------------------------------------------------------------
00396   // initialize most of the things related to mapping
00397 
00398   // The element type and order to use in the base map
00399   const Order    base_mapping_order     ( base_elem->default_order() );
00400   const ElemType base_mapping_elem_type ( base_elem->type()          );
00401 
00402   // the number of base shape functions used to construct the map
00403   // (Lagrange shape functions are used for mapping in the base)
00404   unsigned int n_base_mapping_shape_functions = Base::n_base_mapping_sf(base_mapping_elem_type,
00405                                                                         base_mapping_order);
00406 
00407   const unsigned int n_total_mapping_shape_functions =
00408     n_radial_mapping_sf * n_base_mapping_shape_functions;
00409 
00410 
00411 
00412   // -----------------------------------------------------------------
00413   // initialize most of the things related to physical approximation
00414 
00415   unsigned int n_base_approx_shape_functions;
00416   if (Dim > 1)
00417     n_base_approx_shape_functions = base_fe->n_shape_functions();
00418   else
00419     n_base_approx_shape_functions = 1;
00420 
00421 
00422   const unsigned int n_total_approx_shape_functions =
00423     n_radial_approx_sf * n_base_approx_shape_functions;
00424 
00425   // update class member field
00426   _n_total_approx_sf = n_total_approx_shape_functions;
00427 
00428 
00429   // The number of the base quadrature points.
00430   const unsigned int        n_base_qp =  base_qrule->n_points();
00431 
00432   // The total number of quadrature points.
00433   const unsigned int        n_total_qp =  n_radial_qp * n_base_qp;
00434 
00435 
00436   // update class member field
00437   _n_total_qp = n_total_qp;
00438 
00439 
00440 
00441   // -----------------------------------------------------------------
00442   // initialize the node and shape numbering maps
00443   {
00444     // these vectors work as follows: the i-th entry stores
00445     // the associated base/radial node number
00446     _radial_node_index.resize    (n_total_mapping_shape_functions);
00447     _base_node_index.resize      (n_total_mapping_shape_functions);
00448 
00449     // similar for the shapes: the i-th entry stores
00450     // the associated base/radial shape number
00451     _radial_shape_index.resize   (n_total_approx_shape_functions);
00452     _base_shape_index.resize     (n_total_approx_shape_functions);
00453 
00454     const ElemType inf_elem_type (inf_elem->type());
00455 
00456     // fill the node index map
00457     for (unsigned int n=0; n<n_total_mapping_shape_functions; n++)
00458       {
00459         compute_node_indices (inf_elem_type,
00460                               n,
00461                               _base_node_index[n],
00462                               _radial_node_index[n]);
00463         libmesh_assert_less (_base_node_index[n], n_base_mapping_shape_functions);
00464         libmesh_assert_less (_radial_node_index[n], n_radial_mapping_sf);
00465       }
00466 
00467     // fill the shape index map
00468     for (unsigned int n=0; n<n_total_approx_shape_functions; n++)
00469       {
00470         compute_shape_indices (this->fe_type,
00471                                inf_elem_type,
00472                                n,
00473                                _base_shape_index[n],
00474                                _radial_shape_index[n]);
00475         libmesh_assert_less (_base_shape_index[n], n_base_approx_shape_functions);
00476         libmesh_assert_less (_radial_shape_index[n], n_radial_approx_sf);
00477       }
00478   }
00479 
00480 
00481 
00482 
00483 
00484   // -----------------------------------------------------------------
00485   // resize the base data fields
00486   dist.resize(n_base_mapping_shape_functions);
00487 
00488 
00489 
00490   // -----------------------------------------------------------------
00491   // resize the total data fields
00492 
00493   // the phase term varies with xi, eta and zeta(v): store it for _all_ qp
00494   //
00495   // when computing the phase, we need the base approximations
00496   // therefore, initialize the phase here, but evaluate it
00497   // in combine_base_radial().
00498   //
00499   // the weight, though, is only needed at the radial quadrature points, n_radial_qp.
00500   // but for a uniform interface to the protected data fields
00501   // the weight data field (which are accessible from the outside) are expanded to n_total_qp.
00502   weight.resize      (n_total_qp);
00503   dweightdv.resize   (n_total_qp);
00504   dweight.resize     (n_total_qp);
00505 
00506   dphase.resize      (n_total_qp);
00507   dphasedxi.resize   (n_total_qp);
00508   dphasedeta.resize  (n_total_qp);
00509   dphasedzeta.resize (n_total_qp);
00510 
00511   // this vector contains the integration weights for the combined quadrature rule
00512   _total_qrule_weights.resize(n_total_qp);
00513 
00514 
00515   // -----------------------------------------------------------------
00516   // InfFE's data fields phi, dphi, dphidx, phi_map etc hold the _total_
00517   // shape and mapping functions, respectively
00518   {
00519     phi.resize     (n_total_approx_shape_functions);
00520     dphi.resize    (n_total_approx_shape_functions);
00521     dphidx.resize  (n_total_approx_shape_functions);
00522     dphidy.resize  (n_total_approx_shape_functions);
00523     dphidz.resize  (n_total_approx_shape_functions);
00524     dphidxi.resize (n_total_approx_shape_functions);
00525 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00526     libmesh_do_once(libMesh::err << "Second derivatives for Infinite elements"
00527                     << " are not yet implemented!"
00528                     << std::endl);
00529 
00530     d2phi.resize     (n_total_approx_shape_functions);
00531     d2phidx2.resize  (n_total_approx_shape_functions);
00532     d2phidxdy.resize (n_total_approx_shape_functions);
00533     d2phidxdz.resize (n_total_approx_shape_functions);
00534     d2phidy2.resize  (n_total_approx_shape_functions);
00535     d2phidydz.resize (n_total_approx_shape_functions);
00536     d2phidz2.resize  (n_total_approx_shape_functions);
00537     d2phidxi2.resize (n_total_approx_shape_functions);
00538 
00539     if (Dim > 1)
00540       {
00541         d2phidxideta.resize   (n_total_approx_shape_functions);
00542         d2phideta2.resize     (n_total_approx_shape_functions);
00543       }
00544 
00545     if (Dim > 2)
00546       {
00547         d2phidetadzeta.resize (n_total_approx_shape_functions);
00548         d2phidxidzeta.resize  (n_total_approx_shape_functions);
00549         d2phidzeta2.resize    (n_total_approx_shape_functions);
00550       }
00551 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00552 
00553     if (Dim > 1)
00554       dphideta.resize      (n_total_approx_shape_functions);
00555 
00556     if (Dim == 3)
00557       dphidzeta.resize     (n_total_approx_shape_functions);
00558 
00559 
00560 
00561     std::vector<std::vector<Real> >& phi_map = this->_fe_map->get_phi_map();
00562     std::vector<std::vector<Real> >& dphidxi_map = this->_fe_map->get_dphidxi_map();
00563 
00564     phi_map.resize         (n_total_mapping_shape_functions);
00565     dphidxi_map.resize     (n_total_mapping_shape_functions);
00566 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00567     std::vector<std::vector<Real> >& d2phidxi2_map = this->_fe_map->get_d2phidxi2_map();
00568     d2phidxi2_map.resize   (n_total_mapping_shape_functions);
00569 
00570     if (Dim > 1)
00571       {
00572         std::vector<std::vector<Real> >& d2phidxideta_map = this->_fe_map->get_d2phidxideta_map();
00573         std::vector<std::vector<Real> >& d2phideta2_map = this->_fe_map->get_d2phideta2_map();
00574         d2phidxideta_map.resize   (n_total_mapping_shape_functions);
00575         d2phideta2_map.resize     (n_total_mapping_shape_functions);
00576       }
00577 
00578     if (Dim == 3)
00579       {
00580         std::vector<std::vector<Real> >& d2phidxidzeta_map = this->_fe_map->get_d2phidxidzeta_map();
00581         std::vector<std::vector<Real> >& d2phidetadzeta_map = this->_fe_map->get_d2phidetadzeta_map();
00582         std::vector<std::vector<Real> >& d2phidzeta2_map = this->_fe_map->get_d2phidzeta2_map();
00583         d2phidxidzeta_map.resize  (n_total_mapping_shape_functions);
00584         d2phidetadzeta_map.resize (n_total_mapping_shape_functions);
00585         d2phidzeta2_map.resize    (n_total_mapping_shape_functions);
00586       }
00587 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00588 
00589     if (Dim > 1)
00590       {
00591         std::vector<std::vector<Real> >& dphideta_map = this->_fe_map->get_dphideta_map();
00592         dphideta_map.resize  (n_total_mapping_shape_functions);
00593       }
00594 
00595     if (Dim == 3)
00596       {
00597         std::vector<std::vector<Real> >& dphidzeta_map = this->_fe_map->get_dphidzeta_map();
00598         dphidzeta_map.resize (n_total_mapping_shape_functions);
00599       }
00600   }
00601 
00602 
00603 
00604   // -----------------------------------------------------------------
00605   // collect all the for loops, where inner vectors are
00606   // resized to the appropriate number of quadrature points
00607   {
00608     for (unsigned int i=0; i<n_total_approx_shape_functions; i++)
00609       {
00610         phi[i].resize         (n_total_qp);
00611         dphi[i].resize        (n_total_qp);
00612         dphidx[i].resize      (n_total_qp);
00613         dphidy[i].resize      (n_total_qp);
00614         dphidz[i].resize      (n_total_qp);
00615         dphidxi[i].resize     (n_total_qp);
00616 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00617         d2phi[i].resize       (n_total_qp);
00618         d2phidx2[i].resize    (n_total_qp);
00619         d2phidxdy[i].resize   (n_total_qp);
00620         d2phidxdz[i].resize   (n_total_qp);
00621         d2phidy2[i].resize    (n_total_qp);
00622         d2phidydz[i].resize   (n_total_qp);
00623         d2phidy2[i].resize    (n_total_qp);
00624         d2phidxi2[i].resize   (n_total_qp);
00625 
00626         if (Dim > 1)
00627           {
00628             d2phidxideta[i].resize   (n_total_qp);
00629             d2phideta2[i].resize     (n_total_qp);
00630           }
00631         if (Dim > 2)
00632           {
00633             d2phidxidzeta[i].resize  (n_total_qp);
00634             d2phidetadzeta[i].resize (n_total_qp);
00635             d2phidzeta2[i].resize    (n_total_qp);
00636           }
00637 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00638 
00639         if (Dim > 1)
00640           dphideta[i].resize  (n_total_qp);
00641 
00642         if (Dim == 3)
00643           dphidzeta[i].resize (n_total_qp);
00644 
00645       }
00646 
00647     for (unsigned int i=0; i<n_total_mapping_shape_functions; i++)
00648       {
00649         std::vector<std::vector<Real> >& phi_map = this->_fe_map->get_phi_map();
00650         std::vector<std::vector<Real> >& dphidxi_map = this->_fe_map->get_dphidxi_map();
00651         phi_map[i].resize         (n_total_qp);
00652         dphidxi_map[i].resize     (n_total_qp);
00653 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00654         std::vector<std::vector<Real> >& d2phidxi2_map = this->_fe_map->get_d2phidxi2_map();
00655         d2phidxi2_map[i].resize   (n_total_qp);
00656         if (Dim > 1)
00657           {
00658             std::vector<std::vector<Real> >& d2phidxideta_map = this->_fe_map->get_d2phidxideta_map();
00659             std::vector<std::vector<Real> >& d2phideta2_map = this->_fe_map->get_d2phideta2_map();
00660             d2phidxideta_map[i].resize   (n_total_qp);
00661             d2phideta2_map[i].resize     (n_total_qp);
00662           }
00663 
00664         if (Dim > 2)
00665           {
00666             std::vector<std::vector<Real> >& d2phidxidzeta_map = this->_fe_map->get_d2phidxidzeta_map();
00667             std::vector<std::vector<Real> >& d2phidetadzeta_map = this->_fe_map->get_d2phidetadzeta_map();
00668             std::vector<std::vector<Real> >& d2phidzeta2_map = this->_fe_map->get_d2phidzeta2_map();
00669             d2phidxidzeta_map[i].resize  (n_total_qp);
00670             d2phidetadzeta_map[i].resize (n_total_qp);
00671             d2phidzeta2_map[i].resize    (n_total_qp);
00672           }
00673 #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
00674 
00675         if (Dim > 1)
00676           {
00677             std::vector<std::vector<Real> >& dphideta_map = this->_fe_map->get_dphideta_map();
00678             dphideta_map[i].resize  (n_total_qp);
00679           }
00680 
00681         if (Dim == 3)
00682           {
00683             std::vector<std::vector<Real> >& dphidzeta_map = this->_fe_map->get_dphidzeta_map();
00684             dphidzeta_map[i].resize (n_total_qp);
00685           }
00686       }
00687   }
00688 
00689 
00690 
00691   {
00692     // -----------------------------------------------------------------
00693     // (a) compute scalar values at _all_ quadrature points  -- for uniform
00694     //     access from the outside to these fields
00695     // (b) form a std::vector<Real> which contains the appropriate weights
00696     //     of the combined quadrature rule!
00697     const std::vector<Point>&  radial_qp = radial_qrule->get_points();
00698     libmesh_assert_equal_to (radial_qp.size(), n_radial_qp);
00699 
00700     const std::vector<Real>&   radial_qw = radial_qrule->get_weights();
00701     const std::vector<Real>&   base_qw   = base_qrule->get_weights();
00702     libmesh_assert_equal_to (radial_qw.size(), n_radial_qp);
00703     libmesh_assert_equal_to (base_qw.size(), n_base_qp);
00704 
00705     for (unsigned int rp=0; rp<n_radial_qp; rp++)
00706       for (unsigned int bp=0; bp<n_base_qp; bp++)
00707         {
00708           weight   [ bp+rp*n_base_qp ] = Radial::D       (radial_qp[rp](0));
00709           dweightdv[ bp+rp*n_base_qp ] = Radial::D_deriv (radial_qp[rp](0));
00710 
00711           _total_qrule_weights[  bp+rp*n_base_qp ] = radial_qw[rp] * base_qw[bp];
00712         }
00713   }
00714 
00715 
00719   STOP_LOG("init_shape_functions()", "InfFE");
00720 
00721 }
00722 
00723 
00724 
00725 
00726 
00727 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
00728 void InfFE<Dim,T_radial,T_map>::combine_base_radial(const Elem* inf_elem)
00729 {
00730   libmesh_assert(inf_elem);
00731   // at least check whether the base element type is correct.
00732   // otherwise this version of computing dist would give problems
00733   libmesh_assert_equal_to (base_elem->type(), Base::get_elem_type(inf_elem->type()));
00734 
00735 
00739   START_LOG("combine_base_radial()", "InfFE");
00740 
00741 
00742   // zero  the phase, since it is to be summed up
00743   std::fill (dphasedxi.begin(),   dphasedxi.end(),   0.);
00744   std::fill (dphasedeta.begin(),  dphasedeta.end(),  0.);
00745   std::fill (dphasedzeta.begin(), dphasedzeta.end(), 0.);
00746 
00747 
00748   const unsigned int n_base_mapping_sf =
00749     cast_int<unsigned int>(dist.size());
00750   const Point origin = inf_elem->origin();
00751 
00752   // for each new infinite element, compute the radial distances
00753   for (unsigned int n=0; n<n_base_mapping_sf; n++)
00754     dist[n] =  Point(base_elem->point(n) - origin).size();
00755 
00756 
00757   switch (Dim)
00758     {
00759 
00760       //------------------------------------------------------------
00761       // 1D
00762     case 1:
00763       {
00764         libmesh_not_implemented();
00765         break;
00766       }
00767 
00768 
00769 
00770       //------------------------------------------------------------
00771       // 2D
00772     case 2:
00773       {
00774         libmesh_not_implemented();
00775         break;
00776       }
00777 
00778 
00779 
00780       //------------------------------------------------------------
00781       // 3D
00782     case 3:
00783       {
00784         // fast access to the approximation and mapping shapes of base_fe
00785         const std::vector<std::vector<Real> >& S  = base_fe->phi;
00786         const std::vector<std::vector<Real> >& Ss = base_fe->dphidxi;
00787         const std::vector<std::vector<Real> >& St = base_fe->dphideta;
00788         const std::vector<std::vector<Real> >& S_map  = (base_fe->get_fe_map()).get_phi_map();
00789         const std::vector<std::vector<Real> >& Ss_map = (base_fe->get_fe_map()).get_dphidxi_map();
00790         const std::vector<std::vector<Real> >& St_map = (base_fe->get_fe_map()).get_dphideta_map();
00791 
00792         const unsigned int n_radial_qp         = radial_qrule->n_points();
00793         const unsigned int n_base_qp           = base_qrule->  n_points();
00794 
00795         const unsigned int n_total_mapping_sf  =
00796           cast_int<unsigned int>(radial_map.size()) * n_base_mapping_sf;
00797 
00798         const unsigned int n_total_approx_sf   = Radial::n_dofs(fe_type.radial_order) *  base_fe->n_shape_functions();
00799 
00800 
00801         // compute the phase term derivatives
00802         {
00803           unsigned int tp=0;
00804           for (unsigned int rp=0; rp<n_radial_qp; rp++)  // over radial qp's
00805             for (unsigned int bp=0; bp<n_base_qp; bp++)  // over base qp's
00806               {
00807                 // sum over all base shapes, to get the average distance
00808                 for (unsigned int i=0; i<n_base_mapping_sf; i++)
00809                   {
00810                     dphasedxi[tp]   += Ss_map[i][bp] * dist[i] * radial_map   [1][rp];
00811                     dphasedeta[tp]  += St_map[i][bp] * dist[i] * radial_map   [1][rp];
00812                     dphasedzeta[tp] += S_map [i][bp] * dist[i] * dradialdv_map[1][rp];
00813                   }
00814 
00815                 tp++;
00816 
00817               } // loop radial and base qp's
00818 
00819         }
00820 
00821         libmesh_assert_equal_to (phi.size(), n_total_approx_sf);
00822         libmesh_assert_equal_to (dphidxi.size(), n_total_approx_sf);
00823         libmesh_assert_equal_to (dphideta.size(), n_total_approx_sf);
00824         libmesh_assert_equal_to (dphidzeta.size(), n_total_approx_sf);
00825 
00826         // compute the overall approximation shape functions,
00827         // pick the appropriate radial and base shapes through using
00828         // _base_shape_index and _radial_shape_index
00829         for (unsigned int rp=0; rp<n_radial_qp; rp++)  // over radial qp's
00830           for (unsigned int bp=0; bp<n_base_qp; bp++)  // over base qp's
00831             for (unsigned int ti=0; ti<n_total_approx_sf; ti++)  // over _all_ approx_sf
00832               {
00833                 // let the index vectors take care of selecting the appropriate base/radial shape
00834                 const unsigned int bi = _base_shape_index  [ti];
00835                 const unsigned int ri = _radial_shape_index[ti];
00836                 phi      [ti][bp+rp*n_base_qp] = S [bi][bp] * mode[ri][rp] * som[rp];
00837                 dphidxi  [ti][bp+rp*n_base_qp] = Ss[bi][bp] * mode[ri][rp] * som[rp];
00838                 dphideta [ti][bp+rp*n_base_qp] = St[bi][bp] * mode[ri][rp] * som[rp];
00839                 dphidzeta[ti][bp+rp*n_base_qp] = S [bi][bp]
00840                   * (dmodedv[ri][rp] * som[rp] + mode[ri][rp] * dsomdv[rp]);
00841               }
00842 
00843         std::vector<std::vector<Real> >& phi_map = this->_fe_map->get_phi_map();
00844         std::vector<std::vector<Real> >& dphidxi_map = this->_fe_map->get_dphidxi_map();
00845         std::vector<std::vector<Real> >& dphideta_map = this->_fe_map->get_dphideta_map();
00846         std::vector<std::vector<Real> >& dphidzeta_map = this->_fe_map->get_dphidzeta_map();
00847 
00848         libmesh_assert_equal_to (phi_map.size(), n_total_mapping_sf);
00849         libmesh_assert_equal_to (dphidxi_map.size(), n_total_mapping_sf);
00850         libmesh_assert_equal_to (dphideta_map.size(), n_total_mapping_sf);
00851         libmesh_assert_equal_to (dphidzeta_map.size(), n_total_mapping_sf);
00852 
00853         // compute the overall mapping functions,
00854         // pick the appropriate radial and base entries through using
00855         // _base_node_index and _radial_node_index
00856         for (unsigned int rp=0; rp<n_radial_qp; rp++)  // over radial qp's
00857           for (unsigned int bp=0; bp<n_base_qp; bp++)  // over base qp's
00858             for (unsigned int ti=0; ti<n_total_mapping_sf; ti++)  // over all mapping shapes
00859               {
00860                 // let the index vectors take care of selecting the appropriate base/radial mapping shape
00861                 const unsigned int bi = _base_node_index  [ti];
00862                 const unsigned int ri = _radial_node_index[ti];
00863                 phi_map      [ti][bp+rp*n_base_qp] = S_map [bi][bp] * radial_map   [ri][rp];
00864                 dphidxi_map  [ti][bp+rp*n_base_qp] = Ss_map[bi][bp] * radial_map   [ri][rp];
00865                 dphideta_map [ti][bp+rp*n_base_qp] = St_map[bi][bp] * radial_map   [ri][rp];
00866                 dphidzeta_map[ti][bp+rp*n_base_qp] = S_map [bi][bp] * dradialdv_map[ri][rp];
00867               }
00868 
00869 
00870         break;
00871       }
00872 
00873     default:
00874       libmesh_error_msg("Unsupported Dim = " << Dim);
00875     }
00876 
00877 
00881   STOP_LOG("combine_base_radial()", "InfFE");
00882 }
00883 
00884 
00885 
00886 
00887 
00888 
00889 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
00890 void InfFE<Dim,T_radial,T_map>::compute_shape_functions(const Elem*, const std::vector<Point>&)
00891 {
00892   libmesh_assert(radial_qrule);
00893 
00894   // Start logging the overall computation of shape functions
00895   START_LOG("compute_shape_functions()", "InfFE");
00896 
00897 
00898   const unsigned int n_total_qp  = _n_total_qp;
00899 
00900 
00901   //-------------------------------------------------------------------------
00902   // Compute the shape function values (and derivatives)
00903   // at the Quadrature points.  Note that the actual values
00904   // have already been computed via init_shape_functions
00905 
00906   // Compute the value of the derivative shape function i at quadrature point p
00907   switch (dim)
00908     {
00909 
00910     case 1:
00911       {
00912         libmesh_not_implemented();
00913         break;
00914       }
00915 
00916     case 2:
00917       {
00918         libmesh_not_implemented();
00919         break;
00920       }
00921 
00922     case 3:
00923       {
00924         const std::vector<Real>& dxidx_map = this->_fe_map->get_dxidx();
00925         const std::vector<Real>& dxidy_map = this->_fe_map->get_dxidy();
00926         const std::vector<Real>& dxidz_map = this->_fe_map->get_dxidz();
00927 
00928         const std::vector<Real>& detadx_map = this->_fe_map->get_detadx();
00929         const std::vector<Real>& detady_map = this->_fe_map->get_detady();
00930         const std::vector<Real>& detadz_map = this->_fe_map->get_detadz();
00931 
00932         const std::vector<Real>& dzetadx_map = this->_fe_map->get_dzetadx();
00933         const std::vector<Real>& dzetady_map = this->_fe_map->get_dzetady();
00934         const std::vector<Real>& dzetadz_map = this->_fe_map->get_dzetadz();
00935 
00936         // These are _all_ shape functions of this infinite element
00937         for (unsigned int i=0; i<phi.size(); i++)
00938           for (unsigned int p=0; p<n_total_qp; p++)
00939             {
00940               // dphi/dx    = (dphi/dxi)*(dxi/dx) + (dphi/deta)*(deta/dx) + (dphi/dzeta)*(dzeta/dx);
00941               dphi[i][p](0) =
00942                 dphidx[i][p] = (dphidxi[i][p]*dxidx_map[p] +
00943                                 dphideta[i][p]*detadx_map[p] +
00944                                 dphidzeta[i][p]*dzetadx_map[p]);
00945 
00946               // dphi/dy    = (dphi/dxi)*(dxi/dy) + (dphi/deta)*(deta/dy) + (dphi/dzeta)*(dzeta/dy);
00947               dphi[i][p](1) =
00948                 dphidy[i][p] = (dphidxi[i][p]*dxidy_map[p] +
00949                                 dphideta[i][p]*detady_map[p] +
00950                                 dphidzeta[i][p]*dzetady_map[p]);
00951 
00952               // dphi/dz    = (dphi/dxi)*(dxi/dz) + (dphi/deta)*(deta/dz) + (dphi/dzeta)*(dzeta/dz);
00953               dphi[i][p](2) =
00954                 dphidz[i][p] = (dphidxi[i][p]*dxidz_map[p] +
00955                                 dphideta[i][p]*detadz_map[p] +
00956                                 dphidzeta[i][p]*dzetadz_map[p]);
00957             }
00958 
00959 
00960         // This is the derivative of the phase term of this infinite element
00961         for (unsigned int p=0; p<n_total_qp; p++)
00962           {
00963             // the derivative of the phase term
00964             dphase[p](0) = (dphasedxi[p]   * dxidx_map[p] +
00965                             dphasedeta[p]  * detadx_map[p] +
00966                             dphasedzeta[p] * dzetadx_map[p]);
00967 
00968             dphase[p](1) = (dphasedxi[p]   * dxidy_map[p] +
00969                             dphasedeta[p]  * detady_map[p] +
00970                             dphasedzeta[p] * dzetady_map[p]);
00971 
00972             dphase[p](2) = (dphasedxi[p]   * dxidz_map[p] +
00973                             dphasedeta[p]  * detadz_map[p] +
00974                             dphasedzeta[p] * dzetadz_map[p]);
00975 
00976             // the derivative of the radial weight - varies only in radial direction,
00977             // therefore dweightdxi = dweightdeta = 0.
00978             dweight[p](0) = dweightdv[p] * dzetadx_map[p];
00979 
00980             dweight[p](1) = dweightdv[p] * dzetady_map[p];
00981 
00982             dweight[p](2) = dweightdv[p] * dzetadz_map[p];
00983 
00984           }
00985 
00986         break;
00987       }
00988 
00989     default:
00990       libmesh_error_msg("Unsupported dim = " << dim);
00991     }
00992 
00993   // Stop logging the overall computation of shape functions
00994   STOP_LOG("compute_shape_functions()", "InfFE");
00995 }
00996 
00997 
00998 
00999 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
01000 bool InfFE<Dim,T_radial,T_map>::shapes_need_reinit() const
01001 {
01002   return false;
01003 }
01004 
01005 } // namespace libMesh
01006 
01007 
01008 //--------------------------------------------------------------
01009 // Explicit instantiations
01010 #include "libmesh/inf_fe_instantiate_1D.h"
01011 #include "libmesh/inf_fe_instantiate_2D.h"
01012 #include "libmesh/inf_fe_instantiate_3D.h"
01013 
01014 
01015 
01016 #endif //ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS