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 /* ----------------------------------------------------------------------
16    Contributing author: Tim Fuller (Sandia)
17 ------------------------------------------------------------------------- */
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include "sparta_masks.h"
23 #include "kokkos_base.h"
24 #include "fix_ave_histo_kokkos.h"
25 #include "particle_kokkos.h"
26 #include "update.h"
27 #include "particle.h"
28 #include "mixture.h"
29 #include "grid.h"
30 #include "grid_kokkos.h"
31 #include "domain.h"
32 #include "region.h"
33 #include "modify.h"
34 #include "compute.h"
35 #include "input.h"
36 #include "variable.h"
37 #include "memory.h"
38 #include "memory_kokkos.h"
39 #include "error.h"
40 
41 using namespace SPARTA_NS;
42 
43 enum{X,V,F,COMPUTE,FIX,VARIABLE};
44 enum{ONE,RUNNING};
45 enum{SCALAR,VECTOR,WINDOW};
46 enum{GLOBAL,PERPARTICLE,PERGRID};
47 enum{IGNORE,END,EXTRA};
48 
49 #define INVOKED_SCALAR 1
50 #define INVOKED_VECTOR 2
51 #define INVOKED_ARRAY 4
52 #define INVOKED_PER_PARTICLE 8
53 #define INVOKED_PER_GRID 16
54 
55 /* ---------------------------------------------------------------------- */
56 
FixAveHistoKokkos(SPARTA * spa,int narg,char ** arg)57 FixAveHistoKokkos::FixAveHistoKokkos(SPARTA *spa, int narg, char **arg) :
58   FixAveHisto(spa, narg, arg)
59 {
60   kokkos_flag = 1;
61   execution_space = Device;
62 
63   k_stats.resize(4);
64   d_stats = k_stats.d_view;
65 
66   memory->destroy(bin);
67   bin = NULL;
68   memoryKK->grow_kokkos(k_bin, bin, nbins, "ave/histo:bin");
69   d_bin = k_bin.d_view;
70 
71 }
72 
73 /* ---------------------------------------------------------------------- */
74 
~FixAveHistoKokkos()75 FixAveHistoKokkos::~FixAveHistoKokkos()
76 {
77   if (copymode) return;
78 
79   k_stats = DAT::tdual_float_1d();
80   memoryKK->destroy_kokkos(k_bin, bin);
81 }
82 
83 /* ---------------------------------------------------------------------- */
84 
init()85 void FixAveHistoKokkos::init()
86 {
87   // set current indices for all computes,fixes,variables
88 
89   for (int i = 0; i < nvalues; i++) {
90     if (which[i] == COMPUTE) {
91       int icompute = modify->find_compute(ids[i]);
92       if (icompute < 0)
93         error->all(FLERR,"Compute ID for fix ave/histo/kk does not exist");
94       value2index[i] = icompute;
95 
96     } else if (which[i] == FIX) {
97       int ifix = modify->find_fix(ids[i]);
98       if (ifix < 0)
99         error->all(FLERR,"Fix ID for fix ave/histo/kk does not exist");
100       value2index[i] = ifix;
101 
102     } else if (which[i] == VARIABLE) {
103       int ivariable = input->variable->find(ids[i]);
104       if (ivariable < 0)
105         error->all(FLERR,"Variable name for fix ave/histo/kk does not exist");
106       value2index[i] = ivariable;
107     }
108   }
109 }
110 
111 /* ----------------------------------------------------------------------
112    only does something if nvalid = current timestep
113 ------------------------------------------------------------------------- */
114 
setup()115 void FixAveHistoKokkos::setup()
116 {
117   end_of_step();
118 }
119 
120 /* ---------------------------------------------------------------------- */
121 
end_of_step()122 void FixAveHistoKokkos::end_of_step()
123 {
124 
125   using FixKokkosDetails::mirror_view_from_raw_host_array;
126 
127   int j,m;
128 
129   // skip if not step which requires doing something
130 
131   bigint ntimestep = update->ntimestep;
132   if (ntimestep != nvalid) {
133     return;
134   }
135 
136   ParticleKokkos* particle_kk = (ParticleKokkos*) particle;
137   particle_kk->sync(Device, PARTICLE_MASK|SPECIES_MASK);
138   d_particles = particle_kk->k_particles.d_view;
139 
140   d_s2g = particle_kk->k_species2group.d_view;
141 
142   copymode = 1;
143 
144   // zero if first step
145   if (irepeat == 0) {
146     for (int i=0; i<4; i++) k_stats.h_view(i) = 0.0;
147     k_stats.modify_host();
148     k_stats.sync_device();
149 
150     for (int i=0; i<nbins; i++) k_bin.h_view(i) = 0.0;
151     k_bin.modify_host();
152     k_bin.sync_device();
153   }
154 
155   minmax_type::value_type minmax;
156   minmax_type reducer(minmax);
157 
158   // accumulate results of computes,fixes,variables to local copy
159   // compute/fix/variable may invoke computes so wrap with clear/add
160 
161   modify->clearstep_compute();
162 
163   // for fix ave/histo/weight, nvalues will be 2
164   // first calculate weight factors, then histogram single value
165 
166   int ncount = nvalues;
167   if (weightflag) {
168     calculate_weights();
169     ncount = 1;
170   }
171 
172   for (int i = 0; i < ncount; i++) {
173     m = value2index[i];
174     j = argindex[i];
175 
176     // invoke compute if not previously invoked
177 
178     if (which[i] == COMPUTE) {
179       Compute *compute = modify->compute[m];
180       if (!compute->kokkos_flag)
181         error->all(FLERR,"Cannot (yet) use non-Kokkos computes with fix ave/histo/kk");
182       KokkosBase* computeKKBase = dynamic_cast<KokkosBase*>(compute);
183 
184       if (kind == GLOBAL && mode == SCALAR) {
185         if (j == 0) {
186           if (!(compute->invoked_flag & INVOKED_SCALAR)) {
187             compute->compute_scalar();
188             compute->invoked_flag |= INVOKED_SCALAR;
189           }
190           bin_scalar(minmax, compute->scalar);
191         }
192         else {
193           error->all(FLERR,"Compute kind not compatible with fix ave/histo/kk");
194           if (!(compute->invoked_flag & INVOKED_VECTOR)) {
195             compute->compute_vector();
196             compute->invoked_flag |= INVOKED_VECTOR;
197           }
198           bin_scalar(minmax, compute->vector[j-1]);
199         }
200       } else if (kind == GLOBAL && mode == VECTOR) {
201           error->all(FLERR,"Compute kind not compatible with fix ave/histo/kk");
202         if (j == 0) {
203           if (!(compute->invoked_flag & INVOKED_VECTOR)) {
204             compute->compute_vector();
205             compute->invoked_flag |= INVOKED_VECTOR;
206           }
207           bin_vector(reducer, compute->size_vector,compute->vector,1);
208         } else {
209           if (!(compute->invoked_flag & INVOKED_ARRAY)) {
210             compute->compute_array();
211             compute->invoked_flag |= INVOKED_ARRAY;
212           }
213           if (compute->array)
214             bin_vector(reducer, compute->size_array_rows,&compute->array[0][j-1],
215                        compute->size_array_cols);
216         }
217       } else if (kind == PERPARTICLE) {
218           error->all(FLERR,"Compute kind not compatible with fix ave/histo/kk");
219         if (!(compute->invoked_flag & INVOKED_PER_PARTICLE)) {
220           compute->compute_per_particle();
221           compute->invoked_flag |= INVOKED_PER_PARTICLE;
222         }
223         if (j == 0)
224           bin_particles(reducer, compute->vector_particle,1);
225         else if (compute->array_particle)
226           bin_particles(reducer, &compute->array_particle[0][j-1],
227                         compute->size_per_particle_cols);
228       } else if (kind == PERGRID) {
229         if (!(compute->invoked_flag & INVOKED_PER_GRID)) {
230           computeKKBase->compute_per_grid_kokkos();
231           compute->invoked_flag |= INVOKED_PER_GRID;
232         }
233 
234         if (compute->post_process_grid_flag) {
235           DAT::t_float_2d_lr d_etally;
236           DAT::t_float_1d_strided d_vec;
237           computeKKBase->post_process_grid_kokkos(j,1,d_etally,NULL,d_vec);
238         }
239         else if (compute->post_process_isurf_grid_flag)
240           compute->post_process_isurf_grid();
241 
242         if (j == 0 || compute->post_process_grid_flag)
243           bin_grid_cells(reducer, computeKKBase->d_vector);
244         else if (computeKKBase->d_array_grid.data())
245           // @stamoor: fix_ave_histo.cpp passes compute->array_grid[0][j-1],
246           // @stamoor: so send subview of d_array_grid.
247           bin_grid_cells(reducer,
248                          Kokkos::subview(computeKKBase->d_array_grid,Kokkos::ALL(),j-1));
249       }
250 
251     // access fix fields, guaranteed to be ready
252 
253     } else if (which[i] == FIX) {
254 
255       Fix *fix = modify->fix[m];
256       if (!fix->kokkos_flag)
257         error->all(FLERR,"Cannot (yet) use non-Kokkos fixes with fix ave/histo/kk");
258       KokkosBase* fixKKBase = dynamic_cast<KokkosBase*>(fix);
259 
260       if (kind == GLOBAL && mode == SCALAR) {
261         if (j == 0) {
262           bin_scalar(minmax, fix->compute_scalar());
263         }
264         else {
265           error->all(FLERR,"Fix not compatible with fix ave/histo/kk");
266           bin_scalar(minmax, fix->compute_vector(j-1));
267         }
268       } else if (kind == GLOBAL && mode == VECTOR) {
269         error->all(FLERR,"Fix not compatible with fix ave/histo/kk");
270         if (j == 0) {
271           int n = fix->size_vector;
272           for (i = 0; i < n; i++) bin_scalar(minmax, fix->compute_vector(i));
273         } else {
274           int n = fix->size_vector;
275           for (i = 0; i < n; i++) bin_scalar(minmax, fix->compute_array(i,j-1));
276         }
277 
278       } else if (kind == PERPARTICLE) {
279         error->all(FLERR,"Fix not compatible with fix ave/histo/kk");
280         if (j == 0) bin_particles(reducer, fix->vector_particle,1);
281         else if (fix->array_particle)
282           bin_particles(reducer, fix->array_particle[j-1],fix->size_per_particle_cols);
283       } else if (kind == PERGRID) {
284         if (j == 0) {
285           bin_grid_cells(reducer, fixKKBase->d_vector);
286         } else if (fixKKBase->d_array_grid.data()) {
287           // @stamoor: fix_ave_histo.cpp passes fix->array_grid[j-1], which is
288           // not the same as what happens above with the compute object, it is
289           // also inconsistent with fix_ave_histo_weight which uses
290           // fix->array_grid[0][j-1] too.  Is this a type in fix_ave_histo?
291           bin_grid_cells(reducer,
292                          Kokkos::subview(fixKKBase->d_array_grid,Kokkos::ALL(),j-1));
293         }
294       }
295 
296     // evaluate equal-style or particle-style or grid-style variable
297     } else if (which[i] == VARIABLE) {
298       error->all(FLERR,"Cannot (yet) use variables with fix ave/histo/kk");
299       if (kind == GLOBAL && mode == SCALAR) {
300         bin_scalar(minmax, input->variable->compute_equal(m));
301 
302       } else if (which[i] == VARIABLE && kind == PERPARTICLE) {
303         if (particle->maxlocal > maxvector) {
304           memory->destroy(vector);
305           maxvector = particle->maxlocal;
306           memory->create(vector,maxvector,"ave/histo:vector");
307         }
308         input->variable->compute_particle(m,vector,1,0);
309         bin_particles(reducer, vector,1);
310 
311       } else if (which[i] == VARIABLE && kind == PERGRID) {
312         if (grid->maxlocal > maxvector) {
313           memory->destroy(vector);
314           maxvector = grid->maxlocal;
315           memory->create(vector,maxvector,"ave/histo:vector");
316         }
317         input->variable->compute_grid(m,vector,1,0);
318         //bin_grid_cells(reducer, vector);
319       }
320     } else {
321       // explicit per-particle attributes
322       bin_particles(reducer, which[i], j);
323     }
324   }
325 
326   k_stats.modify_device();
327   k_stats.sync_host();
328 
329   k_bin.modify_device();
330   k_bin.sync_host();
331 
332   // Copy data back
333   stats[0] = k_stats.h_view(0);
334   stats[1] = k_stats.h_view(1);
335   stats[2] = minmax.min_val;
336   stats[3] = minmax.max_val;
337 
338   // done if irepeat < nrepeat
339   // else reset irepeat and nvalid
340 
341   irepeat++;
342   if (irepeat < nrepeat) {
343     nvalid += nevery;
344     modify->addstep_compute(nvalid);
345     copymode = 0;
346     return;
347   }
348 
349   irepeat = 0;
350   nvalid = ntimestep + nfreq - (nrepeat-1)*nevery;
351   modify->addstep_compute(nvalid);
352 
353   // merge histogram stats across procs if necessary
354   if (kind == PERPARTICLE || kind == PERGRID) {
355     MPI_Allreduce(stats,stats_all,2,MPI_DOUBLE,MPI_SUM,world);
356     MPI_Allreduce(&stats[2],&stats_all[2],1,MPI_DOUBLE,MPI_MIN,world);
357     MPI_Allreduce(&stats[3],&stats_all[3],1,MPI_DOUBLE,MPI_MAX,world);
358     MPI_Allreduce(bin,bin_all,nbins,MPI_DOUBLE,MPI_SUM,world);
359 
360     stats[0] = stats_all[0];
361     stats[1] = stats_all[1];
362     stats[2] = stats_all[2];
363     stats[3] = stats_all[3];
364     for (int i = 0; i < nbins; i++) bin[i] = bin_all[i];
365   }
366 
367   // if ave = ONE, only single Nfreq timestep value is needed
368   // if ave = RUNNING, combine with all previous Nfreq timestep values
369   // if ave = WINDOW, combine with nwindow most recent Nfreq timestep values
370 
371   if (ave == ONE) {
372     stats_total[0] = stats[0];
373     stats_total[1] = stats[1];
374     stats_total[2] = stats[2];
375     stats_total[3] = stats[3];
376     for (int i = 0; i < nbins; i++) bin_total[i] = bin[i];
377 
378   } else if (ave == RUNNING) {
379     stats_total[0] += stats[0];
380     stats_total[1] += stats[1];
381     stats_total[2] = MIN(stats_total[2],stats[2]);
382     stats_total[3] = MAX(stats_total[3],stats[3]);
383     for (int i = 0; i < nbins; i++) bin_total[i] += bin[i];
384 
385   } else if (ave == WINDOW) {
386     stats_total[0] += stats[0];
387     if (window_limit) stats_total[0] -= stats_list[iwindow][0];
388     stats_list[iwindow][0] = stats[0];
389     stats_total[1] += stats[1];
390     if (window_limit) stats_total[1] -= stats_list[iwindow][1];
391     stats_list[iwindow][1] = stats[1];
392 
393     if (window_limit) m = nwindow;
394     else m = iwindow+1;
395 
396     stats_list[iwindow][2] = stats[2];
397     stats_total[2] = stats_list[0][2];
398     for (int i = 1; i < m; i++)
399       stats_total[2] = MIN(stats_total[2],stats_list[i][2]);
400     stats_list[iwindow][3] = stats[3];
401     stats_total[3] = stats_list[0][3];
402     for (int i = 1; i < m; i++)
403       stats_total[3] = MAX(stats_total[3],stats_list[i][3]);
404 
405     for (int i = 0; i < nbins; i++) {
406       bin_total[i] += bin[i];
407       if (window_limit) bin_total[i] -= bin_list[iwindow][i];
408       bin_list[iwindow][i] = bin[i];
409     }
410 
411     iwindow++;
412     if (iwindow == nwindow) {
413       iwindow = 0;
414       window_limit = 1;
415     }
416   }
417 
418   // output result to file
419 
420   if (fp && me == 0) {
421     clearerr(fp);
422     if (overwrite) fseek(fp,filepos,SEEK_SET);
423     fprintf(fp,BIGINT_FORMAT " %d %g %g %g %g\n",ntimestep,nbins,
424             stats_total[0],stats_total[1],stats_total[2],stats_total[3]);
425     if (stats_total[0] != 0.0) {
426       for (int i = 0; i < nbins; i++) {
427         fprintf(fp,"%d %g %g %g\n",
428                 i+1,coord[i],bin_total[i],bin_total[i]/stats_total[0]);
429       }
430     } else {
431       for (int i = 0; i < nbins; i++)
432         fprintf(fp,"%d %g %g %g\n",i+1,coord[i],0.0,0.0);
433     }
434 
435     if (ferror(fp)) {
436       error->one(FLERR,"Error writing out histogram data");
437     }
438 
439     fflush(fp);
440     if (overwrite) {
441       long fileend = ftell(fp);
442       if (fileend > 0) ftruncate(fileno(fp),fileend);
443     }
444   }
445   copymode = 0;
446 }
447 
448 /* ----------------------------------------------------------------------
449    return Ith vector value
450 ------------------------------------------------------------------------- */
451 
compute_vector(int i)452 double FixAveHistoKokkos::compute_vector(int i)
453 {
454   return stats_total[i];
455 }
456 
457 /* ----------------------------------------------------------------------
458    return I,J array value
459 ------------------------------------------------------------------------- */
460 
compute_array(int i,int j)461 double FixAveHistoKokkos::compute_array(int i, int j)
462 {
463   if (j == 0) return coord[i];
464   else if (j == 1) return bin_total[i];
465   else if (stats_total[0] != 0.0) return bin_total[i]/stats_total[0];
466   return 0.0;
467 }
468 
469 /* ----------------------------------------------------------------------
470    bin a Scalar
471 ------------------------------------------------------------------------- */
bin_scalar(minmax_type::value_type & minmax,double val)472 void FixAveHistoKokkos::bin_scalar(minmax_type::value_type& minmax, double val)
473 {
474   bin_one(minmax, val);
475 }
476 
477 /* ----------------------------------------------------------------------
478    bin a vector of values with stride
479 ------------------------------------------------------------------------- */
bin_vector(minmax_type & reducer,int n,double * values,int stride)480 void FixAveHistoKokkos::bin_vector(
481     minmax_type& reducer,
482     int n, double *values, int stride)
483 {
484   using FixKokkosDetails::mirror_view_from_raw_host_array;
485   this->stride = stride;
486 
487   d_values = mirror_view_from_raw_host_array<double,DeviceType>(values, n, stride);
488 
489   auto policy = Kokkos::RangePolicy<TagFixAveHisto_BinVector,DeviceType>(0, n);
490   Kokkos::parallel_reduce(policy, *this, reducer);
491   DeviceType().fence();
492 }
493 
494 /* ----------------------------------------------------------------------
495    bin a per-particle attribute
496    index is 0,1,2 if attribute is X or V
497 ------------------------------------------------------------------------- */
bin_particles(minmax_type & reducer,int attribute,int index)498 void FixAveHistoKokkos::bin_particles(
499     minmax_type& reducer,
500     int attribute, int index)
501 {
502   using Kokkos::RangePolicy;
503 
504   this->index = index;
505   int n = particle->nlocal;
506 
507   // FIXME: Kokkos version of region
508   //Region *region;
509   //if (regionflag) region = domain->regions[iregion];
510 
511   if (regionflag)
512     error->all(FLERR,"Cannot (yet) use regionflag with fix ave/histo/kk");
513 
514   if (attribute == X) {
515 
516     if (regionflag && mixflag) {
517       //auto policy = RangePolicy<TagFixAveHisto_BinParticlesX1,DeviceType>(0, n);
518       //Kokkos::parallel_reduce(policy, *this, reducer);
519     } else if (regionflag) {
520       //auto policy = RangePolicy<TagFixAveHisto_BinParticlesX2,DeviceType>(0, n);
521       //Kokkos::parallel_reduce(policy, *this, reducer);
522     } else if (mixflag) {
523       auto policy = RangePolicy<TagFixAveHisto_BinParticlesX3,DeviceType>(0, n);
524       Kokkos::parallel_reduce(policy, *this, reducer);
525     } else {
526       auto policy = RangePolicy<TagFixAveHisto_BinParticlesX4,DeviceType>(0, n);
527       Kokkos::parallel_reduce(policy, *this, reducer);
528     }
529     DeviceType().fence();
530 
531   } else if (attribute == V) {
532 
533     if (regionflag && mixflag) {
534       //auto policy = RangePolicy<TagFixAveHisto_BinParticlesV1,DeviceType>(0, n);
535       //Kokkos::parallel_reduce(policy, *this, reducer);
536     } else if (regionflag) {
537       //auto policy = RangePolicy<TagFixAveHisto_BinParticlesV2,DeviceType>(0, n);
538       //Kokkos::parallel_reduce(policy, *this, reducer);
539     } else if (mixflag) {
540       auto policy = RangePolicy<TagFixAveHisto_BinParticlesV3,DeviceType>(0, n);
541       Kokkos::parallel_reduce(policy, *this, reducer);
542     } else {
543       auto policy = RangePolicy<TagFixAveHisto_BinParticlesV4,DeviceType>(0, n);
544       Kokkos::parallel_reduce(policy, *this, reducer);
545     }
546     DeviceType().fence();
547   }
548 }
549 
550 /* ----------------------------------------------------------------------
551    bin a per-particle vector of values with stride
552 ------------------------------------------------------------------------- */
bin_particles(minmax_type & reducer,double * values,int stride)553 void FixAveHistoKokkos::bin_particles(
554     minmax_type& reducer,
555     double *values, int stride)
556 {
557   using Kokkos::RangePolicy;
558   using FixKokkosDetails::mirror_view_from_raw_host_array;
559 
560   this->stride = stride;
561   int n = particle->nlocal;
562 
563   d_values = mirror_view_from_raw_host_array<double,DeviceType>(values, n, stride);
564 
565   // FIXME: Kokkos version of region
566   // FIXME: Does values need to be made a view that lives on Device?
567   //Region *region;
568   //if (regionflag) region = domain->regions[iregion];
569 
570   if (regionflag)
571     error->all(FLERR,"Cannot (yet) use regionflag with fix ave/histo/kk");
572 
573   if (regionflag && mixflag) {
574     //auto policy = RangePolicy<TagFixAveHisto_BinParticles1,DeviceType>(0, n);
575     //Kokkos::parallel_reduce(policy, *this, reducer);
576   } else if (regionflag) {
577     //auto policy = RangePolicy<TagFixAveHisto_BinParticles2,DeviceType>(0, n);
578     //Kokkos::parallel_reduce(policy, *this, reducer);
579   } else if (mixflag) {
580     auto policy = RangePolicy<TagFixAveHisto_BinParticles3,DeviceType>(0, n);
581     Kokkos::parallel_reduce(policy, *this, reducer);
582   } else {
583     auto policy = RangePolicy<TagFixAveHisto_BinParticles4,DeviceType>(0, n);
584     Kokkos::parallel_reduce(policy, *this, reducer);
585   }
586   DeviceType().fence();
587 }
588 
589 /* ----------------------------------------------------------------------
590    bin a per-grid vector of values with stride
591 ------------------------------------------------------------------------- */
bin_grid_cells(minmax_type & reducer,DAT::t_float_1d_strided d_vec)592 void FixAveHistoKokkos::bin_grid_cells(
593     minmax_type& reducer,
594     DAT::t_float_1d_strided d_vec)
595 {
596   using Kokkos::RangePolicy;
597   using FixKokkosDetails::mirror_view_from_raw_host_array;
598 
599   int n = grid->nlocal;
600   d_values = d_vec;
601 
602   if (groupflag) {
603     GridKokkos* grid_kk = (GridKokkos*) grid;
604     grid_kk->sync(Device, CINFO_MASK);
605     auto policy = RangePolicy<TagFixAveHisto_BinGridCells1,DeviceType>(0, n);
606     Kokkos::parallel_reduce(policy, *this, reducer);
607   } else {
608     auto policy = RangePolicy<TagFixAveHisto_BinGridCells2,DeviceType>(0, n);
609     Kokkos::parallel_reduce(policy, *this, reducer);
610   }
611   DeviceType().fence();
612 }
613 
614 
615 /* ----------------------------------------------------------------------
616    calculate nvalid = next step on which end_of_step does something
617    can be this timestep if multiple of nfreq and nrepeat = 1
618    else backup from next multiple of nfreq
619    startstep is lower bound on nfreq multiple
620 ------------------------------------------------------------------------- */
621 
nextvalid()622 bigint FixAveHistoKokkos::nextvalid()
623 {
624   bigint nvalid = (update->ntimestep/nfreq)*nfreq + nfreq;
625   while (nvalid < startstep) nvalid += nfreq;
626   if (nvalid-nfreq == update->ntimestep && nrepeat == 1)
627     nvalid = update->ntimestep;
628   else
629     nvalid -= (nrepeat-1)*nevery;
630   if (nvalid < update->ntimestep) nvalid += nfreq;
631   return nvalid;
632 }
633 
634 /* ------------------------------------------------------------------------- */
635 KOKKOS_INLINE_FUNCTION
636 void
operator ()(TagFixAveHisto_BinVector,const int i,minmax_type::value_type & lminmax) const637 FixAveHistoKokkos::operator()(TagFixAveHisto_BinVector, const int i,
638                               minmax_type::value_type& lminmax) const
639 {
640   bin_one(lminmax, d_values(i));
641 }
642 
643 /* ------------------------------------------------------------------------- */
644 KOKKOS_INLINE_FUNCTION
645 void
operator ()(TagFixAveHisto_BinParticles1,const int i,minmax_type::value_type & lminmax) const646 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticles1, const int i,
647                               minmax_type::value_type& lminmax) const
648 {
649   /*
650    * region is not Kokkos compatible
651    * If a Kokkos compatible region becomes available,
652    * this code can be recommissioned.
653    *
654   const int ispecies = d_particles(i).ispecies;
655   if (region_kk->match(d_particles(i).x) && d_s2g(imix, ispecies) >= 0)
656   {
657     bin_one(lminmax, d_values(i));
658   }
659   */
660 }
661 
662 /* ------------------------------------------------------------------------- */
663 KOKKOS_INLINE_FUNCTION
664 void
operator ()(TagFixAveHisto_BinParticles2,const int i,minmax_type::value_type & lminmax) const665 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticles2, const int i,
666                               minmax_type::value_type& lminmax) const
667 {
668   /*
669    * region is not Kokkos compatible.
670    * If a Kokkos compatible region becomes available,
671    * this code can be recommissioned.
672    *
673   if (region_kk->match(d_particles(i).x))
674   {
675     bin_one(lminmax, d_values(i));
676   }
677   */
678 }
679 
680 /* ------------------------------------------------------------------------- */
681 KOKKOS_INLINE_FUNCTION
682 void
operator ()(TagFixAveHisto_BinParticles3,const int i,minmax_type::value_type & lminmax) const683 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticles3, const int i,
684                               minmax_type::value_type& lminmax) const
685 {
686   const int ispecies = d_particles(i).ispecies;
687   if (d_s2g(imix, ispecies) < 0)
688   {
689     bin_one(lminmax, d_values(i));
690   }
691 }
692 
693 /* ------------------------------------------------------------------------- */
694 KOKKOS_INLINE_FUNCTION
695 void
operator ()(TagFixAveHisto_BinParticles4,const int i,minmax_type::value_type & lminmax) const696 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticles4, const int i,
697                               minmax_type::value_type& lminmax) const
698 {
699   bin_one(lminmax, d_values(i));
700 }
701 
702 /* ------------------------------------------------------------------------- */
703 KOKKOS_INLINE_FUNCTION
704 void
operator ()(TagFixAveHisto_BinGridCells1,const int i,minmax_type::value_type & lminmax) const705 FixAveHistoKokkos::operator()(TagFixAveHisto_BinGridCells1, const int i,
706                               minmax_type::value_type& lminmax) const
707 {
708   if (grid_kk->k_cinfo.d_view[i].mask & groupbit)
709   {
710     bin_one(lminmax, d_values(i));
711   }
712 }
713 
714 /* ------------------------------------------------------------------------- */
715 KOKKOS_INLINE_FUNCTION
716 void
operator ()(TagFixAveHisto_BinGridCells2,const int i,minmax_type::value_type & lminmax) const717 FixAveHistoKokkos::operator()(TagFixAveHisto_BinGridCells2, const int i,
718                               minmax_type::value_type& lminmax) const
719 {
720   bin_one(lminmax, d_values(i));
721 }
722 
723 /* ------------------------------------------------------------------------- */
724 KOKKOS_INLINE_FUNCTION
725 void
operator ()(TagFixAveHisto_BinParticlesX1,const int i,minmax_type::value_type & lminmax) const726 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticlesX1, const int i,
727                               minmax_type::value_type& lminmax) const
728 {
729   /*
730    * region is not Kokkos compatible
731    * If a Kokkos compatible region becomes available,
732    * this code can be recommissioned.
733    *
734   const int ispecies = d_particles(i).ispecies;
735   if (region_kk->match(d_particles(i).x) && d_s2g(imix, ispecies) < 0)
736   {
737     bin_one(lminmax, d_particles(i).x[index]);
738   }
739   */
740 }
741 
742 /* ------------------------------------------------------------------------- */
743 KOKKOS_INLINE_FUNCTION
744 void
operator ()(TagFixAveHisto_BinParticlesX2,const int i,minmax_type::value_type & lminmax) const745 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticlesX2, const int i,
746                               minmax_type::value_type& lminmax) const
747 {
748   /*
749    * region is not Kokkos compatible
750    * If a Kokkos compatible region becomes available,
751    * this code can be recommissioned.
752    *
753   if (region_kk->match(d_particles(i).x))
754   {
755     bin_one(lminmax, d_particles(i).x[index]);
756   }
757   */
758 }
759 
760 /* ------------------------------------------------------------------------- */
761 KOKKOS_INLINE_FUNCTION
762 void
operator ()(TagFixAveHisto_BinParticlesX3,const int i,minmax_type::value_type & lminmax) const763 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticlesX3, const int i,
764                               minmax_type::value_type& lminmax) const
765 {
766   const int ispecies = d_particles(i).ispecies;
767   if (d_s2g(imix, ispecies) >= 0)
768   {
769     bin_one(lminmax, d_particles(i).x[index]);
770   }
771 }
772 
773 /* ------------------------------------------------------------------------- */
774 KOKKOS_INLINE_FUNCTION
775 void
operator ()(TagFixAveHisto_BinParticlesX4,const int i,minmax_type::value_type & lminmax) const776 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticlesX4, const int i,
777                               minmax_type::value_type& lminmax) const
778 {
779   bin_one(lminmax, d_particles(i).x[index]);
780 }
781 
782 /* ------------------------------------------------------------------------- */
783 KOKKOS_INLINE_FUNCTION
784 void
operator ()(TagFixAveHisto_BinParticlesV1,const int i,minmax_type::value_type & lminmax) const785 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticlesV1, const int i,
786                               minmax_type::value_type& lminmax) const
787 {
788   /*
789    * region is not Kokkos compatible
790    * If a Kokkos compatible region becomes available,
791    * this code can be recommissioned.
792    *
793   const int ispecies = d_particles(i).ispecies;
794   if (region_kk->match(d_particles(i).x) && d_s2g(imix, ispecies) < 0)
795   {
796     bin_one(lminmax, d_particles(i).v[index]);
797   }
798   */
799 }
800 
801 /* ------------------------------------------------------------------------- */
802 KOKKOS_INLINE_FUNCTION
803 void
operator ()(TagFixAveHisto_BinParticlesV2,const int i,minmax_type::value_type & lminmax) const804 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticlesV2, const int i,
805                               minmax_type::value_type& lminmax) const
806 {
807   /*
808    * region is not Kokkos compatible
809    * If a Kokkos compatible region becomes available,
810    * this code can be recommissioned.
811    *
812   if (region_kk->match(d_particles(i).x))
813   {
814     bin_one(lminmax, d_particles(i).v[index]);
815   }
816   */
817 }
818 
819 /* ------------------------------------------------------------------------- */
820 KOKKOS_INLINE_FUNCTION
821 void
operator ()(TagFixAveHisto_BinParticlesV3,const int i,minmax_type::value_type & lminmax) const822 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticlesV3, const int i,
823                               minmax_type::value_type& lminmax) const
824 {
825   const int ispecies = d_particles(i).ispecies;
826   if (d_s2g(imix, ispecies) >= 0)
827   {
828     bin_one(lminmax, d_particles(i).v[index]);
829   }
830 }
831 
832 /* ------------------------------------------------------------------------- */
833 KOKKOS_INLINE_FUNCTION
834 void
operator ()(TagFixAveHisto_BinParticlesV4,const int i,minmax_type::value_type & lminmax) const835 FixAveHistoKokkos::operator()(TagFixAveHisto_BinParticlesV4, const int i,
836                               minmax_type::value_type& lminmax) const
837 {
838   bin_one(lminmax, d_particles(i).v[index]);
839 }
840