1 /* ----------------------------------------------------------------------
2 SPARTA - Stochastic PArallel Rarefied-gas Time-accurate Analyzer
3 http://sparta.sandia.gov
4 Steve Plimpton, sjplimp@sandia.gov, Michael Gallis, magalli@sandia.gov
5 Sandia National Laboratories
6
7 Copyright (2014) 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 SPARTA directory.
13 ------------------------------------------------------------------------- */
14
15 #include "stdio.h"
16 #include "stdlib.h"
17 #include "string.h"
18 #include "output.h"
19 #include "style_dump.h"
20 #include "comm.h"
21 #include "input.h"
22 #include "variable.h"
23 #include "update.h"
24 #include "particle.h"
25 #include "grid.h"
26 #include "surf.h"
27 #include "domain.h"
28 #include "modify.h"
29 #include "stats.h"
30 #include "dump.h"
31 #include "write_restart.h"
32 #include "memory.h"
33 #include "error.h"
34
35 using namespace SPARTA_NS;
36
37 #define DELTA 1
38
39 /* ----------------------------------------------------------------------
40 initialize all output
41 ------------------------------------------------------------------------- */
42
Output(SPARTA * sparta)43 Output::Output(SPARTA *sparta) : Pointers(sparta)
44 {
45 // create default Stats class
46
47 stats = new Stats(sparta);
48
49 stats_every = 0;
50 var_stats = NULL;
51
52 ndump = 0;
53 max_dump = 0;
54 every_dump = NULL;
55 next_dump = NULL;
56 last_dump = NULL;
57 var_dump = NULL;
58 ivar_dump = NULL;
59 dump = NULL;
60
61 restart_flag = restart_flag_single = restart_flag_double = 0;
62 restart_every_single = restart_every_double = 0;
63 last_restart = -1;
64 restart1 = restart2a = restart2b = NULL;
65 var_restart_single = var_restart_double = NULL;
66 restart = NULL;
67 }
68
69 /* ----------------------------------------------------------------------
70 free all memory
71 ------------------------------------------------------------------------- */
72
~Output()73 Output::~Output()
74 {
75 if (stats) delete stats;
76 delete [] var_stats;
77
78 memory->destroy(every_dump);
79 memory->destroy(next_dump);
80 memory->destroy(last_dump);
81 for (int i = 0; i < ndump; i++) delete [] var_dump[i];
82 memory->sfree(var_dump);
83 memory->destroy(ivar_dump);
84 for (int i = 0; i < ndump; i++) delete dump[i];
85 memory->sfree(dump);
86
87 delete [] restart1;
88 delete [] restart2a;
89 delete [] restart2b;
90 delete [] var_restart_single;
91 delete [] var_restart_double;
92 delete restart;
93 }
94
95 /* ---------------------------------------------------------------------- */
96
init()97 void Output::init()
98 {
99 stats->init();
100 if (var_stats) {
101 ivar_stats = input->variable->find(var_stats);
102 if (ivar_stats < 0)
103 error->all(FLERR,"Variable name for stats every does not exist");
104 if (!input->variable->equal_style(ivar_stats))
105 error->all(FLERR,"Variable for stats every is invalid style");
106 }
107
108 for (int i = 0; i < ndump; i++) dump[i]->init();
109 for (int i = 0; i < ndump; i++)
110 if (every_dump[i] == 0) {
111 ivar_dump[i] = input->variable->find(var_dump[i]);
112 if (ivar_dump[i] < 0)
113 error->all(FLERR,"Variable name for dump every does not exist");
114 if (!input->variable->equal_style(ivar_dump[i]))
115 error->all(FLERR,"Variable for dump every is invalid style");
116 }
117
118 if (restart_flag_single && restart_every_single == 0) {
119 ivar_restart_single = input->variable->find(var_restart_single);
120 if (ivar_restart_single < 0)
121 error->all(FLERR,"Variable name for restart does not exist");
122 if (!input->variable->equal_style(ivar_restart_single))
123 error->all(FLERR,"Variable for restart is invalid style");
124 }
125 if (restart_flag_double && restart_every_double == 0) {
126 ivar_restart_double = input->variable->find(var_restart_double);
127 if (ivar_restart_double < 0)
128 error->all(FLERR,"Variable name for restart does not exist");
129 if (!input->variable->equal_style(ivar_restart_double))
130 error->all(FLERR,"Variable for restart is invalid style");
131 }
132 }
133
134 /* ----------------------------------------------------------------------
135 perform output for setup of run/min
136 do dump first, so memory_usage will include dump allocation
137 do stats last, so will print after memory_usage
138 memflag = 0/1 for printing out memory usage
139 ------------------------------------------------------------------------- */
140
setup(int memflag)141 void Output::setup(int memflag)
142 {
143 bigint ntimestep = update->ntimestep;
144
145 // perform dump at start of run only if:
146 // current timestep is multiple of every and last dump not >= this step
147 // this is first run after dump created and firstflag is set
148 // note that variable freq will not write unless triggered by firstflag
149 // set next_dump to multiple of every or variable value
150 // set next_dump_any to smallest next_dump
151 // wrap dumps that invoke computes and variable eval with clear/add
152 // if dump not written now, use addstep_compute_all() since don't know
153 // what computes the dump write would invoke
154 // if no dumps, set next_dump_any to last+1 so will not influence next
155
156 int writeflag;
157
158 if (ndump) {
159 for (int idump = 0; idump < ndump; idump++) {
160 if (dump[idump]->clearstep || every_dump[idump] == 0)
161 modify->clearstep_compute();
162 writeflag = 0;
163 if (every_dump[idump] && ntimestep % every_dump[idump] == 0 &&
164 last_dump[idump] != ntimestep) writeflag = 1;
165 if (last_dump[idump] < 0 && dump[idump]->first_flag == 1) writeflag = 1;
166
167 if (writeflag) {
168 dump[idump]->write();
169 last_dump[idump] = ntimestep;
170 }
171 if (every_dump[idump])
172 next_dump[idump] =
173 (ntimestep/every_dump[idump])*every_dump[idump] + every_dump[idump];
174 else {
175 bigint nextdump = static_cast<bigint>
176 (input->variable->compute_equal(ivar_dump[idump]));
177 if (nextdump <= ntimestep)
178 error->all(FLERR,"Dump every variable returned a bad timestep");
179 next_dump[idump] = nextdump;
180 }
181 if (dump[idump]->clearstep || every_dump[idump] == 0) {
182 if (writeflag) modify->addstep_compute(next_dump[idump]);
183 else modify->addstep_compute_all(next_dump[idump]);
184 }
185 if (idump) next_dump_any = MIN(next_dump_any,next_dump[idump]);
186 else next_dump_any = next_dump[0];
187 }
188 } else next_dump_any = update->laststep + 1;
189
190 // do not write restart files at start of run
191 // set next_restart values to multiple of every or variable value
192 // wrap variable eval with clear/add
193 // if no restarts, set next_restart to last+1 so will not influence next
194
195 if (restart_flag) {
196 if (restart_flag_single) {
197 if (restart_every_single)
198 next_restart_single =
199 (ntimestep/restart_every_single)*restart_every_single +
200 restart_every_single;
201 else {
202 bigint nextrestart = static_cast<bigint>
203 (input->variable->compute_equal(ivar_restart_single));
204 if (nextrestart <= ntimestep)
205 error->all(FLERR,"Restart variable returned a bad timestep");
206 next_restart_single = nextrestart;
207 }
208 } else next_restart_single = update->laststep + 1;
209 if (restart_flag_double) {
210 if (restart_every_double)
211 next_restart_double =
212 (ntimestep/restart_every_double)*restart_every_double +
213 restart_every_double;
214 else {
215 bigint nextrestart = static_cast<bigint>
216 (input->variable->compute_equal(ivar_restart_double));
217 if (nextrestart <= ntimestep)
218 error->all(FLERR,"Restart variable returned a bad timestep");
219 next_restart_double = nextrestart;
220 }
221 } else next_restart_double = update->laststep + 1;
222 next_restart = MIN(next_restart_single,next_restart_double);
223 } else next_restart = update->laststep + 1;
224
225 // print memory usage unless being called between multiple runs
226
227 if (memflag) memory_usage();
228
229 // set next_stats to multiple of every or variable eval if var defined
230 // insure stats output on last step of run
231 // stats may invoke computes so wrap with clear/add
232
233 modify->clearstep_compute();
234
235 stats->header();
236 stats->compute(0);
237 last_stats = ntimestep;
238
239 if (var_stats) {
240 next_stats = static_cast<bigint>
241 (input->variable->compute_equal(ivar_stats));
242 if (next_stats <= ntimestep)
243 error->all(FLERR,"Stats every variable returned a bad timestep");
244 } else if (stats_every) {
245 next_stats = (ntimestep/stats_every)*stats_every + stats_every;
246 next_stats = MIN(next_stats,update->laststep);
247 } else next_stats = update->laststep;
248
249 modify->addstep_compute(next_stats);
250
251 // next = next timestep any output will be done
252
253 next = MIN(next_dump_any,next_restart);
254 next = MIN(next,next_stats);
255 }
256
257 /* ----------------------------------------------------------------------
258 perform all output for this timestep
259 only perform output if next matches current step and last output doesn't
260 do dump/restart before stats so stats CPU time will include them
261 ------------------------------------------------------------------------- */
262
write(bigint ntimestep)263 void Output::write(bigint ntimestep)
264 {
265 // next_dump does not force output on last step of run
266 // wrap dumps that invoke computes or eval of variable with clear/add
267 // download data from GPU if necessary
268
269 if (next_dump_any == ntimestep) {
270 for (int idump = 0; idump < ndump; idump++) {
271 if (next_dump[idump] == ntimestep) {
272 if (dump[idump]->clearstep || every_dump[idump] == 0)
273 modify->clearstep_compute();
274 if (last_dump[idump] != ntimestep) {
275 dump[idump]->write();
276 last_dump[idump] = ntimestep;
277 }
278 if (every_dump[idump]) next_dump[idump] += every_dump[idump];
279 else {
280 bigint nextdump = static_cast<bigint>
281 (input->variable->compute_equal(ivar_dump[idump]));
282 if (nextdump <= ntimestep)
283 error->all(FLERR,"Dump every variable returned a bad timestep");
284 next_dump[idump] = nextdump;
285 }
286 if (dump[idump]->clearstep || every_dump[idump] == 0)
287 modify->addstep_compute(next_dump[idump]);
288 }
289 if (idump) next_dump_any = MIN(next_dump_any,next_dump[idump]);
290 else next_dump_any = next_dump[0];
291 }
292 }
293
294 // next_restart does not force output on last step of run
295 // for toggle = 0, replace "*" with current timestep in restart filename
296 // eval of variable may invoke computes so wrap with clear/add
297
298 if (next_restart == ntimestep) {
299 if (next_restart_single == ntimestep) {
300 char *file = new char[strlen(restart1) + 16];
301 char *ptr = strchr(restart1,'*');
302 *ptr = '\0';
303 sprintf(file,"%s" BIGINT_FORMAT "%s",restart1,ntimestep,ptr+1);
304 *ptr = '*';
305 if (last_restart != ntimestep) restart->write(file);
306 delete [] file;
307 if (restart_every_single) next_restart_single += restart_every_single;
308 else {
309 modify->clearstep_compute();
310 bigint nextrestart = static_cast<bigint>
311 (input->variable->compute_equal(ivar_restart_single));
312 if (nextrestart <= ntimestep)
313 error->all(FLERR,"Restart variable returned a bad timestep");
314 next_restart_single = nextrestart;
315 modify->addstep_compute(next_restart_single);
316 }
317 }
318 if (next_restart_double == ntimestep) {
319 if (last_restart != ntimestep) {
320 if (restart_toggle == 0) {
321 restart->write(restart2a);
322 restart_toggle = 1;
323 } else {
324 restart->write(restart2b);
325 restart_toggle = 0;
326 }
327 }
328 if (restart_every_double) next_restart_double += restart_every_double;
329 else {
330 modify->clearstep_compute();
331 bigint nextrestart = static_cast<bigint>
332 (input->variable->compute_equal(ivar_restart_double));
333 if (nextrestart <= ntimestep)
334 error->all(FLERR,"Restart variable returned a bad timestep");
335 next_restart_double = nextrestart;
336 modify->addstep_compute(next_restart_double);
337 }
338 }
339 last_restart = ntimestep;
340 next_restart = MIN(next_restart_single,next_restart_double);
341 }
342
343 // insure next_thermo forces output on last step of run
344 // thermo may invoke computes so wrap with clear/add
345
346 if (next_stats == ntimestep) {
347 modify->clearstep_compute();
348 if (last_stats != ntimestep) stats->compute(1);
349 last_stats = ntimestep;
350 if (var_stats) {
351 next_stats = static_cast<bigint>
352 (input->variable->compute_equal(ivar_stats));
353 if (next_stats <= ntimestep)
354 error->all(FLERR,"Stats every variable returned a bad timestep");
355 } else if (stats_every) next_stats += stats_every;
356 else next_stats = update->laststep;
357 next_stats = MIN(next_stats,update->laststep);
358 modify->addstep_compute(next_stats);
359 }
360
361 // next = next timestep any output will be done
362
363 next = MIN(next_dump_any,next_restart);
364 next = MIN(next,next_stats);
365 }
366
367 /* ----------------------------------------------------------------------
368 force a snapshot to be written for all dumps
369 ------------------------------------------------------------------------- */
370
write_dump(bigint ntimestep)371 void Output::write_dump(bigint ntimestep)
372 {
373 for (int idump = 0; idump < ndump; idump++) {
374 dump[idump]->write();
375 last_dump[idump] = ntimestep;
376 }
377 }
378
379 /* ----------------------------------------------------------------------
380 force restart file(s) to be written
381 ------------------------------------------------------------------------- */
382
write_restart(bigint ntimestep)383 void Output::write_restart(bigint ntimestep)
384 {
385 if (restart_flag_single) {
386 char *file = new char[strlen(restart1) + 16];
387 char *ptr = strchr(restart1,'*');
388 *ptr = '\0';
389 sprintf(file,"%s" BIGINT_FORMAT "%s",restart1,ntimestep,ptr+1);
390 *ptr = '*';
391 restart->write(file);
392 delete [] file;
393 }
394
395 if (restart_flag_double) {
396 if (restart_toggle == 0) {
397 restart->write(restart2a);
398 restart_toggle = 1;
399 } else {
400 restart->write(restart2b);
401 restart_toggle = 0;
402 }
403 }
404
405 last_restart = ntimestep;
406 }
407
408 /* ----------------------------------------------------------------------
409 timestep is being changed, called by update->reset_timestep()
410 reset next timestep values for dumps, restart, thermo output
411 reset to smallest value >= new timestep
412 if next timestep set by variable evaluation,
413 eval for ntimestep-1, so current ntimestep can be returned if needed
414 no guarantee that variable can be evaluated for ntimestep-1
415 if it depends on computes, but live with that rare case for now
416 ------------------------------------------------------------------------- */
417
reset_timestep(bigint ntimestep)418 void Output::reset_timestep(bigint ntimestep)
419 {
420 next_dump_any = MAXBIGINT;
421 for (int idump = 0; idump < ndump; idump++) {
422 if (every_dump[idump]) {
423 next_dump[idump] = (ntimestep/every_dump[idump])*every_dump[idump];
424 if (next_dump[idump] < ntimestep) next_dump[idump] += every_dump[idump];
425 } else {
426 modify->clearstep_compute();
427 update->ntimestep--;
428 bigint nextdump = static_cast<bigint>
429 (input->variable->compute_equal(ivar_dump[idump]));
430 if (nextdump < ntimestep)
431 error->all(FLERR,"Dump every variable returned a bad timestep");
432 update->ntimestep++;
433 next_dump[idump] = nextdump;
434 modify->addstep_compute(next_dump[idump]);
435 }
436 next_dump_any = MIN(next_dump_any,next_dump[idump]);
437 }
438
439 if (restart_flag_single) {
440 if (restart_every_single) {
441 next_restart_single =
442 (ntimestep/restart_every_single)*restart_every_single;
443 if (next_restart_single < ntimestep)
444 next_restart_single += restart_every_single;
445 } else {
446 modify->clearstep_compute();
447 update->ntimestep--;
448 bigint nextrestart = static_cast<bigint>
449 (input->variable->compute_equal(ivar_restart_single));
450 if (nextrestart < ntimestep)
451 error->all(FLERR,"Restart variable returned a bad timestep");
452 update->ntimestep++;
453 next_restart_single = nextrestart;
454 modify->addstep_compute(next_restart_single);
455 }
456 } else next_restart_single = update->laststep + 1;
457
458 if (restart_flag_double) {
459 if (restart_every_double) {
460 next_restart_double =
461 (ntimestep/restart_every_double)*restart_every_double;
462 if (next_restart_double < ntimestep)
463 next_restart_double += restart_every_double;
464 } else {
465 modify->clearstep_compute();
466 update->ntimestep--;
467 bigint nextrestart = static_cast<bigint>
468 (input->variable->compute_equal(ivar_restart_double));
469 if (nextrestart < ntimestep)
470 error->all(FLERR,"Restart variable returned a bad timestep");
471 update->ntimestep++;
472 next_restart_double = nextrestart;
473 modify->addstep_compute(next_restart_double);
474 }
475 } else next_restart_double = update->laststep + 1;
476
477 next_restart = MIN(next_restart_single,next_restart_double);
478
479 if (var_stats) {
480 modify->clearstep_compute();
481 update->ntimestep--;
482 next_stats = static_cast<bigint>
483 (input->variable->compute_equal(ivar_stats));
484 if (next_stats < ntimestep)
485 error->all(FLERR,"Stats_modify every variable returned a bad timestep");
486 update->ntimestep++;
487 next_stats = MIN(next_stats,update->laststep);
488 modify->addstep_compute(next_stats);
489 } else if (stats_every) {
490 next_stats = (ntimestep/stats_every)*stats_every;
491 if (next_stats < ntimestep) next_stats += stats_every;
492 next_stats = MIN(next_stats,update->laststep);
493 } else next_stats = update->laststep;
494
495 next = MIN(next_dump_any,next_restart);
496 next = MIN(next,next_stats);
497 }
498
499 /* ----------------------------------------------------------------------
500 add a Dump to list of Dumps
501 ------------------------------------------------------------------------- */
502
add_dump(int narg,char ** arg)503 void Output::add_dump(int narg, char **arg)
504 {
505 if (narg < 5) error->all(FLERR,"Illegal dump command");
506
507 // error checks
508
509 for (int idump = 0; idump < ndump; idump++)
510 if (strcmp(arg[0],dump[idump]->id) == 0)
511 error->all(FLERR,"Reuse of dump ID");
512 if (atoi(arg[3]) <= 0) error->all(FLERR,"Invalid dump frequency");
513
514 // extend Dump list if necessary
515
516 if (ndump == max_dump) {
517 max_dump += DELTA;
518 dump = (Dump **)
519 memory->srealloc(dump,max_dump*sizeof(Dump *),"output:dump");
520 memory->grow(every_dump,max_dump,"output:every_dump");
521 memory->grow(next_dump,max_dump,"output:next_dump");
522 memory->grow(last_dump,max_dump,"output:last_dump");
523 var_dump = (char **)
524 memory->srealloc(var_dump,max_dump*sizeof(char *),"output:var_dump");
525 memory->grow(ivar_dump,max_dump,"output:ivar_dump");
526 }
527
528 // create the Dump
529
530 if (0) return; // dummy line to enable else-if macro expansion
531
532 #define DUMP_CLASS
533 #define DumpStyle(key,Class) \
534 else if (strcmp(arg[1],#key) == 0) dump[ndump] = new Class(sparta,narg,arg);
535 #include "style_dump.h"
536 #undef DUMP_CLASS
537
538 else error->all(FLERR,"Unrecognized dump style");
539
540 every_dump[ndump] = atoi(arg[3]);
541 if (every_dump[ndump] <= 0) error->all(FLERR,"Illegal dump command");
542 last_dump[ndump] = -1;
543 var_dump[ndump] = NULL;
544 ndump++;
545 }
546
547 /* ----------------------------------------------------------------------
548 modify parameters of a Dump
549 ------------------------------------------------------------------------- */
550
modify_dump(int narg,char ** arg)551 void Output::modify_dump(int narg, char **arg)
552 {
553 if (narg < 1) error->all(FLERR,"Illegal dump_modify command");
554
555 // find which dump it is
556
557 int idump;
558 for (idump = 0; idump < ndump; idump++)
559 if (strcmp(arg[0],dump[idump]->id) == 0) break;
560 if (idump == ndump) error->all(FLERR,"Cound not find dump_modify ID");
561
562 dump[idump]->modify_params(narg-1,&arg[1]);
563 }
564
565 /* ----------------------------------------------------------------------
566 delete a Dump from list of Dumps
567 ------------------------------------------------------------------------- */
568
delete_dump(char * id)569 void Output::delete_dump(char *id)
570 {
571 // find which dump it is and delete it
572
573 int idump;
574 for (idump = 0; idump < ndump; idump++)
575 if (strcmp(id,dump[idump]->id) == 0) break;
576 if (idump == ndump) error->all(FLERR,"Could not find undump ID");
577
578 delete dump[idump];
579 delete [] var_dump[idump];
580
581 // move other dumps down in list one slot
582
583 for (int i = idump+1; i < ndump; i++) {
584 dump[i-1] = dump[i];
585 every_dump[i-1] = every_dump[i];
586 next_dump[i-1] = next_dump[i];
587 last_dump[i-1] = last_dump[i];
588 var_dump[i-1] = var_dump[i];
589 ivar_dump[i-1] = ivar_dump[i];
590 }
591 ndump--;
592 }
593
594 /* ----------------------------------------------------------------------
595 set stats output frequency from input script
596 ------------------------------------------------------------------------- */
597
set_stats(int narg,char ** arg)598 void Output::set_stats(int narg, char **arg)
599 {
600 if (narg != 1) error->all(FLERR,"Illegal stats command");
601
602 if (strstr(arg[0],"v_") == arg[0]) {
603 delete [] var_stats;
604 int n = strlen(&arg[0][2]) + 1;
605 var_stats = new char[n];
606 strcpy(var_stats,&arg[0][2]);
607 } else {
608 stats_every = atoi(arg[0]);
609 if (stats_every < 0) error->all(FLERR,"Illegal stats command");
610 }
611 }
612
613 /* ----------------------------------------------------------------------
614 new Stats style
615 ------------------------------------------------------------------------- */
616
create_stats(int narg,char ** arg)617 void Output::create_stats(int narg, char **arg)
618 {
619 if (narg < 1) error->all(FLERR,"Illegal stats_style command");
620 stats->set_fields(narg,arg);
621 }
622
623 /* ----------------------------------------------------------------------
624 setup restart capability
625 if only one filename and it contains no "*", then append ".*"
626 ------------------------------------------------------------------------- */
627
create_restart(int narg,char ** arg)628 void Output::create_restart(int narg, char **arg)
629 {
630 if (narg < 1) error->all(FLERR,"Illegal restart command");
631
632 int every = 0;
633 int varflag = 0;
634
635 if (strstr(arg[0],"v_") == arg[0]) varflag = 1;
636 else every = atoi(arg[0]);
637
638 if (!varflag && every == 0) {
639 if (narg != 1) error->all(FLERR,"Illegal restart command");
640
641 restart_flag = restart_flag_single = restart_flag_double = 0;
642 last_restart = -1;
643
644 delete restart;
645 restart = NULL;
646 delete [] restart1;
647 delete [] restart2a;
648 delete [] restart2b;
649 restart1 = restart2a = restart2b = NULL;
650 delete [] var_restart_single;
651 delete [] var_restart_double;
652 var_restart_single = var_restart_double = NULL;
653
654 return;
655 }
656
657 if (narg < 2) error->all(FLERR,"Illegal restart command");
658
659 int nfile = 0;
660 if (narg % 2 == 0) nfile = 1;
661 else nfile = 2;
662
663 if (nfile == 1) {
664 restart_flag = restart_flag_single = 1;
665
666 if (varflag) {
667 delete [] var_restart_single;
668 int n = strlen(&arg[0][2]) + 1;
669 var_restart_single = new char[n];
670 strcpy(var_restart_single,&arg[0][2]);
671 restart_every_single = 0;
672 } else restart_every_single = every;
673
674 int n = strlen(arg[1]) + 3;
675 restart1 = new char[n];
676 strcpy(restart1,arg[1]);
677 if (strchr(restart1,'*') == NULL) strcat(restart1,".*");
678 }
679
680 if (nfile == 2) {
681 restart_flag = restart_flag_double = 1;
682
683 if (varflag) {
684 delete [] var_restart_double;
685 int n = strlen(&arg[0][2]) + 1;
686 var_restart_double = new char[n];
687 strcpy(var_restart_double,&arg[0][2]);
688 restart_every_double = 0;
689 } else restart_every_double = every;
690
691 restart_toggle = 0;
692 int n = strlen(arg[1]) + 3;
693 restart2a = new char[n];
694 strcpy(restart2a,arg[1]);
695 n = strlen(arg[2]) + 1;
696 restart2b = new char[n];
697 strcpy(restart2b,arg[2]);
698 }
699
700 // check for multiproc output and an MPI-IO filename
701 // if 2 filenames, must be consistent
702
703 int multiproc;
704 if (strchr(arg[1],'%')) multiproc = comm->nprocs;
705 else multiproc = 0;
706 if (nfile == 2) {
707 if (multiproc && !strchr(arg[2],'%'))
708 error->all(FLERR,"Both restart files must use % or neither");
709 if (!multiproc && strchr(arg[2],'%'))
710 error->all(FLERR,"Both restart files must use % or neither");
711 }
712
713 // setup output style and process optional args
714
715 delete restart;
716 restart = new WriteRestart(sparta);
717 int iarg = nfile+1;
718 restart->multiproc_options(multiproc,narg-iarg,&arg[iarg]);
719 }
720
721 /* ----------------------------------------------------------------------
722 sum and print memory usage
723 ------------------------------------------------------------------------- */
724
memory_usage()725 void Output::memory_usage()
726 {
727 bigint pbytes,gbytes,sbytes,bytes;
728 pbytes = particle->memory_usage();
729 gbytes = grid->memory_usage();
730 sbytes = surf->memory_usage();
731 bytes = pbytes + gbytes + sbytes;
732 bytes += modify->memory_usage();
733
734 double scale = 1.0/1024.0/1024.0;
735
736 bigint ave,min,max;
737
738 MPI_Allreduce(&pbytes,&ave,1,MPI_SPARTA_BIGINT,MPI_SUM,world);
739 double pave = scale * ave/comm->nprocs;
740 MPI_Allreduce(&pbytes,&min,1,MPI_SPARTA_BIGINT,MPI_MIN,world);
741 double pmin = scale * min;
742 MPI_Allreduce(&pbytes,&max,1,MPI_SPARTA_BIGINT,MPI_MAX,world);
743 double pmax = scale * max;
744
745 MPI_Allreduce(&gbytes,&ave,1,MPI_SPARTA_BIGINT,MPI_SUM,world);
746 double gave = scale * ave/comm->nprocs;
747 MPI_Allreduce(&gbytes,&min,1,MPI_SPARTA_BIGINT,MPI_MIN,world);
748 double gmin = scale * min;
749 MPI_Allreduce(&gbytes,&max,1,MPI_SPARTA_BIGINT,MPI_MAX,world);
750 double gmax = scale * max;
751
752 MPI_Allreduce(&sbytes,&ave,1,MPI_SPARTA_BIGINT,MPI_SUM,world);
753 double save = scale * ave/comm->nprocs;
754 MPI_Allreduce(&sbytes,&min,1,MPI_SPARTA_BIGINT,MPI_MIN,world);
755 double smin = scale * min;
756 MPI_Allreduce(&sbytes,&max,1,MPI_SPARTA_BIGINT,MPI_MAX,world);
757 double smax = scale * max;
758
759 MPI_Allreduce(&bytes,&ave,1,MPI_SPARTA_BIGINT,MPI_SUM,world);
760 double tave = scale * ave/comm->nprocs;
761 MPI_Allreduce(&bytes,&min,1,MPI_SPARTA_BIGINT,MPI_MIN,world);
762 double tmin = scale * min;
763 MPI_Allreduce(&bytes,&max,1,MPI_SPARTA_BIGINT,MPI_MAX,world);
764 double tmax = scale * max;
765
766 if (comm->me == 0) {
767 if (screen) {
768 fprintf(screen,"Memory usage per proc in Mbytes:\n");
769 fprintf(screen," particles (ave,min,max) = %g %g %g\n",
770 pave,pmin,pmax);
771 fprintf(screen," grid (ave,min,max) = %g %g %g\n",
772 gave,gmin,gmax);
773 fprintf(screen," surf (ave,min,max) = %g %g %g\n",
774 save,smin,smax);
775 fprintf(screen," total (ave,min,max) = %g %g %g\n",
776 tave,tmin,tmax);
777 }
778 if (logfile) {
779 fprintf(logfile,"Memory usage per proc in Mbytes:\n");
780 fprintf(logfile," particles (ave,min,max) = %g %g %g\n",
781 pave,pmin,pmax);
782 fprintf(logfile," grid (ave,min,max) = %g %g %g\n",
783 gave,gmin,gmax);
784 fprintf(logfile," surf (ave,min,max) = %g %g %g\n",
785 save,smin,smax);
786 fprintf(logfile," total (ave,min,max) = %g %g %g\n",
787 tave,tmin,tmax);
788 }
789 }
790 }
791