1 // clang-format off
2 /* ----------------------------------------------------------------------
3 LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
4 https://www.lammps.org/, Sandia National Laboratories
5 Steve Plimpton, sjplimp@sandia.gov
6
7 Copyright (2003) Sandia Corporation. Under the terms of Contract
8 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
9 certain rights in this software. This software is distributed under
10 the GNU General Public License.
11
12 See the README file in the top-level LAMMPS directory.
13 ------------------------------------------------------------------------- */
14
15 /* ----------------------------------------------------------------------
16 Contributing author: Liang Wan (Chinese Academy of Sciences)
17 Memory efficiency improved by Ray Shan (Sandia)
18 ------------------------------------------------------------------------- */
19
20 #include "dump_cfg.h"
21
22 #include "arg_info.h"
23 #include "atom.h"
24 #include "domain.h"
25 #include "memory.h"
26 #include "error.h"
27
28 #include <cstring>
29
30 using namespace LAMMPS_NS;
31
32 #define UNWRAPEXPAND 10.0
33 #define ONEFIELD 32
34 #define DELTA 1048576
35
36 /* ---------------------------------------------------------------------- */
37
DumpCFG(LAMMPS * lmp,int narg,char ** arg)38 DumpCFG::DumpCFG(LAMMPS *lmp, int narg, char **arg) :
39 DumpCustom(lmp, narg, arg), auxname(nullptr)
40 {
41 multifile_override = 0;
42
43 // use earg instead of original arg since it includes expanded wildcards
44 // earg was created by parent DumpCustom
45
46 if (nfield < 5 ||
47 strcmp(earg[0],"mass") != 0 || strcmp(earg[1],"type") != 0 ||
48 (strcmp(earg[2],"xs") != 0 && strcmp(earg[2],"xsu") != 0) ||
49 (strcmp(earg[3],"ys") != 0 && strcmp(earg[3],"ysu") != 0) ||
50 (strcmp(earg[4],"zs") != 0 && strcmp(earg[4],"zsu") != 0))
51 error->all(FLERR,"Dump cfg arguments must start with "
52 "'mass type xs ys zs' or 'mass type xsu ysu zsu'");
53
54 if (strcmp(earg[2],"xs") == 0) {
55 if (strcmp(earg[3],"ysu") == 0 || strcmp(earg[4],"zsu") == 0)
56 error->all(FLERR,
57 "Dump cfg arguments can not mix xs|ys|zs with xsu|ysu|zsu");
58 unwrapflag = 0;
59 } else {
60 if (strcmp(earg[3],"ys") == 0 || strcmp(earg[4],"zs") == 0)
61 error->all(FLERR,
62 "Dump cfg arguments can not mix xs|ys|zs with xsu|ysu|zsu");
63 unwrapflag = 1;
64 }
65
66 // setup auxiliary property name strings
67 // convert 'X_ID[m]' (X=c,f,v) to 'X_ID_m'
68
69 if (nfield > 5) auxname = new char*[nfield];
70 else auxname = nullptr;
71
72 int i = 0;
73 for (int iarg = 5; iarg < nfield; iarg++, i++) {
74 ArgInfo argi(earg[iarg],ArgInfo::COMPUTE|ArgInfo::FIX|ArgInfo::VARIABLE
75 |ArgInfo::DNAME|ArgInfo::INAME);
76
77 if (argi.get_dim() == 1) {
78 std::string newarg = fmt::format("{}_{}_{}", earg[iarg][0], argi.get_name(), argi.get_index1());
79 auxname[i] = utils::strdup(newarg);
80 } else {
81 auxname[i] = utils::strdup(earg[iarg]);
82 }
83 }
84 }
85
86 /* ---------------------------------------------------------------------- */
87
~DumpCFG()88 DumpCFG::~DumpCFG()
89 {
90 if (auxname) {
91 for (int i = 0; i < nfield-5; i++) delete [] auxname[i];
92 delete [] auxname;
93 }
94 }
95
96 /* ---------------------------------------------------------------------- */
97
init_style()98 void DumpCFG::init_style()
99 {
100 if (multifile == 0 && !multifile_override)
101 error->all(FLERR,"Dump cfg requires one snapshot per file");
102
103 DumpCustom::init_style();
104
105 // setup function ptrs
106
107 if (buffer_flag == 1) write_choice = &DumpCFG::write_string;
108 else write_choice = &DumpCFG::write_lines;
109 }
110
111 /* ---------------------------------------------------------------------- */
112
write_header(bigint n)113 void DumpCFG::write_header(bigint n)
114 {
115 // set scale factor used by AtomEye for CFG viz
116 // default = 1.0
117 // for peridynamics, set to pre-computed PD scale factor
118 // so PD particles mimic C atoms
119 // for unwrapped coords, set to UNWRAPEXPAND (10.0)
120 // so molecules are not split across periodic box boundaries
121
122 double scale = 1.0;
123 if (atom->peri_flag) scale = atom->pdscale;
124 else if (unwrapflag == 1) scale = UNWRAPEXPAND;
125
126 fprintf(fp,"Number of particles = " BIGINT_FORMAT "\n", n);
127 fprintf(fp,"A = %g Angstrom (basic length-scale)\n",scale);
128 fprintf(fp,"H0(1,1) = %g A\n",domain->xprd);
129 fprintf(fp,"H0(1,2) = 0 A \n");
130 fprintf(fp,"H0(1,3) = 0 A \n");
131 fprintf(fp,"H0(2,1) = %g A \n",domain->xy);
132 fprintf(fp,"H0(2,2) = %g A\n",domain->yprd);
133 fprintf(fp,"H0(2,3) = 0 A \n");
134 fprintf(fp,"H0(3,1) = %g A \n",domain->xz);
135 fprintf(fp,"H0(3,2) = %g A \n",domain->yz);
136 fprintf(fp,"H0(3,3) = %g A\n",domain->zprd);
137 fprintf(fp,".NO_VELOCITY.\n");
138 fprintf(fp,"entry_count = %d\n",nfield-2);
139 for (int i = 0; i < nfield-5; i++)
140 fprintf(fp,"auxiliary[%d] = %s\n",i,auxname[i]);
141 }
142
143 /* ----------------------------------------------------------------------
144 convert mybuf of doubles to one big formatted string in sbuf
145 return -1 if strlen exceeds an int, since used as arg in MPI calls in Dump
146 ------------------------------------------------------------------------- */
147
convert_string(int n,double * mybuf)148 int DumpCFG::convert_string(int n, double *mybuf)
149 {
150 int i,j;
151
152 int offset = 0;
153 int m = 0;
154
155 if (unwrapflag == 0) {
156 for (i = 0; i < n; i++) {
157 if (offset + size_one*ONEFIELD > maxsbuf) {
158 if ((bigint) maxsbuf + DELTA > MAXSMALLINT) return -1;
159 maxsbuf += DELTA;
160 memory->grow(sbuf,maxsbuf,"dump:sbuf");
161 }
162
163 for (j = 0; j < size_one; j++) {
164 if (j == 0) {
165 offset += sprintf(&sbuf[offset],"%f \n",mybuf[m]);
166 } else if (j == 1) {
167 offset += sprintf(&sbuf[offset],"%s \n",typenames[(int) mybuf[m]]);
168 } else if (j >= 2) {
169 if (vtype[j] == Dump::INT)
170 offset +=
171 sprintf(&sbuf[offset],vformat[j],static_cast<int> (mybuf[m]));
172 else if (vtype[j] == Dump::DOUBLE)
173 offset += sprintf(&sbuf[offset],vformat[j],mybuf[m]);
174 else if (vtype[j] == Dump::STRING)
175 offset +=
176 sprintf(&sbuf[offset],vformat[j],typenames[(int) mybuf[m]]);
177 else if (vtype[j] == Dump::BIGINT)
178 offset +=
179 sprintf(&sbuf[offset],vformat[j],static_cast<bigint> (mybuf[m]));
180 }
181 m++;
182 }
183 offset += sprintf(&sbuf[offset],"\n");
184 }
185
186 } else if (unwrapflag == 1) {
187 double unwrap_coord;
188 for (i = 0; i < n; i++) {
189 if (offset + size_one*ONEFIELD > maxsbuf) {
190 if ((bigint) maxsbuf + DELTA > MAXSMALLINT) return -1;
191 maxsbuf += DELTA;
192 memory->grow(sbuf,maxsbuf,"dump:sbuf");
193 }
194
195 for (j = 0; j < size_one; j++) {
196 if (j == 0) {
197 offset += sprintf(&sbuf[offset],"%f \n",mybuf[m]);
198 } else if (j == 1) {
199 offset += sprintf(&sbuf[offset],"%s \n",typenames[(int) mybuf[m]]);
200 } else if (j >= 2 && j <= 4) {
201 unwrap_coord = (mybuf[m] - 0.5)/UNWRAPEXPAND + 0.5;
202 offset += sprintf(&sbuf[offset],vformat[j],unwrap_coord);
203 } else if (j >= 5) {
204 if (vtype[j] == Dump::INT)
205 offset +=
206 sprintf(&sbuf[offset],vformat[j],static_cast<int> (mybuf[m]));
207 else if (vtype[j] == Dump::DOUBLE)
208 offset += sprintf(&sbuf[offset],vformat[j],mybuf[m]);
209 else if (vtype[j] == Dump::STRING)
210 offset +=
211 sprintf(&sbuf[offset],vformat[j],typenames[(int) mybuf[m]]);
212 else if (vtype[j] == Dump::BIGINT)
213 offset +=
214 sprintf(&sbuf[offset],vformat[j],static_cast<bigint> (mybuf[m]));
215 }
216 m++;
217 }
218 offset += sprintf(&sbuf[offset],"\n");
219 }
220 }
221
222 return offset;
223 }
224
225 /* ---------------------------------------------------------------------- */
226
write_data(int n,double * mybuf)227 void DumpCFG::write_data(int n, double *mybuf)
228 {
229 (this->*write_choice)(n,mybuf);
230 }
231
232 /* ---------------------------------------------------------------------- */
233
write_string(int n,double * mybuf)234 void DumpCFG::write_string(int n, double *mybuf)
235 {
236 if (mybuf)
237 fwrite(mybuf,sizeof(char),n,fp);
238 }
239
240 /* ---------------------------------------------------------------------- */
241
write_lines(int n,double * mybuf)242 void DumpCFG::write_lines(int n, double *mybuf)
243 {
244 int i,j,m;
245
246 if (unwrapflag == 0) {
247 m = 0;
248 for (i = 0; i < n; i++) {
249 for (j = 0; j < size_one; j++) {
250 if (j == 0) {
251 fprintf(fp,"%f \n",mybuf[m]);
252 } else if (j == 1) {
253 fprintf(fp,"%s \n",typenames[(int) mybuf[m]]);
254 } else if (j >= 2) {
255 if (vtype[j] == Dump::INT)
256 fprintf(fp,vformat[j],static_cast<int> (mybuf[m]));
257 else if (vtype[j] == Dump::DOUBLE)
258 fprintf(fp,vformat[j],mybuf[m]);
259 else if (vtype[j] == Dump::STRING)
260 fprintf(fp,vformat[j],typenames[(int) mybuf[m]]);
261 else if (vtype[j] == Dump::BIGINT)
262 fprintf(fp,vformat[j],static_cast<bigint> (mybuf[m]));
263 }
264 m++;
265 }
266 fprintf(fp,"\n");
267 }
268 } else if (unwrapflag == 1) {
269 m = 0;
270 double unwrap_coord;
271 for (i = 0; i < n; i++) {
272 for (j = 0; j < size_one; j++) {
273 if (j == 0) {
274 fprintf(fp,"%f \n",mybuf[m]);
275 } else if (j == 1) {
276 fprintf(fp,"%s \n",typenames[(int) mybuf[m]]);
277 } else if (j >= 2 && j <= 4) {
278 unwrap_coord = (mybuf[m] - 0.5)/UNWRAPEXPAND + 0.5;
279 fprintf(fp,vformat[j],unwrap_coord);
280 } else if (j >= 5) {
281 if (vtype[j] == Dump::INT)
282 fprintf(fp,vformat[j],static_cast<int> (mybuf[m]));
283 else if (vtype[j] == Dump::DOUBLE)
284 fprintf(fp,vformat[j],mybuf[m]);
285 else if (vtype[j] == Dump::STRING)
286 fprintf(fp,vformat[j],typenames[(int) mybuf[m]]);
287 else if (vtype[j] == Dump::BIGINT)
288 fprintf(fp,vformat[j],static_cast<bigint> (mybuf[m]));
289 }
290 m++;
291 }
292 fprintf(fp,"\n");
293 }
294 }
295 }
296