Exemple #1
0
InfFE<Dim,T_radial,T_map>::InfFE (const FEType & fet) :
  FEBase       (Dim, fet),

  _n_total_approx_sf (0),
  _n_total_qp        (0),

  base_qrule   (libmesh_nullptr),
  radial_qrule (libmesh_nullptr),
  base_elem    (libmesh_nullptr),
  base_fe      (libmesh_nullptr),

  // initialize the current_fe_type to all the same
  // values as \p fet (since the FE families and coordinate
  // map type should @e not change), but use an invalid order
  // for the radial part (since this is the only order
  // that may change!).
  // the data structures like \p phi etc are not initialized
  // through the constructor, but throught reinit()
  current_fe_type ( FEType(fet.order,
                           fet.family,
                           INVALID_ORDER,
                           fet.radial_family,
                           fet.inf_map) )

{
  // Sanity checks
  libmesh_assert_equal_to (T_radial, fe_type.radial_family);
  libmesh_assert_equal_to (T_map, fe_type.inf_map);

  // build the base_fe object, handle the UniquePtr
  if (Dim != 1)
    {
      UniquePtr<FEBase> ap_fb(FEBase::build(Dim-1, fet));
      base_fe = ap_fb.release();
    }
}
Exemple #2
0
void InfFE<Dim,T_radial,T_base>::init_face_shape_functions(const std::vector<Point>&,
                                                           const Elem* inf_side)
{
  libmesh_assert(inf_side);

  // Currently, this makes only sense in 3-D!
  libmesh_assert_equal_to (Dim, 3);

  // Initialiize the radial shape functions
  this->init_radial_shape_functions(inf_side);

  // Initialize the base shape functions
  this->update_base_elem(inf_side);

  // Initialize the base quadratur rule
  base_qrule->init(base_elem->type(), inf_side->p_level());

  // base_fe still corresponds to the (dim-1)-dimensional base of the InfFE object,
  // so update the fe_base.
  {
    libmesh_assert_equal_to (Dim, 3);

    AutoPtr<FEBase> ap_fb(FEBase::build(Dim-2, this->fe_type));
    if (base_fe != NULL)
      delete base_fe;
    base_fe = ap_fb.release();
    base_fe->attach_quadrature_rule(base_qrule);
  }

  // initialize the shape functions on the base
  base_fe->init_base_shape_functions(base_fe->qrule->get_points(),
                                     base_elem);

  // the number of quadrature points
  const unsigned int n_radial_qp =
    libmesh_cast_int<unsigned int>(som.size());
  const unsigned int n_base_qp   = base_qrule->n_points();
  const unsigned int n_total_qp  = n_radial_qp * n_base_qp;

  // the quadratur weigths
  _total_qrule_weights.resize(n_total_qp);

  // now inite the shapes for boundary work
  {

    // The element type and order to use in the base map
    const Order    base_mapping_order     ( base_elem->default_order() );
    const ElemType base_mapping_elem_type ( base_elem->type()          );

    // the number of mapping shape functions
    // (Lagrange shape functions are used for mapping in the base)
    const unsigned int n_radial_mapping_sf =
      libmesh_cast_int<unsigned int>(radial_map.size());
    const unsigned int n_base_mapping_shape_functions = Base::n_base_mapping_sf(base_mapping_elem_type,
                                                                                base_mapping_order);

    const unsigned int n_total_mapping_shape_functions =
      n_radial_mapping_sf * n_base_mapping_shape_functions;


    // initialize the node and shape numbering maps
    {
      _radial_node_index.resize    (n_total_mapping_shape_functions);
      _base_node_index.resize      (n_total_mapping_shape_functions);

      const ElemType inf_face_elem_type (inf_side->type());

      // fill the node index map
      for (unsigned int n=0; n<n_total_mapping_shape_functions; n++)
        {
          compute_node_indices (inf_face_elem_type,
                                n,
                                _base_node_index[n],
                                _radial_node_index[n]);

          libmesh_assert_less (_base_node_index[n], n_base_mapping_shape_functions);
          libmesh_assert_less (_radial_node_index[n], n_radial_mapping_sf);
        }

    }

    // rezise map data fields
    {
      std::vector<std::vector<Real> >& psi_map = this->_fe_map->get_psi();
      std::vector<std::vector<Real> >& dpsidxi_map = this->_fe_map->get_dpsidxi();
      std::vector<std::vector<Real> >& d2psidxi2_map = this->_fe_map->get_d2psidxi2();
      psi_map.resize          (n_total_mapping_shape_functions);
      dpsidxi_map.resize      (n_total_mapping_shape_functions);
      d2psidxi2_map.resize    (n_total_mapping_shape_functions);

      //  if (Dim == 3)
      {
        std::vector<std::vector<Real> >& dpsideta_map = this->_fe_map->get_dpsideta();
        std::vector<std::vector<Real> >& d2psidxideta_map = this->_fe_map->get_d2psidxideta();
        std::vector<std::vector<Real> >& d2psideta2_map = this->_fe_map->get_d2psideta2();
        dpsideta_map.resize     (n_total_mapping_shape_functions);
        d2psidxideta_map.resize (n_total_mapping_shape_functions);
        d2psideta2_map.resize   (n_total_mapping_shape_functions);
      }

      for (unsigned int i=0; i<n_total_mapping_shape_functions; i++)
        {
          psi_map[i].resize         (n_total_qp);
          dpsidxi_map[i].resize     (n_total_qp);
          d2psidxi2_map[i].resize   (n_total_qp);

          // if (Dim == 3)
          {
            std::vector<std::vector<Real> >& dpsideta_map = this->_fe_map->get_dpsideta();
            std::vector<std::vector<Real> >& d2psidxideta_map = this->_fe_map->get_d2psidxideta();
            std::vector<std::vector<Real> >& d2psideta2_map = this->_fe_map->get_d2psideta2();
            dpsideta_map[i].resize     (n_total_qp);
            d2psidxideta_map[i].resize (n_total_qp);
            d2psideta2_map[i].resize   (n_total_qp);
          }
        }
    }


    // compute shape maps
    {
      const std::vector<std::vector<Real> >& S_map  = (base_fe->get_fe_map()).get_phi_map();
      const std::vector<std::vector<Real> >& Ss_map = (base_fe->get_fe_map()).get_dphidxi_map();

      std::vector<std::vector<Real> >& psi_map = this->_fe_map->get_psi();
      std::vector<std::vector<Real> >& dpsidxi_map = this->_fe_map->get_dpsidxi();
      std::vector<std::vector<Real> >& dpsideta_map = this->_fe_map->get_dpsideta();

      for (unsigned int rp=0; rp<n_radial_qp; rp++)  // over radial qp's
        for (unsigned int bp=0; bp<n_base_qp; bp++)  // over base qp's
          for (unsigned int ti=0; ti<n_total_mapping_shape_functions; ti++)  // over all mapping shapes
            {
              // let the index vectors take care of selecting the appropriate base/radial mapping shape
              const unsigned int bi = _base_node_index  [ti];
              const unsigned int ri = _radial_node_index[ti];
              psi_map          [ti][bp+rp*n_base_qp] = S_map [bi][bp] * radial_map   [ri][rp];
              dpsidxi_map      [ti][bp+rp*n_base_qp] = Ss_map[bi][bp] * radial_map   [ri][rp];
              dpsideta_map     [ti][bp+rp*n_base_qp] = S_map [bi][bp] * dradialdv_map[ri][rp];

              // second derivatives are not implemented for infinite elements
              // d2psidxi2_map    [ti][bp+rp*n_base_qp] = 0.;
              // d2psidxideta_map [ti][bp+rp*n_base_qp] = 0.;
              // d2psideta2_map   [ti][bp+rp*n_base_qp] = 0.;
            }

    }

  }

  // quadrature rule weights
  {
    const std::vector<Real>&   radial_qw = radial_qrule->get_weights();
    const std::vector<Real>&   base_qw   = base_qrule->get_weights();

    libmesh_assert_equal_to (radial_qw.size(), n_radial_qp);
    libmesh_assert_equal_to (base_qw.size(), n_base_qp);

    for (unsigned int rp=0; rp<n_radial_qp; rp++)
      for (unsigned int bp=0; bp<n_base_qp; bp++)
        {
          _total_qrule_weights[  bp+rp*n_base_qp ] = radial_qw[rp] * base_qw[bp];
        }
  }

}
Exemple #3
0
void InfFE<Dim,T_radial,T_map>::reinit(const Elem * inf_elem,
                                       const std::vector<Point> * const pts,
                                       const std::vector<Real> * const weights)
{
  libmesh_assert(base_fe);
  libmesh_assert(base_fe->qrule);
  libmesh_assert_equal_to (base_fe->qrule, base_qrule);
  libmesh_assert(radial_qrule);
  libmesh_assert(inf_elem);

  if (pts == libmesh_nullptr)
    {
      bool init_shape_functions_required = false;

      // -----------------------------------------------------------------
      // init the radial data fields only when the radial order changes
      if (current_fe_type.radial_order != fe_type.radial_order)
        {
          current_fe_type.radial_order = fe_type.radial_order;

          // Watch out: this call to QBase->init() only works for
          // current_fe_type = const!   To allow variable Order,
          // the init() of QBase has to be modified...
          radial_qrule->init(EDGE2);

          // initialize the radial shape functions
          this->init_radial_shape_functions(inf_elem);

          init_shape_functions_required=true;
        }


      bool update_base_elem_required=true;

      // -----------------------------------------------------------------
      // update the type in accordance to the current cell
      // and reinit if the cell type has changed or (as in
      // the case of the hierarchics) the shape functions
      // depend on the particular element and need a reinit
      if (  ( Dim != 1) &&
            (  (this->get_type() != inf_elem->type())  ||
               (base_fe->shapes_need_reinit())  )  )
        {
          // store the new element type, update base_elem
          // here.  Through \p update_base_elem_required,
          // remember whether it has to be updated (see below).
          elem_type = inf_elem->type();
          this->update_base_elem(inf_elem);
          update_base_elem_required=false;

          // initialize the base quadrature rule for the new element
          base_qrule->init(base_elem->type());

          // initialize the shape functions in the base
          base_fe->init_base_shape_functions(base_fe->qrule->get_points(),
                                             base_elem);

          init_shape_functions_required=true;
        }


      // when either the radial or base part change,
      // we have to init the whole fields
      if (init_shape_functions_required)
        this->init_shape_functions (inf_elem);

      // computing the distance only works when we have the current
      // base_elem stored.  This happens when fe_type is const,
      // the inf_elem->type remains the same.  Then we have to
      // update the base elem _here_.
      if (update_base_elem_required)
        this->update_base_elem(inf_elem);

      // compute dist (depends on geometry, therefore has to be updated for
      // each and every new element), throw radial and base part together
      this->combine_base_radial (inf_elem);

      this->_fe_map->compute_map (this->dim, _total_qrule_weights, inf_elem, this->calculate_d2phi);

      // Compute the shape functions and the derivatives
      // at all quadrature points.
      this->compute_shape_functions (inf_elem,base_fe->qrule->get_points());
    }

  else // if pts != libmesh_nullptr
    {
      // update the elem_type
      elem_type = inf_elem->type();

      // init radial shapes
      this->init_radial_shape_functions(inf_elem);

      // update the base
      this->update_base_elem(inf_elem);

      // the finite element on the ifem base
      {
        UniquePtr<FEBase> ap_fb(FEBase::build(Dim-1, this->fe_type));
        if (base_fe != libmesh_nullptr)
          delete base_fe;
        base_fe = ap_fb.release();
      }

      // inite base shapes
      base_fe->init_base_shape_functions(*pts,
                                         base_elem);

      this->init_shape_functions (inf_elem);

      // combine the base and radial shapes
      this->combine_base_radial (inf_elem);

      // weights
      if (weights != libmesh_nullptr)
        {
          this->_fe_map->compute_map (this->dim, *weights, inf_elem, this->calculate_d2phi);
        }
      else
        {
          std::vector<Real> dummy_weights (pts->size(), 1.);
          this->_fe_map->compute_map (this->dim, dummy_weights, inf_elem, this->calculate_d2phi);
        }

      // finally compute the ifem shapes
      this->compute_shape_functions (inf_elem,*pts);
    }

}