/*
   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 : 11 june 2007, Siracusa, Jean Michel Sellier
// Last modified : 16 august 2007, Siracusa, Jean Michel Sellier

// this is the ensemble MC algorithm

void ensemble_montecarlo(void)
{
 long int n=1;
 int i,ni,j;
 double tdt,ti,tau;

 tdt=TEMPO+DT;

 do{
    IV=(int)(P[n][0]);
    KX=P[n][1];
    KY=P[n][2];
    KZ=P[n][3];
    TS=P[n][4];
    L[0]=P[n][5];
    L[1]=P[n][6];
    L[2]=P[n][7];
    L[3]=P[n][8];
// printf("before  %g %g %g %g %g\n",L[0],L[1],L[2],L[3],L[0]+L[1]+L[2]+L[3]);
    EL=(int)(P[n][9]);
//    if(i_dom[EL]==SIO2) printf("SIO2!!!\n");
    ti=TEMPO;

    while(TS<=tdt){
       tau=TS-ti;
//       printf("tau = %g\n",tau);
       drift(tau);
//       printf("drift...scat\n");
       scat(i_dom[EL]);
       ti=TS;
       TS=ti-log(rnd())/GM[i_dom[EL]];
    }
    tau=tdt-ti;
    drift(tau);

// ==============================================
     if(IV!=9){
       P[n][0]=IV;
       P[n][1]=KX;
       P[n][2]=KY;
       P[n][3]=KZ;
       P[n][4]=TS;
       P[n][5]=L[0];
       P[n][6]=L[1];
       P[n][7]=L[2];
       P[n][8]=L[3];
       P[n][9]=EL;
       n++;
     }
// if IV=9 then the super-particle has been eliminated
     if(IV==9){
       for(i=1;i<=9;i++) P[n][i]=P[INUM][i];
       INUM--;
     }
//  printf("n = %d INUM = %d\n",n,INUM);
  }while(n<INUM);

// computes the number of electrons in every element
  for(i=0;i<Ne;i++) NOELEC[i]=0.;
  for(n=1;n<=INUM;n++){
   int el;
   el=(int)(P[n][9]);
   if(i_dom[el]==SIO2) NOELEC[el]=0;
   if(i_dom[el]!=SIO2) NOELEC[el]++;
  }
//  for(i=0;i<Ne;i++) printf("NOELEC[%d]=%d\n",i,NOELEC[i]);
  
// create particles
// ================
// this part of the code maintains a perfect charge neutrality
// on the ohmic contacts.
  for(i=0;i<Ne;i++){
   int np;
   if((i_front[noeud_geo[0][i]-1]==OHMIC 
    && i_front[noeud_geo[1][i]-1]==OHMIC 
    && i_front[noeud_geo[2][i]-1]==OHMIC) ||
    (i_front[noeud_geo[0][i]-1]==OHMIC
    && i_front[noeud_geo[2][i]-1]==OHMIC
    && i_front[noeud_geo[3][i]-1]==OHMIC) ||
    (i_front[noeud_geo[0][i]-1]==OHMIC
    && i_front[noeud_geo[1][i]-1]==OHMIC
    && i_front[noeud_geo[3][i]-1]==OHMIC) ||
    (i_front[noeud_geo[1][i]-1]==OHMIC
    && i_front[noeud_geo[2][i]-1]==OHMIC
    && i_front[noeud_geo[3][i]-1]==OHMIC)){
// np = the number of electrons that one should always find in the i-th element
// (i.e. for maintaining the charge-neutrality).
    np=(int)(ND[i]*VOLUME[i]/EPP[i]+0.5);
    if(ND[i]==0.) np=0;
// the number of electrons to be injected in order to maintain the
// charge neutrality.
    ni=np-NOELEC[i];
//    ni/=2; // <--- "Tomizawa's trick"
//    printf("ni = %d np = %d noelec = %d\n",ni,np,NOELEC[i]);
    if(ni>0){
      n=0;
      for(j=1;j<=ni;j++){
// the following "if" is extremely important in order to avoid
// particle creations in the SiO2 regions!
        if(i_dom[i]!=SIO2){
         n++;
         creation(i,TEMPO);
         P[INUM+n][0]=IV;
         P[INUM+n][1]=KX;
         P[INUM+n][2]=KY;
         P[INUM+n][3]=KZ;
         P[INUM+n][4]=TS;
         P[INUM+n][5]=L[0];
         P[INUM+n][6]=L[1];
         P[INUM+n][7]=L[2];
         P[INUM+n][8]=L[3];
         P[INUM+n][9]=i;
        }
      } // end of j-cycle
      INUM += n;
    } // end of if(ni>0) control
   } // end of if i_front...
  } // end of i-cycle

 printf("Actual number of electron super-particles = %d\n",INUM);
 if(INUM>NPMAX){
   printf("ensemble_montecarlo : too big actual number of particles\n");
   exit(EXIT_FAILURE);
 }
}
