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