/*************************************************************************************
 * Program: LP2C                                                                     *
 * Purpose: Calculate Carbon Content of Austenite and Ferrite from Lattice Parameter *
 * using empirical relationships (linear) due to Dyson and Holmes                    *
 *                                                                                   *
 * Author:  Mathew James Peet                                                        *
 * Version: 0.03                                                                     *
 * Date:    01-Mar-2010  ... White Rabits!                                           *
 * 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 <stdlib.h>
#define K 0.28664 //checked - calc should be in nm and mol_frac
#define KK 0.0821624896 // K*K just to save calc
#define KKK 0.0235510560189 // K*K*K just to save calc




// define global variables 
double lp=0;  // lattice parameter in nanometers
double Comp_Si=0; //weight percent
double Comp_Mn=0; //weight percent
double Comp_Cr=0; //weight percent
double Comp_Ni=0; //weight percent
double Comp_V=0; //weight percent
double Comp_Mo=0; //weight percent
double Comp_C=0; //weight percent


main()
{
  warn();
  printf("Enter Lattice Parameter: \n");
  scanf("%lf",&lp);
  entercomposition();
  if (lp >1.0)
    {
      printf("assuming entered value in angstoms dividing by 10\n");
      lp = lp/10.0;
    }
  else
    {
      printf(".\n");
    }
  
  if (lp > 0.25 && lp < 0.4)
    {
      if (lp > 0.3 && lp < 0.4)
        calc_aus_lp();
      else if (lp > 0.25)
        calc_fer_lp();
      else
	exit(-1);
    }
  else
    {
      printf("Lattice Paramater Out of Range\n");
      exit(-1);
    }
  exit(0);
}

entercomposition() //replace with interactive or load from file option
{
  /*    Comp_Si=1.59; //Aus 1 weight percent
  Comp_Mn=1.94;
  Comp_Cr=1.33;
  Comp_Ni=0.02;
  Comp_V=0.11;
  Comp_Mo=0.3; 
  Comp_C=0.8;// Average or Nominal Composition */

  Comp_Si=1.59; //Stress induced bainite transformation in steel -  weight percent
  Comp_Mn=1.94;
  Comp_Cr=1.33;
  Comp_Ni=0.02;
  Comp_V=0.1;
  Comp_Mo=0.3; 
  Comp_C=0;// Average or Nominal Composition */

}
calc_aus_lp()
{
  double w_Mn=0;
  double w_Si=0;
  double w_Ni=0;
  double w_Cr=0;
  double w_Mo=0;
  double w_V=0;
  double w_C=0;



  printf("Assuming Austenite... Calculating for Austenite\n");
  //for testing we have the values we need.
   printf("lp is %f\n",lp);
  printf("Si is %f\n",Comp_Si);
  printf("Mn is %f\n",Comp_Mn);
  printf("Cr is %f\n",Comp_Cr);
  printf("Ni is %f\n",Comp_Ni);
  printf("V is %f\n",Comp_V);
  printf("Mo is %f\n",Comp_Mo);
  
  w_Mn=Comp_Mn/100;
  w_Si=Comp_Si/100; //anyway Si isnt used in calc.
  w_Ni=Comp_Ni/100;
  w_Cr=Comp_Cr/100;
  w_Mo=Comp_Mo/100;
  w_V=Comp_V/100;
  
  w_C=(lp-(0.3578+0.0095*w_Mn-0.002*w_Ni+0.006*w_Cr+0.031*w_Mo+0.018*w_V))/0.33; // Dyson and Holmes - Alloy additions
  // paper also contains estimate of errors due to each element
  Comp_C=w_C*100;

  printf("C in Austenite is %f Wt%\n",Comp_C);
  printf("C in Austenite is %lf Wt%\n",Comp_C);

  Comp_C = (10*lp-(3.578+0.00095*Comp_Mn - 0.0002*Comp_Ni + 0.0006*Comp_Cr + 0.0031*Comp_Mo + 0.0018*Comp_V))/0.033;
  printf("C in Austenite is %f Wt%\n",Comp_C);
  printf("C in Austenite is %lf Wt%\n",Comp_C);

}

