Beispiel #1
0
void
AEFVMaterial::computeQpProperties()
{
  // initialize the variable
  _u[_qp] = _uc[_qp];

  // interpolate variable values at face center
  if (_bnd)
  {
    // you should know how many equations you are solving and assign this number
    // e.g. = 1 (for the advection equation)
    unsigned int nvars = 1;
    std::vector<RealGradient> ugrad(nvars, RealGradient(0., 0., 0.));
    ugrad = _lslope.getElementSlope(_current_elem->id());

    // get the directional vector from cell center to face center
    RealGradient dvec = _q_point[_qp] - _current_elem->centroid();

    // calculate the variable at face center
    _u[_qp] += ugrad[0] * dvec;

    // clear the temporary vectors
    ugrad.clear();
  }
  // calculations only for elemental output
  else if (!_bnd)
  {
  }
}
Beispiel #2
0
void dtron(int n, double *x, double *xl, double *xu, double gtol, double frtol, double fatol, double fmin, int maxfev, double cgtol) 
{
/*
c     *********
c
c     Subroutine dtron
c
c     The optimization problem of BSVM is a bound-constrained quadratic
c     optimization problem and its Hessian matrix is positive semidefinite. 
c     We modified the optimization solver TRON by Chih-Jen Lin and
c     Jorge More' into this version which is suitable for this
c     special case.
c
c     This subroutine implements a trust region Newton method for the
c     solution of large bound-constrained quadratic optimization problems
c
c           min { f(x)=0.5*x'*A*x + g0'*x : xl <= x <= xu }
c
c     where the Hessian matrix A is dense and positive semidefinite. The
c     user must define functions which evaluate the function, gradient, 
c     and the Hessian matrix.
c
c     The user must choose an initial approximation x to the minimizer,
c     lower bounds, upper bounds, quadratic terms, linear terms, and
c     constants about termination criterion.
c
c	parameters:
c
c       n is an integer variable.
c         On entry n is the number of variables.
c         On exit n is unchanged.
c
c       x is a double precision array of dimension n.
c         On entry x specifies the vector x.
c         On exit x is the final minimizer.
c
c       xl is a double precision array of dimension n.
c         On entry xl is the vector of lower bounds.
c         On exit xl is unchanged.
c
c       xu is a double precision array of dimension n.
c         On entry xu is the vector of upper bounds.
c         On exit xu is unchanged.
c
c       gtol is a double precision variable.
c         On entry gtol specifies the relative error of the projected 
c            gradient.
c         On exit gtol is unchanged. 
c
c       frtol is a double precision variable.
c         On entry frtol specifies the relative error desired in the
c            function. Convergence occurs if the estimate of the
c            relative error between f(x) and f(xsol), where xsol
c            is a local minimizer, is less than frtol.
c         On exit frtol is unchanged.
c
c       fatol is a double precision variable.
c         On entry fatol specifies the absolute error desired in the
c            function. Convergence occurs if the estimate of the
c            absolute error between f(x) and f(xsol), where xsol
c            is a local minimizer, is less than fatol.
c         On exit fatol is unchanged.
c
c       fmin is a double precision variable.
c         On entry fmin specifies a lower bound for the function.
c            The subroutine exits with a warning if f < fmin.
c         On exit fmin is unchanged.
c
c       maxfev is an integer variable.
c         On entry maxfev specifies the limit of function evaluations.
c         On exit maxfev is unchanged.
c
c       cgtol is a double precision variable.
c         On entry gqttol specifies the convergence criteria for
c            subproblems.
c         On exit gqttol is unchanged.
c
c     **********
*/

	/* Parameters for updating the iterates. */
	double eta0 = 1e-4, eta1 = 0.25, eta2 = 0.75;
	
	/* Parameters for updating the trust region size delta. */
	double sigma1 = 0.25, sigma2 = 0.5, sigma3 = 4;

	double p5 = 0.5, one = 1;
	double gnorm, gnorm0, delta, snorm;
	double alphac = 1, alpha, f, fc, prered, actred, gs;
	int search = 1, iter = 1, info, inc = 1;	
	double *xc = (double *) xmalloc(sizeof(double)*n);
	double *s = (double *) xmalloc(sizeof(double)*n);
	double *wa = (double *) xmalloc(sizeof(double)*n); 	
	double *g = (double *) xmalloc(sizeof(double)*n);
	double *A = NULL;

	uhes(n, x, &A);
	ugrad(n, x, g);	
	ufv(n, x, &f);	
	gnorm0 = F77_CALL(dnrm2)(&n, g, &inc);
	delta = 1000*gnorm0;
	gnorm = dgpnrm(n, x, xl, xu, g);
	if (gnorm <= gtol*gnorm0)
	{
		/*
		//printf("CONVERGENCE: GTOL TEST SATISFIED\n");
		*/
		search = 0;
	}

	while (search)
	{ 

		/* Save the best function value and the best x. */   
		fc = f;
		memcpy(xc, x, sizeof(double)*n);
		
		/* Compute the Cauchy step and store in s. */		
		dcauchy(n, x, xl, xu, A, g, delta, &alphac, s, wa);
		
		/* Compute the projected Newton step. */		
		dspcg(n, x, xl, xu, A, g, delta, cgtol, s, &info);
		if (ufv(n, x, &f) > maxfev)
		{
			/*
			//printf("ERROR: NFEV > MAXFEV\n");
			*/
			search = 0;
			continue;
		}

		/* Compute the predicted reduction. */
		memcpy(wa, g, sizeof(double)*n);
		F77_CALL(dsymv)("U", &n, &p5, A, &n, s, &inc, &one, wa, &inc);
		prered = -F77_CALL(ddot)(&n, s, &inc, wa, &inc);
                        
		/* Compute the actual reduction. */
	        actred = fc - f;                
                                    
		/* On the first iteration, adjust the initial step bound. */
		snorm = F77_CALL(dnrm2)(&n, s, &inc);
		if (iter == 1)
			delta = mymin(delta, snorm);

		/* Compute prediction alpha*snorm of the step. */
		gs = F77_CALL(ddot)(&n, g, &inc, s, &inc);

		if (f - fc - gs <= 0)
			alpha = sigma3;
		else
			alpha = mymax(sigma1, -0.5*(gs/(f - fc - gs)));

		/* Update the trust region bound according to the ratio
		of actual to predicted reduction. */
		if (actred < eta0*prered)
		
			/* Reduce delta. Step is not successful. */
			delta = mymin(mymax(alpha, sigma1)*snorm, sigma2*delta);
		else 
		{
			if (actred < eta1*prered)

				/* Reduce delta. Step is not sufficiently successful. */
				delta = mymax(sigma1*delta, mymin(alpha*snorm, sigma2*delta));
			else 
				if (actred < eta2*prered)
				
					/* The ratio of actual to predicted reduction is in
					the interval (eta1,eta2). We are allowed to either
					increase or decrease delta. */
					delta = mymax(sigma1*delta, mymin(alpha*snorm, sigma3*delta));
				else
				
					/* The ratio of actual to predicted reduction exceeds eta2.
					Do not decrease delta. */
					delta = mymax(delta, mymin(alpha*snorm, sigma3*delta));
		}

		/* Update the iterate. */
		if (actred > eta0*prered) 
		{
		
			/* Successful iterate. */
			iter++;
			/*
			uhes(n, x, &A);
			*/
			ugrad(n, x, g);
			gnorm = dgpnrm(n, x, xl, xu, g);		
			if (gnorm <= gtol*gnorm0)
        		{
				/*
				//printf("CONVERGENCE: GTOL = %g TEST SATISFIED\n", gnorm/gnorm0);
				*/
				search = 0;
		                continue;
			}
		}
		else
		{

			/* Unsuccessful iterate. */
			memcpy(x, xc, sizeof(double)*n);
			f = fc;
		}
	
		/* Test for convergence */
		if (f < fmin)
		{
			//printf("WARNING: F .LT. FMIN\n");
			search = 0; /* warning */
			continue;
		}
		if (fabs(actred) <= fatol && prered <= fatol)
		{
			//printf("CONVERGENCE: FATOL TEST SATISFIED\n");
			search = 0;
			continue;
		}
		if (fabs(actred) <= frtol*fabs(f) && prered <= frtol*fabs(f))
		{
			/*
			//printf("CONVERGENCE: FRTOL TEST SATISFIED\n");		
			*/
			search = 0;
			continue;
		}
	}	

	free(g);
	free(xc);
	free(s);
	free(wa);
}
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;
}
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;
}