/*
   This file belongs to Aeneas. Aeneas is a GNU package released under GPL 3 license.
   This code is a simulator for Submicron 3D Semiconductor Devices. 
   It implements the Monte Carlo transport in 3D tetrahedra meshes
   for the simulation of the semiclassical Boltzmann equation for both electrons.
   It also includes all the relevant quantum effects for nanodevices.

   Copyright (C) 2007 Jean Michel Sellier <sellier@dmi.unict.it>
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

// Created on : 18 june 2007, Siracusa, Jean Michel Sellier
// Last modified : 16 august 2007, Siracusa, Jean Michel Sellier

// This subroutine open the file called "file.inp" where
// the simulated device is described.

void read_input_file(void)
{
  int index;
  double dum;
  char s[200];
  FILE *fp;
    
// some resets before we load the input file...
  TEMPO=0.;
  DDMAX=0.;
  IIFLAG=NO; // no impact ionization as default
  Quantum_Flag=0; // no quantum effects taken into account (standard)
  NHTFLAG=WRITE; // compute and save the neighbourhood table as default
  POISSONUPDATEFLAG=YES; // the Poisson equation is updated as default
  SAVEPARTICLESFLAG=YES; // save particles as default
  SAVEPARTICLESFORMAT=ALL; // save all particles output format as default
  SAVEFIELDSFLAG=YES; // save fields as default
  SAVEFIELDSFORMAT=ALL; // save all format as default

//  RELATIVEDISTANCESFLAG=WRITE; // compute and save relative distances as default
  for(index=0;index<Ng;index++) VIC[index]=0.;
  for(index=0;index<Ng;index++) i_front[index]=NOCONTACT;
  for(index=0;index<Ne;index++) i_dom[index]=SILICON;
  for(index=0;index<Ne;index++) ND[index]=NA[index]=0.;

  for(index=0;index<NOAMTIA;index++) XVAL[index]=0.2;

  fp=fopen("file.inp","r");
  if(fp==NULL){
    printf("read_input_file error : problems in opening file.inp!\n");
    system("PAUSE");
    exit(0);
  }
  
  printf("\nProcessing the input file...\n");
  printf("******************************\n");
  while(!feof(fp)){
// read the current row
    fscanf(fp,"%s",s);
// if row is a comment then read it and ignore it
    if(strcmp(s,"#")==0){
      fgets(s,80,fp);
      printf("COMMENT ---> %s",s);
    } else if(strcmp(s,"TIMESTEP")==0){
      fscanf(fp,"%lf",&dum);
      DT=dum;
      if(DT<=0.){
        printf("read_input_file error : negative time step!\n");
        system("PAUSE");
        exit(0);
      }
      printf("TIMESTEP ---> %g",DT);
    } else if(strcmp(s,"FINALTIME")==0){
      fscanf(fp,"%lf",&dum);
      TF=dum;
      if(TF<=0.){
        printf("read_input_file error : negative final time!\n");
        system("PAUSE");
        exit(0);
      } 
      printf("FINAL TIME = %lg ---> Ok\n",TF);      
    } else if(strcmp(s,"MEDIA")==0){
      fscanf(fp,"%d",&MEAN);
      if(MEAN<0){
        printf("read_input_file error : number of media is negative!\n");
        system("PAUSE");
        exit(0);
      }
      printf("MEDIA = %d ---> Ok\n",MEAN);
      } else if(strcmp(s,"LATTICETEMPERATURE")==0){
        fscanf(fp,"%lf",&TL);
        if(TL<=0.){
          printf("read_input_file error : not valid lattice temperature!\n");
          exit(EXIT_FAILURE);
        }
        printf("LATTICE TEMPERATURE = %g ---> Ok\n",TL);
      } else if(strcmp(s,"SAVEEVERYNUMSTEPS")==0){
        fscanf(fp,"%d",&every_num_steps);
        printf("SAVE EVERY %d STEPS ---> Ok\n",every_num_steps);
      }  else if(strcmp(s,"CIMP")==0){
        fscanf(fp,"%lf",&CIMP);
        if(CIMP<0.){
          printf("read_input_file error : not valid impurity concentration\n");
          system("PAUSE");
          exit(0);
        }
        printf("CIMP = %g ---> Ok\n",CIMP);
      } else if(strcmp(s,"CONTACT")==0){
        int type;
        double xi,xf;
        double yi,yf;
        double zi,zf;
        double volt;
        fscanf(fp,"%s",s);
        if(strcmp(s,"X")==0) fscanf(fp,"%lf %lf",&xi,&xf);
        else{
          printf("read_input_file error : X contact not specified!\n");
          system("PAUSE");
          exit(0);            
        }
        fscanf(fp,"%s",s);
        if(strcmp(s,"Y")==0) fscanf(fp,"%lf %lf",&yi,&yf);
        else{
          printf("read_input_file error : Y contact not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%s",s);
        if(strcmp(s,"Z")==0) fscanf(fp,"%lf %lf",&zi,&zf);
        else{
          printf("read_input_file error : Z contact not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%s",s);
        if(strcmp(s,"OHMIC")==0){
          type=OHMIC;
          fscanf(fp,"%lf",&volt);
        }
        else if(strcmp(s,"SCHOTTKY")==0){
          type=SCHOTTKY;
          fscanf(fp,"%lf",&volt);
        }
        else if(strcmp(s,"INSULATOR")==0) type=INSULATOR;
        else{
          printf("read_input_file error : unknown specified contact!\n");
          printf("contact %s is unknown!\n",s);
          system("PAUSE");
          exit(0);
        }
        if(type==OHMIC || type==SCHOTTKY)
          printf("CONTACT X=[%g,%g] Y=[%g,%g] Z=[%g,%g] %s %g volts ---> Ok\n",
                 xi,xf,yi,yf,zi,zf,s,volt);
        if(type==INSULATOR)
          printf("CONTACT X=[%g,%g] Y=[%g,%g] Z=[%g,%g] %s ---> Ok\n",
                 xi,xf,yi,yf,zi,zf,s);
        for(index=0;index<Ng;index++) 
           if((xi<=coord[0][index]) &&(coord[0][index]<=xf) &&
              (yi<=coord[1][index]) &&(coord[1][index]<=yf) &&
              (zi<=coord[2][index]) &&(coord[2][index]<=zf)){
             VIC[index]=volt;
             i_front[index]=type;
           }
      } else if(strcmp(s,"STATISTICALWEIGHT")==0){
        fscanf(fp,"%d",&NP1);
        printf("STATISTICAL WEIGHT = %d ---> Ok\n",NP1);
      } else if(strcmp(s,"POISSONSOLVER")==0){
        fscanf(fp,"%d",&itol);
        printf("POISSONSOLVER %d ---> Ok\n",itol);
      } else if(strcmp(s,"POISSONTOLLERANCE")==0){
        fscanf(fp,"%lf",&tol);
        printf("POISSONTOLLERANCE %g ---> Ok\n",tol);
      } else if(strcmp(s,"POISSONITMAX")==0){
        fscanf(fp,"%d",&itmax);
        printf("POISSONITMAX %d ---> Ok\n",itmax);
      } else if(strcmp(s,"MATERIAL")==0){
        int type;
        double xi,xf;
        double yi,yf;
        double zi,zf;
        fscanf(fp,"%s",s);
        if(strcmp(s,"X")==0) fscanf(fp,"%lf %lf",&xi,&xf);
        else{
          printf("read_input_file error : X material not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%s",s);
        if(strcmp(s,"Y")==0) fscanf(fp,"%lf %lf",&yi,&yf);
        else{
          printf("read_input_file error : Y material not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%s",s);
        if(strcmp(s,"Z")==0) fscanf(fp,"%lf %lf",&zi,&zf);
        else{
          printf("read_input_file error : Z material not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%s",s);
        if(strcmp(s,"SILICON")==0)        type=SILICON;
        else if(strcmp(s,"GAAS")==0)      type=GAAS;
        else if(strcmp(s,"GERMANIUM")==0) type=GERMANIUM;
        else if(strcmp(s,"INSB")==0)      type=INSB;
        else if(strcmp(s,"ALSB")==0)      type=ALSB;
        else if(strcmp(s,"ALAS")==0)      type=ALAS;
        else if(strcmp(s,"ALP")==0)       type=ALP;
        else if(strcmp(s,"GAP")==0)       type=GAP;
        else if(strcmp(s,"GASB")==0)      type=GASB;
        else if(strcmp(s,"INAS")==0)      type=INAS;
        else if(strcmp(s,"INP")==0)       type=INP;
        else if(strcmp(s,"SIO2")==0)      type=SIO2;
        else if(strcmp(s,"ALxINxSB")==0){
          type=ALXINXSB;
          fscanf(fp,"%lf",&dum);
          if(XVAL[type]<=0.){printf("read_input_file error : x negative for AlxInxSb!\n");
                       system("PAUSE");
                       exit(0);
                      }
          if(XVAL[type]>1.){printf("read_input_file error : x greater than 1.0 for AlxInxSb!\n");
                       system("PAUSE");
                       exit(0);
                      }
          XVAL[type]=dum;
          printf("AlxInxSb X = %g\n",XVAL[type]);
        }
        else if(strcmp(s,"ALxIN1-xSB")==0){
          type=ALXIN1XSB;
          fscanf(fp,"%lf",&dum);
          if(XVAL[type]<=0.){printf("read_input_file error : x negative for AlxIn(1-x)Sb!\n");
                       system("PAUSE");
                       exit(0);
                      }
          if(XVAL[type]>1.){printf("read_input_file error : x greater than 1.0 for AlxIn(1-x)Sb!\n");
                       system("PAUSE");
                       exit(0);
                      }
          XVAL[type]=dum;
          printf("AlxIn(1-x)Sb X = %g\n",XVAL[type]);
        }
        else{
          printf("read_input_file error : unknown specified material!\n");
          printf("material %s is unknown!\n",s);
          system("PAUSE");
          exit(0);
        }
        printf("MATERIAL %s X=[%g,%g] Y=[%g,%g] Z=[%g,%g] ---> Ok\n",s,xi,xf,yi,
                                                                     yf,zi,zf);
        for(index=0;index<Ne;index++){
           double xc,yc,zc;
           xc=0.25*(coord[0][noeud_geo[0][index]-1]+coord[0][noeud_geo[1][index]-1]
             +coord[0][noeud_geo[2][index]-1]+coord[0][noeud_geo[3][index]-1]);
           yc=0.25*(coord[1][noeud_geo[0][index]-1]+coord[1][noeud_geo[1][index]-1]
             +coord[1][noeud_geo[2][index]-1]+coord[1][noeud_geo[3][index]-1]);
           zc=0.25*(coord[2][noeud_geo[0][index]-1]+coord[2][noeud_geo[1][index]-1]
             +coord[2][noeud_geo[2][index]-1]+coord[2][noeud_geo[3][index]-1]);
           if((xi<=xc) && (xc<=xf) && (yi<=yc) &&(yc<=yf) && (zi<=zc) &&(zc<=zf))
             i_dom[index]=type;
        }
      } else if(strcmp(s,"DONORDENSITY")==0){
        double xi,xf;
        double yi,yf;
        double zi,zf;
        double conc;
        fscanf(fp,"%s",s);
        if(strcmp(s,"X")==0) fscanf(fp,"%lf %lf",&xi,&xf);
        else{
          printf("read_input_file error : X donordensity not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%s",s);
        if(strcmp(s,"Y")==0) fscanf(fp,"%lf %lf",&yi,&yf);
        else{
          printf("read_input_file error : Y donordensity not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%s",s);
        if(strcmp(s,"Z")==0) fscanf(fp,"%lf %lf",&zi,&zf);
        else{
          printf("read_input_file error : Z donordensity not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%lf",&conc);
        if(DDMAX<conc) DDMAX=conc;
//        printf("DDMAX=%g\n",DDMAX);
        for(index=0;index<Ne;index++){
           double xc,yc,zc;
           xc=0.25*(coord[0][noeud_geo[0][index]-1]+coord[0][noeud_geo[1][index]-1]
             +coord[0][noeud_geo[2][index]-1]+coord[0][noeud_geo[3][index]-1]);
           yc=0.25*(coord[1][noeud_geo[0][index]-1]+coord[1][noeud_geo[1][index]-1]
             +coord[1][noeud_geo[2][index]-1]+coord[1][noeud_geo[3][index]-1]);
           zc=0.25*(coord[2][noeud_geo[0][index]-1]+coord[2][noeud_geo[1][index]-1]
             +coord[2][noeud_geo[2][index]-1]+coord[2][noeud_geo[3][index]-1]);
           if((xi<=xc) && (xc<=xf) && (yi<=yc) &&(yc<=yf) && (zi<=zc) &&(zc<=zf)){
             ND[index]=conc;
             NE[noeud_geo[0][index]-1]=conc;
             NE[noeud_geo[1][index]-1]=conc;
             NE[noeud_geo[2][index]-1]=conc;
             NE[noeud_geo[3][index]-1]=conc;
           }
        }
        printf("DONORDENSITY X=[%g,%g] Y=[%g,%g] Z=[%g,%g] %g ---> Ok\n",
                xi,xf,yi,yf,zi,zf,conc);
      } else if(strcmp(s,"ACCEPTORDENSITY")==0){
        double xi,xf;
        double yi,yf;
        double zi,zf;
        double conc;
        fscanf(fp,"%s",s);
        if(strcmp(s,"X")==0) fscanf(fp,"%lf %lf",&xi,&xf);
        else{
          printf("read_input_file error : X acceptordensity not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%s",s);
        if(strcmp(s,"Y")==0) fscanf(fp,"%lf %lf",&yi,&yf);
        else{
          printf("read_input_file error : Y acceptordensity not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%s",s);
        if(strcmp(s,"Z")==0) fscanf(fp,"%lf %lf",&zi,&zf);
        else{
          printf("read_input_file error : Z acceptordensity not specified!\n");
          system("PAUSE");
          exit(0);
        }
        fscanf(fp,"%lf",&conc);
        for(index=0;index<Ne;index++){
           double xc,yc,zc;
           xc=0.25*(coord[0][noeud_geo[0][index]-1]+coord[0][noeud_geo[1][index]-1]
             +coord[0][noeud_geo[2][index]-1]+coord[0][noeud_geo[3][index]-1]);
           yc=0.25*(coord[1][noeud_geo[0][index]-1]+coord[1][noeud_geo[1][index]-1]
             +coord[1][noeud_geo[2][index]-1]+coord[1][noeud_geo[3][index]-1]);
           zc=0.25*(coord[2][noeud_geo[0][index]-1]+coord[2][noeud_geo[1][index]-1]
             +coord[2][noeud_geo[2][index]-1]+coord[2][noeud_geo[3][index]-1]);
           if((xi<=xc) && (xc<=xf) && (yi<=yc) &&(yc<=yf) && (zi<=zc) &&(zc<=zf)){
             NA[index]=conc;
//             NH[noeud_geo[0][index]-1]=conc;
//             NH[noeud_geo[1][index]-1]=conc;
//             NH[noeud_geo[2][index]-1]=conc;
//             NH[noeud_geo[3][index]-1]=conc;
           }
        }
        printf("ACCEPTORDENSITY X=[%g,%g] Y=[%g,%g] Z=[%g,%g] %g ---> Ok\n",
                xi,xf,yi,yf,zi,zf,conc);
      } else if(strcmp(s,"NOQUANTUMEFFECTS")==0){
         Quantum_Flag=0;
         printf("QUANTUM EFFECTS = NO --->Ok\n");
      } else if(strcmp(s,"QUANTUMEFFECTS")==0){
         Quantum_Flag=1;
        printf("QUANTUM EFFECTS = YES --->Ok\n");
      } else if(strcmp(s,"LOADMESH")==0){
         fscanf(fp,"%s",s);
         {int h; for(h=0;h<100;h++) MESHNAME[h]=s[h];}
         printf("\n\nLoading the input mesh file...\n");
         load_mesh(s); // this row has to be putted before everything calculation!!!
         printf("Mesh input file correctly processed...\n\n");
      } else if(strcmp(s,"LOADMSH")==0){
         printf("\n\nLoading the input msh file...\n");
         fscanf(fp,"%s",s);
         {int h; for(h=0;h<100;h++) MESHNAME[h]=s[h];}
         load_mshV1(s); // this subroutine is recommended only for GMSH experts
         printf("msh input file correctly processed...\n\n");
      } else if(strcmp(s,"NEIGHBOURHOODTABLE")==0){
         fscanf(fp,"%s",s);
         if(strcmp(s,"READ")==0){
           NHTFLAG=READ;
           printf("NEIGHBOURHOOD = READ ---> Ok\n");
         }
         if(strcmp(s,"WRITE")==0){
           NHTFLAG=WRITE;
           printf("NEIGHBOURHOOD = WRITE ---> Ok\n");
         }
      } else if(strcmp(s,"POISSONUPDATE")==0){
         fscanf(fp,"%s",s);
         if(strcmp(s,"YES")==0){
           POISSONUPDATEFLAG=YES;
           printf("POISSON UPDATE = YES ---> Ok\n");
         }
         if(strcmp(s,"NO")==0){
           POISSONUPDATEFLAG=NO;
           printf("POISSON UPDATE = NO ---> Ok\n");
         }
      } else if(strcmp(s,"SAVEPARTICLES")==0){
         fscanf(fp,"%s",s);
         if(strcmp(s,"NO")==0){
           SAVEPARTICLESFLAG=NO;
           printf("DO NOT SAVE PARTICLES ---> Ok\n");
         }
         if(strcmp(s,"YES")==0){
           SAVEPARTICLESFLAG=YES;
           fscanf(fp,"%s",s);
           if(strcmp(s,"POINT3D")==0) SAVEPARTICLESFORMAT=POINT3D;
           if(strcmp(s,"MESH")==0) SAVEPARTICLESFORMAT=MESH;
           if(strcmp(s,"ALL")==0) SAVEPARTICLESFORMAT=ALL;
           printf("PARTICLES OUTPUT SELECTED = %s ---> Ok\n",s);
        }
      } else if(strcmp(s,"SAVEFIELDS")==0){
         fscanf(fp,"%s",s);
         if(strcmp(s,"NO")==0){
           SAVEFIELDSFLAG=NO;
           printf("DO NOT SAVE FIELDS ---> Ok\n");
         }
         if(strcmp(s,"YES")==0){
           SAVEFIELDSFLAG=YES;
           fscanf(fp,"%s",s);
           if(strcmp(s,"VTK")==0) SAVEFIELDSFORMAT=VTK;
           if(strcmp(s,"MESH")==0) SAVEFIELDSFORMAT=MESH;
           if(strcmp(s,"ALL")==0) SAVEFIELDSFORMAT=ALL;
           printf("FIELDS OUTPUT SELECTED = %s ---> Ok\n",s);
         }
      } else if(strcmp(s,"DONORDENSITYONELEMENTS")==0){
         int idum;
         fscanf(fp,"%d",&idum);
         fscanf(fp,"%lf",&dum);
         for(index=0;index<Ne;index++) if(i_dom[index]==idum) ND[index]=dum;
         printf("DONORDENSITYONELEMENTS %g %d ---> Ok\n",dum,idum);
      } else if(strcmp(s,"IMPACTIONIZATION")==0){
         fscanf(fp,"%s",s);
         if(strcmp(s,"YES")==0) IIFLAG=YES;
         if(strcmp(s,"NO")==0) IIFLAG=NO;
         printf("IMPACT IONIZATION = %s ---> Ok\n",s);
      }
      
      /* else if(strcmp(s,"RELATIVEDISTANCES")==0){
         fscanf(fp,"%s",s);
         if(strcmp(s,"WRITE")==0){
           RELATIVEDISTANCESFLAG=WRITE;
           printf("RELATIVE DISTANCES = WRITE ---> Ok\n");
         }
         if(strcmp(s,"READ")==0){
           RELATIVEDISTANCESFLAG=READ;
           printf("RELATIVEDISTANCES = READ ---> Ok\n");
         }
      }*/



