1 /* ----------------------------------------------------------------------
2 LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
3 https://www.lammps.org/, Sandia National Laboratories
4 Steve Plimpton, sjplimp@sandia.gov
5
6 Copyright (2003) Sandia Corporation. Under the terms of Contract
7 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
8 certain rights in this software. This software is distributed under
9 the GNU General Public License.
10
11 See the README file in the top-level LAMMPS directory.
12 ------------------------------------------------------------------------- */
13
14 /* ----------------------------------------------------------------------
15 Contributing author: Richard Berger (Temple U)
16 ------------------------------------------------------------------------- */
17
18 #ifdef LAMMPS_ZSTD
19
20 #include "dump_cfg_zstd.h"
21
22 #include "atom.h"
23 #include "domain.h"
24 #include "error.h"
25 #include "file_writer.h"
26 #include "update.h"
27
28 #include <cstring>
29
30 using namespace LAMMPS_NS;
31 #define UNWRAPEXPAND 10.0
32
DumpCFGZstd(LAMMPS * lmp,int narg,char ** arg)33 DumpCFGZstd::DumpCFGZstd(LAMMPS *lmp, int narg, char **arg) : DumpCFG(lmp, narg, arg)
34 {
35 if (!compressed) error->all(FLERR, "Dump cfg/zstd only writes compressed files");
36 }
37
38 /* ---------------------------------------------------------------------- */
39
~DumpCFGZstd()40 DumpCFGZstd::~DumpCFGZstd() {}
41
42 /* ----------------------------------------------------------------------
43 generic opening of a dump file
44 ASCII or binary or compressed
45 some derived classes override this function
46 ------------------------------------------------------------------------- */
47
openfile()48 void DumpCFGZstd::openfile()
49 {
50 // single file, already opened, so just return
51
52 if (singlefile_opened) return;
53 if (multifile == 0) singlefile_opened = 1;
54
55 // if one file per timestep, replace '*' with current timestep
56
57 char *filecurrent = filename;
58 if (multiproc) filecurrent = multiname;
59
60 if (multifile) {
61 char *filestar = filecurrent;
62 filecurrent = new char[strlen(filestar) + 16];
63 char *ptr = strchr(filestar, '*');
64 *ptr = '\0';
65 if (padflag == 0)
66 sprintf(filecurrent, "%s" BIGINT_FORMAT "%s", filestar, update->ntimestep, ptr + 1);
67 else {
68 char bif[8], pad[16];
69 strcpy(bif, BIGINT_FORMAT);
70 sprintf(pad, "%%s%%0%d%s%%s", padflag, &bif[1]);
71 sprintf(filecurrent, pad, filestar, update->ntimestep, ptr + 1);
72 }
73 *ptr = '*';
74 if (maxfiles > 0) {
75 if (numfiles < maxfiles) {
76 nameslist[numfiles] = utils::strdup(filecurrent);
77 ++numfiles;
78 } else {
79 if (remove(nameslist[fileidx]) != 0) {
80 error->warning(FLERR, "Could not delete {}", nameslist[fileidx]);
81 }
82 delete[] nameslist[fileidx];
83 nameslist[fileidx] = utils::strdup(filecurrent);
84 fileidx = (fileidx + 1) % maxfiles;
85 }
86 }
87 }
88
89 // each proc with filewriter = 1 opens a file
90
91 if (filewriter) {
92 if (append_flag) { error->one(FLERR, "dump cfg/zstd currently doesn't support append"); }
93
94 try {
95 writer.open(filecurrent);
96 } catch (FileWriterException &e) {
97 error->one(FLERR, e.what());
98 }
99 }
100
101 // delete string with timestep replaced
102
103 if (multifile) delete[] filecurrent;
104 }
105
106 /* ---------------------------------------------------------------------- */
107
write_header(bigint n)108 void DumpCFGZstd::write_header(bigint n)
109 {
110 // set scale factor used by AtomEye for CFG viz
111 // default = 1.0
112 // for peridynamics, set to pre-computed PD scale factor
113 // so PD particles mimic C atoms
114 // for unwrapped coords, set to UNWRAPEXPAND (10.0)
115 // so molecules are not split across periodic box boundaries
116
117 double scale = 1.0;
118 if (atom->peri_flag)
119 scale = atom->pdscale;
120 else if (unwrapflag == 1)
121 scale = UNWRAPEXPAND;
122
123 std::string header = fmt::format("Number of particles = {}\n", n);
124 header += fmt::format("A = {0:g} Angstrom (basic length-scale)\n", scale);
125 header += fmt::format("H0(1,1) = {0:g} A\n", domain->xprd);
126 header += fmt::format("H0(1,2) = 0 A \n");
127 header += fmt::format("H0(1,3) = 0 A \n");
128 header += fmt::format("H0(2,1) = {0:g} A \n", domain->xy);
129 header += fmt::format("H0(2,2) = {0:g} A\n", domain->yprd);
130 header += fmt::format("H0(2,3) = 0 A \n");
131 header += fmt::format("H0(3,1) = {0:g} A \n", domain->xz);
132 header += fmt::format("H0(3,2) = {0:g} A \n", domain->yz);
133 header += fmt::format("H0(3,3) = {0:g} A\n", domain->zprd);
134 header += fmt::format(".NO_VELOCITY.\n");
135 header += fmt::format("entry_count = {}\n", nfield - 2);
136 for (int i = 0; i < nfield - 5; i++) header += fmt::format("auxiliary[{}] = {}\n", i, auxname[i]);
137
138 writer.write(header.c_str(), header.length());
139 }
140
141 /* ---------------------------------------------------------------------- */
142
write_data(int n,double * mybuf)143 void DumpCFGZstd::write_data(int n, double *mybuf)
144 {
145 if (buffer_flag) {
146 writer.write(mybuf, n);
147 } else {
148 constexpr size_t VBUFFER_SIZE = 256;
149 char vbuffer[VBUFFER_SIZE];
150 if (unwrapflag == 0) {
151 int m = 0;
152 for (int i = 0; i < n; i++) {
153 for (int j = 0; j < size_one; j++) {
154 int written = 0;
155 if (j == 0) {
156 written = snprintf(vbuffer, VBUFFER_SIZE, "%f \n", mybuf[m]);
157 } else if (j == 1) {
158 written = snprintf(vbuffer, VBUFFER_SIZE, "%s \n", typenames[(int) mybuf[m]]);
159 } else if (j >= 2) {
160 if (vtype[j] == Dump::INT)
161 written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast<int>(mybuf[m]));
162 else if (vtype[j] == Dump::DOUBLE)
163 written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]);
164 else if (vtype[j] == Dump::STRING)
165 written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], typenames[(int) mybuf[m]]);
166 else if (vtype[j] == Dump::BIGINT)
167 written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast<bigint>(mybuf[m]));
168 }
169 if (written > 0) {
170 writer.write(vbuffer, written);
171 } else if (written < 0) {
172 error->one(FLERR, "Error while writing dump cfg/gz output");
173 }
174 m++;
175 }
176 writer.write("\n", 1);
177 }
178 } else if (unwrapflag == 1) {
179 int m = 0;
180 for (int i = 0; i < n; i++) {
181 for (int j = 0; j < size_one; j++) {
182 int written = 0;
183 if (j == 0) {
184 written = snprintf(vbuffer, VBUFFER_SIZE, "%f \n", mybuf[m]);
185 } else if (j == 1) {
186 written = snprintf(vbuffer, VBUFFER_SIZE, "%s \n", typenames[(int) mybuf[m]]);
187 } else if (j >= 2 && j <= 4) {
188 double unwrap_coord = (mybuf[m] - 0.5) / UNWRAPEXPAND + 0.5;
189 written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], unwrap_coord);
190 } else if (j >= 5) {
191 if (vtype[j] == Dump::INT)
192 written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast<int>(mybuf[m]));
193 else if (vtype[j] == Dump::DOUBLE)
194 written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], mybuf[m]);
195 else if (vtype[j] == Dump::STRING)
196 written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], typenames[(int) mybuf[m]]);
197 else if (vtype[j] == Dump::BIGINT)
198 written = snprintf(vbuffer, VBUFFER_SIZE, vformat[j], static_cast<bigint>(mybuf[m]));
199 }
200 if (written > 0) {
201 writer.write(vbuffer, written);
202 } else if (written < 0) {
203 error->one(FLERR, "Error while writing dump cfg/gz output");
204 }
205 m++;
206 }
207 writer.write("\n", 1);
208 }
209 }
210 }
211 }
212
213 /* ---------------------------------------------------------------------- */
214
write()215 void DumpCFGZstd::write()
216 {
217 DumpCFG::write();
218 if (filewriter) {
219 if (multifile) {
220 writer.close();
221 } else {
222 if (flush_flag && writer.isopen()) { writer.flush(); }
223 }
224 }
225 }
226
227 /* ---------------------------------------------------------------------- */
228
modify_param(int narg,char ** arg)229 int DumpCFGZstd::modify_param(int narg, char **arg)
230 {
231 int consumed = DumpCFG::modify_param(narg, arg);
232 if (consumed == 0) {
233 try {
234 if (strcmp(arg[0], "checksum") == 0) {
235 if (narg < 2) error->all(FLERR, "Illegal dump_modify command");
236 if (strcmp(arg[1], "yes") == 0)
237 writer.setChecksum(true);
238 else if (strcmp(arg[1], "no") == 0)
239 writer.setChecksum(false);
240 else
241 error->all(FLERR, "Illegal dump_modify command");
242 return 2;
243 } else if (strcmp(arg[0], "compression_level") == 0) {
244 if (narg < 2) error->all(FLERR, "Illegal dump_modify command");
245 int compression_level = utils::inumeric(FLERR, arg[1], false, lmp);
246 writer.setCompressionLevel(compression_level);
247 return 2;
248 }
249 } catch (FileWriterException &e) {
250 error->one(FLERR, e.what());
251 }
252 }
253 return consumed;
254 }
255 #endif
256