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 #include "dump_image.h"
16
17 #include "atom.h"
18 #include "atom_vec.h"
19 #include "atom_vec_body.h"
20 #include "atom_vec_line.h"
21 #include "atom_vec_tri.h"
22 #include "body.h"
23 #include "comm.h"
24 #include "domain.h"
25 #include "error.h"
26 #include "fix.h"
27 #include "force.h"
28 #include "image.h"
29 #include "input.h"
30 #include "math_const.h"
31 #include "math_extra.h"
32 #include "memory.h"
33 #include "modify.h"
34 #include "molecule.h"
35 #include "tokenizer.h"
36 #include "variable.h"
37
38 #include <cmath>
39 #include <cctype>
40 #include <cstring>
41
42 using namespace LAMMPS_NS;
43 using namespace MathConst;
44
45 #define BIG 1.0e20
46
47 enum{NUMERIC,ATOM,TYPE,ELEMENT,ATTRIBUTE};
48 enum{SPHERE,LINE,TRI}; // also in some Body and Fix child classes
49 enum{STATIC,DYNAMIC};
50 enum{NO,YES};
51
52 /* ---------------------------------------------------------------------- */
53
DumpImage(LAMMPS * lmp,int narg,char ** arg)54 DumpImage::DumpImage(LAMMPS *lmp, int narg, char **arg) :
55 DumpCustom(lmp, narg, arg), thetastr(nullptr), phistr(nullptr), cxstr(nullptr),
56 cystr(nullptr), czstr(nullptr), upxstr(nullptr), upystr(nullptr), upzstr(nullptr),
57 zoomstr(nullptr), diamtype(nullptr), diamelement(nullptr),
58 bdiamtype(nullptr), colortype(nullptr), colorelement(nullptr), bcolortype(nullptr),
59 avec_line(nullptr), avec_tri(nullptr), avec_body(nullptr), fixptr(nullptr), image(nullptr),
60 chooseghost(nullptr), bufcopy(nullptr)
61 {
62 if (binary || multiproc) error->all(FLERR,"Invalid dump image filename");
63
64 // force binary flag on to avoid corrupted output on Windows
65
66 binary = 1;
67 multifile_override = 0;
68
69 // set filetype based on filename suffix
70
71 int n = strlen(filename);
72 if (strlen(filename) > 4 && strcmp(&filename[n-4],".jpg") == 0)
73 filetype = JPG;
74 else if (strlen(filename) > 4 && strcmp(&filename[n-4],".JPG") == 0)
75 filetype = JPG;
76 else if (strlen(filename) > 5 && strcmp(&filename[n-5],".jpeg") == 0)
77 filetype = JPG;
78 else if (strlen(filename) > 5 && strcmp(&filename[n-5],".JPEG") == 0)
79 filetype = JPG;
80 else if (strlen(filename) > 4 && strcmp(&filename[n-4],".png") == 0)
81 filetype = PNG;
82 else if (strlen(filename) > 4 && strcmp(&filename[n-4],".PNG") == 0)
83 filetype = PNG;
84 else filetype = PPM;
85
86 #ifndef LAMMPS_JPEG
87 if (filetype == JPG)
88 error->all(FLERR,"Support for writing images in JPEG format not included");
89 #endif
90 #ifndef LAMMPS_PNG
91 if (filetype == PNG)
92 error->all(FLERR,"Support for writing images in PNG format not included");
93 #endif
94
95 // atom color,diameter settings
96
97 if (nfield != 2) error->all(FLERR,"Illegal dump image command");
98
99 acolor = ATTRIBUTE;
100 if (strcmp(arg[5],"type") == 0) acolor = TYPE;
101 else if (strcmp(arg[5],"element") == 0) acolor = ELEMENT;
102
103 adiam = ATTRIBUTE;
104 if (strcmp(arg[6],"type") == 0) adiam = TYPE;
105 else if (strcmp(arg[6],"element") == 0) adiam = ELEMENT;
106
107 // create Image class with single colormap for atoms
108 // change defaults for 2d
109
110 image = new Image(lmp,1);
111
112 if (domain->dimension == 2) {
113 image->theta = 0.0;
114 image->phi = 0.0;
115 image->up[0] = 0.0; image->up[1] = 1.0; image->up[2] = 0.0;
116 }
117
118 // set defaults for optional args
119
120 atomflag = YES;
121 lineflag = triflag = bodyflag = fixflag = NO;
122 if (atom->nbondtypes == 0) bondflag = NO;
123 else {
124 bondflag = YES;
125 bcolor = ATOM;
126 bdiam = NUMERIC;
127 bdiamvalue = 0.5;
128 }
129 char *fixID = nullptr;
130
131 thetastr = phistr = nullptr;
132 cflag = STATIC;
133 cx = cy = cz = 0.5;
134 cxstr = cystr = czstr = nullptr;
135
136 upxstr = upystr = upzstr = nullptr;
137 zoomstr = nullptr;
138 boxflag = YES;
139 boxdiam = 0.02;
140 axesflag = NO;
141 subboxflag = NO;
142
143 // parse optional args
144
145 int iarg = ioptional;
146 while (iarg < narg) {
147 if (strcmp(arg[iarg],"atom") == 0) {
148 if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command");
149 if (strcmp(arg[iarg+1],"yes") == 0) atomflag = YES;
150 else if (strcmp(arg[iarg+1],"no") == 0) atomflag = NO;
151 else error->all(FLERR,"Illegal dump image command");
152 iarg += 2;
153
154 } else if (strcmp(arg[iarg],"adiam") == 0) {
155 if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command");
156 adiam = NUMERIC;
157 adiamvalue = utils::numeric(FLERR,arg[iarg+1],false,lmp);
158 if (adiamvalue <= 0.0) error->all(FLERR,"Illegal dump image command");
159 iarg += 2;
160
161 } else if (strcmp(arg[iarg],"bond") == 0) {
162 if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
163 if (atom->nbondtypes == 0)
164 error->all(FLERR,"Dump image bond not allowed with no bond types");
165 bondflag = YES;
166 if (strcmp(arg[iarg+1],"none") == 0) bondflag = NO;
167 else if (strcmp(arg[iarg+1],"atom") == 0) bcolor = ATOM;
168 else if (strcmp(arg[iarg+1],"type") == 0) bcolor = TYPE;
169 else error->all(FLERR,"Illegal dump image command");
170 if (!islower(arg[iarg+2][0])) {
171 bdiam = NUMERIC;
172 bdiamvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp);
173 if (bdiamvalue <= 0.0) error->all(FLERR,"Illegal dump image command");
174 } else if (strcmp(arg[iarg+2],"atom") == 0) bdiam = ATOM;
175 else if (strcmp(arg[iarg+2],"type") == 0) bdiam = TYPE;
176 else if (strcmp(arg[iarg+2],"none") == 0) bondflag = NO;
177 else error->all(FLERR,"Illegal dump image command");
178 iarg += 3;
179
180
181 } else if (strcmp(arg[iarg],"line") == 0) {
182 if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
183 lineflag = YES;
184 if (strcmp(arg[iarg+1],"type") == 0) lcolor = TYPE;
185 else error->all(FLERR,"Illegal dump image command");
186 ldiam = NUMERIC;
187 ldiamvalue = utils::numeric(FLERR,arg[iarg+2],false,lmp);
188 iarg += 3;
189
190 } else if (strcmp(arg[iarg],"tri") == 0) {
191 if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command");
192 triflag = YES;
193 if (strcmp(arg[iarg+1],"type") == 0) tcolor = TYPE;
194 else error->all(FLERR,"Illegal dump image command");
195 tstyle = utils::inumeric(FLERR,arg[iarg+2],false,lmp);
196 tdiamvalue = utils::numeric(FLERR,arg[iarg+3],false,lmp);
197 iarg += 4;
198
199 } else if (strcmp(arg[iarg],"body") == 0) {
200 if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command");
201 bodyflag = YES;
202 if (strcmp(arg[iarg+1],"type") == 0) bodycolor = TYPE;
203 else error->all(FLERR,"Illegal dump image command");
204 bodyflag1 = utils::numeric(FLERR,arg[iarg+2],false,lmp);
205 bodyflag2 = utils::numeric(FLERR,arg[iarg+3],false,lmp);
206 iarg += 4;
207
208 } else if (strcmp(arg[iarg],"fix") == 0) {
209 if (iarg+5 > narg) error->all(FLERR,"Illegal dump image command");
210 fixflag = YES;
211 fixID = arg[iarg+1];
212 if (strcmp(arg[iarg+2],"type") == 0) fixcolor = TYPE;
213 else error->all(FLERR,"Illegal dump image command");
214 fixflag1 = utils::numeric(FLERR,arg[iarg+3],false,lmp);
215 fixflag2 = utils::numeric(FLERR,arg[iarg+4],false,lmp);
216 iarg += 5;
217
218 } else if (strcmp(arg[iarg],"size") == 0) {
219 if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
220 int width = utils::inumeric(FLERR,arg[iarg+1],false,lmp);
221 int height = utils::inumeric(FLERR,arg[iarg+2],false,lmp);
222 if (width <= 0 || height <= 0)
223 error->all(FLERR,"Illegal dump image command");
224 image->width = width;
225 image->height = height;
226 iarg += 3;
227
228 } else if (strcmp(arg[iarg],"view") == 0) {
229 if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
230 if (utils::strmatch(arg[iarg+1],"^v_")) {
231 thetastr = utils::strdup(arg[iarg+1]+2);
232 } else {
233 double theta = utils::numeric(FLERR,arg[iarg+1],false,lmp);
234 if (theta < 0.0 || theta > 180.0)
235 error->all(FLERR,"Invalid dump image theta value");
236 theta *= MY_PI/180.0;
237 image->theta = theta;
238 }
239 if (utils::strmatch(arg[iarg+2],"^v_")) {
240 phistr = utils::strdup(arg[iarg+2]+2);
241 } else {
242 double phi = utils::numeric(FLERR,arg[iarg+2],false,lmp);
243 phi *= MY_PI/180.0;
244 image->phi = phi;
245 }
246 iarg += 3;
247
248 } else if (strcmp(arg[iarg],"center") == 0) {
249 if (iarg+5 > narg) error->all(FLERR,"Illegal dump image command");
250 if (strcmp(arg[iarg+1],"s") == 0) cflag = STATIC;
251 else if (strcmp(arg[iarg+1],"d") == 0) cflag = DYNAMIC;
252 else error->all(FLERR,"Illegal dump image command");
253 if (utils::strmatch(arg[iarg+2],"^v_")) {
254 cxstr = utils::strdup(arg[iarg+2]+2);
255 cflag = DYNAMIC;
256 } else cx = utils::numeric(FLERR,arg[iarg+2],false,lmp);
257 if (utils::strmatch(arg[iarg+3],"^v_")) {
258 cystr = utils::strdup(arg[iarg+3]+2);
259 cflag = DYNAMIC;
260 } else cy = utils::numeric(FLERR,arg[iarg+3],false,lmp);
261 if (utils::strmatch(arg[iarg+4],"^v_")) {
262 czstr = utils::strdup(arg[iarg+4]+2);
263 cflag = DYNAMIC;
264 } else cz = utils::numeric(FLERR,arg[iarg+4],false,lmp);
265 iarg += 5;
266
267 } else if (strcmp(arg[iarg],"up") == 0) {
268 if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command");
269 if (utils::strmatch(arg[iarg+1],"^v_")) {
270 upxstr = utils::strdup(arg[iarg+1]+2);
271 } else image->up[0] = utils::numeric(FLERR,arg[iarg+1],false,lmp);
272 if (utils::strmatch(arg[iarg+2],"^v_")) {
273 upystr = utils::strdup(arg[iarg+2]+2);
274 } else image->up[1] = utils::numeric(FLERR,arg[iarg+2],false,lmp);
275 if (utils::strmatch(arg[iarg+3],"^v_")) {
276 upzstr = utils::strdup(arg[iarg+3]+2);
277 } else image->up[2] = utils::numeric(FLERR,arg[iarg+3],false,lmp);
278 iarg += 4;
279
280 } else if (strcmp(arg[iarg],"zoom") == 0) {
281 if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command");
282 if (utils::strmatch(arg[iarg+1],"^v_")) {
283 zoomstr = utils::strdup(arg[iarg+1]+2);
284 } else {
285 double zoom = utils::numeric(FLERR,arg[iarg+1],false,lmp);
286 if (zoom <= 0.0) error->all(FLERR,"Illegal dump image command");
287 image->zoom = zoom;
288 }
289 iarg += 2;
290
291 } else if (strcmp(arg[iarg],"box") == 0) {
292 if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
293 if (strcmp(arg[iarg+1],"yes") == 0) boxflag = YES;
294 else if (strcmp(arg[iarg+1],"no") == 0) boxflag = NO;
295 else error->all(FLERR,"Illegal dump image command");
296 boxdiam = utils::numeric(FLERR,arg[iarg+2],false,lmp);
297 if (boxdiam < 0.0) error->all(FLERR,"Illegal dump image command");
298 iarg += 3;
299
300 } else if (strcmp(arg[iarg],"axes") == 0) {
301 if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
302 if (strcmp(arg[iarg+1],"yes") == 0) axesflag = YES;
303 else if (strcmp(arg[iarg+1],"no") == 0) axesflag = NO;
304 else error->all(FLERR,"Illegal dump image command");
305 axeslen = utils::numeric(FLERR,arg[iarg+2],false,lmp);
306 axesdiam = utils::numeric(FLERR,arg[iarg+3],false,lmp);
307 if (axeslen < 0.0 || axesdiam < 0.0)
308 error->all(FLERR,"Illegal dump image command");
309 iarg += 4;
310
311 } else if (strcmp(arg[iarg],"subbox") == 0) {
312 if (iarg+3 > narg) error->all(FLERR,"Illegal dump image command");
313 if (strcmp(arg[iarg+1],"yes") == 0) subboxflag = YES;
314 else if (strcmp(arg[iarg+1],"no") == 0) subboxflag = NO;
315 else error->all(FLERR,"Illegal dump image command");
316 subboxdiam = utils::numeric(FLERR,arg[iarg+2],false,lmp);
317 if (subboxdiam < 0.0) error->all(FLERR,"Illegal dump image command");
318 iarg += 3;
319
320 } else if (strcmp(arg[iarg],"shiny") == 0) {
321 if (iarg+2 > narg) error->all(FLERR,"Illegal dump image command");
322 double shiny = utils::numeric(FLERR,arg[iarg+1],false,lmp);
323 if (shiny < 0.0 || shiny > 1.0)
324 error->all(FLERR,"Illegal dump image command");
325 image->shiny = shiny;
326 iarg += 2;
327
328 } else if (strcmp(arg[iarg],"ssao") == 0) {
329 if (iarg+4 > narg) error->all(FLERR,"Illegal dump image command");
330 if (strcmp(arg[iarg+1],"yes") == 0) image->ssao = YES;
331 else if (strcmp(arg[iarg+1],"no") == 0) image->ssao = NO;
332 else error->all(FLERR,"Illegal dump image command");
333 int seed = utils::inumeric(FLERR,arg[iarg+2],false,lmp);
334 if (seed <= 0) error->all(FLERR,"Illegal dump image command");
335 image->seed = seed;
336 double ssaoint = utils::numeric(FLERR,arg[iarg+3],false,lmp);
337 if (ssaoint < 0.0 || ssaoint > 1.0)
338 error->all(FLERR,"Illegal dump image command");
339 image->ssaoint = ssaoint;
340 iarg += 4;
341
342 } else error->all(FLERR,"Illegal dump image command");
343 }
344
345 // error checks and setup for lineflag, triflag, bodyflag, fixflag
346
347 if (lineflag) {
348 avec_line = (AtomVecLine *) atom->style_match("line");
349 if (!avec_line)
350 error->all(FLERR,"Dump image line requires atom style line");
351 }
352 if (triflag) {
353 avec_tri = (AtomVecTri *) atom->style_match("tri");
354 if (!avec_tri)
355 error->all(FLERR,"Dump image tri requires atom style tri");
356 }
357 if (bodyflag) {
358 avec_body = (AtomVecBody *) atom->style_match("body");
359 if (!avec_body)
360 error->all(FLERR,"Dump image body yes requires atom style body");
361 }
362
363 extraflag = 0;
364 if (lineflag || triflag || bodyflag) extraflag = 1;
365
366 if (fixflag) {
367 int ifix = modify->find_fix(fixID);
368 if (ifix < 0) error->all(FLERR,"Fix ID for dump image does not exist");
369 fixptr = modify->fix[ifix];
370 }
371
372 // allocate image buffer now that image size is known
373
374 image->buffers();
375
376 // communication needed for bonds colored by atoms
377
378 if (bondflag) {
379 if (bcolor == ATOM || bdiam == ATOM) comm_forward = 3;
380 else comm_forward = 1;
381 }
382
383 // additional defaults for dump_modify options
384
385 diamtype = new double[ntypes+1];
386 diamelement = new double[ntypes+1];
387 colortype = new double*[ntypes+1];
388 colorelement = new double*[ntypes+1];
389
390 for (int i = 1; i <= ntypes; i++) {
391 diamtype[i] = 1.0;
392 if (i % 6 == 1) colortype[i] = image->color2rgb("red");
393 else if (i % 6 == 2) colortype[i] = image->color2rgb("green");
394 else if (i % 6 == 3) colortype[i] = image->color2rgb("blue");
395 else if (i % 6 == 4) colortype[i] = image->color2rgb("yellow");
396 else if (i % 6 == 5) colortype[i] = image->color2rgb("aqua");
397 else if (i % 6 == 0) colortype[i] = image->color2rgb("cyan");
398 }
399
400 if (bondflag) {
401 bdiamtype = new double[atom->nbondtypes+1];
402 bcolortype = new double*[atom->nbondtypes+1];
403 for (int i = 1; i <= atom->nbondtypes; i++) {
404 bdiamtype[i] = 0.5;
405 if (i % 6 == 1) bcolortype[i] = image->color2rgb("red");
406 else if (i % 6 == 2) bcolortype[i] = image->color2rgb("green");
407 else if (i % 6 == 3) bcolortype[i] = image->color2rgb("blue");
408 else if (i % 6 == 4) bcolortype[i] = image->color2rgb("yellow");
409 else if (i % 6 == 5) bcolortype[i] = image->color2rgb("aqua");
410 else if (i % 6 == 0) bcolortype[i] = image->color2rgb("cyan");
411 }
412 } else {
413 bdiamtype = nullptr;
414 bcolortype = nullptr;
415 }
416
417 // viewflag = DYNAMIC if any view parameter is dynamic
418
419 viewflag = STATIC;
420 if (thetastr || phistr || cflag == DYNAMIC ||
421 upxstr || upystr || upzstr || zoomstr) viewflag = DYNAMIC;
422
423 box_bounds();
424 if (cflag == STATIC) box_center();
425 if (viewflag == STATIC) view_params();
426
427 // local data
428
429 maxbufcopy = 0;
430 chooseghost = nullptr;
431 bufcopy = nullptr;
432 }
433
434 /* ---------------------------------------------------------------------- */
435
~DumpImage()436 DumpImage::~DumpImage()
437 {
438 delete image;
439
440 delete [] diamtype;
441 delete [] diamelement;
442 delete [] colortype;
443 delete [] colorelement;
444 delete [] bdiamtype;
445 delete [] bcolortype;
446 memory->destroy(chooseghost);
447 memory->destroy(bufcopy);
448 }
449
450 /* ---------------------------------------------------------------------- */
451
init_style()452 void DumpImage::init_style()
453 {
454 if (multifile == 0 && !multifile_override)
455 error->all(FLERR,"Dump image requires one snapshot per file");
456 if (sort_flag) error->all(FLERR,"Dump image cannot perform sorting");
457
458 DumpCustom::init_style();
459
460 // check variables
461
462 if (thetastr) {
463 thetavar = input->variable->find(thetastr);
464 if (thetavar < 0)
465 error->all(FLERR,"Variable name for dump image theta does not exist");
466 if (!input->variable->equalstyle(thetavar))
467 error->all(FLERR,"Variable for dump image theta is invalid style");
468 }
469 if (phistr) {
470 phivar = input->variable->find(phistr);
471 if (phivar < 0)
472 error->all(FLERR,"Variable name for dump image phi does not exist");
473 if (!input->variable->equalstyle(phivar))
474 error->all(FLERR,"Variable for dump image phi is invalid style");
475 }
476 if (cxstr) {
477 cxvar = input->variable->find(cxstr);
478 if (cxvar < 0)
479 error->all(FLERR,"Variable name for dump image center does not exist");
480 if (!input->variable->equalstyle(cxvar))
481 error->all(FLERR,"Variable for dump image center is invalid style");
482 }
483 if (cystr) {
484 cyvar = input->variable->find(cystr);
485 if (cyvar < 0)
486 error->all(FLERR,"Variable name for dump image center does not exist");
487 if (!input->variable->equalstyle(cyvar))
488 error->all(FLERR,"Variable for dump image center is invalid style");
489 }
490 if (czstr) {
491 czvar = input->variable->find(czstr);
492 if (czvar < 0)
493 error->all(FLERR,"Variable name for dump image center does not exist");
494 if (!input->variable->equalstyle(czvar))
495 error->all(FLERR,"Variable for dump image center is invalid style");
496 }
497 if (upxstr) {
498 upxvar = input->variable->find(upxstr);
499 if (upxvar < 0)
500 error->all(FLERR,"Variable name for dump image center does not exist");
501 if (!input->variable->equalstyle(upxvar))
502 error->all(FLERR,"Variable for dump image center is invalid style");
503 }
504 if (upystr) {
505 upyvar = input->variable->find(upystr);
506 if (upyvar < 0)
507 error->all(FLERR,"Variable name for dump image center does not exist");
508 if (!input->variable->equalstyle(upyvar))
509 error->all(FLERR,"Variable for dump image center is invalid style");
510 }
511 if (upzstr) {
512 upzvar = input->variable->find(upzstr);
513 if (upzvar < 0)
514 error->all(FLERR,"Variable name for dump image center does not exist");
515 if (!input->variable->equalstyle(upzvar))
516 error->all(FLERR,"Variable for dump image center is invalid style");
517 }
518 if (zoomstr) {
519 zoomvar = input->variable->find(zoomstr);
520 if (zoomvar < 0)
521 error->all(FLERR,"Variable name for dump image zoom does not exist");
522 if (!input->variable->equalstyle(zoomvar))
523 error->all(FLERR,"Variable for dump image zoom is invalid style");
524 }
525
526 // set up type -> element mapping
527
528 if (atomflag && acolor == ELEMENT) {
529 for (int i = 1; i <= ntypes; i++) {
530 colorelement[i] = image->element2color(typenames[i]);
531 if (colorelement[i] == nullptr)
532 error->all(FLERR,"Invalid dump image element name");
533 }
534 }
535
536 if (atomflag && adiam == ELEMENT) {
537 for (int i = 1; i <= ntypes; i++) {
538 diamelement[i] = image->element2diam(typenames[i]);
539 if (diamelement[i] == 0.0)
540 error->all(FLERR,"Invalid dump image element name");
541 }
542 }
543 }
544
545 /* ---------------------------------------------------------------------- */
546
write()547 void DumpImage::write()
548 {
549 // open new file
550
551 openfile();
552
553 // reset box center and view parameters if dynamic
554
555 box_bounds();
556 if (cflag == DYNAMIC) box_center();
557 if (viewflag == DYNAMIC) view_params();
558
559 // nme = # of atoms this proc will contribute to dump
560
561 nme = count();
562
563 if (nme > maxbuf) {
564 maxbuf = nme;
565 memory->destroy(buf);
566 memory->create(buf,maxbuf*size_one,"dump:buf");
567 }
568
569 // pack buf with color & diameter
570
571 pack(nullptr);
572
573 // set minmax color range if using dynamic atom color map
574
575 if (acolor == ATTRIBUTE && image->map_dynamic(0)) {
576 double two[2],twoall[2];
577 double lo = BIG;
578 double hi = -BIG;
579 int m = 0;
580 for (int i = 0; i < nchoose; i++) {
581 lo = MIN(lo,buf[m]);
582 hi = MAX(hi,buf[m]);
583 m += size_one;
584 }
585 two[0] = -lo;
586 two[1] = hi;
587 MPI_Allreduce(two,twoall,2,MPI_DOUBLE,MPI_MAX,world);
588 int flag = image->map_minmax(0,-twoall[0],twoall[1]);
589 if (flag) error->all(FLERR,"Invalid color map min/max values");
590 }
591
592 // create image on each proc, then merge them
593
594 image->clear();
595 create_image();
596 image->merge();
597
598 // write image file
599
600 if (me == 0) {
601 if (filetype == JPG) image->write_JPG(fp);
602 else if (filetype == PNG) image->write_PNG(fp);
603 else image->write_PPM(fp);
604 if (multifile) {
605 fclose(fp);
606 fp = nullptr;
607 }
608 }
609 }
610
611 /* ----------------------------------------------------------------------
612 simulation box bounds
613 ------------------------------------------------------------------------- */
614
box_bounds()615 void DumpImage::box_bounds()
616 {
617 if (domain->triclinic == 0) {
618 boxxlo = domain->boxlo[0];
619 boxxhi = domain->boxhi[0];
620 boxylo = domain->boxlo[1];
621 boxyhi = domain->boxhi[1];
622 boxzlo = domain->boxlo[2];
623 boxzhi = domain->boxhi[2];
624 } else {
625 boxxlo = domain->boxlo_bound[0];
626 boxxhi = domain->boxhi_bound[0];
627 boxylo = domain->boxlo_bound[1];
628 boxyhi = domain->boxhi_bound[1];
629 boxzlo = domain->boxlo_bound[2];
630 boxzhi = domain->boxhi_bound[2];
631 boxxy = domain->xy;
632 boxxz = domain->xz;
633 boxyz = domain->yz;
634 }
635 }
636
637 /* ----------------------------------------------------------------------
638 reset view parameters
639 called once from constructor if view is STATIC
640 called every snapshot from write() if view is DYNAMIC
641 ------------------------------------------------------------------------- */
642
box_center()643 void DumpImage::box_center()
644 {
645 if (cxstr) cx = input->variable->compute_equal(cxvar);
646 if (cystr) cy = input->variable->compute_equal(cyvar);
647 if (czstr) cz = input->variable->compute_equal(czvar);
648
649 image->xctr = boxxlo + cx*(boxxhi-boxxlo);
650 image->yctr = boxylo + cy*(boxyhi-boxylo);
651 image->zctr = boxzlo + cz*(boxzhi-boxzlo);
652 }
653
654 /* ----------------------------------------------------------------------
655 reset view parameters in Image class
656 called once from constructor if view is STATIC
657 called every snapshot from write() if view is DYNAMIC
658 ------------------------------------------------------------------------- */
659
view_params()660 void DumpImage::view_params()
661 {
662 // view direction theta and phi
663
664 if (thetastr) {
665 double theta = input->variable->compute_equal(thetavar);
666 if (theta < 0.0 || theta > 180.0)
667 error->all(FLERR,"Invalid dump image theta value");
668 theta *= MY_PI/180.0;
669 image->theta = theta;
670 }
671
672 if (phistr) {
673 double phi = input->variable->compute_equal(phivar);
674 phi *= MY_PI/180.0;
675 image->phi = phi;
676 }
677
678 // up vector
679
680 if (upxstr) image->up[0] = input->variable->compute_equal(upxvar);
681 if (upystr) image->up[1] = input->variable->compute_equal(upyvar);
682 if (upzstr) image->up[2] = input->variable->compute_equal(upzvar);
683
684 // zoom
685
686 if (zoomstr) image->zoom = input->variable->compute_equal(zoomvar);
687 if (image->zoom <= 0.0) error->all(FLERR,"Invalid dump image zoom value");
688
689 // remainder of view setup is internal to Image class
690
691 image->view_params(boxxlo,boxxhi,boxylo,boxyhi,boxzlo,boxzhi);
692 }
693
694 /* ----------------------------------------------------------------------
695 create image for atoms on this proc
696 every pixel has depth
697 ------------------------------------------------------------------------- */
698
create_image()699 void DumpImage::create_image()
700 {
701 int i,j,k,m,n,itype,atom1,atom2,imol,iatom,btype,ibonus,drawflag;
702 tagint tagprev;
703 double diameter,delx,dely,delz;
704 int *bodyvec,*fixvec;
705 double **bodyarray,**fixarray;
706 double *color,*color1,*color2;
707 double *p1,*p2,*p3;
708 double xmid[3],pt1[3],pt2[3],pt3[3];
709 double mat[3][3];
710
711 // render my atoms
712
713 if (atomflag) {
714 double **x = atom->x;
715 int *line = atom->line;
716 int *tri = atom->tri;
717 int *body = atom->body;
718
719 m = 0;
720 for (i = 0; i < nchoose; i++) {
721 j = clist[i];
722
723 if (acolor == TYPE) {
724 itype = static_cast<int> (buf[m]);
725 color = colortype[itype];
726 } else if (acolor == ELEMENT) {
727 itype = static_cast<int> (buf[m]);
728 color = colorelement[itype];
729 } else if (acolor == ATTRIBUTE) {
730 color = image->map_value2color(0,buf[m]);
731 } else color = image->color2rgb("white");
732
733 if (adiam == NUMERIC) {
734 diameter = adiamvalue;
735 } else if (adiam == TYPE) {
736 itype = static_cast<int> (buf[m+1]);
737 diameter = diamtype[itype];
738 } else if (adiam == ELEMENT) {
739 itype = static_cast<int> (buf[m+1]);
740 diameter = diamelement[itype];
741 } else if (adiam == ATTRIBUTE) {
742 diameter = buf[m+1];
743 }
744
745 // do not draw if line,tri,body keywords enabled and atom is one of those
746
747 drawflag = 1;
748 if (extraflag) {
749 if (lineflag && line[j] >= 0) drawflag = 0;
750 if (triflag && tri[j] >= 0) drawflag = 0;
751 if (bodyflag && body[j] >= 0) drawflag = 0;
752 }
753
754 if (drawflag) image->draw_sphere(x[j],color,diameter);
755
756 m += size_one;
757 }
758 }
759
760 // render atoms that are lines
761
762 if (lineflag) {
763 double length,theta,dx,dy;
764 double **x = atom->x;
765 int *line = atom->line;
766 int *type = atom->type;
767
768 for (i = 0; i < nchoose; i++) {
769 j = clist[i];
770 if (line[j] < 0) continue;
771
772 if (lcolor == TYPE) {
773 color = colortype[type[j]];
774 }
775
776 if (ldiam == NUMERIC) {
777 diameter = ldiamvalue;
778 }
779
780 length = avec_line->bonus[line[j]].length;
781 theta = avec_line->bonus[line[j]].theta;
782 dx = 0.5*length*cos(theta);
783 dy = 0.5*length*sin(theta);
784
785 pt1[0] = x[j][0] + dx;
786 pt1[1] = x[j][1] + dy;
787 pt1[2] = 0.0;
788 pt2[0] = x[j][0] - dx;
789 pt2[1] = x[j][1] - dy;
790 pt2[2] = 0.0;
791
792 image->draw_cylinder(pt1,pt2,color,ldiamvalue,3);
793 }
794 }
795
796 // render atoms that are triangles
797 // tstyle = 1 for tri only, 2 for edges only, 3 for both
798
799 if (triflag) {
800 int tridraw = 1;
801 if (tstyle == 2) tridraw = 0;
802 int edgedraw = 1;
803 if (tstyle == 1) edgedraw = 0;
804
805 double **x = atom->x;
806 int *tri = atom->tri;
807 int *type = atom->type;
808
809 for (i = 0; i < nchoose; i++) {
810 j = clist[i];
811 if (tri[j] < 0) continue;
812
813 if (tcolor == TYPE) {
814 color = colortype[type[j]];
815 }
816
817 MathExtra::quat_to_mat(avec_tri->bonus[tri[i]].quat,mat);
818 MathExtra::matvec(mat,avec_tri->bonus[tri[i]].c1,pt1);
819 MathExtra::matvec(mat,avec_tri->bonus[tri[i]].c2,pt2);
820 MathExtra::matvec(mat,avec_tri->bonus[tri[i]].c3,pt3);
821 MathExtra::add3(pt1,x[i],pt1);
822 MathExtra::add3(pt2,x[i],pt2);
823 MathExtra::add3(pt3,x[i],pt3);
824
825 if (tridraw) image->draw_triangle(pt1,pt2,pt3,color);
826 if (edgedraw) {
827 image->draw_cylinder(pt1,pt2,color,tdiamvalue,3);
828 image->draw_cylinder(pt2,pt3,color,tdiamvalue,3);
829 image->draw_cylinder(pt3,pt1,color,tdiamvalue,3);
830 }
831 }
832 }
833
834 // render atoms that are bodies
835
836 if (bodyflag) {
837 Body *bptr = avec_body->bptr;
838 int *body = atom->body;
839
840 m = 0;
841 for (i = 0; i < nchoose; i++) {
842 j = clist[i];
843 if (body[j] < 0) continue;
844
845 if (bodycolor == TYPE) {
846 itype = static_cast<int> (buf[m]);
847 color = colortype[itype];
848 }
849
850 ibonus = body[i];
851 n = bptr->image(ibonus,bodyflag1,bodyflag2,bodyvec,bodyarray);
852 for (k = 0; k < n; k++) {
853 if (bodyvec[k] == SPHERE)
854 image->draw_sphere(bodyarray[k],color,bodyarray[k][3]);
855 else if (bodyvec[k] == LINE)
856 image->draw_cylinder(&bodyarray[k][0],&bodyarray[k][3],
857 color,bodyarray[k][6],3);
858 }
859
860 m += size_one;
861 }
862 }
863
864 // render bonds for my atoms
865 // both atoms in bond must be selected for bond to be rendered
866 // if newton_bond is off, only render bond once
867 // render bond in 2 pieces if crosses periodic boundary
868 // if bond is deleted (type = 0), do not render
869 // if bond is turned off (type < 0), still render
870
871 if (bondflag) {
872 double **x = atom->x;
873 tagint *tag = atom->tag;
874 tagint **bond_atom = atom->bond_atom;
875 int **bond_type = atom->bond_type;
876 int *num_bond = atom->num_bond;
877 int *molindex = atom->molindex;
878 int *molatom = atom->molatom;
879 int *type = atom->type;
880 int nlocal = atom->nlocal;
881 int newton_bond = force->newton_bond;
882 int molecular = atom->molecular;
883 Molecule **onemols = atom->avec->onemols;
884
885 // communicate choose flag for ghost atoms to know if they are selected
886 // if bcolor/bdiam = ATOM, setup bufcopy to comm atom color/diam attributes
887
888 if (atom->nmax > maxbufcopy) {
889 maxbufcopy = atom->nmax;
890 memory->destroy(chooseghost);
891 memory->create(chooseghost,maxbufcopy,"dump:chooseghost");
892 if (comm_forward == 3) {
893 memory->destroy(bufcopy);
894 memory->create(bufcopy,maxbufcopy,2,"dump:bufcopy");
895 }
896 }
897
898 for (i = 0; i < nlocal; i++) chooseghost[i] = choose[i];
899
900 if (comm_forward == 3) {
901 for (i = 0; i < nlocal; i++) bufcopy[i][0] = bufcopy[i][1] = 0.0;
902 m = 0;
903 for (i = 0; i < nchoose; i++) {
904 j = clist[i];
905 bufcopy[j][0] = buf[m];
906 bufcopy[j][1] = buf[m+1];
907 m += size_one;
908 }
909 }
910
911 comm->forward_comm_dump(this);
912
913 for (i = 0; i < nchoose; i++) {
914 atom1 = clist[i];
915 if (molecular == Atom::MOLECULAR) n = num_bond[atom1];
916 else {
917 if (molindex[atom1] < 0) continue;
918 imol = molindex[atom1];
919 iatom = molatom[atom1];
920 n = onemols[imol]->num_bond[iatom];
921 }
922
923 for (m = 0; m < n; m++) {
924 if (molecular == Atom::MOLECULAR) {
925 btype = bond_type[atom1][m];
926 atom2 = atom->map(bond_atom[atom1][m]);
927 } else {
928 tagprev = tag[i] - iatom - 1;
929 btype = atom->map(onemols[imol]->bond_type[iatom][m]);
930 atom2 = atom->map(onemols[imol]->bond_atom[iatom][m]+tagprev);
931 }
932
933 if (atom2 < 0 || !chooseghost[atom2]) continue;
934 if (newton_bond == 0 && tag[atom1] > tag[atom2]) continue;
935 if (btype == 0) continue;
936
937 if (bcolor == ATOM) {
938 if (acolor == TYPE) {
939 color1 = colortype[type[atom1]];
940 color2 = colortype[type[atom2]];
941 } else if (acolor == ELEMENT) {
942 color1 = colorelement[type[atom1]];
943 color2 = colorelement[type[atom2]];
944 } else if (acolor == ATTRIBUTE) {
945 color1 = image->map_value2color(0,bufcopy[atom1][0]);
946 color2 = image->map_value2color(0,bufcopy[atom2][0]);
947 } else {
948 color1 = image->color2rgb("white");
949 color2 = image->color2rgb("white");
950 }
951 } else if (bcolor == TYPE) {
952 itype = btype;
953 if (itype < 0) itype = -itype;
954 color = bcolortype[itype];
955 }
956
957 if (bdiam == NUMERIC) {
958 diameter = bdiamvalue;
959 } else if (bdiam == ATOM) {
960 if (adiam == NUMERIC) {
961 diameter = adiamvalue;
962 } else if (adiam == TYPE) {
963 diameter = MIN(diamtype[type[atom1]],diamtype[type[atom1]]);
964 } else if (adiam == ELEMENT) {
965 diameter = MIN(diamelement[type[atom1]],diamelement[type[atom1]]);
966 } else if (adiam == ATTRIBUTE) {
967 diameter = MIN(bufcopy[atom1][1],bufcopy[atom2][1]);
968 }
969 } else if (bdiam == TYPE) {
970 itype = btype;
971 if (itype < 0) itype = -itype;
972 diameter = bdiamtype[itype];
973 }
974
975 // draw cylinder in 2 pieces if bcolor = ATOM
976 // or bond crosses periodic boundary
977
978 delx = x[atom2][0] - x[atom1][0];
979 dely = x[atom2][1] - x[atom1][1];
980 delz = x[atom2][2] - x[atom1][2];
981
982 if (bcolor == ATOM || domain->minimum_image_check(delx,dely,delz)) {
983 domain->minimum_image(delx,dely,delz);
984 xmid[0] = x[atom1][0] + 0.5*delx;
985 xmid[1] = x[atom1][1] + 0.5*dely;
986 xmid[2] = x[atom1][2] + 0.5*delz;
987 if (bcolor == ATOM)
988 image->draw_cylinder(x[atom1],xmid,color1,diameter,3);
989 else image->draw_cylinder(x[atom1],xmid,color,diameter,3);
990 xmid[0] = x[atom2][0] - 0.5*delx;
991 xmid[1] = x[atom2][1] - 0.5*dely;
992 xmid[2] = x[atom2][2] - 0.5*delz;
993 if (bcolor == ATOM)
994 image->draw_cylinder(xmid,x[atom2],color2,diameter,3);
995 else image->draw_cylinder(xmid,x[atom2],color,diameter,3);
996
997 } else image->draw_cylinder(x[atom1],x[atom2],color,diameter,3);
998 }
999 }
1000 }
1001
1002 // render objects provided by a fix
1003
1004 if (fixflag) {
1005 int tridraw=0,edgedraw=0;
1006 if (domain->dimension == 3) {
1007 tridraw = 1;
1008 edgedraw = 1;
1009 if ((int) fixflag1 == 2) tridraw = 0;
1010 if ((int) fixflag1 == 1) edgedraw = 0;
1011 }
1012
1013 n = fixptr->image(fixvec,fixarray);
1014
1015 for (i = 0; i < n; i++) {
1016 if (fixvec[i] == SPHERE) {
1017 // no fix draws spheres yet
1018 } else if (fixvec[i] == LINE) {
1019 if (fixcolor == TYPE) {
1020 itype = static_cast<int> (fixarray[i][0]);
1021 color = colortype[itype];
1022 }
1023 image->draw_cylinder(&fixarray[i][1],&fixarray[i][4],
1024 color,fixflag1,3);
1025 } else if (fixvec[i] == TRI) {
1026 if (fixcolor == TYPE) {
1027 itype = static_cast<int> (fixarray[i][0]);
1028 color = colortype[itype];
1029 }
1030 p1 = &fixarray[i][1];
1031 p2 = &fixarray[i][4];
1032 p3 = &fixarray[i][7];
1033 if (tridraw) image->draw_triangle(p1,p2,p3,color);
1034 if (edgedraw) {
1035 image->draw_cylinder(p1,p2,color,fixflag2,3);
1036 image->draw_cylinder(p2,p3,color,fixflag2,3);
1037 image->draw_cylinder(p3,p1,color,fixflag2,3);
1038 }
1039 }
1040 }
1041 }
1042
1043 // render outline of my sub-box, orthogonal or triclinic
1044
1045 if (subboxflag) {
1046 diameter = MIN(boxxhi-boxxlo,boxyhi-boxylo);
1047 if (domain->dimension == 3) diameter = MIN(diameter,boxzhi-boxzlo);
1048 diameter *= subboxdiam;
1049
1050 double *sublo = domain->sublo;
1051 double *subhi = domain->subhi;
1052
1053 double (*boxcorners)[3];
1054 double box[8][3];
1055 if (domain->triclinic == 0) {
1056 box[0][0] = sublo[0]; box[0][1] = sublo[1]; box[0][2] = sublo[2];
1057 box[1][0] = subhi[0]; box[1][1] = sublo[1]; box[1][2] = sublo[2];
1058 box[2][0] = sublo[0]; box[2][1] = subhi[1]; box[2][2] = sublo[2];
1059 box[3][0] = subhi[0]; box[3][1] = subhi[1]; box[3][2] = sublo[2];
1060 box[4][0] = sublo[0]; box[4][1] = sublo[1]; box[4][2] = subhi[2];
1061 box[5][0] = subhi[0]; box[5][1] = sublo[1]; box[5][2] = subhi[2];
1062 box[6][0] = sublo[0]; box[6][1] = subhi[1]; box[6][2] = subhi[2];
1063 box[7][0] = subhi[0]; box[7][1] = subhi[1]; box[7][2] = subhi[2];
1064 boxcorners = box;
1065 } else {
1066 domain->subbox_corners();
1067 boxcorners = domain->corners;
1068 }
1069
1070 image->draw_box(boxcorners,diameter);
1071 }
1072
1073 // render outline of simulation box, orthogonal or triclinic
1074
1075 if (boxflag) {
1076 diameter = MIN(boxxhi-boxxlo,boxyhi-boxylo);
1077 if (domain->dimension == 3) diameter = MIN(diameter,boxzhi-boxzlo);
1078 diameter *= boxdiam;
1079
1080 double (*boxcorners)[3];
1081 double box[8][3];
1082 if (domain->triclinic == 0) {
1083 box[0][0] = boxxlo; box[0][1] = boxylo; box[0][2] = boxzlo;
1084 box[1][0] = boxxhi; box[1][1] = boxylo; box[1][2] = boxzlo;
1085 box[2][0] = boxxlo; box[2][1] = boxyhi; box[2][2] = boxzlo;
1086 box[3][0] = boxxhi; box[3][1] = boxyhi; box[3][2] = boxzlo;
1087 box[4][0] = boxxlo; box[4][1] = boxylo; box[4][2] = boxzhi;
1088 box[5][0] = boxxhi; box[5][1] = boxylo; box[5][2] = boxzhi;
1089 box[6][0] = boxxlo; box[6][1] = boxyhi; box[6][2] = boxzhi;
1090 box[7][0] = boxxhi; box[7][1] = boxyhi; box[7][2] = boxzhi;
1091 boxcorners = box;
1092 } else {
1093 domain->box_corners();
1094 boxcorners = domain->corners;
1095 }
1096
1097 image->draw_box(boxcorners,diameter);
1098 }
1099
1100 // render XYZ axes in red/green/blue
1101 // offset by 10% of box size and scale by axeslen
1102
1103 if (axesflag) {
1104 diameter = MIN(boxxhi-boxxlo,boxyhi-boxylo);
1105 if (domain->dimension == 3) diameter = MIN(diameter,boxzhi-boxzlo);
1106 diameter *= axesdiam;
1107
1108 double (*boxcorners)[3];
1109 double axes[4][3];
1110 if (domain->triclinic == 0) {
1111 axes[0][0] = boxxlo; axes[0][1] = boxylo; axes[0][2] = boxzlo;
1112 axes[1][0] = boxxhi; axes[1][1] = boxylo; axes[1][2] = boxzlo;
1113 axes[2][0] = boxxlo; axes[2][1] = boxyhi; axes[2][2] = boxzlo;
1114 axes[3][0] = boxxlo; axes[3][1] = boxylo; axes[3][2] = boxzhi;
1115 } else {
1116 domain->box_corners();
1117 boxcorners = domain->corners;
1118 axes[0][0] = boxcorners[0][0];
1119 axes[0][1] = boxcorners[0][1];
1120 axes[0][2] = boxcorners[0][2];
1121 axes[1][0] = boxcorners[1][0];
1122 axes[1][1] = boxcorners[1][1];
1123 axes[1][2] = boxcorners[1][2];
1124 axes[2][0] = boxcorners[2][0];
1125 axes[2][1] = boxcorners[2][1];
1126 axes[2][2] = boxcorners[2][2];
1127 axes[3][0] = boxcorners[4][0];
1128 axes[3][1] = boxcorners[4][1];
1129 axes[3][2] = boxcorners[4][2];
1130 }
1131
1132 double offset = MAX(boxxhi-boxxlo,boxyhi-boxylo);
1133 if (domain->dimension == 3) offset = MAX(offset,boxzhi-boxzlo);
1134 offset *= 0.1;
1135 axes[0][0] -= offset; axes[0][1] -= offset; axes[0][2] -= offset;
1136 axes[1][0] -= offset; axes[1][1] -= offset; axes[1][2] -= offset;
1137 axes[2][0] -= offset; axes[2][1] -= offset; axes[2][2] -= offset;
1138 axes[3][0] -= offset; axes[3][1] -= offset; axes[3][2] -= offset;
1139
1140 axes[1][0] = axes[0][0] + axeslen*(axes[1][0]-axes[0][0]);
1141 axes[1][1] = axes[0][1] + axeslen*(axes[1][1]-axes[0][1]);
1142 axes[1][2] = axes[0][2] + axeslen*(axes[1][2]-axes[0][2]);
1143 axes[2][0] = axes[0][0] + axeslen*(axes[2][0]-axes[0][0]);
1144 axes[2][1] = axes[0][1] + axeslen*(axes[2][1]-axes[0][1]);
1145 axes[2][2] = axes[0][2] + axeslen*(axes[2][2]-axes[0][2]);
1146 axes[3][0] = axes[0][0] + axeslen*(axes[3][0]-axes[0][0]);
1147 axes[3][1] = axes[0][1] + axeslen*(axes[3][1]-axes[0][1]);
1148 axes[3][2] = axes[0][2] + axeslen*(axes[3][2]-axes[0][2]);
1149
1150 image->draw_axes(axes,diameter);
1151 }
1152 }
1153
1154 /* ---------------------------------------------------------------------- */
1155
pack_forward_comm(int n,int * list,double * buf,int,int *)1156 int DumpImage::pack_forward_comm(int n, int *list, double *buf,
1157 int /*pbc_flag*/, int * /*pbc*/)
1158 {
1159 int i,j,m;
1160
1161 m = 0;
1162
1163 if (comm_forward == 1) {
1164 for (i = 0; i < n; i++) {
1165 j = list[i];
1166 buf[m++] = chooseghost[j];
1167 }
1168 } else {
1169 for (i = 0; i < n; i++) {
1170 j = list[i];
1171 buf[m++] = chooseghost[j];
1172 buf[m++] = bufcopy[j][0];
1173 buf[m++] = bufcopy[j][1];
1174 }
1175 }
1176
1177 return m;
1178 }
1179
1180 /* ---------------------------------------------------------------------- */
1181
unpack_forward_comm(int n,int first,double * buf)1182 void DumpImage::unpack_forward_comm(int n, int first, double *buf)
1183 {
1184 int i,m,last;
1185
1186 m = 0;
1187 last = first + n;
1188
1189 if (comm_forward == 1)
1190 for (i = first; i < last; i++) chooseghost[i] = static_cast<int> (buf[m++]);
1191 else {
1192 for (i = first; i < last; i++) {
1193 chooseghost[i] = static_cast<int> (buf[m++]);
1194 bufcopy[i][0] = buf[m++];
1195 bufcopy[i][1] = buf[m++];
1196 }
1197 }
1198 }
1199
1200 /* ---------------------------------------------------------------------- */
1201
modify_param(int narg,char ** arg)1202 int DumpImage::modify_param(int narg, char **arg)
1203 {
1204 int n = DumpCustom::modify_param(narg,arg);
1205 if (n) return n;
1206
1207 if (strcmp(arg[0],"acolor") == 0) {
1208 if (narg < 3) error->all(FLERR,"Illegal dump_modify command");
1209 int nlo,nhi;
1210 utils::bounds(FLERR,arg[1],1,atom->ntypes,nlo,nhi,error);
1211
1212 // get list of colors
1213 auto colors = Tokenizer(arg[2],"/").as_vector();
1214 const int ncolors = colors.size();
1215
1216 // assign colors in round-robin fashion to types
1217
1218 int m = 0;
1219 for (int i = nlo; i <= nhi; i++) {
1220 colortype[i] = image->color2rgb(colors[m%ncolors].c_str());
1221 if (colortype[i] == nullptr)
1222 error->all(FLERR,"Invalid color in dump_modify command");
1223 m++;
1224 }
1225 return 3;
1226 }
1227
1228 if (strcmp(arg[0],"adiam") == 0) {
1229 if (narg < 3) error->all(FLERR,"Illegal dump_modify command");
1230 int nlo,nhi;
1231 utils::bounds(FLERR,arg[1],1,atom->ntypes,nlo,nhi,error);
1232 double diam = utils::numeric(FLERR,arg[2],false,lmp);
1233 if (diam <= 0.0) error->all(FLERR,"Illegal dump_modify command");
1234 for (int i = nlo; i <= nhi; i++) diamtype[i] = diam;
1235 return 3;
1236 }
1237
1238 if (strcmp(arg[0],"amap") == 0) {
1239 if (narg < 6) error->all(FLERR,"Illegal dump_modify command");
1240 if (strlen(arg[3]) != 2) error->all(FLERR,"Illegal dump_modify command");
1241 int factor = 0;
1242 if (arg[3][0] == 's') factor = 1;
1243 else if (arg[3][0] == 'c') factor = 2;
1244 else if (arg[3][0] == 'd') factor = 3;
1245 else error->all(FLERR,"Illegal dump_modify command");
1246 int nentry = utils::inumeric(FLERR,arg[5],false,lmp);
1247 if (nentry < 1) error->all(FLERR,"Illegal dump_modify command");
1248 n = 6 + factor*nentry;
1249 if (narg < n) error->all(FLERR,"Illegal dump_modify command");
1250 int flag = image->map_reset(0,n-1,&arg[1]);
1251 if (flag) error->all(FLERR,"Illegal dump_modify command");
1252 return n;
1253 }
1254
1255 if (strcmp(arg[0],"bcolor") == 0) {
1256 if (narg < 3) error->all(FLERR,"Illegal dump_modify command");
1257 if (atom->nbondtypes == 0)
1258 error->all(FLERR,"Dump modify bcolor not allowed with no bond types");
1259 int nlo,nhi;
1260 utils::bounds(FLERR,arg[1],1,atom->nbondtypes,nlo,nhi,error);
1261
1262 // ptrs = list of ncount colornames separated by '/'
1263
1264 int ncount = 1;
1265 char *nextptr;
1266 char *ptr = arg[2];
1267 while ((nextptr = strchr(ptr,'/'))) {
1268 ptr = nextptr + 1;
1269 ncount++;
1270 }
1271 char **ptrs = new char*[ncount+1];
1272 ncount = 0;
1273 ptrs[ncount++] = strtok(arg[2],"/");
1274 while ((ptrs[ncount++] = strtok(nullptr,"/")));
1275 ncount--;
1276
1277 // assign each of ncount colors in round-robin fashion to types
1278
1279 int m = 0;
1280 for (int i = nlo; i <= nhi; i++) {
1281 bcolortype[i] = image->color2rgb(ptrs[m%ncount]);
1282 if (bcolortype[i] == nullptr)
1283 error->all(FLERR,"Invalid color in dump_modify command");
1284 m++;
1285 }
1286
1287 delete [] ptrs;
1288 return 3;
1289 }
1290
1291 if (strcmp(arg[0],"bdiam") == 0) {
1292 if (narg < 3) error->all(FLERR,"Illegal dump_modify command");
1293 if (atom->nbondtypes == 0)
1294 error->all(FLERR,"Dump modify bdiam not allowed with no bond types");
1295 int nlo,nhi;
1296 utils::bounds(FLERR,arg[1],1,atom->nbondtypes,nlo,nhi,error);
1297 double diam = utils::numeric(FLERR,arg[2],false,lmp);
1298 if (diam <= 0.0) error->all(FLERR,"Illegal dump_modify command");
1299 for (int i = nlo; i <= nhi; i++) bdiamtype[i] = diam;
1300 return 3;
1301 }
1302
1303 if (strcmp(arg[0],"backcolor") == 0) {
1304 if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
1305 double *color = image->color2rgb(arg[1]);
1306 if (color == nullptr) error->all(FLERR,"Invalid color in dump_modify command");
1307 image->background[0] = static_cast<int> (color[0]*255.0);
1308 image->background[1] = static_cast<int> (color[1]*255.0);
1309 image->background[2] = static_cast<int> (color[2]*255.0);
1310 return 2;
1311 }
1312
1313 if (strcmp(arg[0],"boxcolor") == 0) {
1314 if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
1315 image->boxcolor = image->color2rgb(arg[1]);
1316 if (image->boxcolor == nullptr)
1317 error->all(FLERR,"Invalid color in dump_modify command");
1318 return 2;
1319 }
1320
1321 if (strcmp(arg[0],"color") == 0) {
1322 if (narg < 5) error->all(FLERR,"Illegal dump_modify command");
1323 int flag = image->addcolor(arg[1],utils::numeric(FLERR,arg[2],false,lmp),
1324 utils::numeric(FLERR,arg[3],false,lmp),
1325 utils::numeric(FLERR,arg[4],false,lmp));
1326 if (flag) error->all(FLERR,"Illegal dump_modify command");
1327 return 5;
1328 }
1329
1330 return 0;
1331 }
1332