diff --git a/doc/src/compute_reduce.rst b/doc/src/compute_reduce.rst index 89554ebece..3c16988abd 100644 --- a/doc/src/compute_reduce.rst +++ b/doc/src/compute_reduce.rst @@ -23,7 +23,7 @@ Syntax *reduce/region* arg = region-ID region-ID = ID of region to use for choosing atoms -* mode = *sum* or *min* or *max* or *ave* or *sumsq* or *avesq* or *sumabs* or *aveabs* +* mode = *sum* or *min* or *minabs* or *max* or *maxabs* or *ave* or *sumsq* or *avesq* or *sumabs* or *aveabs* * one or more inputs can be listed * input = *x* or *y* or *z* or *vx* or *vy* or *vz* or *fx* or *fy* or *fz* or c_ID or c_ID[N] or f_ID or f_ID[N] or v_name @@ -71,12 +71,13 @@ vectors. The reduction operation is specified by the *mode* setting. The *sum* option adds the values in the vector into a global total. The *min* or *max* options find the minimum or maximum value across all vector -values. The *ave* setting adds the vector values into a global total, -then divides by the number of values in the vector. The *sumsq* -option sums the square of the values in the vector into a global -total. The *avesq* setting does the same as *sumsq*, then divides the -sum of squares by the number of values. The last two options can be -useful for calculating the variance of some quantity (e.g., variance = +values. The *minabs* or *maxabs* options find the minimum or maximum +value across all absolute vector values. The *ave* setting adds the +vector values into a global total, then divides by the number of values +in the vector. The *sumsq* option sums the square of the values in the +vector into a global total. The *avesq* setting does the same as *sumsq*, +then divides the sum of squares by the number of values. The last two options +can be useful for calculating the variance of some quantity (e.g., variance = sumsq :math:`-` ave\ :math:`^2`). The *sumabs* option sums the absolute values in the vector into a global total. The *aveabs* setting does the same as *sumabs*, then divides the sum of absolute values by the number of diff --git a/src/compute_reduce.cpp b/src/compute_reduce.cpp index f2afeab3e6..5af532869c 100644 --- a/src/compute_reduce.cpp +++ b/src/compute_reduce.cpp @@ -33,6 +33,34 @@ using namespace LAMMPS_NS; #define BIG 1.0e20 +//---------------------------------------------------------------- +void abs_max(void *in, void *inout, int *len, MPI_Datatype *type) +{ + // r is the already reduced value, n is the new value + double n = std::fabs(*(double *) in), r = *(double *) inout; + double m; + + if (n > r) { + m = n; + } else { + m = r; + } + *(double *) inout = m; +} +void abs_min(void *in, void *inout, int *len, MPI_Datatype *type) +{ + // r is the already reduced value, n is the new value + double n = std::fabs(*(double *) in), r = *(double *) inout; + double m; + + if (n < r) { + m = n; + } else { + m = r; + } + *(double *) inout = m; +} + /* ---------------------------------------------------------------------- */ ComputeReduce::ComputeReduce(LAMMPS *lmp, int narg, char **arg) : @@ -67,10 +95,28 @@ ComputeReduce::ComputeReduce(LAMMPS *lmp, int narg, char **arg) : mode = AVESQ; else if (strcmp(arg[iarg], "aveabs") == 0) mode = AVEABS; + else if (strcmp(arg[iarg], "maxabs") == 0) + mode = MAXABS; + else if (strcmp(arg[iarg], "minabs") == 0) + mode = MINABS; else error->all(FLERR, "Unknown compute {} mode: {}", style, arg[iarg]); iarg++; + if (mode == SUM || mode == SUMSQ || mode == SUMABS) { + this->scalar_reduction_operation = MPI_SUM; + } else if (mode == AVE || mode == AVESQ || mode == AVEABS) { + this->scalar_reduction_operation = MPI_SUM; + } else if (mode == MINN) { + this->scalar_reduction_operation = MPI_MIN; + } else if (mode == MAXX) { + this->scalar_reduction_operation = MPI_MAX; + } else if (mode == MAXABS) { + MPI_Op_create(&abs_max, 1, &this->scalar_reduction_operation); + } else if (mode == MINABS) { + MPI_Op_create(&abs_min, 1, &this->scalar_reduction_operation); + } + // expand args if any have wildcard character "*" int expand = 0; @@ -329,14 +375,9 @@ double ComputeReduce::compute_scalar() double one = compute_one(0, -1); - if (mode == SUM || mode == SUMSQ || mode == SUMABS) { - MPI_Allreduce(&one, &scalar, 1, MPI_DOUBLE, MPI_SUM, world); - } else if (mode == MINN) { - MPI_Allreduce(&one, &scalar, 1, MPI_DOUBLE, MPI_MIN, world); - } else if (mode == MAXX) { - MPI_Allreduce(&one, &scalar, 1, MPI_DOUBLE, MPI_MAX, world); - } else if (mode == AVE || mode == AVESQ || mode == AVEABS) { - MPI_Allreduce(&one, &scalar, 1, MPI_DOUBLE, MPI_SUM, world); + MPI_Allreduce(&one, &scalar, 1, MPI_DOUBLE, this->scalar_reduction_operation, world); + + if (mode == AVE || mode == AVESQ || mode == AVEABS) { bigint n = count(0); if (n) scalar /= n; } @@ -441,7 +482,7 @@ double ComputeReduce::compute_one(int m, int flag) int nlocal = atom->nlocal; double one = 0.0; - if (mode == MINN) one = BIG; + if (mode == MINN || mode == MINABS) one = BIG; if (mode == MAXX) one = -BIG; if (val.which == ArgInfo::X) { @@ -637,6 +678,11 @@ void ComputeReduce::combine(double &one, double two, int i) one = two; index = i; } + } else if (mode == MAXABS) { + if (std::fabs(two) > one) { + one = std::fabs(two); + index = i; + } } } diff --git a/src/compute_reduce.h b/src/compute_reduce.h index 74313514f0..f8f73cb17a 100644 --- a/src/compute_reduce.h +++ b/src/compute_reduce.h @@ -26,7 +26,7 @@ namespace LAMMPS_NS { class ComputeReduce : public Compute { public: - enum { SUM, SUMSQ, SUMABS, MINN, MAXX, AVE, AVESQ, AVEABS }; + enum { SUM, SUMSQ, SUMABS, MINN, MAXX, AVE, AVESQ, AVEABS, MINABS, MAXABS }; enum { PERATOM, LOCAL }; ComputeReduce(class LAMMPS *, int, char **); @@ -52,6 +52,7 @@ class ComputeReduce : public Compute { std::vector values; double *onevec; int *replace, *indices, *owner; + MPI_Op scalar_reduction_operation; int index; char *idregion;