Page MenuHomec4science

dump.cpp
No OneTemporary

File Metadata

Created
Mon, Oct 7, 16:15

dump.cpp

/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, 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 "mpi.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "dump.h"
#include "atom.h"
#include "update.h"
#include "group.h"
#include "output.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
Dump::Dump(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
{
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
int n = strlen(arg[0]) + 1;
id = new char[n];
strcpy(id,arg[0]);
igroup = group->find(arg[1]);
groupbit = group->bitmask[igroup];
n = strlen(arg[2]) + 1;
style = new char[n];
strcpy(style,arg[2]);
n = strlen(arg[4]) + 1;
filename = new char[n];
strcpy(filename,arg[4]);
flush_flag = 1;
format = NULL;
format_user = NULL;
maxbuf = 0;
buf = NULL;
// parse filename for special syntax
// if contains '%', write one file per proc and replace % with proc-ID
// if contains '*', write one file per timestep and replace * with timestep
// check file suffixes
// if ends in .bin = binary file
// else if ends in .gz = gzipped text file
// else ASCII text file
compressed = 0;
binary = 0;
multifile = 0;
multiproc = 0;
char *ptr;
if (ptr = strchr(filename,'%')) {
multiproc = 1;
char *extend = new char[strlen(filename) + 16];
*ptr = '\0';
sprintf(extend,"%s%d%s",filename,me,ptr+1);
delete [] filename;
n = strlen(extend) + 1;
filename = new char[n];
strcpy(filename,extend);
delete [] extend;
}
if (strchr(filename,'*')) multifile = 1;
char *suffix = filename + strlen(filename) - strlen(".bin");
if (suffix > filename && strcmp(suffix,".bin") == 0) binary = 1;
suffix = filename + strlen(filename) - strlen(".gz");
if (suffix > filename && strcmp(suffix,".gz") == 0) compressed = 1;
}
/* ---------------------------------------------------------------------- */
Dump::~Dump()
{
delete [] id;
delete [] style;
delete [] filename;
delete [] format;
delete [] format_default;
delete [] format_user;
memory->sfree(buf);
// XTC style sets fp to NULL since it closes file in its destructor
if (multifile == 0 && fp != NULL) {
if (multiproc) fclose(fp);
else if (me == 0) fclose(fp);
}
}
/* ---------------------------------------------------------------------- */
void Dump::write()
{
// if file per timestep, open new file
if (multifile) openfile();
// nme = # of dump lines this proc will contribute to dump
// ntotal = total # of dump lines
// nmax = max # of dump lines on any proc
int nme = count();
int ntotal,nmax;
if (multiproc) nmax = nme;
else {
MPI_Allreduce(&nme,&ntotal,1,MPI_INT,MPI_SUM,world);
MPI_Allreduce(&nme,&nmax,1,MPI_INT,MPI_MAX,world);
}
// write timestep header
if (multiproc) write_header(nme);
else if (me == 0) write_header(ntotal);
// grow communication buffer if necessary
if (nmax*size_one > maxbuf) {
maxbuf = nmax*size_one;
memory->sfree(buf);
buf = (double *) memory->smalloc(maxbuf*sizeof(double),"dump:buf");
}
// pack my data into buf
// send_size = # of quantities in buf
int me_size = pack();
// 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);
else {
int tmp,nlines;
MPI_Status status;
MPI_Request request;
if (me == 0) {
for (int iproc = 0; iproc < nprocs; iproc++) {
if (iproc) {
MPI_Irecv(buf,maxbuf,MPI_DOUBLE,iproc,0,world,&request);
MPI_Send(&tmp,0,MPI_INT,iproc,0,world);
MPI_Wait(&request,&status);
MPI_Get_count(&status,MPI_DOUBLE,&nlines);
nlines /= size_one;
} else nlines = me_size/size_one;
write_data(nlines,buf);
}
if (flush_flag) fflush(fp);
} else {
MPI_Recv(&tmp,0,MPI_INT,0,0,world,&status);
MPI_Rsend(buf,me_size,MPI_DOUBLE,0,0,world);
}
}
// if file per timestep, close file
if (multifile) {
if (multiproc) fclose(fp);
else if (me == 0) fclose(fp);
}
}
/* ----------------------------------------------------------------------
process params common to all dumps here
if unknown param, call modify_param specific to the dump
------------------------------------------------------------------------- */
void Dump::modify_params(int narg, char **arg)
{
if (narg == 0) error->all("Illegal dump_modify command");
int iarg = 0;
while (iarg < narg) {
if (strcmp(arg[iarg],"format") == 0) {
if (iarg+2 > narg) error->all("Illegal dump_modify command");
delete [] format_user;
format_user = NULL;
if (strcmp(arg[iarg+1],"none")) {
int n = strlen(arg[iarg+1]) + 1;
format_user = new char[n];
strcpy(format_user,arg[iarg+1]);
}
iarg += 2;
} else if (strcmp(arg[iarg],"flush") == 0) {
if (iarg+2 > narg) error->all("Illegal dump_modify command");
if (strcmp(arg[iarg+1],"yes") == 0) flush_flag = 1;
else if (strcmp(arg[iarg+1],"no") == 0) flush_flag = 0;
else error->all("Illegal dump_modify command");
iarg += 2;
} else if (strcmp(arg[iarg],"every") == 0) {
if (iarg+2 > narg) error->all("Illegal dump_modify command");
int n = atoi(arg[iarg+1]);
if (n <= 0) error->all("Illegal dump_modify command");
int idump;
for (idump = 0; idump < output->ndump; idump++)
if (strcmp(id,output->dump[idump]->id) == 0) break;
output->dump_every[idump] = n;
iarg += 2;
} else {
int n = modify_param(narg-iarg,&arg[iarg]);
if (n == 0) error->all("Illegal dump_modify command");
iarg += n;
}
}
}
/* ----------------------------------------------------------------------
return # of bytes of allocated memory in buf
------------------------------------------------------------------------- */
int Dump::memory_usage()
{
int bytes = maxbuf * sizeof(double);
return bytes;
}
/* ----------------------------------------------------------------------
generic opening of a dump file
ASCII or binary or gzipped
some derived classes override this function
------------------------------------------------------------------------- */
void Dump::openfile()
{
// 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 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 {
fp = fopen(filecurrent,"w");
}
if (fp == NULL) error->one("Cannot open dump file");
}
// delete string with timestep replaced
if (multifile) delete [] filecurrent;
}

Event Timeline