/********************************************************************
 *                                                                  *
 *     SU(3) adjoint Higgs field in 3d                              *
 *                                                                  *
 *     coupling constants: betag, x, y                              *
 *     action is always exp[-S]                                     *
 *                                                                  *
 *     Kari Rummukainen, May 97 (MIMD)                              *
 *******************************************************************/

#define CONTROL
#include "lattice.h"    /* global variables for lattice fields */


void runthis(int maxiters,int status);

static int istimelimit = 0;

/* PABS main -> kernel_b */

int
kernel_b()
{
  int kernel_number = 1;
  int s_iteration;
  int i,status;
  time_t t;
  double at;

  /* JuBE */
  /* call jube initial function */
  jube_kernel_init(&kernel_number);


  t  = time(NULL);

  /* Machine initialization first */
  initial_setup();

  /* set up */
  status = setup();

  /* allocate the variable fields */
  foralldir(i) U[i] = new_latfield( su3_matrix );
#ifdef HIGGS
  ahiggs = new_latfield( adjoint_matrix );
#endif

  /* load in config, if it exists */
  load_config(status);

  /* Setup measurement etc files */
  setfiles((status == 0) && (iteration != 0));

#ifdef HIGGS
  /* check if we want to do this multicanonically */
  setmulti();
#endif

  /* timelimit, if it is used */
/*   PABS, no time limit */
/*   istimelimit = setup_timelimit(t,argc-1,argv[1]); */
  istimelimit = 0;

  fflush(stdout);

  /* first, set the Metropolis scales and thermalise */
  if (status >= 1) {
    runthis(n_thermal,1);
  }

  if (this_node == 0) {
    printf(" - Time spent thermalising: %lg seconds\n",cputime());
    fflush(stdout);
  }

  resettime();  /* reset the clock */

  if (status > 0) timeu = timea = timerest = 0;
  ahithb = nhithb = ahitu = nhitu = 0;
#ifdef HIGGS
  ahitua = ahitax = ahitmc = ahitog = 0.0;
  nhitua = nhitax = nhitmc = nhitog = 0;
#endif
  s_iteration = iteration;

  /* JuBE */
  /* call jube run function */
  jube_kernel_run();

  runthis(n_iteration,0);

  /* JuBE */
  /* call jube finalize function */
  jube_kernel_finalize();


  /* print the tail */

  if (this_node == 0) {
    printf("---------\n");
    
    printf("Acceptances (after last start: %d iterations:\n",
	   n_iteration-s_iteration);
    if (nhitu)
      printf(" Kennedy-Pendleton for gauge: %g (%d sweeps)\n",
	     ahitu/nhitu,nhitu);
#ifdef HIGGS
    if (nhitua)
      printf(" Adjoint acceptance for gauge: %g (%d sweeps)\n",
	     ahitua/nhitua,nhitua);
    if (nhitax)
      printf(" X-overrelaxation for Higgs: %g (%d sweeps)\n",
	     ahitax/nhitax,nhitax);
    if (nhitog)
      printf(" Gaussian overrelaxation for Higgs: %g (%d sweeps)\n",
	     ahitog/nhitog,nhitog);
    if (nhithb)
      printf(" Heat bath for Higgs: %g (%d sweeps)\n",
	     ahithb/nhithb,nhithb);
    if (nhitmc)
      printf(" Multicanonical acceptance: %g (%d sweeps)\n",
	     ahitmc/nhitmc,nhitmc);
#endif

    at = timeu+timea+timerest;
    printf("\nCpu times:\n");
    printf("     %9.1lf   total time in seconds\n",at);
    printf("       %9.3lf seconds for one cycle\n",at/n_iteration);
    at = 1.0/((mc_steps+1) * n_iteration * lattice.volume);
    printf("     %9.1lf   seconds for su3 gauge field update\n",timeu);
    printf("       %9.3lf microseconds/U/update\n",1e6*timeu*at/3);
#ifdef HIGGS
    printf("     %9.1lf   seconds for Higgs update\n",timea);
    printf("       %9.3lf microseconds/Higgs/update\n",1e6*timea*at);
    printf("     %9.1lf   seconds for the rest\n",timerest);
#endif    

#ifdef check
    print_check();
#endif
    at = cputime();
    printf("Resources:");
    printf(" Cpu:  %lg\n",at);
    t = time(NULL) - t;
    printf(" Wallclock time %ld seconds, Cpu/Wall %lg\n",t,at/t);
    
    printf("#########\n");
  }
#ifdef MPI
  report_comm_timers();
/*   MPI_Finalize(); */
#endif

  /* JuBE */
  /* call jube finalize function */
  jube_kernel_end();

  return 0;
}


/*************************************************
 * do the whole run
 */

void
runthis(int maxiters,int status)
{
  int meas,i;

  if (istimelimit) inittimecheck();

  meas = (status == 0);
  iteration ++;
  for (; iteration <= maxiters; iteration++) {
    for (i=0; i<mc_steps; i++) {
      updategauge(1);
      addtime(timeu);
      check_action(0);
#ifdef HIGGS
      updatehiggs(1); 
      check_action(1);
      addtime(timea);
#endif
    }
    updategauge(0);
    reunitarize(U);
    addtime(timeu);
#ifdef HIGGS
    updatehiggs(0);
    addtime(timea);
#endif
    if (meas) {
      if (iteration%n_measurement == 0) {
	measure();
	writemeas();
      }
#ifdef HIGGS
      if (iteration%n_correlation == 0) {
	hcorr();
	if (iteration%w_correlation == 0) writecorr();
      }
#endif
    }

    /* check if there is need to quit ... */
#ifdef HIGGS
    if (istimelimit && iteration%w_correlation == 0) 
#else
    if (istimelimit) 
#endif
      timecheck(iteration, maxiters, status);

    if (iteration% abs(n_save) == 0) {
#ifdef HIGGS
      if (is_mucacalc && this_node == 0) writemuca();
#endif
      g_sync();
      dumpall(status,&maxiters);
    }
    addtime(timerest);
  }

  iteration--;
  /* save if not done above */
  if (iteration%n_save != 0) dumpall(status,&maxiters);
  iteration = 0;    /* prepare for the next sweep */
}

