Пример #1
0
std::vector<RealGradient>
CNSFVMinmaxSlopeLimiting::limitElementSlope() const
{
  const Elem * elem = _current_elem;

  /// current element id
  dof_id_type _elementID = elem->id();

  /// current element centroid coordinte
  Point ecent = elem->centroid();

  /// number of sides surrounding an element
  unsigned int nside = elem->n_sides();

  /// number of conserved variables
  unsigned int nvars = 5;

  /// vector for the centroid of the sides surrounding an element
  std::vector<Point> scent(nside, Point(0., 0., 0.));

  /// vector for the limited gradients of the conserved variables
  std::vector<RealGradient> ugrad(nvars, RealGradient(0., 0., 0.));

  /// a flag to indicate the boundary side of the current cell
  bool bflag = false;

  /// initialize local minimum variable values
  std::vector<Real> umin(nvars, 0.);
  /// initialize local maximum variable values
  std::vector<Real> umax(nvars, 0.);
  /// initialize local cache for element variable values
  std::vector<Real> uelem(nvars, 0.);
  /// initialize local cache for reconstructed element gradients
  std::vector<RealGradient> rugrad(nvars, RealGradient(0., 0., 0.));
  /// initialize local cache for element slope limitor values
  std::vector<std::vector<Real>> limit(nside + 1, std::vector<Real>(nvars, 1.));

  Real dij = 0.;

  uelem = _rslope.getElementAverageValue(_elementID);

  for (unsigned int iv = 0; iv < nvars; iv++)
  {
    umin[iv] = uelem[iv];
    umax[iv] = uelem[iv];
  }

  /// loop over the sides to find the min and max cell-average values

  for (unsigned int is = 0; is < nside; is++)
  {
    const Elem * neighbor = elem->neighbor_ptr(is);

    if (neighbor != nullptr && this->hasBlocks(neighbor->subdomain_id()))
    {
      dof_id_type _neighborID = neighbor->id();
      uelem = _rslope.getElementAverageValue(_neighborID);
      scent[is] = _rslope.getSideCentroid(_elementID, _neighborID);
    }
    else
    {
      uelem = _rslope.getBoundaryAverageValue(_elementID, is);
      scent[is] = _rslope.getBoundarySideCentroid(_elementID, is);
    }

    for (unsigned int iv = 0; iv < nvars; iv++)
    {
      if (uelem[iv] < umin[iv])
        umin[iv] = uelem[iv];
      if (uelem[iv] > umax[iv])
        umax[iv] = uelem[iv];
    }
  }

  /// loop over the sides to compute the limiter values

  rugrad = _rslope.getElementSlope(_elementID);
  uelem = _rslope.getElementAverageValue(_elementID);

  for (unsigned int is = 0; is < nside; is++)
  {
    for (unsigned int iv = 0; iv < nvars; iv++)
    {
      dij = (scent[is] - ecent) * rugrad[iv];

      if (dij > 0.)
        limit[is + 1][iv] = std::min(1., (umax[iv] - uelem[iv]) / dij);
      else if (dij < 0.)
        limit[is + 1][iv] = std::min(1., (umin[iv] - uelem[iv]) / dij);
    }
  }

  /// loop over the sides to get the final limiter of this cell

  for (unsigned int is = 0; is < nside; is++)
  {
    for (unsigned int iv = 0; iv < nvars; iv++)
    {
      if (limit[0][iv] > limit[is + 1][iv])
        limit[0][iv] = limit[is + 1][iv];
    }
  }

  /// get the limited slope of this cell

  if (!_include_bc && bflag)
  {
    for (unsigned int iv = 0; iv < nvars; iv++)
      ugrad[iv] = RealGradient(0., 0., 0.);
  }
  else
  {
    for (unsigned int iv = 0; iv < nvars; iv++)
      ugrad[iv] = rugrad[iv] * limit[0][iv];
  }

  return ugrad;
}
Пример #2
0
std::vector<RealGradient>
CNSFVWENOSlopeLimiting::limitElementSlope() const
{
  const Elem * elem = _current_elem;

  /// current element id
  dof_id_type _elementID = elem->id();

  /// number of conserved variables
  unsigned int nvars = 5;

  /// number of sides surrounding an element
  unsigned int nside = elem->n_sides();

  /// vector for the limited gradients of the conserved variables
  std::vector<RealGradient> ugrad(nvars, RealGradient(0., 0., 0.));

  /// initialize local cache for reconstructed element gradients
  std::vector<RealGradient> rugrad(nvars, RealGradient(0., 0., 0.));

  /// a small number to avoid dividing by zero
  Real eps = 1e-7;

  /// initialize oscillation indicator
  std::vector<std::vector<Real>> osci(nside + 1, std::vector<Real>(nvars, 0.));

  /// initialize weight coefficients
  std::vector<std::vector<Real>> weig(nside + 1, std::vector<Real>(nvars, 0.));

  /// initialize summed coefficients
  std::vector<Real> summ(nvars, 0.);

  /// compute oscillation indicators, nonlinear weights and their summ for each stencil

  rugrad = _rslope.getElementSlope(_elementID);

  for (unsigned int iv = 0; iv < nvars; iv++)
  {
    osci[0][iv] = std::sqrt(rugrad[iv] * rugrad[iv]);

    weig[0][iv] = _lweig / std::pow(eps + osci[0][iv], _dpowe);

    summ[iv] = weig[0][iv];
  }

  for (unsigned int is = 0; is < nside; is++)
  {
    unsigned int in = is + 1;

    if (elem->neighbor(is) != NULL)
    {
      dof_id_type _neighborID = elem->neighbor(is)->id();
      rugrad = _rslope.getElementSlope(_neighborID);

      for (unsigned int iv = 0; iv < nvars; iv++)
      {
        osci[in][iv] = std::sqrt(rugrad[iv] * rugrad[iv]);

        weig[in][iv] = 1. / std::pow(eps + osci[in][iv], _dpowe);

        summ[iv] += weig[in][iv];
      }
    }
  }

  /// compute the normalized weight

  for (unsigned int iv = 0; iv < nvars; iv++)
    weig[0][iv] = weig[0][iv] / summ[iv];

  for (unsigned int is = 0; is < nside; is++)
  {
    unsigned int in = is + 1;

    if (elem->neighbor(is) != NULL)
      for (unsigned int iv = 0; iv < nvars; iv++)
        weig[in][iv] = weig[in][iv] / summ[iv];
  }

  /// compute the limited slope

  rugrad = _rslope.getElementSlope(_elementID);

  for (unsigned int iv = 0; iv < nvars; iv++)
    ugrad[iv] = weig[0][iv] * rugrad[iv];

  for (unsigned int is = 0; is < nside; is++)
  {
    unsigned int in = is + 1;

    if (elem->neighbor(is) != NULL)
    {
      dof_id_type _neighborID = elem->neighbor(is)->id();
      rugrad = _rslope.getElementSlope(_neighborID);

      for (unsigned int iv = 0; iv < nvars; iv++)
        ugrad[iv] += weig[in][iv] * rugrad[iv];
    }
  }

  return ugrad;
}