diff --git a/src/KSPACE/fft3d.cpp b/src/KSPACE/fft3d.cpp index 7a271326f7..6a05be4e6f 100644 --- a/src/KSPACE/fft3d.cpp +++ b/src/KSPACE/fft3d.cpp @@ -69,7 +69,6 @@ void fft_3d(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan) { - int i,total,length,offset,num; FFT_SCALAR norm; #if defined(FFT_FFTW3) FFT_SCALAR *out_ptr; @@ -99,9 +98,6 @@ void fft_3d(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan) // 1d FFTs along fast axis - total = plan->total1; - length = plan->length1; - #if defined(FFT_MKL) if (flag == 1) DftiComputeForward(plan->handle_fast,data); @@ -114,11 +110,14 @@ void fft_3d(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan) theplan=plan->plan_fast_backward; FFTW_API(execute_dft)(theplan,data,data); #else + int total = plan->total1; + int length = plan->length1; + if (flag == 1) - for (offset = 0; offset < total; offset += length) + for (int offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_fast_forward,&data[offset],&data[offset]); else - for (offset = 0; offset < total; offset += length) + for (int offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_fast_backward,&data[offset],&data[offset]); #endif @@ -133,9 +132,6 @@ void fft_3d(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan) // 1d FFTs along mid axis - total = plan->total2; - length = plan->length2; - #if defined(FFT_MKL) if (flag == 1) DftiComputeForward(plan->handle_mid,data); @@ -148,11 +144,14 @@ void fft_3d(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan) theplan=plan->plan_mid_backward; FFTW_API(execute_dft)(theplan,data,data); #else + total = plan->total2; + length = plan->length2; + if (flag == 1) - for (offset = 0; offset < total; offset += length) + for (int offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_mid_forward,&data[offset],&data[offset]); else - for (offset = 0; offset < total; offset += length) + for (int offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_mid_backward,&data[offset],&data[offset]); #endif @@ -167,9 +166,6 @@ void fft_3d(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan) // 1d FFTs along slow axis - total = plan->total3; - length = plan->length3; - #if defined(FFT_MKL) if (flag == 1) DftiComputeForward(plan->handle_slow,data); @@ -182,11 +178,14 @@ void fft_3d(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan) theplan=plan->plan_slow_backward; FFTW_API(execute_dft)(theplan,data,data); #else + total = plan->total3; + length = plan->length3; + if (flag == 1) - for (offset = 0; offset < total; offset += length) + for (int offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_slow_forward,&data[offset],&data[offset]); else - for (offset = 0; offset < total; offset += length) + for (int offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_slow_backward,&data[offset],&data[offset]); #endif @@ -201,11 +200,11 @@ void fft_3d(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan) if (flag == -1 && plan->scaled) { norm = plan->norm; - num = plan->normnum; + const int num = plan->normnum; #if defined(FFT_FFTW3) out_ptr = (FFT_SCALAR *)out; #endif - for (i = 0; i < num; i++) { + for (int i = 0; i < num; i++) { #if defined(FFT_FFTW3) *(out_ptr++) *= norm; *(out_ptr++) *= norm; diff --git a/src/atom_vec.cpp b/src/atom_vec.cpp index 7d7cfa4878..eec09cf58a 100644 --- a/src/atom_vec.cpp +++ b/src/atom_vec.cpp @@ -71,21 +71,6 @@ AtomVec::AtomVec(LAMMPS *lmp) : Pointers(lmp) default_create = "id type mask image x v"; default_data_atom = ""; default_data_vel = ""; - - // initializations - - init_method(&mgrow); - init_method(&mcopy); - init_method(&mcomm); - init_method(&mcomm_vel); - init_method(&mreverse); - init_method(&mborder); - init_method(&mborder_vel); - init_method(&mexchange); - init_method(&mrestart); - init_method(&mcreate); - init_method(&mdata_atom); - init_method(&mdata_vel); } /* ---------------------------------------------------------------------- */ @@ -129,19 +114,6 @@ AtomVec::~AtomVec() } } - destroy_method(&mgrow); - destroy_method(&mcopy); - destroy_method(&mcomm); - destroy_method(&mcomm_vel); - destroy_method(&mreverse); - destroy_method(&mborder); - destroy_method(&mborder_vel); - destroy_method(&mexchange); - destroy_method(&mrestart); - destroy_method(&mcreate); - destroy_method(&mdata_atom); - destroy_method(&mdata_vel); - delete [] threads; } @@ -2395,18 +2367,18 @@ void AtomVec::setup_fields() // populate field-based data struct for each method to use - create_method(ngrow,&mgrow); - create_method(ncopy,&mcopy); - create_method(ncomm,&mcomm); - create_method(ncomm_vel,&mcomm_vel); - create_method(nreverse,&mreverse); - create_method(nborder,&mborder); - create_method(nborder_vel,&mborder_vel); - create_method(nexchange,&mexchange); - create_method(nrestart,&mrestart); - create_method(ncreate,&mcreate); - create_method(ndata_atom,&mdata_atom); - create_method(ndata_vel,&mdata_vel); + init_method(ngrow,&mgrow); + init_method(ncopy,&mcopy); + init_method(ncomm,&mcomm); + init_method(ncomm_vel,&mcomm_vel); + init_method(nreverse,&mreverse); + init_method(nborder,&mborder); + init_method(nborder_vel,&mborder_vel); + init_method(nexchange,&mexchange); + init_method(nrestart,&mrestart); + init_method(ncreate,&mcreate); + init_method(ndata_atom,&mdata_atom); + init_method(ndata_vel,&mdata_vel); // create threads data struct for grow and memory_usage to use @@ -2480,7 +2452,6 @@ void AtomVec::setup_fields() int AtomVec::process_fields(char *str, const char *default_str, Method *method) { if (str == nullptr) { - method->index = nullptr; return 0; } @@ -2496,17 +2467,19 @@ int AtomVec::process_fields(char *str, const char *default_str, Method *method) Atom::PerAtom *peratom = atom->peratom; int nperatom = atom->nperatom; - int *index; + // allocate memory in method + method->resize(nfield); + + std::vector & index = method->index; int match; - if (nfield) index = new int[nfield]; for (int i = 0; i < nfield; i++) { - const char * field = words[i].c_str(); + const std::string & field = words[i]; // find field in master Atom::peratom list for (match = 0; match < nperatom; match++) - if (strcmp(field, peratom[match].name) == 0) break; + if (field == peratom[match].name) break; if (match == nperatom) error->all(FLERR,fmt::format("Peratom field {} not recognized", field)); index[i] = match; @@ -2520,38 +2493,19 @@ int AtomVec::process_fields(char *str, const char *default_str, Method *method) // error if field is in default str for (match = 0; match < ndef; match++) - if (strcmp(field, def_words[match].c_str()) == 0) + if (field == def_words[match]) error->all(FLERR,fmt::format("Peratom field {} is a default", field)); } - if (nfield) method->index = index; - else method->index = nullptr; return nfield; } /* ---------------------------------------------------------------------- - create a method data structs for processing fields + init method data structs for processing fields ------------------------------------------------------------------------- */ -void AtomVec::create_method(int nfield, Method *method) +void AtomVec::init_method(int nfield, Method *method) { - if (nfield > 0) { - method->pdata = new void*[nfield]; - method->datatype = new int[nfield]; - method->cols = new int[nfield]; - method->maxcols = new int*[nfield]; - method->collength = new int[nfield]; - method->plength = new void*[nfield]; - } else { - method->pdata = nullptr; - method->datatype = nullptr; - method->cols = nullptr; - method->maxcols = nullptr; - method->collength = nullptr; - method->plength = nullptr; - return; - } - for (int i = 0; i < nfield; i++) { Atom::PerAtom *field = &atom->peratom[method->index[i]]; method->pdata[i] = (void *) field->address; @@ -2566,31 +2520,15 @@ void AtomVec::create_method(int nfield, Method *method) } /* ---------------------------------------------------------------------- - free memory in a method data structs + Method class members ------------------------------------------------------------------------- */ -void AtomVec::init_method(Method *method) -{ - method->pdata = nullptr; - method->datatype = nullptr; - method->cols = nullptr; - method->maxcols = nullptr; - method->collength = nullptr; - method->plength = nullptr; - method->index = nullptr; -} - -/* ---------------------------------------------------------------------- - free memory in a method data structs -------------------------------------------------------------------------- */ - -void AtomVec::destroy_method(Method *method) -{ - delete [] method->pdata; - delete [] method->datatype; - delete [] method->cols; - delete [] method->maxcols; - delete [] method->collength; - delete [] method->plength; - delete [] method->index; +void AtomVec::Method::resize(int nfield) { + pdata.resize(nfield); + datatype.resize(nfield); + cols.resize(nfield); + maxcols.resize(nfield); + collength.resize(nfield); + plength.resize(nfield); + index.resize(nfield); } diff --git a/src/atom_vec.h b/src/atom_vec.h index 8e670304ed..a8f5f5ec22 100644 --- a/src/atom_vec.h +++ b/src/atom_vec.h @@ -191,13 +191,15 @@ class AtomVec : protected Pointers { const char *default_create,*default_data_atom,*default_data_vel; struct Method { - void **pdata; - int *datatype; - int *cols; - int **maxcols; - int *collength; - void **plength; - int *index; + std::vector pdata; + std::vector datatype; + std::vector cols; + std::vector maxcols; + std::vector collength; + std::vector plength; + std::vector index; + + void resize(int nfield); }; Method mgrow,mcopy; @@ -219,9 +221,7 @@ class AtomVec : protected Pointers { int grow_nmax_bonus(int); void setup_fields(); int process_fields(char *, const char *, Method *); - void create_method(int, Method *); - void init_method(Method *); - void destroy_method(Method *); + void init_method(int, Method *); }; } diff --git a/src/force.cpp b/src/force.cpp index e56e250ffc..80f5ef22a7 100644 --- a/src/force.cpp +++ b/src/force.cpp @@ -36,8 +36,6 @@ using namespace LAMMPS_NS; -#define MAXLINE 1024 - /* ---------------------------------------------------------------------- */ Force::Force(LAMMPS *lmp) : Pointers(lmp) diff --git a/src/group.cpp b/src/group.cpp index 0143008a72..9e140779ef 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -30,11 +30,13 @@ #include "region.h" #include "tokenizer.h" #include "variable.h" +#include "exceptions.h" #include #include #include #include +#include using namespace LAMMPS_NS; @@ -151,12 +153,14 @@ void Group::assign(int narg, char **arg) // add a new group if igroup = -1 int igroup = find(arg[0]); + bool created = false; if (igroup == -1) { if (ngroup == MAX_GROUP) error->all(FLERR,"Too many groups"); igroup = find_unused(); names[igroup] = utils::strdup(arg[0]); ngroup++; + created = true; } double **x = atom->x; @@ -164,355 +168,360 @@ void Group::assign(int narg, char **arg) int nlocal = atom->nlocal; int bit = bitmask[igroup]; - // style = region - // add to group if atom is in region + try { + // style = region + // add to group if atom is in region - if (strcmp(arg[1],"region") == 0) { + if (strcmp(arg[1],"region") == 0) { - if (narg != 3) error->all(FLERR,"Illegal group command"); + if (narg != 3) error->all(FLERR,"Illegal group command"); - int iregion = domain->find_region(arg[2]); - if (iregion == -1) error->all(FLERR,"Group region ID does not exist"); - domain->regions[iregion]->init(); - domain->regions[iregion]->prematch(); + int iregion = domain->find_region(arg[2]); + if (iregion == -1) error->all(FLERR,"Group region ID does not exist"); + domain->regions[iregion]->init(); + domain->regions[iregion]->prematch(); - for (i = 0; i < nlocal; i++) - if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2])) - mask[i] |= bit; + for (i = 0; i < nlocal; i++) + if (domain->regions[iregion]->match(x[i][0],x[i][1],x[i][2])) + mask[i] |= bit; - // create an empty group + // create an empty group - } else if (strcmp(arg[1],"empty") == 0) { + } else if (strcmp(arg[1],"empty") == 0) { - if (narg != 2) error->all(FLERR,"Illegal group command"); - // nothing else to do here + if (narg != 2) error->all(FLERR,"Illegal group command"); + // nothing else to do here - // style = type, molecule, id - // add to group if atom matches type/molecule/id or condition + // style = type, molecule, id + // add to group if atom matches type/molecule/id or condition - } else if (strcmp(arg[1],"type") == 0 || strcmp(arg[1],"molecule") == 0 || - strcmp(arg[1],"id") == 0) { + } else if (strcmp(arg[1],"type") == 0 || strcmp(arg[1],"molecule") == 0 || + strcmp(arg[1],"id") == 0) { - if (narg < 3) error->all(FLERR,"Illegal group command"); + if (narg < 3) error->all(FLERR,"Illegal group command"); - int category=NONE; - if (strcmp(arg[1],"type") == 0) category = TYPE; - else if (strcmp(arg[1],"molecule") == 0) category = MOLECULE; - else if (strcmp(arg[1],"id") == 0) category = ID; + int category=NONE; + if (strcmp(arg[1],"type") == 0) category = TYPE; + else if (strcmp(arg[1],"molecule") == 0) category = MOLECULE; + else if (strcmp(arg[1],"id") == 0) category = ID; - if ((category == MOLECULE) && (!atom->molecule_flag)) - error->all(FLERR,"Group command requires atom attribute molecule"); - - if ((category == ID) && (!atom->tag_enable)) - error->all(FLERR,"Group command requires atom IDs"); - - // args = logical condition - - if (narg > 3 && - (strcmp(arg[2],"<") == 0 || strcmp(arg[2],">") == 0 || - strcmp(arg[2],"<=") == 0 || strcmp(arg[2],">=") == 0 || - strcmp(arg[2],"==") == 0 || strcmp(arg[2],"!=") == 0 || - strcmp(arg[2],"<>") == 0)) { - - int condition = -1; - if (strcmp(arg[2],"<") == 0) condition = LT; - else if (strcmp(arg[2],"<=") == 0) condition = LE; - else if (strcmp(arg[2],">") == 0) condition = GT; - else if (strcmp(arg[2],">=") == 0) condition = GE; - else if (strcmp(arg[2],"==") == 0) condition = EQ; - else if (strcmp(arg[2],"!=") == 0) condition = NEQ; - else if (strcmp(arg[2],"<>") == 0) condition = BETWEEN; - else error->all(FLERR,"Illegal group command"); - - tagint bound1,bound2; - bound1 = utils::tnumeric(FLERR,arg[3],false,lmp); - bound2 = -1; - - if (condition == BETWEEN) { - if (narg != 5) error->all(FLERR,"Illegal group command"); - bound2 = utils::tnumeric(FLERR,arg[4],false,lmp); - } else if (narg != 4) error->all(FLERR,"Illegal group command"); - - int *attribute = nullptr; - tagint *tattribute = nullptr; - if (category == TYPE) attribute = atom->type; - else if (category == MOLECULE) tattribute = atom->molecule; - else if (category == ID) tattribute = atom->tag; - - // add to group if meets condition - - if (attribute) { - if (condition == LT) { - for (i = 0; i < nlocal; i++) - if (attribute[i] < bound1) mask[i] |= bit; - } else if (condition == LE) { - for (i = 0; i < nlocal; i++) - if (attribute[i] <= bound1) mask[i] |= bit; - } else if (condition == GT) { - for (i = 0; i < nlocal; i++) - if (attribute[i] > bound1) mask[i] |= bit; - } else if (condition == GE) { - for (i = 0; i < nlocal; i++) - if (attribute[i] >= bound1) mask[i] |= bit; - } else if (condition == EQ) { - for (i = 0; i < nlocal; i++) - if (attribute[i] == bound1) mask[i] |= bit; - } else if (condition == NEQ) { - for (i = 0; i < nlocal; i++) - if (attribute[i] != bound1) mask[i] |= bit; - } else if (condition == BETWEEN) { - for (i = 0; i < nlocal; i++) - if (attribute[i] >= bound1 && attribute[i] <= bound2) - mask[i] |= bit; - } - } else { - if (condition == LT) { - for (i = 0; i < nlocal; i++) - if (tattribute[i] < bound1) mask[i] |= bit; - } else if (condition == LE) { - for (i = 0; i < nlocal; i++) - if (tattribute[i] <= bound1) mask[i] |= bit; - } else if (condition == GT) { - for (i = 0; i < nlocal; i++) - if (tattribute[i] > bound1) mask[i] |= bit; - } else if (condition == GE) { - for (i = 0; i < nlocal; i++) - if (tattribute[i] >= bound1) mask[i] |= bit; - } else if (condition == EQ) { - for (i = 0; i < nlocal; i++) - if (tattribute[i] == bound1) mask[i] |= bit; - } else if (condition == NEQ) { - for (i = 0; i < nlocal; i++) - if (tattribute[i] != bound1) mask[i] |= bit; - } else if (condition == BETWEEN) { - for (i = 0; i < nlocal; i++) - if (tattribute[i] >= bound1 && tattribute[i] <= bound2) - mask[i] |= bit; - } - } - - // args = list of values - - } else { - int *attribute = nullptr; - tagint *tattribute = nullptr; - if (category == TYPE) attribute = atom->type; - else if (category == MOLECULE) tattribute = atom->molecule; - else if (category == ID) tattribute = atom->tag; - - tagint start,stop,delta; - - for (int iarg = 2; iarg < narg; iarg++) { - delta = 1; - try { - ValueTokenizer values(arg[iarg],":"); - start = values.next_tagint(); - if (utils::strmatch(arg[iarg],"^-?\\d+$")) { - stop = start; - } else if (utils::strmatch(arg[iarg],"^-?\\d+:-?\\d+$")) { - stop = values.next_tagint(); - } else if (utils::strmatch(arg[iarg],"^-?\\d+:-?\\d+:\\d+$")) { - stop = values.next_tagint(); - delta = values.next_tagint(); - } else throw TokenizerException("Syntax error",""); - } catch (TokenizerException &e) { - error->all(FLERR,fmt::format("Incorrect range string " - "'{}': {}",arg[iarg],e.what())); - } - if (delta < 1) - error->all(FLERR,"Illegal range increment value"); - - // add to group if attribute matches value or sequence - - if (attribute) { - for (i = 0; i < nlocal; i++) - if (attribute[i] >= start && attribute[i] <= stop && - (attribute[i]-start) % delta == 0) mask[i] |= bit; - } else { - for (i = 0; i < nlocal; i++) - if (tattribute[i] >= start && tattribute[i] <= stop && - (tattribute[i]-start) % delta == 0) mask[i] |= bit; - } - } - } - - // style = variable - // add to group if atom-atyle variable is non-zero - - } else if (strcmp(arg[1],"variable") == 0) { - - int ivar = input->variable->find(arg[2]); - if (ivar < 0) error->all(FLERR,"Variable name for group does not exist"); - if (!input->variable->atomstyle(ivar)) - error->all(FLERR,"Variable for group is invalid style"); - - double *aflag; - - // aflag = evaluation of per-atom variable - - memory->create(aflag,nlocal,"group:aflag"); - input->variable->compute_atom(ivar,0,aflag,1,0); - - // add to group if per-atom variable evaluated to non-zero - - for (i = 0; i < nlocal; i++) - if (aflag[i] != 0.0) mask[i] |= bit; - - memory->destroy(aflag); - - // style = include - - } else if (strcmp(arg[1],"include") == 0) { - - if (narg != 3) error->all(FLERR,"Illegal group command"); - if (strcmp(arg[2],"molecule") == 0) { - if (!atom->molecule_flag) + if ((category == MOLECULE) && (!atom->molecule_flag)) error->all(FLERR,"Group command requires atom attribute molecule"); - add_molecules(igroup,bit); + if ((category == ID) && (!atom->tag_enable)) + error->all(FLERR,"Group command requires atom IDs"); + + // args = logical condition + + if (narg > 3 && + (strcmp(arg[2],"<") == 0 || strcmp(arg[2],">") == 0 || + strcmp(arg[2],"<=") == 0 || strcmp(arg[2],">=") == 0 || + strcmp(arg[2],"==") == 0 || strcmp(arg[2],"!=") == 0 || + strcmp(arg[2],"<>") == 0)) { + + int condition = -1; + if (strcmp(arg[2],"<") == 0) condition = LT; + else if (strcmp(arg[2],"<=") == 0) condition = LE; + else if (strcmp(arg[2],">") == 0) condition = GT; + else if (strcmp(arg[2],">=") == 0) condition = GE; + else if (strcmp(arg[2],"==") == 0) condition = EQ; + else if (strcmp(arg[2],"!=") == 0) condition = NEQ; + else if (strcmp(arg[2],"<>") == 0) condition = BETWEEN; + else error->all(FLERR,"Illegal group command"); + + tagint bound1,bound2; + bound1 = utils::tnumeric(FLERR,arg[3],false,lmp); + bound2 = -1; + + if (condition == BETWEEN) { + if (narg != 5) error->all(FLERR,"Illegal group command"); + bound2 = utils::tnumeric(FLERR,arg[4],false,lmp); + } else if (narg != 4) error->all(FLERR,"Illegal group command"); + + int *attribute = nullptr; + tagint *tattribute = nullptr; + if (category == TYPE) attribute = atom->type; + else if (category == MOLECULE) tattribute = atom->molecule; + else if (category == ID) tattribute = atom->tag; + + // add to group if meets condition + + if (attribute) { + if (condition == LT) { + for (i = 0; i < nlocal; i++) + if (attribute[i] < bound1) mask[i] |= bit; + } else if (condition == LE) { + for (i = 0; i < nlocal; i++) + if (attribute[i] <= bound1) mask[i] |= bit; + } else if (condition == GT) { + for (i = 0; i < nlocal; i++) + if (attribute[i] > bound1) mask[i] |= bit; + } else if (condition == GE) { + for (i = 0; i < nlocal; i++) + if (attribute[i] >= bound1) mask[i] |= bit; + } else if (condition == EQ) { + for (i = 0; i < nlocal; i++) + if (attribute[i] == bound1) mask[i] |= bit; + } else if (condition == NEQ) { + for (i = 0; i < nlocal; i++) + if (attribute[i] != bound1) mask[i] |= bit; + } else if (condition == BETWEEN) { + for (i = 0; i < nlocal; i++) + if (attribute[i] >= bound1 && attribute[i] <= bound2) + mask[i] |= bit; + } + } else { + if (condition == LT) { + for (i = 0; i < nlocal; i++) + if (tattribute[i] < bound1) mask[i] |= bit; + } else if (condition == LE) { + for (i = 0; i < nlocal; i++) + if (tattribute[i] <= bound1) mask[i] |= bit; + } else if (condition == GT) { + for (i = 0; i < nlocal; i++) + if (tattribute[i] > bound1) mask[i] |= bit; + } else if (condition == GE) { + for (i = 0; i < nlocal; i++) + if (tattribute[i] >= bound1) mask[i] |= bit; + } else if (condition == EQ) { + for (i = 0; i < nlocal; i++) + if (tattribute[i] == bound1) mask[i] |= bit; + } else if (condition == NEQ) { + for (i = 0; i < nlocal; i++) + if (tattribute[i] != bound1) mask[i] |= bit; + } else if (condition == BETWEEN) { + for (i = 0; i < nlocal; i++) + if (tattribute[i] >= bound1 && tattribute[i] <= bound2) + mask[i] |= bit; + } + } + + // args = list of values + + } else { + int *attribute = nullptr; + tagint *tattribute = nullptr; + if (category == TYPE) attribute = atom->type; + else if (category == MOLECULE) tattribute = atom->molecule; + else if (category == ID) tattribute = atom->tag; + + tagint start,stop,delta; + + for (int iarg = 2; iarg < narg; iarg++) { + delta = 1; + try { + ValueTokenizer values(arg[iarg],":"); + start = values.next_tagint(); + if (utils::strmatch(arg[iarg],"^-?\\d+$")) { + stop = start; + } else if (utils::strmatch(arg[iarg],"^-?\\d+:-?\\d+$")) { + stop = values.next_tagint(); + } else if (utils::strmatch(arg[iarg],"^-?\\d+:-?\\d+:\\d+$")) { + stop = values.next_tagint(); + delta = values.next_tagint(); + } else throw TokenizerException("Syntax error",""); + } catch (TokenizerException &e) { + error->all(FLERR,fmt::format("Incorrect range string " + "'{}': {}",arg[iarg],e.what())); + } + if (delta < 1) + error->all(FLERR,"Illegal range increment value"); + + // add to group if attribute matches value or sequence + + if (attribute) { + for (i = 0; i < nlocal; i++) + if (attribute[i] >= start && attribute[i] <= stop && + (attribute[i]-start) % delta == 0) mask[i] |= bit; + } else { + for (i = 0; i < nlocal; i++) + if (tattribute[i] >= start && tattribute[i] <= stop && + (tattribute[i]-start) % delta == 0) mask[i] |= bit; + } + } + } + + // style = variable + // add to group if atom-atyle variable is non-zero + + } else if (strcmp(arg[1],"variable") == 0) { + + int ivar = input->variable->find(arg[2]); + if (ivar < 0) error->all(FLERR,"Variable name for group does not exist"); + if (!input->variable->atomstyle(ivar)) + error->all(FLERR,"Variable for group is invalid style"); + + double *aflag; + + // aflag = evaluation of per-atom variable + + memory->create(aflag,nlocal,"group:aflag"); + input->variable->compute_atom(ivar,0,aflag,1,0); + + // add to group if per-atom variable evaluated to non-zero + + for (i = 0; i < nlocal; i++) + if (aflag[i] != 0.0) mask[i] |= bit; + + memory->destroy(aflag); + + // style = include + + } else if (strcmp(arg[1],"include") == 0) { + + if (narg != 3) error->all(FLERR,"Illegal group command"); + if (strcmp(arg[2],"molecule") == 0) { + if (!atom->molecule_flag) + error->all(FLERR,"Group command requires atom attribute molecule"); + + add_molecules(igroup,bit); + + } else error->all(FLERR,"Illegal group command"); + + // style = subtract + + } else if (strcmp(arg[1],"subtract") == 0) { + + if (narg < 4) error->all(FLERR,"Illegal group command"); + + int length = narg-2; + std::vector list(length); + + int jgroup; + for (int iarg = 2; iarg < narg; iarg++) { + jgroup = find(arg[iarg]); + if (jgroup == -1) error->all(FLERR,"Group ID does not exist"); + if (dynamic[jgroup]) + error->all(FLERR,"Cannot subtract groups using a dynamic group"); + list[iarg-2] = jgroup; + } + + // add to group if in 1st group in list + + int otherbit = bitmask[list[0]]; + + for (i = 0; i < nlocal; i++) + if (mask[i] & otherbit) mask[i] |= bit; + + // remove atoms if they are in any of the other groups + // AND with inverse mask removes the atom from group + + int inverse = inversemask[igroup]; + + for (int ilist = 1; ilist < length; ilist++) { + otherbit = bitmask[list[ilist]]; + for (i = 0; i < nlocal; i++) + if (mask[i] & otherbit) mask[i] &= inverse; + } + + // style = union + + } else if (strcmp(arg[1],"union") == 0) { + + if (narg < 3) error->all(FLERR,"Illegal group command"); + + int length = narg-2; + std::vector list(length); + + int jgroup; + for (int iarg = 2; iarg < narg; iarg++) { + jgroup = find(arg[iarg]); + if (jgroup == -1) error->all(FLERR,"Group ID does not exist"); + if (dynamic[jgroup]) + error->all(FLERR,"Cannot union groups using a dynamic group"); + list[iarg-2] = jgroup; + } + + // add to group if in any other group in list + + int otherbit; + + for (int ilist = 0; ilist < length; ilist++) { + otherbit = bitmask[list[ilist]]; + for (i = 0; i < nlocal; i++) + if (mask[i] & otherbit) mask[i] |= bit; + } + + // style = intersect + + } else if (strcmp(arg[1],"intersect") == 0) { + + if (narg < 4) error->all(FLERR,"Illegal group command"); + + int length = narg-2; + std::vector list(length); + + int jgroup; + for (int iarg = 2; iarg < narg; iarg++) { + jgroup = find(arg[iarg]); + if (jgroup == -1) error->all(FLERR,"Group ID does not exist"); + if (dynamic[jgroup]) + error->all(FLERR,"Cannot intersect groups using a dynamic group"); + list[iarg-2] = jgroup; + } + + // add to group if in all groups in list + + int otherbit,ok,ilist; + + for (i = 0; i < nlocal; i++) { + ok = 1; + for (ilist = 0; ilist < length; ilist++) { + otherbit = bitmask[list[ilist]]; + if ((mask[i] & otherbit) == 0) ok = 0; + } + if (ok) mask[i] |= bit; + } + + // style = dynamic + // create a new FixGroup to dynamically determine atoms in group + + } else if (strcmp(arg[1],"dynamic") == 0) { + + if (narg < 4) error->all(FLERR,"Illegal group command"); + if (strcmp(arg[0],arg[2]) == 0) + error->all(FLERR,"Group dynamic cannot reference itself"); + if (find(arg[2]) < 0) + error->all(FLERR,"Group dynamic parent group does not exist"); + if (igroup == 0) error->all(FLERR,"Group all cannot be made dynamic"); + + // if group is already dynamic, delete existing FixGroup + + if (dynamic[igroup]) + modify->delete_fix(std::string("GROUP_") + names[igroup]); + + dynamic[igroup] = 1; + + std::string fixcmd = "GROUP_"; + fixcmd += fmt::format("{} {} GROUP",names[igroup],arg[2]); + for (int i = 3; i < narg; i++) fixcmd += std::string(" ") + arg[i]; + modify->add_fix(fixcmd); + + // style = static + // remove dynamic FixGroup if necessary + + } else if (strcmp(arg[1],"static") == 0) { + + if (narg != 2) error->all(FLERR,"Illegal group command"); + + if (dynamic[igroup]) + modify->delete_fix(std::string("GROUP_") + names[igroup]); + + dynamic[igroup] = 0; + + // not a valid group style } else error->all(FLERR,"Illegal group command"); - // style = subtract - - } else if (strcmp(arg[1],"subtract") == 0) { - - if (narg < 4) error->all(FLERR,"Illegal group command"); - - int length = narg-2; - int *list = new int[length]; - - int jgroup; - for (int iarg = 2; iarg < narg; iarg++) { - jgroup = find(arg[iarg]); - if (jgroup == -1) error->all(FLERR,"Group ID does not exist"); - if (dynamic[jgroup]) - error->all(FLERR,"Cannot subtract groups using a dynamic group"); - list[iarg-2] = jgroup; + } catch (LAMMPSException & e) { + // undo created group in case of an error + if (created) { + delete [] names[igroup]; + names[igroup] = nullptr; + ngroup--; } - - // add to group if in 1st group in list - - int otherbit = bitmask[list[0]]; - - for (i = 0; i < nlocal; i++) - if (mask[i] & otherbit) mask[i] |= bit; - - // remove atoms if they are in any of the other groups - // AND with inverse mask removes the atom from group - - int inverse = inversemask[igroup]; - - for (int ilist = 1; ilist < length; ilist++) { - otherbit = bitmask[list[ilist]]; - for (i = 0; i < nlocal; i++) - if (mask[i] & otherbit) mask[i] &= inverse; - } - - delete [] list; - - // style = union - - } else if (strcmp(arg[1],"union") == 0) { - - if (narg < 3) error->all(FLERR,"Illegal group command"); - - int length = narg-2; - int *list = new int[length]; - - int jgroup; - for (int iarg = 2; iarg < narg; iarg++) { - jgroup = find(arg[iarg]); - if (jgroup == -1) error->all(FLERR,"Group ID does not exist"); - if (dynamic[jgroup]) - error->all(FLERR,"Cannot union groups using a dynamic group"); - list[iarg-2] = jgroup; - } - - // add to group if in any other group in list - - int otherbit; - - for (int ilist = 0; ilist < length; ilist++) { - otherbit = bitmask[list[ilist]]; - for (i = 0; i < nlocal; i++) - if (mask[i] & otherbit) mask[i] |= bit; - } - - delete [] list; - - // style = intersect - - } else if (strcmp(arg[1],"intersect") == 0) { - - if (narg < 4) error->all(FLERR,"Illegal group command"); - - int length = narg-2; - int *list = new int[length]; - - int jgroup; - for (int iarg = 2; iarg < narg; iarg++) { - jgroup = find(arg[iarg]); - if (jgroup == -1) error->all(FLERR,"Group ID does not exist"); - if (dynamic[jgroup]) - error->all(FLERR,"Cannot intersect groups using a dynamic group"); - list[iarg-2] = jgroup; - } - - // add to group if in all groups in list - - int otherbit,ok,ilist; - - for (i = 0; i < nlocal; i++) { - ok = 1; - for (ilist = 0; ilist < length; ilist++) { - otherbit = bitmask[list[ilist]]; - if ((mask[i] & otherbit) == 0) ok = 0; - } - if (ok) mask[i] |= bit; - } - - delete [] list; - - // style = dynamic - // create a new FixGroup to dynamically determine atoms in group - - } else if (strcmp(arg[1],"dynamic") == 0) { - - if (narg < 4) error->all(FLERR,"Illegal group command"); - if (strcmp(arg[0],arg[2]) == 0) - error->all(FLERR,"Group dynamic cannot reference itself"); - if (find(arg[2]) < 0) - error->all(FLERR,"Group dynamic parent group does not exist"); - if (igroup == 0) error->all(FLERR,"Group all cannot be made dynamic"); - - // if group is already dynamic, delete existing FixGroup - - if (dynamic[igroup]) - modify->delete_fix(std::string("GROUP_") + names[igroup]); - - dynamic[igroup] = 1; - - std::string fixcmd = "GROUP_"; - fixcmd += fmt::format("{} {} GROUP",names[igroup],arg[2]); - for (int i = 3; i < narg; i++) fixcmd += std::string(" ") + arg[i]; - modify->add_fix(fixcmd); - - // style = static - // remove dynamic FixGroup if necessary - - } else if (strcmp(arg[1],"static") == 0) { - - if (narg != 2) error->all(FLERR,"Illegal group command"); - - if (dynamic[igroup]) - modify->delete_fix(std::string("GROUP_") + names[igroup]); - - dynamic[igroup] = 0; - - // not a valid group style - - } else error->all(FLERR,"Illegal group command"); + throw e; + } // print stats for changed group @@ -539,13 +548,12 @@ void Group::assign(int narg, char **arg) void Group::assign(const std::string &groupcmd) { auto args = utils::split_words(groupcmd); - char **newarg = new char*[args.size()]; + std::vector newarg(args.size()); int i=0; for (const auto &arg : args) { newarg[i++] = (char *)arg.c_str(); } - assign(args.size(),newarg); - delete[] newarg; + assign(args.size(),newarg.data()); } /* ---------------------------------------------------------------------- diff --git a/src/modify.cpp b/src/modify.cpp index 79a0ecd41f..246b855913 100644 --- a/src/modify.cpp +++ b/src/modify.cpp @@ -964,13 +964,12 @@ void Modify::add_fix(int narg, char **arg, int trysuffix) void Modify::add_fix(const std::string &fixcmd, int trysuffix) { auto args = utils::split_words(fixcmd); - char **newarg = new char*[args.size()]; - int i=0; + std::vector newarg(args.size()); + int i = 0; for (const auto &arg : args) { newarg[i++] = (char *)arg.c_str(); } - add_fix(args.size(),newarg,trysuffix); - delete[] newarg; + add_fix(args.size(),newarg.data(),trysuffix); } diff --git a/src/pair_coul_streitz.cpp b/src/pair_coul_streitz.cpp index 55529f9eae..87bcd45736 100644 --- a/src/pair_coul_streitz.cpp +++ b/src/pair_coul_streitz.cpp @@ -36,7 +36,6 @@ using namespace LAMMPS_NS; using namespace MathConst; -#define MAXLINE 1024 #define DELTA 4 #define PGDELTA 1 #define MAXNEIGH 24 diff --git a/src/run.cpp b/src/run.cpp index 379cf8015a..1534d506d6 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -27,8 +27,6 @@ using namespace LAMMPS_NS; -#define MAXLINE 2048 - /* ---------------------------------------------------------------------- */ Run::Run(LAMMPS *lmp) : Command(lmp) {} diff --git a/src/variable.cpp b/src/variable.cpp index f66b99d6e5..3e93a33797 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -412,7 +412,7 @@ void Variable::set(int narg, char **arg) if (style[ivar] != EQUAL) error->all(FLERR,"Cannot redefine variable as a different style"); delete [] data[ivar][0]; - copy(1,&arg[2],data[ivar]); + data[ivar][0] = utils::strdup(arg[2]); replaceflag = 1; } else { if (nvar == maxvar) grow(); @@ -421,7 +421,7 @@ void Variable::set(int narg, char **arg) which[nvar] = 0; pad[nvar] = 0; data[nvar] = new char*[num[nvar]]; - copy(1,&arg[2],data[nvar]); + data[nvar][0] = utils::strdup(arg[2]); data[nvar][1] = new char[VALUELENGTH]; strcpy(data[nvar][1],"(undefined)"); } @@ -438,7 +438,7 @@ void Variable::set(int narg, char **arg) if (style[ivar] != ATOM) error->all(FLERR,"Cannot redefine variable as a different style"); delete [] data[ivar][0]; - copy(1,&arg[2],data[ivar]); + data[ivar][0] = utils::strdup(arg[2]); replaceflag = 1; } else { if (nvar == maxvar) grow(); @@ -447,7 +447,7 @@ void Variable::set(int narg, char **arg) which[nvar] = 0; pad[nvar] = 0; data[nvar] = new char*[num[nvar]]; - copy(1,&arg[2],data[nvar]); + data[nvar][0] = utils::strdup(arg[2]); } // VECTOR @@ -462,7 +462,7 @@ void Variable::set(int narg, char **arg) if (style[ivar] != VECTOR) error->all(FLERR,"Cannot redefine variable as a different style"); delete [] data[ivar][0]; - copy(1,&arg[2],data[ivar]); + data[ivar][0] = utils::strdup(arg[2]); replaceflag = 1; } else { if (nvar == maxvar) grow(); @@ -471,7 +471,7 @@ void Variable::set(int narg, char **arg) which[nvar] = 0; pad[nvar] = 0; data[nvar] = new char*[num[nvar]]; - copy(1,&arg[2],data[nvar]); + data[nvar][0] = utils::strdup(arg[2]); } // PYTHON @@ -488,7 +488,7 @@ void Variable::set(int narg, char **arg) if (style[ivar] != PYTHON) error->all(FLERR,"Cannot redefine variable as a different style"); delete [] data[ivar][0]; - copy(1,&arg[2],data[ivar]); + data[ivar][0] = utils::strdup(arg[2]); replaceflag = 1; } else { if (nvar == maxvar) grow(); @@ -497,7 +497,7 @@ void Variable::set(int narg, char **arg) which[nvar] = 1; pad[nvar] = 0; data[nvar] = new char*[num[nvar]]; - copy(1,&arg[2],data[nvar]); + data[nvar][0] = utils::strdup(arg[2]); data[nvar][1] = new char[VALUELENGTH]; strcpy(data[nvar][1],"(undefined)"); } diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 4e27f4be45..412cf8d3d6 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -7,6 +7,7 @@ add_test(NAME RunLammps COMMAND $ -log none -echo none -in in.empty WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) set_tests_properties(RunLammps PROPERTIES + ENVIRONMENT "TSAN_OPTIONS='ignore_noninstrumented_modules=1'" PASS_REGULAR_EXPRESSION "^LAMMPS \\([0-9]+ [A-Za-z]+ 2[0-9][0-9][0-9]\\)") if(BUILD_MPI) diff --git a/unittest/commands/test_groups.cpp b/unittest/commands/test_groups.cpp index 181f000a7c..7feddcc685 100644 --- a/unittest/commands/test_groups.cpp +++ b/unittest/commands/test_groups.cpp @@ -297,7 +297,7 @@ TEST_F(GroupTest, Dynamic) command("group grow delete"); command("variable ramp equal step"); END_HIDE_OUTPUT(); - ASSERT_EQ(group->ngroup, 4); + ASSERT_EQ(group->ngroup, 3); TEST_FAILURE(".*ERROR: Group dynamic cannot reference itself.*", command("group half dynamic half region top");); diff --git a/unittest/formats/test_atom_styles.cpp b/unittest/formats/test_atom_styles.cpp index 8a031fe308..980afc3182 100644 --- a/unittest/formats/test_atom_styles.cpp +++ b/unittest/formats/test_atom_styles.cpp @@ -48,7 +48,7 @@ using LAMMPS_NS::utils::split_words; -static void create_molecule_files() +static void create_molecule_files(const std::string & h2o_filename, const std::string & co2_filename) { // create molecule files const char h2o_file[] = "# Water molecule. SPC/E model.\n\n3 atoms\n2 bonds\n1 angles\n\n" @@ -73,18 +73,16 @@ static void create_molecule_files() "Special Bond Counts\n\n1 2 0 0\n2 1 1 0\n3 1 1 0\n\n" "Special Bonds\n\n1 2 3\n2 1 3\n3 1 2\n\n"; - FILE *fp = fopen("tmp.h2o.mol", "w"); + FILE *fp = fopen(h2o_filename.c_str(), "w"); if (fp) { fputs(h2o_file, fp); fclose(fp); } - rename("tmp.h2o.mol", "h2o.mol"); - fp = fopen("tmp.co2.mol", "w"); + fp = fopen(co2_filename.c_str(), "w"); if (fp) { fputs(co2_file, fp); fclose(fp); } - rename("tmp.co2.mol", "co2.mol"); } // whether to print verbose output (i.e. not capturing LAMMPS screen output). @@ -97,6 +95,15 @@ using ::testing::Eq; class AtomStyleTest : public LAMMPSTest { protected: + static void SetUpTestSuite() { + create_molecule_files("h2o.mol", "co2.mol"); + } + + static void TearDownTestSuite() { + remove("h2o.mol"); + remove("co2.mol"); + } + void SetUp() override { testbinary = "AtomStyleTest"; @@ -2618,7 +2625,6 @@ TEST_F(AtomStyleTest, body_nparticle) TEST_F(AtomStyleTest, template) { if (!LAMMPS::is_installed_pkg("MOLECULE")) GTEST_SKIP(); - create_molecule_files(); BEGIN_HIDE_OUTPUT(); command("molecule twomols h2o.mol co2.mol offset 2 1 1 0 0"); command("atom_style template twomols"); @@ -3014,7 +3020,6 @@ TEST_F(AtomStyleTest, template) TEST_F(AtomStyleTest, template_charge) { if (!LAMMPS::is_installed_pkg("MOLECULE")) GTEST_SKIP(); - create_molecule_files(); BEGIN_HIDE_OUTPUT(); command("molecule twomols h2o.mol co2.mol offset 2 1 1 0 0"); command("atom_style hybrid template twomols charge"); diff --git a/unittest/formats/test_molecule_file.cpp b/unittest/formats/test_molecule_file.cpp index 9928ec4b7c..5712e31a30 100644 --- a/unittest/formats/test_molecule_file.cpp +++ b/unittest/formats/test_molecule_file.cpp @@ -35,7 +35,7 @@ using utils::split_words; #define test_name test_info_->name() -static void create_molecule_files() +static void create_molecule_files(const std::string & h2o_filename, const std::string & co2_filename) { // create molecule files const char h2o_file[] = "# Water molecule. SPC/E model.\n\n3 atoms\n2 bonds\n1 angles\n\n" @@ -60,18 +60,16 @@ static void create_molecule_files() "Special Bond Counts\n\n1 2 0 0\n2 1 1 0\n3 1 1 0\n\n" "Special Bonds\n\n1 2 3\n2 1 3\n3 1 2\n\n"; - FILE *fp = fopen("tmp.h2o.mol", "w"); + FILE *fp = fopen(h2o_filename.c_str(), "w"); if (fp) { fputs(h2o_file, fp); fclose(fp); } - rename("tmp.h2o.mol", "h2o.mol"); - fp = fopen("tmp.co2.mol", "w"); + fp = fopen(co2_filename.c_str(), "w"); if (fp) { fputs(co2_file, fp); fclose(fp); } - rename("tmp.co2.mol", "co2.mol"); } // whether to print verbose output (i.e. not capturing LAMMPS screen output). @@ -79,26 +77,30 @@ bool verbose = false; class MoleculeFileTest : public LAMMPSTest { protected: + static void SetUpTestSuite() { + create_molecule_files("moltest.h2o.mol", "moltest.co2.mol"); + } + + static void TearDownTestSuite() { + remove("moltest.h2o.mol"); + remove("moltest.co2.mol"); + } + void SetUp() override { testbinary = "MoleculeFileTest"; LAMMPSTest::SetUp(); ASSERT_NE(lmp, nullptr); - BEGIN_HIDE_OUTPUT(); - create_molecule_files(); - END_HIDE_OUTPUT(); } void TearDown() override { LAMMPSTest::TearDown(); - remove("h2o.mol"); - remove("co2.mol"); } void run_mol_cmd(const std::string &name, const std::string &args, const std::string &content) { - std::string file = name + ".mol"; + std::string file = fmt::format("moltest_{}.mol", name); FILE *fp = fopen(file.c_str(), "w"); fputs(content.c_str(), fp); fclose(fp); @@ -195,7 +197,7 @@ TEST_F(MoleculeFileTest, twomols) TEST_F(MoleculeFileTest, twofiles) { BEGIN_CAPTURE_OUTPUT(); - command("molecule twomols h2o.mol co2.mol offset 2 1 1 0 0"); + command("molecule twomols moltest.h2o.mol moltest.co2.mol offset 2 1 1 0 0"); auto output = END_CAPTURE_OUTPUT(); ASSERT_THAT(output, MatchesRegex(".*Read molecule template twomols:.*1 molecules.*3 atoms " "with max type 2.*2 bonds with max type 1.*" diff --git a/unittest/testing/core.h b/unittest/testing/core.h index 75b0564d02..843d135645 100644 --- a/unittest/testing/core.h +++ b/unittest/testing/core.h @@ -42,6 +42,9 @@ using ::testing::MatchesRegex; auto mesg = ::testing::internal::GetCapturedStdout(); \ ASSERT_THAT(mesg, MatchesRegex(errmsg)); \ } \ + else { \ + std::cerr << "[ ] [ INFO ] Skipping death test (no exception support) \n"; \ + } \ } // whether to print verbose output (i.e. not capturing LAMMPS screen output).