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) { } }
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; }