/*******************************************************************************
*
* McXtrace, x-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: Progress_bar
*
* %Identification
* Written by: Emmanuel Farhi
* Modified by: Erik Knudsen
* Date: 2009
* Origin: ILL
* Release: McXtrace 1.0
*
* A simulation progress bar
*
* %Description
* An indicator of the progress of the simulation, monitoring
* the Init, Trace with the achieved percentage, and the Finally section.
* Intermediate savings (e.g. triggered by USR2 signal) are also shown.
* This component should be positioned at the very begining of the instrument
* The profile option will save the intensity and number of events for each
* component It may be used to evaluate the simulation efficiency.
*
* Example: Progress_bar(percent=10,flag_save=1) AT (0,0,0)
*
* %Parameters
* INPUT PARAMETERS:
* percent: [0-100]  percentage interval between updates. Default is 10%.
* minutes: [min]    time in minutes between updates (Overrides percent flag).
* flag_save: [0|1]  flag to enable intermediate saving for all monitors
* profile: [str]    file name to save the simulation profile in. If set to "", it is set to the name of the instrument.
*
* %End
*******************************************************************************/

DEFINE COMPONENT Progress_bar
DEFINITION PARAMETERS ()
SETTING PARAMETERS (string profile="NULL", percent=10,flag_save=0,minutes=0)
OUTPUT PARAMETERS ()
/* X-ray parameters: (x,y,z,kx,ky,kz,phi,t,Ex,Ey,Ez,p) */ 

DECLARE
%{
#ifndef PROGRESS_BAR
#define PROGRESS_BAR
#else
#error Only one Progress_bar component may be used in an instrument definition.
#endif

  double IntermediateCnts;
  time_t StartTime;
  time_t EndTime;
  time_t CurrentTime;
  char infostring[64];
%}

INITIALIZE
%{
  IntermediateCnts=0;
  StartTime=0;
  EndTime=0;
  CurrentTime=0;

  fprintf(stdout, "[%s] Initialize\n", instrument_name);
  if (percent*mcget_ncount()/100 < 1e5) {
    percent=1e5*100.0/mcget_ncount();
  }
  #ifdef OPENACC
  time(&StartTime);
  #endif

#ifdef USE_MPI
  sprintf(infostring, "(%i MPI processes) ", mpi_node_count);
#else
  sprintf(infostring, "");
#endif

%}

TRACE
%{
#ifndef OPENACC
  double ncount;
  ncount = mcget_run_num();
  if (!StartTime) {
    time(&StartTime); /* compute starting time */
    IntermediateCnts = 1e3;
  }
  time_t NowTime;
  time(&NowTime);
  /* compute initial estimate of computation duration */
  if (!EndTime && ncount >= IntermediateCnts) {
    CurrentTime = NowTime;
    if (difftime(NowTime,StartTime) > 10 && ncount) { /* wait 10 sec before writing ETA */
      EndTime = StartTime + (time_t)(difftime(NowTime,StartTime)
				     *(double)mcget_ncount()/ncount);
      IntermediateCnts = 0;
      MPI_MASTER(
      fprintf(stdout, "\nTrace ETA ");
	fprintf(stdout, "%s", infostring);
      if (difftime(EndTime,StartTime) < 60.0)
        fprintf(stdout, "%g [s] %% ", difftime(EndTime,StartTime));
      else if (difftime(EndTime,StartTime) > 3600.0)
        fprintf(stdout, "%g [h] %% ", difftime(EndTime,StartTime)/3600.0);
      else
          fprintf(stdout, "%g [min] ", difftime(EndTime,StartTime)/60.0);
	fprintf(stdout, "\n");
      );
    } else IntermediateCnts += 1e3;
    fflush(stdout);
  }

  /* display percentage when percent or minutes have reached step */
  if (EndTime && mcget_ncount() &&
    (    (minutes && difftime(NowTime,CurrentTime) > minutes*60)
      || (percent && !minutes && ncount >= IntermediateCnts))   )
  {
    MPI_MASTER(
      fprintf(stdout, "%llu %%\n", (unsigned long long)(ncount*100.0/mcget_ncount())); fflush(stdout);
    );
    CurrentTime = NowTime;

    IntermediateCnts = ncount + percent*mcget_ncount()/100;
    /* check that next intermediate ncount check is a multiple of the desired percentage */
    IntermediateCnts = floor(IntermediateCnts*100/percent/mcget_ncount())*percent*mcget_ncount()/100;
    /* raise flag to indicate that we did something */
    SCATTER;
    if (flag_save) save(NULL);
  }
#endif
%}

SAVE
%{
  MPI_MASTER(fprintf(stdout, "\nSave [%s]\n", instrument_name););
  if (profile && strlen(profile) && strcmp(profile,"NULL") && strcmp(profile,"0")) {
    char filename[256];
    if (!strlen(profile) || !strcmp(profile,"NULL") || !strcmp(profile,"0")) strcpy(filename, instrument_name);
    else strcpy(filename, profile);
    DETECTOR_OUT_1D(
        "Intensity profiler",
        "Component index [1]",
        "Intensity",
        "prof", 1, mcNUMCOMP, mcNUMCOMP-1,
        &(instrument->counter_N[1]),&(instrument->counter_P[1]),&(instrument->counter_P2[1]),
        filename);

  }
%}

FINALLY
%{
  time_t NowTime;
  time(&NowTime);
  fprintf(stdout, "\nFinally [%s: %s]. Time: ", instrument_name, dirname ? dirname : ".");
  if (difftime(NowTime,StartTime) < 60.0)
    fprintf(stdout, "%g [s] ", difftime(NowTime,StartTime));
  else if (difftime(NowTime,StartTime) > 3600.0)
    fprintf(stdout, "%g [h] ", difftime(NowTime,StartTime)/3600.0);
  else
    fprintf(stdout, "%g [min] ", difftime(NowTime,StartTime)/60.0);
  fprintf(stdout, "\n");
%}

MCDISPLAY
%{

%}

END
