diff --git a/src/GRANULAR/pair_gran_hooke_history.cpp b/src/GRANULAR/pair_gran_hooke_history.cpp index de205dce91..3375d9a7a3 100644 --- a/src/GRANULAR/pair_gran_hooke_history.cpp +++ b/src/GRANULAR/pair_gran_hooke_history.cpp @@ -24,6 +24,7 @@ #include "update.h" #include "modify.h" #include "fix.h" +#include "fix_dummy.h" #include "fix_neigh_history.h" #include "comm.h" #include "neighbor.h" @@ -43,7 +44,6 @@ PairGranHookeHistory::PairGranHookeHistory(LAMMPS *lmp) : Pair(lmp) no_virial_fdotr_compute = 1; history = 1; size_history = 3; - fix_history = NULL; single_extra = 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] 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; 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) { memory->destroy(setflag); @@ -412,7 +427,9 @@ void PairGranHookeHistory::init_style() 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) { char dnumstr[16]; @@ -422,7 +439,7 @@ void PairGranHookeHistory::init_style() fixarg[1] = (char *) "all"; fixarg[2] = (char *) "NEIGH_HISTORY"; fixarg[3] = dnumstr; - modify->add_fix(4,fixarg,1); + modify->replace_fix("NEIGH_HISTORY_DUMMY",4,fixarg,1); delete [] fixarg; fix_history = (FixNeighHistory *) modify->fix[modify->nfix-1]; fix_history->pair = this; diff --git a/src/GRANULAR/pair_gran_hooke_history.h b/src/GRANULAR/pair_gran_hooke_history.h index 81f2d8fd4a..309af54ee6 100644 --- a/src/GRANULAR/pair_gran_hooke_history.h +++ b/src/GRANULAR/pair_gran_hooke_history.h @@ -56,6 +56,7 @@ class PairGranHookeHistory : public Pair { int size_history; + class FixDummy *fix_dummy; class FixNeighHistory *fix_history; // storage of rigid body masses for use in granular interactions diff --git a/src/GRANULAR/pair_granular.cpp b/src/GRANULAR/pair_granular.cpp index 85eab1fb9e..d37ae8c00c 100644 --- a/src/GRANULAR/pair_granular.cpp +++ b/src/GRANULAR/pair_granular.cpp @@ -1,13 +1,14 @@ /* ---------------------------------------------------------------------- -http://lammps.sandia.gov, Sandia National Laboratories -Steve Plimpton, sjplimp@sandia.gov + 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. + 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. + See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- @@ -25,6 +26,7 @@ See the README file in the top-level LAMMPS directory. #include "update.h" #include "modify.h" #include "fix.h" +#include "fix_dummy.h" #include "fix_neigh_history.h" #include "comm.h" #include "neighbor.h" @@ -62,7 +64,6 @@ PairGranular::PairGranular(LAMMPS *lmp) : Pair(lmp) { single_enable = 1; no_virial_fdotr_compute = 1; - fix_history = NULL; single_extra = 12; svector = new double[single_extra]; @@ -90,6 +91,19 @@ PairGranular::PairGranular(LAMMPS *lmp) : Pair(lmp) nondefault_history_transfer = 0; tangential_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() { 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) { memory->destroy(setflag); @@ -1021,8 +1037,9 @@ void PairGranular::init_style() dt = update->dt; - // if history is stored: - // if first init, create Fix needed for storing 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 (use_history && fix_history == NULL) { char dnumstr[16]; @@ -1032,7 +1049,7 @@ void PairGranular::init_style() fixarg[1] = (char *) "all"; fixarg[2] = (char *) "NEIGH_HISTORY"; fixarg[3] = dnumstr; - modify->add_fix(4,fixarg,1); + modify->replace_fix("NEIGH_HISTORY_DUMMY",4,fixarg,1); delete [] fixarg; fix_history = (FixNeighHistory *) modify->fix[modify->nfix-1]; fix_history->pair = this; diff --git a/src/GRANULAR/pair_granular.h b/src/GRANULAR/pair_granular.h index d799acb733..e9ba629b49 100644 --- a/src/GRANULAR/pair_granular.h +++ b/src/GRANULAR/pair_granular.h @@ -51,6 +51,7 @@ class PairGranular : public Pair { double *maxrad_dynamic,*maxrad_frozen; double **cut; + class FixDummy *fix_dummy; class FixNeighHistory *fix_history; // storage of rigid body masses for use in granular interactions @@ -111,4 +112,4 @@ 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. - */ +*/ diff --git a/src/USER-BOCS/fix_bocs.cpp b/src/USER-BOCS/fix_bocs.cpp index adce231bf1..0c5ebb7df4 100644 --- a/src/USER-BOCS/fix_bocs.cpp +++ b/src/USER-BOCS/fix_bocs.cpp @@ -302,10 +302,10 @@ FixBocs::FixBocs(LAMMPS *lmp, int narg, char **arg) : // pre_exchange only required if flips can occur due to shape changes 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 || domain->xy != 0.0)) - pre_exchange_flag = 1; + pre_exchange_flag = pre_exchange_migrate = 1; } // convert input periods to frequencies diff --git a/src/USER-MISC/fix_srp.cpp b/src/USER-MISC/fix_srp.cpp index c0db252db4..2a96555fd7 100644 --- a/src/USER-MISC/fix_srp.cpp +++ b/src/USER-MISC/fix_srp.cpp @@ -22,6 +22,7 @@ #include "atom.h" #include "force.h" #include "domain.h" +#include "modify.h" #include "comm.h" #include "memory.h" #include "error.h" @@ -112,19 +113,21 @@ void FixSRP::init() if ((bptype < 1) || (bptype > atom->ntypes)) error->all(FLERR,"Illegal bond particle type"); - // fix SRP should be the first fix running at the PRE_EXCHANGE step. - // Otherwise it might conflict with, e.g. fix deform + // 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 - if (modify->n_pre_exchange > 1) { - char *first = modify->fix[modify->list_pre_exchange[0]]->id; - if ((comm->me == 0) && (strcmp(id,first) != 0)) - error->warning(FLERR,"Internal fix for pair srp defined too late." - " May lead to incorrect behavior."); + 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 SRP comes after a fix which " + "migrates atoms in pre_exchange"); } // setup neigh exclusions for diff atom types // bond particles do not interact with other types // type bptype only interacts with itself + char* arg1[4]; arg1[0] = (char *) "exclude"; arg1[1] = (char *) "type"; diff --git a/src/USER-MISC/pair_srp.cpp b/src/USER-MISC/pair_srp.cpp index 606fdc9fc5..d0e73b265d 100644 --- a/src/USER-MISC/pair_srp.cpp +++ b/src/USER-MISC/pair_srp.cpp @@ -79,13 +79,18 @@ PairSRP::PairSRP(LAMMPS *lmp) : Pair(lmp) segment = NULL; // generate unique fix-id for this pair style instance + fix_id = strdup("XX_FIX_SRP"); fix_id[0] = '0' + srp_instance / 10; fix_id[1] = '0' + srp_instance % 10; ++srp_instance; - // create fix SRP instance here, as it has to - // be executed before all other fixes + // create fix SRP instance here + // 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]; fixarg[0] = fix_id; fixarg[1] = (char *) "all"; @@ -143,7 +148,6 @@ PairSRP::~PairSRP() ------------------------------------------------------------------------- */ void PairSRP::compute(int eflag, int vflag) - { // setup energy and virial ev_init(eflag, vflag); @@ -458,6 +462,7 @@ void PairSRP::init_style() error->all(FLERR,"PairSRP: Pair srp requires newton pair on"); // verify that fix SRP is still defined and has not been changed. + int ifix = modify->find_fix(fix_id); if (f_srp != (FixSRP *)modify->fix[ifix]) 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 // if bond type is 0, then all bonds have bond particles // btype = bond type + char c0[20]; char* arg0[2]; sprintf(c0, "%d", btype); @@ -506,7 +512,6 @@ void PairSRP::init_style() double PairSRP::init_one(int i, int j) { - if (setflag[i][j] == 0) error->all(FLERR,"PairSRP: All pair coeffs are not set"); cut[j][i] = cut[i][j]; diff --git a/src/fix.cpp b/src/fix.cpp index d86acf0ae4..024d44e5bd 100644 --- a/src/fix.cpp +++ b/src/fix.cpp @@ -79,6 +79,7 @@ Fix::Fix(LAMMPS *lmp, int /*narg*/, char **arg) : respa_level = -1; maxexchange = 0; maxexchange_dynamic = 0; + pre_exchange_migrate = 0; scalar_flag = vector_flag = array_flag = 0; peratom_flag = local_flag = 0; diff --git a/src/fix.h b/src/fix.h index bcab6f289e..fa016232f0 100644 --- a/src/fix.h +++ b/src/fix.h @@ -58,6 +58,7 @@ class Fix : protected Pointers { int respa_level; // which respa level to apply fix (1-Nrespa) int maxexchange; // max # of per-atom values for Comm::exchange() 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 vector_flag; // 0/1 if compute_vector() function exists diff --git a/src/fix_balance.cpp b/src/fix_balance.cpp index 5ca1ec124a..46525796a7 100644 --- a/src/fix_balance.cpp +++ b/src/fix_balance.cpp @@ -40,6 +40,7 @@ FixBalance::FixBalance(LAMMPS *lmp, int narg, char **arg) : if (narg < 6) error->all(FLERR,"Illegal fix balance command"); box_change_domain = 1; + pre_exchange_migrate = 1; scalar_flag = 1; extscalar = 0; vector_flag = 1; diff --git a/src/fix_deform.cpp b/src/fix_deform.cpp index 9d84c4bb62..7b3239f1af 100644 --- a/src/fix_deform.cpp +++ b/src/fix_deform.cpp @@ -48,6 +48,7 @@ rfix(NULL), irregular(NULL), set(NULL) no_change_box = 1; restart_global = 1; + pre_exchange_migrate = 1; nevery = force->inumeric(FLERR,arg[3]); if (nevery <= 0) error->all(FLERR,"Illegal fix deform command"); diff --git a/src/fix_dummy.cpp b/src/fix_dummy.cpp new file mode 100644 index 0000000000..fd9d0cf062 --- /dev/null +++ b/src/fix_dummy.cpp @@ -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 +#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; +} diff --git a/src/fix_dummy.h b/src/fix_dummy.h new file mode 100644 index 0000000000..ea8ce97c3a --- /dev/null +++ b/src/fix_dummy.h @@ -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. + +*/ diff --git a/src/fix_neigh_history.cpp b/src/fix_neigh_history.cpp index 673e2b1c06..1967e43336 100644 --- a/src/fix_neigh_history.cpp +++ b/src/fix_neigh_history.cpp @@ -19,6 +19,7 @@ #include "comm.h" #include "neighbor.h" #include "neigh_list.h" +#include "modify.h" #include "force.h" #include "pair.h" #include "memory.h" @@ -147,6 +148,19 @@ void FixNeighHistory::init() if (atom->tag_enable == 0) 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(); } diff --git a/src/fix_nh.cpp b/src/fix_nh.cpp index bb3fe7559c..3098a8c72c 100644 --- a/src/fix_nh.cpp +++ b/src/fix_nh.cpp @@ -492,10 +492,10 @@ FixNH::FixNH(LAMMPS *lmp, int narg, char **arg) : // pre_exchange only required if flips can occur due to shape changes 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 || domain->xy != 0.0)) - pre_exchange_flag = 1; + pre_exchange_flag = pre_exchange_migrate = 1; } // convert input periods to frequencies diff --git a/src/modify.cpp b/src/modify.cpp index 101540f786..732770f34e 100644 --- a/src/modify.cpp +++ b/src/modify.cpp @@ -953,6 +953,46 @@ void Modify::add_fix(int narg, char **arg, int trysuffix) 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 ------------------------------------------------------------------------- */ diff --git a/src/modify.h b/src/modify.h index b736485196..0b809d4d6a 100644 --- a/src/modify.h +++ b/src/modify.h @@ -96,6 +96,7 @@ class Modify : protected Pointers { virtual int min_reset_ref(); void add_fix(int, char **, int trysuffix=1); + void replace_fix(const char *, int, char **, int trysuffix=1); void modify_fix(int, char **); void delete_fix(const char *); void delete_fix(int);