Commit e3ed8d85 authored by alxvov's avatar alxvov
Browse files

parallelisation of lbfgs, change indentation, more comments

parent 707c5b13
Loading
Loading
Loading
Loading
+26 −8
Changes for src/SPIN/min_spin_oso_lbfgs_ls.cpp: 26 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@
------------------------------------------------------------------------- */

/* ------------------------------------------------------------------------
   Contributing authors: Aleksei Ivanov (UI)
   Contributing authors: Aleksei Ivanov (University of Iceland)
                         Julien Tranchida (SNL)

   Please cite the related publication:
@@ -176,6 +176,7 @@ int MinSpinOSO_LBFGS_LS::iterate(int maxiter)
  double fmdotfm;
  int flag, flagall;
  double **sp = atom->sp;
  double der_e_cur_global = 0.0;

  if (nlocal_max < nlocal) {
    nlocal_max = nlocal;
@@ -213,6 +214,8 @@ int MinSpinOSO_LBFGS_LS::iterate(int maxiter)
      for (int i = 0; i < 3 * nlocal; i++) {
        der_e_cur += g_cur[i] * p_s[i];
      }
      MPI_Allreduce(&der_e_cur, &der_e_cur_global, 1, MPI_DOUBLE, MPI_SUM, world);
      der_e_cur = der_e_cur_global;
    }

    if (use_line_search){
@@ -353,7 +356,10 @@ void MinSpinOSO_LBFGS_LS::calc_gradient(double dts)
}

/* ----------------------------------------------------------------------
   search direction
   search direction:
   Limited-memory BFGS.
   See Jorge Nocedal and Stephen J. Wright 'Numerical
   Optimization' Second Edition, 2006 (p. 177)
---------------------------------------------------------------------- */

void MinSpinOSO_LBFGS_LS::calc_search_direction(int iter)
@@ -629,9 +635,9 @@ void MinSpinOSO_LBFGS_LS::make_step(double c, double *energy_and_der)
  double rot_mat[9]; // exponential of matrix made of search direction
  double s_new[3];
  double **sp = atom->sp;
  double der_e_cur_global = 0.0;;

  for (int i = 0; i < nlocal; i++) {

    // scale the search direction

    for (int j = 0; j < 3; j++) p_scaled[j] = c * p_s[3 * i + j];
@@ -653,10 +659,17 @@ void MinSpinOSO_LBFGS_LS::make_step(double c, double *energy_and_der)
    for (int i = 0; i < 3 * nlocal; i++) {
        der_e_cur += g_cur[i] * p_s[i];
    }
    MPI_Allreduce(&der_e_cur, &der_e_cur_global, 1, MPI_DOUBLE, MPI_SUM, world);
    der_e_cur = der_e_cur_global;

    energy_and_der[0] = ecurrent;
    energy_and_der[1] = der_e_cur;
}

/* ----------------------------------------------------------------------
  Calculate step length which satisfies approximate Wolfe conditions
  using the cubic interpolation
------------------------------------------------------------------------- */

int MinSpinOSO_LBFGS_LS::calc_and_make_step(double a, double b, int index)
{
@@ -671,6 +684,7 @@ int MinSpinOSO_LBFGS_LS::calc_and_make_step(double a, double b, int index)
  index++;

  if (awc(der_e_pr, eprevious, e_and_d[1], e_and_d[0]) || index == 3){
    MPI_Bcast(&b,1,MPI_DOUBLE,0,world);

      for (int i = 0; i < 3 * nlocal; i++) {
        p_s[i] = b * p_s[i];
@@ -689,6 +703,9 @@ int MinSpinOSO_LBFGS_LS::calc_and_make_step(double a, double b, int index)
    c2 = 3.0*(f1-f0)/(r*r)-(df1+2.0*df0)/(r);
    c3 = df0;

    // f(x) = c1 x^3 + c2 x^2 + c3 x^1 + c4
    // has minimum at alpha below. We do not check boundaries.

    alpha = (-c2 + sqrt(c2*c2 - 3.0*c1*c3))/(3.0*c1);
    if (alpha < 0.0) alpha = r/2.0;

@@ -699,18 +716,19 @@ int MinSpinOSO_LBFGS_LS::calc_and_make_step(double a, double b, int index)
   }

  return 0;

}


/* ----------------------------------------------------------------------
  Approximate Wolfe conditions:
  William W. Hager and Hongchao Zhang
  SIAM J. optim., 16(1), 170-192. (23 pages)
------------------------------------------------------------------------- */
int MinSpinOSO_LBFGS_LS::awc(double der_phi_0, double phi_0, double der_phi_j, double phi_j){

  double eps = 1.0e-6;
  double delta = 0.1;
  double sigma = 0.9;

    if ((phi_j <= phi_0 + eps * fabs(phi_0)) &&
        ((2.0*delta - 1.0) * der_phi_0 >= der_phi_j >= sigma * der_phi_0))
  if ((phi_j <= phi_0 + eps * fabs(phi_0)) && ((2.0*delta - 1.0) * der_phi_0 >= der_phi_j >= sigma * der_phi_0))
    return 1;
  else
    return 0;