6#ifndef __B2LINE_SEARCH_H__ 
    7#define __B2LINE_SEARCH_H__ 
   15inline double put_in_range(
double min, 
double max, 
double v) {
 
   16    if (v < min) { 
return min; }
 
   17    if (v > max) { 
return max; }
 
   21inline double poly_min_extrap(
double f0, 
double d0, 
double f1) {
 
   22    const double temp = 2 * (f1 - f0 - d0);
 
   23    if (std::abs(temp) <= d0 * std::numeric_limits<double>::epsilon()) { 
return 0.5; }
 
   25    const double alpha = -d0 / temp;
 
   28    return put_in_range(0, 1, alpha);
 
   31inline double poly_min_extrap(
double f0, 
double d0, 
double f1, 
double d1) {
 
   32    const double n = 3 * (f1 - f0) - 2 * d0 - d1;
 
   33    const double e = d0 + d1 - 2 * (f1 - f0);
 
   37    double temp = std::max(n * n - 3 * e * d0, 0.0);
 
   39    if (temp < 0) { 
return 0.5; }
 
   41    temp = std::sqrt(temp);
 
   43    if (std::abs(e) <= std::numeric_limits<double>::epsilon()) { 
return 0.5; }
 
   46    double x1 = (temp - n) / (3 * e);
 
   47    double x2 = -(temp + n) / (3 * e);
 
   50    double y1 = f0 + d0 * x1 + n * x1 * x1 + e * x1 * x1 * x1;
 
   51    double y2 = f0 + d0 * x2 + n * x2 * x2 + e * x2 * x2 * x2;
 
   62    return put_in_range(0, 1, x);
 
   65inline double poly_min_extrap(
 
   66      double f0, 
double d0, 
double x1, 
double f_x1, 
double x2, 
double f_x2) {
 
   67    assert(0 < x1 && x1 < x2);
 
   71    const double aa2 = x2 * x2;
 
   72    const double aa1 = x1 * x1;
 
   73    const double m[2][2] = {{aa2, -aa2 * x2}, {-aa1, aa1 * x1}};
 
   74    const double v[2] = {f_x1 - f0 - d0 * x1, f_x2 - f0 - d0 * x2};
 
   75    double temp = aa2 * aa1 * (x1 - x2);
 
   78    if (temp == 0) { 
return x1 / 2.0; }
 
   80    const double inv_temp = 1 / temp;
 
   81    const double a = inv_temp * (m[0][0] * v[0] + m[1][0] * v[1]);
 
   82    const double b = inv_temp * (m[0][1] * v[0] + m[1][1] * v[1]);
 
   84    temp = b * b - 3 * a * d0;
 
   85    if (temp < 0 || a == 0) {
 
   93    temp = (-b + std::sqrt(temp)) / (3 * a);
 
   94    return put_in_range(0, x2, temp);
 
   97template <
typename funct>
 
   99      const funct& f, 
const double f0, 
const double d0, 
double rho, 
double sigma, 
double min_f,
 
  100      unsigned long max_iter) {
 
  101    assert(0 < rho && rho < sigma && sigma < 1 && max_iter > 0);
 
  108    const double tau1 = 9;
 
  112    const double tau2 = 1.0 / 10.0;
 
  113    const double tau3 = 1.0 / 2.0;
 
  116    if (std::abs(d0) < std::numeric_limits<double>::epsilon()) { 
return 0; }
 
  119    if (f0 <= min_f) { 
return 0; }
 
  122    const double mu = (min_f - f0) / (rho * d0);
 
  125    if (mu < 0) { alpha = -alpha; }
 
  126    alpha = put_in_range(0, 0.65 * mu, alpha);
 
  128    double last_alpha = 0;
 
  129    double last_val = f0;
 
  130    double last_val_der = d0;
 
  137    double a_val, b_val, a_val_der, b_val_der;
 
  140    const double thresh = std::abs(sigma * d0);
 
  142    unsigned long itr = 0;
 
  147        const double val = f(alpha, val_der);
 
  151        if (val <= min_f) { 
return alpha; }
 
  153        if (val > f0 + rho * alpha * d0 || val >= last_val) {
 
  155            a_val_der = last_val_der;
 
  164        if (std::abs(val_der) <= thresh) { 
return alpha; }
 
  167        if (last_alpha == alpha || itr >= max_iter) { 
return alpha; }
 
  173            b_val_der = last_val_der;
 
  180        if (mu <= 2 * alpha - last_alpha) {
 
  184            const double temp = alpha;
 
  186            double first = 2 * alpha - last_alpha;
 
  189                last = std::min(mu, alpha + tau1 * (alpha - last_alpha));
 
  191                last = std::max(mu, alpha + tau1 * (alpha - last_alpha));
 
  195            if (last_alpha < alpha) {
 
  197                        + (alpha - last_alpha)
 
  198                                * poly_min_extrap(last_val, last_val_der, val, val_der);
 
  201                        + (last_alpha - alpha)
 
  202                                * poly_min_extrap(val, val_der, last_val, last_val_der);
 
  205            alpha = put_in_range(first, last, alpha);
 
  211        last_val_der = val_der;
 
  217        double first = a + tau2 * (b - a);
 
  218        double last = b - tau3 * (b - a);
 
  221        alpha = a + (b - a) * poly_min_extrap(a_val, a_val_der, b_val, b_val_der);
 
  222        alpha = put_in_range(first, last, alpha);
 
  225        const double val = f(alpha, val_der);
 
  229        if (val <= min_f || itr >= max_iter) { 
return alpha; }
 
  232        if (a == first || b == last) { 
return b; }
 
  234        if (val > f0 + rho * alpha * d0 || val >= a_val) {
 
  239            if (std::abs(val_der) <= thresh) { 
return alpha; }
 
  241            if ((b - a) * val_der >= 0) {
 
  244                b_val_der = a_val_der;
 
  254template <
typename funct>
 
  255double backtracking_line_search(
 
  256      const funct& f, 
double f0, 
double d0, 
double alpha, 
double rho, 
unsigned long max_iter) {
 
  257    assert(0 < rho && rho < 1 && max_iter > 0);
 
  261    if ((d0 > 0 && alpha > 0) || (d0 < 0 && alpha < 0)) { alpha *= -1; }
 
  263    bool have_prev_alpha = 
false;
 
  264    double prev_alpha = 0;
 
  266    unsigned long iter = 0;
 
  269        const double val = f(alpha);
 
  270        if (val <= f0 + alpha * rho * d0 || iter >= max_iter) {
 
  276            if (!have_prev_alpha) {
 
  278                    step = alpha * put_in_range(0.1, 0.9, poly_min_extrap(f0, d0, val));
 
  280                    step = alpha * put_in_range(0.1, 0.9, poly_min_extrap(f0, -d0, val));
 
  282                have_prev_alpha = 
true;
 
  286                          0.1 * alpha, 0.9 * alpha,
 
  287                          poly_min_extrap(f0, d0, alpha, val, prev_alpha, prev_val));
 
  290                          0.1 * alpha, 0.9 * alpha,
 
  291                          -poly_min_extrap(f0, -d0, -alpha, val, -prev_alpha, prev_val));
 
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32