git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@4795 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
383
src/dump.cpp
383
src/dump.cpp
@ -17,6 +17,7 @@
|
||||
#include "stdio.h"
|
||||
#include "dump.h"
|
||||
#include "atom.h"
|
||||
#include "irregular.h"
|
||||
#include "update.h"
|
||||
#include "domain.h"
|
||||
#include "group.h"
|
||||
@ -26,6 +27,17 @@
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
// allocate space for static class variable
|
||||
|
||||
Dump *Dump::dumpptr;
|
||||
|
||||
#define BIG 1.0e20
|
||||
#define IBIG 2147483647
|
||||
#define EPSILON 1.0e-6
|
||||
|
||||
#define MIN(A,B) ((A) < (B)) ? (A) : (B)
|
||||
#define MAX(A,B) ((A) > (B)) ? (A) : (B)
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
Dump::Dump(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
|
||||
@ -56,8 +68,10 @@ Dump::Dump(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
|
||||
sort_flag = 0;
|
||||
append_flag = 0;
|
||||
|
||||
maxbuf = 0;
|
||||
buf = NULL;
|
||||
maxbuf = maxsort = maxproc = 0;
|
||||
buf = bufsort = NULL;
|
||||
idsort = index = proclist = NULL;
|
||||
irregular = NULL;
|
||||
|
||||
// parse filename for special syntax
|
||||
// if contains '%', write one file per proc and replace % with proc-ID
|
||||
@ -108,6 +122,11 @@ Dump::~Dump()
|
||||
delete [] format_user;
|
||||
|
||||
memory->sfree(buf);
|
||||
memory->sfree(bufsort);
|
||||
memory->sfree(idsort);
|
||||
memory->sfree(index);
|
||||
memory->sfree(proclist);
|
||||
delete irregular;
|
||||
|
||||
// XTC style sets fp to NULL since it closes file in its destructor
|
||||
|
||||
@ -124,6 +143,36 @@ Dump::~Dump()
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void Dump::init()
|
||||
{
|
||||
init_style();
|
||||
|
||||
if (!sort_flag) {
|
||||
memory->sfree(buf);
|
||||
memory->sfree(bufsort);
|
||||
memory->sfree(idsort);
|
||||
memory->sfree(index);
|
||||
memory->sfree(proclist);
|
||||
delete irregular;
|
||||
|
||||
maxbuf = maxsort = maxproc = 0;
|
||||
buf = bufsort = NULL;
|
||||
idsort = index = proclist = NULL;
|
||||
irregular = NULL;
|
||||
}
|
||||
|
||||
if (sort_flag && sortcol == 0 && atom->tag_enable == 0)
|
||||
error->all("Cannot use dump sort on atom IDs with no atom IDs defined");
|
||||
|
||||
if (sort_flag && sortcol > size_one)
|
||||
error->all("Dump sort column is invalid");
|
||||
|
||||
if (sort_flag && nprocs > 1 && irregular == NULL)
|
||||
irregular = new Irregular(lmp);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void Dump::write()
|
||||
{
|
||||
// if file per timestep, open new file
|
||||
@ -152,11 +201,12 @@ void Dump::write()
|
||||
}
|
||||
|
||||
// nme = # of dump lines this proc will contribute to dump
|
||||
|
||||
nme = count();
|
||||
|
||||
// ntotal = total # of dump lines
|
||||
// nmax = max # of dump lines on any proc
|
||||
|
||||
int nme = count();
|
||||
|
||||
int ntotal,nmax;
|
||||
if (multiproc) nmax = nme;
|
||||
else {
|
||||
@ -169,25 +219,31 @@ void Dump::write()
|
||||
if (multiproc) write_header(nme);
|
||||
else write_header(ntotal);
|
||||
|
||||
// grow communication buffer if necessary
|
||||
// pack my data into buf
|
||||
// if sorting on IDs also request ID list from pack()
|
||||
// sort buf as needed
|
||||
|
||||
if (nmax*size_one > maxbuf) {
|
||||
maxbuf = nmax*size_one;
|
||||
if (nmax > maxbuf) {
|
||||
maxbuf = nmax;
|
||||
memory->sfree(buf);
|
||||
buf = (double *) memory->smalloc(maxbuf*sizeof(double),"dump:buf");
|
||||
buf = (double *)
|
||||
memory->smalloc(maxbuf*size_one*sizeof(double),"dump:buf");
|
||||
if (sort_flag && sortcol == 0) {
|
||||
memory->sfree(ids);
|
||||
ids = (int *) memory->smalloc(maxbuf*sizeof(int),"dump:ids");
|
||||
}
|
||||
}
|
||||
|
||||
// pack my data into buf
|
||||
// me_size = # of quantities in buf
|
||||
|
||||
int me_size = pack();
|
||||
if (sort_flag && sortcol == 0) pack(ids);
|
||||
else pack(NULL);
|
||||
if (sort_flag) sort();
|
||||
|
||||
// multiproc = 1 = each proc writes own data to own file
|
||||
// multiproc = 0 = all procs write to one file thru proc 0
|
||||
// proc 0 pings each proc, receives it's data, writes to file
|
||||
// all other procs wait for ping, send their data to proc 0
|
||||
|
||||
if (multiproc) write_data(me_size/size_one,buf);
|
||||
if (multiproc) write_data(nme,buf);
|
||||
else {
|
||||
int tmp,nlines;
|
||||
MPI_Status status;
|
||||
@ -201,7 +257,7 @@ void Dump::write()
|
||||
MPI_Wait(&request,&status);
|
||||
MPI_Get_count(&status,MPI_DOUBLE,&nlines);
|
||||
nlines /= size_one;
|
||||
} else nlines = me_size/size_one;
|
||||
} else nlines = nme;
|
||||
|
||||
write_data(nlines,buf);
|
||||
}
|
||||
@ -209,7 +265,7 @@ void Dump::write()
|
||||
|
||||
} else {
|
||||
MPI_Recv(&tmp,0,MPI_INT,0,0,world,&status);
|
||||
MPI_Rsend(buf,me_size,MPI_DOUBLE,0,0,world);
|
||||
MPI_Rsend(buf,nme*size_one,MPI_DOUBLE,0,0,world);
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,6 +282,229 @@ void Dump::write()
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
generic opening of a dump file
|
||||
ASCII or binary or gzipped
|
||||
some derived classes override this function
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Dump::openfile()
|
||||
{
|
||||
// single file, already opened, so just return
|
||||
|
||||
if (singlefile_opened) return;
|
||||
if (multifile == 0) singlefile_opened = 1;
|
||||
|
||||
// if one file per timestep, replace '*' with current timestep
|
||||
|
||||
char *filecurrent;
|
||||
if (multifile == 0) filecurrent = filename;
|
||||
else {
|
||||
filecurrent = new char[strlen(filename) + 16];
|
||||
char *ptr = strchr(filename,'*');
|
||||
*ptr = '\0';
|
||||
sprintf(filecurrent,"%s%d%s",filename,update->ntimestep,ptr+1);
|
||||
*ptr = '*';
|
||||
}
|
||||
|
||||
// open one file on proc 0 or file on every proc
|
||||
|
||||
if (me == 0 || multiproc) {
|
||||
if (compressed) {
|
||||
#ifdef LAMMPS_GZIP
|
||||
char gzip[128];
|
||||
sprintf(gzip,"gzip -6 > %s",filecurrent);
|
||||
fp = popen(gzip,"w");
|
||||
#else
|
||||
error->one("Cannot open gzipped file");
|
||||
#endif
|
||||
} else if (binary) {
|
||||
fp = fopen(filecurrent,"wb");
|
||||
} else if (append_flag) {
|
||||
fp = fopen(filecurrent,"a");
|
||||
} else {
|
||||
fp = fopen(filecurrent,"w");
|
||||
}
|
||||
|
||||
if (fp == NULL) error->one("Cannot open dump file");
|
||||
} else fp = NULL;
|
||||
|
||||
// delete string with timestep replaced
|
||||
|
||||
if (multifile) delete [] filecurrent;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
parallel sort of buf across all procs
|
||||
changes nme, reorders datums in buf, grows buf if necessary
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Dump::sort()
|
||||
{
|
||||
int i,iproc;
|
||||
double value;
|
||||
|
||||
// if single proc, swap ptrs to buf,ids <-> bufsort,idsort
|
||||
|
||||
if (nprocs == 1) {
|
||||
if (nme > maxsort) {
|
||||
maxsort = nme;
|
||||
memory->sfree(bufsort);
|
||||
bufsort = (double *)
|
||||
memory->smalloc(maxsort*size_one*sizeof(double),"dump:bufsort");
|
||||
memory->sfree(index);
|
||||
index = (int *) memory->smalloc(maxsort*sizeof(int),"dump:index");
|
||||
if (sortcol == 0) {
|
||||
memory->sfree(idsort);
|
||||
idsort = (int *) memory->smalloc(maxsort*sizeof(int),"dump:idsort");
|
||||
}
|
||||
}
|
||||
|
||||
double *dptr = buf;
|
||||
buf = bufsort;
|
||||
bufsort = dptr;
|
||||
|
||||
if (sortcol == 0) {
|
||||
int *iptr = ids;
|
||||
ids = idsort;
|
||||
idsort = iptr;
|
||||
}
|
||||
|
||||
// if multiple procs, exchange datums between procs via irregular
|
||||
|
||||
} else {
|
||||
|
||||
// grow proclist if necessary
|
||||
|
||||
if (nme > maxproc) {
|
||||
maxproc = nme;
|
||||
memory->sfree(proclist);
|
||||
proclist = (int *) memory->smalloc(maxproc*sizeof(int),"dump:proclist");
|
||||
}
|
||||
|
||||
// proclist[i] = which proc Ith datum will be sent to
|
||||
|
||||
if (sortcol == 0) {
|
||||
int min = IBIG;
|
||||
int max = 0;
|
||||
for (i = 0; i < nme; i++) {
|
||||
min = MIN(min,ids[i]);
|
||||
max = MAX(max,ids[i]);
|
||||
}
|
||||
int minall,maxall;
|
||||
MPI_Allreduce(&min,&minall,1,MPI_INT,MPI_MIN,world);
|
||||
MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world);
|
||||
double range = maxall - minall + 0.1;
|
||||
for (i = 0; i < nme; i++) {
|
||||
iproc = static_cast<int> ((ids[i]-minall)/range * nprocs);
|
||||
proclist[i] = iproc;
|
||||
}
|
||||
|
||||
} else {
|
||||
double min = BIG;
|
||||
double max = -BIG;
|
||||
for (i = 0; i < nme; i++) {
|
||||
value = buf[i*size_one + sortcolm1];
|
||||
min = MIN(min,value);
|
||||
max = MAX(max,value);
|
||||
}
|
||||
double minall,maxall;
|
||||
MPI_Allreduce(&min,&minall,1,MPI_DOUBLE,MPI_MIN,world);
|
||||
MPI_Allreduce(&max,&maxall,1,MPI_DOUBLE,MPI_MAX,world);
|
||||
double range = maxall-minall + EPSILON*(maxall-minall);
|
||||
if (range == 0.0) range = EPSILON;
|
||||
for (i = 0; i < nme; i++) {
|
||||
value = buf[i*size_one + sortcolm1];
|
||||
iproc = static_cast<int> ((value-minall)/range * nprocs);
|
||||
proclist[i] = iproc;
|
||||
}
|
||||
}
|
||||
|
||||
// create comm plan, grow recv bufs if necessary,
|
||||
// exchange datums, destroy plan
|
||||
// if sorting on atom IDs, exchange IDs also
|
||||
|
||||
nme = irregular->create_data(nme,proclist);
|
||||
|
||||
if (nme > maxsort) {
|
||||
maxsort = nme;
|
||||
memory->sfree(bufsort);
|
||||
bufsort = (double *)
|
||||
memory->smalloc(maxsort*size_one*sizeof(double),"dump:bufsort");
|
||||
memory->sfree(index);
|
||||
index = (int *) memory->smalloc(maxsort*sizeof(int),"dump:index");
|
||||
if (sortcol == 0) {
|
||||
memory->sfree(idsort);
|
||||
idsort = (int *) memory->smalloc(maxsort*sizeof(int),"dump:idsort");
|
||||
}
|
||||
}
|
||||
|
||||
irregular->exchange_data((char *) buf,size_one*sizeof(double),
|
||||
(char *) bufsort);
|
||||
if (sortcol == 0)
|
||||
irregular->exchange_data((char *) ids,sizeof(int),(char *) idsort);
|
||||
irregular->destroy_data();
|
||||
}
|
||||
|
||||
// quicksort indices using IDs or buf column as comparator
|
||||
|
||||
dumpptr = this;
|
||||
for (i = 0; i < nme; i++) index[i] = i;
|
||||
if (sortcol == 0) qsort(index,nme,sizeof(int),idcompare);
|
||||
else qsort(index,nme,sizeof(int),bufcompare);
|
||||
|
||||
// copy data from bufsort to buf using index
|
||||
|
||||
if (nme > maxbuf) {
|
||||
maxbuf = nme;
|
||||
memory->sfree(buf);
|
||||
buf = (double *)
|
||||
memory->smalloc(maxbuf*size_one*sizeof(double),"dump:buf");
|
||||
}
|
||||
|
||||
int nbytes = size_one*sizeof(double);
|
||||
for (i = 0; i < nme; i++)
|
||||
memcpy(&buf[i*size_one],&bufsort[index[i]*size_one],nbytes);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
compare two atom IDs in sort data structure
|
||||
called via qsort_r in sort() method
|
||||
is a static method so access sort data structure via ptr
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int Dump::idcompare(const void *pi, const void *pj)
|
||||
{
|
||||
int *idsort = dumpptr->idsort;
|
||||
|
||||
int i = *((int *) pi);
|
||||
int j = *((int *) pj);
|
||||
|
||||
if (idsort[i] < idsort[j]) return -1;
|
||||
if (idsort[i] > idsort[j]) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
compare two buffer quantities in sort data structure with size_one stride
|
||||
called via qsort_r in sort() method
|
||||
is a static method so access sort data structure via ptr
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int Dump::bufcompare(const void *pi, const void *pj)
|
||||
{
|
||||
double *bufsort = dumpptr->bufsort;
|
||||
int size_one = dumpptr->size_one;
|
||||
int sortcolm1 = dumpptr->sortcolm1;
|
||||
|
||||
int i = *((int *) pi)*size_one + sortcolm1;
|
||||
int j = *((int *) pj)*size_one + sortcolm1;
|
||||
|
||||
if (bufsort[i] < bufsort[j]) return -1;
|
||||
if (bufsort[i] > bufsort[j]) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
process params common to all dumps here
|
||||
if unknown param, call modify_param specific to the dump
|
||||
@ -285,9 +564,13 @@ void Dump::modify_params(int narg, char **arg)
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"sort") == 0) {
|
||||
if (iarg+2 > narg) error->all("Illegal dump_modify command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) sort_flag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) sort_flag = 0;
|
||||
else error->all("Illegal dump_modify command");
|
||||
if (strcmp(arg[iarg+1],"off") == 0) sort_flag = 0;
|
||||
else {
|
||||
sort_flag = 1;
|
||||
sortcol = atoi(arg[iarg+1]);
|
||||
if (sortcol < 0) error->all("Illegal dump_modify command");
|
||||
sortcolm1 = sortcol - 1;
|
||||
}
|
||||
iarg += 2;
|
||||
} else {
|
||||
int n = modify_param(narg-iarg,&arg[iarg]);
|
||||
@ -298,63 +581,19 @@ void Dump::modify_params(int narg, char **arg)
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
return # of bytes of allocated memory in buf
|
||||
return # of bytes of allocated memory
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double Dump::memory_usage()
|
||||
{
|
||||
double bytes = maxbuf * sizeof(double);
|
||||
double bytes = maxbuf*size_one * sizeof(double);
|
||||
if (sort_flag) {
|
||||
if (sortcol == 0) bytes += maxbuf * sizeof(int); // ids
|
||||
bytes += maxsort*size_one * sizeof(double); // bufsort
|
||||
bytes += maxsort * sizeof(int); // index
|
||||
if (sortcol == 0) bytes += maxsort * sizeof(int); // idsort
|
||||
bytes += maxproc * sizeof(int); // proclist
|
||||
if (irregular) bytes += irregular->memory_usage();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
generic opening of a dump file
|
||||
ASCII or binary or gzipped
|
||||
some derived classes override this function
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void Dump::openfile()
|
||||
{
|
||||
// single file, already opened, so just return
|
||||
|
||||
if (singlefile_opened) return;
|
||||
if (multifile == 0) singlefile_opened = 1;
|
||||
|
||||
// if one file per timestep, replace '*' with current timestep
|
||||
|
||||
char *filecurrent;
|
||||
if (multifile == 0) filecurrent = filename;
|
||||
else {
|
||||
filecurrent = new char[strlen(filename) + 16];
|
||||
char *ptr = strchr(filename,'*');
|
||||
*ptr = '\0';
|
||||
sprintf(filecurrent,"%s%d%s",filename,update->ntimestep,ptr+1);
|
||||
*ptr = '*';
|
||||
}
|
||||
|
||||
// open one file on proc 0 or file on every proc
|
||||
|
||||
if (me == 0 || multiproc) {
|
||||
if (compressed) {
|
||||
#ifdef LAMMPS_GZIP
|
||||
char gzip[128];
|
||||
sprintf(gzip,"gzip -6 > %s",filecurrent);
|
||||
fp = popen(gzip,"w");
|
||||
#else
|
||||
error->one("Cannot open gzipped file");
|
||||
#endif
|
||||
} else if (binary) {
|
||||
fp = fopen(filecurrent,"wb");
|
||||
} else if (append_flag) {
|
||||
fp = fopen(filecurrent,"a");
|
||||
} else {
|
||||
fp = fopen(filecurrent,"w");
|
||||
}
|
||||
|
||||
if (fp == NULL) error->one("Cannot open dump file");
|
||||
} else fp = NULL;
|
||||
|
||||
// delete string with timestep replaced
|
||||
|
||||
if (multifile) delete [] filecurrent;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user