initial version of dump grid

This commit is contained in:
Steve Plimpton
2022-07-19 11:03:44 -06:00
parent 68d5b3e3d9
commit 5c81ba81d7
5 changed files with 1029 additions and 40 deletions

863
src/dump_grid.cpp Normal file
View File

@ -0,0 +1,863 @@
// clang-format off
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
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 "dump_grid.h"
#include "arg_info.h"
#include "compute.h"
#include "domain.h"
#include "error.h"
#include "fix.h"
#include "memory.h"
#include "modify.h"
#include "region.h"
#include "update.h"
#include <cstring>
using namespace LAMMPS_NS;
// customize by adding keyword
// also customize compute_atom_property.cpp
enum{COMPUTE,FIX};
#define ONEFIELD 32
#define DELTA 1048576
/* ---------------------------------------------------------------------- */
DumpGrid::DumpGrid(LAMMPS *lmp, int narg, char **arg) :
Dump(lmp, narg, arg)
{
if (narg == 5) error->all(FLERR,"No dump grid arguments specified");
clearstep = 1;
nevery = utils::inumeric(FLERR,arg[3],false,lmp);
if (nevery <= 0) error->all(FLERR,"Illegal dump grid command");
// expand args if any have wildcard character "*"
// ok to include trailing optional args,
// so long as they do not have "*" between square brackets
// nfield may be shrunk below if extra optional args exist
expand = 0;
nfield = nargnew = utils::expand_args(FLERR,narg-5,&arg[5],1,earg,lmp);
if (earg != &arg[5]) expand = 1;
// allocate field vectors
pack_choice = new FnPtrPack[nfield];
vtype = new int[nfield];
memory->create(field2index,nfield,"dump:field2index");
memory->create(argindex,nfield,"dump:argindex");
buffer_allow = 1;
buffer_flag = 1;
// computes and fixes which the dump accesses
ncompute = 0;
nfix = 0;
// process attributes
// ioptional = start of additional optional args in expanded args
ioptional = parse_fields(nfield,earg);
if (ioptional < nfield &&
strcmp(style,"image") != 0 && strcmp(style,"movie") != 0)
error->all(FLERR,"Invalid attribute {} in dump {} command",earg[ioptional],style);
// noptional = # of optional args
// reset nfield to subtract off optional args
// reset ioptional to what it would be in original arg list
// only dump image and dump movie styles process optional args,
// they do not use expanded earg list
int noptional = nfield - ioptional;
nfield -= noptional;
size_one = nfield;
ioptional = narg - noptional;
// setup format strings
vformat = new char*[nfield];
std::string cols;
cols.clear();
for (int i = 0; i < nfield; i++) {
if (vtype[i] == Dump::INT) cols += "%d ";
else if (vtype[i] == Dump::DOUBLE) cols += "%g ";
else if (vtype[i] == Dump::STRING) cols += "%s ";
else if (vtype[i] == Dump::BIGINT) cols += BIGINT_FORMAT " ";
vformat[i] = nullptr;
}
cols.resize(cols.size()-1);
format_default = utils::strdup(cols);
format_column_user = new char*[nfield];
for (int i = 0; i < nfield; i++) format_column_user[i] = nullptr;
// setup column string
cols.clear();
keyword_user.resize(nfield);
for (int iarg = 0; iarg < nfield; iarg++) {
key2col[earg[iarg]] = iarg;
keyword_user[iarg].clear();
if (cols.size()) cols += " ";
cols += earg[iarg];
}
columns_default = utils::strdup(cols);
}
/* ---------------------------------------------------------------------- */
DumpGrid::~DumpGrid()
{
// if wildcard expansion occurred, free earg memory from expand_args()
// could not do in constructor, b/c some derived classes process earg
if (expand) {
for (int i = 0; i < nargnew; i++) delete[] earg[i];
memory->sfree(earg);
}
delete[] pack_choice;
delete[] vtype;
memory->destroy(field2index);
memory->destroy(argindex);
delete[] idregion;
for (int i = 0; i < ncompute; i++) delete[] id_compute[i];
memory->sfree(id_compute);
delete[] compute;
for (int i = 0; i < nfix; i++) delete[] id_fix[i];
memory->sfree(id_fix);
delete[] fix;
if (vformat) {
for (int i = 0; i < nfield; i++) delete[] vformat[i];
delete[] vformat;
}
if (format_column_user) {
for (int i = 0; i < nfield; i++) delete[] format_column_user[i];
delete[] format_column_user;
}
delete[] columns_default;
delete[] columns;
}
/* ---------------------------------------------------------------------- */
void DumpGrid::init_style()
{
// assemble ITEMS: column string from defaults and user values
delete[] columns;
std::string combined;
int icol = 0;
for (auto item : utils::split_words(columns_default)) {
if (combined.size()) combined += " ";
if (keyword_user[icol].size()) combined += keyword_user[icol];
else combined += item;
++icol;
}
columns = utils::strdup(combined);
// format = copy of default or user-specified line format
delete[] format;
if (format_line_user) format = utils::strdup(format_line_user);
else format = utils::strdup(format_default);
// tokenize the format string and add space at end of each format element
// if user-specified int/float format exists, use it instead
// if user-specified column format exists, use it instead
// lo priority = line, medium priority = int/float, hi priority = column
auto words = utils::split_words(format);
if ((int) words.size() < nfield)
error->all(FLERR,"Dump_modify format line is too short");
int i=0;
for (const auto &word : words) {
delete[] vformat[i];
if (format_column_user[i])
vformat[i] = utils::strdup(std::string(format_column_user[i]) + " ");
else if (vtype[i] == Dump::INT && format_int_user)
vformat[i] = utils::strdup(std::string(format_int_user) + " ");
else if (vtype[i] == Dump::DOUBLE && format_float_user)
vformat[i] = utils::strdup(std::string(format_float_user) + " ");
else if (vtype[i] == Dump::BIGINT && format_bigint_user)
vformat[i] = utils::strdup(std::string(format_bigint_user) + " ");
else vformat[i] = utils::strdup(word + " ");
// remove trailing blank on last column's format
if (i == nfield-1) vformat[i][strlen(vformat[i])-1] = '\0';
++i;
}
// setup boundary string
domain->boundary_string(boundstr);
// setup function ptrs
if (binary && domain->triclinic == 0)
header_choice = &DumpGrid::header_binary;
else if (binary && domain->triclinic == 1)
header_choice = &DumpGrid::header_binary_triclinic;
else if (!binary && domain->triclinic == 0)
header_choice = &DumpGrid::header_item;
else if (!binary && domain->triclinic == 1)
header_choice = &DumpGrid::header_item_triclinic;
if (binary) write_choice = &DumpGrid::write_binary;
else if (buffer_flag == 1) write_choice = &DumpGrid::write_string;
else write_choice = &DumpGrid::write_lines;
// find current ptr for each compute and fix
// check that fix frequency is acceptable
for (i = 0; i < ncompute; i++) {
compute[i] = modify->get_compute_by_id(id_compute[i]);
if (!compute[i]) error->all(FLERR,"Could not find dump grid compute ID {}",id_compute[i]);
}
for (i = 0; i < nfix; i++) {
fix[i] = modify->get_fix_by_id(id_fix[i]);
if (!fix[i]) error->all(FLERR,"Could not find dump grid fix ID {}", id_fix[i]);
if (nevery % fix[i]->peratom_freq)
error->all(FLERR,"Dump grid and fix not computed at compatible times");
}
// check validity of region
if (idregion && !domain->get_region_by_id(idregion))
error->all(FLERR,"Region {} for dump grid does not exist", idregion);
// open single file, one time only
if (multifile == 0) openfile();
}
/* ---------------------------------------------------------------------- */
void DumpGrid::write_header(bigint ndump)
{
if (multiproc) (this->*header_choice)(ndump);
else if (me == 0) (this->*header_choice)(ndump);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::format_magic_string_binary()
{
// use negative ntimestep as marker for new format
bigint fmtlen = strlen(MAGIC_STRING);
bigint marker = -fmtlen;
fwrite(&marker, sizeof(bigint), 1, fp);
fwrite(MAGIC_STRING, sizeof(char), fmtlen, fp);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::format_endian_binary()
{
int endian = ENDIAN;
fwrite(&endian, sizeof(int), 1, fp);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::format_revision_binary()
{
int revision = FORMAT_REVISION;
fwrite(&revision, sizeof(int), 1, fp);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::header_unit_style_binary()
{
int len = 0;
if (unit_flag && !unit_count) {
++unit_count;
len = strlen(update->unit_style);
fwrite(&len, sizeof(int), 1, fp);
fwrite(update->unit_style, sizeof(char), len, fp);
} else {
fwrite(&len, sizeof(int), 1, fp);
}
}
/* ---------------------------------------------------------------------- */
void DumpGrid::header_columns_binary()
{
int len = strlen(columns);
fwrite(&len, sizeof(int), 1, fp);
fwrite(columns, sizeof(char), len, fp);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::header_time_binary()
{
char flag = time_flag ? 1 : 0;
fwrite(&flag, sizeof(char), 1, fp);
if (time_flag) {
double t = compute_time();
fwrite(&t, sizeof(double), 1, fp);
}
}
/* ---------------------------------------------------------------------- */
void DumpGrid::header_format_binary()
{
format_magic_string_binary();
format_endian_binary();
format_revision_binary();
}
/* ---------------------------------------------------------------------- */
void DumpGrid::header_binary(bigint ndump)
{
header_format_binary();
fwrite(&update->ntimestep,sizeof(bigint),1,fp);
fwrite(&ndump,sizeof(bigint),1,fp);
fwrite(&domain->triclinic,sizeof(int),1,fp);
fwrite(&domain->boundary[0][0],6*sizeof(int),1,fp);
fwrite(&boxxlo,sizeof(double),1,fp);
fwrite(&boxxhi,sizeof(double),1,fp);
fwrite(&boxylo,sizeof(double),1,fp);
fwrite(&boxyhi,sizeof(double),1,fp);
fwrite(&boxzlo,sizeof(double),1,fp);
fwrite(&boxzhi,sizeof(double),1,fp);
fwrite(&nfield,sizeof(int),1,fp);
header_unit_style_binary();
header_time_binary();
header_columns_binary();
if (multiproc) fwrite(&nclusterprocs,sizeof(int),1,fp);
else fwrite(&nprocs,sizeof(int),1,fp);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::header_binary_triclinic(bigint ndump)
{
header_format_binary();
fwrite(&update->ntimestep,sizeof(bigint),1,fp);
fwrite(&ndump,sizeof(bigint),1,fp);
fwrite(&domain->triclinic,sizeof(int),1,fp);
fwrite(&domain->boundary[0][0],6*sizeof(int),1,fp);
fwrite(&boxxlo,sizeof(double),1,fp);
fwrite(&boxxhi,sizeof(double),1,fp);
fwrite(&boxylo,sizeof(double),1,fp);
fwrite(&boxyhi,sizeof(double),1,fp);
fwrite(&boxzlo,sizeof(double),1,fp);
fwrite(&boxzhi,sizeof(double),1,fp);
fwrite(&boxxy,sizeof(double),1,fp);
fwrite(&boxxz,sizeof(double),1,fp);
fwrite(&boxyz,sizeof(double),1,fp);
fwrite(&nfield,sizeof(int),1,fp);
header_unit_style_binary();
header_time_binary();
header_columns_binary();
if (multiproc) fwrite(&nclusterprocs,sizeof(int),1,fp);
else fwrite(&nprocs,sizeof(int),1,fp);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::header_item(bigint ndump)
{
if (unit_flag && !unit_count) {
++unit_count;
fmt::print(fp,"ITEM: UNITS\n{}\n",update->unit_style);
}
if (time_flag) fmt::print(fp,"ITEM: TIME\n{:.16}\n",compute_time());
fmt::print(fp,"ITEM: TIMESTEP\n{}\n"
"ITEM: NUMBER OF ATOMS\n{}\n",
update->ntimestep, ndump);
fmt::print(fp,"ITEM: BOX BOUNDS {}\n"
"{:>1.16e} {:>1.16e}\n"
"{:>1.16e} {:>1.16e}\n"
"{:>1.16e} {:>1.16e}\n",
boundstr,boxxlo,boxxhi,boxylo,boxyhi,boxzlo,boxzhi);
fmt::print(fp,"ITEM: ATOMS {}\n",columns);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::header_item_triclinic(bigint ndump)
{
if (unit_flag && !unit_count) {
++unit_count;
fmt::print(fp,"ITEM: UNITS\n{}\n",update->unit_style);
}
if (time_flag) fmt::print(fp,"ITEM: TIME\n{:.16}\n",compute_time());
fmt::print(fp,"ITEM: TIMESTEP\n{}\n"
"ITEM: NUMBER OF ATOMS\n{}\n",
update->ntimestep, ndump);
fmt::print(fp,"ITEM: BOX BOUNDS xy xz yz {}\n"
"{:>1.16e} {:>1.16e} {:>1.16e}\n"
"{:>1.16e} {:>1.16e} {:>1.16e}\n"
"{:>1.16e} {:>1.16e} {:>1.16e}\n",
boundstr,boxxlo,boxxhi,boxxy,boxylo,boxyhi,boxxz,boxzlo,boxzhi,boxyz);
fmt::print(fp,"ITEM: ATOMS {}\n",columns);
}
/* ---------------------------------------------------------------------- */
int DumpGrid::count()
{
int i;
// grow choose arrays if needed
// NOTE: needs to change
/*
const int nlocal = atom->nlocal;
if (atom->nmax > maxlocal) {
maxlocal = atom->nmax;
memory->destroy(choose);
memory->destroy(dchoose);
memory->destroy(clist);
memory->create(choose,maxlocal,"dump:choose");
memory->create(dchoose,maxlocal,"dump:dchoose");
memory->create(clist,maxlocal,"dump:clist");
}
*/
// invoke Computes for per-grid quantities
// only if within a run or minimize
// else require that computes are current
// this prevents a compute from being invoked by the WriteDump class
if (ncompute) {
if (update->whichflag == 0) {
for (i = 0; i < ncompute; i++)
if (compute[i]->invoked_pergrid != update->ntimestep)
error->all(FLERR,"Compute used in dump between runs is not current");
} else {
for (i = 0; i < ncompute; i++) {
if (!(compute[i]->invoked_flag & Compute::INVOKED_PERGRID)) {
compute[i]->compute_pergrid();
compute[i]->invoked_flag |= Compute::INVOKED_PERGRID;
}
}
}
}
// choose all local grid pts for output
// NOTE: this needs to change
//for (i = 0; i < nlocal; i++) choose[i] = 1;
// un-choose if not in region
// NOTE: this needs to change
if (idregion) {
auto region = domain->get_region_by_id(idregion);
region->prematch();
/*
double **x = atom->x;
for (i = 0; i < nlocal; i++)
if (choose[i] && region->match(x[i][0],x[i][1],x[i][2]) == 0)
choose[i] = 0;
*/
}
// compress choose flags into clist
// nchoose = # of selected atoms
// clist[i] = local index of each selected atom
// NOTE: this neds to change
nchoose = 0;
/*
for (i = 0; i < nlocal; i++)
if (choose[i]) clist[nchoose++] = i;
*/
return nchoose;
}
/* ---------------------------------------------------------------------- */
void DumpGrid::pack(tagint *ids)
{
for (int n = 0; n < size_one; n++) (this->*pack_choice[n])(n);
// NOTE: this needs to be grid IDs ?
/*
if (ids) {
tagint *tag = atom->tag;
for (int i = 0; i < nchoose; i++)
ids[i] = tag[clist[i]];
}
*/
}
/* ----------------------------------------------------------------------
convert mybuf of doubles to one big formatted string in sbuf
return -1 if strlen exceeds an int, since used as arg in MPI calls in Dump
------------------------------------------------------------------------- */
int DumpGrid::convert_string(int n, double *mybuf)
{
int i,j;
int offset = 0;
int m = 0;
for (i = 0; i < n; i++) {
if (offset + nfield*ONEFIELD > maxsbuf) {
if ((bigint) maxsbuf + DELTA > MAXSMALLINT) return -1;
maxsbuf += DELTA;
memory->grow(sbuf,maxsbuf,"dump:sbuf");
}
for (j = 0; j < nfield; j++) {
if (vtype[j] == Dump::INT)
offset += sprintf(&sbuf[offset],vformat[j],static_cast<int> (mybuf[m]));
else if (vtype[j] == Dump::DOUBLE)
offset += sprintf(&sbuf[offset],vformat[j],mybuf[m]);
else if (vtype[j] == Dump::BIGINT)
offset += sprintf(&sbuf[offset],vformat[j],
static_cast<bigint> (mybuf[m]));
m++;
}
offset += sprintf(&sbuf[offset],"\n");
}
return offset;
}
/* ---------------------------------------------------------------------- */
void DumpGrid::write_data(int n, double *mybuf)
{
(this->*write_choice)(n,mybuf);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::write_binary(int n, double *mybuf)
{
n *= size_one;
fwrite(&n,sizeof(int),1,fp);
fwrite(mybuf,sizeof(double),n,fp);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::write_string(int n, double *mybuf)
{
if (mybuf)
fwrite(mybuf,sizeof(char),n,fp);
}
/* ---------------------------------------------------------------------- */
void DumpGrid::write_lines(int n, double *mybuf)
{
int i,j;
int m = 0;
for (i = 0; i < n; i++) {
for (j = 0; j < nfield; j++) {
if (vtype[j] == Dump::INT) fprintf(fp,vformat[j],static_cast<int> (mybuf[m]));
else if (vtype[j] == Dump::DOUBLE) fprintf(fp,vformat[j],mybuf[m]);
else if (vtype[j] == Dump::BIGINT)
fprintf(fp,vformat[j],static_cast<bigint> (mybuf[m]));
m++;
}
fprintf(fp,"\n");
}
}
/* ---------------------------------------------------------------------- */
int DumpGrid::parse_fields(int narg, char **arg)
{
// customize by adding to if statement
for (int iarg = 0; iarg < narg; iarg++) {
int n,flag,cols;
ArgInfo argi(arg[iarg], ArgInfo::COMPUTE | ArgInfo::FIX);
argindex[iarg] = argi.get_index1();
auto name = argi.get_name();
Compute *icompute = nullptr;
Fix *ifix = nullptr;
switch (argi.get_type()) {
case ArgInfo::UNKNOWN:
error->all(FLERR,"Invalid attribute in dump grid command");
break;
// compute value = c_ID
// if no trailing [], then arg is set to 0, else arg is int between []
case ArgInfo::COMPUTE:
pack_choice[iarg] = &DumpGrid::pack_compute;
vtype[iarg] = Dump::DOUBLE;
icompute = modify->get_compute_by_id(name);
if (!icompute) error->all(FLERR,"Could not find dump grid compute ID: {}",name);
if (icompute->pergrid_flag == 0)
error->all(FLERR,"Dump grid compute {} does not compute per-grid info",name);
/*
if (argi.get_dim() == 0 && icompute->size_pergrid_cols > 0)
error->all(FLERR,"Dump grid compute {} does not calculate per-grid vector",name);
if (argi.get_dim() > 0 && icompute->size_pergrid_cols == 0)
error->all(FLERR,"Dump grid compute {} does not calculate per-grid array",name);
if (argi.get_dim() > 0 && argi.get_index1() > icompute->size_pergrid_cols)
error->all(FLERR,"Dump grid compute {} vector is accessed out-of-range",name);
*/
field2index[iarg] = add_compute(name);
break;
// fix value = f_ID
// if no trailing [], then arg is set to 0, else arg is between []
case ArgInfo::FIX:
pack_choice[iarg] = &DumpGrid::pack_fix;
vtype[iarg] = Dump::DOUBLE;
ifix = modify->get_fix_by_id(name);
if (!ifix) error->all(FLERR,"Could not find dump grid fix ID: {}",name);
if (ifix->pergrid_flag == 0)
error->all(FLERR,"Dump grid fix {} does not compute per-atom info",name);
/*
if (argi.get_dim() == 0 && ifix->size_pergrid_cols > 0)
error->all(FLERR,"Dump grid fix {} does not compute per-atom vector",name);
if (argi.get_dim() > 0 && ifix->size_pergrid_cols == 0)
error->all(FLERR,"Dump grid fix {} does not compute per-atom array",name);
if (argi.get_dim() > 0 && argi.get_index1() > ifix->size_pergrid_cols)
error->all(FLERR,"Dump grid fix {} vector is accessed out-of-range",name);
*/
field2index[iarg] = add_fix(name);
break;
// no match
default:
return iarg;
break;
}
}
return narg;
}
/* ----------------------------------------------------------------------
add Compute to list of Compute objects used by dump
return index of where this Compute is in list
if already in list, do not add, just return index, else add to list
------------------------------------------------------------------------- */
int DumpGrid::add_compute(const char *id)
{
int icompute;
for (icompute = 0; icompute < ncompute; icompute++)
if (strcmp(id,id_compute[icompute]) == 0) break;
if (icompute < ncompute) return icompute;
id_compute = (char **)
memory->srealloc(id_compute,(ncompute+1)*sizeof(char *),"dump:id_compute");
delete[] compute;
compute = new Compute*[ncompute+1];
id_compute[ncompute] = utils::strdup(id);
ncompute++;
return ncompute-1;
}
/* ----------------------------------------------------------------------
add Fix to list of Fix objects used by dump
return index of where this Fix is in list
if already in list, do not add, just return index, else add to list
------------------------------------------------------------------------- */
int DumpGrid::add_fix(const char *id)
{
int ifix;
for (ifix = 0; ifix < nfix; ifix++)
if (strcmp(id,id_fix[ifix]) == 0) break;
if (ifix < nfix) return ifix;
id_fix = (char **)
memory->srealloc(id_fix,(nfix+1)*sizeof(char *),"dump:id_fix");
delete[] fix;
fix = new Fix*[nfix+1];
id_fix[nfix] = utils::strdup(id);
nfix++;
return nfix-1;
}
/* ---------------------------------------------------------------------- */
int DumpGrid::modify_param(int narg, char **arg)
{
if (strcmp(arg[0],"region") == 0) {
if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"none") == 0) {
delete[] idregion;
idregion = nullptr;
} else {
delete[] idregion;
if (!domain->get_region_by_id(arg[1]))
error->all(FLERR,"Dump_modify region {} does not exist", arg[1]);
idregion = utils::strdup(arg[1]);
}
return 2;
}
if (strcmp(arg[0],"format") == 0) {
if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"none") == 0) {
// just clear format_column_user allocated by this dump child class
for (int i = 0; i < nfield; i++) {
delete[] format_column_user[i];
format_column_user[i] = nullptr;
}
return 2;
}
if (narg < 3) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"int") == 0) {
delete[] format_int_user;
format_int_user = utils::strdup(arg[2]);
delete[] format_bigint_user;
int n = strlen(format_int_user) + 8;
format_bigint_user = new char[n];
// replace "d" in format_int_user with bigint format specifier
// use of &str[1] removes leading '%' from BIGINT_FORMAT string
char *ptr = strchr(format_int_user,'d');
if (ptr == nullptr)
error->all(FLERR,"Dump_modify int format does not contain d character");
char str[8];
sprintf(str,"%s",BIGINT_FORMAT);
*ptr = '\0';
sprintf(format_bigint_user,"%s%s%s",format_int_user,&str[1],ptr+1);
*ptr = 'd';
} else if (strcmp(arg[1],"float") == 0) {
delete[] format_float_user;
format_float_user = utils::strdup(arg[2]);
} else {
int i = utils::inumeric(FLERR,arg[1],false,lmp) - 1;
if (i < 0 || i >= nfield)
error->all(FLERR,"Illegal dump_modify command");
delete[] format_column_user[i];
format_column_user[i] = utils::strdup(arg[2]);
}
return 3;
}
return 0;
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory in buf, choose, variable arrays
------------------------------------------------------------------------- */
double DumpGrid::memory_usage()
{
double bytes = Dump::memory_usage();
bytes += memory->usage(choose,maxlocal);
bytes += memory->usage(dchoose,maxlocal);
bytes += memory->usage(clist,maxlocal);
return bytes;
}
/* ----------------------------------------------------------------------
extraction of Compute and Fix data
------------------------------------------------------------------------- */
void DumpGrid::pack_compute(int n)
{
double *vector = compute[field2index[n]]->vector_atom;
double **array = compute[field2index[n]]->array_atom;
int index = argindex[n];
if (index == 0) {
for (int i = 0; i < nchoose; i++) {
buf[n] = vector[clist[i]];
n += size_one;
}
} else {
index--;
for (int i = 0; i < nchoose; i++) {
buf[n] = array[clist[i]][index];
n += size_one;
}
}
}
/* ---------------------------------------------------------------------- */
void DumpGrid::pack_fix(int n)
{
double *vector = fix[field2index[n]]->vector_atom;
double **array = fix[field2index[n]]->array_atom;
int index = argindex[n];
if (index == 0) {
for (int i = 0; i < nchoose; i++) {
buf[n] = vector[clist[i]];
n += size_one;
}
} else {
index--;
for (int i = 0; i < nchoose; i++) {
buf[n] = array[clist[i]][index];
n += size_one;
}
}
}