/*************************************************************************************
 * Program:  t32c2t                                                                  *
 * Purpose: Calculate CCT from TTT according to Scheil.                              *
 *                                                                                   *
 * Author:  M J Peet                                                                 *
 * Version: 0.21                                                                     *
 * Date:    09-July-08                                                               *
 * Location: http://mathewpeet.org/thesis/programs/                                  *
 * License: GPL, Gnu Public License, you are free to modify and use this program     *
 * if you distribute the program you must also distribute the code, along with any   *
 * changes you make. Do not modify this header.                                      *
 *                                                                                   *
 ************************************************************************************/



#include <stdio.h>
#include <math.h>
#define ARRAYSIZE 1600/* size of arrays used for globals - max temperature when using 1 K resolution for temperature*/

#undef HELLO /* control DEBUGGING CODE --- set to `define or undef' to test program structure */
#undef DEBUG /* control DEBUGGING CODE --- set to `define or undef' */


/* Globals */
int tempsK[ARRAYSIZE+1];/*!< maximum temp is (ARRAYSIZE) kelvin, the time spent at each temperature will be stored here. */
double starttK[ARRAYSIZE+1];/*!< corresponding time for when transformation is detectable at a temperature in TTT */

int main() {

/** PSEUDO CODE 
 *
 *  Get input cooling (linear, ideal, data file?)
 *
 *  Step through time, and record time spent at each temp
 *
 *  Read in Time-temperature-transformation data (ttt)
 * 
 *  Calculate amounts of transformation at each temp during cooling
 *  output temp and time when transformation is detectable
 * 
 */
  int transf_temp; /*!< temperature at which transformation is first detectable */
  double startT,rate;
  initialise_global_starttK();
  initialise_global_tempsK();

  /*! initilise arrays for temp (0) and start time (large).  */
  
  /*test_ttt();    /* this should only need to be read once 
		  * should be adjusted to allow input from file / IO
		  */
  //test_globals();
  	read_ttt();		 


  //	calc_temp_erf();         /* calculate times spent at each temperature during cooling.*/
  /*make cooling rate or section size a variable in calc_tempsK
   * include this in a loop to find when start_temp is non zero
   * this will allow to find critical cooling rate or section size
   * Also add analytical solution for cylinders
   */
  
  startT=1273; //temperature in kelvin, you can use any as long as you use for input TTT also
  rate=0.00005;
  printf("cooling rate /K/s, temperature /K, time /s\n");
  do {
    //printf("\nlinear cooling rate:"); 
    printf("%lf, ",rate);
    initialise_global_tempsK();
    calc_temp_lin(startT,rate);
    transf_temp = output_cct();
    //printf("\nmain knows temperature was: %d\n", transf_temp);
    rate=rate*1.05;
  } while (transf_temp>0);
 

  /* call subroutine calc_temp_erf with different distances
   * and calculate cooling times in similar way
   *
   */
  
  double surfaceT,diffusivity,depth,mindepth;
  surfaceT = 473;
  depth = 1;            // in m
  mindepth = 0.000000001; // stop when we get this close to surface
  diffusivity = 0.00001175;  // m^2/s
// diffusivity 1.175e-5 m^2/s for 1C wt% steel (Holman), 5.44x10-2 cm^2/s for low alloy at 1000 K.

 startT=1273;


  printf("\n\nsemi infinite heat flow\n");
  printf("Depth /m, temperature /K, time /s\n"); //ensure diffusivity is in appropriate units!
  do {
    //printf("\n Depth:"); 
    printf("%lf, ",depth);
    initialise_global_tempsK();
    calc_temp_erf(startT,surfaceT,diffusivity,depth);
   //show_globals();
    transf_temp = output_cct();
//    printf("\nmain knows temperature was: %d\n", transf_temp);
    depth=(depth/1.1);
  } while (transf_temp>0);




  /* there is also a solution of semi infinite heat flow
   * equation for shafts and cylinders 
   *
   **/
  

   /* could also calculate natural cooling curves for welding CCTs
    *
    */

  
  
  /* QUESTION
   * is this only accurate if longer than           
   * 1 unit of time is spent at each temperature?   
   */
  
  
#ifdef DEBUG
  test_globals();  /* print contents of the two arrays */
  printf ("\nGoodbye from program\n");
#endif /* DEBUG */
  printf("\n");
  return (0);
}

int test_globals() {
  int i;
#ifdef HELLO 
  printf("\nhello from test_globals subroutine\n"); 
#endif /* HELLO */
  printf("\nContents of arrays as follows i, tempsK[i], starttK[i]\n");
  for (i = ARRAYSIZE; i>=0; i--)
     if(tempsK[i]>0)
        printf("i = %#5d, tempsK[] = %#5d N, starttK[] =%4.4le s.\n",i,tempsK[i],starttK[i]);
  return (0);
}


