Exemple #1
0
static float OscillationsMetric(const Curve &rp, int npoints) {
    // nuosci: lowest frequency v for which P(v) ~ 1
    float nuosci = 0.0, maxp = 0.0;
    for (int i = 0; i < rp.size() && maxp < 0.98; ++i) {
        float p = rp[i];
        if (p > maxp) {
            maxp = p;
            nuosci = rp.ToX(i);
        }
    }
    
    float npeaks = 10.f;
    float maxfreq = sqrtf(npoints) / 2;
    float x0 = nuosci;
    float x1 = std::min(x0 + npeaks * maxfreq, rp.x1);
    
    Curve osci(rp);
    for (int i = 0; i < osci.size(); ++i) {
        float nu = osci.ToX(i);
        osci[i] = nu < x0 ? 0.f : (osci[i] - 1.f) * (osci[i] - 1.f) * nu;
    }
    
    return 10.f * sqrtf(TWOPI * Integrate(osci, x0, x1) / RingArea(x0, x1));
}
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;
}