2272 lines
72 KiB
C++
2272 lines
72 KiB
C++
// clang-format off
|
|
/* ----------------------------------------------------------------------
|
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
https://www.lammps.org/, Sandia National Laboratories
|
|
LAMMPS development team: developers@lammps.org
|
|
|
|
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_ave_grid.h"
|
|
|
|
#include "arg_info.h"
|
|
#include "atom.h"
|
|
#include "compute.h"
|
|
#include "domain.h"
|
|
#include "error.h"
|
|
#include "force.h"
|
|
#include "grid2d.h"
|
|
#include "grid3d.h"
|
|
#include "input.h"
|
|
#include "memory.h"
|
|
#include "modify.h"
|
|
#include "neighbor.h"
|
|
#include "update.h"
|
|
#include "variable.h"
|
|
|
|
#include <cstring>
|
|
|
|
using namespace LAMMPS_NS;
|
|
using namespace FixConst;
|
|
|
|
enum{ALL,SAMPLE,NONORM};
|
|
enum{ONE,RUNNING,WINDOW};
|
|
enum{DISCARD,KEEP};
|
|
|
|
// OFFSET avoids outside-of-box atoms being rounded to grid pts incorrectly
|
|
|
|
static constexpr int OFFSET = 16384;
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
FixAveGrid::FixAveGrid(LAMMPS *lmp, int narg, char **arg) :
|
|
Fix(lmp, narg, arg), id_bias(nullptr), which(nullptr), argindex(nullptr), ids(nullptr),
|
|
value2index(nullptr), value2grid(nullptr), value2data(nullptr), grid2d(nullptr), grid3d(nullptr),
|
|
grid_buf1(nullptr), grid_buf2(nullptr), grid_output(nullptr), grid_sample(nullptr),
|
|
grid_nfreq(nullptr), grid_running(nullptr), grid_window(nullptr), grid2d_previous(nullptr),
|
|
grid3d_previous(nullptr), grid_sample_previous(nullptr), grid_nfreq_previous(nullptr),
|
|
grid_running_previous(nullptr), grid_window_previous(nullptr), bin(nullptr), skip(nullptr),
|
|
vresult(nullptr)
|
|
{
|
|
if (narg < 10) utils::missing_cmd_args(FLERR,"fix ave/grid", error);
|
|
|
|
pergrid_flag = 1;
|
|
nevery = utils::inumeric(FLERR,arg[3],false,lmp);
|
|
nrepeat = utils::inumeric(FLERR,arg[4],false,lmp);
|
|
pergrid_freq = utils::inumeric(FLERR,arg[5],false,lmp);
|
|
time_depend = 1;
|
|
|
|
if (nevery <= 0 || nrepeat <= 0 || pergrid_freq <= 0)
|
|
error->all(FLERR,"Illegal fix ave/grid command");
|
|
if (pergrid_freq % nevery || nrepeat*nevery > pergrid_freq)
|
|
error->all(FLERR,"Illegal fix ave/grid command");
|
|
|
|
// NOTE: allow Dxyz as well at some point ?
|
|
|
|
nxgrid = utils::inumeric(FLERR,arg[6],false,lmp);
|
|
nygrid = utils::inumeric(FLERR,arg[7],false,lmp);
|
|
nzgrid = utils::inumeric(FLERR,arg[8],false,lmp);
|
|
|
|
// expand args if any have wildcard character "*"
|
|
// this can reset nvalues
|
|
|
|
int expand = 0;
|
|
char **earg;
|
|
int nargnew = utils::expand_args(FLERR,narg-9,&arg[9],1,earg,lmp);
|
|
|
|
if (earg != &arg[9]) expand = 1;
|
|
arg = earg;
|
|
|
|
// parse values until one isn't recognized (optional keyword)
|
|
|
|
which = new int[nargnew];
|
|
argindex = new int[nargnew];
|
|
ids = new char*[nargnew];
|
|
value2index = new int[nargnew];
|
|
value2grid = new int[nargnew];
|
|
value2data = new int[nargnew];
|
|
|
|
modeatom = modegrid = 0;
|
|
nvalues = 0;
|
|
|
|
int iarg = 0;
|
|
while (iarg < nargnew) {
|
|
ids[nvalues] = nullptr;
|
|
|
|
if (strcmp(arg[iarg],"vx") == 0) {
|
|
which[nvalues] = ArgInfo::V;
|
|
argindex[nvalues] = 0;
|
|
modeatom = 1;
|
|
} else if (strcmp(arg[iarg],"vy") == 0) {
|
|
which[nvalues] = ArgInfo::V;
|
|
argindex[nvalues] = 1;
|
|
modeatom = 1;
|
|
} else if (strcmp(arg[iarg],"vz") == 0) {
|
|
which[nvalues] = ArgInfo::V;
|
|
argindex[nvalues] = 2;
|
|
modeatom = 1;
|
|
|
|
} else if (strcmp(arg[iarg],"fx") == 0) {
|
|
which[nvalues] = ArgInfo::F;
|
|
argindex[nvalues] = 0;
|
|
modeatom = 1;
|
|
} else if (strcmp(arg[iarg],"fy") == 0) {
|
|
which[nvalues] = ArgInfo::F;
|
|
argindex[nvalues] = 1;
|
|
modeatom = 1;
|
|
} else if (strcmp(arg[iarg],"fz") == 0) {
|
|
which[nvalues] = ArgInfo::F;
|
|
argindex[nvalues] = 2;
|
|
modeatom = 1;
|
|
|
|
} else if (strcmp(arg[iarg],"density/number") == 0) {
|
|
which[nvalues] = ArgInfo::DENSITY_NUMBER;
|
|
argindex[nvalues] = 0;
|
|
modeatom = 1;
|
|
} else if (strcmp(arg[iarg],"density/mass") == 0) {
|
|
which[nvalues] = ArgInfo::DENSITY_MASS;
|
|
argindex[nvalues] = 0;
|
|
modeatom = 1;
|
|
} else if (strcmp(arg[iarg],"mass") == 0) {
|
|
which[nvalues] = ArgInfo::MASS;
|
|
argindex[nvalues] = 0;
|
|
modeatom = 1;
|
|
} else if (strcmp(arg[iarg],"temp") == 0) {
|
|
which[nvalues] = ArgInfo::TEMPERATURE;
|
|
argindex[nvalues] = 0;
|
|
modeatom = 1;
|
|
|
|
} else {
|
|
|
|
// if arg is not a per-atom or per-grid value
|
|
// then it's an optional arg after the values
|
|
|
|
ArgInfo argi(arg[iarg]);
|
|
if (argi.get_type() == ArgInfo::NONE || argi.get_type() == ArgInfo::UNKNOWN) break;
|
|
if (argi.get_dim() > 1) error->all(FLERR,"Invalid fix ave/grid command");
|
|
|
|
// atom value has no colon
|
|
|
|
if (!strchr(arg[iarg],':')) {
|
|
modeatom = 1;
|
|
ids[nvalues] = argi.copy_name();
|
|
which[nvalues] = argi.get_type();
|
|
argindex[nvalues] = argi.get_index1();
|
|
|
|
// per-grid value has colons
|
|
|
|
} else {
|
|
modegrid = 1;
|
|
|
|
int igrid,idata,index;
|
|
int iflag =
|
|
utils::check_grid_reference((char *) "Fix ave/grid",
|
|
arg[iarg],nevery,ids[nvalues],igrid,idata,index,lmp);
|
|
if (iflag < 0) error->all(FLERR,"Invalid grid reference in fix ave/grid command");
|
|
|
|
which[nvalues] = iflag;
|
|
value2grid[nvalues] = igrid;
|
|
value2data[nvalues] = idata;
|
|
argindex[nvalues] = index;
|
|
}
|
|
}
|
|
|
|
nvalues++;
|
|
iarg++;
|
|
}
|
|
|
|
if (nvalues == 0) error->all(FLERR,"No values in fix ave/grid command");
|
|
|
|
if (modeatom && modegrid)
|
|
error->all(FLERR,"Fix ave/grid cannot operate on per-atom and "
|
|
"per-grid values");
|
|
|
|
// optional args
|
|
|
|
discardflag = DISCARD;
|
|
normflag = ALL;
|
|
aveflag = ONE;
|
|
nwindow = 0;
|
|
biasflag = 0;
|
|
id_bias = nullptr;
|
|
adof = domain->dimension;
|
|
cdof = 0.0;
|
|
|
|
while (iarg < nargnew) {
|
|
if (strcmp(arg[iarg],"discard") == 0) {
|
|
if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/grid command");
|
|
if (strcmp(arg[iarg+1],"yes") == 0) discardflag = DISCARD;
|
|
else if (strcmp(arg[iarg+1],"no") == 0) discardflag = KEEP;
|
|
else error->all(FLERR,"Illegal fix ave/grid command");
|
|
iarg += 2;
|
|
|
|
} else if (strcmp(arg[iarg],"norm") == 0) {
|
|
if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/grid command");
|
|
if (strcmp(arg[iarg+1],"all") == 0) normflag = ALL;
|
|
else if (strcmp(arg[iarg+1],"sample") == 0) normflag = SAMPLE;
|
|
else if (strcmp(arg[iarg+1],"none") == 0) normflag = NONORM;
|
|
else error->all(FLERR,"Illegal fix ave/grid command");
|
|
iarg += 2;
|
|
|
|
} else if (strcmp(arg[iarg],"ave") == 0) {
|
|
if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/grid command");
|
|
if (strcmp(arg[iarg+1],"one") == 0) aveflag = ONE;
|
|
else if (strcmp(arg[iarg+1],"running") == 0) aveflag = RUNNING;
|
|
else if (strcmp(arg[iarg+1],"window") == 0) aveflag = WINDOW;
|
|
else error->all(FLERR,"Illegal fix ave/grid command");
|
|
if (aveflag == WINDOW) {
|
|
if (iarg+3 > narg) error->all(FLERR,"Illegal fix ave/grid command");
|
|
nwindow = utils::inumeric(FLERR,arg[iarg+2],false,lmp);
|
|
if (nwindow <= 0) error->all(FLERR,"Illegal fix ave/grid command");
|
|
iarg++;
|
|
}
|
|
iarg += 2;
|
|
|
|
} else if (strcmp(arg[iarg],"bias") == 0) {
|
|
if (iarg+2 > narg)
|
|
error->all(FLERR,"Illegal fix ave/grid command");
|
|
biasflag = 1;
|
|
id_bias = utils::strdup(arg[iarg+1]);
|
|
iarg += 2;
|
|
|
|
} else if (strcmp(arg[iarg],"adof") == 0) {
|
|
if (iarg+2 > narg)
|
|
error->all(FLERR,"Illegal fix ave/grid command");
|
|
adof = utils::numeric(FLERR,arg[iarg+1],false,lmp);
|
|
iarg += 2;
|
|
} else if (strcmp(arg[iarg],"cdof") == 0) {
|
|
if (iarg+2 > narg)
|
|
error->all(FLERR,"Illegal fix ave/grid command");
|
|
cdof = utils::numeric(FLERR,arg[iarg+1],false,lmp);
|
|
iarg += 2;
|
|
|
|
} else error->all(FLERR,"Illegal fix ave/grid command");
|
|
}
|
|
|
|
// if wildcard expansion occurred, free earg memory from exapnd_args()
|
|
|
|
if (expand) {
|
|
for (int i = 0; i < nvalues; i++) delete[] earg[i];
|
|
memory->sfree(earg);
|
|
}
|
|
|
|
// more error checks
|
|
// for fix inputs, check that fix frequency is acceptable
|
|
|
|
dimension = domain->dimension;
|
|
|
|
if ((nxgrid < 1) || (nygrid < 1) || (nzgrid < 1))
|
|
error->all(FLERR,"Invalid fix ave/grid grid size");
|
|
if (dimension == 2 && nzgrid != 1)
|
|
error->all(FLERR,"Fix ave/grid grid Nz must be 1 for 2d simulation");
|
|
|
|
if (biasflag) {
|
|
tbias = modify->get_compute_by_id(id_bias);
|
|
if (!tbias)
|
|
error->all(FLERR,"Could not find compute ID for temperature bias");
|
|
if (tbias->tempflag == 0)
|
|
error->all(FLERR,"Bias compute does not calculate temperature");
|
|
if (tbias->tempbias == 0)
|
|
error->all(FLERR,"Bias compute does not calculate a velocity bias");
|
|
}
|
|
|
|
// error checks for ATOM mode
|
|
|
|
if (modeatom) {
|
|
for (int i = 0; i < nvalues; i++) {
|
|
if (which[i] == ArgInfo::COMPUTE) {
|
|
auto icompute = modify->get_compute_by_id(ids[i]);
|
|
if (!icompute)
|
|
error->all(FLERR,"Compute {} for fix ave/grid does not exist", ids[i]);
|
|
if (icompute->peratom_flag == 0)
|
|
error->all(FLERR, "Fix ave/atom compute {} does not calculate per-atom values", ids[i]);
|
|
if ((argindex[i] == 0) && (icompute->size_peratom_cols != 0))
|
|
error->all(FLERR,"Fix ave/atom compute {} does not calculate a per-atom vector", ids[i]);
|
|
if (argindex[i] && (icompute->size_peratom_cols == 0))
|
|
error->all(FLERR,"Fix ave/atom compute {} does not calculate a per-atom array", ids[i]);
|
|
if (argindex[i] && (argindex[i] > icompute->size_peratom_cols))
|
|
error->all(FLERR,"Fix ave/atom compute {} array is accessed out-of-range", ids[i]);
|
|
|
|
} else if (which[i] == ArgInfo::FIX) {
|
|
auto ifix = modify->get_fix_by_id(ids[i]);
|
|
if (!ifix)
|
|
error->all(FLERR,"Fix {} for fix ave/atom does not exist", ids[i]);
|
|
if (ifix->peratom_flag == 0)
|
|
error->all(FLERR,"Fix ave/atom fix {} does not calculate per-atom values", ids[i]);
|
|
if ((argindex[i] == 0) && (ifix->size_peratom_cols != 0))
|
|
error->all(FLERR, "Fix ave/atom fix {} does not calculate a per-atom vector", ids[i]);
|
|
if (argindex[i] && (ifix->size_peratom_cols == 0))
|
|
error->all(FLERR, "Fix ave/atom fix {} does not calculate a per-atom array", ids[i]);
|
|
if (argindex[i] && (argindex[i] > ifix->size_peratom_cols))
|
|
error->all(FLERR,"Fix ave/atom fix {} array is accessed out-of-range", ids[i]);
|
|
if (nevery % ifix->peratom_freq)
|
|
error->all(FLERR, "Fix {} for fix ave/atom not computed at compatible time", ids[i]);
|
|
|
|
} else if (which[i] == ArgInfo::VARIABLE) {
|
|
int ivariable = input->variable->find(ids[i]);
|
|
if (ivariable < 0)
|
|
error->all(FLERR,"Variable name for fix ave/atom does not exist");
|
|
if (input->variable->atomstyle(ivariable) == 0)
|
|
error->all(FLERR,"Fix ave/atom variable is not atom-style variable");
|
|
}
|
|
}
|
|
}
|
|
|
|
// instantiate Grid class and buffers
|
|
// allocate/zero per-grid data
|
|
|
|
allocate_grid();
|
|
|
|
grid_sample = allocate_one_grid();
|
|
grid_nfreq = allocate_one_grid();
|
|
if (aveflag == RUNNING || aveflag == WINDOW) grid_running = allocate_one_grid();
|
|
if (aveflag == WINDOW) {
|
|
grid_window = new GridData*[nwindow];
|
|
for (int i = 0; i < nwindow; i++)
|
|
grid_window[i] = allocate_one_grid();
|
|
}
|
|
|
|
// output may occur via dump on timestep 0
|
|
|
|
grid_output = new GridData();
|
|
output_grid(grid_nfreq);
|
|
|
|
// initialize running and window values
|
|
|
|
running_count = 0;
|
|
window_count = 0;
|
|
window_oldest = -1;
|
|
window_newest = 0;
|
|
|
|
// bin indices and skip flags for ATOM mode
|
|
// vresult for per-atom variable evaluation
|
|
|
|
maxatom = 0;
|
|
bin = nullptr;
|
|
skip = nullptr;
|
|
|
|
maxvar = 0;
|
|
vresult = nullptr;
|
|
|
|
// nvalid = next step on which end_of_step does something
|
|
// add nvalid to all computes that store invocation times
|
|
// since don't know a priori which are invoked by this fix
|
|
// once in end_of_step() can set timestep for ones actually invoked
|
|
|
|
irepeat = 0;
|
|
nvalid_last = -1;
|
|
nvalid = nextvalid();
|
|
modify->addstep_compute_all(nvalid);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
FixAveGrid::~FixAveGrid()
|
|
{
|
|
delete[] which;
|
|
delete[] argindex;
|
|
for (int m = 0; m < nvalues; m++) delete[] ids[m];
|
|
delete[] ids;
|
|
delete[] value2index;
|
|
delete[] value2grid;
|
|
delete[] value2data;
|
|
|
|
// deallocate Grid class and buffers
|
|
|
|
if (dimension == 2) delete grid2d;
|
|
else delete grid3d;
|
|
|
|
memory->destroy(grid_buf1);
|
|
memory->destroy(grid_buf2);
|
|
|
|
// deallocate per-grid data
|
|
|
|
deallocate_one_grid(grid_sample,nxlo_out,nylo_out,nzlo_out);
|
|
deallocate_one_grid(grid_nfreq,nxlo_out,nylo_out,nzlo_out);
|
|
if (aveflag == RUNNING || aveflag == WINDOW)
|
|
deallocate_one_grid(grid_running,nxlo_out,nylo_out,nzlo_out);
|
|
if (aveflag == WINDOW) {
|
|
for (int i = 0; i < nwindow; i++)
|
|
deallocate_one_grid(grid_window[i],nxlo_out,nylo_out,nzlo_out);
|
|
delete [] grid_window;
|
|
}
|
|
|
|
delete grid_output;
|
|
|
|
if (modeatom) {
|
|
memory->destroy(bin);
|
|
memory->destroy(skip);
|
|
memory->destroy(vresult);
|
|
}
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
int FixAveGrid::setmask()
|
|
{
|
|
int mask = 0;
|
|
mask |= END_OF_STEP;
|
|
return mask;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::init()
|
|
{
|
|
if (biasflag) {
|
|
tbias = modify->get_compute_by_id(id_bias);
|
|
if (!tbias)
|
|
error->all(FLERR,"Could not find compute ID for temperature bias");
|
|
}
|
|
|
|
// set indices and check validity of all computes,fixes,variables
|
|
|
|
for (int m = 0; m < nvalues; m++) {
|
|
if (which[m] == ArgInfo::COMPUTE) {
|
|
int icompute = modify->find_compute(ids[m]);
|
|
if (icompute < 0)
|
|
error->all(FLERR,"Compute {} for fix ave/grid does not exist", ids[m]);
|
|
value2index[m] = icompute;
|
|
|
|
} else if (which[m] == ArgInfo::FIX) {
|
|
int ifix = modify->find_fix(ids[m]);
|
|
if (ifix < 0)
|
|
error->all(FLERR,"Fix {} for fix ave/grid does not exist", ids[m]);
|
|
value2index[m] = ifix;
|
|
|
|
} else if (which[m] == ArgInfo::VARIABLE) {
|
|
int ivariable = input->variable->find(ids[m]);
|
|
if (ivariable < 0)
|
|
error->all(FLERR,"Variable name for fix ave/grid does not exist");
|
|
value2index[m] = ivariable;
|
|
|
|
} else value2index[m] = -1;
|
|
}
|
|
|
|
// check that grid sizes for all fields match grid size for this fix
|
|
|
|
if (modegrid) {
|
|
Compute *compute = nullptr;
|
|
Fix *fix = nullptr;
|
|
Grid2d *grid2d = nullptr;
|
|
Grid3d *grid3d = nullptr;
|
|
|
|
int nxtmp,nytmp,nztmp;
|
|
|
|
for (int m = 0; m < nvalues; m++) {
|
|
if (dimension == 2) {
|
|
if (which[m] == ArgInfo::COMPUTE) {
|
|
compute = modify->get_compute_by_index(value2index[m]);
|
|
grid2d = (Grid2d *) compute->get_grid_by_index(value2grid[m]);
|
|
} else {
|
|
fix = modify->get_fix_by_index(value2index[m]);
|
|
grid2d = (Grid2d *) fix->get_grid_by_index(value2grid[m]);
|
|
}
|
|
grid2d->get_size(nxtmp,nytmp);
|
|
if (nxtmp != nxgrid || nytmp != nygrid)
|
|
error->all(FLERR,"Fix ave/grid value grid sizes do not match");
|
|
|
|
} else {
|
|
if (which[m] == ArgInfo::COMPUTE) {
|
|
compute = modify->get_compute_by_index(value2index[m]);
|
|
grid3d = (Grid3d *) compute->get_grid_by_index(value2grid[m]);
|
|
} else {
|
|
fix = modify->get_fix_by_index(value2index[m]);
|
|
grid3d = (Grid3d *) fix->get_grid_by_index(value2grid[m]);
|
|
}
|
|
grid3d->get_size(nxtmp,nytmp,nztmp);
|
|
if (nxtmp != nxgrid || nytmp != nygrid || nztmp != nzgrid)
|
|
error->all(FLERR,"Fix ave/grid value grid sizes do not match");
|
|
}
|
|
}
|
|
}
|
|
|
|
// set triclinic flag
|
|
|
|
triclinic = domain->triclinic;
|
|
|
|
// need to reset nvalid if nvalid < ntimestep b/c minimize was performed
|
|
|
|
if (nvalid < update->ntimestep) {
|
|
irepeat = 0;
|
|
nvalid = nextvalid();
|
|
modify->addstep_compute_all(nvalid);
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
only does something if nvalid = current timestep
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::setup(int /*vflag*/)
|
|
{
|
|
end_of_step();
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::end_of_step()
|
|
{
|
|
// skip if not step which requires doing something
|
|
|
|
bigint ntimestep = update->ntimestep;
|
|
if (ntimestep != nvalid) return;
|
|
nvalid_last = nvalid;
|
|
|
|
// if first sample in nfreq, zero owned and ghost grid points
|
|
|
|
if (irepeat == 0) {
|
|
zero_grid(grid_sample);
|
|
if (normflag == SAMPLE) zero_grid(grid_nfreq);
|
|
}
|
|
|
|
// accumulate per-grid values for one sample for either ATOM or GRID mode
|
|
// per-atom compute/fix/variable may invoke computes so wrap with clear/add
|
|
|
|
if (modeatom) {
|
|
modify->clearstep_compute();
|
|
atom2grid();
|
|
} else {
|
|
grid2grid();
|
|
}
|
|
|
|
// return if irepeat < nrepeat
|
|
// unless ATOM mode and norm = SAMPLE
|
|
|
|
irepeat++;
|
|
if (irepeat < nrepeat && (modegrid || normflag != SAMPLE)) {
|
|
nvalid += nevery;
|
|
if (modeatom) modify->addstep_compute(nvalid);
|
|
return;
|
|
}
|
|
|
|
// for ATOM mode, perform ghost to owned grid communication
|
|
// done once per Nfreq for norm = ONE
|
|
// done every sample for norm = SAMPLE
|
|
// nvalues+1 includes atom count
|
|
|
|
if (modeatom) {
|
|
if (dimension == 2)
|
|
grid2d->reverse_comm(Grid2d::FIX,this,0,nvalues+1,sizeof(double),
|
|
grid_buf1,grid_buf2,MPI_DOUBLE);
|
|
else
|
|
grid3d->reverse_comm(Grid3d::FIX,this,0,nvalues+1,sizeof(double),
|
|
grid_buf1,grid_buf2,MPI_DOUBLE);
|
|
}
|
|
|
|
// if ATOM mode and norm = SAMPLE:
|
|
// normalize the single sample
|
|
// sum sample grid to Nfreq grid
|
|
// return if irepeat < nrepeat
|
|
|
|
if (modeatom && normflag == SAMPLE) {
|
|
normalize_atom(1,grid_sample);
|
|
add_grid(grid_sample,grid_nfreq);
|
|
zero_grid(grid_sample);
|
|
|
|
if (irepeat < nrepeat) {
|
|
nvalid += nevery;
|
|
modify->addstep_compute(nvalid);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// this is an Nfreq timestep
|
|
// reset irepeat and nvalid
|
|
|
|
irepeat = 0;
|
|
nvalid = ntimestep+pergrid_freq - ((bigint) nrepeat-1)*nevery;
|
|
if (modeatom) modify->addstep_compute(nvalid);
|
|
|
|
// just return if this proc owns no grid points
|
|
|
|
if (ngridout == 0) return;
|
|
|
|
// average final results over the entire Nfreq of samples
|
|
// store final result in Nfreq grid
|
|
// for ATOM mode:
|
|
// for norm = ALL, normalize sample grid by counts over all samples
|
|
// for norm = SAMPLE, normalize Nfreq grid by Nrepeat
|
|
// for norm = NONORM, normalize sample grid by Nrepeat, not by counts
|
|
// this check is made inside normalize_atom()
|
|
// for GRID mode:
|
|
// normalize sample grid by Nrepeat
|
|
|
|
if (modeatom) {
|
|
if (normflag == ALL) {
|
|
normalize_atom(nrepeat,grid_sample);
|
|
normalize_count(nrepeat,grid_sample);
|
|
copy_grid(grid_sample,grid_nfreq);
|
|
|
|
} else if (normflag == SAMPLE) {
|
|
normalize_grid(nrepeat,grid_nfreq);
|
|
normalize_count(nrepeat,grid_nfreq);
|
|
|
|
} else if (normflag == NONORM) {
|
|
normalize_atom(nrepeat,grid_sample);
|
|
normalize_count(nrepeat,grid_sample);
|
|
copy_grid(grid_sample,grid_nfreq);
|
|
}
|
|
}
|
|
|
|
if (modegrid) {
|
|
normalize_grid(nrepeat,grid_sample);
|
|
copy_grid(grid_sample,grid_nfreq);
|
|
}
|
|
|
|
// create Nfreq output
|
|
// for aveflag == RUNNING
|
|
// running_count = # of Nfreq entries in grid_running
|
|
// for aveflag == WINDOW
|
|
// window_count = # of Nfreq entries in grid_window
|
|
|
|
if (aveflag == ONE) {
|
|
output_grid(grid_nfreq);
|
|
|
|
} else if (aveflag == RUNNING) {
|
|
running_count++;
|
|
add_grid(grid_nfreq,grid_running);
|
|
copy_grid(grid_running,grid_nfreq);
|
|
normalize_grid(running_count,grid_nfreq);
|
|
if (modeatom) normalize_count(running_count,grid_nfreq);
|
|
output_grid(grid_nfreq);
|
|
|
|
} else if (aveflag == WINDOW) {
|
|
|
|
// update grid_running to be sum over grid_window entries
|
|
// add grid_nfreq to grid_running
|
|
// if window is full, subtract oldest window entry from grid_running
|
|
// copy grid_nfreq into window
|
|
|
|
add_grid(grid_nfreq,grid_running);
|
|
if (window_count == nwindow)
|
|
subtract_grid(grid_window[window_oldest],grid_running);
|
|
copy_grid(grid_nfreq,grid_window[window_newest]);
|
|
|
|
// update status of window
|
|
// window_count = # of entries in window
|
|
// window_oldest = index of oldest entry in grid_window
|
|
// window_newest = index in window where next grid_nfreq will be copied
|
|
|
|
if (window_count < nwindow) window_count++;
|
|
if (window_count == nwindow) window_oldest++;
|
|
if (window_oldest == nwindow) window_oldest = 0;
|
|
window_newest++;
|
|
if (window_newest == nwindow) window_newest = 0;
|
|
|
|
// copy grid running to grid_nfreq and perform normalization
|
|
|
|
copy_grid(grid_running,grid_nfreq);
|
|
normalize_grid(window_count,grid_nfreq);
|
|
output_grid(grid_nfreq);
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
sum per-atom contributions to owned+ghost grid cells
|
|
sets one of vec2d,array2d,vec3d,array3d sample
|
|
also set count2d or count3d for atom count per bin
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::atom2grid()
|
|
{
|
|
int i,j,m,n,ix,iy,iz;
|
|
|
|
double **count2d = grid_sample->count2d;
|
|
double **vec2d = grid_sample->vec2d;
|
|
double ***array2d = grid_sample->array2d;
|
|
double ***count3d = grid_sample->count3d;
|
|
double ***vec3d = grid_sample->vec3d;
|
|
double ****array3d = grid_sample->array3d;
|
|
|
|
// scan my owned atoms before tallying to bins
|
|
// bin[i][dim] = indices of bin each atom is in
|
|
// count[][] or count[][][] = count of atoms contributing to each bin
|
|
// error check if any atom is out of bounds for my local+ghost grid cells
|
|
// skip atom if group mask does not match
|
|
// skip atom if out of bounds for a nonperiodic dim and discardflag = DISCARD
|
|
// if out of bounds for a nonperiodic dim and discardflag = KEEP, remap atom to first/last bin
|
|
|
|
double *boxlo,*prd;
|
|
int *periodicity = domain->periodicity;
|
|
|
|
if (triclinic) {
|
|
boxlo = domain->boxlo_lamda;
|
|
prd = domain->prd_lamda;
|
|
} else {
|
|
boxlo = domain->boxlo;
|
|
prd = domain->prd;
|
|
}
|
|
|
|
double dxinv = nxgrid/prd[0];
|
|
double dyinv = nygrid/prd[1];
|
|
double dzinv = nzgrid/prd[2];
|
|
|
|
double **x = atom->x;
|
|
int *mask = atom->mask;
|
|
int nlocal = atom->nlocal;
|
|
|
|
if (nlocal > maxatom) {
|
|
memory->destroy(bin);
|
|
memory->destroy(skip);
|
|
maxatom = atom->nmax;
|
|
memory->create(bin,maxatom,dimension,"ave/grid:bin");
|
|
memory->create(skip,maxatom,"ave/grid:skip");
|
|
}
|
|
|
|
if (triclinic) domain->x2lamda(nlocal);
|
|
|
|
// set to 1
|
|
int flag = 0;
|
|
|
|
if (dimension == 2) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!(mask[i] & groupbit)) {
|
|
skip[i] = 1;
|
|
continue;
|
|
}
|
|
|
|
ix = static_cast<int> ((x[i][0]-boxlo[0])*dxinv + OFFSET) - OFFSET;
|
|
iy = static_cast<int> ((x[i][1]-boxlo[1])*dyinv + OFFSET) - OFFSET;
|
|
|
|
if (ix < nxlo_out || ix > nxhi_out) {
|
|
if (periodicity[0]) {
|
|
flag = 1;
|
|
continue;
|
|
} else if (discardflag == KEEP) {
|
|
if (ix < nxlo_out && nxlo_out == 0) ix = 0;
|
|
else if (ix > nxhi_out && nxhi_out == nxgrid-1) ix = nxgrid-1;
|
|
else {
|
|
flag = 1;
|
|
continue;
|
|
}
|
|
} else {
|
|
skip[i] = 1;
|
|
continue;
|
|
}
|
|
}
|
|
if (iy < nylo_out || iy > nyhi_out) {
|
|
if (periodicity[1]) {
|
|
flag = 1;
|
|
continue;
|
|
} else if (discardflag == KEEP) {
|
|
if (iy < nylo_out && nylo_out == 0) iy = 0;
|
|
else if (iy > nyhi_out && nyhi_out == nygrid-1) iy = nygrid-1;
|
|
else {
|
|
flag = 1;
|
|
continue;
|
|
}
|
|
} else {
|
|
skip[i] = 1;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
skip[i] = 0;
|
|
count2d[iy][ix] += 1.0;
|
|
bin[i][0] = iy;
|
|
bin[i][1] = ix;
|
|
}
|
|
|
|
} else {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!(mask[i] & groupbit)) {
|
|
skip[i] = 1;
|
|
continue;
|
|
}
|
|
|
|
ix = static_cast<int> ((x[i][0]-boxlo[0])*dxinv + OFFSET) - OFFSET;
|
|
iy = static_cast<int> ((x[i][1]-boxlo[1])*dyinv + OFFSET) - OFFSET;
|
|
iz = static_cast<int> ((x[i][2]-boxlo[2])*dzinv + OFFSET) - OFFSET;
|
|
|
|
if (ix < nxlo_out || ix > nxhi_out) {
|
|
if (periodicity[0]) {
|
|
flag = 1;
|
|
continue;
|
|
} else if (discardflag == KEEP) {
|
|
if (ix < nxlo_out && nxlo_out == 0) ix = 0;
|
|
else if (ix > nxhi_out && nxhi_out == nxgrid-1) ix = nxgrid-1;
|
|
else {
|
|
flag = 1;
|
|
continue;
|
|
}
|
|
} else {
|
|
skip[i] = 1;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (iy < nylo_out || iy > nyhi_out) {
|
|
if (periodicity[1]) {
|
|
flag = 1;
|
|
continue;
|
|
} else if (discardflag == KEEP) {
|
|
if (iy < nylo_out && nylo_out == 0) iy = 0;
|
|
else if (iy > nyhi_out && nyhi_out == nygrid-1) iy = nygrid-1;
|
|
else {
|
|
flag = 1;
|
|
continue;
|
|
}
|
|
} else {
|
|
skip[i] = 1;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (iz < nzlo_out || iz > nzhi_out) {
|
|
if (periodicity[2]) {
|
|
flag = 1;
|
|
continue;
|
|
} else if (discardflag == KEEP) {
|
|
if (iz < nzlo_out && nzlo_out == 0) iz = 0;
|
|
else if (iz > nzhi_out && nzhi_out == nzgrid-1) iz = nzgrid-1;
|
|
else {
|
|
flag = 1;
|
|
continue;
|
|
}
|
|
} else {
|
|
skip[i] = 1;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
skip[i] = 0;
|
|
count3d[iz][iy][ix] += 1.0;
|
|
bin[i][0] = iz;
|
|
bin[i][1] = iy;
|
|
bin[i][2] = ix;
|
|
}
|
|
}
|
|
|
|
if (flag) error->one(FLERR,"Out of range fix ave/grid atoms");
|
|
|
|
if (triclinic) domain->lamda2x(nlocal);
|
|
|
|
// loop over user-specified values
|
|
|
|
for (m = 0; m < nvalues; m++) {
|
|
n = value2index[m];
|
|
j = argindex[m];
|
|
|
|
// V,F adds velocity,force to value
|
|
|
|
if (which[m] == ArgInfo::V || which[m] == ArgInfo::F) {
|
|
|
|
double **attribute;
|
|
if (which[m] == ArgInfo::V) attribute = atom->v;
|
|
else if (which[m] == ArgInfo::F) attribute = atom->f;
|
|
|
|
if (dimension == 2) {
|
|
if (nvalues == 1) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
vec2d[bin[i][0]][bin[i][1]] += attribute[i][j];
|
|
}
|
|
} else
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
array2d[bin[i][0]][bin[i][1]][m] += attribute[i][j];
|
|
}
|
|
} else {
|
|
if (nvalues == 1) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
vec3d[bin[i][0]][bin[i][1]][bin[i][2]] += attribute[i][j];
|
|
}
|
|
} else
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
array3d[bin[i][0]][bin[i][1]][bin[i][2]][m] += attribute[i][j];
|
|
}
|
|
}
|
|
|
|
// DENSITY_NUMBER adds 1 to value
|
|
// DENSITY_MASS or MASS adds mass to value
|
|
|
|
} else if ((which[m] == ArgInfo::DENSITY_NUMBER) ||
|
|
(which[m] == ArgInfo::DENSITY_MASS) ||
|
|
(which[m] == ArgInfo::MASS)) {
|
|
|
|
int *type = atom->type;
|
|
double *mass = atom->mass;
|
|
double *rmass = atom->rmass;
|
|
double one;
|
|
|
|
if (dimension == 2) {
|
|
if (nvalues == 1) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i]) {
|
|
if (which[m] == ArgInfo::DENSITY_NUMBER) one = 1.0;
|
|
else if (rmass) one = rmass[i];
|
|
else one = mass[type[i]];
|
|
vec2d[bin[i][0]][bin[i][1]] += one;
|
|
}
|
|
}
|
|
} else
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i]) {
|
|
if (which[m] == ArgInfo::DENSITY_NUMBER) one = 1.0;
|
|
else if (rmass) one = rmass[i];
|
|
else one = mass[type[i]];
|
|
array2d[bin[i][0]][bin[i][1]][m] += one;
|
|
}
|
|
}
|
|
} else {
|
|
if (nvalues == 1) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i]) {
|
|
if (which[m] == ArgInfo::DENSITY_NUMBER) one = 1.0;
|
|
else if (rmass) one = rmass[i];
|
|
else one = mass[type[i]];
|
|
vec3d[bin[i][0]][bin[i][1]][bin[i][2]] += one;
|
|
}
|
|
}
|
|
} else
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i]) {
|
|
if (which[m] == ArgInfo::DENSITY_NUMBER) one = 1.0;
|
|
else if (rmass) one = rmass[i];
|
|
else one = mass[type[i]];
|
|
array3d[bin[i][0]][bin[i][1]][bin[i][2]][m] += one;
|
|
}
|
|
}
|
|
}
|
|
|
|
// TEMPERATURE adds KE to values
|
|
// subtract and restore velocity bias if requested
|
|
|
|
} else if (which[m] == ArgInfo::TEMPERATURE) {
|
|
|
|
if (biasflag) {
|
|
if (tbias->invoked_scalar != update->ntimestep) tbias->compute_scalar();
|
|
tbias->remove_bias_all();
|
|
}
|
|
|
|
double **v = atom->v;
|
|
int *type = atom->type;
|
|
double *mass = atom->mass;
|
|
double *rmass = atom->rmass;
|
|
double vsq,one;
|
|
|
|
if (dimension == 2) {
|
|
if (nvalues == 1) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i]) {
|
|
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
|
|
if (rmass) one = rmass[i];
|
|
else one = mass[type[i]];
|
|
vec2d[bin[i][0]][bin[i][1]] += one*vsq;
|
|
}
|
|
}
|
|
} else
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i]) {
|
|
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
|
|
if (rmass) one = rmass[i];
|
|
else one = mass[type[i]];
|
|
array2d[bin[i][0]][bin[i][1]][m] += one*vsq;
|
|
}
|
|
}
|
|
} else {
|
|
if (nvalues == 1) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i]) {
|
|
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
|
|
if (rmass) one = rmass[i];
|
|
else one = mass[type[i]];
|
|
vec3d[bin[i][0]][bin[i][1]][bin[i][2]] += one*vsq;
|
|
}
|
|
}
|
|
} else
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i]) {
|
|
vsq = v[i][0]*v[i][0] + v[i][1]*v[i][1] + v[i][2]*v[i][2];
|
|
if (rmass) one = rmass[i];
|
|
else one = mass[type[i]];
|
|
array3d[bin[i][0]][bin[i][1]][bin[i][2]][m] += one*vsq;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (biasflag) tbias->restore_bias_all();
|
|
|
|
// per-atom compute or fix or variable
|
|
// invoke compute if not previously invoked
|
|
// evaluate atom-style variable
|
|
|
|
} else if (which[m] == ArgInfo::COMPUTE || which[m] == ArgInfo::FIX ||
|
|
which[m] == ArgInfo::VARIABLE) {
|
|
double *ovector,**oarray;
|
|
|
|
if (which[m] == ArgInfo::COMPUTE) {
|
|
Compute *compute = modify->get_compute_by_index(n);
|
|
if (!(compute->invoked_flag & Compute::INVOKED_PERATOM)) {
|
|
compute->compute_peratom();
|
|
compute->invoked_flag |= Compute::INVOKED_PERATOM;
|
|
}
|
|
if (j == 0) ovector = compute->vector_atom;
|
|
else oarray = compute->array_atom;
|
|
|
|
} else if (which[m] == ArgInfo::FIX) {
|
|
Fix *fix = modify->get_fix_by_index(n);
|
|
if (j == 0) ovector = fix->vector_atom;
|
|
else oarray = fix->array_atom;
|
|
} else if (which[m] == ArgInfo::VARIABLE) {
|
|
if (nlocal > maxvar) {
|
|
memory->destroy(vresult);
|
|
maxvar = atom->nmax;
|
|
memory->create(vresult,maxvar,"ave/grid:vresult");
|
|
}
|
|
input->variable->compute_atom(n,igroup,vresult,1,0);
|
|
ovector = vresult;
|
|
}
|
|
|
|
if (dimension == 2) {
|
|
if (nvalues == 1) {
|
|
if (j == 0) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
vec2d[bin[i][0]][bin[i][1]] += ovector[i];
|
|
}
|
|
} else {
|
|
int jm1 = j = 1;
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
vec2d[bin[i][0]][bin[i][1]] += oarray[i][jm1];
|
|
}
|
|
}
|
|
} else {
|
|
if (j == 0) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
array2d[bin[i][0]][bin[i][1]][m] += ovector[i];
|
|
}
|
|
} else {
|
|
int jm1 = j - 1;
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
array2d[bin[i][0]][bin[i][1]][m] += oarray[i][jm1];
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
if (nvalues == 1) {
|
|
if (j == 0) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
vec3d[bin[i][0]][bin[i][1]][bin[i][2]] += ovector[i];
|
|
}
|
|
} else {
|
|
int jm1 = j - 1;
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
vec3d[bin[i][0]][bin[i][1]][bin[i][2]] += oarray[i][jm1];
|
|
}
|
|
}
|
|
} else {
|
|
if (j == 0) {
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
array3d[bin[i][0]][bin[i][1]][bin[i][2]][m] += ovector[i];
|
|
}
|
|
} else {
|
|
int jm1 = j - 1;
|
|
for (i = 0; i < nlocal; i++) {
|
|
if (!skip[i])
|
|
array3d[bin[i][0]][bin[i][1]][bin[i][2]][m] += oarray[i][jm1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
copy per-grid values from other computes/fixes to owned grid cells
|
|
sets one of vec2d,array2d,vec3d,array3d
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::grid2grid()
|
|
{
|
|
int j,m,n,ix,iy,iz;
|
|
|
|
double **vec2d = grid_sample->vec2d;
|
|
double ***array2d = grid_sample->array2d;
|
|
double ***vec3d = grid_sample->vec3d;
|
|
double ****array3d = grid_sample->array3d;
|
|
|
|
// loop over user-specified values
|
|
|
|
for (m = 0; m < nvalues; m++) {
|
|
n = value2index[m];
|
|
j = argindex[m];
|
|
int idata = value2data[m];
|
|
|
|
Compute *compute;
|
|
Fix *fix;
|
|
|
|
if (which[m] == ArgInfo::COMPUTE) {
|
|
compute = modify->get_compute_by_index(n);
|
|
if (!(compute->invoked_flag & Compute::INVOKED_PERGRID)) {
|
|
compute->compute_pergrid();
|
|
compute->invoked_flag |= Compute::INVOKED_PERGRID;
|
|
}
|
|
} else if (which[m] == ArgInfo::FIX) fix = modify->get_fix_by_index(n);
|
|
|
|
if (dimension == 2) {
|
|
double **ovec2d,***oarray2d;
|
|
if (which[m] == ArgInfo::COMPUTE) {
|
|
if (j == 0)
|
|
ovec2d = (double **) compute->get_griddata_by_index(idata);
|
|
else
|
|
oarray2d = (double ***) compute->get_griddata_by_index(idata);
|
|
} else {
|
|
if (j == 0)
|
|
ovec2d = (double **) fix->get_griddata_by_index(idata);
|
|
else
|
|
oarray2d = (double ***) fix->get_griddata_by_index(idata);
|
|
}
|
|
|
|
if (nvalues == 1) {
|
|
if (j == 0) {
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vec2d[iy][ix] += ovec2d[iy][ix];
|
|
} else {
|
|
int jm1 = j - 1;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vec2d[iy][ix] += oarray2d[iy][ix][jm1];
|
|
}
|
|
} else {
|
|
if (j == 0) {
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
array2d[iy][ix][m] += ovec2d[iy][ix];
|
|
} else {
|
|
int jm1 = j - 1;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
array2d[iy][ix][m] += oarray2d[iy][ix][jm1];
|
|
}
|
|
}
|
|
|
|
} else {
|
|
double ***ovec3d,****oarray3d;
|
|
if (which[m] == ArgInfo::COMPUTE) {
|
|
if (j == 0)
|
|
ovec3d = (double ***) compute->get_griddata_by_index(idata);
|
|
else
|
|
oarray3d = (double ****) compute->get_griddata_by_index(idata);
|
|
} else {
|
|
if (j == 0) {
|
|
ovec3d = (double ***) fix->get_griddata_by_index(idata);
|
|
} else
|
|
oarray3d = (double ****) fix->get_griddata_by_index(idata);
|
|
}
|
|
|
|
if (nvalues == 1) {
|
|
if (j == 0) {
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vec3d[iz][iy][ix] += ovec3d[iz][iy][ix];
|
|
} else {
|
|
int jm1 = j - 1;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vec3d[iz][iy][ix] += oarray3d[iz][iy][ix][jm1];
|
|
}
|
|
} else {
|
|
if (j == 0) {
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
array3d[iz][iy][ix][m] += ovec3d[iz][iy][ix];
|
|
} else {
|
|
int jm1 = j - 1;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
array3d[iz][iy][ix][m] += oarray3d[iz][iy][ix][jm1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
normalize grid values for ATOM mode for owned cells
|
|
grid values are summed over numsamples (can be 1 or Nrepeat)
|
|
result = sample_value / count
|
|
exception is DENSITY_NUMBER:
|
|
result = value / (current binvol * Nrepeat)
|
|
exception is DENSITY_MASS:
|
|
result = (value * mv2d) / (current binvol * Nrepeat)
|
|
exception is TEMPERATURE:
|
|
result = (value * mvv2e) / (Nrepeat*cdof + adof*count) * boltz)
|
|
exception normalization is same for norm = ALL, SAMPLE, NONORM
|
|
so NONORM if test is after exception if tests
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::normalize_atom(int numsamples, GridData *grid)
|
|
{
|
|
int ix,iy,iz,m;
|
|
double count,norm;
|
|
|
|
double mvv2e = force->mvv2e;
|
|
double mv2d = force->mv2d;
|
|
double boltz = force->boltz;
|
|
|
|
double *prd = domain->prd;
|
|
double dx = prd[0]/nxgrid;
|
|
double dy = prd[1]/nygrid;
|
|
double dz = prd[2]/nzgrid;
|
|
|
|
double repeat = numsamples;
|
|
double invrepeat = 1.0/repeat;
|
|
|
|
double binvol;
|
|
if (dimension == 2) binvol = dx*dy;
|
|
else binvol = dx*dy*dz;
|
|
|
|
double density_number_norm = 1.0 / (binvol * repeat);
|
|
double density_mass_norm = mv2d / (binvol * repeat);
|
|
|
|
if (dimension == 2) {
|
|
double **count2d = grid->count2d;
|
|
|
|
if (nvalues == 1) {
|
|
double **vec2d = grid->vec2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
|
|
count = count2d[iy][ix];
|
|
if (count) {
|
|
if (which[0] == ArgInfo::DENSITY_NUMBER)
|
|
norm = density_number_norm;
|
|
else if (which[0] == ArgInfo::DENSITY_MASS)
|
|
norm = density_mass_norm;
|
|
else if (which[0] == ArgInfo::TEMPERATURE)
|
|
norm = mvv2e / ((repeat*cdof + adof*count) * boltz);
|
|
else if (normflag == NONORM)
|
|
norm = invrepeat;
|
|
else
|
|
norm = 1.0/count;
|
|
vec2d[iy][ix] *= norm;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
double ***array2d = grid->array2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
|
|
count = count2d[iy][ix];
|
|
if (count) {
|
|
for (m = 0; m < nvalues; m++) {
|
|
if (which[m] == ArgInfo::DENSITY_NUMBER)
|
|
norm = density_number_norm;
|
|
else if (which[m] == ArgInfo::DENSITY_MASS)
|
|
norm = density_mass_norm;
|
|
else if (which[m] == ArgInfo::TEMPERATURE)
|
|
norm = mvv2e / ((repeat*cdof + adof*count) * boltz);
|
|
else if (normflag == NONORM)
|
|
norm = invrepeat;
|
|
else
|
|
norm = 1.0/count;
|
|
array2d[iy][ix][m] *= norm;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} else if (dimension == 3) {
|
|
double ***count3d = grid->count3d;
|
|
|
|
if (nvalues == 1) {
|
|
double ***vec3d = grid->vec3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
|
|
count = count3d[iz][iy][ix];
|
|
if (count) {
|
|
if (which[0] == ArgInfo::DENSITY_NUMBER)
|
|
norm = density_number_norm;
|
|
else if (which[0] == ArgInfo::DENSITY_MASS)
|
|
norm = density_mass_norm;
|
|
else if (which[0] == ArgInfo::TEMPERATURE)
|
|
norm = mvv2e / ((repeat*cdof + adof*count) * boltz);
|
|
else if (normflag == NONORM)
|
|
norm = invrepeat;
|
|
else
|
|
norm = 1.0/count;
|
|
vec3d[iz][iy][ix] *= norm;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
double ****array3d = grid->array3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++) {
|
|
count = count3d[iz][iy][ix];
|
|
if (count) {
|
|
for (m = 0; m < nvalues; m++) {
|
|
if (which[m] == ArgInfo::DENSITY_NUMBER)
|
|
norm = density_number_norm;
|
|
else if (which[m] == ArgInfo::DENSITY_MASS)
|
|
norm = density_mass_norm;
|
|
else if (which[m] == ArgInfo::TEMPERATURE)
|
|
norm = mvv2e / ((repeat*cdof + adof*count) * boltz);
|
|
else if (normflag == NONORM)
|
|
norm = invrepeat;
|
|
else
|
|
norm = 1.0/count;
|
|
array3d[iz][iy][ix][m] *= norm;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
normalize grid values by numsamples
|
|
used for ATOM MODE when norm = SAMPLE
|
|
used for GRID mode
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::normalize_grid(int numsamples, GridData *grid)
|
|
{
|
|
int ix,iy,iz,m;
|
|
|
|
double invrepeat = 1.0/numsamples;
|
|
|
|
if (dimension == 2) {
|
|
if (nvalues == 1) {
|
|
double **vec2d = grid->vec2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vec2d[iy][ix] *= invrepeat;
|
|
} else {
|
|
double ***array2d = grid->array2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
for (m = 0; m < nvalues; m++)
|
|
array2d[iy][ix][m] *= invrepeat;
|
|
}
|
|
|
|
} else if (dimension == 3) {
|
|
if (nvalues == 1) {
|
|
double ***vec3d = grid->vec3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vec3d[iz][iy][ix] *= invrepeat;
|
|
} else {
|
|
double ****array3d = grid->array3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
for (m = 0; m < nvalues; m++)
|
|
array3d[iz][iy][ix][m] *= invrepeat;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
normalize grid counts by numsamples
|
|
used for ATOM mode
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::normalize_count(int numsamples, GridData *grid)
|
|
{
|
|
int ix,iy,iz;
|
|
|
|
double invrepeat = 1.0/numsamples;
|
|
|
|
if (dimension == 2) {
|
|
double **count2d = grid->count2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
count2d[iy][ix] *= invrepeat;
|
|
|
|
} else if (dimension == 3) {
|
|
double ***count3d = grid->count3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
count3d[iz][iy][ix] *= invrepeat;
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
allocate instance of Grid2d or Grid3d
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::allocate_grid()
|
|
{
|
|
if (modeatom) maxdist = 0.5 * neighbor->skin;
|
|
else if (modegrid) maxdist = 0.0;
|
|
|
|
if (dimension == 2) {
|
|
grid2d = new Grid2d(lmp, world, nxgrid, nygrid);
|
|
grid2d->set_distance(maxdist);
|
|
grid2d->setup_grid(nxlo_in, nxhi_in, nylo_in, nyhi_in,
|
|
nxlo_out, nxhi_out, nylo_out, nyhi_out);
|
|
|
|
// ngrid_buf12 converted to nvalues + count
|
|
|
|
grid2d->setup_comm(ngrid_buf1, ngrid_buf2);
|
|
ngrid_buf1 *= nvalues + 1;
|
|
ngrid_buf2 *= nvalues + 1;
|
|
|
|
grid_buf1 = grid_buf2 = nullptr;
|
|
if (ngrid_buf1) memory->create(grid_buf1, ngrid_buf1, "ave/grid:grid_buf1");
|
|
if (ngrid_buf2) memory->create(grid_buf2, ngrid_buf2, "ave/grid:grid_buf2");
|
|
|
|
ngridout = (nxhi_out - nxlo_out + 1) * (nyhi_out - nylo_out + 1);
|
|
|
|
} else {
|
|
grid3d = new Grid3d(lmp, world, nxgrid, nygrid, nzgrid);
|
|
grid3d->set_distance(maxdist);
|
|
grid3d->setup_grid(nxlo_in, nxhi_in, nylo_in, nyhi_in, nzlo_in, nzhi_in,
|
|
nxlo_out, nxhi_out, nylo_out, nyhi_out, nzlo_out, nzhi_out);
|
|
|
|
// ngrid_buf12 converted to nvalues + count
|
|
|
|
grid3d->setup_comm(ngrid_buf1, ngrid_buf2);
|
|
ngrid_buf1 *= nvalues + 1;
|
|
ngrid_buf2 *= nvalues + 1;
|
|
|
|
grid_buf1 = grid_buf2 = nullptr;
|
|
if (ngrid_buf1) memory->create(grid_buf1, ngrid_buf1, "ave/grid:grid_buf1");
|
|
if (ngrid_buf2) memory->create(grid_buf2, ngrid_buf2, "ave/grid:grid_buf2");
|
|
|
|
ngridout = (nxhi_out - nxlo_out + 1) * (nyhi_out - nylo_out + 1) *
|
|
(nzhi_out - nzlo_out + 1);
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
allocate a data grid and zero its values
|
|
if ATOM mode, also allocate per-grid count
|
|
------------------------------------------------------------------------- */
|
|
|
|
FixAveGrid::GridData *FixAveGrid::allocate_one_grid()
|
|
{
|
|
GridData *grid = new GridData();
|
|
|
|
grid->vec2d = nullptr;
|
|
grid->array2d = nullptr;
|
|
grid->count2d = nullptr;
|
|
grid->vec3d = nullptr;
|
|
grid->array3d = nullptr;
|
|
grid->count3d = nullptr;
|
|
|
|
if (dimension == 2) {
|
|
if (nvalues == 1)
|
|
memory->create2d_offset(grid->vec2d, nylo_out, nyhi_out,
|
|
nxlo_out, nxhi_out, "ave/grid:vec2d");
|
|
else
|
|
memory->create3d_offset_last(grid->array2d, nylo_out, nyhi_out,
|
|
nxlo_out, nxhi_out,
|
|
nvalues, "ave/grid:array3d");
|
|
if (modeatom)
|
|
memory->create2d_offset(grid->count2d, nylo_out, nyhi_out,
|
|
nxlo_out, nxhi_out, "ave/grid:count2d");
|
|
|
|
} else if (dimension == 3) {
|
|
if (nvalues == 1)
|
|
memory->create3d_offset(grid->vec3d, nzlo_out, nzhi_out, nylo_out,
|
|
nyhi_out, nxlo_out, nxhi_out, "ave/grid:vec3d");
|
|
else
|
|
memory->create4d_offset_last(grid->array3d, nzlo_out, nzhi_out, nylo_out,
|
|
nyhi_out, nxlo_out, nxhi_out, nvalues,
|
|
"ave/grid:array3d");
|
|
if (modeatom)
|
|
memory->create3d_offset(grid->count3d, nzlo_out, nzhi_out, nylo_out,
|
|
nyhi_out, nxlo_out, nxhi_out, "ave/grid:count3d");
|
|
}
|
|
|
|
zero_grid(grid);
|
|
|
|
return grid;
|
|
}
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
create clone of a data grid
|
|
allocate a new grid and copy only the pointers from the source grid
|
|
used by reset_grid() to keep old data values until remap is complete
|
|
------------------------------------------------------------------------- */
|
|
|
|
FixAveGrid::GridData *FixAveGrid::clone_one_grid(GridData *src)
|
|
{
|
|
GridData *grid = new GridData();
|
|
|
|
grid->vec2d = src->vec2d;
|
|
grid->array2d = src->array2d;
|
|
grid->count2d = src->count2d;
|
|
grid->vec3d = src->vec3d;
|
|
grid->array3d = src->array3d;
|
|
grid->count3d = src->count3d;
|
|
|
|
return grid;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
deallocate a data grid and all its memory
|
|
if ATOM mode, also deallocate per-grid count
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::deallocate_one_grid(GridData *grid,
|
|
int xoffset, int yoffset, int zoffset)
|
|
{
|
|
if (dimension == 2) {
|
|
if (nvalues == 1)
|
|
memory->destroy2d_offset(grid->vec2d,yoffset,xoffset);
|
|
else
|
|
memory->destroy3d_offset_last(grid->array2d,yoffset,xoffset);
|
|
if (modeatom)
|
|
memory->destroy2d_offset(grid->count2d,yoffset,xoffset);
|
|
|
|
} else if (dimension == 3) {
|
|
if (nvalues == 1)
|
|
memory->destroy3d_offset(grid->vec3d,zoffset,yoffset,xoffset);
|
|
else
|
|
memory->destroy4d_offset_last(grid->array3d,zoffset,yoffset,xoffset);
|
|
if (modeatom)
|
|
memory->destroy3d_offset(grid->count3d,zoffset,yoffset,xoffset);
|
|
}
|
|
|
|
delete grid;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
size of a data grid
|
|
if ATOM mode, also include per-grid count
|
|
------------------------------------------------------------------------- */
|
|
|
|
double FixAveGrid::size_grid(GridData * /*grid*/)
|
|
{
|
|
int nper = nvalues;
|
|
if (modeatom) nper++;
|
|
|
|
double bytes;
|
|
if (dimension == 2)
|
|
bytes = sizeof(double) * nper * (nxhi_out - nxlo_out + 1) * (nyhi_out - nylo_out + 1);
|
|
else
|
|
bytes = sizeof(double) * nper * (nxhi_out - nxlo_out + 1) * (nyhi_out - nylo_out + 1) *
|
|
(nzhi_out - nzlo_out + 1);
|
|
|
|
return bytes;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
zero values for a data grid including ghost cells
|
|
for ATOM mode, also zero per-grid count
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::zero_grid(GridData *grid)
|
|
{
|
|
if (!ngridout) return;
|
|
|
|
if (dimension == 2) {
|
|
if (nvalues == 1)
|
|
memset(&grid->vec2d[nylo_out][nxlo_out], 0, sizeof(double) * ngridout);
|
|
else
|
|
memset(&grid->array2d[nylo_out][nxlo_out][0], 0, sizeof(double) * ngridout * nvalues);
|
|
if (modeatom) memset(&grid->count2d[nylo_out][nxlo_out], 0, sizeof(double) * ngridout);
|
|
|
|
} else {
|
|
if (nvalues == 1)
|
|
memset(&grid->vec3d[nzlo_out][nylo_out][nxlo_out], 0, sizeof(double) * ngridout);
|
|
else
|
|
memset(&grid->array3d[nzlo_out][nylo_out][nxlo_out][0], 0, sizeof(double)* ngridout * nvalues);
|
|
if (modeatom)
|
|
memset(&grid->count3d[nzlo_out][nylo_out][nxlo_out], 0, sizeof(double) * ngridout);
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
copy src grid values to result grid, just for owned grid cells
|
|
for ATOM mode, also copy per-grid count
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::copy_grid(GridData *src, GridData *result)
|
|
{
|
|
int ix,iy,iz,m;
|
|
|
|
if (!ngridout) return;
|
|
|
|
if (dimension == 2) {
|
|
if (nvalues == 1) {
|
|
double **vsrc = src->vec2d;
|
|
double **vresult = result->vec2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vresult[iy][ix] = vsrc[iy][ix];
|
|
} else {
|
|
double ***asrc = src->array2d;
|
|
double ***aresult = result->array2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
for (m = 0; m < nvalues; m++)
|
|
aresult[iy][ix][m] = asrc[iy][ix][m];
|
|
}
|
|
if (modeatom) {
|
|
double **csrc = src->count2d;
|
|
double **cresult = result->count2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
cresult[iy][ix] = csrc[iy][ix];
|
|
}
|
|
|
|
} else if (dimension == 3) {
|
|
if (nvalues == 1) {
|
|
double ***vsrc = src->vec3d;
|
|
double ***vresult = result->vec3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vresult[iz][iy][ix] = vsrc[iz][iy][ix];
|
|
} else {
|
|
double ****asrc = src->array3d;
|
|
double ****aresult = result->array3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
for (m = 0; m < nvalues; m++)
|
|
aresult[iz][iy][ix][m] = asrc[iz][iy][ix][m];
|
|
}
|
|
if (modeatom) {
|
|
double ***csrc = src->count3d;
|
|
double ***cresult = result->count3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
cresult[iz][iy][ix] = csrc[iz][iy][ix];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
add values in src grid to result grid, just for owned grid cells
|
|
for ATOM mode, also sum per-grid count
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::add_grid(GridData *src, GridData *result)
|
|
{
|
|
int ix,iy,iz,m;
|
|
|
|
if (!ngridout) return;
|
|
|
|
if (dimension == 2) {
|
|
if (nvalues == 1) {
|
|
double **vsrc = src->vec2d;
|
|
double **vresult = result->vec2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vresult[iy][ix] += vsrc[iy][ix];
|
|
} else {
|
|
double ***asrc = src->array2d;
|
|
double ***aresult = result->array2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
for (m = 0; m < nvalues; m++)
|
|
aresult[iy][ix][m] += asrc[iy][ix][m];
|
|
}
|
|
if (modeatom) {
|
|
double **csrc = src->count2d;
|
|
double **cresult = result->count2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
cresult[iy][ix] += csrc[iy][ix];
|
|
}
|
|
|
|
} else if (dimension == 3) {
|
|
if (nvalues == 1) {
|
|
double ***vsrc = src->vec3d;
|
|
double ***vresult = result->vec3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vresult[iz][iy][ix] += vsrc[iz][iy][ix];
|
|
} else {
|
|
double ****asrc = src->array3d;
|
|
double ****aresult = result->array3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
for (m = 0; m < nvalues; m++)
|
|
aresult[iz][iy][ix][m] += asrc[iz][iy][ix][m];
|
|
}
|
|
if (modeatom) {
|
|
double ***csrc = src->count3d;
|
|
double ***cresult = result->count3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
cresult[iz][iy][ix] += csrc[iz][iy][ix];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
subtact values in src grid from result grid, just for owned grid cells
|
|
for ATOM mode, also sum per-grid count
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::subtract_grid(GridData *src, GridData *result)
|
|
{
|
|
int ix,iy,iz,m;
|
|
|
|
if (!ngridout) return;
|
|
|
|
if (dimension == 2) {
|
|
if (nvalues == 1) {
|
|
double **vsrc = src->vec2d;
|
|
double **vresult = result->vec2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vresult[iy][ix] -= vsrc[iy][ix];
|
|
} else {
|
|
double ***asrc = src->array2d;
|
|
double ***aresult = result->array2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
for (m = 0; m < nvalues; m++)
|
|
aresult[iy][ix][m] -= asrc[iy][ix][m];
|
|
}
|
|
if (modeatom) {
|
|
double **csrc = src->count2d;
|
|
double **cresult = result->count2d;
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
cresult[iy][ix] -= csrc[iy][ix];
|
|
}
|
|
|
|
} else if (dimension == 3) {
|
|
if (nvalues == 1) {
|
|
double ***vsrc = src->vec3d;
|
|
double ***vresult = result->vec3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
vresult[iz][iy][ix] -= vsrc[iz][iy][ix];
|
|
} else {
|
|
double ****asrc = src->array3d;
|
|
double ****aresult = result->array3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
for (m = 0; m < nvalues; m++)
|
|
aresult[iz][iy][ix][m] -= asrc[iz][iy][ix][m];
|
|
}
|
|
if (modeatom) {
|
|
double ***csrc = src->count3d;
|
|
double ***cresult = result->count3d;
|
|
for (iz = nzlo_in; iz <= nzhi_in; iz++)
|
|
for (iy = nylo_in; iy <= nyhi_in; iy++)
|
|
for (ix = nxlo_in; ix <= nxhi_in; ix++)
|
|
cresult[iz][iy][ix] -= csrc[iz][iy][ix];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
set output grid pointers to src grid data
|
|
for ATOM mode, also set pointers to per-grid count
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::output_grid(GridData *src)
|
|
{
|
|
if (dimension == 2) {
|
|
if (nvalues == 1)
|
|
grid_output->vec2d = src->vec2d;
|
|
else
|
|
grid_output->array2d = src->array2d;
|
|
if (modeatom)
|
|
grid_output->count2d = src->count2d;
|
|
|
|
} else if (dimension == 3) {
|
|
if (nvalues == 1)
|
|
grid_output->vec3d = src->vec3d;
|
|
else
|
|
grid_output->array3d = src->array3d;
|
|
if (modeatom)
|
|
grid_output->count3d = src->count3d;
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
pack ghost values into buf to send to another proc
|
|
nvalues per grid point + count-
|
|
only invoked for ATOM mode
|
|
------------------------------------------------------------------------ */
|
|
|
|
void FixAveGrid::pack_reverse_grid(int /*which*/, void *vbuf, int nlist, int *list)
|
|
{
|
|
int i,j,m;
|
|
|
|
auto buf = (double *) vbuf;
|
|
double *count,*data,*values;
|
|
m = 0;
|
|
|
|
if (dimension == 2) {
|
|
count = &grid_sample->count2d[nylo_out][nxlo_out];
|
|
if (nvalues == 1) data = &grid_sample->vec2d[nylo_out][nxlo_out];
|
|
else data = &grid_sample->array2d[nylo_out][nxlo_out][0];
|
|
} else {
|
|
count = &grid_sample->count3d[nzlo_out][nylo_out][nxlo_out];
|
|
if (nvalues == 1) data = &grid_sample->vec3d[nzlo_out][nylo_out][nxlo_out];
|
|
else data = &grid_sample->array3d[nzlo_out][nylo_out][nxlo_out][0];
|
|
}
|
|
|
|
if (nvalues == 1) {
|
|
for (i = 0; i < nlist; i++) {
|
|
buf[m++] = count[list[i]];
|
|
buf[m++] = data[list[i]];
|
|
}
|
|
} else {
|
|
for (i = 0; i < nlist; i++) {
|
|
buf[m++] = count[list[i]];
|
|
values = &data[nvalues*list[i]];
|
|
for (j = 0; j < nvalues; j++)
|
|
buf[m++] = values[j];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
unpack another proc's ghost values from buf and add to own values
|
|
nvalues per grid point + count
|
|
only invoked for ATOM mode
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::unpack_reverse_grid(int /*which*/, void *vbuf, int nlist, int *list)
|
|
{
|
|
int i,j,m;
|
|
|
|
auto buf = (double *) vbuf;
|
|
double *count,*data,*values;
|
|
|
|
if (dimension == 2) {
|
|
count = &grid_sample->count2d[nylo_out][nxlo_out];
|
|
if (nvalues == 1) data = &grid_sample->vec2d[nylo_out][nxlo_out];
|
|
else data = &grid_sample->array2d[nylo_out][nxlo_out][0];
|
|
} else {
|
|
count = &grid_sample->count3d[nzlo_out][nylo_out][nxlo_out];
|
|
if (nvalues == 1) data = &grid_sample->vec3d[nzlo_out][nylo_out][nxlo_out];
|
|
else data = &grid_sample->array3d[nzlo_out][nylo_out][nxlo_out][0];
|
|
}
|
|
|
|
m = 0;
|
|
if (nvalues == 1) {
|
|
for (i = 0; i < nlist; i++) {
|
|
count[list[i]] += buf[m++];
|
|
data[list[i]] += buf[m++];
|
|
}
|
|
} else {
|
|
for (i = 0; i < nlist; i++) {
|
|
count[list[i]] += buf[m++];
|
|
values = &data[nvalues*list[i]];
|
|
for (j = 0; j < nvalues; j++)
|
|
values[j] += buf[m++];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
pack old grid values to buf to send to another proc
|
|
invoked for both GRID and ATOM mode
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::pack_remap_grid(int /*which*/, void *vbuf, int nlist, int *list)
|
|
{
|
|
auto buf = (double *) vbuf;
|
|
|
|
int running_flag = 0;
|
|
if (aveflag == RUNNING || aveflag == WINDOW) running_flag = 1;
|
|
int window_flag = 0;
|
|
if (aveflag == WINDOW) window_flag = 1;
|
|
|
|
int m = 0;
|
|
for (int i = 0; i < nlist; i++) {
|
|
m += pack_one_grid(grid_sample_previous,list[i],&buf[m]);
|
|
m += pack_one_grid(grid_nfreq_previous,list[i],&buf[m]);
|
|
if (running_flag) m += pack_one_grid(grid_running_previous,list[i],&buf[m]);
|
|
if (window_flag)
|
|
for (int iwindow = 0; iwindow < nwindow; iwindow++)
|
|
m += pack_one_grid(grid_window_previous[iwindow],list[i],&buf[m]);
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
unpack received owned values from buf into new grid
|
|
invoked for both GRID and ATOM mode
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::unpack_remap_grid(int /*which*/, void *vbuf, int nlist, int *list)
|
|
{
|
|
auto buf = (double *) vbuf;
|
|
|
|
int running_flag = 0;
|
|
if (aveflag == RUNNING || aveflag == WINDOW) running_flag = 1;
|
|
int window_flag = 0;
|
|
if (aveflag == WINDOW) window_flag = 1;
|
|
|
|
int m = 0;
|
|
for (int i = 0; i < nlist; i++) {
|
|
m += unpack_one_grid(&buf[m],grid_sample,list[i]);
|
|
m += unpack_one_grid(&buf[m],grid_nfreq,list[i]);
|
|
if (running_flag) m += unpack_one_grid(&buf[m],grid_running,list[i]);
|
|
if (window_flag)
|
|
for (int iwindow = 0; iwindow < nwindow; iwindow++)
|
|
m += unpack_one_grid(&buf[m],grid_window[iwindow],list[i]);
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
pack values for a single grid cell to buf
|
|
return number of values packed
|
|
------------------------------------------------------------------------- */
|
|
|
|
int FixAveGrid::pack_one_grid(GridData *grid, int index, double *buf)
|
|
{
|
|
double *count,*data,*values;
|
|
|
|
if (dimension == 2) {
|
|
count = &grid->count2d[nylo_out_previous][nxlo_out_previous];
|
|
if (nvalues == 1) data = &grid->vec2d[nylo_out_previous][nxlo_out_previous];
|
|
else data = &grid->array2d[nylo_out_previous][nxlo_out_previous][0];
|
|
} else {
|
|
count = &grid->count3d[nzlo_out_previous][nylo_out_previous][nxlo_out_previous];
|
|
if (nvalues == 1) data = &grid->vec3d[nzlo_out_previous][nylo_out_previous][nxlo_out_previous];
|
|
else data = &grid->array3d[nzlo_out_previous][nylo_out_previous][nxlo_out_previous][0];
|
|
}
|
|
|
|
int m = 0;
|
|
if (modeatom) buf[m++] = count[index];
|
|
if (nvalues == 1) buf[m++] = data[index];
|
|
else {
|
|
values = &data[nvalues*index];
|
|
for (int j = 0; j < nvalues; j++)
|
|
buf[m++] = values[j];
|
|
}
|
|
|
|
return m;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
unpack values for a single grid cell from buf
|
|
return number of values unpacked
|
|
------------------------------------------------------------------------- */
|
|
|
|
int FixAveGrid::unpack_one_grid(double *buf, GridData *grid, int index)
|
|
{
|
|
double *count,*data,*values;
|
|
|
|
if (dimension == 2) {
|
|
count = &grid->count2d[nylo_out][nxlo_out];
|
|
if (nvalues == 1) data = &grid->vec2d[nylo_out][nxlo_out];
|
|
else data = &grid->array2d[nylo_out][nxlo_out][0];
|
|
} else {
|
|
count = &grid->count3d[nzlo_out][nylo_out][nxlo_out];
|
|
if (nvalues == 1) data = &grid->vec3d[nzlo_out][nylo_out][nxlo_out];
|
|
else data = &grid->array3d[nzlo_out][nylo_out][nxlo_out][0];
|
|
}
|
|
|
|
int m = 0;
|
|
if (modeatom) count[index] = buf[m++];
|
|
if (nvalues == 1) data[index] = buf[m++];
|
|
else {
|
|
values = &data[nvalues*index];
|
|
for (int j = 0; j < nvalues; j++)
|
|
values[j] = buf[m++];
|
|
}
|
|
|
|
return m;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
subset of grid assigned to each proc may have changed
|
|
called by load balancer when proc subdomains are adjusted
|
|
persist per-grid data by performing a grid remap
|
|
------------------------------------------------------------------------- */
|
|
|
|
void FixAveGrid::reset_grid()
|
|
{
|
|
// check if new grid partitioning is different on any proc
|
|
// if not, just return
|
|
|
|
if (dimension == 2) {
|
|
int tmp[8];
|
|
Grid2d *gridnew = new Grid2d(lmp, world, nxgrid, nygrid);
|
|
gridnew->set_distance(maxdist);
|
|
gridnew->setup_grid(tmp[0], tmp[1], tmp[2], tmp[3],
|
|
tmp[4], tmp[5], tmp[6], tmp[7]);
|
|
|
|
if (grid2d->identical(gridnew)) {
|
|
delete gridnew;
|
|
return;
|
|
} else delete gridnew;
|
|
|
|
} else {
|
|
|
|
int tmp[12];
|
|
Grid3d *gridnew = new Grid3d(lmp, world, nxgrid, nygrid, nzgrid);
|
|
gridnew->set_distance(maxdist);
|
|
gridnew->setup_grid(tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5],
|
|
tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11]);
|
|
|
|
if (grid3d->identical(gridnew)) {
|
|
delete gridnew;
|
|
return;
|
|
} else delete gridnew;
|
|
}
|
|
|
|
// for ATOM mode, perform ghost to owned grid comm for grid_sample
|
|
// necessary b/c remap will only communicate owned grid cell data
|
|
// so can't lose ghost data not yet summed to owned cells
|
|
// nvalues+1 includes atom count
|
|
|
|
if (modeatom) {
|
|
if (dimension == 2)
|
|
grid2d->reverse_comm(Grid2d::FIX,this,0,nvalues+1,sizeof(double),
|
|
grid_buf1,grid_buf2,MPI_DOUBLE);
|
|
else
|
|
grid3d->reverse_comm(Grid3d::FIX,this,0,nvalues+1,sizeof(double),
|
|
grid_buf1,grid_buf2,MPI_DOUBLE);
|
|
}
|
|
|
|
// deallocate local comm buffers b/c new ones will be allocated
|
|
|
|
memory->destroy(grid_buf1);
|
|
memory->destroy(grid_buf2);
|
|
|
|
// make copy of ptrs to grid data which needs to persist
|
|
|
|
if (dimension == 2) grid2d_previous = grid2d;
|
|
else grid3d_previous = grid3d;
|
|
|
|
nxlo_out_previous = nxlo_out;
|
|
nylo_out_previous = nylo_out;
|
|
nzlo_out_previous = nzlo_out;
|
|
|
|
grid_sample_previous = clone_one_grid(grid_sample);
|
|
grid_nfreq_previous = clone_one_grid(grid_nfreq);
|
|
if (aveflag == RUNNING || aveflag == WINDOW)
|
|
grid_running_previous = clone_one_grid(grid_running);
|
|
if (aveflag == WINDOW) {
|
|
grid_window_previous = new GridData*[nwindow];
|
|
for (int i = 0; i < nwindow; i++)
|
|
grid_window_previous[i] = clone_one_grid(grid_window[i]);
|
|
}
|
|
|
|
delete grid_sample;
|
|
delete grid_nfreq;
|
|
if (aveflag == RUNNING || aveflag == WINDOW) delete grid_running;
|
|
if (aveflag == WINDOW) {
|
|
for (int i = 0; i < nwindow; i++)
|
|
delete grid_window[i];
|
|
delete [] grid_window;
|
|
}
|
|
|
|
// allocate grid instance and grid data for new decomposition
|
|
|
|
allocate_grid();
|
|
|
|
grid_sample = allocate_one_grid();
|
|
grid_nfreq = allocate_one_grid();
|
|
if (aveflag == RUNNING || aveflag == WINDOW) grid_running = allocate_one_grid();
|
|
if (aveflag == WINDOW) {
|
|
grid_window = new GridData*[nwindow];
|
|
for (int i = 0; i < nwindow; i++)
|
|
grid_window[i] = allocate_one_grid();
|
|
}
|
|
|
|
// perform remap from previous decomp to new decomp
|
|
// nper = # of remapped values per grid cell
|
|
// depends on atom vs grid mode, and running/window options
|
|
|
|
int nremap_buf1,nremap_buf2;
|
|
if (dimension == 2)
|
|
grid2d->setup_remap(grid2d_previous,nremap_buf1,nremap_buf2);
|
|
else
|
|
grid3d->setup_remap(grid3d_previous,nremap_buf1,nremap_buf2);
|
|
|
|
int n = 2; // grid_sample & grid_nfreq
|
|
if (aveflag == RUNNING || aveflag == WINDOW) n++; // grid_running
|
|
if (aveflag == WINDOW) n += nwindow; // grid_window
|
|
int nper = n*nvalues;
|
|
if (modeatom) nper += n;
|
|
|
|
double *remap_buf1 = nullptr;
|
|
double *remap_buf2 = nullptr;
|
|
if (nremap_buf1) memory->create(remap_buf1, nper*nremap_buf1, "ave/grid:remap_buf1");
|
|
if (nremap_buf2) memory->create(remap_buf2, nper*nremap_buf2, "ave/grid:remap_buf2");
|
|
|
|
if (dimension == 2)
|
|
grid2d->remap(Grid2d::FIX,this,0,nper,sizeof(double),remap_buf1,remap_buf2,MPI_DOUBLE);
|
|
else
|
|
grid3d->remap(Grid3d::FIX,this,0,nper,sizeof(double),remap_buf1,remap_buf2,MPI_DOUBLE);
|
|
|
|
memory->destroy(remap_buf1);
|
|
memory->destroy(remap_buf2);
|
|
|
|
// delete grid instance and grid data for previous decomposition
|
|
|
|
if (dimension == 2) delete grid2d_previous;
|
|
else delete grid3d_previous;
|
|
|
|
deallocate_one_grid(grid_sample_previous,nxlo_out_previous,nylo_out_previous,nzlo_out_previous);
|
|
deallocate_one_grid(grid_nfreq_previous,nxlo_out_previous,nylo_out_previous,nzlo_out_previous);
|
|
if (aveflag == RUNNING || aveflag == WINDOW)
|
|
deallocate_one_grid(grid_running_previous,nxlo_out_previous,nylo_out_previous,nzlo_out_previous);
|
|
if (aveflag == WINDOW) {
|
|
for (int i = 0; i < nwindow; i++)
|
|
deallocate_one_grid(grid_window_previous[i],nxlo_out_previous,nylo_out_previous,nzlo_out_previous);
|
|
delete [] grid_window_previous;
|
|
}
|
|
|
|
// set output data in case load balance fix comes after fix ave/grid
|
|
|
|
output_grid(grid_nfreq);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return index of grid associated with name
|
|
this class can store M named grids, indexed 0 to M-1
|
|
also set dim for 2d vs 3d grid
|
|
return -1 if grid name not found
|
|
------------------------------------------------------------------------- */
|
|
|
|
int FixAveGrid::get_grid_by_name(const std::string &name, int &dim)
|
|
{
|
|
if (name == "grid") {
|
|
dim = dimension;
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return ptr to Grid data struct for grid with index
|
|
this class can store M named grids, indexed 0 to M-1
|
|
return nullptr if index is invalid
|
|
------------------------------------------------------------------------- */
|
|
|
|
void *FixAveGrid::get_grid_by_index(int index)
|
|
{
|
|
if (index == 0) {
|
|
if (dimension == 2) return grid2d;
|
|
else return grid3d;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return index of data associated with name in grid with index igrid
|
|
this class can store M named grids, indexed 0 to M-1
|
|
each grid can store G named data sets, indexed 0 to G-1
|
|
a data set name can be associated with multiple grids
|
|
set ncol for data set, 0 = vector, 1-N for array with N columns
|
|
vector = single value per grid pt, array = N values per grid pt
|
|
return -1 if data name not found
|
|
------------------------------------------------------------------------- */
|
|
|
|
int FixAveGrid::get_griddata_by_name(int igrid, const std::string &name, int &ncol)
|
|
{
|
|
if ((igrid == 0) && (name == "data")) {
|
|
if (nvalues == 1) ncol = 0;
|
|
else ncol = nvalues;
|
|
return 0;
|
|
}
|
|
|
|
// count is only produced for ATOM mode
|
|
|
|
if (modeatom && (igrid == 0) && (name == "count")) {
|
|
ncol = 0;
|
|
return 1;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
return ptr to multidim data array associated with index
|
|
this class can store G named data sets, indexed 0 to M-1
|
|
return nullptr if index is invalid
|
|
------------------------------------------------------------------------- */
|
|
|
|
void *FixAveGrid::get_griddata_by_index(int index)
|
|
{
|
|
if (index == 0) {
|
|
if (dimension == 2) {
|
|
if (nvalues == 1) return grid_output->vec2d;
|
|
else return grid_output->array2d;
|
|
} else {
|
|
if (nvalues == 1) return grid_output->vec3d;
|
|
else return grid_output->array3d;
|
|
}
|
|
}
|
|
if (index == 1) {
|
|
if (dimension == 2) return grid_output->count2d;
|
|
else return grid_output->count3d;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
memory usage of local per-grid data
|
|
------------------------------------------------------------------------- */
|
|
|
|
double FixAveGrid::memory_usage()
|
|
{
|
|
double bytes = 0.0;
|
|
|
|
bytes += size_grid(grid_sample);
|
|
bytes += size_grid(grid_nfreq);
|
|
if (aveflag == RUNNING || aveflag == WINDOW)
|
|
bytes += size_grid(grid_running);
|
|
if (aveflag == WINDOW)
|
|
bytes += nwindow * size_grid(grid_window[0]);
|
|
|
|
if (modeatom) {
|
|
bytes += sizeof(int) * maxatom * dimension; // bin array
|
|
bytes += sizeof(int) * maxatom; // skip vector
|
|
bytes += sizeof(double) * maxvar; // vresult for per-atom variable
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
calculate nvalid = next step on which end_of_step does something
|
|
can be this timestep if multiple of nfreq and nrepeat = 1
|
|
else backup from next multiple of nfreq
|
|
------------------------------------------------------------------------- */
|
|
|
|
bigint FixAveGrid::nextvalid()
|
|
{
|
|
bigint nvalid = (update->ntimestep/pergrid_freq)*pergrid_freq + pergrid_freq;
|
|
if (nvalid-pergrid_freq == update->ntimestep && nrepeat == 1)
|
|
nvalid = update->ntimestep;
|
|
else
|
|
nvalid -= ((bigint)nrepeat-1)*nevery;
|
|
if (nvalid < update->ntimestep) nvalid += pergrid_freq;
|
|
return nvalid;
|
|
}
|