int initialise_global_tempsK() {
#ifdef HELLO
  printf("\nhello from initialise_global_tempsK subroutine\n"); 
#endif /* HELLO */
  int i;
  for (i = ARRAYSIZE; i>=0; i--) {	
    tempsK[i]=0; /*initialise */
  }
  tempsK[0]=0;
  return (0);	
}



int initialise_global_starttK() {
#ifdef HELLO
  printf("\nhello from initialise_global_starttK subroutine\n"); 
#endif /* HELLO */
  int i;
  for (i = ARRAYSIZE; i>0; --i) {	
    starttK[i]=1.65e308;
  }
  starttK[0]=1.65e308;
  return (0);	
}



int calc_temp_erf(double Ti, double Ts, double A, double X) {
#ifdef HELLO
  printf("\nhello from calc_temps_erf subroutine\n");
  printf("%lf %lf %lf %lf",Ts,Ti,A,X);
#endif /* HELLO */
  
  double time;
  double temp;
  int a;
  //double Ts, Ti, A, X;  /*	variables used in semi - infinite solution of heat flow */
  
  /** Ti initial temperature, 
  *   Ts surface temperature, 
  *   A thermal diffusivity heat,
  *   X distance - units depends upon units of A. 
  * \f$\textrm{temp} = Ts + (Ti-Ts)\times \textrm{erf}\left(\frac{X}{2 \sqrt{A*\textrm{time}}} \right)\f$
  **/
//   printf("Ts: %lf Ti:%lf A:%lf X:%lf",Ts,Ti,A,X);
   time = 0.0;

  do {
    temp = Ts + (Ti-Ts)*(erf(X/(2.0*sqrt(A*time)))); /* 1 D heat flow 
/*  temp = 1273 - (time*0.39); */
    a = (int)temp;
//    printf("a = %#5d,temp = %4.4le K, time = %4.4le s.\n",a,temp,time);
    tempsK[a]++; 
    time = time + 1.0;
  } while (temp > 0 && time < 10e7);
  
  //printf("\nCooled to %lf kelvin in %lf seconds.",temp, time);
  
  return (0);
}


int calc_temp_lin(double start_temp,double rate) {
   double time;
  double temp;
  //start_temp = 1273;
  //rate = 1.0;
  int a;
#ifdef HELLO
  printf("\nhello from calc_temps_lin subroutine\n");
  printf("I know start_temp %lf and rate is %lf",start_temp,rate);
#endif /* HELLO */
  time = 0.0;
  do {
    temp = start_temp - (time*rate); /* linear cooling */
    a = (int)temp;
    
#ifdef DEBUG
    printf("a = %#5d,temp = %4.4le K, time = %4.4le s.\n",a,temp,time);
#endif /* DEBUG */
    tempsK[a]++;
    time = time + 1.0;
  } while (temp > 0);
  
#ifdef DEBUG  
  printf("\nCooled to %lf Kelvin in %lf seconds.\n",temp, time);
#endif /* DEBUG */
 
  return (0);	
}


int test_ttt()
{
  printf("\nHello from test_ttt\n");
  int i;	
  for (i = 1000; i >= 600; i--)	
    starttK[i] = 3000.0;	
  
  return (0);
}

int read_ttt()
{
  double tttT, tttt;
  int error_detect[ARRAYSIZE];
  int i;
  for (i = ARRAYSIZE; i>=0; i--) 
    error_detect[i]=0;
  
  
#ifdef HELLO
  printf("\nhello from read_ttt\n");
#endif /* HELLO */

  /* read numbers until you find a non number (eof or character) */
  while((scanf("%lf %lf", &tttT, &tttt)) != EOF) {	
#ifdef DEBUG
    printf("%lf %lf \n",tttT,tttt);
#endif /* DEBUG */
    error_detect[(int)tttT]++;
    starttK[(int)tttT]=tttt;
  }	
  
  return (0);
}

int show_globals()
{
  printf("\nHello from show_globals\n");
  int i;	
  for (i = ARRAYSIZE; i >= 0; i--)	
    printf("\n starttK[%d] %le, tempsK[%d] %d, tran: %le",i,starttK[i],i,tempsK[i],tempsK[i]*(1.0/starttK[i]));
  
  return (0);
}


int output_cct() /** this function returns the temperature at which transformation was first detected */
{
#ifdef HELLO  
  printf("\nhello from output_cct\n");
#endif /*HELLO*/
  int b;
  int time;
  double amount = 0; /* volume fraction transformed as fraction of detectable amount */
  
  //  printf("Time for detectable transformation to occur during cooling.");
  //printf("Temperature, amount");
  time =0;
  b = ARRAYSIZE;
  do {
    b--;
    amount += tempsK[b]*(1.0/starttK[b]);
    time += tempsK[b];
#ifdef DEBUG	  
    printf("b = %d amount = %le\n", b, amount);
#endif /* DEBUG */
  } while ((amount < 1.0) && b > 0 );
  
  //printf("start detected at temperature of"); 
  printf(" %d, %d\n",b,time);
  
  return b;
}
