diff --git a/src/dump_atom.cpp b/src/dump_atom.cpp index 4b2ee96b69..7e89e5a075 100644 --- a/src/dump_atom.cpp +++ b/src/dump_atom.cpp @@ -204,6 +204,7 @@ void DumpAtom::header_format_binary() void DumpAtom::header_binary(bigint ndump) { header_format_binary(); + fwrite(&update->ntimestep,sizeof(bigint),1,fp); fwrite(&ndump,sizeof(bigint),1,fp); fwrite(&domain->triclinic,sizeof(int),1,fp); @@ -216,10 +217,22 @@ void DumpAtom::header_binary(bigint ndump) fwrite(&boxzhi,sizeof(double),1,fp); fwrite(&size_one,sizeof(int),1,fp); - int len = strlen(columns); + int len = 0; + + if (unit_flag && !unit_count) { + ++unit_count; + len = strlen(update->unit_style); + fwrite(&len, sizeof(int), 1, fp); + fwrite(update->unit_style, sizeof(char), len, fp); + } else { + fwrite(&len, sizeof(int), 1, fp); + } + + len = strlen(columns); fwrite(&len, sizeof(int), 1, fp); fwrite(columns, sizeof(char), len, fp); + if (multiproc) fwrite(&nclusterprocs,sizeof(int),1,fp); else fwrite(&nprocs,sizeof(int),1,fp); } @@ -244,7 +257,18 @@ void DumpAtom::header_binary_triclinic(bigint ndump) fwrite(&boxyz,sizeof(double),1,fp); fwrite(&size_one,sizeof(int),1,fp); - int len = strlen(columns); + int len = 0; + + if (unit_flag && !unit_count) { + ++unit_count; + len = strlen(update->unit_style); + fwrite(&len, sizeof(int), 1, fp); + fwrite(update->unit_style, sizeof(char), len, fp); + } else { + fwrite(&len, sizeof(int), 1, fp); + } + + len = strlen(columns); fwrite(&len, sizeof(int), 1, fp); fwrite(columns, sizeof(char), len, fp); diff --git a/tools/binary2txt.cpp b/tools/binary2txt.cpp index d65e74b0d1..a2f000e22c 100644 --- a/tools/binary2txt.cpp +++ b/tools/binary2txt.cpp @@ -93,7 +93,7 @@ int main(int narg, char **arg) // detect newer format char * magic_string = nullptr; char * columns = nullptr; - + char * unit_style = nullptr; // loop over snapshots in file @@ -148,8 +148,20 @@ int main(int narg, char **arg) fread(&size_one,sizeof(int),1,fp); if (magic_string && revision > 0x0001) { - // newer format includes columns string + // newer format includes units and columns string 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+1] = '\0'; + fprintf(fptxt, "ITEM: UNITS\n"); + fprintf(fptxt, "%s\n", unit_style); + } + fread(&len, sizeof(int), 1, fp); delete [] columns; columns = new char[len+1]; @@ -229,6 +241,10 @@ int main(int narg, char **arg) printf("\n"); delete [] columns; delete [] magic_string; + delete [] unit_style; + columns = nullptr; + magic_string = nullptr; + unit_style = nullptr; } if (buf) delete [] buf; diff --git a/unittest/formats/test_dump.cpp b/unittest/formats/test_dump.cpp index bbcd151892..177770e130 100644 --- a/unittest/formats/test_dump.cpp +++ b/unittest/formats/test_dump.cpp @@ -270,6 +270,61 @@ TEST_F(DumpAtomTest, with_units_run1) delete_file("dump_with_units_run1.melt"); } +TEST_F(DumpAtomTest, binary_with_units_run0) +{ + if(!BINARY2TXT_BINARY) GTEST_SKIP(); + + if (!verbose) ::testing::internal::CaptureStdout(); + command("dump id0 all atom 1 dump_text_with_units_run0.melt"); + command("dump id1 all atom 1 dump_binary_with_units_run0.melt.bin"); + command("dump_modify id0 scale no units yes"); + command("dump_modify id1 scale no units yes"); + command("run 0"); + if (!verbose) ::testing::internal::GetCapturedStdout(); + + ASSERT_FILE_EXISTS("dump_text_with_units_run0.melt"); + ASSERT_FILE_EXISTS("dump_binary_with_units_run0.melt.bin"); + + if (!verbose) ::testing::internal::CaptureStdout(); + std::string cmdline = fmt::format("{} dump_binary_with_units_run0.melt.bin", BINARY2TXT_BINARY); + system(cmdline.c_str()); + if (!verbose) ::testing::internal::GetCapturedStdout(); + + ASSERT_FILE_EXISTS("dump_binary_with_units_run0.melt.bin.txt"); + ASSERT_FILE_EQUAL("dump_text_with_units_run0.melt", "dump_binary_with_units_run0.melt.bin.txt"); + delete_file("dump_text_with_units_run0.melt"); + delete_file("dump_binary_with_units_run0.melt.bin"); + delete_file("dump_binary_with_units_run0.melt.bin.txt"); +} + +TEST_F(DumpAtomTest, binary_triclinic_with_units_run0) +{ + if(!BINARY2TXT_BINARY) GTEST_SKIP(); + + if (!verbose) ::testing::internal::CaptureStdout(); + command("change_box all triclinic"); + command("dump id0 all atom 1 dump_text_tri_with_units_run0.melt"); + command("dump id1 all atom 1 dump_binary_tri_with_units_run0.melt.bin"); + command("dump_modify id0 scale no units yes"); + command("dump_modify id1 scale no units yes"); + command("run 0"); + if (!verbose) ::testing::internal::GetCapturedStdout(); + + ASSERT_FILE_EXISTS("dump_text_tri_with_units_run0.melt"); + ASSERT_FILE_EXISTS("dump_binary_tri_with_units_run0.melt.bin"); + + if (!verbose) ::testing::internal::CaptureStdout(); + std::string cmdline = fmt::format("{} dump_binary_tri_with_units_run0.melt.bin", BINARY2TXT_BINARY); + system(cmdline.c_str()); + if (!verbose) ::testing::internal::GetCapturedStdout(); + + ASSERT_FILE_EXISTS("dump_binary_tri_with_units_run0.melt.bin.txt"); + ASSERT_FILE_EQUAL("dump_text_tri_with_units_run0.melt", "dump_binary_tri_with_units_run0.melt.bin.txt"); + delete_file("dump_text_tri_with_units_run0.melt"); + delete_file("dump_binary_tri_with_units_run0.melt.bin"); + delete_file("dump_binary_tri_with_units_run0.melt.bin.txt"); +} + TEST_F(DumpAtomTest, no_buffer_with_scale_and_image_run0) { if (!verbose) ::testing::internal::CaptureStdout(); @@ -307,6 +362,28 @@ TEST_F(DumpAtomTest, tricilinic_run0) delete_file("dump_triclinic_run0.melt"); } +TEST_F(DumpAtomTest, tricilinic_with_units_run0) +{ + if (!verbose) ::testing::internal::CaptureStdout(); + + command("change_box all triclinic"); + command("dump id all atom 1 dump_triclinic_with_units_run0.melt"); + command("dump_modify id units yes"); + command("run 0"); + if (!verbose) ::testing::internal::GetCapturedStdout(); + + ASSERT_FILE_EXISTS("dump_triclinic_with_units_run0.melt"); + + auto lines = read_lines("dump_triclinic_with_units_run0.melt"); + ASSERT_STREQ(lines[0].c_str(), "ITEM: UNITS"); + ASSERT_STREQ(lines[1].c_str(), "lj"); + ASSERT_STREQ(lines[6].c_str(), "ITEM: BOX BOUNDS xy xz yz pp pp pp"); + ASSERT_EQ(utils::split_words(lines[7]).size(), 3); + + ASSERT_EQ(lines.size(), 43); + delete_file("dump_triclinic_with_units_run0.melt"); +} + TEST_F(DumpAtomTest, triclinic_with_image_run0) { if (!verbose) ::testing::internal::CaptureStdout();