diff --git a/doc/src/compute_reduce.rst b/doc/src/compute_reduce.rst index 31591d4419..4692e161b4 100644 --- a/doc/src/compute_reduce.rst +++ b/doc/src/compute_reduce.rst @@ -63,9 +63,11 @@ Description """"""""""" Define a calculation that "reduces" one or more vector inputs into -scalar values, one per listed input. The inputs can be per-atom or -local quantities and must all be the same kind (per-atom or local); -see discussion of the optional *inputs* keyword below. +scalar values, one per listed input. For the compute reduce command, +the inputs can be either per-atom or local quantities and must all be +of the same kind (per-atom or local); see discussion of the optional +*inputs* keyword below. The compute reduce/region command can only be +used with per-atom inputs. Atom attributes are per-atom quantities, :doc:`computes ` and :doc:`fixes ` can generate either per-atom or local quantities, @@ -92,13 +94,13 @@ values. Each listed input is operated on independently. For per-atom inputs, the group specified with this command means only atoms within the -group contribute to the result. For per-atom inputs, if the compute -reduce/region command is used, the atoms must also currently be within -the region. Note that an input that produces per-atom quantities may -define its own group which affects the quantities it returns. For -example, if a compute is used as an input which generates a per-atom -vector, it will generate values of 0.0 for atoms that are not in the -group specified for that compute. +group contribute to the result. Likewise for per-atom inputs, if the +compute reduce/region command is used, the atoms must also currently +be within the region. Note that an input that produces per-atom +quantities may define its own group which affects the quantities it +returns. For example, if a compute is used as an input which +generates a per-atom vector, it will generate values of 0.0 for atoms +that are not in the group specified for that compute. Each listed input can be an atom attribute (position, velocity, force component) or can be the result of a :doc:`compute ` or @@ -246,7 +248,9 @@ the quantities being reduced are in. Restrictions """""""""""" - none + +As noted above, the compute reduce/region command can only be used +with per-atom inputs. Related commands """""""""""""""" diff --git a/doc/src/fix_ave_histo.rst b/doc/src/fix_ave_histo.rst index 8bb66f0615..31e5476f9e 100644 --- a/doc/src/fix_ave_histo.rst +++ b/doc/src/fix_ave_histo.rst @@ -79,9 +79,10 @@ Description Use one or more values as inputs every few timesteps to create a single histogram. The histogram can then be averaged over longer -timescales. The resulting histogram can be used by other :doc:`output commands `, and can also be written to a file. The -fix ave/histo/weight command has identical syntax to fix ave/histo, -except that exactly two values must be specified. See details below. +timescales. The resulting histogram can be used by other :doc:`output +commands `, and can also be written to a file. The fix +ave/histo/weight command has identical syntax to fix ave/histo, except +that exactly two values must be specified. See details below. The group specified with this command is ignored for global and local input values. For per-atom input values, only atoms in the group @@ -96,14 +97,18 @@ different ways; see the discussion of the *beyond* keyword below. Each input value can be an atom attribute (position, velocity, force component) or can be the result of a :doc:`compute ` or -:doc:`fix ` or the evaluation of an equal-style or vector-style or -atom-style :doc:`variable `. The set of input values can be -either all global, all per-atom, or all local quantities. Inputs of -different kinds (e.g. global and per-atom) cannot be mixed. Atom -attributes are per-atom vector values. See the page for -individual "compute" and "fix" commands to see what kinds of -quantities they generate. See the optional *kind* keyword below for -how to force the fix ave/histo command to disambiguate if necessary. +:doc:`fix ` or the evaluation of an equal-style or vector-style +or atom-style :doc:`variable `. The set of input values can +be either all global, all per-atom, or all local quantities. Inputs +of different kinds (e.g. global and per-atom) cannot be mixed. Atom +attributes are per-atom vector values. See the page for individual +"compute" and "fix" commands to see what kinds of quantities they +generate. + +Note that a compute or fix can produce multiple kinds of data (global, +per-atom, local). If LAMMPS cannot unambiguosly determine which kind +of data to use, the optional *kind* keyword discussed below can force +the desired disambiguation. Note that the output of this command is a single histogram for all input values combined together, not one histogram per input value. @@ -258,13 +263,14 @@ keyword is set to *vector*, then all input values must be global or per-atom or local vectors, or columns of global or per-atom or local arrays. -The *kind* keyword only needs to be set if a compute or fix produces -more than one kind of output (global, per-atom, local). If this is -not the case, then LAMMPS will determine what kind of input is -provided and whether all the input arguments are consistent. If a -compute or fix produces more than one kind of output, the *kind* -keyword should be used to specify which output will be used. The -remaining input arguments must still be consistent. +The *kind* keyword only needs to be used if any of the specfied input +computes or fixes produce more than one kind of output (global, +per-atom, local). If not, LAMMPS will determine the kind of data all +the inputs produce and verify it is all the same kind. If not, an +error will be triggered. If a compute or fix produces more than one +kind of output, the *kind* keyword should be used to specify which +output will be used. The other input arguments must still be +consistent. The *beyond* keyword determines how input values that fall outside the *lo* to *hi* bounds are treated. Values such that *lo* :math:`\le` value diff --git a/src/compute_reduce_region.cpp b/src/compute_reduce_region.cpp index 2f5a3de675..d0a32b8adf 100644 --- a/src/compute_reduce_region.cpp +++ b/src/compute_reduce_region.cpp @@ -35,13 +35,15 @@ static constexpr double BIG = 1.0e20; ComputeReduceRegion::ComputeReduceRegion(LAMMPS *lmp, int narg, char **arg) : ComputeReduce(lmp, narg, arg) { + if (input_mode == LOCAL) + error->all(FLERR,"Compute reduce/region cannot use local data as input"); } /* ---------------------------------------------------------------------- calculate reduced value for one input M and return it if flag = -1: sum/min/max/ave all values in vector - for per-atom quantities, limit to atoms in group and region + limit to atoms in group and region if mode = MIN or MAX, also set index to which vector value wins if flag >= 0: simply return vector[flag] ------------------------------------------------------------------------- */ @@ -59,6 +61,7 @@ double ComputeReduceRegion::compute_one(int m, int flag) // initialization in case it has not yet been run, e.g. when // the compute was invoked right after it has been created + if ((val.which == ArgInfo::COMPUTE) || (val.which == ArgInfo::FIX)) { if (val.val.c == nullptr) init(); } @@ -99,52 +102,29 @@ double ComputeReduceRegion::compute_one(int m, int flag) // invoke compute if not previously invoked } else if (val.which == ArgInfo::COMPUTE) { - if (input_mode == PERATOM) { - if (!(val.val.c->invoked_flag & Compute::INVOKED_PERATOM)) { - val.val.c->compute_peratom(); - val.val.c->invoked_flag |= Compute::INVOKED_PERATOM; - } - if (aidx == 0) { - double *compute_vector = val.val.c->vector_atom; - if (flag < 0) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit && region->match(x[i][0], x[i][1], x[i][2])) - combine(one, compute_vector[i], i); - } else - one = compute_vector[flag]; - } else { - double **compute_array = val.val.c->array_atom; - int aidxm1 = aidx - 1; - if (flag < 0) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit && region->match(x[i][0], x[i][1], x[i][2])) - combine(one, compute_array[i][aidxm1], i); - } else - one = compute_array[flag][aidxm1]; - } + if (!(val.val.c->invoked_flag & Compute::INVOKED_PERATOM)) { + val.val.c->compute_peratom(); + val.val.c->invoked_flag |= Compute::INVOKED_PERATOM; + } - } else if (input_mode == LOCAL) { - if (!(val.val.c->invoked_flag & Compute::INVOKED_LOCAL)) { - val.val.c->compute_local(); - val.val.c->invoked_flag |= Compute::INVOKED_LOCAL; - } - - if (aidx == 0) { - double *compute_vector = val.val.c->vector_local; - if (flag < 0) - for (int i = 0; i < val.val.c->size_local_rows; i++) combine(one, compute_vector[i], i); - else - one = compute_vector[flag]; - } else { - double **compute_array = val.val.c->array_local; - int aidxm1 = aidx - 1; - if (flag < 0) - for (int i = 0; i < val.val.c->size_local_rows; i++) + if (aidx == 0) { + double *compute_vector = val.val.c->vector_atom; + if (flag < 0) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit && region->match(x[i][0], x[i][1], x[i][2])) + combine(one, compute_vector[i], i); + } else + one = compute_vector[flag]; + } else { + double **compute_array = val.val.c->array_atom; + int aidxm1 = aidx - 1; + if (flag < 0) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit && region->match(x[i][0], x[i][1], x[i][2])) combine(one, compute_array[i][aidxm1], i); - else - one = compute_array[flag][aidxm1]; - } + } else + one = compute_array[flag][aidxm1]; } // check if fix frequency is a match @@ -153,45 +133,26 @@ double ComputeReduceRegion::compute_one(int m, int flag) if (update->ntimestep % val.val.f->peratom_freq) error->all(FLERR, "Fix {} used in compute {} not computed at compatible time", val.id, style); - if (input_mode == PERATOM) { - if (aidx == 0) { - double *fix_vector = val.val.f->vector_atom; - if (flag < 0) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit && region->match(x[i][0], x[i][1], x[i][2])) - combine(one, fix_vector[i], i); - } else - one = fix_vector[flag]; - } else { - double **fix_array = val.val.f->array_atom; - int aidxm1 = aidx - 1; - if (flag < 0) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit && region->match(x[i][0], x[i][1], x[i][2])) - combine(one, fix_array[i][aidxm1], i); - } else - one = fix_array[flag][aidxm1]; - } - - } else if (input_mode == LOCAL) { - if (aidx == 0) { - double *fix_vector = val.val.f->vector_local; - if (flag < 0) - for (int i = 0; i < val.val.f->size_local_rows; i++) combine(one, fix_vector[i], i); - else - one = fix_vector[flag]; - } else { - double **fix_array = val.val.f->array_local; - int aidxm1 = aidx - 1; - if (flag < 0) - for (int i = 0; i < val.val.f->size_local_rows; i++) + if (aidx == 0) { + double *fix_vector = val.val.f->vector_atom; + if (flag < 0) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit && region->match(x[i][0], x[i][1], x[i][2])) + combine(one, fix_vector[i], i); + } else + one = fix_vector[flag]; + } else { + double **fix_array = val.val.f->array_atom; + int aidxm1 = aidx - 1; + if (flag < 0) { + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit && region->match(x[i][0], x[i][1], x[i][2])) combine(one, fix_array[i][aidxm1], i); - else - one = fix_array[flag][aidxm1]; - } + } else + one = fix_array[flag][aidxm1]; } - // evaluate atom-style variable + // evaluate atom-style variable } else if (val.which == ArgInfo::VARIABLE) { if (atom->nmax > maxatom) { @@ -220,25 +181,11 @@ bigint ComputeReduceRegion::count(int m) if (val.which == ArgInfo::X || val.which == ArgInfo::V || val.which == ArgInfo::F) return group->count(igroup, region); - else if (val.which == ArgInfo::COMPUTE) { - if (input_mode == PERATOM) { - return group->count(igroup, region); - } else if (input_mode == LOCAL) { - bigint ncount = val.val.c->size_local_rows; - bigint ncountall; - MPI_Allreduce(&ncount, &ncountall, 1, MPI_DOUBLE, MPI_SUM, world); - return ncountall; - } - } else if (val.which == ArgInfo::FIX) { - if (input_mode == PERATOM) { - return group->count(igroup, region); - } else if (input_mode == LOCAL) { - bigint ncount = val.val.f->size_local_rows; - bigint ncountall; - MPI_Allreduce(&ncount, &ncountall, 1, MPI_DOUBLE, MPI_SUM, world); - return ncountall; - } - } else if (val.which == ArgInfo::VARIABLE) + else if (val.which == ArgInfo::COMPUTE) + return group->count(igroup, region); + else if (val.which == ArgInfo::FIX) + return group->count(igroup, region); + else if (val.which == ArgInfo::VARIABLE) return group->count(igroup, region); bigint dummy = 0; diff --git a/src/fix_ave_histo.cpp b/src/fix_ave_histo.cpp index 0a2975bb2e..4503ad56f4 100644 --- a/src/fix_ave_histo.cpp +++ b/src/fix_ave_histo.cpp @@ -164,7 +164,7 @@ FixAveHisto::FixAveHisto(LAMMPS *lmp, int narg, char **arg) : } // check input args for kind consistency - // all inputs must all be global, per-atom, or local + // inputs must all be all either global, per-atom, or local if (nevery <= 0) error->all(FLERR,"Illegal {} nevery value: {}", mycmd, nevery);