Commit c5b7a36e authored by julient31's avatar julient31
Browse files

Commit JT 072619

- added a min_style option for norm type (euclidean or Max)
- adapted and tested spin minimizers
- adapted (net tested) regular minimizers
parent 883f6d1e
Loading
Loading
Loading
Loading
+14 −76
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ void MinSpin::reset_vectors()
int MinSpin::iterate(int maxiter)
{
  bigint ntimestep;
  double fmdotfm;
  double fmdotfm,fmsq,fmsqall;
  int flag,flagall;

  for (int iter = 0; iter < maxiter; iter++) {
@@ -166,8 +166,20 @@ int MinSpin::iterate(int maxiter)
    // magnetic torque tolerance criterion
    // sync across replicas if running multi-replica minimization

    fmdotfm = fmsq = fmsqall = 0.0;
    if (update->ftol > 0.0) {
      fmdotfm = max_torque();
      if (normstyle == 1) {		// max torque norm
	fmsq = max_torque();
	fmsqall = fmsq;
	if (update->multireplica == 0)
	  MPI_Allreduce(&fmsq,&fmsqall,1,MPI_INT,MPI_MAX,universe->uworld);
      } else {				// Euclidean torque norm
	fmsq = total_torque();
	fmsqall = fmsq;
	if (update->multireplica == 0)
	  MPI_Allreduce(&fmsq,&fmsqall,1,MPI_INT,MPI_SUM,universe->uworld);
      }
      fmdotfm = fmsqall*fmsqall;
      if (update->multireplica == 0) {
        if (fmdotfm < update->ftol*update->ftol) return FTOL;
      } else {
@@ -297,77 +309,3 @@ void MinSpin::advance_spins(double dts)
    // because no need for simplecticity
  }
}

/* ----------------------------------------------------------------------
   compute and return ||mag. torque||_2^2
------------------------------------------------------------------------- */

double MinSpin::fmnorm_sqr()
{
  int nlocal = atom->nlocal;
  double tx,ty,tz;
  double **sp = atom->sp;
  double **fm = atom->fm;

  // calc. magnetic torques

  double local_norm2_sqr = 0.0;
  for (int i = 0; i < nlocal; i++) {
    tx = (fm[i][1]*sp[i][2] - fm[i][2]*sp[i][1]);
    ty = (fm[i][2]*sp[i][0] - fm[i][0]*sp[i][2]);
    tz = (fm[i][0]*sp[i][1] - fm[i][1]*sp[i][0]);

    local_norm2_sqr += tx*tx + ty*ty + tz*tz;
  }

  // no extra atom calc. for spins

  if (nextra_atom)
    error->all(FLERR,"extra atom option not available yet");

  double norm2_sqr = 0.0;
  MPI_Allreduce(&local_norm2_sqr,&norm2_sqr,1,MPI_DOUBLE,MPI_SUM,world);

  return norm2_sqr;
}

/* ----------------------------------------------------------------------
   compute and return  max_i||mag. torque_i||_2
------------------------------------------------------------------------- */

double MinSpin::max_torque()
{
  double fmsq,fmaxsqone,fmaxsqloc,fmaxsqall;
  int nlocal = atom->nlocal;
  double hbar = force->hplanck/MY_2PI;
  double tx,ty,tz;
  double **sp = atom->sp;
  double **fm = atom->fm;

  fmsq = fmaxsqone = fmaxsqloc = fmaxsqall = 0.0;
  for (int i = 0; i < nlocal; i++) {
    tx = fm[i][1] * sp[i][2] - fm[i][2] * sp[i][1];
    ty = fm[i][2] * sp[i][0] - fm[i][0] * sp[i][2];
    tz = fm[i][0] * sp[i][1] - fm[i][1] * sp[i][0];
    fmsq = tx * tx + ty * ty + tz * tz;
    fmaxsqone = MAX(fmaxsqone,fmsq);
  }

  // finding max fm on this replica

  fmaxsqloc = fmaxsqone;
  MPI_Allreduce(&fmaxsqone,&fmaxsqloc,1,MPI_DOUBLE,MPI_MAX,world);

  // finding max fm over all replicas, if necessary
  // this communicator would be invalid for multiprocess replicas

  fmaxsqall = fmaxsqloc;
  if (update->multireplica == 1) {
    fmaxsqall = fmaxsqloc;
    MPI_Allreduce(&fmaxsqloc,&fmaxsqall,1,MPI_DOUBLE,MPI_MAX,universe->uworld);
  }

  // multiply it by hbar so that units are in eV

  return sqrt(fmaxsqall) * hbar;
}
+0 −2
Original line number Diff line number Diff line
@@ -35,8 +35,6 @@ class MinSpin : public Min {
  int iterate(int);
  double evaluate_dt();
  void advance_spins(double);
  double fmnorm_sqr();
  double max_torque();

 private:

+38 −56
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "universe.h"
#include "atom.h"
#include "citeme.h"
#include "comm.h"
#include "force.h"
#include "update.h"
#include "output.h"
@@ -99,6 +100,13 @@ void MinSpinOSO_CG::init()

  Min::init();

  // warning if line_search combined to gneb

  if ((nreplica >= 1) && (linestyle != 4) && (comm->me == 0))
    error->warning(FLERR,"Line search incompatible gneb");

  // set back use_line_search to 0 if more than one replica
  
  if (linestyle == 3 && nreplica == 1){
    use_line_search = 1;
  }
@@ -175,7 +183,7 @@ int MinSpinOSO_CG::iterate(int maxiter)
{
  int nlocal = atom->nlocal;
  bigint ntimestep;
  double fmdotfm;
  double fmdotfm,fmsq,fmsqall;
  int flag, flagall;
  double **sp = atom->sp;
  double der_e_cur_tmp = 0.0;
@@ -261,8 +269,20 @@ int MinSpinOSO_CG::iterate(int maxiter)
    // magnetic torque tolerance criterion
    // sync across replicas if running multi-replica minimization

    fmdotfm = fmsq = fmsqall = 0.0;
    if (update->ftol > 0.0) {
      fmdotfm = max_torque();
      if (normstyle == 1) {		// max torque norm
	fmsq = max_torque();
	fmsqall = fmsq;
	if (update->multireplica == 0)
	  MPI_Allreduce(&fmsq,&fmsqall,1,MPI_INT,MPI_MAX,universe->uworld);
      } else {				// Euclidean torque norm
	fmsq = total_torque();
	fmsqall = fmsq;
	if (update->multireplica == 0)
	  MPI_Allreduce(&fmsq,&fmsqall,1,MPI_INT,MPI_SUM,universe->uworld);
      }
      fmdotfm = fmsqall*fmsqall;
      if (update->multireplica == 0) {
        if (fmdotfm < update->ftol*update->ftol) return FTOL;
      } else {
@@ -353,6 +373,7 @@ void MinSpinOSO_CG::calc_search_direction()
    MPI_Allreduce(&g2old,&g2old_global,1,MPI_DOUBLE,MPI_SUM,world);

    // Sum over all replicas. Good for GNEB.
    
    if (nreplica > 1) {
      g2 = g2_global * factor;
      g2old = g2old_global * factor;
@@ -361,7 +382,9 @@ void MinSpinOSO_CG::calc_search_direction()
    }
    if (fabs(g2_global) < 1.0e-60) beta = 0.0;
    else beta = g2_global / g2old_global;
    
    // calculate conjugate direction
    
    for (int i = 0; i < 3 * nlocal; i++) {
      p_s[i] = (beta * p_s[i] - g_cur[i]) * factor;
      g_old[i] = g_cur[i] * factor;
@@ -394,47 +417,6 @@ void MinSpinOSO_CG::advance_spins()
  }
}

/* ----------------------------------------------------------------------
   compute and return  max_i||mag. torque_i||_2
------------------------------------------------------------------------- */

double MinSpinOSO_CG::max_torque()
{
  double fmsq,fmaxsqone,fmaxsqloc,fmaxsqall;
  int nlocal = atom->nlocal;
  double factor;
  double hbar = force->hplanck/MY_2PI;

  if (use_line_search) factor = 1.0;
  else factor = hbar;

  // finding max fm on this proc.

  fmsq = fmaxsqone = fmaxsqloc = fmaxsqall = 0.0;
  for (int i = 0; i < nlocal; i++) {
    fmsq = 0.0;
    for (int j = 0; j < 3; j++)
      fmsq += g_cur[3 * i + j] * g_cur[3 * i + j];
    fmaxsqone = MAX(fmaxsqone,fmsq);
  }

  // finding max fm on this replica

  fmaxsqloc = fmaxsqone;
  MPI_Allreduce(&fmaxsqone,&fmaxsqloc,1,MPI_DOUBLE,MPI_MAX,world);

  // finding max fm over all replicas, if necessary
  // this communicator would be invalid for multiprocess replicas

  fmaxsqall = fmaxsqloc;
  if (update->multireplica == 1) {
    fmaxsqall = fmaxsqloc;
    MPI_Allreduce(&fmaxsqloc,&fmaxsqall,1,MPI_DOUBLE,MPI_MAX,universe->uworld);
  }

  return sqrt(fmaxsqall) * factor;
}

/* ----------------------------------------------------------------------
  calculate 3x3 matrix exponential using Rodrigues' formula
  (R. Murray, Z. Li, and S. Shankar Sastry,
@@ -457,12 +439,11 @@ void MinSpinOSO_CG::rodrigues_rotation(const double *upp_tr, double *out)
      fabs(upp_tr[2]) < 1.0e-40){

    // if upp_tr is zero, return unity matrix
    
    for(int k = 0; k < 3; k++){
      for(int m = 0; m < 3; m++){
      if (m == k)
        out[3 * k + m] = 1.0;
      else
        out[3 * k + m] = 0.0;
        if (m == k) out[3 * k + m] = 1.0;
        else out[3 * k + m] = 0.0;
      }
    }
    return;
@@ -512,13 +493,14 @@ void MinSpinOSO_CG::rodrigues_rotation(const double *upp_tr, double *out)
void MinSpinOSO_CG::vm3(const double *m, const double *v, double *out)
{
  for(int i = 0; i < 3; i++){
    //out[i] *= 0.0;
    out[i] = 0.0;
    for(int j = 0; j < 3; j++)
    out[i] += *(m + 3 * j + i) * v[j];
    for(int j = 0; j < 3; j++) out[i] += *(m + 3 * j + i) * v[j];
  }
}

/* ----------------------------------------------------------------------
  advance spins
------------------------------------------------------------------------- */

void MinSpinOSO_CG::make_step(double c, double *energy_and_der)
{
+36 −36
Original line number Diff line number Diff line
@@ -30,37 +30,37 @@ class MinSpinOSO_CG: public Min {
  virtual ~MinSpinOSO_CG();
  void init();
  void setup_style();
    int modify_param(int, char **);
  void reset_vectors();
  int modify_param(int, char **);
  int iterate(int);

 private:
  int local_iter;		// for neb
  int nlocal_max;		// max value of nlocal (for size of lists)
  int use_line_search;		// use line search or not.
  int ireplica,nreplica;	// for neb
  double dt;			// global timestep
  double dts;			// spin timestep
    int ireplica,nreplica; // for neb
  double discrete_factor;	// factor for spin timestep evaluation
  double der_e_cur;		// current derivative along search dir.
  double der_e_pr;		// previous derivative along search dir.
  double *spvec;		// variables for atomic dof, as 1d vector
  double *fmvec;		// variables for atomic dof, as 1d vector
  double *g_old;  		// gradient vector at previous step
  double *g_cur;  		// current gradient vector
  double *p_s;  		// search direction vector
  double **sp_copy;		// copy of the spins
    int local_iter;     // for neb
    int nlocal_max;		// max value of nlocal (for size of lists)
    double discrete_factor;	// factor for spin timestep evaluation

    double evaluate_dt();
  void advance_spins();
  void calc_gradient();
  void calc_search_direction();
    double maximum_rotation(double *);
  void vm3(const double *, const double *, double *);
  void rodrigues_rotation(const double *, double *);
  void make_step(double, double *);
  int calc_and_make_step(double, double, int);
  int awc(double, double, double, double);
    void make_step(double, double *);
    double max_torque();
    double der_e_cur;   // current derivative along search dir.
    double der_e_pr;    // previous derivative along search dir.
    int use_line_search; // use line search or not.
  double evaluate_dt();
  double maximum_rotation(double *);

  bigint last_negative;
};
+22 −39
Original line number Diff line number Diff line
@@ -26,9 +26,9 @@
#include <cstdlib>
#include <cstring>
#include "min_spin_oso_lbfgs.h"
#include "universe.h"
#include "atom.h"
#include "citeme.h"
#include "comm.h"
#include "force.h"
#include "update.h"
#include "output.h"
@@ -107,6 +107,13 @@ void MinSpinOSO_LBFGS::init()

  Min::init();

  // warning if line_search combined to gneb

  if ((nreplica >= 1) && (linestyle != 4) && (comm->me == 0))
    error->warning(FLERR,"Line search incompatible gneb");

  // set back use_line_search to 0 if more than one replica

  if (linestyle != 4 && nreplica == 1){
    use_line_search = 1;
  }
@@ -188,7 +195,7 @@ int MinSpinOSO_LBFGS::iterate(int maxiter)
{
  int nlocal = atom->nlocal;
  bigint ntimestep;
  double fmdotfm;
  double fmdotfm,fmsq,fmsqall;
  int flag, flagall;
  double **sp = atom->sp;
  double der_e_cur_tmp = 0.0;
@@ -280,8 +287,20 @@ int MinSpinOSO_LBFGS::iterate(int maxiter)
    // magnetic torque tolerance criterion
    // sync across replicas if running multi-replica minimization

    fmdotfm = fmsq = fmsqall = 0.0;
    if (update->ftol > 0.0) {
      fmdotfm = max_torque();
      if (normstyle == 1) {		// max torque norm
	fmsq = max_torque();
	fmsqall = fmsq;
	if (update->multireplica == 0)
	  MPI_Allreduce(&fmsq,&fmsqall,1,MPI_INT,MPI_MAX,universe->uworld);
      } else {				// Euclidean torque norm
	fmsq = total_torque();
	fmsqall = fmsq;
	if (update->multireplica == 0)
	  MPI_Allreduce(&fmsq,&fmsqall,1,MPI_INT,MPI_SUM,universe->uworld);
      }
      fmdotfm = fmsqall*fmsqall;
      if (update->multireplica == 0) {
        if (fmdotfm < update->ftol*update->ftol) return FTOL;
      } else {
@@ -534,42 +553,6 @@ void MinSpinOSO_LBFGS::advance_spins()
  }
}

/* ----------------------------------------------------------------------
   compute and return  max_i||mag. torque_i||_2
------------------------------------------------------------------------- */

double MinSpinOSO_LBFGS::max_torque()
{
  double fmsq,fmaxsqone,fmaxsqloc,fmaxsqall;
  int nlocal = atom->nlocal;

  // finding max fm on this proc.

  fmsq = fmaxsqone = fmaxsqloc = fmaxsqall = 0.0;
  for (int i = 0; i < nlocal; i++) {
    fmsq = 0.0;
    for (int j = 0; j < 3; j++)
      fmsq += g_cur[3 * i + j] * g_cur[3 * i + j];
    fmaxsqone = MAX(fmaxsqone,fmsq);
  }

  // finding max fm on this replica

  fmaxsqloc = fmaxsqone;
  MPI_Allreduce(&fmaxsqone,&fmaxsqloc,1,MPI_DOUBLE,MPI_MAX,world);

  // finding max fm over all replicas, if necessary
  // this communicator would be invalid for multiprocess replicas

  fmaxsqall = fmaxsqloc;
  if (update->multireplica == 1) {
    fmaxsqall = fmaxsqloc;
    MPI_Allreduce(&fmaxsqloc,&fmaxsqall,1,MPI_DOUBLE,MPI_MAX,universe->uworld);
  }

  return sqrt(fmaxsqall);
}

/* ----------------------------------------------------------------------
  calculate 3x3 matrix exponential using Rodrigues' formula
  (R. Murray, Z. Li, and S. Shankar Sastry,
Loading