lammps/tools/binary2txt.cpp

263 lines
7.3 KiB
C++

/* -----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/
Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
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.
------------------------------------------------------------------------ */
// Convert one or more LAMMPS binary dump files to ASCII text files
//
// this serial code must be compiled on a platform that can read the binary
// dump files since binary formats are not compatible across all platforms
//
// Syntax: binary2txt file1 file2 ...
// Creates: file1.txt file2.txt ...
#include <stdio.h>
#include <string.h>
// these must match settings in src/lmptype.h which builds LAMMPS with
// -DLAMMPS_SMALLBIG (the default), -DLAMMPS_BIGBIG, or -DLAMMPS_SMALLSMALL
// you can edit the tools/Makefile to enforce the same setting
// for the build of binary2txt, e.g.
// g++ -g -DLAMMPS_BIGBIG binarytxt.o -o binary2txt
// again -DLAMMPS_SMALLBIG is the default
#include "stdint.h"
#define __STDC_FORMAT_MACROS
#include "inttypes.h"
#ifndef PRId64
#define PRId64 "ld"
#endif
#if !defined(LAMMPS_SMALLSMALL) && !defined(LAMMPS_BIGBIG) && !defined(LAMMPS_SMALLBIG)
#define LAMMPS_SMALLBIG
#endif
#if defined(LAMMPS_SMALLBIG)
typedef int tagint;
typedef int64_t bigint;
#define BIGINT_FORMAT "%" PRId64
#elif defined(LAMMPS_SMALLSMALL)
typedef int tagint;
typedef int bigint;
#define BIGINT_FORMAT "%d"
#else /* LAMMPS_BIGBIG */
typedef int64_t tagint;
typedef int64_t bigint;
#define BIGINT_FORMAT "%" PRId64
#endif
int main(int narg, char **arg)
{
int i,j,k,m,n;
bigint ntimestep,natoms;
int size_one,nchunk,triclinic;
double xlo,xhi,ylo,yhi,zlo,zhi,xy,xz,yz;
int boundary[3][2];
char boundstr[9];
int maxbuf = 0;
double *buf = NULL;
if (narg == 1) {
printf("Syntax: binary2txt file1 file2 ...\n");
return 1;
}
// loop over files
for (int iarg = 1; iarg < narg; iarg++) {
printf("%s:",arg[iarg]);
fflush(stdout);
FILE *fp = fopen(arg[iarg],"rb");
if (!fp) {
printf("ERROR: Could not open %s\n",arg[iarg]);
return 1;
}
n = strlen(arg[iarg]) + 1 + 4;
char *filetxt = new char[n];
strcpy(filetxt,arg[iarg]);
strcat(filetxt,".txt");
FILE *fptxt = fopen(filetxt,"w");
delete [] filetxt;
// detect newer format
char * magic_string = nullptr;
char * columns = nullptr;
char * unit_style = nullptr;
// loop over snapshots in file
while (1) {
int endian = 0x0001;
int revision = 0x0001;
fread(&ntimestep,sizeof(bigint),1,fp);
// detect end-of-file
if (feof(fp)) {
fclose(fp);
fclose(fptxt);
break;
}
// detect newer format
if (ntimestep < 0) {
// first bigint encodes negative format name length
bigint magic_string_len = -ntimestep;
delete [] magic_string;
magic_string = new char[magic_string_len + 1];
fread(magic_string, sizeof(char), magic_string_len, fp);
magic_string[magic_string_len] = '\0';
// read endian flag
fread(&endian, sizeof(int), 1, fp);
// read revision number
fread(&revision, sizeof(int), 1, fp);
// read the real ntimestep
fread(&ntimestep,sizeof(bigint),1,fp);
}
fread(&natoms,sizeof(bigint),1,fp);
fread(&triclinic,sizeof(int),1,fp);
fread(&boundary[0][0],6*sizeof(int),1,fp);
fread(&xlo,sizeof(double),1,fp);
fread(&xhi,sizeof(double),1,fp);
fread(&ylo,sizeof(double),1,fp);
fread(&yhi,sizeof(double),1,fp);
fread(&zlo,sizeof(double),1,fp);
fread(&zhi,sizeof(double),1,fp);
if (triclinic) {
fread(&xy,sizeof(double),1,fp);
fread(&xz,sizeof(double),1,fp);
fread(&yz,sizeof(double),1,fp);
}
fread(&size_one,sizeof(int),1,fp);
if (magic_string && revision > 0x0001) {
// newer format includes units string, columns string
// and time
int len = 0;
fread(&len, sizeof(int), 1, fp);
if (len > 0) {
// has units
delete [] unit_style;
unit_style = new char[len+1];
fread(unit_style, sizeof(char), len, fp);
unit_style[len] = '\0';
fprintf(fptxt, "ITEM: UNITS\n");
fprintf(fptxt, "%s\n", unit_style);
}
char flag = 0;
fread(&flag, sizeof(char), 1, fp);
if (flag) {
double time;
fread(&time, sizeof(double), 1, fp);
fprintf(fptxt, "ITEM: TIME\n%.16g\n", time);
}
fread(&len, sizeof(int), 1, fp);
delete [] columns;
columns = new char[len+1];
fread(columns, sizeof(char), len, fp);
columns[len] = '\0';
}
fread(&nchunk,sizeof(int),1,fp);
fprintf(fptxt,"ITEM: TIMESTEP\n");
fprintf(fptxt,BIGINT_FORMAT "\n",ntimestep);
fprintf(fptxt,"ITEM: NUMBER OF ATOMS\n");
fprintf(fptxt,BIGINT_FORMAT "\n",natoms);
m = 0;
for (int idim = 0; idim < 3; idim++) {
for (int iside = 0; iside < 2; iside++) {
if (boundary[idim][iside] == 0) boundstr[m++] = 'p';
else if (boundary[idim][iside] == 1) boundstr[m++] = 'f';
else if (boundary[idim][iside] == 2) boundstr[m++] = 's';
else if (boundary[idim][iside] == 3) boundstr[m++] = 'm';
}
boundstr[m++] = ' ';
}
boundstr[8] = '\0';
if (!triclinic) {
fprintf(fptxt,"ITEM: BOX BOUNDS %s\n",boundstr);
fprintf(fptxt,"%-1.16e %-1.16e\n",xlo,xhi);
fprintf(fptxt,"%-1.16e %-1.16e\n",ylo,yhi);
fprintf(fptxt,"%-1.16e %-1.16e\n",zlo,zhi);
} else {
fprintf(fptxt,"ITEM: BOX BOUNDS xy xz yz %s\n",boundstr);
fprintf(fptxt,"%-1.16e %-1.16e %-1.16e\n",xlo,xhi,xy);
fprintf(fptxt,"%-1.16e %-1.16e %-1.16e\n",ylo,yhi,xz);
fprintf(fptxt,"%-1.16e %-1.16e %-1.16e\n",zlo,zhi,yz);
}
if (columns)
fprintf(fptxt,"ITEM: ATOMS %s\n", columns);
else
fprintf(fptxt,"ITEM: ATOMS\n");
// loop over processor chunks in file
for (i = 0; i < nchunk; i++) {
fread(&n,sizeof(int),1,fp);
// extend buffer to fit chunk size
if (n > maxbuf) {
if (buf) delete [] buf;
buf = new double[n];
maxbuf = n;
}
// read chunk and write as size_one values per line
fread(buf,sizeof(double),n,fp);
n /= size_one;
m = 0;
for (j = 0; j < n; j++) {
for (k = 0; k < size_one; k++) {
if(k+1 < size_one) {
fprintf(fptxt,"%g ",buf[m++]);
} else {
fprintf(fptxt,"%g",buf[m++]);
}
}
fprintf(fptxt,"\n");
}
}
printf(" " BIGINT_FORMAT,ntimestep);
fflush(stdout);
}
printf("\n");
delete [] columns;
delete [] magic_string;
delete [] unit_style;
columns = nullptr;
magic_string = nullptr;
unit_style = nullptr;
}
if (buf) delete [] buf;
return 0;
}