diff --git a/src/SPIN/min_spin.cpp b/src/SPIN/min_spin.cpp index 2277281e80..9849ba9946 100644 --- a/src/SPIN/min_spin.cpp +++ b/src/SPIN/min_spin.cpp @@ -167,7 +167,7 @@ int MinSpin::iterate(int maxiter) // sync across replicas if running multi-replica minimization if (update->ftol > 0.0) { - fmdotfm = fmnorm_sqr(); + fmdotfm = max_torque(); if (update->multireplica == 0) { if (fmdotfm < update->ftol*update->ftol) return FTOL; } else { @@ -331,3 +331,43 @@ double MinSpin::fmnorm_sqr() 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; +} diff --git a/src/SPIN/min_spin.h b/src/SPIN/min_spin.h index fbc624a9cc..d6d49203d5 100644 --- a/src/SPIN/min_spin.h +++ b/src/SPIN/min_spin.h @@ -36,6 +36,7 @@ class MinSpin : public Min { double evaluate_dt(); void advance_spins(double); double fmnorm_sqr(); + double max_torque(); private: