Commit JT 072619

- added a min_style option for norm type (euclidean or Max)
- adapted and tested spin minimizers
- adapted (net tested) regular minimizers
This commit is contained in:
julient31 2019-07-26 17:33:49 -06:00
parent 883f6d1e8d
commit c5b7a36eeb
13 changed files with 266 additions and 258 deletions

View File

@ -119,7 +119,7 @@ void MinSpin::reset_vectors()
int MinSpin::iterate(int maxiter) int MinSpin::iterate(int maxiter)
{ {
bigint ntimestep; bigint ntimestep;
double fmdotfm; double fmdotfm,fmsq,fmsqall;
int flag,flagall; int flag,flagall;
for (int iter = 0; iter < maxiter; iter++) { for (int iter = 0; iter < maxiter; iter++) {
@ -166,8 +166,20 @@ int MinSpin::iterate(int maxiter)
// magnetic torque tolerance criterion // magnetic torque tolerance criterion
// sync across replicas if running multi-replica minimization // sync across replicas if running multi-replica minimization
fmdotfm = fmsq = fmsqall = 0.0;
if (update->ftol > 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 (update->multireplica == 0) {
if (fmdotfm < update->ftol*update->ftol) return FTOL; if (fmdotfm < update->ftol*update->ftol) return FTOL;
} else { } else {
@ -297,77 +309,3 @@ void MinSpin::advance_spins(double dts)
// because no need for simplecticity // 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;
}

View File

@ -35,8 +35,6 @@ class MinSpin : public Min {
int iterate(int); int iterate(int);
double evaluate_dt(); double evaluate_dt();
void advance_spins(double); void advance_spins(double);
double fmnorm_sqr();
double max_torque();
private: private:

View File

@ -29,6 +29,7 @@
#include "universe.h" #include "universe.h"
#include "atom.h" #include "atom.h"
#include "citeme.h" #include "citeme.h"
#include "comm.h"
#include "force.h" #include "force.h"
#include "update.h" #include "update.h"
#include "output.h" #include "output.h"
@ -99,6 +100,13 @@ void MinSpinOSO_CG::init()
Min::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){ if (linestyle == 3 && nreplica == 1){
use_line_search = 1; use_line_search = 1;
} }
@ -175,7 +183,7 @@ int MinSpinOSO_CG::iterate(int maxiter)
{ {
int nlocal = atom->nlocal; int nlocal = atom->nlocal;
bigint ntimestep; bigint ntimestep;
double fmdotfm; double fmdotfm,fmsq,fmsqall;
int flag, flagall; int flag, flagall;
double **sp = atom->sp; double **sp = atom->sp;
double der_e_cur_tmp = 0.0; double der_e_cur_tmp = 0.0;
@ -261,8 +269,20 @@ int MinSpinOSO_CG::iterate(int maxiter)
// magnetic torque tolerance criterion // magnetic torque tolerance criterion
// sync across replicas if running multi-replica minimization // sync across replicas if running multi-replica minimization
fmdotfm = fmsq = fmsqall = 0.0;
if (update->ftol > 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 (update->multireplica == 0) {
if (fmdotfm < update->ftol*update->ftol) return FTOL; if (fmdotfm < update->ftol*update->ftol) return FTOL;
} else { } else {
@ -353,6 +373,7 @@ void MinSpinOSO_CG::calc_search_direction()
MPI_Allreduce(&g2old,&g2old_global,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&g2old,&g2old_global,1,MPI_DOUBLE,MPI_SUM,world);
// Sum over all replicas. Good for GNEB. // Sum over all replicas. Good for GNEB.
if (nreplica > 1) { if (nreplica > 1) {
g2 = g2_global * factor; g2 = g2_global * factor;
g2old = g2old_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; if (fabs(g2_global) < 1.0e-60) beta = 0.0;
else beta = g2_global / g2old_global; else beta = g2_global / g2old_global;
// calculate conjugate direction // calculate conjugate direction
for (int i = 0; i < 3 * nlocal; i++) { for (int i = 0; i < 3 * nlocal; i++) {
p_s[i] = (beta * p_s[i] - g_cur[i]) * factor; p_s[i] = (beta * p_s[i] - g_cur[i]) * factor;
g_old[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 calculate 3x3 matrix exponential using Rodrigues' formula
(R. Murray, Z. Li, and S. Shankar Sastry, (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){ fabs(upp_tr[2]) < 1.0e-40){
// if upp_tr is zero, return unity matrix // if upp_tr is zero, return unity matrix
for(int k = 0; k < 3; k++){ for(int k = 0; k < 3; k++){
for(int m = 0; m < 3; m++){ for(int m = 0; m < 3; m++){
if (m == k) if (m == k) out[3 * k + m] = 1.0;
out[3 * k + m] = 1.0; else out[3 * k + m] = 0.0;
else
out[3 * k + m] = 0.0;
} }
} }
return; 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) void MinSpinOSO_CG::vm3(const double *m, const double *v, double *out)
{ {
for(int i = 0; i < 3; i++){ for(int i = 0; i < 3; i++){
//out[i] *= 0.0;
out[i] = 0.0; out[i] = 0.0;
for(int j = 0; j < 3; j++) for(int j = 0; j < 3; j++) out[i] += *(m + 3 * j + i) * v[j];
out[i] += *(m + 3 * j + i) * v[j];
} }
} }
/* ----------------------------------------------------------------------
advance spins
------------------------------------------------------------------------- */
void MinSpinOSO_CG::make_step(double c, double *energy_and_der) void MinSpinOSO_CG::make_step(double c, double *energy_and_der)
{ {
@ -586,7 +568,7 @@ int MinSpinOSO_CG::calc_and_make_step(double a, double b, int index)
} }
return 1; return 1;
} }
else{ else {
double r,f0,f1,df0,df1; double r,f0,f1,df0,df1;
r = b - a; r = b - a;
f0 = eprevious; f0 = eprevious;

View File

@ -30,37 +30,37 @@ class MinSpinOSO_CG: public Min {
virtual ~MinSpinOSO_CG(); virtual ~MinSpinOSO_CG();
void init(); void init();
void setup_style(); void setup_style();
int modify_param(int, char **);
void reset_vectors(); void reset_vectors();
int modify_param(int, char **);
int iterate(int); int iterate(int);
private: 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 dt; // global timestep
double dts; // spin 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 *spvec; // variables for atomic dof, as 1d vector
double *fmvec; // 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_old; // gradient vector at previous step
double *g_cur; // current gradient vector double *g_cur; // current gradient vector
double *p_s; // search direction vector double *p_s; // search direction vector
double **sp_copy; // copy of the spins 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 advance_spins();
void calc_gradient(); void calc_gradient();
void calc_search_direction(); void calc_search_direction();
double maximum_rotation(double *);
void vm3(const double *, const double *, double *); void vm3(const double *, const double *, double *);
void rodrigues_rotation(const double *, double *); void rodrigues_rotation(const double *, double *);
void make_step(double, double *);
int calc_and_make_step(double, double, int); int calc_and_make_step(double, double, int);
int awc(double, double, double, double); int awc(double, double, double, double);
void make_step(double, double *); double evaluate_dt();
double max_torque(); double maximum_rotation(double *);
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.
bigint last_negative; bigint last_negative;
}; };

View File

@ -26,9 +26,9 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include "min_spin_oso_lbfgs.h" #include "min_spin_oso_lbfgs.h"
#include "universe.h"
#include "atom.h" #include "atom.h"
#include "citeme.h" #include "citeme.h"
#include "comm.h"
#include "force.h" #include "force.h"
#include "update.h" #include "update.h"
#include "output.h" #include "output.h"
@ -107,6 +107,13 @@ void MinSpinOSO_LBFGS::init()
Min::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){ if (linestyle != 4 && nreplica == 1){
use_line_search = 1; use_line_search = 1;
} }
@ -188,7 +195,7 @@ int MinSpinOSO_LBFGS::iterate(int maxiter)
{ {
int nlocal = atom->nlocal; int nlocal = atom->nlocal;
bigint ntimestep; bigint ntimestep;
double fmdotfm; double fmdotfm,fmsq,fmsqall;
int flag, flagall; int flag, flagall;
double **sp = atom->sp; double **sp = atom->sp;
double der_e_cur_tmp = 0.0; double der_e_cur_tmp = 0.0;
@ -280,8 +287,20 @@ int MinSpinOSO_LBFGS::iterate(int maxiter)
// magnetic torque tolerance criterion // magnetic torque tolerance criterion
// sync across replicas if running multi-replica minimization // sync across replicas if running multi-replica minimization
fmdotfm = fmsq = fmsqall = 0.0;
if (update->ftol > 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 (update->multireplica == 0) {
if (fmdotfm < update->ftol*update->ftol) return FTOL; if (fmdotfm < update->ftol*update->ftol) return FTOL;
} else { } 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 calculate 3x3 matrix exponential using Rodrigues' formula
(R. Murray, Z. Li, and S. Shankar Sastry, (R. Murray, Z. Li, and S. Shankar Sastry,

View File

@ -33,30 +33,30 @@ class MinSpinOSO_LBFGS: public Min {
int modify_param(int, char **); int modify_param(int, char **);
void reset_vectors(); void reset_vectors();
int iterate(int); int iterate(int);
private: private:
int local_iter; // for neb
int use_line_search; // use line search or not.
int nlocal_max; // max value of nlocal (for size of lists)
int ireplica,nreplica; // for neb int ireplica,nreplica; // for neb
double der_e_cur; // current derivative along search dir.
double der_e_pr; // previous derivative along search dir.
double maxepsrot;
double *spvec; // variables for atomic dof, as 1d vector double *spvec; // variables for atomic dof, as 1d vector
double *fmvec; // 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_old; // gradient vector at previous step
double *g_cur; // current gradient vector double *g_cur; // current gradient vector
double *p_s; // search direction vector double *p_s; // search direction vector
int local_iter; // for neb
int nlocal_max; // max value of nlocal (for size of lists)
void advance_spins(); void advance_spins();
void calc_gradient(); void calc_gradient();
void calc_search_direction(); void calc_search_direction();
double maximum_rotation(double *);
void vm3(const double *, const double *, double *); void vm3(const double *, const double *, double *);
void rodrigues_rotation(const double *, double *); void rodrigues_rotation(const double *, double *);
void make_step(double, double *);
int calc_and_make_step(double, double, int); int calc_and_make_step(double, double, int);
int awc(double, double, double, double); int awc(double, double, double, double);
void make_step(double, double *); double maximum_rotation(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 maxepsrot;
double *rho; // estimation of curvature double *rho; // estimation of curvature
double **ds; // change in rotation matrix between two iterations, da double **ds; // change in rotation matrix between two iterations, da

View File

@ -42,10 +42,12 @@
#include "output.h" #include "output.h"
#include "thermo.h" #include "thermo.h"
#include "timer.h" #include "timer.h"
#include "math_const.h"
#include "memory.h" #include "memory.h"
#include "error.h" #include "error.h"
using namespace LAMMPS_NS; using namespace LAMMPS_NS;
using namespace MathConst;
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -54,6 +56,7 @@ Min::Min(LAMMPS *lmp) : Pointers(lmp)
dmax = 0.1; dmax = 0.1;
searchflag = 0; searchflag = 0;
linestyle = 1; linestyle = 1;
normstyle = 0;
elist_global = elist_atom = NULL; elist_global = elist_atom = NULL;
vlist_global = vlist_atom = NULL; vlist_global = vlist_atom = NULL;
@ -653,6 +656,14 @@ void Min::modify_params(int narg, char **arg)
if (strcmp(arg[iarg+1],"backtrack") == 0) linestyle = 0; if (strcmp(arg[iarg+1],"backtrack") == 0) linestyle = 0;
else if (strcmp(arg[iarg+1],"quadratic") == 0) linestyle = 1; else if (strcmp(arg[iarg+1],"quadratic") == 0) linestyle = 1;
else if (strcmp(arg[iarg+1],"forcezero") == 0) linestyle = 2; else if (strcmp(arg[iarg+1],"forcezero") == 0) linestyle = 2;
else if (strcmp(arg[iarg+1],"spin_cubic") == 0) linestyle = 3;
else if (strcmp(arg[iarg+1],"spin_none") == 0) linestyle = 4;
else error->all(FLERR,"Illegal min_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"norm") == 0) {
if (iarg+2 > narg) error->all(FLERR,"Illegal min_modify command");
if (strcmp(arg[iarg+1],"euclidean") == 0) normstyle = 0;
else if (strcmp(arg[iarg+1],"max") == 0) normstyle = 1;
else error->all(FLERR,"Illegal min_modify command"); else error->all(FLERR,"Illegal min_modify command");
iarg += 2; iarg += 2;
} else { } else {
@ -816,6 +827,69 @@ double Min::fnorm_inf()
return norm_inf; return norm_inf;
} }
/* ----------------------------------------------------------------------
compute and return sum_i||mag. torque_i||_2 (in eV)
------------------------------------------------------------------------- */
double Min::total_torque()
{
double fmsq,ftotsqone,ftotsqall;
int nlocal = atom->nlocal;
double hbar = force->hplanck/MY_2PI;
double tx,ty,tz;
double **sp = atom->sp;
double **fm = atom->fm;
fmsq = ftotsqone = ftotsqall = 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;
ftotsqone += fmsq;
}
// summing all fmsqtot on this replica
MPI_Allreduce(&ftotsqone,&ftotsqall,1,MPI_DOUBLE,MPI_SUM,world);
// multiply it by hbar so that units are in eV
return sqrt(ftotsqall) * hbar;
}
/* ----------------------------------------------------------------------
compute and return max_i ||mag. torque_i|| (in eV)
------------------------------------------------------------------------- */
double Min::max_torque()
{
double fmsq,fmaxsqone,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 = 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
fmaxsqall = fmaxsqone;
MPI_Allreduce(&fmaxsqone,&fmaxsqall,1,MPI_DOUBLE,MPI_MAX,world);
// multiply it by hbar so that units are in eV
return sqrt(fmaxsqall) * hbar;
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
possible stop conditions possible stop conditions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */

View File

@ -42,6 +42,10 @@ class Min : protected Pointers {
double fnorm_sqr(); double fnorm_sqr();
double fnorm_inf(); double fnorm_inf();
// methods for spin minimizers
double max_torque();
double total_torque();
virtual void init_style() {} virtual void init_style() {}
virtual void setup_style() = 0; virtual void setup_style() = 0;
virtual void reset_vectors() = 0; virtual void reset_vectors() = 0;
@ -58,6 +62,9 @@ class Min : protected Pointers {
double dmax; // max dist to move any atom in one step double dmax; // max dist to move any atom in one step
int linestyle; // 0 = backtrack, 1 = quadratic, 2 = forcezero int linestyle; // 0 = backtrack, 1 = quadratic, 2 = forcezero
// 3 = spin_cubic, 4 = spin_none
int normstyle; // 0 = Euclidean norm, 1 = inf. norm
int nelist_global,nelist_atom; // # of PE,virial computes to check int nelist_global,nelist_atom; // # of PE,virial computes to check
int nvlist_global,nvlist_atom; int nvlist_global,nvlist_atom;
@ -102,9 +109,6 @@ class Min : protected Pointers {
double energy_force(int); double energy_force(int);
void force_clear(); void force_clear();
double compute_force_norm_sqr();
double compute_force_norm_inf();
void ev_setup(); void ev_setup();
void ev_set(bigint); void ev_set(bigint);

View File

@ -37,7 +37,7 @@ MinCG::MinCG(LAMMPS *lmp) : MinLineSearch(lmp) {}
int MinCG::iterate(int maxiter) int MinCG::iterate(int maxiter)
{ {
int i,m,n,fail,ntimestep; int i,m,n,fail,ntimestep;
double beta,gg,dot[2],dotall[2]; double beta,gg,dot[2],dotall[2],fmax,fmaxall;
double *fatom,*gatom,*hatom; double *fatom,*gatom,*hatom;
// nlimit = max # of CG iterations before restarting // nlimit = max # of CG iterations before restarting
@ -87,10 +87,12 @@ int MinCG::iterate(int maxiter)
// force tolerance criterion // force tolerance criterion
fmax = fmaxall = 0.0;
dot[0] = dot[1] = 0.0; dot[0] = dot[1] = 0.0;
for (i = 0; i < nvec; i++) { for (i = 0; i < nvec; i++) {
dot[0] += fvec[i]*fvec[i]; dot[0] += fvec[i]*fvec[i];
dot[1] += fvec[i]*g[i]; dot[1] += fvec[i]*g[i];
fmax = MAX(fmax,fvec[i]*fvec[i]);
} }
if (nextra_atom) if (nextra_atom)
for (m = 0; m < nextra_atom; m++) { for (m = 0; m < nextra_atom; m++) {
@ -100,16 +102,22 @@ int MinCG::iterate(int maxiter)
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
dot[0] += fatom[i]*fatom[i]; dot[0] += fatom[i]*fatom[i];
dot[1] += fatom[i]*gatom[i]; dot[1] += fatom[i]*gatom[i];
fmax = MAX(fmax,fatom[i]*fatom[i]);
} }
} }
MPI_Allreduce(dot,dotall,2,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(dot,dotall,2,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(&fmax,&fmaxall,2,MPI_DOUBLE,MPI_MAX,world);
if (nextra_global) if (nextra_global)
for (i = 0; i < nextra_global; i++) { for (i = 0; i < nextra_global; i++) {
dotall[0] += fextra[i]*fextra[i]; dotall[0] += fextra[i]*fextra[i];
dotall[1] += fextra[i]*gextra[i]; dotall[1] += fextra[i]*gextra[i];
} }
if (normstyle == 1) { // max force norm
if (fmax < update->ftol*update->ftol) return FTOL;
} else { // Euclidean force norm
if (dotall[0] < update->ftol*update->ftol) return FTOL; if (dotall[0] < update->ftol*update->ftol) return FTOL;
}
// update new search direction h from new f = -Grad(x) and old g // update new search direction h from new f = -Grad(x) and old g
// this is Polak-Ribieri formulation // this is Polak-Ribieri formulation

View File

@ -80,7 +80,7 @@ void MinFire::reset_vectors()
int MinFire::iterate(int maxiter) int MinFire::iterate(int maxiter)
{ {
bigint ntimestep; bigint ntimestep;
double vmax,vdotf,vdotfall,vdotv,vdotvall,fdotf,fdotfall; double vmax,vdotf,vdotfall,vdotv,vdotvall,fdotf,fdotfloc,fdotfall;
double scale1,scale2; double scale1,scale2;
double dtvone,dtv,dtf,dtfm; double dtvone,dtv,dtf,dtfm;
int flag,flagall; int flag,flagall;
@ -250,7 +250,15 @@ int MinFire::iterate(int maxiter)
// sync across replicas if running multi-replica minimization // sync across replicas if running multi-replica minimization
if (update->ftol > 0.0) { if (update->ftol > 0.0) {
if (normstyle == 1) { // max force norm
fdotf = fnorm_inf();
fdotfloc = fdotf;
MPI_Allreduce(&fdotfloc,&fdotf,1,MPI_INT,MPI_MAX,universe->uworld);
} else { // Euclidean force norm
fdotf = fnorm_sqr(); fdotf = fnorm_sqr();
fdotfloc = fdotf;
MPI_Allreduce(&fdotfloc,&fdotf,1,MPI_INT,MPI_SUM,universe->uworld);
}
if (update->multireplica == 0) { if (update->multireplica == 0) {
if (fdotf < update->ftol*update->ftol) return FTOL; if (fdotf < update->ftol*update->ftol) return FTOL;
} else { } else {

View File

@ -20,6 +20,7 @@
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
#include "atom.h" #include "atom.h"
#include "error.h"
#include "fix_minimize.h" #include "fix_minimize.h"
#include "min_hftn.h" #include "min_hftn.h"
#include "modify.h" #include "modify.h"
@ -111,6 +112,9 @@ void MinHFTN::init()
{ {
Min::init(); Min::init();
if (normstyle == 1)
error->all(FLERR,"Incorrect min_modify option");
for (int i = 1; i < NUM_HFTN_ATOM_BASED_VECTORS; i++) { for (int i = 1; i < NUM_HFTN_ATOM_BASED_VECTORS; i++) {
if (_daExtraGlobal[i] != NULL) if (_daExtraGlobal[i] != NULL)
delete [] _daExtraGlobal[i]; delete [] _daExtraGlobal[i];

View File

@ -76,7 +76,7 @@ void MinQuickMin::reset_vectors()
int MinQuickMin::iterate(int maxiter) int MinQuickMin::iterate(int maxiter)
{ {
bigint ntimestep; bigint ntimestep;
double vmax,vdotf,vdotfall,fdotf,fdotfall,scale; double vmax,vdotf,vdotfall,fdotf,fdotfloc,fdotfall,scale;
double dtvone,dtv,dtf,dtfm; double dtvone,dtv,dtf,dtfm;
int flag,flagall; int flag,flagall;
@ -216,7 +216,15 @@ int MinQuickMin::iterate(int maxiter)
// sync across replicas if running multi-replica minimization // sync across replicas if running multi-replica minimization
if (update->ftol > 0.0) { if (update->ftol > 0.0) {
if (normstyle == 1) { // max force norm
fdotf = fnorm_inf();
fdotfloc = fdotf;
MPI_Allreduce(&fdotfloc,&fdotf,1,MPI_INT,MPI_MAX,universe->uworld);
} else { // Euclidean force norm
fdotf = fnorm_sqr(); fdotf = fnorm_sqr();
fdotfloc = fdotf;
MPI_Allreduce(&fdotfloc,&fdotf,1,MPI_INT,MPI_SUM,universe->uworld);
}
if (update->multireplica == 0) { if (update->multireplica == 0) {
if (fdotf < update->ftol*update->ftol) return FTOL; if (fdotf < update->ftol*update->ftol) return FTOL;
} else { } else {

View File

@ -79,7 +79,8 @@ int MinSD::iterate(int maxiter)
// force tolerance criterion // force tolerance criterion
fdotf = fnorm_sqr(); if (normstyle == 1) fdotf = fnorm_inf(); // max force norm
else fdotf = fnorm_sqr(); // Euclidean force norm
if (fdotf < update->ftol*update->ftol) return FTOL; if (fdotf < update->ftol*update->ftol) return FTOL;
// set new search direction h to f = -Grad(x) // set new search direction h to f = -Grad(x)