fix issue with restoring box-shifted atom coords

This commit is contained in:
Steve Plimpton
2020-02-28 12:53:04 -07:00
parent 7a720ee9cf
commit cdb4275ced
2 changed files with 46 additions and 49 deletions

View File

@ -17,7 +17,7 @@
#include "fix_numdiff.h" #include "fix_numdiff.h"
#include <mpi.h> #include <mpi.h>
#include <memory.h> #include <string.h>
#include "atom.h" #include "atom.h"
#include "domain.h" #include "domain.h"
#include "update.h" #include "update.h"
@ -31,6 +31,7 @@
#include "dihedral.h" #include "dihedral.h"
#include "improper.h" #include "improper.h"
#include "kspace.h" #include "kspace.h"
#include "memory.h"
#include "error.h" #include "error.h"
using namespace LAMMPS_NS; using namespace LAMMPS_NS;
@ -51,7 +52,8 @@ FixNumDiff::FixNumDiff(LAMMPS *lmp, int narg, char **arg) :
nevery = force->inumeric(FLERR,arg[3]); nevery = force->inumeric(FLERR,arg[3]);
delta = force->numeric(FLERR,arg[4]); delta = force->numeric(FLERR,arg[4]);
if (nevery <= 0 || delta <= 0.0) error->all(FLERR,"Illegal fix numdiff command"); if (nevery <= 0 || delta <= 0.0)
error->all(FLERR,"Illegal fix numdiff command");
int n = strlen(id) + 6; int n = strlen(id) + 6;
id_pe = new char[n]; id_pe = new char[n];
@ -67,9 +69,9 @@ FixNumDiff::FixNumDiff(LAMMPS *lmp, int narg, char **arg) :
maxatom = 0; maxatom = 0;
numdiff_forces = NULL; numdiff_forces = NULL;
temp_x = NULL;
temp_f = NULL; temp_f = NULL;
array_atom = NULL; array_atom = NULL;
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -77,6 +79,7 @@ FixNumDiff::FixNumDiff(LAMMPS *lmp, int narg, char **arg) :
FixNumDiff::~FixNumDiff() FixNumDiff::~FixNumDiff()
{ {
memory->destroy(numdiff_forces); memory->destroy(numdiff_forces);
memory->destroy(temp_x);
memory->destroy(temp_f); memory->destroy(temp_f);
modify->delete_compute(id_pe); modify->delete_compute(id_pe);
@ -102,7 +105,8 @@ void FixNumDiff::init()
{ {
// require consecutive atom IDs // require consecutive atom IDs
if (!atom->tag_enable || !atom->tag_consecutive()) error->all(FLERR,"Fix numdiff requires consecutive atom IDs"); if (!atom->tag_enable || !atom->tag_consecutive())
error->all(FLERR,"Fix numdiff requires consecutive atom IDs");
// check for PE compute // check for PE compute
@ -119,15 +123,6 @@ void FixNumDiff::init()
ilevel_respa = ((Respa *) update->integrate)->nlevels-1; ilevel_respa = ((Respa *) update->integrate)->nlevels-1;
if (respa_level >= 0) ilevel_respa = MIN(respa_level,ilevel_respa); if (respa_level >= 0) ilevel_respa = MIN(respa_level,ilevel_respa);
} }
if (atom->nmax > maxatom) {
memory->destroy(numdiff_forces);
memory->destroy(temp_f);
maxatom = atom->nmax;
memory->create(numdiff_forces,maxatom,3,"numdiff:numdiff_force");
memory->create(temp_f,maxatom,3,"numdiff:temp_f");
array_atom = numdiff_forces;
}
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -136,7 +131,7 @@ void FixNumDiff::post_force(int vflag)
{ {
if (update->ntimestep % nevery) return; if (update->ntimestep % nevery) return;
calculate_forces(vflag); calculate_forces();
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -154,31 +149,37 @@ void FixNumDiff::min_post_force(int vflag)
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
create dynamical matrix compute finite difference forces
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void FixNumDiff::calculate_forces(int vflag) void FixNumDiff::calculate_forces()
{ {
int i,j,ilocal; int i,j,ilocal;
double energy; double energy;
if (atom->nmax > maxatom) { // grow arrays if necessary
if (atom->nlocal + atom->nghost > maxatom) {
memory->destroy(numdiff_forces); memory->destroy(numdiff_forces);
memory->destroy(temp_x);
memory->destroy(temp_f); memory->destroy(temp_f);
maxatom = atom->nmax; maxatom = atom->nmax;
memory->create(numdiff_forces,maxatom,3,"numdiff:numdiff_force"); memory->create(numdiff_forces,maxatom,3,"numdiff:numdiff_force");
memory->create(temp_x,maxatom,3,"numdiff:temp_x");
memory->create(temp_f,maxatom,3,"numdiff:temp_f"); memory->create(temp_f,maxatom,3,"numdiff:temp_f");
array_atom = numdiff_forces; array_atom = numdiff_forces;
} }
// store copy of current forces for owned and ghost atoms // store copy of current forces for owned and ghost atoms
double **x = atom->x;
double **f = atom->f; double **f = atom->f;
int nlocal = atom->nlocal; int nlocal = atom->nlocal;
int nall = nlocal + atom->nghost; int nall = nlocal + atom->nghost;
for (i = 0; i < nall; i++) for (i = 0; i < nall; i++)
for (j = 0; j < 3; j++) { for (j = 0; j < 3; j++) {
temp_x[i][j] = x[i][j];
temp_f[i][j] = f[i][j]; temp_f[i][j] = f[i][j];
} }
@ -186,6 +187,9 @@ void FixNumDiff::calculate_forces(int vflag)
force_clear(numdiff_forces); force_clear(numdiff_forces);
// loop over all atoms in system
// compute a finite difference force in each dimension
int flag,allflag; int flag,allflag;
double denominator = 0.5 / delta; double denominator = 0.5 / delta;
@ -201,19 +205,19 @@ void FixNumDiff::calculate_forces(int vflag)
if (!allflag) continue; if (!allflag) continue;
for (int idim = 0; idim < dimension; idim++) { for (int idim = 0; idim < dimension; idim++) {
displace_atom(ilocal,idim,1); displace_atoms(ilocal,idim,1);
energy = update_energy(vflag); energy = update_energy();
if (ilocal >= 0 && ilocal < nlocal) if (ilocal >= 0 && ilocal < nlocal)
numdiff_forces[ilocal][idim] -= energy; numdiff_forces[ilocal][idim] -= energy;
displace_atom(ilocal,idim,-2); displace_atoms(ilocal,idim,-2);
energy = update_energy(vflag); energy = update_energy();
if (ilocal >= 0 && ilocal < nlocal) { if (ilocal >= 0 && ilocal < nlocal) {
numdiff_forces[ilocal][idim] += energy; numdiff_forces[ilocal][idim] += energy;
numdiff_forces[ilocal][idim] *= denominator; numdiff_forces[ilocal][idim] *= denominator;
} }
reset_atom_position(ilocal, idim); restore_atoms(ilocal,idim);
} }
} }
@ -226,43 +230,40 @@ void FixNumDiff::calculate_forces(int vflag)
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
displace coord of all owned and ghost copies of ilocal displace position of all owned and ghost copies of ilocal
---------------------------------------------------------------------- */ ---------------------------------------------------------------------- */
void FixNumDiff::displace_atom(int ilocal, int idim, int magnitude) void FixNumDiff::displace_atoms(int ilocal, int idim, int magnitude)
{ {
if (ilocal < 0) return; if (ilocal < 0) return;
double **x = atom->x; double **x = atom->x;
int *sametag = atom->sametag; int *sametag = atom->sametag;
int j = ilocal; int j = ilocal;
if (magnitude == 1) position = x[ilocal][idim];
x[ilocal][idim] += delta*magnitude; x[ilocal][idim] += delta*magnitude;
while (sametag[j] >= 0) { while (sametag[j] >= 0) {
j = sametag[j]; j = sametag[j];
if (magnitude == 1 && x[j][idim] != position) image = x[j][idim];
x[j][idim] += delta*magnitude; x[j][idim] += delta*magnitude;
} }
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
reset coord of all owned and ghost copies of ilocal (moved atom) restore position of all owned and ghost copies of ilocal
---------------------------------------------------------------------- */ ---------------------------------------------------------------------- */
void FixNumDiff::reset_atom_position(int ilocal, int idim) void FixNumDiff::restore_atoms(int ilocal, int idim)
{ {
if (ilocal < 0) return; if (ilocal < 0) return;
double **x = atom->x; double **x = atom->x;
int *sametag = atom->sametag; int *sametag = atom->sametag;
int j = ilocal; int j = ilocal;
x[ilocal][idim] = position; x[ilocal][idim] = temp_x[ilocal][idim];
while (sametag[j] >= 0) { while (sametag[j] >= 0) {
j = sametag[j]; j = sametag[j];
if (abs(x[j][idim]-position) < abs(x[j][idim]-image)) x[j][idim] = position; x[j][idim] = temp_x[j][idim];
else x[j][idim] = image;
} }
} }
@ -271,23 +272,22 @@ void FixNumDiff::reset_atom_position(int ilocal, int idim)
same logic as in Verlet same logic as in Verlet
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
double FixNumDiff::update_energy(int vflag) double FixNumDiff::update_energy()
{ {
force_clear(atom->f); force_clear(atom->f);
int eflag = 1; int eflag = 1;
int vvflag = 0;
if (pair_compute_flag) force->pair->compute(eflag,vvflag); if (pair_compute_flag) force->pair->compute(eflag,0);
if (atom->molecular) { if (atom->molecular) {
if (force->bond) force->bond->compute(eflag,vvflag); if (force->bond) force->bond->compute(eflag,0);
if (force->angle) force->angle->compute(eflag,vvflag); if (force->angle) force->angle->compute(eflag,0);
if (force->dihedral) force->dihedral->compute(eflag,vvflag); if (force->dihedral) force->dihedral->compute(eflag,0);
if (force->improper) force->improper->compute(eflag,vvflag); if (force->improper) force->improper->compute(eflag,0);
} }
if (kspace_compute_flag) force->kspace->compute(eflag,vvflag); if (kspace_compute_flag) force->kspace->compute(eflag,0);
double energy = pe->compute_scalar(); double energy = pe->compute_scalar();
return energy; return energy;
@ -311,6 +311,6 @@ void FixNumDiff::force_clear(double **forces)
double FixNumDiff::memory_usage() double FixNumDiff::memory_usage()
{ {
bigint bytes = 0.0; bigint bytes = 0.0;
bytes += 2 * maxatom*3 * sizeof(double); bytes += 3 * maxatom*3 * sizeof(double);
return bytes; return bytes;
} }

View File

@ -47,17 +47,14 @@ private:
class Compute *pe; class Compute *pe;
double **numdiff_forces; // finite diff forces double **numdiff_forces; // finite diff forces
double **temp_x; // original coords
double **temp_f; // original forces double **temp_f; // original forces
double position; void calculate_forces();
double image; void displace_atoms(int, int, int);
void restore_atoms(int, int);
double update_energy(int vflag); double update_energy();
void force_clear(double **forces); void force_clear(double **);
void create_groupmap();
void displace_atom(int local_idx, int direction, int magnitude);
void reset_atom_position(int local_idx, int direction);
void calculate_forces(int vflag);
}; };
} }