diff --git a/doc/src/dump_modify.rst b/doc/src/dump_modify.rst index 753cce703c..07f00c4030 100644 --- a/doc/src/dump_modify.rst +++ b/doc/src/dump_modify.rst @@ -308,9 +308,9 @@ performed with dump style *xtc*\ . ---------- -The *format* keyword can be used to change the default numeric format -output by the text-based dump styles: *atom*\ , *custom*\ , *cfg*\ , and -*xyz* styles, and their MPIIO variants. Only the *line* or *none* +The *format* keyword can be used to change the default numeric format output +by the text-based dump styles: *atom*\ , *local*\ , *custom*\ , *cfg*\ , and +*xyz* styles, and their MPIIO variants. Only the *line* or *none* options can be used with the *atom* and *xyz* styles. All the specified format strings are C-style formats, e.g. as used by @@ -362,7 +362,7 @@ settings, reverting all values to their default format. compute 1 all property/local batom1 batom2 dump 1 all local 100 tmp.bonds index c_1[1] c_1[2] - dump_modify 1 format "%d %0.0f %0.0f" + dump_modify 1 format line "%d %0.0f %0.0f" will output the two atom IDs for atoms in each bond as integers. If the dump_modify command were omitted, they would appear as diff --git a/src/COMPRESS/dump_atom_gz.cpp b/src/COMPRESS/dump_atom_gz.cpp index f252e32064..7b54fd8e62 100644 --- a/src/COMPRESS/dump_atom_gz.cpp +++ b/src/COMPRESS/dump_atom_gz.cpp @@ -11,24 +11,18 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -#include "dump_atom_gz.h" #include "domain.h" +#include "dump_atom_gz.h" #include "error.h" #include "update.h" - #include - using namespace LAMMPS_NS; DumpAtomGZ::DumpAtomGZ(LAMMPS *lmp, int narg, char **arg) : DumpAtom(lmp, narg, arg) { - gzFp = nullptr; - - compression_level = Z_BEST_COMPRESSION; - if (!compressed) error->all(FLERR,"Dump atom/gz only writes compressed files"); } @@ -37,9 +31,6 @@ DumpAtomGZ::DumpAtomGZ(LAMMPS *lmp, int narg, char **arg) : DumpAtomGZ::~DumpAtomGZ() { - if (gzFp) gzclose(gzFp); - gzFp = nullptr; - fp = nullptr; } /* ---------------------------------------------------------------------- @@ -80,7 +71,9 @@ void DumpAtomGZ::openfile() nameslist[numfiles] = utils::strdup(filecurrent); ++numfiles; } else { - remove(nameslist[fileidx]); + if (remove(nameslist[fileidx]) != 0) { + error->warning(FLERR, fmt::format("Could not delete {}", nameslist[fileidx])); + } delete[] nameslist[fileidx]; nameslist[fileidx] = utils::strdup(filecurrent); fileidx = (fileidx + 1) % maxfiles; @@ -91,17 +84,12 @@ void DumpAtomGZ::openfile() // each proc with filewriter = 1 opens a file if (filewriter) { - std::string mode; - if (append_flag) { - mode = fmt::format("ab{}", compression_level); - } else { - mode = fmt::format("wb{}", compression_level); + try { + writer.open(filecurrent, append_flag); + } catch (FileWriterException &e) { + error->one(FLERR, e.what()); } - - gzFp = gzopen(filecurrent, mode.c_str()); - - if (gzFp == nullptr) error->one(FLERR,"Cannot open dump file"); - } else gzFp = nullptr; + } // delete string with timestep replaced @@ -112,29 +100,34 @@ void DumpAtomGZ::openfile() void DumpAtomGZ::write_header(bigint ndump) { + std::string header; + if ((multiproc) || (!multiproc && me == 0)) { if (unit_flag && !unit_count) { ++unit_count; - gzprintf(gzFp,"ITEM: UNITS\n%s\n",update->unit_style); + header = fmt::format("ITEM: UNITS\n{}\n",update->unit_style); } - if (time_flag) gzprintf(gzFp,"ITEM: TIME\n%.16g\n",compute_time()); - gzprintf(gzFp,"ITEM: TIMESTEP\n"); - gzprintf(gzFp,BIGINT_FORMAT "\n",update->ntimestep); - gzprintf(gzFp,"ITEM: NUMBER OF ATOMS\n"); - gzprintf(gzFp,BIGINT_FORMAT "\n",ndump); - if (domain->triclinic == 0) { - gzprintf(gzFp,"ITEM: BOX BOUNDS %s\n",boundstr); - gzprintf(gzFp,"%-1.16e %-1.16e\n",boxxlo,boxxhi); - gzprintf(gzFp,"%-1.16e %-1.16e\n",boxylo,boxyhi); - gzprintf(gzFp,"%-1.16e %-1.16e\n",boxzlo,boxzhi); - } else { - gzprintf(gzFp,"ITEM: BOX BOUNDS xy xz yz %s\n",boundstr); - gzprintf(gzFp,"%-1.16e %-1.16e %-1.16e\n",boxxlo,boxxhi,boxxy); - gzprintf(gzFp,"%-1.16e %-1.16e %-1.16e\n",boxylo,boxyhi,boxxz); - gzprintf(gzFp,"%-1.16e %-1.16e %-1.16e\n",boxzlo,boxzhi,boxyz); + if (time_flag) { + header += fmt::format("ITEM: TIME\n{0:.16g}\n", compute_time()); } - gzprintf(gzFp,"ITEM: ATOMS %s\n",columns); + + header += fmt::format("ITEM: TIMESTEP\n{}\n", update->ntimestep); + header += fmt::format("ITEM: NUMBER OF ATOMS\n{}\n", ndump); + if (domain->triclinic == 0) { + header += fmt::format("ITEM: BOX BOUNDS {}\n", boundstr); + header += fmt::format("{0:-1.16e} {1:-1.16e}\n", boxxlo, boxxhi); + header += fmt::format("{0:-1.16e} {1:-1.16e}\n", boxylo, boxyhi); + header += fmt::format("{0:-1.16e} {1:-1.16e}\n", boxzlo, boxzhi); + } else { + header += fmt::format("ITEM: BOX BOUNDS xy xz yz {}\n", boundstr); + header += fmt::format("{0:-1.16e} {1:-1.16e} {2:-1.16e}\n", boxxlo, boxxhi, boxxy); + header += fmt::format("{0:-1.16e} {1:-1.16e} {2:-1.16e}\n", boxylo, boxyhi, boxxz); + header += fmt::format("{0:-1.16e} {1:-1.16e} {2:-1.16e}\n", boxzlo, boxzhi, boxyz); + } + header += fmt::format("ITEM: ATOMS {}\n", columns); + + writer.write(header.c_str(), header.length()); } } @@ -142,7 +135,33 @@ void DumpAtomGZ::write_header(bigint ndump) void DumpAtomGZ::write_data(int n, double *mybuf) { - gzwrite(gzFp,mybuf,sizeof(char)*n); + if (buffer_flag == 1) { + writer.write(mybuf, n); + } else { + constexpr size_t VBUFFER_SIZE = 256; + char vbuffer[VBUFFER_SIZE]; + int m = 0; + for (int i = 0; i < n; i++) { + int written = 0; + if (image_flag == 1) { + written = snprintf(vbuffer, VBUFFER_SIZE, format, + static_cast (mybuf[m]), static_cast (mybuf[m+1]), + mybuf[m+2],mybuf[m+3],mybuf[m+4], static_cast (mybuf[m+5]), + static_cast (mybuf[m+6]), static_cast (mybuf[m+7])); + } else { + written = snprintf(vbuffer, VBUFFER_SIZE, format, + static_cast (mybuf[m]), static_cast (mybuf[m+1]), + mybuf[m+2],mybuf[m+3],mybuf[m+4]); + } + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump atom/gz output"); + } + + m += size_one; + } + } } /* ---------------------------------------------------------------------- */ @@ -152,11 +171,11 @@ void DumpAtomGZ::write() DumpAtom::write(); if (filewriter) { if (multifile) { - gzclose(gzFp); - gzFp = nullptr; + writer.close(); } else { - if (flush_flag) - gzflush(gzFp,Z_SYNC_FLUSH); + if (flush_flag && writer.isopen()) { + writer.flush(); + } } } } @@ -167,14 +186,15 @@ int DumpAtomGZ::modify_param(int narg, char **arg) { int consumed = DumpAtom::modify_param(narg, arg); if (consumed == 0) { - if (strcmp(arg[0],"compression_level") == 0) { - if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - int min_level = Z_DEFAULT_COMPRESSION; - int max_level = Z_BEST_COMPRESSION; - compression_level = utils::inumeric(FLERR, arg[1], false, lmp); - if (compression_level < min_level || compression_level > max_level) - error->all(FLERR, fmt::format("Illegal dump_modify command: compression level must in the range of [{}, {}]", min_level, max_level)); - return 2; + try { + if (strcmp(arg[0],"compression_level") == 0) { + if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); + int compression_level = utils::inumeric(FLERR, arg[1], false, lmp); + writer.setCompressionLevel(compression_level); + return 2; + } + } catch (FileWriterException &e) { + error->one(FLERR, fmt::format("Illegal dump_modify command: {}", e.what())); } } return consumed; diff --git a/src/COMPRESS/dump_atom_gz.h b/src/COMPRESS/dump_atom_gz.h index 0c0b95974f..d540f5300a 100644 --- a/src/COMPRESS/dump_atom_gz.h +++ b/src/COMPRESS/dump_atom_gz.h @@ -21,7 +21,7 @@ DumpStyle(atom/gz,DumpAtomGZ) #define LMP_DUMP_ATOM_GZ_H #include "dump_atom.h" -#include +#include "gz_file_writer.h" namespace LAMMPS_NS { @@ -31,8 +31,7 @@ class DumpAtomGZ : public DumpAtom { virtual ~DumpAtomGZ(); protected: - int compression_level; - gzFile gzFp; // file pointer for the compressed output stream + GzFileWriter writer; virtual void openfile(); virtual void write_header(bigint); diff --git a/src/COMPRESS/dump_atom_zstd.cpp b/src/COMPRESS/dump_atom_zstd.cpp index 3dde07bbf4..b53ebb2269 100644 --- a/src/COMPRESS/dump_atom_zstd.cpp +++ b/src/COMPRESS/dump_atom_zstd.cpp @@ -43,7 +43,7 @@ DumpAtomZstd::~DumpAtomZstd() /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or zstdipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ @@ -79,7 +79,9 @@ void DumpAtomZstd::openfile() nameslist[numfiles] = utils::strdup(filecurrent); ++numfiles; } else { - remove(nameslist[fileidx]); + if (remove(nameslist[fileidx]) != 0) { + error->warning(FLERR, fmt::format("Could not delete {}", nameslist[fileidx])); + } delete[] nameslist[fileidx]; nameslist[fileidx] = utils::strdup(filecurrent); fileidx = (fileidx + 1) % maxfiles; @@ -90,12 +92,8 @@ void DumpAtomZstd::openfile() // each proc with filewriter = 1 opens a file if (filewriter) { - if (append_flag) { - error->one(FLERR, "dump/zstd currently doesn't support append"); - } - try { - writer.open(filecurrent); + writer.open(filecurrent, append_flag); } catch (FileWriterException &e) { error->one(FLERR, e.what()); } @@ -145,7 +143,33 @@ void DumpAtomZstd::write_header(bigint ndump) void DumpAtomZstd::write_data(int n, double *mybuf) { - writer.write(mybuf, n); + if (buffer_flag == 1) { + writer.write(mybuf, n); + } else { + constexpr size_t VBUFFER_SIZE = 256; + char vbuffer[VBUFFER_SIZE]; + int m = 0; + for (int i = 0; i < n; i++) { + int written = 0; + if (image_flag == 1) { + written = snprintf(vbuffer, VBUFFER_SIZE, format, + static_cast (mybuf[m]), static_cast (mybuf[m+1]), + mybuf[m+2],mybuf[m+3],mybuf[m+4], static_cast (mybuf[m+5]), + static_cast (mybuf[m+6]), static_cast (mybuf[m+7])); + } else { + written = snprintf(vbuffer, VBUFFER_SIZE, format, + static_cast (mybuf[m]), static_cast (mybuf[m+1]), + mybuf[m+2],mybuf[m+3],mybuf[m+4]); + } + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump atom/gz output"); + } + + m += size_one; + } + } } /* ---------------------------------------------------------------------- */ @@ -184,7 +208,7 @@ int DumpAtomZstd::modify_param(int narg, char **arg) return 2; } } catch (FileWriterException &e) { - error->one(FLERR, e.what()); + error->one(FLERR, fmt::format("Illegal dump_modify command: {}", e.what())); } } return consumed; diff --git a/src/COMPRESS/dump_cfg_gz.cpp b/src/COMPRESS/dump_cfg_gz.cpp index 378baf502f..c5942c1fc5 100644 --- a/src/COMPRESS/dump_cfg_gz.cpp +++ b/src/COMPRESS/dump_cfg_gz.cpp @@ -11,41 +11,30 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -#include "dump_cfg_gz.h" #include "atom.h" #include "domain.h" +#include "dump_cfg_gz.h" #include "error.h" #include "update.h" - #include - using namespace LAMMPS_NS; #define UNWRAPEXPAND 10.0 DumpCFGGZ::DumpCFGGZ(LAMMPS *lmp, int narg, char **arg) : DumpCFG(lmp, narg, arg) { - gzFp = nullptr; - - compression_level = Z_BEST_COMPRESSION; - if (!compressed) error->all(FLERR,"Dump cfg/gz only writes compressed files"); } - /* ---------------------------------------------------------------------- */ DumpCFGGZ::~DumpCFGGZ() { - if (gzFp) gzclose(gzFp); - gzFp = nullptr; - fp = nullptr; } - /* ---------------------------------------------------------------------- generic opening of a dump file ASCII or binary or gzipped @@ -84,7 +73,9 @@ void DumpCFGGZ::openfile() nameslist[numfiles] = utils::strdup(filecurrent); ++numfiles; } else { - remove(nameslist[fileidx]); + if (remove(nameslist[fileidx]) != 0) { + error->warning(FLERR, fmt::format("Could not delete {}", nameslist[fileidx])); + } delete[] nameslist[fileidx]; nameslist[fileidx] = utils::strdup(filecurrent); fileidx = (fileidx + 1) % maxfiles; @@ -95,17 +86,12 @@ void DumpCFGGZ::openfile() // each proc with filewriter = 1 opens a file if (filewriter) { - std::string mode; - if (append_flag) { - mode = fmt::format("ab{}", compression_level); - } else { - mode = fmt::format("wb{}", compression_level); + try { + writer.open(filecurrent, append_flag); + } catch (FileWriterException &e) { + error->one(FLERR, e.what()); } - - gzFp = gzopen(filecurrent, mode.c_str()); - - if (gzFp == nullptr) error->one(FLERR,"Cannot open dump file"); - } else gzFp = nullptr; + } // delete string with timestep replaced @@ -127,30 +113,95 @@ void DumpCFGGZ::write_header(bigint n) if (atom->peri_flag) scale = atom->pdscale; else if (unwrapflag == 1) scale = UNWRAPEXPAND; - char str[64]; - sprintf(str,"Number of particles = %s\n",BIGINT_FORMAT); - gzprintf(gzFp,str,n); - gzprintf(gzFp,"A = %g Angstrom (basic length-scale)\n",scale); - gzprintf(gzFp,"H0(1,1) = %g A\n",domain->xprd); - gzprintf(gzFp,"H0(1,2) = 0 A \n"); - gzprintf(gzFp,"H0(1,3) = 0 A \n"); - gzprintf(gzFp,"H0(2,1) = %g A \n",domain->xy); - gzprintf(gzFp,"H0(2,2) = %g A\n",domain->yprd); - gzprintf(gzFp,"H0(2,3) = 0 A \n"); - gzprintf(gzFp,"H0(3,1) = %g A \n",domain->xz); - gzprintf(gzFp,"H0(3,2) = %g A \n",domain->yz); - gzprintf(gzFp,"H0(3,3) = %g A\n",domain->zprd); - gzprintf(gzFp,".NO_VELOCITY.\n"); - gzprintf(gzFp,"entry_count = %d\n",nfield-2); + std::string header = fmt::format("Number of particles = {}\n", n); + header += fmt::format("A = {0:g} Angstrom (basic length-scale)\n", scale); + header += fmt::format("H0(1,1) = {0:g} A\n",domain->xprd); + header += fmt::format("H0(1,2) = 0 A \n"); + header += fmt::format("H0(1,3) = 0 A \n"); + header += fmt::format("H0(2,1) = {0:g} A \n",domain->xy); + header += fmt::format("H0(2,2) = {0:g} A\n",domain->yprd); + header += fmt::format("H0(2,3) = 0 A \n"); + header += fmt::format("H0(3,1) = {0:g} A \n",domain->xz); + header += fmt::format("H0(3,2) = {0:g} A \n",domain->yz); + header += fmt::format("H0(3,3) = {0:g} A\n",domain->zprd); + header += fmt::format(".NO_VELOCITY.\n"); + header += fmt::format("entry_count = {}\n",nfield-2); for (int i = 0; i < nfield-5; i++) - gzprintf(gzFp,"auxiliary[%d] = %s\n",i,auxname[i]); + header += fmt::format("auxiliary[{}] = {}\n",i,auxname[i]); + + writer.write(header.c_str(), header.length()); } /* ---------------------------------------------------------------------- */ void DumpCFGGZ::write_data(int n, double *mybuf) { - gzwrite(gzFp,mybuf,sizeof(char)*n); + if (buffer_flag) { + writer.write(mybuf, n); + } else { + constexpr size_t VBUFFER_SIZE = 256; + char vbuffer[VBUFFER_SIZE]; + if (unwrapflag == 0) { + int m = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < size_one; j++) { + int written = 0; + if (j == 0) { + written = snprintf(vbuffer, VBUFFER_SIZE, "%f \n", mybuf[m]); + } else if (j == 1) { + written = snprintf(vbuffer, VBUFFER_SIZE, "%s \n", typenames[(int) mybuf[m]]); + } else if (j >= 2) { + if (vtype[j] == Dump::INT) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + else if (vtype[j] == Dump::DOUBLE) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]); + else if (vtype[j] == Dump::STRING) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], typenames[(int) mybuf[m]]); + else if (vtype[j] == Dump::BIGINT) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump cfg/gz output"); + } + m++; + } + writer.write("\n", 1); + } + } else if (unwrapflag == 1) { + int m = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < size_one; j++) { + int written = 0; + if (j == 0) { + written = snprintf(vbuffer, VBUFFER_SIZE, "%f \n", mybuf[m]); + } else if (j == 1) { + written = snprintf(vbuffer, VBUFFER_SIZE, "%s \n", typenames[(int) mybuf[m]]); + } else if (j >= 2 && j <= 4) { + double unwrap_coord = (mybuf[m] - 0.5)/UNWRAPEXPAND + 0.5; + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], unwrap_coord); + } else if (j >= 5) { + if (vtype[j] == Dump::INT) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + else if (vtype[j] == Dump::DOUBLE) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]); + else if (vtype[j] == Dump::STRING) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], typenames[(int) mybuf[m]]); + else if (vtype[j] == Dump::BIGINT) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump cfg/gz output"); + } + m++; + } + writer.write("\n", 1); + } + } + } } /* ---------------------------------------------------------------------- */ @@ -160,11 +211,11 @@ void DumpCFGGZ::write() DumpCFG::write(); if (filewriter) { if (multifile) { - gzclose(gzFp); - gzFp = nullptr; + writer.close(); } else { - if (flush_flag) - gzflush(gzFp,Z_SYNC_FLUSH); + if (flush_flag && writer.isopen()) { + writer.flush(); + } } } } @@ -175,16 +226,16 @@ int DumpCFGGZ::modify_param(int narg, char **arg) { int consumed = DumpCFG::modify_param(narg, arg); if (consumed == 0) { - if (strcmp(arg[0],"compression_level") == 0) { - if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - int min_level = Z_DEFAULT_COMPRESSION; - int max_level = Z_BEST_COMPRESSION; - compression_level = utils::inumeric(FLERR, arg[1], false, lmp); - if (compression_level < min_level || compression_level > max_level) - error->all(FLERR, fmt::format("Illegal dump_modify command: compression level must in the range of [{}, {}]", min_level, max_level)); - return 2; + try { + if (strcmp(arg[0],"compression_level") == 0) { + if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); + int compression_level = utils::inumeric(FLERR, arg[1], false, lmp); + writer.setCompressionLevel(compression_level); + return 2; + } + } catch (FileWriterException &e) { + error->one(FLERR, fmt::format("Illegal dump_modify command: {}", e.what())); } } return consumed; } - diff --git a/src/COMPRESS/dump_cfg_gz.h b/src/COMPRESS/dump_cfg_gz.h index 0c6ed24f06..2844902a38 100644 --- a/src/COMPRESS/dump_cfg_gz.h +++ b/src/COMPRESS/dump_cfg_gz.h @@ -21,7 +21,7 @@ DumpStyle(cfg/gz,DumpCFGGZ) #define LMP_DUMP_CFG_GZ_H #include "dump_cfg.h" -#include +#include "gz_file_writer.h" namespace LAMMPS_NS { @@ -31,8 +31,7 @@ class DumpCFGGZ : public DumpCFG { virtual ~DumpCFGGZ(); protected: - int compression_level; - gzFile gzFp; // file pointer for the compressed output stream + GzFileWriter writer; virtual void openfile(); virtual void write_header(bigint); diff --git a/src/COMPRESS/dump_cfg_zstd.cpp b/src/COMPRESS/dump_cfg_zstd.cpp index 459649c70a..0ea92f3807 100644 --- a/src/COMPRESS/dump_cfg_zstd.cpp +++ b/src/COMPRESS/dump_cfg_zstd.cpp @@ -21,7 +21,6 @@ #include "domain.h" #include "dump_cfg_zstd.h" #include "error.h" -#include "file_writer.h" #include "update.h" #include @@ -46,7 +45,7 @@ DumpCFGZstd::~DumpCFGZstd() /* ---------------------------------------------------------------------- generic opening of a dump file - ASCII or binary or zstdipped + ASCII or binary or compressed some derived classes override this function ------------------------------------------------------------------------- */ @@ -82,7 +81,9 @@ void DumpCFGZstd::openfile() nameslist[numfiles] = utils::strdup(filecurrent); ++numfiles; } else { - remove(nameslist[fileidx]); + if (remove(nameslist[fileidx]) != 0) { + error->warning(FLERR, fmt::format("Could not delete {}", nameslist[fileidx])); + } delete[] nameslist[fileidx]; nameslist[fileidx] = utils::strdup(filecurrent); fileidx = (fileidx + 1) % maxfiles; @@ -147,7 +148,72 @@ void DumpCFGZstd::write_header(bigint n) void DumpCFGZstd::write_data(int n, double *mybuf) { - writer.write(mybuf, n); + if (buffer_flag) { + writer.write(mybuf, n); + } else { + constexpr size_t VBUFFER_SIZE = 256; + char vbuffer[VBUFFER_SIZE]; + if (unwrapflag == 0) { + int m = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < size_one; j++) { + int written = 0; + if (j == 0) { + written = snprintf(vbuffer, VBUFFER_SIZE, "%f \n", mybuf[m]); + } else if (j == 1) { + written = snprintf(vbuffer, VBUFFER_SIZE, "%s \n", typenames[(int) mybuf[m]]); + } else if (j >= 2) { + if (vtype[j] == Dump::INT) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + else if (vtype[j] == Dump::DOUBLE) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]); + else if (vtype[j] == Dump::STRING) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], typenames[(int) mybuf[m]]); + else if (vtype[j] == Dump::BIGINT) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump cfg/gz output"); + } + m++; + } + writer.write("\n", 1); + } + } else if (unwrapflag == 1) { + int m = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < size_one; j++) { + int written = 0; + if (j == 0) { + written = snprintf(vbuffer, VBUFFER_SIZE, "%f \n", mybuf[m]); + } else if (j == 1) { + written = snprintf(vbuffer, VBUFFER_SIZE, "%s \n", typenames[(int) mybuf[m]]); + } else if (j >= 2 && j <= 4) { + double unwrap_coord = (mybuf[m] - 0.5)/UNWRAPEXPAND + 0.5; + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], unwrap_coord); + } else if (j >= 5) { + if (vtype[j] == Dump::INT) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + else if (vtype[j] == Dump::DOUBLE) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]); + else if (vtype[j] == Dump::STRING) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], typenames[(int) mybuf[m]]); + else if (vtype[j] == Dump::BIGINT) + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump cfg/gz output"); + } + m++; + } + writer.write("\n", 1); + } + } + } } /* ---------------------------------------------------------------------- */ diff --git a/src/COMPRESS/dump_custom_gz.cpp b/src/COMPRESS/dump_custom_gz.cpp index 4f03a4a232..9a3fc39d0a 100644 --- a/src/COMPRESS/dump_custom_gz.cpp +++ b/src/COMPRESS/dump_custom_gz.cpp @@ -11,39 +11,28 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -#include "dump_custom_gz.h" #include "domain.h" +#include "dump_custom_gz.h" #include "error.h" #include "update.h" - #include - using namespace LAMMPS_NS; DumpCustomGZ::DumpCustomGZ(LAMMPS *lmp, int narg, char **arg) : DumpCustom(lmp, narg, arg) { - gzFp = nullptr; - - compression_level = Z_BEST_COMPRESSION; - if (!compressed) error->all(FLERR,"Dump custom/gz only writes compressed files"); } - /* ---------------------------------------------------------------------- */ DumpCustomGZ::~DumpCustomGZ() { - if (gzFp) gzclose(gzFp); - gzFp = nullptr; - fp = nullptr; } - /* ---------------------------------------------------------------------- generic opening of a dump file ASCII or binary or gzipped @@ -82,7 +71,9 @@ void DumpCustomGZ::openfile() nameslist[numfiles] = utils::strdup(filecurrent); ++numfiles; } else { - remove(nameslist[fileidx]); + if (remove(nameslist[fileidx]) != 0) { + error->warning(FLERR, fmt::format("Could not delete {}", nameslist[fileidx])); + } delete[] nameslist[fileidx]; nameslist[fileidx] = utils::strdup(filecurrent); fileidx = (fileidx + 1) % maxfiles; @@ -93,17 +84,12 @@ void DumpCustomGZ::openfile() // each proc with filewriter = 1 opens a file if (filewriter) { - std::string mode; - if (append_flag) { - mode = fmt::format("ab{}", compression_level); - } else { - mode = fmt::format("wb{}", compression_level); + try { + writer.open(filecurrent, append_flag); + } catch (FileWriterException &e) { + error->one(FLERR, e.what()); } - - gzFp = gzopen(filecurrent, mode.c_str()); - - if (gzFp == nullptr) error->one(FLERR,"Cannot open dump file"); - } else gzFp = nullptr; + } // delete string with timestep replaced @@ -112,29 +98,34 @@ void DumpCustomGZ::openfile() void DumpCustomGZ::write_header(bigint ndump) { + std::string header; + if ((multiproc) || (!multiproc && me == 0)) { if (unit_flag && !unit_count) { ++unit_count; - gzprintf(gzFp,"ITEM: UNITS\n%s\n",update->unit_style); + header = fmt::format("ITEM: UNITS\n{}\n",update->unit_style); } - if (time_flag) gzprintf(gzFp,"ITEM: TIME\n%.16g\n",compute_time()); - gzprintf(gzFp,"ITEM: TIMESTEP\n"); - gzprintf(gzFp,BIGINT_FORMAT "\n",update->ntimestep); - gzprintf(gzFp,"ITEM: NUMBER OF ATOMS\n"); - gzprintf(gzFp,BIGINT_FORMAT "\n",ndump); - if (domain->triclinic == 0) { - gzprintf(gzFp,"ITEM: BOX BOUNDS %s\n",boundstr); - gzprintf(gzFp,"%-1.16e %-1.16e\n",boxxlo,boxxhi); - gzprintf(gzFp,"%-1.16e %-1.16e\n",boxylo,boxyhi); - gzprintf(gzFp,"%-1.16e %-1.16e\n",boxzlo,boxzhi); - } else { - gzprintf(gzFp,"ITEM: BOX BOUNDS xy xz yz %s\n",boundstr); - gzprintf(gzFp,"%-1.16e %-1.16e %-1.16e\n",boxxlo,boxxhi,boxxy); - gzprintf(gzFp,"%-1.16e %-1.16e %-1.16e\n",boxylo,boxyhi,boxxz); - gzprintf(gzFp,"%-1.16e %-1.16e %-1.16e\n",boxzlo,boxzhi,boxyz); + if (time_flag) { + header += fmt::format("ITEM: TIME\n{0:.16g}\n", compute_time()); } - gzprintf(gzFp,"ITEM: ATOMS %s\n",columns); + + header += fmt::format("ITEM: TIMESTEP\n{}\n", update->ntimestep); + header += fmt::format("ITEM: NUMBER OF ATOMS\n{}\n", ndump); + if (domain->triclinic == 0) { + header += fmt::format("ITEM: BOX BOUNDS {}\n", boundstr); + header += fmt::format("{0:-1.16e} {1:-1.16e}\n", boxxlo, boxxhi); + header += fmt::format("{0:-1.16e} {1:-1.16e}\n", boxylo, boxyhi); + header += fmt::format("{0:-1.16e} {1:-1.16e}\n", boxzlo, boxzhi); + } else { + header += fmt::format("ITEM: BOX BOUNDS xy xz yz {}\n", boundstr); + header += fmt::format("{0:-1.16e} {1:-1.16e} {2:-1.16e}\n", boxxlo, boxxhi, boxxy); + header += fmt::format("{0:-1.16e} {1:-1.16e} {2:-1.16e}\n", boxylo, boxyhi, boxxz); + header += fmt::format("{0:-1.16e} {1:-1.16e} {2:-1.16e}\n", boxzlo, boxzhi, boxyz); + } + header += fmt::format("ITEM: ATOMS {}\n", columns); + + writer.write(header.c_str(), header.length()); } } @@ -142,7 +133,35 @@ void DumpCustomGZ::write_header(bigint ndump) void DumpCustomGZ::write_data(int n, double *mybuf) { - gzwrite(gzFp,mybuf,sizeof(char)*n); + if (buffer_flag == 1) { + writer.write(mybuf, n); + } else { + constexpr size_t VBUFFER_SIZE = 256; + char vbuffer[VBUFFER_SIZE]; + int m = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < nfield; j++) { + int written = 0; + if (vtype[j] == Dump::INT) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } else if (vtype[j] == Dump::DOUBLE) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]); + } else if (vtype[j] == Dump::STRING) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], typenames[(int) mybuf[m]]); + } else if (vtype[j] == Dump::BIGINT) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } + + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump custom/gz output"); + } + m++; + } + writer.write("\n", 1); + } + } } /* ---------------------------------------------------------------------- */ @@ -152,11 +171,11 @@ void DumpCustomGZ::write() DumpCustom::write(); if (filewriter) { if (multifile) { - gzclose(gzFp); - gzFp = nullptr; + writer.close(); } else { - if (flush_flag) - gzflush(gzFp,Z_SYNC_FLUSH); + if (flush_flag && writer.isopen()) { + writer.flush(); + } } } } @@ -167,14 +186,15 @@ int DumpCustomGZ::modify_param(int narg, char **arg) { int consumed = DumpCustom::modify_param(narg, arg); if (consumed == 0) { - if (strcmp(arg[0],"compression_level") == 0) { - if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - int min_level = Z_DEFAULT_COMPRESSION; - int max_level = Z_BEST_COMPRESSION; - compression_level = utils::inumeric(FLERR, arg[1], false, lmp); - if (compression_level < min_level || compression_level > max_level) - error->all(FLERR, fmt::format("Illegal dump_modify command: compression level must in the range of [{}, {}]", min_level, max_level)); - return 2; + try { + if (strcmp(arg[0],"compression_level") == 0) { + if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); + int compression_level = utils::inumeric(FLERR, arg[1], false, lmp); + writer.setCompressionLevel(compression_level); + return 2; + } + } catch (FileWriterException &e) { + error->one(FLERR, fmt::format("Illegal dump_modify command: {}", e.what())); } } return consumed; diff --git a/src/COMPRESS/dump_custom_gz.h b/src/COMPRESS/dump_custom_gz.h index 184f3563f1..db30b944ec 100644 --- a/src/COMPRESS/dump_custom_gz.h +++ b/src/COMPRESS/dump_custom_gz.h @@ -21,7 +21,7 @@ DumpStyle(custom/gz,DumpCustomGZ) #define LMP_DUMP_CUSTOM_GZ_H #include "dump_custom.h" -#include +#include "gz_file_writer.h" namespace LAMMPS_NS { @@ -31,8 +31,7 @@ class DumpCustomGZ : public DumpCustom { virtual ~DumpCustomGZ(); protected: - int compression_level; - gzFile gzFp; // file pointer for the compressed output stream + GzFileWriter writer; virtual void openfile(); virtual void write_header(bigint); diff --git a/src/COMPRESS/dump_custom_zstd.cpp b/src/COMPRESS/dump_custom_zstd.cpp index 3aa3f874ea..b3f0971bf5 100644 --- a/src/COMPRESS/dump_custom_zstd.cpp +++ b/src/COMPRESS/dump_custom_zstd.cpp @@ -20,7 +20,6 @@ #include "domain.h" #include "dump_custom_zstd.h" #include "error.h" -#include "file_writer.h" #include "update.h" #include @@ -79,7 +78,9 @@ void DumpCustomZstd::openfile() nameslist[numfiles] = utils::strdup(filecurrent); ++numfiles; } else { - remove(nameslist[fileidx]); + if (remove(nameslist[fileidx]) != 0) { + error->warning(FLERR, fmt::format("Could not delete {}", nameslist[fileidx])); + } delete[] nameslist[fileidx]; nameslist[fileidx] = utils::strdup(filecurrent); fileidx = (fileidx + 1) % maxfiles; @@ -145,7 +146,35 @@ void DumpCustomZstd::write_header(bigint ndump) void DumpCustomZstd::write_data(int n, double *mybuf) { - writer.write(mybuf, n); + if (buffer_flag == 1) { + writer.write(mybuf, n); + } else { + constexpr size_t VBUFFER_SIZE = 256; + char vbuffer[VBUFFER_SIZE]; + int m = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < nfield; j++) { + int written = 0; + if (vtype[j] == Dump::INT) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } else if (vtype[j] == Dump::DOUBLE) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]); + } else if (vtype[j] == Dump::STRING) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], typenames[(int) mybuf[m]]); + } else if (vtype[j] == Dump::BIGINT) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } + + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump custom/gz output"); + } + m++; + } + writer.write("\n", 1); + } + } } /* ---------------------------------------------------------------------- */ @@ -184,7 +213,7 @@ int DumpCustomZstd::modify_param(int narg, char **arg) return 2; } } catch (FileWriterException &e) { - error->one(FLERR, e.what()); + error->one(FLERR, fmt::format("Illegal dump_modify command: {}", e.what())); } } return consumed; diff --git a/src/COMPRESS/dump_local_gz.cpp b/src/COMPRESS/dump_local_gz.cpp index e8065a848a..7ffb8d80ff 100644 --- a/src/COMPRESS/dump_local_gz.cpp +++ b/src/COMPRESS/dump_local_gz.cpp @@ -11,39 +11,28 @@ See the README file in the top-level LAMMPS directory. ------------------------------------------------------------------------- */ -#include "dump_local_gz.h" #include "domain.h" +#include "dump_local_gz.h" #include "error.h" #include "update.h" - #include - using namespace LAMMPS_NS; DumpLocalGZ::DumpLocalGZ(LAMMPS *lmp, int narg, char **arg) : DumpLocal(lmp, narg, arg) { - gzFp = nullptr; - - compression_level = Z_BEST_COMPRESSION; - if (!compressed) error->all(FLERR,"Dump local/gz only writes compressed files"); } - /* ---------------------------------------------------------------------- */ DumpLocalGZ::~DumpLocalGZ() { - if (gzFp) gzclose(gzFp); - gzFp = nullptr; - fp = nullptr; } - /* ---------------------------------------------------------------------- generic opening of a dump file ASCII or binary or gzipped @@ -82,7 +71,9 @@ void DumpLocalGZ::openfile() nameslist[numfiles] = utils::strdup(filecurrent); ++numfiles; } else { - remove(nameslist[fileidx]); + if (remove(nameslist[fileidx]) != 0) { + error->warning(FLERR, fmt::format("Could not delete {}", nameslist[fileidx])); + } delete[] nameslist[fileidx]; nameslist[fileidx] = utils::strdup(filecurrent); fileidx = (fileidx + 1) % maxfiles; @@ -93,17 +84,12 @@ void DumpLocalGZ::openfile() // each proc with filewriter = 1 opens a file if (filewriter) { - std::string mode; - if (append_flag) { - mode = fmt::format("ab{}", compression_level); - } else { - mode = fmt::format("wb{}", compression_level); + try { + writer.open(filecurrent, append_flag); + } catch (FileWriterException &e) { + error->one(FLERR, e.what()); } - - gzFp = gzopen(filecurrent, mode.c_str()); - - if (gzFp == nullptr) error->one(FLERR,"Cannot open dump file"); - } else gzFp = nullptr; + } // delete string with timestep replaced @@ -112,29 +98,34 @@ void DumpLocalGZ::openfile() void DumpLocalGZ::write_header(bigint ndump) { + std::string header; + if ((multiproc) || (!multiproc && me == 0)) { if (unit_flag && !unit_count) { ++unit_count; - gzprintf(gzFp,"ITEM: UNITS\n%s\n",update->unit_style); + header = fmt::format("ITEM: UNITS\n{}\n",update->unit_style); } - if (time_flag) gzprintf(gzFp,"ITEM: TIME\n%.16g\n",compute_time()); - gzprintf(gzFp,"ITEM: TIMESTEP\n"); - gzprintf(gzFp,BIGINT_FORMAT "\n",update->ntimestep); - gzprintf(gzFp,"ITEM: NUMBER OF %s\n",label); - gzprintf(gzFp,BIGINT_FORMAT "\n",ndump); - if (domain->triclinic) { - gzprintf(gzFp,"ITEM: BOX BOUNDS xy xz yz %s\n",boundstr); - gzprintf(gzFp,"%-1.16e %-1.16e %-1.16e\n",boxxlo,boxxhi,boxxy); - gzprintf(gzFp,"%-1.16e %-1.16e %-1.16e\n",boxylo,boxyhi,boxxz); - gzprintf(gzFp,"%-1.16e %-1.16e %-1.16e\n",boxzlo,boxzhi,boxyz); - } else { - gzprintf(gzFp,"ITEM: BOX BOUNDS %s\n",boundstr); - gzprintf(gzFp,"%-1.16e %-1.16e\n",boxxlo,boxxhi); - gzprintf(gzFp,"%-1.16e %-1.16e\n",boxylo,boxyhi); - gzprintf(gzFp,"%-1.16e %-1.16e\n",boxzlo,boxzhi); + if (time_flag) { + header += fmt::format("ITEM: TIME\n{0:.16g}\n", compute_time()); } - gzprintf(gzFp,"ITEM: %s %s\n",label,columns); + + header += fmt::format("ITEM: TIMESTEP\n{}\n", update->ntimestep); + header += fmt::format("ITEM: NUMBER OF {}\n{}\n", label, ndump); + if (domain->triclinic == 0) { + header += fmt::format("ITEM: BOX BOUNDS {}\n", boundstr); + header += fmt::format("{0:-1.16e} {1:-1.16e}\n", boxxlo, boxxhi); + header += fmt::format("{0:-1.16e} {1:-1.16e}\n", boxylo, boxyhi); + header += fmt::format("{0:-1.16e} {1:-1.16e}\n", boxzlo, boxzhi); + } else { + header += fmt::format("ITEM: BOX BOUNDS xy xz yz {}\n", boundstr); + header += fmt::format("{0:-1.16e} {1:-1.16e} {2:-1.16e}\n", boxxlo, boxxhi, boxxy); + header += fmt::format("{0:-1.16e} {1:-1.16e} {2:-1.16e}\n", boxylo, boxyhi, boxxz); + header += fmt::format("{0:-1.16e} {1:-1.16e} {2:-1.16e}\n", boxzlo, boxzhi, boxyz); + } + header += fmt::format("ITEM: {} {}\n", label, columns); + + writer.write(header.c_str(), header.length()); } } @@ -143,19 +134,32 @@ void DumpLocalGZ::write_header(bigint ndump) void DumpLocalGZ::write_data(int n, double *mybuf) { if (buffer_flag == 1) { - gzwrite(gzFp,mybuf,sizeof(char)*n); - + writer.write(mybuf, sizeof(char)*n); } else { - int i,j; + constexpr size_t VBUFFER_SIZE = 256; + char vbuffer[VBUFFER_SIZE]; int m = 0; - for (i = 0; i < n; i++) { - for (j = 0; j < size_one; j++) { - if (vtype[j] == INT) - gzprintf(gzFp,vformat[j],static_cast (mybuf[m])); - else gzprintf(gzFp,vformat[j],mybuf[m]); + for (int i = 0; i < n; i++) { + for (int j = 0; j < size_one; j++) { + int written = 0; + if (vtype[j] == Dump::INT) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } else if (vtype[j] == Dump::DOUBLE) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]); + } else if (vtype[j] == Dump::BIGINT) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } else { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]); + } + + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump local/gz output"); + } m++; } - gzprintf(gzFp,"\n"); + writer.write("\n", 1); } } } @@ -167,11 +171,11 @@ void DumpLocalGZ::write() DumpLocal::write(); if (filewriter) { if (multifile) { - gzclose(gzFp); - gzFp = nullptr; + writer.close(); } else { - if (flush_flag) - gzflush(gzFp,Z_SYNC_FLUSH); + if (flush_flag && writer.isopen()) { + writer.flush(); + } } } } @@ -182,14 +186,15 @@ int DumpLocalGZ::modify_param(int narg, char **arg) { int consumed = DumpLocal::modify_param(narg, arg); if (consumed == 0) { - if (strcmp(arg[0],"compression_level") == 0) { - if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - int min_level = Z_DEFAULT_COMPRESSION; - int max_level = Z_BEST_COMPRESSION; - compression_level = utils::inumeric(FLERR, arg[1], false, lmp); - if (compression_level < min_level || compression_level > max_level) - error->all(FLERR, fmt::format("Illegal dump_modify command: compression level must in the range of [{}, {}]", min_level, max_level)); - return 2; + try { + if (strcmp(arg[0],"compression_level") == 0) { + if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); + int compression_level = utils::inumeric(FLERR, arg[1], false, lmp); + writer.setCompressionLevel(compression_level); + return 2; + } + } catch (FileWriterException &e) { + error->one(FLERR, fmt::format("Illegal dump_modify command: {}", e.what())); } } return consumed; diff --git a/src/COMPRESS/dump_local_gz.h b/src/COMPRESS/dump_local_gz.h index b3f7c7dcf8..7feb6a8945 100644 --- a/src/COMPRESS/dump_local_gz.h +++ b/src/COMPRESS/dump_local_gz.h @@ -21,7 +21,7 @@ DumpStyle(local/gz,DumpLocalGZ) #define LMP_DUMP_LOCAL_GZ_H #include "dump_local.h" -#include +#include "gz_file_writer.h" namespace LAMMPS_NS { @@ -31,8 +31,7 @@ class DumpLocalGZ : public DumpLocal { virtual ~DumpLocalGZ(); protected: - int compression_level; - gzFile gzFp; // file pointer for the compressed output stream + GzFileWriter writer; virtual void openfile(); virtual void write_header(bigint); diff --git a/src/COMPRESS/dump_local_zstd.cpp b/src/COMPRESS/dump_local_zstd.cpp index d26555d282..4d7fe9361b 100644 --- a/src/COMPRESS/dump_local_zstd.cpp +++ b/src/COMPRESS/dump_local_zstd.cpp @@ -17,15 +17,13 @@ #ifdef LAMMPS_ZSTD -#include "dump_local_zstd.h" #include "domain.h" +#include "dump_local_zstd.h" #include "error.h" #include "update.h" - #include - using namespace LAMMPS_NS; DumpLocalZstd::DumpLocalZstd(LAMMPS *lmp, int narg, char **arg) : @@ -42,7 +40,6 @@ DumpLocalZstd::~DumpLocalZstd() { } - /* ---------------------------------------------------------------------- generic opening of a dump file ASCII or binary or gzipped @@ -81,7 +78,9 @@ void DumpLocalZstd::openfile() nameslist[numfiles] = utils::strdup(filecurrent); ++numfiles; } else { - remove(nameslist[fileidx]); + if (remove(nameslist[fileidx]) != 0) { + error->warning(FLERR, fmt::format("Could not delete {}", nameslist[fileidx])); + } delete[] nameslist[fileidx]; nameslist[fileidx] = utils::strdup(filecurrent); fileidx = (fileidx + 1) % maxfiles; @@ -145,7 +144,35 @@ void DumpLocalZstd::write_header(bigint ndump) void DumpLocalZstd::write_data(int n, double *mybuf) { - writer.write(mybuf, sizeof(char)*n); + if (buffer_flag == 1) { + writer.write(mybuf, sizeof(char)*n); + } else { + constexpr size_t VBUFFER_SIZE = 256; + char vbuffer[VBUFFER_SIZE]; + int m = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < size_one; j++) { + int written = 0; + if (vtype[j] == Dump::INT) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } else if (vtype[j] == Dump::DOUBLE) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]); + } else if (vtype[j] == Dump::BIGINT) { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast (mybuf[m])); + } else { + written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]); + } + + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump local/gz output"); + } + m++; + } + writer.write("\n", 1); + } + } } /* ---------------------------------------------------------------------- */ @@ -184,7 +211,7 @@ int DumpLocalZstd::modify_param(int narg, char **arg) return 2; } } catch (FileWriterException &e) { - error->one(FLERR, e.what()); + error->one(FLERR, fmt::format("Illegal dump_modify command: {}", e.what())); } } return consumed; diff --git a/src/COMPRESS/dump_xyz_gz.cpp b/src/COMPRESS/dump_xyz_gz.cpp index c63d354e80..abd6e7fa78 100644 --- a/src/COMPRESS/dump_xyz_gz.cpp +++ b/src/COMPRESS/dump_xyz_gz.cpp @@ -15,19 +15,13 @@ #include "error.h" #include "update.h" - #include - using namespace LAMMPS_NS; DumpXYZGZ::DumpXYZGZ(LAMMPS *lmp, int narg, char **arg) : DumpXYZ(lmp, narg, arg) { - gzFp = nullptr; - - compression_level = Z_BEST_COMPRESSION; - if (!compressed) error->all(FLERR,"Dump xyz/gz only writes compressed files"); } @@ -37,12 +31,8 @@ DumpXYZGZ::DumpXYZGZ(LAMMPS *lmp, int narg, char **arg) : DumpXYZGZ::~DumpXYZGZ() { - if (gzFp) gzclose(gzFp); - gzFp = nullptr; - fp = nullptr; } - /* ---------------------------------------------------------------------- generic opening of a dump file ASCII or binary or gzipped @@ -81,7 +71,9 @@ void DumpXYZGZ::openfile() nameslist[numfiles] = utils::strdup(filecurrent); ++numfiles; } else { - remove(nameslist[fileidx]); + if (remove(nameslist[fileidx]) != 0) { + error->warning(FLERR, fmt::format("Could not delete {}", nameslist[fileidx])); + } delete[] nameslist[fileidx]; nameslist[fileidx] = utils::strdup(filecurrent); fileidx = (fileidx + 1) % maxfiles; @@ -92,17 +84,12 @@ void DumpXYZGZ::openfile() // each proc with filewriter = 1 opens a file if (filewriter) { - std::string mode; - if (append_flag) { - mode = fmt::format("ab{}", compression_level); - } else { - mode = fmt::format("wb{}", compression_level); + try { + writer.open(filecurrent, append_flag); + } catch (FileWriterException &e) { + error->one(FLERR, e.what()); } - - gzFp = gzopen(filecurrent, mode.c_str()); - - if (gzFp == nullptr) error->one(FLERR,"Cannot open dump file"); - } else gzFp = nullptr; + } // delete string with timestep replaced @@ -112,8 +99,9 @@ void DumpXYZGZ::openfile() void DumpXYZGZ::write_header(bigint ndump) { if (me == 0) { - gzprintf(gzFp,BIGINT_FORMAT "\n",ndump); - gzprintf(gzFp,"Atoms. Timestep: " BIGINT_FORMAT "\n",update->ntimestep); + std::string header = fmt::format("{}\n", ndump); + header += fmt::format("Atoms. Timestep: {}\n", update->ntimestep); + writer.write(header.c_str(), header.length()); } } @@ -121,7 +109,24 @@ void DumpXYZGZ::write_header(bigint ndump) void DumpXYZGZ::write_data(int n, double *mybuf) { - gzwrite(gzFp,mybuf,sizeof(char)*n); + if (buffer_flag) { + writer.write(mybuf, n); + } else { + constexpr size_t VBUFFER_SIZE = 256; + char vbuffer[VBUFFER_SIZE]; + int m = 0; + for (int i = 0; i < n; i++) { + int written = snprintf(vbuffer, VBUFFER_SIZE, format, + typenames[static_cast (mybuf[m+1])], + mybuf[m+2],mybuf[m+3],mybuf[m+4]); + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump xyz/gz output"); + } + m += size_one; + } + } } /* ---------------------------------------------------------------------- */ @@ -131,11 +136,11 @@ void DumpXYZGZ::write() DumpXYZ::write(); if (filewriter) { if (multifile) { - gzclose(gzFp); - gzFp = nullptr; + writer.close(); } else { - if (flush_flag) - gzflush(gzFp,Z_SYNC_FLUSH); + if (flush_flag && writer.isopen()) { + writer.flush(); + } } } } @@ -146,14 +151,15 @@ int DumpXYZGZ::modify_param(int narg, char **arg) { int consumed = DumpXYZ::modify_param(narg, arg); if (consumed == 0) { - if (strcmp(arg[0],"compression_level") == 0) { - if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); - int min_level = Z_DEFAULT_COMPRESSION; - int max_level = Z_BEST_COMPRESSION; - compression_level = utils::inumeric(FLERR, arg[1], false, lmp); - if (compression_level < min_level || compression_level > max_level) - error->all(FLERR, fmt::format("Illegal dump_modify command: compression level must in the range of [{}, {}]", min_level, max_level)); - return 2; + try { + if (strcmp(arg[0],"compression_level") == 0) { + if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); + int compression_level = utils::inumeric(FLERR, arg[1], false, lmp); + writer.setCompressionLevel(compression_level); + return 2; + } + } catch (FileWriterException &e) { + error->one(FLERR, fmt::format("Illegal dump_modify command: {}", e.what())); } } return consumed; diff --git a/src/COMPRESS/dump_xyz_gz.h b/src/COMPRESS/dump_xyz_gz.h index 834db488a5..2fce0a3f5a 100644 --- a/src/COMPRESS/dump_xyz_gz.h +++ b/src/COMPRESS/dump_xyz_gz.h @@ -21,7 +21,7 @@ DumpStyle(xyz/gz,DumpXYZGZ) #define LMP_DUMP_XYZ_GZ_H #include "dump_xyz.h" -#include +#include "gz_file_writer.h" namespace LAMMPS_NS { @@ -31,8 +31,7 @@ class DumpXYZGZ : public DumpXYZ { virtual ~DumpXYZGZ(); protected: - int compression_level; - gzFile gzFp; // file pointer for the compressed output stream + GzFileWriter writer; virtual void openfile(); virtual void write_header(bigint); diff --git a/src/COMPRESS/dump_xyz_zstd.cpp b/src/COMPRESS/dump_xyz_zstd.cpp index 7c5b73d0ba..74e482717b 100644 --- a/src/COMPRESS/dump_xyz_zstd.cpp +++ b/src/COMPRESS/dump_xyz_zstd.cpp @@ -19,7 +19,6 @@ #include "dump_xyz_zstd.h" #include "error.h" -#include "file_writer.h" #include "update.h" #include @@ -79,7 +78,9 @@ void DumpXYZZstd::openfile() nameslist[numfiles] = utils::strdup(filecurrent); ++numfiles; } else { - remove(nameslist[fileidx]); + if (remove(nameslist[fileidx]) != 0) { + error->warning(FLERR, fmt::format("Could not delete {}", nameslist[fileidx])); + } delete[] nameslist[fileidx]; nameslist[fileidx] = utils::strdup(filecurrent); fileidx = (fileidx + 1) % maxfiles; @@ -119,7 +120,24 @@ void DumpXYZZstd::write_header(bigint ndump) void DumpXYZZstd::write_data(int n, double *mybuf) { - writer.write(mybuf, n); + if (buffer_flag) { + writer.write(mybuf, n); + } else { + constexpr size_t VBUFFER_SIZE = 256; + char vbuffer[VBUFFER_SIZE]; + int m = 0; + for (int i = 0; i < n; i++) { + int written = snprintf(vbuffer, VBUFFER_SIZE, format, + typenames[static_cast (mybuf[m+1])], + mybuf[m+2],mybuf[m+3],mybuf[m+4]); + if (written > 0) { + writer.write(vbuffer, written); + } else if (written < 0) { + error->one(FLERR, "Error while writing dump xyz/gz output"); + } + m += size_one; + } + } } /* ---------------------------------------------------------------------- */ @@ -158,7 +176,7 @@ int DumpXYZZstd::modify_param(int narg, char **arg) return 2; } } catch (FileWriterException &e) { - error->one(FLERR, e.what()); + error->one(FLERR, fmt::format("Illegal dump_modify command: {}", e.what())); } } return consumed; diff --git a/src/COMPRESS/gz_file_writer.cpp b/src/COMPRESS/gz_file_writer.cpp new file mode 100644 index 0000000000..d24d77b21a --- /dev/null +++ b/src/COMPRESS/gz_file_writer.cpp @@ -0,0 +1,105 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing author: Richard Berger (Temple U) +------------------------------------------------------------------------- */ + +#include "gz_file_writer.h" +#include +#include "fmt/format.h" + +using namespace LAMMPS_NS; + +GzFileWriter::GzFileWriter() : FileWriter(), + compression_level(Z_BEST_COMPRESSION), + gzFp(nullptr) +{ +} + +/* ---------------------------------------------------------------------- */ + +GzFileWriter::~GzFileWriter() +{ + close(); +} + +/* ---------------------------------------------------------------------- */ + +void GzFileWriter::open(const std::string &path, bool append) +{ + if (isopen()) return; + + std::string mode; + if (append) { + mode = fmt::format("ab{}", mode, compression_level); + } else { + mode = fmt::format("wb{}", mode, compression_level); + } + + gzFp = gzopen(path.c_str(), mode.c_str()); + + if (gzFp == nullptr) + throw FileWriterException(fmt::format("Could not open file '{}'", path)); +} + +/* ---------------------------------------------------------------------- */ + +size_t GzFileWriter::write(const void * buffer, size_t length) +{ + if (!isopen()) return 0; + + return gzwrite(gzFp, buffer, length); +} + +/* ---------------------------------------------------------------------- */ + +void GzFileWriter::flush() +{ + if (!isopen()) return; + + gzflush(gzFp, Z_SYNC_FLUSH); +} + +/* ---------------------------------------------------------------------- */ + +void GzFileWriter::close() +{ + if (!isopen()) return; + + gzclose(gzFp); + gzFp = nullptr; +} + +/* ---------------------------------------------------------------------- */ + +bool GzFileWriter::isopen() const +{ + return gzFp; +} + +/* ---------------------------------------------------------------------- */ + +void GzFileWriter::setCompressionLevel(int level) +{ + if (isopen()) + throw FileWriterException("Compression level can not be changed while file is open"); + + const int min_level = Z_DEFAULT_COMPRESSION; + const int max_level = Z_BEST_COMPRESSION; + + if (level < min_level || level > max_level) + throw FileWriterException(fmt::format("Compression level must in the range of [{}, {}]", min_level, max_level)); + + compression_level = level; +} diff --git a/src/COMPRESS/gz_file_writer.h b/src/COMPRESS/gz_file_writer.h new file mode 100644 index 0000000000..28473b1164 --- /dev/null +++ b/src/COMPRESS/gz_file_writer.h @@ -0,0 +1,47 @@ +/* -*- c++ -*- ---------------------------------------------------------- + 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. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing author: Richard Berger (Temple U) +------------------------------------------------------------------------- */ + +#ifndef LMP_GZ_FILE_WRITER_H +#define LMP_GZ_FILE_WRITER_H + +#include "file_writer.h" +#include +#include +#include + +namespace LAMMPS_NS { + +class GzFileWriter : public FileWriter { + int compression_level; + + gzFile gzFp; // file pointer for the compressed output stream +public: + GzFileWriter(); + virtual ~GzFileWriter(); + virtual void open(const std::string &path, bool append = false) override; + virtual void close() override; + virtual void flush() override; + virtual size_t write(const void * buffer, size_t length) override; + virtual bool isopen() const override; + + void setCompressionLevel(int level); +}; + + +} + +#endif diff --git a/src/COMPRESS/zstd_file_writer.cpp b/src/COMPRESS/zstd_file_writer.cpp index f82ade605c..3356fc1ad5 100644 --- a/src/COMPRESS/zstd_file_writer.cpp +++ b/src/COMPRESS/zstd_file_writer.cpp @@ -46,11 +46,15 @@ ZstdFileWriter::~ZstdFileWriter() /* ---------------------------------------------------------------------- */ -void ZstdFileWriter::open(const std::string &path) +void ZstdFileWriter::open(const std::string &path, bool append) { if (isopen()) return; - fp = fopen(path.c_str(), "wb"); + if (append) { + fp = fopen(path.c_str(), "ab"); + } else { + fp = fopen(path.c_str(), "wb"); + } if (!fp) { throw FileWriterException(fmt::format("Could not open file '{}'", path)); diff --git a/src/COMPRESS/zstd_file_writer.h b/src/COMPRESS/zstd_file_writer.h index 30afc86994..a4dbbdff64 100644 --- a/src/COMPRESS/zstd_file_writer.h +++ b/src/COMPRESS/zstd_file_writer.h @@ -38,7 +38,7 @@ class ZstdFileWriter : public FileWriter { public: ZstdFileWriter(); virtual ~ZstdFileWriter(); - virtual void open(const std::string &path) override; + virtual void open(const std::string &path, bool append = false) override; virtual void close() override; virtual void flush() override; virtual size_t write(const void * buffer, size_t length) override; diff --git a/src/dump_local.cpp b/src/dump_local.cpp index 53a82b496f..0f8d139f66 100644 --- a/src/dump_local.cpp +++ b/src/dump_local.cpp @@ -112,7 +112,7 @@ DumpLocal::DumpLocal(LAMMPS *lmp, int narg, char **arg) : label = utils::strdup("ENTRIES"); - // if wildcard expansion occurred, free earg memory from exapnd_args() + // if wildcard expansion occurred, free earg memory from expand_args() if (expand) { for (int i = 0; i < nfield; i++) delete [] earg[i]; @@ -179,6 +179,8 @@ void DumpLocal::init_style() 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 + " "); ++i; } @@ -225,6 +227,46 @@ int DumpLocal::modify_param(int narg, char **arg) delete [] label; label = utils::strdup(arg[1]); return 2; + } else 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; + } else 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"); + if (format_column_user[i]) delete [] format_column_user[i]; + format_column_user[i] = utils::strdup(arg[2]); + } + return 3; } return 0; } @@ -335,6 +377,10 @@ int DumpLocal::convert_string(int n, double *mybuf) for (j = 0; j < size_one; j++) { if (vtype[j] == Dump::INT) offset += sprintf(&sbuf[offset],vformat[j],static_cast (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 (mybuf[m])); else offset += sprintf(&sbuf[offset],vformat[j],mybuf[m]); m++; @@ -369,6 +415,8 @@ void DumpLocal::write_lines(int n, double *mybuf) for (i = 0; i < n; i++) { for (j = 0; j < size_one; j++) { if (vtype[j] == Dump::INT) fprintf(fp,vformat[j],static_cast (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(mybuf[m])); else fprintf(fp,vformat[j],mybuf[m]); m++; } diff --git a/src/file_writer.h b/src/file_writer.h index 8597ab570d..02eef6ad70 100644 --- a/src/file_writer.h +++ b/src/file_writer.h @@ -27,7 +27,7 @@ class FileWriter { public: FileWriter() = default; virtual ~FileWriter() = default; - virtual void open(const std::string &path) = 0; + virtual void open(const std::string &path, bool append = false) = 0; virtual void close() = 0; virtual void flush() = 0; virtual size_t write(const void * buffer, size_t length) = 0; diff --git a/unittest/formats/CMakeLists.txt b/unittest/formats/CMakeLists.txt index be0d14c47d..4c6de98729 100644 --- a/unittest/formats/CMakeLists.txt +++ b/unittest/formats/CMakeLists.txt @@ -102,6 +102,11 @@ target_link_libraries(test_dump_cfg PRIVATE lammps GTest::GMock GTest::GTest) add_test(NAME DumpCfg COMMAND test_dump_cfg WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) set_tests_properties(DumpCfg PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") +add_executable(test_dump_local test_dump_local.cpp) +target_link_libraries(test_dump_local PRIVATE lammps GTest::GMock GTest::GTest) +add_test(NAME DumpLocal COMMAND test_dump_local WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +set_tests_properties(DumpLocal PROPERTIES ENVIRONMENT "LAMMPS_POTENTIALS=${LAMMPS_POTENTIALS_DIR}") + if(BUILD_TOOLS) set_tests_properties(DumpAtom PROPERTIES ENVIRONMENT "BINARY2TXT_BINARY=$") set_tests_properties(DumpCustom PROPERTIES ENVIRONMENT "BINARY2TXT_BINARY=$") diff --git a/unittest/formats/test_dump_atom.cpp b/unittest/formats/test_dump_atom.cpp index 5161eece3e..669f4d38bd 100644 --- a/unittest/formats/test_dump_atom.cpp +++ b/unittest/formats/test_dump_atom.cpp @@ -135,7 +135,7 @@ TEST_F(DumpAtomTest, no_scale_run0) TEST_F(DumpAtomTest, no_buffer_no_scale_run0) { auto dump_file = "dump_no_buffer_no_scale_run0.melt"; - generate_dump(dump_file, "scale no", 0); + generate_dump(dump_file, "buffer no scale no", 0); ASSERT_FILE_EXISTS(dump_file); auto lines = read_lines(dump_file); diff --git a/unittest/formats/test_dump_atom_compressed.cpp b/unittest/formats/test_dump_atom_compressed.cpp index 5a519e06a1..aeb747004e 100644 --- a/unittest/formats/test_dump_atom_compressed.cpp +++ b/unittest/formats/test_dump_atom_compressed.cpp @@ -61,6 +61,34 @@ TEST_F(DumpAtomCompressTest, compressed_run0) delete_file(converted_file); } +TEST_F(DumpAtomCompressTest, compressed_no_buffer_run0) +{ + if (!COMPRESS_BINARY) GTEST_SKIP(); + + auto text_file = text_dump_filename("no_buffer_run0.melt"); + auto compressed_file = compressed_dump_filename("no_buffer_run0.melt"); + + if(compression_style == "atom/zstd") { + generate_text_and_compressed_dump(text_file, compressed_file, "", "", "buffer no", "buffer no checksum yes", 0); + } else { + generate_text_and_compressed_dump(text_file, compressed_file, "", "buffer no", 0); + } + + TearDown(); + + ASSERT_FILE_EXISTS(text_file); + ASSERT_FILE_EXISTS(compressed_file); + + auto converted_file = convert_compressed_to_text(compressed_file); + + ASSERT_THAT(converted_file, Eq(converted_dump_filename("no_buffer_run0.melt"))); + ASSERT_FILE_EXISTS(converted_file); + ASSERT_FILE_EQUAL(text_file, converted_file); + delete_file(text_file); + delete_file(compressed_file); + delete_file(converted_file); +} + TEST_F(DumpAtomCompressTest, compressed_multi_file_run1) { if (!COMPRESS_BINARY) GTEST_SKIP(); @@ -344,7 +372,7 @@ TEST_F(DumpAtomCompressTest, compressed_modify_bad_param) command(fmt::format("dump id1 all {} 1 {}", compression_style, compressed_dump_filename("modify_bad_param_run0_*.melt"))); END_HIDE_OUTPUT(); - TEST_FAILURE(".*ERROR: Illegal dump_modify command: compression level must in the range of.*", + TEST_FAILURE(".*ERROR on proc 0: Illegal dump_modify command: Compression level must in the range of.*", command("dump_modify id1 compression_level 12"); ); } @@ -357,7 +385,7 @@ TEST_F(DumpAtomCompressTest, compressed_modify_multi_bad_param) command(fmt::format("dump id1 all {} 1 {}", compression_style, compressed_dump_filename("modify_multi_bad_param_run0_*.melt"))); END_HIDE_OUTPUT(); - TEST_FAILURE(".*ERROR: Illegal dump_modify command: compression level must in the range of.*", + TEST_FAILURE(".*ERROR on proc 0: Illegal dump_modify command: Compression level must in the range of.*", command("dump_modify id1 pad 3 compression_level 12"); ); } diff --git a/unittest/formats/test_dump_cfg_compressed.cpp b/unittest/formats/test_dump_cfg_compressed.cpp index 20f902091b..1a00f9520e 100644 --- a/unittest/formats/test_dump_cfg_compressed.cpp +++ b/unittest/formats/test_dump_cfg_compressed.cpp @@ -66,6 +66,39 @@ TEST_F(DumpCfgCompressTest, compressed_run0) delete_file(converted_file_0); } +TEST_F(DumpCfgCompressTest, compressed_no_buffer_run0) +{ + if (!COMPRESS_BINARY) GTEST_SKIP(); + + auto base_name = "no_buffer_run*.melt.cfg"; + auto text_files = text_dump_filename(base_name); + auto compressed_files = compressed_dump_filename(base_name); + + auto base_name_0 = "no_buffer_run0.melt.cfg"; + auto text_file_0 = text_dump_filename(base_name_0); + auto compressed_file_0 = compressed_dump_filename(base_name_0); + auto fields = "mass type xs ys zs id proc procp1 x y z ix iy iz vx vy vz fx fy fz"; + + if(compression_style == "cfg/zstd") { + generate_text_and_compressed_dump(text_files, compressed_files, fields, fields, "buffer no", "buffer no", 0); + } else { + generate_text_and_compressed_dump(text_files, compressed_files, fields, "buffer no", 0); + } + + TearDown(); + + ASSERT_FILE_EXISTS(text_file_0); + ASSERT_FILE_EXISTS(compressed_file_0); + + auto converted_file_0 = convert_compressed_to_text(compressed_file_0); + + ASSERT_FILE_EXISTS(converted_file_0); + ASSERT_FILE_EQUAL(text_file_0, converted_file_0); + delete_file(text_file_0); + delete_file(compressed_file_0); + delete_file(converted_file_0); +} + TEST_F(DumpCfgCompressTest, compressed_unwrap_run0) { if (!COMPRESS_BINARY) GTEST_SKIP(); @@ -234,7 +267,7 @@ TEST_F(DumpCfgCompressTest, compressed_modify_bad_param) command(fmt::format("dump id1 all {} 1 {} {}", compression_style, compressed_dump_filename("modify_bad_param_run0_*.melt.cfg"), fields)); END_HIDE_OUTPUT(); - TEST_FAILURE(".*ERROR: Illegal dump_modify command: compression level must in the range of.*", + TEST_FAILURE(".*ERROR on proc 0: Illegal dump_modify command: Compression level must in the range of.*", command("dump_modify id1 compression_level 12"); ); } @@ -248,7 +281,7 @@ TEST_F(DumpCfgCompressTest, compressed_modify_multi_bad_param) command(fmt::format("dump id1 all {} 1 {} {}", compression_style, compressed_dump_filename("modify_multi_bad_param_run0_*.melt.cfg"), fields)); END_HIDE_OUTPUT(); - TEST_FAILURE(".*ERROR: Illegal dump_modify command: compression level must in the range of.*", + TEST_FAILURE(".*ERROR on proc 0: Illegal dump_modify command: Compression level must in the range of.*", command("dump_modify id1 pad 3 compression_level 12"); ); } diff --git a/unittest/formats/test_dump_custom_compressed.cpp b/unittest/formats/test_dump_custom_compressed.cpp index fb70206590..cb45c1b837 100644 --- a/unittest/formats/test_dump_custom_compressed.cpp +++ b/unittest/formats/test_dump_custom_compressed.cpp @@ -58,6 +58,64 @@ TEST_F(DumpCustomCompressTest, compressed_run1) delete_file(converted_file); } +TEST_F(DumpCustomCompressTest, compressed_with_time_run1) +{ + if (!COMPRESS_BINARY) GTEST_SKIP(); + + auto base_name = "with_time_custom_run1.melt"; + auto text_file = text_dump_filename(base_name); + auto compressed_file = compressed_dump_filename(base_name); + auto fields = "id type proc x y z ix iy iz xs ys zs xu yu zu xsu ysu zsu vx vy vz fx fy fz"; + + if(compression_style == "custom/zstd") { + generate_text_and_compressed_dump(text_file, compressed_file, fields, fields, "time yes", "time yes checksum yes", 1); + } else { + generate_text_and_compressed_dump(text_file, compressed_file, fields, "time yes", 1); + } + + TearDown(); + + ASSERT_FILE_EXISTS(text_file); + ASSERT_FILE_EXISTS(compressed_file); + + auto converted_file = convert_compressed_to_text(compressed_file); + + ASSERT_FILE_EXISTS(converted_file); + ASSERT_FILE_EQUAL(text_file, converted_file); + delete_file(text_file); + delete_file(compressed_file); + delete_file(converted_file); +} + +TEST_F(DumpCustomCompressTest, compressed_no_buffer_run1) +{ + if (!COMPRESS_BINARY) GTEST_SKIP(); + + auto base_name = "no_buffer_custom_run1.melt"; + auto text_file = text_dump_filename(base_name); + auto compressed_file = compressed_dump_filename(base_name); + auto fields = "id type proc x y z ix iy iz xs ys zs xu yu zu xsu ysu zsu vx vy vz fx fy fz"; + + if(compression_style == "custom/zstd") { + generate_text_and_compressed_dump(text_file, compressed_file, fields, fields, "buffer no", "buffer no checksum yes", 1); + } else { + generate_text_and_compressed_dump(text_file, compressed_file, fields, "buffer no", 1); + } + + TearDown(); + + ASSERT_FILE_EXISTS(text_file); + ASSERT_FILE_EXISTS(compressed_file); + + auto converted_file = convert_compressed_to_text(compressed_file); + + ASSERT_FILE_EXISTS(converted_file); + ASSERT_FILE_EQUAL(text_file, converted_file); + delete_file(text_file); + delete_file(compressed_file); + delete_file(converted_file); +} + TEST_F(DumpCustomCompressTest, compressed_triclinic_run1) { if (!COMPRESS_BINARY) GTEST_SKIP(); @@ -222,7 +280,7 @@ TEST_F(DumpCustomCompressTest, compressed_modify_bad_param) auto fields = "id type proc x y z ix iy iz xs ys zs xu yu zu xsu ysu zsu vx vy vz fx fy fz"; command(fmt::format("dump id1 all {} 1 {} {}", compression_style, compressed_dump_filename("modify_bad_param_run0_*.melt.custom"), fields)); - TEST_FAILURE(".*ERROR: Illegal dump_modify command: compression level must in the range of.*", + TEST_FAILURE(".*ERROR on proc 0: Illegal dump_modify command: Compression level must in the range of.*", command("dump_modify id1 compression_level 12"); ); } @@ -234,7 +292,7 @@ TEST_F(DumpCustomCompressTest, compressed_modify_multi_bad_param) auto fields = "id type proc x y z ix iy iz xs ys zs xu yu zu xsu ysu zsu vx vy vz fx fy fz"; command(fmt::format("dump id1 all {} 1 {} {}", compression_style, compressed_dump_filename("modify_multi_bad_param_run0_*.melt.custom"), fields)); - TEST_FAILURE(".*ERROR: Illegal dump_modify command: compression level must in the range of.*", + TEST_FAILURE(".*ERROR on proc 0: Illegal dump_modify command: Compression level must in the range of.*", command("dump_modify id1 pad 3 compression_level 12"); ); } diff --git a/unittest/formats/test_dump_local.cpp b/unittest/formats/test_dump_local.cpp new file mode 100644 index 0000000000..b122d71849 --- /dev/null +++ b/unittest/formats/test_dump_local.cpp @@ -0,0 +1,261 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + https://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 "../testing/core.h" +#include "../testing/systems/melt.h" +#include "../testing/utils.h" +#include "fmt/format.h" +#include "output.h" +#include "thermo.h" +#include "utils.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include + +using ::testing::Eq; + +char *BINARY2TXT_BINARY = nullptr; +bool verbose = false; + +class DumpLocalTest : public MeltTest { + std::string dump_style = "local"; + +public: + void enable_triclinic() + { + BEGIN_HIDE_OUTPUT(); + command("change_box all triclinic"); + END_HIDE_OUTPUT(); + } + + void generate_dump(std::string dump_file, std::string dump_options, std::string dump_modify_options, int ntimesteps) + { + BEGIN_HIDE_OUTPUT(); + command(fmt::format("dump id all {} 1 {} {}", dump_style, dump_file, dump_options)); + + if (!dump_modify_options.empty()) { + command(fmt::format("dump_modify id {}", dump_modify_options)); + } + + command(fmt::format("run {} post no", ntimesteps)); + END_HIDE_OUTPUT(); + } + + void continue_dump(int ntimesteps) + { + BEGIN_HIDE_OUTPUT(); + command(fmt::format("run {} pre no post no", ntimesteps)); + END_HIDE_OUTPUT(); + } + + void SetUp() override { + MeltTest::SetUp(); + + BEGIN_HIDE_OUTPUT(); + command("compute comp all pair/local dist eng"); + END_HIDE_OUTPUT(); + } +}; + +TEST_F(DumpLocalTest, run0) +{ + auto dump_file = "dump_local_run0.melt"; + generate_dump(dump_file, "index c_comp[1]", "", 0); + + ASSERT_FILE_EXISTS(dump_file); + auto lines = read_lines(dump_file); + ASSERT_EQ(lines.size(), 873); + + ASSERT_THAT(lines[0], Eq("ITEM: TIMESTEP")); + ASSERT_EQ(std::stoi(lines[1]), 0); + + ASSERT_THAT(lines[2], Eq("ITEM: NUMBER OF ENTRIES")); + ASSERT_EQ(std::stoi(lines[3]), 864); + + ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS pp pp pp")); + ASSERT_EQ(utils::split_words(lines[5]).size(), 2); + ASSERT_EQ(utils::split_words(lines[6]).size(), 2); + ASSERT_EQ(utils::split_words(lines[7]).size(), 2); + ASSERT_THAT(lines[8], Eq("ITEM: ENTRIES index c_comp[1] ")); + ASSERT_EQ(utils::split_words(lines[9]).size(), 2); + ASSERT_THAT(lines[9], Eq("1 1.18765 ")); + delete_file(dump_file); +} + +TEST_F(DumpLocalTest, label_run0) +{ + auto dump_file = "dump_local_label_run0.melt"; + generate_dump(dump_file, "index c_comp[1]", "label ELEMENTS", 0); + + ASSERT_FILE_EXISTS(dump_file); + auto lines = read_lines(dump_file); + ASSERT_THAT(lines[2], Eq("ITEM: NUMBER OF ELEMENTS")); + ASSERT_THAT(lines[8], Eq("ITEM: ELEMENTS index c_comp[1] ")); + delete_file(dump_file); +} + +TEST_F(DumpLocalTest, format_line_run0) +{ + auto dump_file = "dump_local_format_line_run0.melt"; + generate_dump(dump_file, "index c_comp[1]", "format line \"%d %20.8g\"", 0); + + ASSERT_FILE_EXISTS(dump_file); + auto lines = read_lines(dump_file); + + ASSERT_EQ(utils::split_words(lines[9]).size(), 2); + ASSERT_THAT(lines[9], Eq("1 1.1876539 ")); + delete_file(dump_file); +} + +TEST_F(DumpLocalTest, format_int_run0) +{ + auto dump_file = "dump_local_format_int_run0.melt"; + generate_dump(dump_file, "index c_comp[1]", "format int \"%20d\"", 0); + + ASSERT_FILE_EXISTS(dump_file); + auto lines = read_lines(dump_file); + + ASSERT_EQ(utils::split_words(lines[9]).size(), 2); + ASSERT_THAT(lines[9], Eq(" 1 1.18765 ")); + delete_file(dump_file); +} + +TEST_F(DumpLocalTest, format_float_run0) +{ + auto dump_file = "dump_local_format_float_run0.melt"; + generate_dump(dump_file, "index c_comp[1]", "format float \"%20.5g\"", 0); + + ASSERT_FILE_EXISTS(dump_file); + auto lines = read_lines(dump_file); + + ASSERT_EQ(utils::split_words(lines[9]).size(), 2); + ASSERT_THAT(lines[9], Eq("1 1.1877 ")); + delete_file(dump_file); +} + +TEST_F(DumpLocalTest, format_column_run0) +{ + auto dump_file = "dump_local_format_column_run0.melt"; + generate_dump(dump_file, "index c_comp[1]", "format 1 \"%20d\"", 0); + + ASSERT_FILE_EXISTS(dump_file); + auto lines = read_lines(dump_file); + + ASSERT_EQ(utils::split_words(lines[9]).size(), 2); + ASSERT_THAT(lines[9], Eq(" 1 1.18765 ")); + delete_file(dump_file); +} + +TEST_F(DumpLocalTest, no_buffer_run0) +{ + auto dump_file = "dump_local_format_line_run0.melt"; + generate_dump(dump_file, "index c_comp[1]", "buffer no", 0); + + ASSERT_FILE_EXISTS(dump_file); + auto lines = read_lines(dump_file); + ASSERT_EQ(lines.size(), 873); + + ASSERT_THAT(lines[0], Eq("ITEM: TIMESTEP")); + ASSERT_EQ(std::stoi(lines[1]), 0); + + ASSERT_THAT(lines[2], Eq("ITEM: NUMBER OF ENTRIES")); + ASSERT_EQ(std::stoi(lines[3]), 864); + + ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS pp pp pp")); + ASSERT_EQ(utils::split_words(lines[5]).size(), 2); + ASSERT_EQ(utils::split_words(lines[6]).size(), 2); + ASSERT_EQ(utils::split_words(lines[7]).size(), 2); + ASSERT_THAT(lines[8], Eq("ITEM: ENTRIES index c_comp[1] ")); + ASSERT_EQ(utils::split_words(lines[9]).size(), 2); + ASSERT_THAT(lines[9], Eq("1 1.18765 ")); + delete_file(dump_file); +} + +TEST_F(DumpLocalTest, with_units_run0) +{ + auto dump_file = "dump_with_units_run0.melt"; + generate_dump(dump_file, "index c_comp[1]", "units yes", 0); + + ASSERT_FILE_EXISTS(dump_file); + auto lines = read_lines(dump_file); + ASSERT_EQ(lines.size(), 875); + + ASSERT_THAT(lines[0], Eq("ITEM: UNITS")); + ASSERT_THAT(lines[1], Eq("lj")); + + ASSERT_THAT(lines[2], Eq("ITEM: TIMESTEP")); + ASSERT_EQ(std::stoi(lines[3]), 0); + + ASSERT_THAT(lines[4], Eq("ITEM: NUMBER OF ENTRIES")); + ASSERT_EQ(std::stoi(lines[5]), 864); +} + +TEST_F(DumpLocalTest, with_time_run0) +{ + auto dump_file = "dump_with_time_run0.melt"; + generate_dump(dump_file, "index c_comp[1]", "time yes", 0); + + ASSERT_FILE_EXISTS(dump_file); + auto lines = read_lines(dump_file); + ASSERT_EQ(lines.size(), 875); + + ASSERT_THAT(lines[0], Eq("ITEM: TIME")); + ASSERT_THAT(std::stof(lines[1]), 0.0); + + ASSERT_THAT(lines[2], Eq("ITEM: TIMESTEP")); + ASSERT_EQ(std::stoi(lines[3]), 0); + + ASSERT_THAT(lines[4], Eq("ITEM: NUMBER OF ENTRIES")); + ASSERT_EQ(std::stoi(lines[5]), 864); +} + +TEST_F(DumpLocalTest, triclinic_run0) +{ + auto dump_file = "dump_local_triclinic_run0.melt"; + enable_triclinic(); + generate_dump(dump_file, "index c_comp[1]", "", 0); + + ASSERT_FILE_EXISTS(dump_file); + auto lines = read_lines(dump_file); + + ASSERT_THAT(lines[4], Eq("ITEM: BOX BOUNDS xy xz yz pp pp pp")); + ASSERT_EQ(utils::split_words(lines[5]).size(), 3); + ASSERT_EQ(utils::split_words(lines[6]).size(), 3); + ASSERT_EQ(utils::split_words(lines[7]).size(), 3); + delete_file(dump_file); +} + +int main(int argc, char **argv) +{ + MPI_Init(&argc, &argv); + ::testing::InitGoogleMock(&argc, argv); + + // handle arguments passed via environment variable + if (const char *var = getenv("TEST_ARGS")) { + std::vector env = utils::split_words(var); + for (auto arg : env) { + if (arg == "-v") { + verbose = true; + } + } + } + + BINARY2TXT_BINARY = getenv("BINARY2TXT_BINARY"); + + if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = true; + + int rv = RUN_ALL_TESTS(); + MPI_Finalize(); + return rv; +} diff --git a/unittest/formats/test_dump_local_compressed.cpp b/unittest/formats/test_dump_local_compressed.cpp index 95656071fc..cd217354af 100644 --- a/unittest/formats/test_dump_local_compressed.cpp +++ b/unittest/formats/test_dump_local_compressed.cpp @@ -69,6 +69,135 @@ TEST_F(DumpLocalCompressTest, compressed_run0) delete_file(converted_file_0); } +TEST_F(DumpLocalCompressTest, compressed_no_buffer_run0) +{ + if (!COMPRESS_BINARY) GTEST_SKIP(); + + auto base_name = "no_buffer_run*.melt.local"; + auto base_name_0 = "no_buffer_run0.melt.local"; + auto text_files = text_dump_filename(base_name); + auto compressed_files = compressed_dump_filename(base_name); + auto text_file_0 = text_dump_filename(base_name_0); + auto compressed_file_0 = compressed_dump_filename(base_name_0); + auto fields = "index c_comp[1]"; + + if(compression_style == "local/zstd") { + generate_text_and_compressed_dump(text_files, compressed_files, fields, fields, "buffer no", "buffer no checksum yes", 0); + } else { + generate_text_and_compressed_dump(text_files, compressed_files, fields, "buffer no", 0); + } + + TearDown(); + + ASSERT_FILE_EXISTS(text_file_0); + ASSERT_FILE_EXISTS(compressed_file_0); + + auto converted_file_0 = convert_compressed_to_text(compressed_file_0); + + ASSERT_FILE_EXISTS(converted_file_0); + ASSERT_FILE_EQUAL(text_file_0, converted_file_0); + delete_file(text_file_0); + delete_file(compressed_file_0); + delete_file(converted_file_0); +} + +TEST_F(DumpLocalCompressTest, compressed_with_time_run0) +{ + if (!COMPRESS_BINARY) GTEST_SKIP(); + + auto base_name = "with_time_run*.melt.local"; + auto base_name_0 = "with_time_run0.melt.local"; + auto text_files = text_dump_filename(base_name); + auto compressed_files = compressed_dump_filename(base_name); + auto text_file_0 = text_dump_filename(base_name_0); + auto compressed_file_0 = compressed_dump_filename(base_name_0); + auto fields = "index c_comp[1]"; + + if(compression_style == "local/zstd") { + generate_text_and_compressed_dump(text_files, compressed_files, fields, fields, "time yes", "time yes checksum yes", 0); + } else { + generate_text_and_compressed_dump(text_files, compressed_files, fields, "time yes", 0); + } + + TearDown(); + + ASSERT_FILE_EXISTS(text_file_0); + ASSERT_FILE_EXISTS(compressed_file_0); + + auto converted_file_0 = convert_compressed_to_text(compressed_file_0); + + ASSERT_FILE_EXISTS(converted_file_0); + ASSERT_FILE_EQUAL(text_file_0, converted_file_0); + delete_file(text_file_0); + delete_file(compressed_file_0); + delete_file(converted_file_0); +} + +TEST_F(DumpLocalCompressTest, compressed_with_units_run0) +{ + if (!COMPRESS_BINARY) GTEST_SKIP(); + + auto base_name = "with_units_run*.melt.local"; + auto base_name_0 = "with_units_run0.melt.local"; + auto text_files = text_dump_filename(base_name); + auto compressed_files = compressed_dump_filename(base_name); + auto text_file_0 = text_dump_filename(base_name_0); + auto compressed_file_0 = compressed_dump_filename(base_name_0); + auto fields = "index c_comp[1]"; + + if(compression_style == "local/zstd") { + generate_text_and_compressed_dump(text_files, compressed_files, fields, fields, "units yes", "units yes checksum yes", 0); + } else { + generate_text_and_compressed_dump(text_files, compressed_files, fields, "units yes", 0); + } + + TearDown(); + + ASSERT_FILE_EXISTS(text_file_0); + ASSERT_FILE_EXISTS(compressed_file_0); + + auto converted_file_0 = convert_compressed_to_text(compressed_file_0); + + ASSERT_FILE_EXISTS(converted_file_0); + ASSERT_FILE_EQUAL(text_file_0, converted_file_0); + delete_file(text_file_0); + delete_file(compressed_file_0); + delete_file(converted_file_0); +} + +TEST_F(DumpLocalCompressTest, compressed_triclinic_run0) +{ + if (!COMPRESS_BINARY) GTEST_SKIP(); + enable_triclinic(); + + auto base_name = "triclinic_run*.melt.local"; + auto base_name_0 = "triclinic_run0.melt.local"; + auto text_files = text_dump_filename(base_name); + auto compressed_files = compressed_dump_filename(base_name); + auto text_file_0 = text_dump_filename(base_name_0); + auto compressed_file_0 = compressed_dump_filename(base_name_0); + auto fields = "index c_comp[1]"; + + if(compression_style == "local/zstd") { + generate_text_and_compressed_dump(text_files, compressed_files, fields, fields, "", "checksum yes", 0); + } else { + generate_text_and_compressed_dump(text_files, compressed_files, fields, "", 0); + } + + TearDown(); + + ASSERT_FILE_EXISTS(text_file_0); + ASSERT_FILE_EXISTS(compressed_file_0); + + auto converted_file_0 = convert_compressed_to_text(compressed_file_0); + + ASSERT_FILE_EXISTS(converted_file_0); + ASSERT_FILE_EQUAL(text_file_0, converted_file_0); + delete_file(text_file_0); + delete_file(compressed_file_0); + delete_file(converted_file_0); +} + TEST_F(DumpLocalCompressTest, compressed_multi_file_run1) { if (!COMPRESS_BINARY) GTEST_SKIP(); @@ -209,7 +338,7 @@ TEST_F(DumpLocalCompressTest, compressed_modify_bad_param) command(fmt::format("dump id1 all {} 1 {} {}", compression_style, compressed_dump_filename("modify_bad_param_run0_*.melt.local"), fields)); END_HIDE_OUTPUT(); - TEST_FAILURE(".*ERROR: Illegal dump_modify command: compression level must in the range of.*", + TEST_FAILURE(".*ERROR on proc 0: Illegal dump_modify command: Compression level must in the range of.*", command("dump_modify id1 compression_level 12"); ); } @@ -224,7 +353,7 @@ TEST_F(DumpLocalCompressTest, compressed_modify_multi_bad_param) command(fmt::format("dump id1 all {} 1 {} {}", compression_style, compressed_dump_filename("modify_multi_bad_param_run0_*.melt.local"), fields)); END_HIDE_OUTPUT(); - TEST_FAILURE(".*ERROR: Illegal dump_modify command: compression level must in the range of.*", + TEST_FAILURE(".*ERROR on proc 0: Illegal dump_modify command: Compression level must in the range of.*", command("dump_modify id1 pad 3 compression_level 12"); ); } diff --git a/unittest/formats/test_dump_xyz_compressed.cpp b/unittest/formats/test_dump_xyz_compressed.cpp index dad7911b4c..d9aa8e370d 100644 --- a/unittest/formats/test_dump_xyz_compressed.cpp +++ b/unittest/formats/test_dump_xyz_compressed.cpp @@ -60,6 +60,37 @@ TEST_F(DumpXYZCompressTest, compressed_run0) delete_file(converted_file_0); } +TEST_F(DumpXYZCompressTest, compressed_no_buffer_run0) +{ + if (!COMPRESS_BINARY) GTEST_SKIP(); + + auto base_name = "no_buffer_run*.melt.xyz"; + auto base_name_0 = "no_buffer_run0.melt.xyz"; + auto text_files = text_dump_filename(base_name); + auto compressed_files = compressed_dump_filename(base_name); + auto text_file_0 = text_dump_filename(base_name_0); + auto compressed_file_0 = compressed_dump_filename(base_name_0); + + if(compression_style == "xyz/zstd") { + generate_text_and_compressed_dump(text_files, compressed_files, "", "", "buffer no", "buffer no", 0); + } else { + generate_text_and_compressed_dump(text_files, compressed_files, "", "buffer no", 0); + } + + TearDown(); + + ASSERT_FILE_EXISTS(text_file_0); + ASSERT_FILE_EXISTS(compressed_file_0); + + auto converted_file_0 = convert_compressed_to_text(compressed_file_0); + + ASSERT_FILE_EXISTS(converted_file_0); + ASSERT_FILE_EQUAL(text_file_0, converted_file_0); + delete_file(text_file_0); + delete_file(compressed_file_0); + delete_file(converted_file_0); +} + TEST_F(DumpXYZCompressTest, compressed_multi_file_run1) { if (!COMPRESS_BINARY) GTEST_SKIP(); @@ -195,7 +226,7 @@ TEST_F(DumpXYZCompressTest, compressed_modify_bad_param) command(fmt::format("dump id1 all {} 1 {}", compression_style, compressed_dump_filename("modify_bad_param_run0_*.melt.xyz"))); END_HIDE_OUTPUT(); - TEST_FAILURE(".*ERROR: Illegal dump_modify command: compression level must in the range of.*", + TEST_FAILURE(".*ERROR on proc 0: Illegal dump_modify command: Compression level must in the range of.*", command("dump_modify id1 compression_level 12"); ); } @@ -208,7 +239,7 @@ TEST_F(DumpXYZCompressTest, compressed_modify_multi_bad_param) command(fmt::format("dump id1 all {} 1 {}", compression_style, compressed_dump_filename("modify_multi_bad_param_run0_*.melt.xyz"))); END_HIDE_OUTPUT(); - TEST_FAILURE(".*ERROR: Illegal dump_modify command: compression level must in the range of.*", + TEST_FAILURE(".*ERROR on proc 0: Illegal dump_modify command: Compression level must in the range of.*", command("dump_modify id1 pad 3 compression_level 12"); ); }