#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

#define DEBUG 0
#define BINARYFILE 0

void input_file_read(int my_rank)
{
  extern double Det_t, racc, dbob1, b01;
  extern int nfs, derivative_type1, field_type1, num_fieldlines;

  extern int NZ, NX, NY, nits, output_node_0;

  extern char output_filename[80];
  extern int temp_int_transfer[8];

  extern double temp_double_transfer[8];

  extern int num_integers, num_doubles;
  extern int integer_input[];

  extern double double_input[];
  extern double lenx1, leny1, lenz1, dt;

  int i;
  char temp_char[80];
  FILE *input_file;

  /* The <setup file name> is hard coded as setup */

  if ( ( input_file = fopen("setup", "r") ) == NULL)
    {
      printf("File not found: setup\nProgram Aborted\n");
      MPI_Abort(MPI_COMM_WORLD,0);
      exit(1);
    }

      fscanf(input_file, "NFS=%d\n", &nfs);
      fscanf(input_file, "output_node_0=%d\n", &output_node_0);
      fscanf(input_file, "output_filename=%s\n", output_filename);
      fscanf(input_file, "derivative_type=%d\n", &derivative_type1);
      fscanf(input_file, "field_type=%d\n", &field_type1);
      fscanf(input_file, "num_fieldlines=%d\n", &num_fieldlines);
      fscanf(input_file, "NZ=%d\n", &NZ);
      fscanf(input_file, "NX=%d\n", &NX);
      fscanf(input_file, "NY=%d\n", &NY);
      fscanf(input_file, "nits=%d\n", &nits);
      fscanf(input_file, "lenx=%lf\n", &lenx1);
      fscanf(input_file, "leny=%lf\n", &leny1);
      fscanf(input_file, "lenz=%lf\n", &lenz1);
      fscanf(input_file, "dt=%lf\n", &dt);
      fscanf(input_file, "racc=%le\n", &racc);
      fscanf(input_file, "Det_t=%le\n", &Det_t);
      fscanf(input_file, "dbob=%lf\n", &dbob1);
      fscanf(input_file, "b0=%lf\n", &b01);
      fscanf(input_file, "num_integers=%d\n", &num_integers);
      fscanf(input_file, "num_doubles=%d\n", &num_doubles);
  fclose(input_file);

  /* Deciding on the correct value for dt */
  if (dt > Det_t || dt == 0.0 )
    /* Using default value */
    dt = 0.00001 * Det_t;
  else
    if (dt < 0.0 )
      /* Using the input value of dt as a fraction of Det_t */ 
      dt = -1.0 * Det_t * dt;

  if (num_integers > 0)
    {
      /* All the integer values are read in here */
      if ( (input_file = fopen("int_values", "r") ) == NULL)
	{
	  printf("File not found: int_values\nProgram Aborted\n");
	  MPI_Abort(MPI_COMM_WORLD,0);
	  exit(1);
	}
      
      for ( i = 0; i < num_integers; i++ )
	{
	  fscanf(input_file,"%d\n", &integer_input[i]);
	  if (my_rank == 0) printf("int_input[%d] = %d\n", i, integer_input[i] );
	  
	  fgets(temp_char, 100, input_file);
	  if (DEBUG) printf("temp_char = %s\n", temp_char);
	}
      
      
      fclose(input_file);
    }

  /* All the double values are read in here */
  if (num_doubles > 0 )
    {
      if ( (input_file = fopen("double_values", "r")) == NULL )
	{
	  printf("File not found: double_values\nProgram Aborted\n");
	  MPI_Abort(MPI_COMM_WORLD,0);
	  exit(1);
	}
      
      for ( i = 0; i < num_doubles; i++ )
	{
	  fscanf(input_file,"%lf", &double_input[i]);
	  if (my_rank == 0) printf("double_input[%d] = %lf\n", i, double_input[i] );
	  
	  fgets(temp_char, 100, input_file);
	  if (DEBUG) printf("temp_char = %s\n", temp_char);
	  
	}
      
      fclose(input_file);
    }

  if ( nfs == 0)
    {
      temp_double_transfer[0] = Det_t;
      temp_double_transfer[1] = racc;
      temp_double_transfer[2] = dbob1;
      temp_double_transfer[3] = b01;
      temp_double_transfer[4] = lenx1;
      temp_double_transfer[5] = leny1;
      temp_double_transfer[6] = lenz1;
      temp_double_transfer[7] = dt;
    
      temp_int_transfer[0] = output_node_0;
      temp_int_transfer[1] = derivative_type1;
      temp_int_transfer[2] = field_type1;
      temp_int_transfer[3] = num_fieldlines;
      temp_int_transfer[4] = NZ;
      temp_int_transfer[5] = NX;
      temp_int_transfer[6] = NY;
      temp_int_transfer[7] = nits;
    }

  if ( my_rank == 0 )
    {
      printf( "NFS=%d\n", nfs);
      printf( "Output_node_0=%d\n", output_node_0);
      printf( "Output_filename=%s\n", output_filename);
      printf( "Derivative_type=%d\n", derivative_type1);
      printf( "Field_type=%d\n", field_type1);
      printf( "num_fieldlines=%d\n", num_fieldlines);
      printf( "NZ=%d\n", NZ);
      printf( "NX=%d\n", NX);
      printf( "NY=%d\n", NY);
      printf( "dt=%f\n", dt);
      printf( "nits=%d\n",   nits);
      printf( "lenx=%f\n",   lenx1);
      printf( "leny=%f\n",   leny1);
      printf( "lenz=%f\n",   lenz1);
      printf( "racc=%e\n",   racc);
      printf( "Det_t=%e\n",  Det_t);
      printf( "dbob=%f\n",   dbob1);
      printf( "b0=%f\n",     b01);
      printf( "num_integers=%d\n", num_integers);
      printf( "num_doubles=%d\n", num_doubles);
    }
}