// no detection of syntax error in the input file...
/*      else{
            printf("***********\n");
            printf("%s\n",s);
            printf("***********\n");
            printf("syntax error in input file!\n");
            system("PAUSE");
            exit(0);
        }
*/
  } // end of while loop
  printf("End of input file.\n");
  printf("******************\n\n");
  
// THE FOLLOWING ROWS HAS TO BE SPECIFIED BY THE USER!!!
// example : a silicon diode...
// ****************************
//  DT=0.015e-12; // 1 femtosecond
//  TF=10.*DT; // 1 picosecond
//  MEAN=500; // Time of Mean Average
//  TL=300.; // Kelvin
//  every_num_steps=2;
//  CIMP=1.e14; // 1/m^3
// applied potential
//  for(index=0;index<Ng;index++) if(coord[2][index]==1.0e-6) VIC[index]=2.0; // Volt
//  DDMAX=1.e23; // maximum doping in the device (1/meter^3)
//  NP1=25;    // number of particles per tetrahedra in the maximum doped elements
            // (i.e. statistical weight)
//  itol=4; // for poisson linear solver
//  tol=1.e-16; // for poisson linear solver
//  itmax=1500; // for poisson linear solver
//  for(index=0;index<Ne;index++) i_dom[index]=SILICON;
// definition of the donor density in each element of the mesh
//  for(index=0;index<Ne;index++){
//     double xc,yc,zc;
//     xc=0.25*(coord[0][noeud_geo[0][index]-1]+coord[0][noeud_geo[1][index]-1]
//             +coord[0][noeud_geo[2][index]-1]+coord[0][noeud_geo[3][index]-1]);
//     yc=0.25*(coord[1][noeud_geo[0][index]-1]+coord[1][noeud_geo[1][index]-1]
//             +coord[1][noeud_geo[2][index]-1]+coord[1][noeud_geo[3][index]-1]);
//     zc=0.25*(coord[2][noeud_geo[0][index]-1]+coord[2][noeud_geo[1][index]-1]
//             +coord[2][noeud_geo[2][index]-1]+coord[2][noeud_geo[3][index]-1]);
//     if(zc<=0.3e-6 || zc>=0.7e-6) ND[index]=DDMAX;
//     else ND[index]=1.e22;
//  }
//  ND[19]=DDMAX;
//  for(index=0;index<Ng;index++){
//     i_front[index]=NOCONTACT;
//     if(coord[0][index]==0. || coord[0][index]==0.3e-6) i_front[index]=INSULATOR;
//     if(coord[1][index]==0. || coord[1][index]==0.3e-6) i_front[index]=INSULATOR;
//     if(coord[2][index]==0. || coord[2][index]==1.0e-6) i_front[index]=OHMIC;
//  }
// ******************************************************    
  fclose(fp);
}
