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 "spatype.h"
16 #include "stdlib.h"
17 #include "string.h"
18 #include "fix_ave_time.h"
19 #include "update.h"
20 #include "modify.h"
21 #include "compute.h"
22 #include "input.h"
23 #include "variable.h"
24 #include "memory.h"
25 #include "error.h"
26
27 using namespace SPARTA_NS;
28
29 enum{COMPUTE,FIX,VARIABLE};
30 enum{ONE,RUNNING,WINDOW};
31 enum{SCALAR,VECTOR};
32
33 #define INVOKED_SCALAR 1
34 #define INVOKED_VECTOR 2
35 #define INVOKED_ARRAY 4
36 #define DELTA 8;
37
38 /* ---------------------------------------------------------------------- */
39
FixAveTime(SPARTA * sparta,int narg,char ** arg)40 FixAveTime::FixAveTime(SPARTA *sparta, int narg, char **arg) :
41 Fix(sparta, narg, arg)
42 {
43 if (narg < 6) error->all(FLERR,"Illegal fix ave/time command");
44
45 MPI_Comm_rank(world,&me);
46
47 nevery = atoi(arg[2]);
48 nrepeat = atoi(arg[3]);
49 nfreq = atoi(arg[4]);
50
51 time_depend = 1;
52 global_freq = nfreq;
53
54 // scan values to count them
55 // then read options so know mode = SCALAR/VECTOR before re-reading values
56
57 nvalues = 0;
58
59 int iarg = 5;
60 while (iarg < narg) {
61 if ((strncmp(arg[iarg],"c_",2) == 0) ||
62 (strncmp(arg[iarg],"f_",2) == 0) ||
63 (strncmp(arg[iarg],"v_",2) == 0)) {
64 nvalues++;
65 iarg++;
66 } else break;
67 }
68
69 if (nvalues == 0) error->all(FLERR,"No values in fix ave/time command");
70
71 options(iarg,narg,arg);
72
73 // expand args if any have wildcard character "*"
74 // this can reset nvalues
75
76 int expand = 0;
77 char **earg;
78 nvalues = input->expand_args(nvalues,&arg[5],mode,earg);
79
80 if (earg != &arg[5]) expand = 1;
81 arg = earg;
82
83 // parse values
84
85 which = new int[nvalues];
86 argindex = new int[nvalues];
87 value2index = new int[nvalues];
88 offcol = new int[nvalues];
89 ids = new char*[nvalues];
90
91 for (int i = 0; i < nvalues; i++) {
92 if (arg[i][0] == 'c') which[i] = COMPUTE;
93 else if (arg[i][0] == 'f') which[i] = FIX;
94 else if (arg[i][0] == 'v') which[i] = VARIABLE;
95
96 int n = strlen(arg[i]);
97 char *suffix = new char[n];
98 strcpy(suffix,&arg[i][2]);
99
100 char *ptr = strchr(suffix,'[');
101 if (ptr) {
102 if (suffix[strlen(suffix)-1] != ']')
103 error->all(FLERR,"Illegal fix ave/time command");
104 argindex[i] = atoi(ptr+1);
105 *ptr = '\0';
106 } else argindex[i] = 0;
107
108 n = strlen(suffix) + 1;
109 ids[i] = new char[n];
110 strcpy(ids[i],suffix);
111 delete [] suffix;
112 }
113
114 // set off columns now that nvalues is finalized
115
116 for (int i = 0; i < nvalues; i++) offcol[i] = 0;
117 for (int i = 0; i < noff; i++) {
118 if (offlist[i] < 1 || offlist[i] > nvalues)
119 error->all(FLERR,"Invalid fix ave/time off column");
120 offcol[offlist[i]-1] = 1;
121 }
122
123 // setup and error check
124 // for fix inputs, check that fix frequency is acceptable
125
126 if (nevery <= 0 || nrepeat <= 0 || nfreq <= 0)
127 error->all(FLERR,"Illegal fix ave/time command");
128 if (nfreq % nevery || (nrepeat-1)*nevery >= nfreq)
129 error->all(FLERR,"Illegal fix ave/time command");
130
131 for (int i = 0; i < nvalues; i++) {
132 if (which[i] == COMPUTE && mode == SCALAR) {
133 int icompute = modify->find_compute(ids[i]);
134 if (icompute < 0)
135 error->all(FLERR,"Compute ID for fix ave/time does not exist");
136 if (argindex[i] == 0 && modify->compute[icompute]->scalar_flag == 0)
137 error->all(FLERR,"Fix ave/time compute does not calculate a scalar");
138 if (argindex[i] && modify->compute[icompute]->vector_flag == 0)
139 error->all(FLERR,"Fix ave/time compute does not calculate a vector");
140 if (argindex[i] && argindex[i] > modify->compute[icompute]->size_vector)
141 error->all(FLERR,
142 "Fix ave/time compute vector is accessed out-of-range");
143
144 } else if (which[i] == COMPUTE && mode == VECTOR) {
145 int icompute = modify->find_compute(ids[i]);
146 if (icompute < 0)
147 error->all(FLERR,"Compute ID for fix ave/time does not exist");
148 if (argindex[i] == 0 && modify->compute[icompute]->vector_flag == 0)
149 error->all(FLERR,"Fix ave/time compute does not calculate a vector");
150 if (argindex[i] && modify->compute[icompute]->array_flag == 0)
151 error->all(FLERR,"Fix ave/time compute does not calculate an array");
152 if (argindex[i] &&
153 argindex[i] > modify->compute[icompute]->size_array_cols)
154 error->all(FLERR,"Fix ave/time compute array is accessed out-of-range");
155
156 } else if (which[i] == FIX && mode == SCALAR) {
157 int ifix = modify->find_fix(ids[i]);
158 if (ifix < 0)
159 error->all(FLERR,"Fix ID for fix ave/time does not exist");
160 if (argindex[i] == 0 && modify->fix[ifix]->scalar_flag == 0)
161 error->all(FLERR,"Fix ave/time fix does not calculate a scalar");
162 if (argindex[i] && modify->fix[ifix]->vector_flag == 0)
163 error->all(FLERR,"Fix ave/time fix does not calculate a vector");
164 if (argindex[i] && argindex[i] > modify->fix[ifix]->size_vector)
165 error->all(FLERR,"Fix ave/time fix vector is accessed out-of-range");
166 if (nevery % modify->fix[ifix]->global_freq)
167 error->all(FLERR,
168 "Fix for fix ave/time not computed at compatible time");
169
170 } else if (which[i] == FIX && mode == VECTOR) {
171 int ifix = modify->find_fix(ids[i]);
172 if (ifix < 0)
173 error->all(FLERR,"Fix ID for fix ave/time does not exist");
174 if (argindex[i] == 0 && modify->fix[ifix]->vector_flag == 0)
175 error->all(FLERR,"Fix ave/time fix does not calculate a vector");
176 if (argindex[i] && modify->fix[ifix]->array_flag == 0)
177 error->all(FLERR,"Fix ave/time fix does not calculate an array");
178 if (argindex[i] && argindex[i] > modify->fix[ifix]->size_array_cols)
179 error->all(FLERR,"Fix ave/time fix array is accessed out-of-range");
180 if (nevery % modify->fix[ifix]->global_freq)
181 error->all(FLERR,
182 "Fix for fix ave/time not computed at compatible time");
183
184 } else if (which[i] == VARIABLE) {
185 int ivariable = input->variable->find(ids[i]);
186 if (ivariable < 0)
187 error->all(FLERR,"Variable name for fix ave/time does not exist");
188 if (input->variable->equal_style(ivariable) == 0)
189 error->all(FLERR,"Fix ave/time variable is not equal-style variable");
190 if (mode == VECTOR)
191 error->all(FLERR,"Fix ave/time cannot use variable with vector mode");
192 }
193 }
194
195 // if VECTOR mode, check that all columns are same length
196 // nrows = # of rows in output array
197
198 if (mode == VECTOR) {
199 int length;
200
201 for (int i = 0; i < nvalues; i++) {
202 if (which[i] == COMPUTE) {
203 int icompute = modify->find_compute(ids[i]);
204 if (argindex[i] == 0) length = modify->compute[icompute]->size_vector;
205 else length = modify->compute[icompute]->size_array_rows;
206 } else if (which[i] == FIX) {
207 int ifix = modify->find_fix(ids[i]);
208 if (argindex[i] == 0) length = modify->fix[ifix]->size_vector;
209 else length = modify->fix[ifix]->size_array_rows;
210 }
211 if (i == 0) nrows = length;
212 else if (length != nrows)
213 error->all(FLERR,"Fix ave/time columns are inconsistent lengths");
214 }
215
216 column = new double[nrows];
217 } else column = NULL;
218
219 // print file comment lines
220 // for mode = VECTOR, cannot use arg to print
221 // since array args may have been expanded to multiple vectors
222
223 if (fp && me == 0) {
224 if (title1) fprintf(fp,"%s\n",title1);
225 else fprintf(fp,"# Time-averaged data for fix %s\n",id);
226 if (title2) fprintf(fp,"%s\n",title2);
227 else if (mode == SCALAR) {
228 fprintf(fp,"# TimeStep");
229 for (int i = 0; i < nvalues; i++) fprintf(fp," %s",earg[i]);
230 fprintf(fp,"\n");
231 } else fprintf(fp,"# TimeStep Number-of-rows\n");
232 if (title3 && mode == VECTOR) fprintf(fp,"%s\n",title3);
233 else if (mode == VECTOR) {
234 fprintf(fp,"# Row");
235 for (int i = 0; i < nvalues; i++) fprintf(fp," %s",earg[i]);
236 fprintf(fp,"\n");
237 }
238 }
239
240 delete [] title1;
241 delete [] title2;
242 delete [] title3;
243
244 // if wildcard expansion occurred, free earg memory from expand_args()
245 // wait to do this until after file comment lines are printed
246
247 if (expand) {
248 for (int i = 0; i < nvalues; i++) delete [] earg[i];
249 memory->sfree(earg);
250 }
251
252 // allocate accumulators
253
254 vector = vector_total = NULL;
255 vector_list = NULL;
256 array = array_total = NULL;
257 array_list = NULL;
258
259 if (mode == SCALAR) {
260 vector = new double[nvalues];
261 vector_total = new double[nvalues];
262 if (ave == WINDOW)
263 memory->create(vector_list,nwindow,nvalues,"ave/time:vector_list");
264 } else {
265 memory->create(array,nrows,nvalues,"ave/time:array");
266 memory->create(array_total,nrows,nvalues,"ave/time:array_total");
267 if (ave == WINDOW)
268 memory->create(array_list,nwindow,nrows,nvalues,"ave/time:array_list");
269 }
270
271 // this fix produces either a global scalar or vector or array
272 // SCALAR mode produces either a scalar or vector
273 // VECTOR mode produces either a vector or array
274
275 if (mode == SCALAR) {
276 if (nvalues == 1) scalar_flag = 1;
277 else {
278 vector_flag = 1;
279 size_vector = nvalues;
280 }
281 } else {
282 if (nvalues == 1) {
283 vector_flag = 1;
284 size_vector = nrows;
285 } else {
286 array_flag = 1;
287 size_array_rows = nrows;
288 size_array_cols = nvalues;
289 }
290 }
291
292 // initializations
293 // set vector_total/array_total to zero since it accumulates
294
295 irepeat = 0;
296 iwindow = window_limit = 0;
297 norm = 0;
298
299 if (mode == SCALAR)
300 for (int i = 0; i < nvalues; i++) vector_total[i] = 0.0;
301 else
302 for (int i = 0; i < nrows; i++)
303 for (int j = 0; j < nvalues; j++)
304 array_total[i][j] = 0.0;
305
306 // nvalid = next step on which end_of_step does something
307 // add nvalid to all computes that store invocation times
308 // since don't know a priori which are invoked by this fix
309 // once in end_of_step() can set timestep for ones actually invoked
310
311 nvalid = nextvalid();
312 modify->addstep_compute_all(nvalid);
313 }
314
315 /* ---------------------------------------------------------------------- */
316
~FixAveTime()317 FixAveTime::~FixAveTime()
318 {
319 delete [] which;
320 delete [] argindex;
321 delete [] value2index;
322 delete [] offcol;
323 for (int i = 0; i < nvalues; i++) delete [] ids[i];
324 delete [] ids;
325
326 if (fp && me == 0) fclose(fp);
327
328 delete [] vector;
329 delete [] vector_total;
330 delete [] column;
331 memory->destroy(array);
332 memory->destroy(array_total);
333 memory->destroy(array_list);
334 }
335
336 /* ---------------------------------------------------------------------- */
337
setmask()338 int FixAveTime::setmask()
339 {
340 int mask = 0;
341 mask |= END_OF_STEP;
342 return mask;
343 }
344
345 /* ---------------------------------------------------------------------- */
346
init()347 void FixAveTime::init()
348 {
349 // set current indices for all computes,fixes,variables
350
351 for (int i = 0; i < nvalues; i++) {
352 if (which[i] == COMPUTE) {
353 int icompute = modify->find_compute(ids[i]);
354 if (icompute < 0)
355 error->all(FLERR,"Compute ID for fix ave/time does not exist");
356 value2index[i] = icompute;
357
358 } else if (which[i] == FIX) {
359 int ifix = modify->find_fix(ids[i]);
360 if (ifix < 0)
361 error->all(FLERR,"Fix ID for fix ave/time does not exist");
362 value2index[i] = ifix;
363
364 } else if (which[i] == VARIABLE) {
365 int ivariable = input->variable->find(ids[i]);
366 if (ivariable < 0)
367 error->all(FLERR,"Variable name for fix ave/time does not exist");
368 value2index[i] = ivariable;
369 }
370 }
371 }
372
373 /* ----------------------------------------------------------------------
374 only does something if nvalid = current timestep
375 ------------------------------------------------------------------------- */
376
setup()377 void FixAveTime::setup()
378 {
379 end_of_step();
380 }
381
382 /* ---------------------------------------------------------------------- */
383
end_of_step()384 void FixAveTime::end_of_step()
385 {
386 // skip if not step which requires doing something
387
388 bigint ntimestep = update->ntimestep;
389 if (ntimestep != nvalid) return;
390
391 if (mode == SCALAR) invoke_scalar(ntimestep);
392 else invoke_vector(ntimestep);
393 }
394
395 /* ---------------------------------------------------------------------- */
396
invoke_scalar(bigint ntimestep)397 void FixAveTime::invoke_scalar(bigint ntimestep)
398 {
399 int i,m;
400 double scalar;
401
402 // zero if first step
403
404 if (irepeat == 0)
405 for (i = 0; i < nvalues; i++) vector[i] = 0.0;
406
407 // accumulate results of computes,fixes,variables to local copy
408 // compute/fix/variable may invoke computes so wrap with clear/add
409
410 modify->clearstep_compute();
411
412 for (i = 0; i < nvalues; i++) {
413 m = value2index[i];
414
415 // invoke compute if not previously invoked
416
417 if (which[i] == COMPUTE) {
418 Compute *compute = modify->compute[m];
419
420 if (argindex[i] == 0) {
421 if (!(compute->invoked_flag & INVOKED_SCALAR)) {
422 compute->compute_scalar();
423 compute->invoked_flag |= INVOKED_SCALAR;
424 }
425 scalar = compute->scalar;
426 } else {
427 if (!(compute->invoked_flag & INVOKED_VECTOR)) {
428 compute->compute_vector();
429 compute->invoked_flag |= INVOKED_VECTOR;
430 }
431 scalar = compute->vector[argindex[i]-1];
432 }
433
434 // access fix fields, guaranteed to be ready
435
436 } else if (which[i] == FIX) {
437 if (argindex[i] == 0)
438 scalar = modify->fix[m]->compute_scalar();
439 else
440 scalar = modify->fix[m]->compute_vector(argindex[i]-1);
441
442 // evaluate equal-style variable
443
444 } else if (which[i] == VARIABLE)
445 scalar = input->variable->compute_equal(m);
446
447 // add value to vector or just set directly if offcol is set
448
449 if (offcol[i]) vector[i] = scalar;
450 else vector[i] += scalar;
451 }
452
453 // done if irepeat < nrepeat
454 // else reset irepeat and nvalid
455
456 irepeat++;
457 if (irepeat < nrepeat) {
458 nvalid += nevery;
459 modify->addstep_compute(nvalid);
460 return;
461 }
462
463 irepeat = 0;
464 nvalid = ntimestep + nfreq - (nrepeat-1)*nevery;
465 modify->addstep_compute(nvalid);
466
467 // average the final result for the Nfreq timestep
468 // no other normalization factor used
469
470 double repeat = nrepeat;
471 for (i = 0; i < nvalues; i++)
472 if (offcol[i] == 0) vector[i] /= repeat;
473
474 // if ave = ONE, only single Nfreq timestep value is needed
475 // if ave = RUNNING, combine with all previous Nfreq timestep values
476 // if ave = WINDOW, combine with nwindow most recent Nfreq timestep values
477
478 if (ave == ONE) {
479 for (i = 0; i < nvalues; i++) vector_total[i] = vector[i];
480 norm = 1;
481
482 } else if (ave == RUNNING) {
483 for (i = 0; i < nvalues; i++) vector_total[i] += vector[i];
484 norm++;
485
486 } else if (ave == WINDOW) {
487 for (i = 0; i < nvalues; i++) {
488 vector_total[i] += vector[i];
489 if (window_limit) vector_total[i] -= vector_list[iwindow][i];
490 vector_list[iwindow][i] = vector[i];
491 }
492
493 iwindow++;
494 if (iwindow == nwindow) {
495 iwindow = 0;
496 window_limit = 1;
497 }
498 if (window_limit) norm = nwindow;
499 else norm = iwindow;
500 }
501
502 // insure any columns with offcol set are effectively set to last value
503
504 for (i = 0; i < nvalues; i++)
505 if (offcol[i]) vector_total[i] = norm*vector[i];
506
507 // output result to file
508
509 if (fp && me == 0) {
510 fprintf(fp,BIGINT_FORMAT,ntimestep);
511 for (i = 0; i < nvalues; i++) fprintf(fp," %g",vector_total[i]/norm);
512 fprintf(fp,"\n");
513 fflush(fp);
514 }
515 }
516
517 /* ---------------------------------------------------------------------- */
518
invoke_vector(bigint ntimestep)519 void FixAveTime::invoke_vector(bigint ntimestep)
520 {
521 int i,j,m;
522
523 // zero if first step
524
525 if (irepeat == 0)
526 for (i = 0; i < nrows; i++)
527 for (j = 0; j < nvalues; j++) array[i][j] = 0.0;
528
529 // accumulate results of computes,fixes,variables to local copy
530 // compute/fix/variable may invoke computes so wrap with clear/add
531
532 modify->clearstep_compute();
533
534 for (j = 0; j < nvalues; j++) {
535 m = value2index[j];
536
537 // invoke compute if not previously invoked
538
539 if (which[j] == COMPUTE) {
540 Compute *compute = modify->compute[m];
541
542 if (argindex[j] == 0) {
543 if (!(compute->invoked_flag & INVOKED_VECTOR)) {
544 compute->compute_vector();
545 compute->invoked_flag |= INVOKED_VECTOR;
546 }
547 double *cvector = compute->vector;
548 for (i = 0; i < nrows; i++)
549 column[i] = cvector[i];
550
551 } else {
552 if (!(compute->invoked_flag & INVOKED_ARRAY)) {
553 compute->compute_array();
554 compute->invoked_flag |= INVOKED_ARRAY;
555 }
556 double **carray = compute->array;
557 int icol = argindex[j]-1;
558 for (i = 0; i < nrows; i++)
559 column[i] = carray[i][icol];
560 }
561
562 // access fix fields, guaranteed to be ready
563
564 } else if (which[j] == FIX) {
565 Fix *fix = modify->fix[m];
566 if (argindex[j] == 0)
567 for (i = 0; i < nrows; i++)
568 column[i] = fix->compute_vector(i);
569 else {
570 int icol = argindex[j]-1;
571 for (i = 0; i < nrows; i++)
572 column[i] = fix->compute_array(i,icol);
573 }
574 }
575
576 // add columns of values to array or just set directly if offcol is set
577
578 if (offcol[j])
579 for (i = 0; i < nrows; i++)
580 array[i][j] = column[i];
581 else
582 for (i = 0; i < nrows; i++)
583 array[i][j] += column[i];
584 }
585
586 // done if irepeat < nrepeat
587 // else reset irepeat and nvalid
588
589 irepeat++;
590 if (irepeat < nrepeat) {
591 nvalid += nevery;
592 modify->addstep_compute(nvalid);
593 return;
594 }
595
596 irepeat = 0;
597 nvalid = ntimestep + nfreq - (nrepeat-1)*nevery;
598 modify->addstep_compute(nvalid);
599
600 // average the final result for the Nfreq timestep
601
602 double repeat = nrepeat;
603
604 for (m = 0; m < nvalues; m++)
605 if (offcol[m] == 0)
606 for (i = 0; i < nrows; i++) array[i][m] /= repeat;
607
608 // if ave = ONE, only single Nfreq timestep value is needed
609 // if ave = RUNNING, combine with all previous Nfreq timestep values
610 // if ave = WINDOW, combine with nwindow most recent Nfreq timestep values
611
612 if (ave == ONE) {
613 for (i = 0; i < nrows; i++)
614 for (j = 0; j < nvalues; j++) array_total[i][j] = array[i][j];
615 norm = 1;
616
617 } else if (ave == RUNNING) {
618 for (i = 0; i < nrows; i++)
619 for (j = 0; j < nvalues; j++) array_total[i][j] += array[i][j];
620 norm++;
621
622 } else if (ave == WINDOW) {
623 for (i = 0; i < nrows; i++)
624 for (j = 0; j < nvalues; j++) {
625 array_total[i][j] += array[i][j];
626 if (window_limit) array_total[i][j] -= array_list[iwindow][i][j];
627 array_list[iwindow][i][j] = array[i][j];
628 }
629
630 iwindow++;
631 if (iwindow == nwindow) {
632 iwindow = 0;
633 window_limit = 1;
634 }
635 if (window_limit) norm = nwindow;
636 else norm = iwindow;
637 }
638
639 // insure any columns with offcol set are effectively set to last value
640
641 for (i = 0; i < nrows; i++)
642 for (j = 0; j < nvalues; j++)
643 if (offcol[j]) array_total[i][j] = norm*array[i][j];
644
645 // output result to file
646
647 if (fp && me == 0) {
648 fprintf(fp,BIGINT_FORMAT " %d\n",ntimestep,nrows);
649 for (i = 0; i < nrows; i++) {
650 fprintf(fp,"%d",i+1);
651 for (j = 0; j < nvalues; j++) fprintf(fp," %g",array_total[i][j]/norm);
652 fprintf(fp,"\n");
653 }
654 fflush(fp);
655 }
656 }
657
658 /* ----------------------------------------------------------------------
659 return scalar value
660 ------------------------------------------------------------------------- */
661
compute_scalar()662 double FixAveTime::compute_scalar()
663 {
664 if (norm) return vector_total[0]/norm;
665 return 0.0;
666 }
667
668 /* ----------------------------------------------------------------------
669 return Ith vector value
670 ------------------------------------------------------------------------- */
671
compute_vector(int i)672 double FixAveTime::compute_vector(int i)
673 {
674 if (norm) {
675 if (mode == SCALAR) return vector_total[i]/norm;
676 if (mode == VECTOR) return array_total[i][0];
677 }
678 return 0.0;
679 }
680
681 /* ----------------------------------------------------------------------
682 return I,J array value
683 ------------------------------------------------------------------------- */
684
compute_array(int i,int j)685 double FixAveTime::compute_array(int i, int j)
686 {
687 if (norm) return array_total[i][j]/norm;
688 return 0.0;
689 }
690
691 /* ----------------------------------------------------------------------
692 parse optional args
693 ------------------------------------------------------------------------- */
694
options(int iarg,int narg,char ** arg)695 void FixAveTime::options(int iarg, int narg, char **arg)
696 {
697 // option defaults
698
699 fp = NULL;
700 ave = ONE;
701 startstep = 0;
702 mode = SCALAR;
703 noff = 0;
704 offlist = NULL;
705 title1 = NULL;
706 title2 = NULL;
707 title3 = NULL;
708
709 // optional args
710
711 while (iarg < narg) {
712 if (strcmp(arg[iarg],"file") == 0) {
713 if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command");
714 if (me == 0) {
715 fp = fopen(arg[iarg+1],"w");
716 if (fp == NULL) {
717 char str[128];
718 sprintf(str,"Cannot open fix ave/time file %s",arg[iarg+1]);
719 error->one(FLERR,str);
720 }
721 }
722 iarg += 2;
723 } else if (strcmp(arg[iarg],"ave") == 0) {
724 if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command");
725 if (strcmp(arg[iarg+1],"one") == 0) ave = ONE;
726 else if (strcmp(arg[iarg+1],"running") == 0) ave = RUNNING;
727 else if (strcmp(arg[iarg+1],"window") == 0) ave = WINDOW;
728 else error->all(FLERR,"Illegal fix ave/time command");
729 if (ave == WINDOW) {
730 if (iarg+3 > narg) error->all(FLERR,"Illegal fix ave/time command");
731 nwindow = atoi(arg[iarg+2]);
732 if (nwindow <= 0) error->all(FLERR,"Illegal fix ave/time command");
733 }
734 iarg += 2;
735 if (ave == WINDOW) iarg++;
736 } else if (strcmp(arg[iarg],"start") == 0) {
737 if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command");
738 startstep = atoi(arg[iarg+1]);
739 iarg += 2;
740 } else if (strcmp(arg[iarg],"mode") == 0) {
741 if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command");
742 if (strcmp(arg[iarg+1],"scalar") == 0) mode = SCALAR;
743 else if (strcmp(arg[iarg+1],"vector") == 0) mode = VECTOR;
744 else error->all(FLERR,"Illegal fix ave/time command");
745 iarg += 2;
746 } else if (strcmp(arg[iarg],"off") == 0) {
747 if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/time command");
748 memory->grow(offlist,noff+1,"ave/time:offlist");
749 offlist[noff++] = atoi(arg[iarg+1]);
750 iarg += 2;
751 } else if (strcmp(arg[iarg],"title1") == 0) {
752 if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
753 delete [] title1;
754 int n = strlen(arg[iarg+1]) + 1;
755 title1 = new char[n];
756 strcpy(title1,arg[iarg+1]);
757 iarg += 2;
758 } else if (strcmp(arg[iarg],"title2") == 0) {
759 if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
760 delete [] title2;
761 int n = strlen(arg[iarg+1]) + 1;
762 title2 = new char[n];
763 strcpy(title2,arg[iarg+1]);
764 iarg += 2;
765 } else if (strcmp(arg[iarg],"title3") == 0) {
766 if (iarg+2 > narg) error->all(FLERR,"Illegal fix ave/spatial command");
767 delete [] title3;
768 int n = strlen(arg[iarg+1]) + 1;
769 title3 = new char[n];
770 strcpy(title3,arg[iarg+1]);
771 iarg += 2;
772 } else error->all(FLERR,"Illegal fix ave/time command");
773 }
774 }
775
776 /* ----------------------------------------------------------------------
777 reallocate vectors for each input value, of length N
778 ------------------------------------------------------------------------- */
779
grow()780 void FixAveTime::grow()
781 {
782 maxvalues += DELTA;
783 memory->grow(which,maxvalues,"ave/time:which");
784 memory->grow(argindex,maxvalues,"ave/time:argindex");
785 memory->grow(value2index,maxvalues,"ave/time:value2index");
786 memory->grow(offcol,maxvalues,"ave/time:offcol");
787 ids = (char **) memory->srealloc(ids,maxvalues*sizeof(char *),"ave/time:ids");
788 }
789
790 /* ----------------------------------------------------------------------
791 calculate nvalid = next step on which end_of_step does something
792 can be this timestep if multiple of nfreq and nrepeat = 1
793 else backup from next multiple of nfreq
794 startstep is lower bound on nfreq multiple
795 ------------------------------------------------------------------------- */
796
nextvalid()797 bigint FixAveTime::nextvalid()
798 {
799 bigint nvalid = (update->ntimestep/nfreq)*nfreq + nfreq;
800 while (nvalid < startstep) nvalid += nfreq;
801 if (nvalid-nfreq == update->ntimestep && nrepeat == 1)
802 nvalid = update->ntimestep;
803 else
804 nvalid -= (nrepeat-1)*nevery;
805 if (nvalid < update->ntimestep) nvalid += nfreq;
806 return nvalid;
807 }
808