void x0_file_read()
{
  extern double *job_input_array;
  extern int num_fieldlines, length;
  int i;

  FILE *data_file;

  /* The <data input file name> is hard coded as data */ 
  if ( (data_file = fopen("data", "r")) == NULL )
    {
      printf("File not found: data\nProgram Aborted\n");
      MPI_Abort(MPI_COMM_WORLD,0);
      exit(1);
    }

  if (DEBUG) printf("length = %d\n", length);
  for ( i = 0; i < num_fieldlines; i++)
    {
      job_input_array[i * length + 0] = (double) i+1; /* job _number initialization */
      job_input_array[i * length + 2] = 1.0; /* Initialize the status of all jobs to 1 */

      fscanf( data_file, "%lf %lf %lf %lf %lf %lf %lf\n", 
	      &job_input_array[i * length + 1], \
	      &job_input_array[i * length + 4], \
	      &job_input_array[i * length + 5], \
	      &job_input_array[i * length + 6], \
	      &job_input_array[i * length + 7], \
	      &job_input_array[i * length + 8], 
	      &job_input_array[i * length + 9] );

    }  

  if (DEBUG)
    {
      printf("Inside file_read\n");
      for (i=0; i<length*num_fieldlines; i++)
	printf("%f\t", job_input_array[i]);
      printf("\n");
    }
  fclose(data_file);
}

void local_file_write(int i, double *job_result, FILE *output_file)
{
  int j;
  extern int length;

  if (BINARYFILE)
    fwrite(job_result, sizeof(double), i * length, output_file);
  
  else
    for (j=0; j<i; j++)
      fprintf(output_file,"%.0f %.0f %.4f %.20f %.20f %.20f %.10f %.10f %.10f\n",
	      job_result[j * length + 0], job_result[j * length + 1],
	      job_result[j * length + 2], job_result[j * length + 4],
	      job_result[j * length + 5], job_result[j * length + 6],
	      job_result[j * length + 7], job_result[j * length + 8],
	      job_result[j * length + 9] );
}

void c_file_write__( int *dimension, int *n, char *fname, double *data)
{
  int i, j;
  FILE *f1;

  if ( ( f1 = fopen( fname, "w") ) == NULL)
    {
      printf("Unable to create file: %s\nProgram Aborted\n", fname);
      MPI_Abort(MPI_COMM_WORLD,0);
      exit(1);
    }

  for (i = 0; i < *n; i++)
    {
      for (j = 0; j < *dimension; j++)
        {

          if (DEBUG) printf("i,j = %d %d %d %lf\n", 
	      i, j, (i * (*dimension)) +j , data[i*(*dimension)+j]);
 
          fprintf(f1, "%4.12f\t", data[( i * (*dimension) ) + j] );

        }
      fprintf(f1, "\n");
    }
  fclose(f1);
}


void error_printf__(char *display_string)
{
  printf("%s\n", display_string);
}









