Implement maxabs and minabs atom reduction operations

This commit is contained in:
Tim Bernhard
2023-04-11 18:52:34 +02:00
parent ff5b4e971d
commit 7a32152ee5
3 changed files with 65 additions and 17 deletions

View File

@ -23,7 +23,7 @@ Syntax
*reduce/region* arg = region-ID *reduce/region* arg = region-ID
region-ID = ID of region to use for choosing atoms 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 * 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 * 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* The reduction operation is specified by the *mode* setting. The *sum*
option adds the values in the vector into a global total. The *min* 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 or *max* options find the minimum or maximum value across all vector
values. The *ave* setting adds the vector values into a global total, values. The *minabs* or *maxabs* options find the minimum or maximum
then divides by the number of values in the vector. The *sumsq* value across all absolute vector values. The *ave* setting adds the
option sums the square of the values in the vector into a global vector values into a global total, then divides by the number of values
total. The *avesq* setting does the same as *sumsq*, then divides the in the vector. The *sumsq* option sums the square of the values in the
sum of squares by the number of values. The last two options can be vector into a global total. The *avesq* setting does the same as *sumsq*,
useful for calculating the variance of some quantity (e.g., variance = 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 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 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 as *sumabs*, then divides the sum of absolute values by the number of

View File

@ -33,6 +33,34 @@ using namespace LAMMPS_NS;
#define BIG 1.0e20 #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) : ComputeReduce::ComputeReduce(LAMMPS *lmp, int narg, char **arg) :
@ -67,10 +95,28 @@ ComputeReduce::ComputeReduce(LAMMPS *lmp, int narg, char **arg) :
mode = AVESQ; mode = AVESQ;
else if (strcmp(arg[iarg], "aveabs") == 0) else if (strcmp(arg[iarg], "aveabs") == 0)
mode = AVEABS; mode = AVEABS;
else if (strcmp(arg[iarg], "maxabs") == 0)
mode = MAXABS;
else if (strcmp(arg[iarg], "minabs") == 0)
mode = MINABS;
else else
error->all(FLERR, "Unknown compute {} mode: {}", style, arg[iarg]); error->all(FLERR, "Unknown compute {} mode: {}", style, arg[iarg]);
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 "*" // expand args if any have wildcard character "*"
int expand = 0; int expand = 0;
@ -329,14 +375,9 @@ double ComputeReduce::compute_scalar()
double one = compute_one(0, -1); double one = compute_one(0, -1);
if (mode == SUM || mode == SUMSQ || mode == SUMABS) { MPI_Allreduce(&one, &scalar, 1, MPI_DOUBLE, this->scalar_reduction_operation, world);
MPI_Allreduce(&one, &scalar, 1, MPI_DOUBLE, MPI_SUM, world);
} else if (mode == MINN) { if (mode == AVE || mode == AVESQ || mode == AVEABS) {
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);
bigint n = count(0); bigint n = count(0);
if (n) scalar /= n; if (n) scalar /= n;
} }
@ -441,7 +482,7 @@ double ComputeReduce::compute_one(int m, int flag)
int nlocal = atom->nlocal; int nlocal = atom->nlocal;
double one = 0.0; double one = 0.0;
if (mode == MINN) one = BIG; if (mode == MINN || mode == MINABS) one = BIG;
if (mode == MAXX) one = -BIG; if (mode == MAXX) one = -BIG;
if (val.which == ArgInfo::X) { if (val.which == ArgInfo::X) {
@ -637,6 +678,11 @@ void ComputeReduce::combine(double &one, double two, int i)
one = two; one = two;
index = i; index = i;
} }
} else if (mode == MAXABS) {
if (std::fabs(two) > one) {
one = std::fabs(two);
index = i;
}
} }
} }

View File

@ -26,7 +26,7 @@ namespace LAMMPS_NS {
class ComputeReduce : public Compute { class ComputeReduce : public Compute {
public: public:
enum { SUM, SUMSQ, SUMABS, MINN, MAXX, AVE, AVESQ, AVEABS }; enum { SUM, SUMSQ, SUMABS, MINN, MAXX, AVE, AVESQ, AVEABS, MINABS, MAXABS };
enum { PERATOM, LOCAL }; enum { PERATOM, LOCAL };
ComputeReduce(class LAMMPS *, int, char **); ComputeReduce(class LAMMPS *, int, char **);
@ -52,6 +52,7 @@ class ComputeReduce : public Compute {
std::vector<value_t> values; std::vector<value_t> values;
double *onevec; double *onevec;
int *replace, *indices, *owner; int *replace, *indices, *owner;
MPI_Op scalar_reduction_operation;
int index; int index;
char *idregion; char *idregion;