1 /* ----------------------------------------------------------------------
2 This is the
3
4 ██╗ ██╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗████████╗███████╗
5 ██║ ██║██╔════╝ ██╔════╝ ██╔════╝ ██║ ██║╚══██╔══╝██╔════╝
6 ██║ ██║██║ ███╗██║ ███╗██║ ███╗███████║ ██║ ███████╗
7 ██║ ██║██║ ██║██║ ██║██║ ██║██╔══██║ ██║ ╚════██║
8 ███████╗██║╚██████╔╝╚██████╔╝╚██████╔╝██║ ██║ ██║ ███████║
9 ╚══════╝╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝®
10
11 DEM simulation engine, released by
12 DCS Computing Gmbh, Linz, Austria
13 http://www.dcs-computing.com, office@dcs-computing.com
14
15 LIGGGHTS® is part of CFDEM®project:
16 http://www.liggghts.com | http://www.cfdem.com
17
18 Core developer and main author:
19 Christoph Kloss, christoph.kloss@dcs-computing.com
20
21 LIGGGHTS® is open-source, distributed under the terms of the GNU Public
22 License, version 2 or later. It is distributed in the hope that it will
23 be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
24 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have
25 received a copy of the GNU General Public License along with LIGGGHTS®.
26 If not, see http://www.gnu.org/licenses . See also top-level README
27 and LICENSE files.
28
29 LIGGGHTS® and CFDEM® are registered trade marks of DCS Computing GmbH,
30 the producer of the LIGGGHTS® software and the CFDEM®coupling software
31 See http://www.cfdem.com/terms-trademark-policy for details.
32
33 -------------------------------------------------------------------------
34 Contributing author and copyright for this file:
35 This file is from LAMMPS
36 LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
37 http://lammps.sandia.gov, Sandia National Laboratories
38 Steve Plimpton, sjplimp@sandia.gov
39
40 Copyright (2003) Sandia Corporation. Under the terms of Contract
41 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
42 certain rights in this software. This software is distributed under
43 the GNU General Public License.
44 ------------------------------------------------------------------------- */
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include "output.h"
50 #include "style_dump.h"
51 #include "atom.h"
52 #include "neighbor.h"
53 #include "input.h"
54 #include "variable.h"
55 #include "comm.h"
56 #include "update.h"
57 #include "group.h"
58 #include "domain.h"
59 #include "thermo.h"
60 #include "modify.h"
61 #include "compute.h"
62 #include "force.h"
63 #include "dump.h"
64 #include "write_restart.h"
65 #include "accelerator_cuda.h"
66 #include "memory.h"
67 #include "error.h"
68 #include "signal_handling.h"
69
70 using namespace LAMMPS_NS;
71
72 #define DELTA 1
73
74 /* ----------------------------------------------------------------------
75 initialize all output
76 ------------------------------------------------------------------------- */
77
Output(LAMMPS * lmp)78 Output::Output(LAMMPS *lmp) :
79 Pointers(lmp),
80 restart_flag(false),
81 restart_flag_single(false),
82 restart_flag_double(false),
83 next_restart(0),
84 next_restart_single(0),
85 next_restart_double(0),
86 restart_every_single(0),
87 restart_every_double(0),
88 last_restart(0),
89 restart_toggle(0),
90 var_restart_single(NULL),
91 var_restart_double(NULL),
92 ivar_restart_single(0),
93 ivar_restart_double(0),
94 restart1(NULL),
95 restart2a(NULL),
96 restart2b(NULL),
97 restart(NULL)
98 {
99 char **newarg = new char*[4];
100 // create a default compute that calculates the temperature of the system
101 // NOTE: This compute is deprecated and will be removed in the future
102 newarg[0] = (char *) "thermo_temp";
103 newarg[1] = (char *) "all";
104 newarg[2] = (char *) "temp";
105 modify->add_compute(3,newarg,lmp->suffix);
106 // create a default compute that calculates the kinetic energy of the system
107 newarg[0] = (char *) "thermo_kin_eng";
108 newarg[1] = (char *) "all";
109 newarg[2] = (char *) "ke";
110 modify->add_compute(3,newarg,lmp->suffix);
111 delete [] newarg;
112
113 // create default Thermo class
114 newarg = new char*[1];
115 newarg[0] = (char *) "one";
116 thermo = new Thermo(lmp,1,newarg);
117 delete [] newarg;
118
119 thermo_every = 0;
120 var_thermo = NULL;
121
122 ndump = 0;
123 max_dump = 0;
124 every_dump = NULL;
125 next_dump = NULL;
126 last_dump = NULL;
127 var_dump = NULL;
128 ivar_dump = NULL;
129 dump = NULL;
130 }
131
132 /* ----------------------------------------------------------------------
133 free all memory
134 ------------------------------------------------------------------------- */
135
~Output()136 Output::~Output()
137 {
138 if (thermo)
139 delete thermo;
140 delete [] var_thermo;
141
142 memory->destroy(every_dump);
143 memory->destroy(next_dump);
144 memory->destroy(last_dump);
145 for (int i = 0; i < ndump; i++)
146 delete [] var_dump[i];
147 memory->sfree(var_dump);
148 memory->destroy(ivar_dump);
149 for (int i = 0; i < ndump; i++)
150 delete dump[i];
151 memory->sfree(dump);
152
153 delete [] restart1;
154 delete [] restart2a;
155 delete [] restart2b;
156 delete [] var_restart_single;
157 delete [] var_restart_double;
158 delete restart;
159 }
160
161 /* ---------------------------------------------------------------------- */
162
init()163 void Output::init()
164 {
165 thermo->init();
166 if (var_thermo) {
167 ivar_thermo = input->variable->find(var_thermo);
168 if (ivar_thermo < 0)
169 error->all(FLERR,"Variable name for thermo every does not exist");
170 if (!input->variable->equalstyle(ivar_thermo))
171 error->all(FLERR,"Variable for thermo every is invalid style");
172 }
173
174 for (int i = 0; i < ndump; i++) dump[i]->init();
175 for (int i = 0; i < ndump; i++)
176 if (every_dump[i] == 0) {
177 ivar_dump[i] = input->variable->find(var_dump[i]);
178 if (ivar_dump[i] < 0)
179 error->all(FLERR,"Variable name for dump every does not exist");
180 if (!input->variable->equalstyle(ivar_dump[i]))
181 error->all(FLERR,"Variable for dump every is invalid style");
182 }
183
184 if (restart_flag_single && restart_every_single == 0) {
185 ivar_restart_single = input->variable->find(var_restart_single);
186 if (ivar_restart_single < 0)
187 error->all(FLERR,"Variable name for restart does not exist");
188 if (!input->variable->equalstyle(ivar_restart_single))
189 error->all(FLERR,"Variable for restart is invalid style");
190 }
191 if (restart_flag_double && restart_every_double == 0) {
192 ivar_restart_double = input->variable->find(var_restart_double);
193 if (ivar_restart_double < 0)
194 error->all(FLERR,"Variable name for restart does not exist");
195 if (!input->variable->equalstyle(ivar_restart_double))
196 error->all(FLERR,"Variable for restart is invalid style");
197 }
198 }
199
200 /* ----------------------------------------------------------------------
201 perform output for setup of run/min
202 do dump first, so memory_usage will include dump allocation
203 do thermo last, so will print after memory_usage
204 memflag = 0/1 for printing out memory usage
205 ------------------------------------------------------------------------- */
206
setup(int memflag)207 void Output::setup(int memflag)
208 {
209 bigint ntimestep = update->ntimestep;
210
211 // perform dump at start of run only if:
212 // current timestep is multiple of every and last dump not >= this step
213 // this is first run after dump created and firstflag is set
214 // note that variable freq will not write unless triggered by firstflag
215 // set next_dump to multiple of every or variable value
216 // set next_dump_any to smallest next_dump
217 // wrap dumps that invoke computes and variable eval with clear/add
218 // if dump not written now, use addstep_compute_all() since don't know
219 // what computes the dump write would invoke
220 // if no dumps, set next_dump_any to last+1 so will not influence next
221
222 int writeflag;
223
224 if (ndump && update->restrict_output == 0) {
225 for (int idump = 0; idump < ndump; idump++) {
226 if (dump[idump]->clearstep || every_dump[idump] == 0)
227 modify->clearstep_compute();
228 writeflag = 0;
229 if (every_dump[idump] && ntimestep % every_dump[idump] == 0 &&
230 last_dump[idump] != ntimestep) writeflag = 1;
231 if (last_dump[idump] < 0 && dump[idump]->first_flag == 1) writeflag = 1;
232
233 if (writeflag) {
234 dump[idump]->write();
235 last_dump[idump] = ntimestep;
236 }
237 if (every_dump[idump])
238 next_dump[idump] =
239 (ntimestep/every_dump[idump])*every_dump[idump] + every_dump[idump];
240 else {
241 bigint nextdump = static_cast<bigint>
242 (input->variable->compute_equal(ivar_dump[idump]));
243 if (nextdump <= ntimestep)
244 error->all(FLERR,"Dump every variable returned a bad timestep");
245 next_dump[idump] = nextdump;
246 }
247 if (dump[idump]->clearstep || every_dump[idump] == 0) {
248 if (writeflag) modify->addstep_compute(next_dump[idump]);
249 else modify->addstep_compute_all(next_dump[idump]);
250 }
251 if (idump) next_dump_any = MIN(next_dump_any,next_dump[idump]);
252 else next_dump_any = next_dump[0];
253 }
254 } else next_dump_any = update->laststep + 1;
255
256 // do not write restart files at start of run
257 // set next_restart values to multiple of every or variable value
258 // wrap variable eval with clear/add
259 // if no restarts, set next_restart to last+1 so will not influence next
260
261 if (restart_flag && update->restrict_output == 0) {
262 if (restart_flag_single) {
263 if (restart_every_single)
264 next_restart_single =
265 (ntimestep/restart_every_single)*restart_every_single +
266 restart_every_single;
267 else {
268 bigint nextrestart = static_cast<bigint>
269 (input->variable->compute_equal(ivar_restart_single));
270 if (nextrestart <= ntimestep)
271 error->all(FLERR,"Restart variable returned a bad timestep");
272 next_restart_single = nextrestart;
273 }
274 } else next_restart_single = update->laststep + 1;
275 if (restart_flag_double) {
276 if (restart_every_double)
277 next_restart_double =
278 (ntimestep/restart_every_double)*restart_every_double +
279 restart_every_double;
280 else {
281 bigint nextrestart = static_cast<bigint>
282 (input->variable->compute_equal(ivar_restart_double));
283 if (nextrestart <= ntimestep)
284 error->all(FLERR,"Restart variable returned a bad timestep");
285 next_restart_double = nextrestart;
286 }
287 } else next_restart_double = update->laststep + 1;
288 next_restart = MIN(next_restart_single,next_restart_double);
289 } else next_restart = update->laststep + 1;
290
291 // print memory usage unless being called between multiple runs
292
293 if (memflag) memory_usage();
294
295 // set next_thermo to multiple of every or variable eval if var defined
296 // insure thermo output on last step of run
297 // thermo may invoke computes so wrap with clear/add
298
299 modify->clearstep_compute();
300
301 thermo->header();
302 thermo->compute(0);
303 last_thermo = ntimestep;
304
305 if (var_thermo) {
306 next_thermo = static_cast<bigint>
307 (input->variable->compute_equal(ivar_thermo));
308 if (next_thermo <= ntimestep)
309 error->all(FLERR,"Thermo every variable returned a bad timestep");
310 } else if (thermo_every) {
311 next_thermo = (ntimestep/thermo_every)*thermo_every + thermo_every;
312 next_thermo = MIN(next_thermo,update->laststep);
313 } else next_thermo = update->laststep;
314
315 modify->addstep_compute(next_thermo);
316
317 // next = next timestep any output will be done
318
319 next = MIN(next_dump_any,next_restart);
320 next = MIN(next,next_thermo);
321 }
322
323 /* ----------------------------------------------------------------------
324 perform all output for this timestep
325 only perform output if next matches current step and last output doesn't
326 do dump/restart before thermo so thermo CPU time will include them
327 ------------------------------------------------------------------------- */
328
write(bigint ntimestep)329 void Output::write(bigint ntimestep)
330 {
331 // next_dump does not force output on last step of run
332 // wrap dumps that invoke computes or eval of variable with clear/add
333 // download data from GPU if necessary
334
335 if (next_dump_any == ntimestep) {
336 if (lmp->cuda && !lmp->cuda->oncpu) lmp->cuda->downloadAll();
337
338 for (int idump = 0; idump < ndump; idump++) {
339 if (next_dump[idump] == ntimestep) {
340 if (dump[idump]->clearstep || every_dump[idump] == 0)
341 modify->clearstep_compute();
342 if (last_dump[idump] != ntimestep) {
343 dump[idump]->write();
344 last_dump[idump] = ntimestep;
345 }
346 if (every_dump[idump]) next_dump[idump] += every_dump[idump];
347 else {
348 bigint nextdump = static_cast<bigint>
349 (input->variable->compute_equal(ivar_dump[idump]));
350 if (nextdump <= ntimestep)
351 error->all(FLERR,"Dump every variable returned a bad timestep");
352 next_dump[idump] = nextdump;
353 }
354 if (dump[idump]->clearstep || every_dump[idump] == 0)
355 modify->addstep_compute(next_dump[idump]);
356 }
357 if (idump) next_dump_any = MIN(next_dump_any,next_dump[idump]);
358 else next_dump_any = next_dump[0];
359 }
360 }
361
362 // next_restart does not force output on last step of run
363 // for toggle = 0, replace "*" with current timestep in restart filename
364 // download data from GPU if necessary
365 // eval of variable may invoke computes so wrap with clear/add
366
367 if (next_restart == ntimestep) {
368 if (lmp->cuda && !lmp->cuda->oncpu) lmp->cuda->downloadAll();
369
370 if (next_restart_single == ntimestep) {
371 char *file = new char[strlen(restart1) + 16];
372 char *ptr = strchr(restart1,'*');
373 *ptr = '\0';
374 sprintf(file,"%s" BIGINT_FORMAT "%s",restart1,ntimestep,ptr+1);
375 *ptr = '*';
376 if (last_restart != ntimestep) restart->write(file);
377 delete [] file;
378 if (restart_every_single) next_restart_single += restart_every_single;
379 else {
380 modify->clearstep_compute();
381 bigint nextrestart = static_cast<bigint>
382 (input->variable->compute_equal(ivar_restart_single));
383 if (nextrestart <= ntimestep)
384 error->all(FLERR,"Restart variable returned a bad timestep");
385 next_restart_single = nextrestart;
386 modify->addstep_compute(next_restart_single);
387 }
388 }
389 if (next_restart_double == ntimestep) {
390 if (last_restart != ntimestep) {
391 if (restart_toggle == 0) {
392 restart->write(restart2a);
393 restart_toggle = 1;
394 } else {
395 restart->write(restart2b);
396 restart_toggle = 0;
397 }
398 }
399 if (restart_every_double) next_restart_double += restart_every_double;
400 else {
401 modify->clearstep_compute();
402 bigint nextrestart = static_cast<bigint>
403 (input->variable->compute_equal(ivar_restart_double));
404 if (nextrestart <= ntimestep)
405 error->all(FLERR,"Restart variable returned a bad timestep");
406 next_restart_double = nextrestart;
407 modify->addstep_compute(next_restart_double);
408 }
409 }
410 last_restart = ntimestep;
411 next_restart = MIN(next_restart_single,next_restart_double);
412
413 if (SignalHandler::request_write_restart) {
414 char *file = new char[24 + 16 + 5];
415 sprintf(file,"restart_forced_liggghts_" BIGINT_FORMAT ".data",ntimestep);
416 bool has_restart = restart != NULL;
417 if (!has_restart)
418 restart = new WriteRestart(lmp);
419 restart->write(file);
420 if (!has_restart)
421 {
422 delete restart;
423 restart = NULL;
424 }
425 delete [] file;
426 SignalHandler::request_write_restart = false;
427 error->warning(FLERR, "Forced restart written");
428 }
429 }
430
431 // insure next_thermo forces output on last step of run
432 // thermo may invoke computes so wrap with clear/add
433
434 if (next_thermo == ntimestep) {
435 modify->clearstep_compute();
436 // check all computes and those with update_on_run_end activated will be updated
437 if (ntimestep == update->laststep)
438 modify->update_computes_on_run_end();
439 if (last_thermo != ntimestep) thermo->compute(1);
440 last_thermo = ntimestep;
441 if (var_thermo) {
442 next_thermo = static_cast<bigint>
443 (input->variable->compute_equal(ivar_thermo));
444 if (next_thermo <= ntimestep)
445 error->all(FLERR,"Thermo every variable returned a bad timestep");
446 } else if (thermo_every) next_thermo += thermo_every;
447 else next_thermo = update->laststep;
448 next_thermo = MIN(next_thermo,update->laststep);
449 modify->addstep_compute(next_thermo);
450 }
451
452 // next = next timestep any output will be done
453
454 next = MIN(next_dump_any,next_restart);
455 next = MIN(next,next_thermo);
456 }
457
458 /* ----------------------------------------------------------------------
459 force a snapshot to be written for all dumps
460 called from PRD and TAD
461 ------------------------------------------------------------------------- */
462
write_dump(bigint ntimestep)463 void Output::write_dump(bigint ntimestep)
464 {
465 for (int idump = 0; idump < ndump; idump++) {
466 dump[idump]->write();
467 last_dump[idump] = ntimestep;
468 }
469 }
470
471 /* ----------------------------------------------------------------------
472 force restart file(s) to be written
473 called from PRD and TAD
474 ------------------------------------------------------------------------- */
475
write_restart(bigint ntimestep)476 void Output::write_restart(bigint ntimestep)
477 {
478 if (restart_flag_single) {
479 char *file = new char[strlen(restart1) + 16];
480 char *ptr = strchr(restart1,'*');
481 *ptr = '\0';
482 sprintf(file,"%s" BIGINT_FORMAT "%s",restart1,ntimestep,ptr+1);
483 *ptr = '*';
484 restart->write(file);
485 delete [] file;
486 }
487
488 if (restart_flag_double) {
489 if (restart_toggle == 0) {
490 restart->write(restart2a);
491 restart_toggle = 1;
492 } else {
493 restart->write(restart2b);
494 restart_toggle = 0;
495 }
496 }
497
498 last_restart = ntimestep;
499 }
500
501 /* ----------------------------------------------------------------------
502 timestep is being changed, called by update->reset_timestep()
503 reset next timestep values for dumps, restart, thermo output
504 reset to smallest value >= new timestep
505 if next timestep set by variable evaluation,
506 eval for ntimestep-1, so current ntimestep can be returned if needed
507 no guarantee that variable can be evaluated for ntimestep-1
508 if it depends on computes, but live with that rare case for now
509 ------------------------------------------------------------------------- */
510
reset_timestep(bigint ntimestep)511 void Output::reset_timestep(bigint ntimestep)
512 {
513 next_dump_any = MAXBIGINT;
514 for (int idump = 0; idump < ndump; idump++) {
515 if (every_dump[idump]) {
516 next_dump[idump] = (ntimestep/every_dump[idump])*every_dump[idump];
517 if (next_dump[idump] < ntimestep) next_dump[idump] += every_dump[idump];
518 } else {
519 modify->clearstep_compute();
520 update->ntimestep--;
521 bigint nextdump = static_cast<bigint>
522 (input->variable->compute_equal(ivar_dump[idump]));
523 if (nextdump < ntimestep)
524 error->all(FLERR,"Dump every variable returned a bad timestep");
525 update->ntimestep++;
526 next_dump[idump] = nextdump;
527 modify->addstep_compute(next_dump[idump]);
528 }
529 next_dump_any = MIN(next_dump_any,next_dump[idump]);
530 }
531
532 if (restart_flag_single) {
533 if (restart_every_single) {
534 next_restart_single =
535 (ntimestep/restart_every_single)*restart_every_single;
536 if (next_restart_single < ntimestep)
537 next_restart_single += restart_every_single;
538 } else {
539 modify->clearstep_compute();
540 update->ntimestep--;
541 bigint nextrestart = static_cast<bigint>
542 (input->variable->compute_equal(ivar_restart_single));
543 if (nextrestart < ntimestep)
544 error->all(FLERR,"Restart variable returned a bad timestep");
545 update->ntimestep++;
546 next_restart_single = nextrestart;
547 modify->addstep_compute(next_restart_single);
548 }
549 } else next_restart_single = update->laststep + 1;
550
551 if (restart_flag_double) {
552 if (restart_every_double) {
553 next_restart_double =
554 (ntimestep/restart_every_double)*restart_every_double;
555 if (next_restart_double < ntimestep)
556 next_restart_double += restart_every_double;
557 } else {
558 modify->clearstep_compute();
559 update->ntimestep--;
560 bigint nextrestart = static_cast<bigint>
561 (input->variable->compute_equal(ivar_restart_double));
562 if (nextrestart < ntimestep)
563 error->all(FLERR,"Restart variable returned a bad timestep");
564 update->ntimestep++;
565 next_restart_double = nextrestart;
566 modify->addstep_compute(next_restart_double);
567 }
568 } else next_restart_double = update->laststep + 1;
569
570 next_restart = MIN(next_restart_single,next_restart_double);
571
572 if (var_thermo) {
573 modify->clearstep_compute();
574 update->ntimestep--;
575 next_thermo = static_cast<bigint>
576 (input->variable->compute_equal(ivar_thermo));
577 if (next_thermo < ntimestep)
578 error->all(FLERR,"Thermo every variable returned a bad timestep");
579 update->ntimestep++;
580 next_thermo = MIN(next_thermo,update->laststep);
581 modify->addstep_compute(next_thermo);
582 } else if (thermo_every) {
583 next_thermo = (ntimestep/thermo_every)*thermo_every;
584 if (next_thermo < ntimestep) next_thermo += thermo_every;
585 next_thermo = MIN(next_thermo,update->laststep);
586 } else next_thermo = update->laststep;
587
588 next = MIN(next_dump_any,next_restart);
589 next = MIN(next,next_thermo);
590 }
591
592 /* ----------------------------------------------------------------------
593 add a Dump to list of Dumps
594 ------------------------------------------------------------------------- */
595
add_dump(int narg,char ** arg)596 void Output::add_dump(int narg, char **arg)
597 {
598 if (narg < 5) error->all(FLERR,"Illegal dump command");
599
600 // error checks
601
602 for (int idump = 0; idump < ndump; idump++)
603 if (strcmp(arg[0],dump[idump]->id) == 0)
604 error->all(FLERR,"Reuse of dump ID");
605 int igroup = group->find(arg[1]);
606 if (igroup == -1) error->all(FLERR,"Could not find dump group ID");
607 if (force->inumeric(FLERR,arg[3]) <= 0)
608 error->all(FLERR,"Invalid dump frequency");
609
610 // extend Dump list if necessary
611
612 if (ndump == max_dump) {
613 max_dump += DELTA;
614 dump = (Dump **)
615 memory->srealloc(dump,max_dump*sizeof(Dump *),"output:dump");
616 memory->grow(every_dump,max_dump,"output:every_dump");
617 memory->grow(next_dump,max_dump,"output:next_dump");
618 memory->grow(last_dump,max_dump,"output:last_dump");
619 var_dump = (char **)
620 memory->srealloc(var_dump,max_dump*sizeof(char *),"output:var_dump");
621 memory->grow(ivar_dump,max_dump,"output:ivar_dump");
622 }
623
624 // create the Dump
625
626 if (0) return; // dummy line to enable else-if macro expansion
627
628 #define DUMP_CLASS
629 #define DumpStyle(key,Class) \
630 else if (strcmp(arg[2],#key) == 0) dump[ndump] = new Class(lmp,narg,arg);
631 #include "style_dump.h"
632 #undef DUMP_CLASS
633
634 else error->all(FLERR,"Invalid dump style");
635
636 every_dump[ndump] = force->inumeric(FLERR,arg[3]);
637 if (every_dump[ndump] <= 0) error->all(FLERR,"Illegal dump command");
638 last_dump[ndump] = -1;
639 var_dump[ndump] = NULL;
640 ndump++;
641 }
642
643 /* ----------------------------------------------------------------------
644 modify parameters of a Dump
645 ------------------------------------------------------------------------- */
646
modify_dump(int narg,char ** arg)647 void Output::modify_dump(int narg, char **arg)
648 {
649 if (narg < 1) error->all(FLERR,"Illegal dump_modify command");
650
651 // find which dump it is
652
653 int idump;
654 for (idump = 0; idump < ndump; idump++)
655 if (strcmp(arg[0],dump[idump]->id) == 0) break;
656 if (idump == ndump) error->all(FLERR,"Cound not find dump_modify ID");
657
658 dump[idump]->modify_params(narg-1,&arg[1]);
659 }
660
661 /* ----------------------------------------------------------------------
662 delete a Dump from list of Dumps
663 ------------------------------------------------------------------------- */
664
delete_dump(char * id)665 void Output::delete_dump(char *id)
666 {
667 // find which dump it is and delete it
668
669 int idump;
670 for (idump = 0; idump < ndump; idump++)
671 if (strcmp(id,dump[idump]->id) == 0) break;
672 if (idump == ndump) error->all(FLERR,"Could not find undump ID");
673
674 delete dump[idump];
675 delete [] var_dump[idump];
676
677 // move other dumps down in list one slot
678
679 for (int i = idump+1; i < ndump; i++) {
680 dump[i-1] = dump[i];
681 every_dump[i-1] = every_dump[i];
682 next_dump[i-1] = next_dump[i];
683 last_dump[i-1] = last_dump[i];
684 var_dump[i-1] = var_dump[i];
685 ivar_dump[i-1] = ivar_dump[i];
686 }
687 ndump--;
688 }
689
690 /* ----------------------------------------------------------------------
691 set thermo output frequency from input script
692 ------------------------------------------------------------------------- */
693
set_thermo(int narg,char ** arg)694 void Output::set_thermo(int narg, char **arg)
695 {
696 if (narg != 1) error->all(FLERR,"Illegal thermo command");
697
698 if (strstr(arg[0],"v_") == arg[0]) {
699 delete [] var_thermo;
700 int n = strlen(&arg[0][2]) + 1;
701 var_thermo = new char[n];
702 strcpy(var_thermo,&arg[0][2]);
703 } else {
704 thermo_every = force->inumeric(FLERR,arg[0]);
705 if (thermo_every < 0) error->all(FLERR,"Illegal thermo command");
706 }
707 }
708
709 /* ----------------------------------------------------------------------
710 new Thermo style
711 ------------------------------------------------------------------------- */
712
create_thermo(int narg,char ** arg)713 void Output::create_thermo(int narg, char **arg)
714 {
715 if (narg < 1) error->all(FLERR,"Illegal thermo_style command");
716
717 // don't allow this so that dipole style can safely allocate inertia vector
718
719 if (domain->box_exist == 0)
720 error->all(FLERR,"Thermo_style command before simulation box is defined");
721
722 // warn if previous thermo had been modified via thermo_modify command
723
724 if (thermo->modified && comm->me == 0 && !lmp->wb)
725 error->warning(FLERR,"New thermo_style command, "
726 "previous thermo_modify settings will be lost");
727
728 // set thermo = NULL in case new Thermo throws an error
729
730 delete thermo;
731 thermo = NULL;
732 thermo = new Thermo(lmp,narg,arg);
733 }
734
735 /* ----------------------------------------------------------------------
736 setup restart capability for single or double output files
737 if only one filename and it contains no "*", then append ".*"
738 ------------------------------------------------------------------------- */
739
create_restart(int narg,char ** arg)740 void Output::create_restart(int narg, char **arg)
741 {
742 if (narg < 1) error->all(FLERR,"Illegal restart command");
743
744 int every = 0;
745 int varflag = 0;
746
747 if (strstr(arg[0],"v_") == arg[0]) varflag = 1;
748 else every = force->inumeric(FLERR,arg[0]);
749
750 if (!varflag && every == 0) {
751 if (narg != 1) error->all(FLERR,"Illegal restart command");
752
753 restart_flag = restart_flag_single = restart_flag_double = false;
754 last_restart = -1;
755
756 delete restart;
757 restart = NULL;
758 delete [] restart1;
759 delete [] restart2a;
760 delete [] restart2b;
761 restart1 = restart2a = restart2b = NULL;
762 delete [] var_restart_single;
763 delete [] var_restart_double;
764 var_restart_single = var_restart_double = NULL;
765
766 return;
767 }
768
769 if (narg != 2 && narg != 3) error->all(FLERR,"Illegal restart command");
770
771 if (narg == 2) {
772 restart_flag = restart_flag_single = true;
773
774 if (varflag) {
775 delete [] var_restart_single;
776 int n = strlen(&arg[0][2]) + 1;
777 var_restart_single = new char[n];
778 strcpy(var_restart_single,&arg[0][2]);
779 restart_every_single = 0;
780 } else restart_every_single = every;
781
782 int n = strlen(arg[1]) + 3;
783 restart1 = new char[n];
784 strcpy(restart1,arg[1]);
785 if (strchr(restart1,'*') == NULL) strcat(restart1,".*");
786 }
787
788 if (narg == 3) {
789 restart_flag = restart_flag_double = true;
790
791 if (varflag) {
792 delete [] var_restart_double;
793 int n = strlen(&arg[0][2]) + 1;
794 var_restart_double = new char[n];
795 strcpy(var_restart_double,&arg[0][2]);
796 restart_every_double = 0;
797 } else restart_every_double = every;
798
799 restart_toggle = 0;
800 int n = strlen(arg[1]) + 3;
801 restart2a = new char[n];
802 strcpy(restart2a,arg[1]);
803 n = strlen(arg[2]) + 1;
804 restart2b = new char[n];
805 strcpy(restart2b,arg[2]);
806 }
807
808 if (restart == NULL) restart = new WriteRestart(lmp);
809 }
810
811 /* ----------------------------------------------------------------------
812 sum and print memory usage
813 result is only memory on proc 0, not averaged across procs
814 ------------------------------------------------------------------------- */
815
memory_usage()816 void Output::memory_usage()
817 {
818 bigint bytes = 0;
819 bytes += atom->memory_usage();
820 bytes += neighbor->memory_usage();
821 bytes += comm->memory_usage();
822 bytes += update->memory_usage();
823 bytes += force->memory_usage();
824 bytes += modify->memory_usage();
825 for (int i = 0; i < ndump; i++) bytes += dump[i]->memory_usage();
826
827 double mbytes = bytes/1024.0/1024.0;
828
829 if (comm->me == 0) {
830 if (screen)
831 fprintf(screen,"Memory usage per processor = %g Mbytes\n",mbytes);
832 if (logfile)
833 fprintf(logfile,"Memory usage per processor = %g Mbytes\n",mbytes);
834 }
835 }
836
837 /* ----------------------------------------------------------------------
838 identifies when the next restart will be written
839 also handles signals to force writing of a restart
840 this function is called by Neighbor::decide
841 ------------------------------------------------------------------------- */
842
restart_requested(const bigint ntimestep)843 bool Output::restart_requested(const bigint ntimestep)
844 {
845 if (SignalHandler::request_write_restart || SignalHandler::request_quit)
846 {
847 // we have something to write now
848 next = ntimestep;
849 // if quit is request write thermo
850 if (SignalHandler::request_quit)
851 next_thermo = ntimestep;
852 // if restart writing is request do it
853 if (SignalHandler::request_write_restart)
854 next_restart = ntimestep;
855 }
856 return next_restart == ntimestep;
857 }
858
859 /* ----------------------------------------------------------------------
860 request a restart for a certain timestep
861 ------------------------------------------------------------------------- */
862
request_restart(const bigint ntimestep)863 void Output::request_restart(const bigint ntimestep)
864 {
865 if (restart_flag)
866 {
867 next_restart = ntimestep;
868 if (restart_every_single)
869 next_restart_single = ntimestep;
870 if (restart_every_double)
871 next_restart_double = ntimestep;
872 }
873 }
874