fix neb bugfix from Emile Maras

NEB was not working fine when using multiple proc
per replica and the keywords last/efirst or last/efirst/middle

I have corrected this in the enclosed fix_neb.cpp

I also slightly modified the nudging for this free end so that
it would be applied only when the target energy is larger than
the energy. Anyway if the target energy is lower than the energy,
the replica should relax toward the target energy without adding
any nudging.

I also modified the documentation according to this change.
This commit is contained in:
Axel Kohlmeyer 2017-12-13 15:19:46 -05:00
parent 2f857c6eda
commit 9a71efc5d5
2 changed files with 39 additions and 37 deletions

View File

@ -138,17 +138,17 @@ By default, no additional forces act on the first and last replicas
during the NEB relaxation, so these replicas simply relax toward their during the NEB relaxation, so these replicas simply relax toward their
respective local minima. By using the key word {end}, additional respective local minima. By using the key word {end}, additional
forces can be applied to the first and/or last replicas, to enable forces can be applied to the first and/or last replicas, to enable
them to relax toward a MEP while constraining their energy. them to relax toward a MEP while constraining their energy E to the
target energy ETarget.
The interatomic force Fi for the specified replica becomes: If ETarget>E, the interatomic force Fi for the specified replica becomes:
Fi = -Grad(V) + (Grad(V) dot T' + (E-ETarget)*Kspring3) T', {when} Grad(V) dot T' < 0 Fi = -Grad(V) + (Grad(V) dot T' + (E-ETarget)*Kspring3) T', {when} Grad(V) dot T' < 0
Fi = -Grad(V) + (Grad(V) dot T' + (ETarget- E)*Kspring3) T', {when} Grad(V) dot T' > 0 Fi = -Grad(V) + (Grad(V) dot T' + (ETarget- E)*Kspring3) T', {when} Grad(V) dot T' > 0
:pre :pre
where E is the current energy of the replica and ETarget is the target The "spring" constant on the difference in energies is the specified
energy. The "spring" constant on the difference in energies is the {Kspring3} value.
specified {Kspring3} value.
When {estyle} is specified as {first}, the force is applied to the When {estyle} is specified as {first}, the force is applied to the
first replica. When {estyle} is specified as {last}, the force is first replica. When {estyle} is specified as {last}, the force is
@ -183,10 +183,9 @@ After converging a NEB calculation using an {estyle} of
have a larger energy than the first replica. If this is not the case, have a larger energy than the first replica. If this is not the case,
the path is probably not a MEP. the path is probably not a MEP.
Finally, note that if the last replica converges toward a local Finally, note that the last replica may never reach the target energy
minimum which has a larger energy than the energy of the first if it is stuck in a local minima which has a larger energy than the
replica, a NEB calculation using an {estyle} of {last/efirst} or target energy.
{last/efirst/middle} cannot reach final convergence.
[Restart, fix_modify, output, run start/stop, minimize info:] [Restart, fix_modify, output, run start/stop, minimize info:]

View File

@ -298,12 +298,14 @@ void FixNEB::min_post_force(int vflag)
if (ireplica == 0) vIni=veng; if (ireplica == 0) vIni=veng;
if (FreeEndFinalWithRespToEIni) { if (FreeEndFinalWithRespToEIni) {
if (me == 0) { if (cmode == SINGLE_PROC_DIRECT || cmode == SINGLE_PROC_MAP) {
int procFirst; int procFirst;
procFirst=universe->root_proc[0]; procFirst=universe->root_proc[0];
MPI_Bcast(&vIni,1,MPI_DOUBLE,procFirst,uworld); MPI_Bcast(&vIni,1,MPI_DOUBLE,procFirst,uworld);
} }else {
if (cmode == MULTI_PROC) { if (me == 0)
MPI_Bcast(&vIni,1,MPI_DOUBLE,0,rootworld);
MPI_Bcast(&vIni,1,MPI_DOUBLE,0,world); MPI_Bcast(&vIni,1,MPI_DOUBLE,0,world);
} }
} }
@ -514,9 +516,10 @@ void FixNEB::min_post_force(int vflag)
MPI_Allreduce(&dot,&dotall,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&dot,&dotall,1,MPI_DOUBLE,MPI_SUM,world);
dot=dotall/tlen; dot=dotall/tlen;
if (veng<EFinalIni) {
if (dot<0) prefactor = -dot - kspringFinal*(veng-EFinalIni); if (dot<0) prefactor = -dot - kspringFinal*(veng-EFinalIni);
else prefactor = -dot + kspringFinal*(veng-EFinalIni); else prefactor = -dot + kspringFinal*(veng-EFinalIni);
}
for (int i = 0; i < nlocal; i++) for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) { if (mask[i] & groupbit) {
f[i][0] += prefactor *tangent[i][0]; f[i][0] += prefactor *tangent[i][0];
@ -531,10 +534,10 @@ void FixNEB::min_post_force(int vflag)
double dotall; double dotall;
MPI_Allreduce(&dot,&dotall,1,MPI_DOUBLE,MPI_SUM,world); MPI_Allreduce(&dot,&dotall,1,MPI_DOUBLE,MPI_SUM,world);
dot=dotall/tlen; dot=dotall/tlen;
if (veng<vIni) {
if (dot<0) prefactor = -dot - kspringFinal*(veng-vIni); if (dot<0) prefactor = -dot - kspringFinal*(veng-vIni);
else prefactor = -dot + kspringFinal*(veng-vIni); else prefactor = -dot + kspringFinal*(veng-vIni);
}
for (int i = 0; i < nlocal; i++) for (int i = 0; i < nlocal; i++)
if (mask[i] & groupbit) { if (mask[i] & groupbit) {
f[i][0] += prefactor *tangent[i][0]; f[i][0] += prefactor *tangent[i][0];