Exemple #1
0
Real InfFE<Dim,T_radial,T_map>::shape(const FEType & fet,
                                      const Elem * inf_elem,
                                      const unsigned int i,
                                      const Point & p)
{
  libmesh_assert(inf_elem);
  libmesh_assert_not_equal_to (Dim, 0);

#ifdef DEBUG
  // this makes only sense when used for mapping
  if ((T_radial != INFINITE_MAP) && !_warned_for_shape)
    {
      libMesh::err << "WARNING: InfFE<Dim,T_radial,T_map>::shape(...) does _not_" << std::endl
                   << " return the correct trial function!  Use " << std::endl
                   << " InfFE<Dim,T_radial,T_map>::compute_data(..) instead!"
                   << std::endl;
      _warned_for_shape = true;
    }
#endif

  const Order o_radial (fet.radial_order);
  const Real v (p(Dim-1));
  UniquePtr<const Elem> base_el (inf_elem->build_side_ptr(0));

  unsigned int i_base, i_radial;
  compute_shape_indices(fet, inf_elem->type(), i, i_base, i_radial);

  if (Dim > 1)
    return FEInterface::shape(Dim-1, fet, base_el.get(), i_base, p)
      * InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial)
      * InfFE<Dim,T_radial,T_map>::Radial::decay(v);
  else
    return InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial)
      * InfFE<Dim,T_radial,T_map>::Radial::decay(v);
}
Exemple #2
0
Real InfFE<Dim,T_radial,T_map>::shape(const FEType & fet,
                                      const ElemType inf_elem_type,
                                      const unsigned int i,
                                      const Point & p)
{
  libmesh_assert_not_equal_to (Dim, 0);

#ifdef DEBUG
  // this makes only sense when used for mapping
  if ((T_radial != INFINITE_MAP) && !_warned_for_shape)
    {
      libMesh::err << "WARNING: InfFE<Dim,T_radial,T_map>::shape(...) does _not_" << std::endl
                   << " return the correct trial function!  Use " << std::endl
                   << " InfFE<Dim,T_radial,T_map>::compute_data(..) instead!"
                   << std::endl;
      _warned_for_shape = true;
    }
#endif

  const ElemType     base_et  (Base::get_elem_type(inf_elem_type));
  const Order        o_radial (fet.radial_order);
  const Real         v        (p(Dim-1));

  unsigned int i_base, i_radial;
  compute_shape_indices(fet, inf_elem_type, i, i_base, i_radial);

  //TODO:[SP/DD]  exp(ikr) is still missing here!
  if (Dim > 1)
    return FEInterface::shape(Dim-1, fet, base_et, i_base, p)
      * InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial)
      * InfFE<Dim,T_radial,T_map>::Radial::decay(v);
  else
    return InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial)
      * InfFE<Dim,T_radial,T_map>::Radial::decay(v);
}
Exemple #3
0
void InfFE<Dim,T_radial,T_map>::init_shape_functions(const Elem * inf_elem)
{
  libmesh_assert(inf_elem);


  // Start logging the radial shape function initialization
  START_LOG("init_shape_functions()", "InfFE");


  // -----------------------------------------------------------------
  // fast access to some const int's for the radial data
  const unsigned int n_radial_mapping_sf =
    cast_int<unsigned int>(radial_map.size());
  const unsigned int n_radial_approx_sf  =
    cast_int<unsigned int>(mode.size());
  const unsigned int n_radial_qp         =
    cast_int<unsigned int>(som.size());


  // -----------------------------------------------------------------
  // initialize most of the things related to mapping

  // 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 base shape functions used to construct the map
  // (Lagrange shape functions are used for mapping in the base)
  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 most of the things related to physical approximation

  unsigned int n_base_approx_shape_functions;
  if (Dim > 1)
    n_base_approx_shape_functions = base_fe->n_shape_functions();
  else
    n_base_approx_shape_functions = 1;


  const unsigned int n_total_approx_shape_functions =
    n_radial_approx_sf * n_base_approx_shape_functions;

  // update class member field
  _n_total_approx_sf = n_total_approx_shape_functions;


  // The number of the base quadrature points.
  const unsigned int        n_base_qp =  base_qrule->n_points();

  // The total number of quadrature points.
  const unsigned int        n_total_qp =  n_radial_qp * n_base_qp;


  // update class member field
  _n_total_qp = n_total_qp;



  // -----------------------------------------------------------------
  // initialize the node and shape numbering maps
  {
    // these vectors work as follows: the i-th entry stores
    // the associated base/radial node number
    _radial_node_index.resize    (n_total_mapping_shape_functions);
    _base_node_index.resize      (n_total_mapping_shape_functions);

    // similar for the shapes: the i-th entry stores
    // the associated base/radial shape number
    _radial_shape_index.resize   (n_total_approx_shape_functions);
    _base_shape_index.resize     (n_total_approx_shape_functions);

    const ElemType inf_elem_type (inf_elem->type());

    // fill the node index map
    for (unsigned int n=0; n<n_total_mapping_shape_functions; n++)
      {
        compute_node_indices (inf_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);
      }

    // fill the shape index map
    for (unsigned int n=0; n<n_total_approx_shape_functions; n++)
      {
        compute_shape_indices (this->fe_type,
                               inf_elem_type,
                               n,
                               _base_shape_index[n],
                               _radial_shape_index[n]);
        libmesh_assert_less (_base_shape_index[n], n_base_approx_shape_functions);
        libmesh_assert_less (_radial_shape_index[n], n_radial_approx_sf);
      }
  }





  // -----------------------------------------------------------------
  // resize the base data fields
  dist.resize(n_base_mapping_shape_functions);



  // -----------------------------------------------------------------
  // resize the total data fields

  // the phase term varies with xi, eta and zeta(v): store it for _all_ qp
  //
  // when computing the phase, we need the base approximations
  // therefore, initialize the phase here, but evaluate it
  // in combine_base_radial().
  //
  // the weight, though, is only needed at the radial quadrature points, n_radial_qp.
  // but for a uniform interface to the protected data fields
  // the weight data field (which are accessible from the outside) are expanded to n_total_qp.
  weight.resize      (n_total_qp);
  dweightdv.resize   (n_total_qp);
  dweight.resize     (n_total_qp);

  dphase.resize      (n_total_qp);
  dphasedxi.resize   (n_total_qp);
  dphasedeta.resize  (n_total_qp);
  dphasedzeta.resize (n_total_qp);

  // this vector contains the integration weights for the combined quadrature rule
  _total_qrule_weights.resize(n_total_qp);


  // -----------------------------------------------------------------
  // InfFE's data fields phi, dphi, dphidx, phi_map etc hold the _total_
  // shape and mapping functions, respectively
  {
    phi.resize     (n_total_approx_shape_functions);
    dphi.resize    (n_total_approx_shape_functions);
    dphidx.resize  (n_total_approx_shape_functions);
    dphidy.resize  (n_total_approx_shape_functions);
    dphidz.resize  (n_total_approx_shape_functions);
    dphidxi.resize (n_total_approx_shape_functions);
#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    libmesh_do_once(libMesh::err << "Second derivatives for Infinite elements"
                    << " are not yet implemented!"
                    << std::endl);

    d2phi.resize     (n_total_approx_shape_functions);
    d2phidx2.resize  (n_total_approx_shape_functions);
    d2phidxdy.resize (n_total_approx_shape_functions);
    d2phidxdz.resize (n_total_approx_shape_functions);
    d2phidy2.resize  (n_total_approx_shape_functions);
    d2phidydz.resize (n_total_approx_shape_functions);
    d2phidz2.resize  (n_total_approx_shape_functions);
    d2phidxi2.resize (n_total_approx_shape_functions);

    if (Dim > 1)
      {
        d2phidxideta.resize   (n_total_approx_shape_functions);
        d2phideta2.resize     (n_total_approx_shape_functions);
      }

    if (Dim > 2)
      {
        d2phidetadzeta.resize (n_total_approx_shape_functions);
        d2phidxidzeta.resize  (n_total_approx_shape_functions);
        d2phidzeta2.resize    (n_total_approx_shape_functions);
      }
#endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES

    if (Dim > 1)
      dphideta.resize      (n_total_approx_shape_functions);

    if (Dim == 3)
      dphidzeta.resize     (n_total_approx_shape_functions);



    std::vector<std::vector<Real> > & phi_map = this->_fe_map->get_phi_map();
    std::vector<std::vector<Real> > & dphidxi_map = this->_fe_map->get_dphidxi_map();

    phi_map.resize         (n_total_mapping_shape_functions);
    dphidxi_map.resize     (n_total_mapping_shape_functions);
#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    std::vector<std::vector<Real> > & d2phidxi2_map = this->_fe_map->get_d2phidxi2_map();
    d2phidxi2_map.resize   (n_total_mapping_shape_functions);

    if (Dim > 1)
      {
        std::vector<std::vector<Real> > & d2phidxideta_map = this->_fe_map->get_d2phidxideta_map();
        std::vector<std::vector<Real> > & d2phideta2_map = this->_fe_map->get_d2phideta2_map();
        d2phidxideta_map.resize   (n_total_mapping_shape_functions);
        d2phideta2_map.resize     (n_total_mapping_shape_functions);
      }

    if (Dim == 3)
      {
        std::vector<std::vector<Real> > & d2phidxidzeta_map = this->_fe_map->get_d2phidxidzeta_map();
        std::vector<std::vector<Real> > & d2phidetadzeta_map = this->_fe_map->get_d2phidetadzeta_map();
        std::vector<std::vector<Real> > & d2phidzeta2_map = this->_fe_map->get_d2phidzeta2_map();
        d2phidxidzeta_map.resize  (n_total_mapping_shape_functions);
        d2phidetadzeta_map.resize (n_total_mapping_shape_functions);
        d2phidzeta2_map.resize    (n_total_mapping_shape_functions);
      }
#endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES

    if (Dim > 1)
      {
        std::vector<std::vector<Real> > & dphideta_map = this->_fe_map->get_dphideta_map();
        dphideta_map.resize  (n_total_mapping_shape_functions);
      }

    if (Dim == 3)
      {
        std::vector<std::vector<Real> > & dphidzeta_map = this->_fe_map->get_dphidzeta_map();
        dphidzeta_map.resize (n_total_mapping_shape_functions);
      }
  }



  // -----------------------------------------------------------------
  // collect all the for loops, where inner vectors are
  // resized to the appropriate number of quadrature points
  {
    for (unsigned int i=0; i<n_total_approx_shape_functions; i++)
      {
        phi[i].resize         (n_total_qp);
        dphi[i].resize        (n_total_qp);
        dphidx[i].resize      (n_total_qp);
        dphidy[i].resize      (n_total_qp);
        dphidz[i].resize      (n_total_qp);
        dphidxi[i].resize     (n_total_qp);
#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
        d2phi[i].resize       (n_total_qp);
        d2phidx2[i].resize    (n_total_qp);
        d2phidxdy[i].resize   (n_total_qp);
        d2phidxdz[i].resize   (n_total_qp);
        d2phidy2[i].resize    (n_total_qp);
        d2phidydz[i].resize   (n_total_qp);
        d2phidy2[i].resize    (n_total_qp);
        d2phidxi2[i].resize   (n_total_qp);

        if (Dim > 1)
          {
            d2phidxideta[i].resize   (n_total_qp);
            d2phideta2[i].resize     (n_total_qp);
          }
        if (Dim > 2)
          {
            d2phidxidzeta[i].resize  (n_total_qp);
            d2phidetadzeta[i].resize (n_total_qp);
            d2phidzeta2[i].resize    (n_total_qp);
          }
#endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES

        if (Dim > 1)
          dphideta[i].resize  (n_total_qp);

        if (Dim == 3)
          dphidzeta[i].resize (n_total_qp);

      }

    for (unsigned int i=0; i<n_total_mapping_shape_functions; i++)
      {
        std::vector<std::vector<Real> > & phi_map = this->_fe_map->get_phi_map();
        std::vector<std::vector<Real> > & dphidxi_map = this->_fe_map->get_dphidxi_map();
        phi_map[i].resize         (n_total_qp);
        dphidxi_map[i].resize     (n_total_qp);
#ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
        std::vector<std::vector<Real> > & d2phidxi2_map = this->_fe_map->get_d2phidxi2_map();
        d2phidxi2_map[i].resize   (n_total_qp);
        if (Dim > 1)
          {
            std::vector<std::vector<Real> > & d2phidxideta_map = this->_fe_map->get_d2phidxideta_map();
            std::vector<std::vector<Real> > & d2phideta2_map = this->_fe_map->get_d2phideta2_map();
            d2phidxideta_map[i].resize   (n_total_qp);
            d2phideta2_map[i].resize     (n_total_qp);
          }

        if (Dim > 2)
          {
            std::vector<std::vector<Real> > & d2phidxidzeta_map = this->_fe_map->get_d2phidxidzeta_map();
            std::vector<std::vector<Real> > & d2phidetadzeta_map = this->_fe_map->get_d2phidetadzeta_map();
            std::vector<std::vector<Real> > & d2phidzeta2_map = this->_fe_map->get_d2phidzeta2_map();
            d2phidxidzeta_map[i].resize  (n_total_qp);
            d2phidetadzeta_map[i].resize (n_total_qp);
            d2phidzeta2_map[i].resize    (n_total_qp);
          }
#endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES

        if (Dim > 1)
          {
            std::vector<std::vector<Real> > & dphideta_map = this->_fe_map->get_dphideta_map();
            dphideta_map[i].resize  (n_total_qp);
          }

        if (Dim == 3)
          {
            std::vector<std::vector<Real> > & dphidzeta_map = this->_fe_map->get_dphidzeta_map();
            dphidzeta_map[i].resize (n_total_qp);
          }
      }
  }



  {
    // -----------------------------------------------------------------
    // (a) compute scalar values at _all_ quadrature points  -- for uniform
    //     access from the outside to these fields
    // (b) form a std::vector<Real> which contains the appropriate weights
    //     of the combined quadrature rule!
    const std::vector<Point> &  radial_qp = radial_qrule->get_points();
    libmesh_assert_equal_to (radial_qp.size(), n_radial_qp);

    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++)
        {
          weight   [ bp+rp*n_base_qp ] = Radial::D       (radial_qp[rp](0));
          dweightdv[ bp+rp*n_base_qp ] = Radial::D_deriv (radial_qp[rp](0));

          _total_qrule_weights[  bp+rp*n_base_qp ] = radial_qw[rp] * base_qw[bp];
        }
  }


  /**
   * Stop logging the radial shape function initialization
   */
  STOP_LOG("init_shape_functions()", "InfFE");

}
Exemple #4
0
void InfFE<Dim,T_radial,T_map>::compute_data(const FEType & fet,
                                             const Elem * inf_elem,
                                             FEComputeData & data)
{
  libmesh_assert(inf_elem);
  libmesh_assert_not_equal_to (Dim, 0);

  const Order        o_radial             (fet.radial_order);
  const Order        radial_mapping_order (Radial::mapping_order());
  const Point &      p                    (data.p);
  const Real         v                    (p(Dim-1));
  UniquePtr<const Elem> base_el (inf_elem->build_side_ptr(0));

  /*
   * compute \p interpolated_dist containing the mapping-interpolated
   * distance of the base point to the origin.  This is the same
   * for all shape functions.  Set \p interpolated_dist to 0, it
   * is added to.
   */
  Real interpolated_dist = 0.;
  switch (Dim)
    {
    case 1:
      {
        libmesh_assert_equal_to (inf_elem->type(), INFEDGE2);
        interpolated_dist =  Point(inf_elem->point(0) - inf_elem->point(1)).size();
        break;
      }

    case 2:
      {
        const unsigned int n_base_nodes = base_el->n_nodes();

        const Point    origin                 = inf_elem->origin();
        const Order    base_mapping_order     (base_el->default_order());
        const ElemType base_mapping_elem_type (base_el->type());

        // interpolate the base nodes' distances
        for (unsigned int n=0; n<n_base_nodes; n++)
          interpolated_dist += Point(base_el->point(n) - origin).size()
            * FE<1,LAGRANGE>::shape (base_mapping_elem_type, base_mapping_order, n, p);
        break;
      }

    case 3:
      {
        const unsigned int n_base_nodes = base_el->n_nodes();

        const Point    origin                 = inf_elem->origin();
        const Order    base_mapping_order     (base_el->default_order());
        const ElemType base_mapping_elem_type (base_el->type());

        // interpolate the base nodes' distances
        for (unsigned int n=0; n<n_base_nodes; n++)
          interpolated_dist += Point(base_el->point(n) - origin).size()
            * FE<2,LAGRANGE>::shape (base_mapping_elem_type, base_mapping_order, n, p);
        break;
      }

    default:
      libmesh_error_msg("Unknown Dim = " << Dim);
    }



#ifdef LIBMESH_USE_COMPLEX_NUMBERS

  // assumption on time-harmonic behavior
  const short int sign (-1);

  // the wave number
  const Real wavenumber = 2. * libMesh::pi * data.frequency / data.speed;

  // the exponent for time-harmonic behavior
  const Real exponent = sign                                                            /* +1. or -1.                */
    * wavenumber                                                                      /* k                         */
    * interpolated_dist                                                               /* together with next line:  */
    * InfFE<Dim,INFINITE_MAP,T_map>::eval(v, radial_mapping_order, 1);                /* phase(s,t,v)              */

  const Number time_harmonic = Number(cos(exponent), sin(exponent));                    /* e^(sign*i*k*phase(s,t,v)) */

  /*
   * compute \p shape for all dof in the element
   */
  if (Dim > 1)
    {
      const unsigned int n_dof = n_dofs (fet, inf_elem->type());
      data.shape.resize(n_dof);

      for (unsigned int i=0; i<n_dof; i++)
        {
          // compute base and radial shape indices
          unsigned int i_base, i_radial;
          compute_shape_indices(fet, inf_elem->type(), i, i_base, i_radial);

          data.shape[i] = (InfFE<Dim,T_radial,T_map>::Radial::decay(v)                  /* (1.-v)/2. in 3D          */
                           *  FEInterface::shape(Dim-1, fet, base_el.get(), i_base, p)  /* S_n(s,t)                 */
                           * InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial))    /* L_n(v)                   */
            * time_harmonic;                                                          /* e^(sign*i*k*phase(s,t,v) */
        }
    }
  else
    libmesh_error_msg("compute_data() for 1-dimensional InfFE not implemented.");

#else

  const Real speed = data.speed;

  /*
   * This is quite weird: the phase is actually
   * a measure how @e advanced the pressure is that
   * we compute.  In other words: the further away
   * the node \p data.p is, the further we look into
   * the future...
   */
  data.phase = interpolated_dist                                                       /* phase(s,t,v)/c  */
    * InfFE<Dim,INFINITE_MAP,T_map>::eval(v, radial_mapping_order, 1) / speed;

  if (Dim > 1)
    {
      const unsigned int n_dof = n_dofs (fet, inf_elem->type());
      data.shape.resize(n_dof);

      for (unsigned int i=0; i<n_dof; i++)
        {
          // compute base and radial shape indices
          unsigned int i_base, i_radial;
          compute_shape_indices(fet, inf_elem->type(), i, i_base, i_radial);

          data.shape[i] = InfFE<Dim,T_radial,T_map>::Radial::decay(v)                  /* (1.-v)/2. in 3D */
            *  FEInterface::shape(Dim-1, fet, base_el.get(), i_base, p)  /* S_n(s,t)        */
            * InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial);    /* L_n(v)          */
        }
    }
  else
    libmesh_error_msg("compute_data() for 1-dimensional InfFE not implemented.");

#endif
}