added internal fix dummy command to enable more control of fix ordering

This commit is contained in:
Steve Plimpton
2019-11-05 12:57:34 -07:00
parent cf251eb8be
commit d8ef5f6991
17 changed files with 253 additions and 32 deletions

View File

@ -24,6 +24,7 @@
#include "update.h" #include "update.h"
#include "modify.h" #include "modify.h"
#include "fix.h" #include "fix.h"
#include "fix_dummy.h"
#include "fix_neigh_history.h" #include "fix_neigh_history.h"
#include "comm.h" #include "comm.h"
#include "neighbor.h" #include "neighbor.h"
@ -43,7 +44,6 @@ PairGranHookeHistory::PairGranHookeHistory(LAMMPS *lmp) : Pair(lmp)
no_virial_fdotr_compute = 1; no_virial_fdotr_compute = 1;
history = 1; history = 1;
size_history = 3; size_history = 3;
fix_history = NULL;
single_extra = 10; single_extra = 10;
svector = new double[10]; svector = new double[10];
@ -60,6 +60,19 @@ PairGranHookeHistory::PairGranHookeHistory(LAMMPS *lmp) : Pair(lmp)
// keep default behavior of history[i][j] = -history[j][i] // keep default behavior of history[i][j] = -history[j][i]
nondefault_history_transfer = 0; nondefault_history_transfer = 0;
// create dummy fix as placeholder for FixNeighHistory
// this is so final order of Modify:fix will conform to input script
fix_history = NULL;
char **fixarg = new char*[3];
fixarg[0] = (char *) "NEIGH_HISTORY_DUMMY";
fixarg[1] = (char *) "all";
fixarg[2] = (char *) "DUMMY";
modify->add_fix(3,fixarg,1);
delete [] fixarg;
fix_dummy = (FixDummy *) modify->fix[modify->nfix-1];
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -69,7 +82,9 @@ PairGranHookeHistory::~PairGranHookeHistory()
if (copymode) return; if (copymode) return;
delete [] svector; delete [] svector;
if (fix_history) modify->delete_fix("NEIGH_HISTORY");
if (!fix_history) modify->delete_fix("NEIGH_HISTORY_DUMMY");
else modify->delete_fix("NEIGH_HISTORY");
if (allocated) { if (allocated) {
memory->destroy(setflag); memory->destroy(setflag);
@ -412,7 +427,9 @@ void PairGranHookeHistory::init_style()
dt = update->dt; dt = update->dt;
// if first init, create Fix needed for storing shear history // if history is stored and first init, create Fix to store history
// it replaces FixDummy, created in the constructor
// this is so its order in the fix list is preserved
if (history && fix_history == NULL) { if (history && fix_history == NULL) {
char dnumstr[16]; char dnumstr[16];
@ -422,7 +439,7 @@ void PairGranHookeHistory::init_style()
fixarg[1] = (char *) "all"; fixarg[1] = (char *) "all";
fixarg[2] = (char *) "NEIGH_HISTORY"; fixarg[2] = (char *) "NEIGH_HISTORY";
fixarg[3] = dnumstr; fixarg[3] = dnumstr;
modify->add_fix(4,fixarg,1); modify->replace_fix("NEIGH_HISTORY_DUMMY",4,fixarg,1);
delete [] fixarg; delete [] fixarg;
fix_history = (FixNeighHistory *) modify->fix[modify->nfix-1]; fix_history = (FixNeighHistory *) modify->fix[modify->nfix-1];
fix_history->pair = this; fix_history->pair = this;

View File

@ -56,6 +56,7 @@ class PairGranHookeHistory : public Pair {
int size_history; int size_history;
class FixDummy *fix_dummy;
class FixNeighHistory *fix_history; class FixNeighHistory *fix_history;
// storage of rigid body masses for use in granular interactions // storage of rigid body masses for use in granular interactions

View File

@ -1,4 +1,5 @@
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov Steve Plimpton, sjplimp@sandia.gov
@ -25,6 +26,7 @@ See the README file in the top-level LAMMPS directory.
#include "update.h" #include "update.h"
#include "modify.h" #include "modify.h"
#include "fix.h" #include "fix.h"
#include "fix_dummy.h"
#include "fix_neigh_history.h" #include "fix_neigh_history.h"
#include "comm.h" #include "comm.h"
#include "neighbor.h" #include "neighbor.h"
@ -62,7 +64,6 @@ PairGranular::PairGranular(LAMMPS *lmp) : Pair(lmp)
{ {
single_enable = 1; single_enable = 1;
no_virial_fdotr_compute = 1; no_virial_fdotr_compute = 1;
fix_history = NULL;
single_extra = 12; single_extra = 12;
svector = new double[single_extra]; svector = new double[single_extra];
@ -90,6 +91,19 @@ PairGranular::PairGranular(LAMMPS *lmp) : Pair(lmp)
nondefault_history_transfer = 0; nondefault_history_transfer = 0;
tangential_history_index = 0; tangential_history_index = 0;
roll_history_index = twist_history_index = 0; roll_history_index = twist_history_index = 0;
// create dummy fix as placeholder for FixNeighHistory
// this is so final order of Modify:fix will conform to input script
fix_history = NULL;
char **fixarg = new char*[3];
fixarg[0] = (char *) "NEIGH_HISTORY_DUMMY";
fixarg[1] = (char *) "all";
fixarg[2] = (char *) "DUMMY";
modify->add_fix(3,fixarg,1);
delete [] fixarg;
fix_dummy = (FixDummy *) modify->fix[modify->nfix-1];
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -97,7 +111,9 @@ PairGranular::PairGranular(LAMMPS *lmp) : Pair(lmp)
PairGranular::~PairGranular() PairGranular::~PairGranular()
{ {
delete [] svector; delete [] svector;
if (fix_history) modify->delete_fix("NEIGH_HISTORY");
if (!fix_history) modify->delete_fix("NEIGH_HISTORY_DUMMY");
else modify->delete_fix("NEIGH_HISTORY");
if (allocated) { if (allocated) {
memory->destroy(setflag); memory->destroy(setflag);
@ -1021,8 +1037,9 @@ void PairGranular::init_style()
dt = update->dt; dt = update->dt;
// if history is stored: // if history is stored and first init, create Fix to store history
// if first init, create Fix needed for storing history // it replaces FixDummy, created in the constructor
// this is so its order in the fix list is preserved
if (use_history && fix_history == NULL) { if (use_history && fix_history == NULL) {
char dnumstr[16]; char dnumstr[16];
@ -1032,7 +1049,7 @@ void PairGranular::init_style()
fixarg[1] = (char *) "all"; fixarg[1] = (char *) "all";
fixarg[2] = (char *) "NEIGH_HISTORY"; fixarg[2] = (char *) "NEIGH_HISTORY";
fixarg[3] = dnumstr; fixarg[3] = dnumstr;
modify->add_fix(4,fixarg,1); modify->replace_fix("NEIGH_HISTORY_DUMMY",4,fixarg,1);
delete [] fixarg; delete [] fixarg;
fix_history = (FixNeighHistory *) modify->fix[modify->nfix-1]; fix_history = (FixNeighHistory *) modify->fix[modify->nfix-1];
fix_history->pair = this; fix_history->pair = this;

View File

@ -51,6 +51,7 @@ class PairGranular : public Pair {
double *maxrad_dynamic,*maxrad_frozen; double *maxrad_dynamic,*maxrad_frozen;
double **cut; double **cut;
class FixDummy *fix_dummy;
class FixNeighHistory *fix_history; class FixNeighHistory *fix_history;
// storage of rigid body masses for use in granular interactions // storage of rigid body masses for use in granular interactions

View File

@ -302,10 +302,10 @@ FixBocs::FixBocs(LAMMPS *lmp, int narg, char **arg) :
// pre_exchange only required if flips can occur due to shape changes // pre_exchange only required if flips can occur due to shape changes
if (flipflag && (p_flag[3] || p_flag[4] || p_flag[5])) if (flipflag && (p_flag[3] || p_flag[4] || p_flag[5]))
pre_exchange_flag = 1; pre_exchange_flag = pre_exchange_migrate = 1;
if (flipflag && (domain->yz != 0.0 || domain->xz != 0.0 || if (flipflag && (domain->yz != 0.0 || domain->xz != 0.0 ||
domain->xy != 0.0)) domain->xy != 0.0))
pre_exchange_flag = 1; pre_exchange_flag = pre_exchange_migrate = 1;
} }
// convert input periods to frequencies // convert input periods to frequencies

View File

@ -22,6 +22,7 @@
#include "atom.h" #include "atom.h"
#include "force.h" #include "force.h"
#include "domain.h" #include "domain.h"
#include "modify.h"
#include "comm.h" #include "comm.h"
#include "memory.h" #include "memory.h"
#include "error.h" #include "error.h"
@ -112,19 +113,21 @@ void FixSRP::init()
if ((bptype < 1) || (bptype > atom->ntypes)) if ((bptype < 1) || (bptype > atom->ntypes))
error->all(FLERR,"Illegal bond particle type"); error->all(FLERR,"Illegal bond particle type");
// fix SRP should be the first fix running at the PRE_EXCHANGE step. // this fix must come before any fix which migrates atoms in its pre_exchange()
// Otherwise it might conflict with, e.g. fix deform // b/c this fix's pre_exchange() creates per-atom data structure
// that data must be current for atom migration to carry it along
if (modify->n_pre_exchange > 1) { for (int i = 0; i < modify->nfix; i++) {
char *first = modify->fix[modify->list_pre_exchange[0]]->id; if (modify->fix[i] == this) break;
if ((comm->me == 0) && (strcmp(id,first) != 0)) if (modify->fix[i]->pre_exchange_migrate)
error->warning(FLERR,"Internal fix for pair srp defined too late." error->all(FLERR,"Fix SRP comes after a fix which "
" May lead to incorrect behavior."); "migrates atoms in pre_exchange");
} }
// setup neigh exclusions for diff atom types // setup neigh exclusions for diff atom types
// bond particles do not interact with other types // bond particles do not interact with other types
// type bptype only interacts with itself // type bptype only interacts with itself
char* arg1[4]; char* arg1[4];
arg1[0] = (char *) "exclude"; arg1[0] = (char *) "exclude";
arg1[1] = (char *) "type"; arg1[1] = (char *) "type";

View File

@ -79,13 +79,18 @@ PairSRP::PairSRP(LAMMPS *lmp) : Pair(lmp)
segment = NULL; segment = NULL;
// generate unique fix-id for this pair style instance // generate unique fix-id for this pair style instance
fix_id = strdup("XX_FIX_SRP"); fix_id = strdup("XX_FIX_SRP");
fix_id[0] = '0' + srp_instance / 10; fix_id[0] = '0' + srp_instance / 10;
fix_id[1] = '0' + srp_instance % 10; fix_id[1] = '0' + srp_instance % 10;
++srp_instance; ++srp_instance;
// create fix SRP instance here, as it has to // create fix SRP instance here
// be executed before all other fixes // similar to granular pair styles with history,
// this should be early enough that FixSRP::pre_exchange()
// will be invoked before other fixes that migrate atoms
// this is checked for in FixSRP
char **fixarg = new char*[3]; char **fixarg = new char*[3];
fixarg[0] = fix_id; fixarg[0] = fix_id;
fixarg[1] = (char *) "all"; fixarg[1] = (char *) "all";
@ -143,7 +148,6 @@ PairSRP::~PairSRP()
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void PairSRP::compute(int eflag, int vflag) void PairSRP::compute(int eflag, int vflag)
{ {
// setup energy and virial // setup energy and virial
ev_init(eflag, vflag); ev_init(eflag, vflag);
@ -458,6 +462,7 @@ void PairSRP::init_style()
error->all(FLERR,"PairSRP: Pair srp requires newton pair on"); error->all(FLERR,"PairSRP: Pair srp requires newton pair on");
// verify that fix SRP is still defined and has not been changed. // verify that fix SRP is still defined and has not been changed.
int ifix = modify->find_fix(fix_id); int ifix = modify->find_fix(fix_id);
if (f_srp != (FixSRP *)modify->fix[ifix]) if (f_srp != (FixSRP *)modify->fix[ifix])
error->all(FLERR,"Fix SRP has been changed unexpectedly"); error->all(FLERR,"Fix SRP has been changed unexpectedly");
@ -471,6 +476,7 @@ void PairSRP::init_style()
// bonds of this type will be represented by bond particles // bonds of this type will be represented by bond particles
// if bond type is 0, then all bonds have bond particles // if bond type is 0, then all bonds have bond particles
// btype = bond type // btype = bond type
char c0[20]; char c0[20];
char* arg0[2]; char* arg0[2];
sprintf(c0, "%d", btype); sprintf(c0, "%d", btype);
@ -506,7 +512,6 @@ void PairSRP::init_style()
double PairSRP::init_one(int i, int j) double PairSRP::init_one(int i, int j)
{ {
if (setflag[i][j] == 0) error->all(FLERR,"PairSRP: All pair coeffs are not set"); if (setflag[i][j] == 0) error->all(FLERR,"PairSRP: All pair coeffs are not set");
cut[j][i] = cut[i][j]; cut[j][i] = cut[i][j];

View File

@ -79,6 +79,7 @@ Fix::Fix(LAMMPS *lmp, int /*narg*/, char **arg) :
respa_level = -1; respa_level = -1;
maxexchange = 0; maxexchange = 0;
maxexchange_dynamic = 0; maxexchange_dynamic = 0;
pre_exchange_migrate = 0;
scalar_flag = vector_flag = array_flag = 0; scalar_flag = vector_flag = array_flag = 0;
peratom_flag = local_flag = 0; peratom_flag = local_flag = 0;

View File

@ -58,6 +58,7 @@ class Fix : protected Pointers {
int respa_level; // which respa level to apply fix (1-Nrespa) int respa_level; // which respa level to apply fix (1-Nrespa)
int maxexchange; // max # of per-atom values for Comm::exchange() int maxexchange; // max # of per-atom values for Comm::exchange()
int maxexchange_dynamic; // 1 if fix sets maxexchange dynamically int maxexchange_dynamic; // 1 if fix sets maxexchange dynamically
int pre_exchange_migrate; // 1 if fix migrates atoms in pre_exchange()
int scalar_flag; // 0/1 if compute_scalar() function exists int scalar_flag; // 0/1 if compute_scalar() function exists
int vector_flag; // 0/1 if compute_vector() function exists int vector_flag; // 0/1 if compute_vector() function exists

View File

@ -40,6 +40,7 @@ FixBalance::FixBalance(LAMMPS *lmp, int narg, char **arg) :
if (narg < 6) error->all(FLERR,"Illegal fix balance command"); if (narg < 6) error->all(FLERR,"Illegal fix balance command");
box_change_domain = 1; box_change_domain = 1;
pre_exchange_migrate = 1;
scalar_flag = 1; scalar_flag = 1;
extscalar = 0; extscalar = 0;
vector_flag = 1; vector_flag = 1;

View File

@ -48,6 +48,7 @@ rfix(NULL), irregular(NULL), set(NULL)
no_change_box = 1; no_change_box = 1;
restart_global = 1; restart_global = 1;
pre_exchange_migrate = 1;
nevery = force->inumeric(FLERR,arg[3]); nevery = force->inumeric(FLERR,arg[3]);
if (nevery <= 0) error->all(FLERR,"Illegal fix deform command"); if (nevery <= 0) error->all(FLERR,"Illegal fix deform command");

65
src/fix_dummy.cpp Normal file
View File

@ -0,0 +1,65 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#include "fix_dummy.h"
#include <cstring>
#include "error.h"
using namespace LAMMPS_NS;
using namespace FixConst;
/* ---------------------------------------------------------------------- */
FixDummy::FixDummy(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg)
{
// process optional args
// customize here and in setmask() by adding a new keyword from fix.h
// only necessary if both of these are true:
// (a) the real fix you are placeholding for defines the method
// (b) the real fix will be defined so late in run initialization
// that the dummy fix will have already been processed by Modify::init()
// to add its index to its lists of fixes to invoke during timestepping
initial_integrate_flag = final_integrate_flag = 0;
pre_exchange_flag = pre_neighbor_flag = 0;
pre_force_flag = post_force_flag = 0;
end_of_step_flag = 0;
int iarg = 3;
while (iarg < narg) {
if (strcmp(arg[iarg],"initial_integrate") == 0) initial_integrate_flag = 1;
else if (strcmp(arg[iarg],"final_integrate") == 0) final_integrate_flag = 1;
else if (strcmp(arg[iarg],"final_integrate") == 0) final_integrate_flag = 1;
else if (strcmp(arg[iarg],"final_integrate") == 0) final_integrate_flag = 1;
else if (strcmp(arg[iarg],"final_integrate") == 0) final_integrate_flag = 1;
else if (strcmp(arg[iarg],"final_integrate") == 0) final_integrate_flag = 1;
else error->all(FLERR,"Illegal fix DUMMY command");
iarg++;
}
}
/* ---------------------------------------------------------------------- */
int FixDummy::setmask()
{
int mask = 0;
if (initial_integrate_flag) mask |= INITIAL_INTEGRATE;
if (final_integrate_flag) mask |= FINAL_INTEGRATE;
if (pre_exchange_flag) mask |= PRE_EXCHANGE;
if (pre_neighbor_flag) mask |= PRE_NEIGHBOR;
if (pre_force_flag) mask |= PRE_FORCE;
if (post_force_flag) mask |= POST_FORCE;
if (end_of_step_flag) mask |= END_OF_STEP;
return mask;
}

53
src/fix_dummy.h Normal file
View File

@ -0,0 +1,53 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifdef FIX_CLASS
FixStyle(DUMMY,FixDummy)
#else
#ifndef LMP_FIX_DUMMY_H
#define LMP_FIX_DUMMY_H
#include "fix.h"
namespace LAMMPS_NS {
class FixDummy : public Fix {
public:
FixDummy(class LAMMPS *, int, char **);
virtual ~FixDummy() {}
int setmask();
protected:
int initial_integrate_flag,final_integrate_flag;
int pre_exchange_flag,pre_neighbor_flag;
int pre_force_flag,post_force_flag;
int end_of_step_flag;
};
}
#endif
#endif
/* ERROR/WARNING messages:
E: Illegal ... command
Self-explanatory. Check the input script syntax and compare to the
documentation for the command. You can use -echo screen as a
command-line option when running LAMMPS to see the offending line.
*/

View File

@ -19,6 +19,7 @@
#include "comm.h" #include "comm.h"
#include "neighbor.h" #include "neighbor.h"
#include "neigh_list.h" #include "neigh_list.h"
#include "modify.h"
#include "force.h" #include "force.h"
#include "pair.h" #include "pair.h"
#include "memory.h" #include "memory.h"
@ -147,6 +148,19 @@ void FixNeighHistory::init()
if (atom->tag_enable == 0) if (atom->tag_enable == 0)
error->all(FLERR,"Neighbor history requires atoms have IDs"); error->all(FLERR,"Neighbor history requires atoms have IDs");
// this fix must come before any fix which migrates atoms in its pre_exchange()
// b/c this fix's pre_exchange() creates per-atom data structure
// that data must be current for atom migration to carry it along
for (int i = 0; i < modify->nfix; i++) {
if (modify->fix[i] == this) break;
if (modify->fix[i]->pre_exchange_migrate)
error->all(FLERR,"Fix neigh_history comes after a fix which "
"migrates atoms in pre_exchange");
}
// setup data struct
allocate_pages(); allocate_pages();
} }

View File

@ -492,10 +492,10 @@ FixNH::FixNH(LAMMPS *lmp, int narg, char **arg) :
// pre_exchange only required if flips can occur due to shape changes // pre_exchange only required if flips can occur due to shape changes
if (flipflag && (p_flag[3] || p_flag[4] || p_flag[5])) if (flipflag && (p_flag[3] || p_flag[4] || p_flag[5]))
pre_exchange_flag = 1; pre_exchange_flag = pre_exchange_migrate = 1;
if (flipflag && (domain->yz != 0.0 || domain->xz != 0.0 || if (flipflag && (domain->yz != 0.0 || domain->xz != 0.0 ||
domain->xy != 0.0)) domain->xy != 0.0))
pre_exchange_flag = 1; pre_exchange_flag = pre_exchange_migrate = 1;
} }
// convert input periods to frequencies // convert input periods to frequencies

View File

@ -953,6 +953,46 @@ void Modify::add_fix(int narg, char **arg, int trysuffix)
fix[ifix]->post_constructor(); fix[ifix]->post_constructor();
} }
/* ----------------------------------------------------------------------
replace replaceID fix with a new fix
this is used by callers to preserve ordering of fixes
e.g. create replaceID as a FixDummy instance early in the input script
replace it later with the desired Fix instance
------------------------------------------------------------------------- */
void Modify::replace_fix(const char *replaceID,
int narg, char **arg, int trysuffix)
{
int ifix = find_fix(replaceID);
if (ifix < 0) error->all(FLERR,"Modify replace_fix ID could not be found");
// change ID, igroup, style of fix being replaced to match new fix
// requires some error checking on arguments for new fix
if (narg < 3) error->all(FLERR,"Illegal replace_fix invocation");
int jfix = find_fix(arg[0]);
if (jfix >= 0) error->all(FLERR,"Replace_fix ID is already in use");
delete [] fix[ifix]->id;
int n = strlen(arg[0]) + 1;
fix[ifix]->id = new char[n];
strcpy(fix[ifix]->id,arg[0]);
int jgroup = group->find(arg[1]);
if (jgroup == -1) error->all(FLERR,"Could not find replace_fix group ID");
fix[ifix]->igroup = jgroup;
delete [] fix[ifix]->style;
n = strlen(arg[2]) + 1;
fix[ifix]->style = new char[n];
strcpy(fix[ifix]->style,arg[2]);
// invoke add_fix
// it will find and overwrite the replaceID fix
add_fix(narg,arg,trysuffix);
}
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
one instance per fix in style_fix.h one instance per fix in style_fix.h
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */

View File

@ -96,6 +96,7 @@ class Modify : protected Pointers {
virtual int min_reset_ref(); virtual int min_reset_ref();
void add_fix(int, char **, int trysuffix=1); void add_fix(int, char **, int trysuffix=1);
void replace_fix(const char *, int, char **, int trysuffix=1);
void modify_fix(int, char **); void modify_fix(int, char **);
void delete_fix(const char *); void delete_fix(const char *);
void delete_fix(int); void delete_fix(int);