From 17f869bf5e78458385d6eacf180e2f0f57b50f8a Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Wed, 31 Jan 2024 20:20:35 -0500 Subject: [PATCH] fix issues with reading and writing data files for systems without atom IDs --- src/atom_vec.cpp | 2 +- src/read_data.cpp | 17 ++++- src/write_data.cpp | 11 ++- unittest/formats/test_atom_styles.cpp | 106 ++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 6 deletions(-) diff --git a/src/atom_vec.cpp b/src/atom_vec.cpp index bfda951823..8ea1d145eb 100644 --- a/src/atom_vec.cpp +++ b/src/atom_vec.cpp @@ -1714,7 +1714,7 @@ void AtomVec::data_atom(double *coord, imageint imagetmp, const std::vectortag_enable && (tag[nlocal] <= 0)) || (!atom->tag_enable && (tag[nlocal] != 0))) error->one(FLERR, "Invalid atom ID {} in line {} of Atoms section of data file", tag[nlocal], nlocal + 1); diff --git a/src/read_data.cpp b/src/read_data.cpp index dcc0f7b46c..657369d5d0 100644 --- a/src/read_data.cpp +++ b/src/read_data.cpp @@ -1465,8 +1465,23 @@ void ReadData::atoms() void ReadData::velocities() { + bigint nread = 0; int nchunk, eof; + // cannot map velocities to atoms without atom IDs + + if (!atom->tag_enable) { + if (me == 0) utils::logmesg(lmp, " skipping velocities without atom IDs ...\n"); + + while (nread < natoms) { + nchunk = MIN(natoms - nread, CHUNK); + eof = utils::read_lines_from_file(fp, nchunk, MAXLINE, buffer, me, world); + if (eof) error->all(FLERR, "Unexpected end of data file"); + nread += nchunk; + } + return; + } + if (me == 0) utils::logmesg(lmp, " reading velocities ...\n"); int mapflag = 0; @@ -1476,8 +1491,6 @@ void ReadData::velocities() atom->map_set(); } - bigint nread = 0; - while (nread < natoms) { nchunk = MIN(natoms - nread, CHUNK); eof = utils::read_lines_from_file(fp, nchunk, MAXLINE, buffer, me, world); diff --git a/src/write_data.cpp b/src/write_data.cpp index dd5b056ae8..5454edab44 100644 --- a/src/write_data.cpp +++ b/src/write_data.cpp @@ -191,8 +191,7 @@ void WriteData::write(const std::string &file) if (me == 0) { fp = fopen(file.c_str(),"w"); if (fp == nullptr) - error->one(FLERR,"Cannot open data file {}: {}", - file, utils::getsyserror()); + error->one(FLERR,"Cannot open data file {}: {}", file, utils::getsyserror()); } // proc 0 writes header, ntype-length arrays, force fields @@ -206,9 +205,15 @@ void WriteData::write(const std::string &file) } // per atom info in Atoms and Velocities sections + // must not write velocities without tags since we cannot read them back if (natoms) atoms(); - if (natoms) velocities(); + if (atom->tag_enable) { + if (natoms) velocities(); + } else { + if (me == 0) + error->warning(FLERR, "Not writing Velocities section of data file without atom IDs"); + } // molecular topology info if defined // do not write molecular topology for atom_style template diff --git a/unittest/formats/test_atom_styles.cpp b/unittest/formats/test_atom_styles.cpp index 39e93b6edf..1da2dfa33c 100644 --- a/unittest/formats/test_atom_styles.cpp +++ b/unittest/formats/test_atom_styles.cpp @@ -693,6 +693,112 @@ TEST_F(AtomStyleTest, atomic) EXPECT_NEAR(x[GETIDX(16)][2], 7.9, EPSILON); } +TEST_F(AtomStyleTest, no_tags) +{ + BEGIN_HIDE_OUTPUT(); + command("atom_modify id no"); + command("create_box 2 box"); + command("create_atoms 1 single -2.0 2.0 0.1"); + command("create_atoms 1 single -2.0 -2.0 -0.1"); + command("create_atoms 2 single 2.0 2.0 -0.1"); + command("create_atoms 2 single 2.0 -2.0 0.1"); + command("mass 1 4.0"); + command("mass 2 2.4"); + command("pair_coeff * *"); + END_HIDE_OUTPUT(); + + ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); + ASSERT_NE(lmp->atom->avec, nullptr); + ASSERT_EQ(lmp->atom->natoms, 4); + ASSERT_EQ(lmp->atom->nlocal, 4); + ASSERT_EQ(lmp->atom->nghost, 0); + ASSERT_NE(lmp->atom->nmax, -1); + ASSERT_EQ(lmp->atom->tag_enable, 0); + ASSERT_EQ(lmp->atom->molecular, Atom::ATOMIC); + ASSERT_EQ(lmp->atom->ntypes, 2); + + ASSERT_NE(lmp->atom->mass, nullptr); + ASSERT_NE(lmp->atom->mass_setflag, nullptr); + ASSERT_EQ(lmp->atom->sametag, nullptr); + ASSERT_EQ(lmp->atom->map_style, Atom::MAP_NONE); + ASSERT_EQ(lmp->atom->map_user, Atom::MAP_NONE); + ASSERT_EQ(lmp->atom->map_tag_max, -1); + ASSERT_EQ(lmp->atom->tag_consecutive(), 0); + + BEGIN_HIDE_OUTPUT(); + command("pair_coeff * *"); + command("write_data test_atom_styles.data nocoeff"); + command("clear"); + command("atom_style atomic"); + command("pair_style zero 4.0"); + command("atom_modify id no"); + command("units real"); + command("read_data test_atom_styles.data"); + END_HIDE_OUTPUT(); + ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); + ASSERT_NE(lmp->atom->avec, nullptr); + ASSERT_EQ(lmp->atom->natoms, 4); + ASSERT_EQ(lmp->atom->nlocal, 4); + ASSERT_EQ(lmp->atom->nghost, 0); + ASSERT_NE(lmp->atom->nmax, -1); + ASSERT_EQ(lmp->atom->tag_enable, 0); + ASSERT_EQ(lmp->atom->molecular, Atom::ATOMIC); + ASSERT_EQ(lmp->atom->ntypes, 2); + + ASSERT_NEAR(lmp->atom->mass[1], 4.0, EPSILON); + ASSERT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); + ASSERT_EQ(lmp->atom->mass_setflag[1], 1); + ASSERT_EQ(lmp->atom->mass_setflag[2], 1); + ASSERT_EQ(lmp->atom->map_style, Atom::MAP_NONE); + ASSERT_EQ(lmp->atom->map_user, Atom::MAP_NONE); + ASSERT_EQ(lmp->atom->map_tag_max, -1); + ASSERT_EQ(lmp->atom->tag_consecutive(), 0); + + BEGIN_HIDE_OUTPUT(); + command("pair_coeff * *"); + command("write_restart test_atom_styles.restart"); + command("clear"); + command("read_restart test_atom_styles.restart"); + END_HIDE_OUTPUT(); + ASSERT_THAT(std::string(lmp->atom->atom_style), Eq("atomic")); + ASSERT_NE(lmp->atom->avec, nullptr); + ASSERT_EQ(lmp->atom->natoms, 4); + ASSERT_EQ(lmp->atom->nlocal, 4); + ASSERT_EQ(lmp->atom->nghost, 0); + ASSERT_NE(lmp->atom->nmax, -1); + ASSERT_EQ(lmp->atom->tag_enable, 0); + ASSERT_EQ(lmp->atom->molecular, Atom::ATOMIC); + ASSERT_EQ(lmp->atom->ntypes, 2); + ASSERT_EQ(lmp->atom->tag_consecutive(), 0); + + ASSERT_NEAR(lmp->atom->mass[1], 4.0, EPSILON); + ASSERT_NEAR(lmp->atom->mass[2], 2.4, EPSILON); + ASSERT_EQ(lmp->atom->mass_setflag[1], 1); + ASSERT_EQ(lmp->atom->mass_setflag[2], 1); + ASSERT_EQ(lmp->atom->map_style, Atom::MAP_NONE); + ASSERT_EQ(lmp->atom->map_user, Atom::MAP_NONE); + ASSERT_EQ(lmp->atom->map_tag_max, -1); + + BEGIN_HIDE_OUTPUT(); + command("comm_style tiled"); + command("change_box all triclinic"); + command("replicate 2 2 2"); + END_HIDE_OUTPUT(); + + ASSERT_EQ(lmp->atom->natoms, 32); + ASSERT_EQ(lmp->atom->nlocal, 32); + ASSERT_EQ(lmp->atom->nghost, 0); + ASSERT_NE(lmp->atom->nmax, -1); + ASSERT_EQ(lmp->atom->tag_enable, 0); + ASSERT_EQ(lmp->atom->molecular, Atom::ATOMIC); + ASSERT_EQ(lmp->atom->ntypes, 2); + ASSERT_EQ(lmp->atom->tag_consecutive(), 0); + ASSERT_EQ(lmp->atom->map_tag_max, -1); + + TEST_FAILURE(".*ERROR: Cannot use reset_atoms id unless atoms have IDs.*", + command("reset_atoms id");); +} + TEST_F(AtomStyleTest, charge) { BEGIN_HIDE_OUTPUT();