calc_fer_lp()
{ 
  double step;  
  double lp_i=0;
  double A=0;
  double X_Si = 0;// Mole fraction
  double X_Mn = 0;
  double X_Cr = 0;
  double X_Ni = 0;
  double X_V = 0;
  double X_Mo = 0;
  double X_C = 0;
  double Comp_Fe = 0;//weight percent 
  double total_moles= 0;

  printf("Assuming Ferrite.... Calculating for Ferrite\n");
  
  Comp_Fe = 100-Comp_Si - Comp_Mn - Comp_Cr - Comp_Ni 
    - Comp_V - Comp_Mo;
  // - Comp_C;   //weight percent
  
  total_moles = 
    Comp_Fe/55.847
    +Comp_Si/28.086
    +Comp_Mn/54.847
    +Comp_Cr/51.996
    +Comp_Ni/58.71
    +Comp_V/50.9415 
    +Comp_Mo/95.94;
    // +Comp_C/12.01115; //moles in 100g
  
  X_Si= (Comp_Si/28.086)/total_moles;
  X_Mn= (Comp_Mn/54.847)/total_moles;
  X_Cr= (Comp_Cr/51.996)/total_moles;
  X_Ni= (Comp_Ni/58.71)/total_moles;
  X_V= (Comp_V/50.9415)/total_moles;
  X_Mo= (Comp_Mo/95.94)/total_moles;
  X_C= 0;
    //(Comp_C/12.01115)/total_moles;

  //testing
  printf("lp is %f\n",lp);
  printf("Element\t Wt%\t\tmole fraction\n");
  printf("Si\t%f\t%f\n",Comp_Si,X_Si);
  printf("C\t%f\t%f\n",Comp_C,X_C);
  printf("Cr\t%f\t%f\n",Comp_Cr,X_Cr);
  printf("Ni\t%f\t%f\n",Comp_Ni,X_Ni);
  printf("V\t%f\t%f\n",Comp_V,X_V);
  printf("Mo\t%f\t%f\n",Comp_Mo,X_Mo);
  
    /*K is a constant relating to lattice param of pure ferrite 
    defined at start of file as 0.28664 - substituted at compile time */
 
   A = K;
  printf("\n\n\t%f\n",A);
  A = KK;
  printf("\n\t%f\n",A);
  A = KKK;
  printf("\n\t%f\n",A);

  
  // A = K - 0.03*Comp_Si+ 0.06*Comp_Mn+ 0.07*Comp_Ni+ 0.31*Comp_Mo+ 0.05*Comp_Cr+ 0.096*Comp_V;
  
  A = K - 0.003*X_Si + 0.006*X_Mn + 0.007*X_Ni + 0.031*X_Mo + 0.005*X_Cr + 0.0096*X_V;
  //A = K;
  printf("contribution of other elements is \n\t%f\n",A);
  

  // printf("setting lattice param from 600 temper \n\t%f\n",A);
  // A = 0.287250737412143;
  //printf("contribution of other elements is \n\t%f\n",A);


  Comp_C=0;//need to reinitalise Comp_C since that is what we want to calculate
  X_C = 0;
  step = 1;
  while (lp_i < lp)
    {
      X_C = X_C + step;
      lp_i = A + (  (   (K-0.0279*X_C)*(K-0.0279*X_C)*(K+0.2496*X_C)-KKK   )  /  (3.0*KK)   );
      
    }
  printf("%f\t \t%f %f\n",Comp_C,X_C,lp_i); //uncomment for testing
  
  Comp_C = X_C*4;
  step = -0.1;
  while (lp_i > lp)
    {
      X_C = X_C + step;
      //lp_i = A + (  ((K-0.0279*X_C)*(K-0.0279*X_C)*(K+0.2496*X_C)-KKK)   /3*KK);
      lp_i = A + (  (   (K-0.0279*X_C)*(K-0.0279*X_C)*(K+0.2496*X_C)-KKK   )  /  (3.0*KK)   );
    }
  printf("%f\t \t%f %f\n",Comp_C,X_C,lp_i); //uncomment for testing
  
  Comp_C = X_C*4;
  step = 0.001;
  while (lp_i < lp)
    {
      X_C = X_C + step;
      //lp_i = A + (  ((K-0.0279*X_C)*(K-0.0279*X_C)*(K+0.2496*X_C)-KKK)   /3*KK);
      lp_i = A + (  (   (K-0.0279*X_C)*(K-0.0279*X_C)*(K+0.2496*X_C)-KKK   )  /  (3.0*KK)   );
    }
    printf("%f\t \t%f %f\n",Comp_C,X_C,lp_i); //uncomment for testing
  
  Comp_C = X_C*4;
  step = -0.00001;
  while (lp_i > lp)
    {
      X_C = X_C + step;
      //lp_i = A + (  ((K-0.0279*X_C)*(K-0.0279*X_C)*(K+0.2496*X_C)-KKK)   /3*KK);
      lp_i = A + (  (   (K-0.0279*X_C)*(K-0.0279*X_C)*(K+0.2496*X_C)-KKK   )  /  (3.0*KK)   );
    }
  printf("%f\t \t%f %f\n",Comp_C,X_C,lp_i); //uncomment for testing
  
  Comp_C = X_C*4;
  step = 0.0000001;
  while (lp_i < lp)
    {
      X_C = X_C + step;
      //lp_i = A + (  ((K-0.0279*X_C)*(K-0.0279*X_C)*(K+0.2496*X_C)-KKK)   /3*KK);
      lp_i = A + (  (   (K-0.0279*X_C)*(K-0.0279*X_C)*(K+0.2496*X_C)-KKK   )  /  (3.0*KK)   );
    }
  printf("%f\t \t%f %f\n",Comp_C,X_C,lp_i); //uncomment for testing
  Comp_C = X_C*21.8;   // (calc for aus1 but should be Approx. X_C x 100 x (12/55 )
  printf("C in Ferrite is %f mole fraction\n",X_C);
  printf("C in Ferrite is %f Wt%\n",Comp_C);
}

warn()
{
printf("\nWarning composition is fixed inside program! You need to edit the source code.\n\n");
printf("\nComposition range used by Dyson and Holmes (1970) for austenite lattice parameter\n");
printf("C   0.004 to  0.126 wt%\n");
printf("N   0.006 to  0.289 wt%\n");
printf("Mn  0.89  to  8.55  wt%\n");
printf("Si  0.13  to  4.15  wt%\n");
printf("Cr 15.4   to 19.60 wt%\n");
printf("Ni  7.7   to 26.00  wt%\n");
printf("Al <0.01  to  1.95 wt%\n");
printf("Ti <0.01  to  1.61 wt%\n");
printf("V  <0.01  to  3.53 wt%\n");
printf("Co <0.01  to  7.97 wt%\n");
printf("Cu <0.01  to  2.24 wt%\n");
printf("Nb <0.01  to  1.21 wt%\n");
printf("Mo <0.01  to  3.73 wt%\n");
printf("W  <0.01  to  3.98 wt%\n");
printf("Ferrite data is from various publications, see Bhadeshia etal Stress Induced bainite transformation in steel\n");
}

