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

// we calculate here the quantum Bohm potential.
// this approach avoids one the use of the Scroedinger equation
// which is computationally heavy. 
// this method is directly relied to the pilot-wave theory
// of quantum mechanics.

// See famous Bohm's paper for more informations

void Bohm_potential(void)
{
 int i,j;
 double *v;
 double *nabla2R;
 double *R;
 double *ac[4],*bc[4],*cc[4],*dc[4];
 double *xi[3], l[4];
 double dx,dy,dz;
 
// infinitesimal increments = 5 Angstrom
 dx=0.5e-9; dy=0.5e-9; dz=0.5e-9;
 
 v=malloc((Ng+1)*sizeof(double));
 nabla2R=malloc((Ng+1)*sizeof(double));
 R=malloc((Ng+1)*sizeof(double));
 for(i=0;i<3;i++) xi[i]=malloc((Ne+1)*sizeof(double));
 for(i=0;i<4;i++){
   ac[i]=malloc((Ne+1)*sizeof(double));
   bc[i]=malloc((Ne+1)*sizeof(double));
   cc[i]=malloc((Ne+1)*sizeof(double));
   dc[i]=malloc((Ne+1)*sizeof(double));
 }

// barycentric coordinates of the Guass point
 l[0]=0.25;  l[1]=0.25;  l[2]=0.25;  l[3]=0.25;

// calculation of the center of mass coordinates for every element
 for(i=0;i<Ne;i++){
      xi[0][i]=l[0]*coord[0][noeud_geo[0][i]-1]
              +l[1]*coord[0][noeud_geo[1][i]-1]
              +l[2]*coord[0][noeud_geo[2][i]-1]
              +l[3]*coord[0][noeud_geo[3][i]-1];
      xi[1][i]=l[0]*coord[1][noeud_geo[0][i]-1]
              +l[1]*coord[1][noeud_geo[1][i]-1]
              +l[2]*coord[1][noeud_geo[2][i]-1]
              +l[3]*coord[1][noeud_geo[3][i]-1];
      xi[2][i]=l[0]*coord[2][noeud_geo[0][i]-1]
              +l[1]*coord[2][noeud_geo[1][i]-1]
              +l[2]*coord[2][noeud_geo[2][i]-1]
              +l[3]*coord[2][noeud_geo[3][i]-1];
//    printf("%g %g %g\n",xi[0][j][i],xi[1][j][i],xi[2][j][i]);
    }

// calculation of the theta functions for every element
 for(i=0;i<Ne;i++){
    int l;
    int n=4;
    int indx[5];
    double d;
    double a[5][5];
    double b[5];

// definition of the a matrix for the linear system
    {int k;
     for(k=0;k<4;k++){
       a[k+1][1]=coord[0][noeud_geo[k][i]-1];
       a[k+1][2]=coord[1][noeud_geo[k][i]-1];
       a[k+1][3]=coord[2][noeud_geo[k][i]-1];
       a[k+1][4]=1.;
     }}
// LU decomposition of the A matrix
#include "../linear_solver/ludcmp.h"
    for(l=0;l<4;l++){
      if(l==0){b[1]=1.;b[2]=0.;b[3]=0.;b[4]=0.;}
      if(l==1){b[1]=0.;b[2]=1.;b[3]=0.;b[4]=0.;}
      if(l==2){b[1]=0.;b[2]=0.;b[3]=1.;b[4]=0.;}
      if(l==3){b[1]=0.;b[2]=0.;b[3]=0.;b[4]=1.;}
#include "../linear_solver/lubksb.h"
      ac[l][i]=b[1]; bc[l][i]=b[2]; cc[l][i]=b[3]; dc[l][i]=b[4];
// printf("%g %g %g %g\n",b[1],b[2],b[3],b[4]);
    } // end of l-cycle

// definition of R field on each node
    for(j=0;j<4;j++) R[noeud_geo[j][i]-1]=sqrt(NE[noeud_geo[j][i]-1]);
 } // end of i-cycle

// just in case...
 for(i=0;i<Ng;i++) nabla2R[i]=0.;

// definition of laplacian of R on each node
 for(i=0;i<Ne;i++){
   double h1,h2,h3;
// second order finite difference scheme
   h1=R[noeud_geo[0][i]-1]*(ac[0][i]*(xi[0][i]+dx)+bc[0][i]*xi[1][i]+cc[0][i]*xi[2][i]+dc[0][i])
     +R[noeud_geo[1][i]-1]*(ac[1][i]*(xi[0][i]+dx)+bc[1][i]*xi[1][i]+cc[1][i]*xi[2][i]+dc[1][i])
     +R[noeud_geo[2][i]-1]*(ac[2][i]*(xi[0][i]+dx)+bc[2][i]*xi[1][i]+cc[2][i]*xi[2][i]+dc[2][i])
     +R[noeud_geo[3][i]-1]*(ac[3][i]*(xi[0][i]+dx)+bc[3][i]*xi[1][i]+cc[3][i]*xi[2][i]+dc[3][i]);
   h2=R[noeud_geo[0][i]-1]*(ac[0][i]*xi[0][i]+bc[0][i]*xi[1][i]+cc[0][i]*xi[2][i]+dc[0][i])
     +R[noeud_geo[1][i]-1]*(ac[1][i]*xi[0][i]+bc[1][i]*xi[1][i]+cc[1][i]*xi[2][i]+dc[1][i])
     +R[noeud_geo[2][i]-1]*(ac[2][i]*xi[0][i]+bc[2][i]*xi[1][i]+cc[2][i]*xi[2][i]+dc[2][i])
     +R[noeud_geo[3][i]-1]*(ac[3][i]*xi[0][i]+bc[3][i]*xi[1][i]+cc[3][i]*xi[2][i]+dc[3][i]);
   h3=R[noeud_geo[0][i]-1]*(ac[0][i]*(xi[0][i]-dx)+bc[0][i]*xi[1][i]+cc[0][i]*xi[2][i]+dc[0][i])
     +R[noeud_geo[1][i]-1]*(ac[1][i]*(xi[0][i]-dx)+bc[1][i]*xi[1][i]+cc[1][i]*xi[2][i]+dc[1][i])
     +R[noeud_geo[2][i]-1]*(ac[2][i]*(xi[0][i]-dx)+bc[2][i]*xi[1][i]+cc[2][i]*xi[2][i]+dc[2][i])
     +R[noeud_geo[3][i]-1]*(ac[3][i]*(xi[0][i]-dx)+bc[3][i]*xi[1][i]+cc[3][i]*xi[2][i]+dc[3][i]);
   for(j=0;j<4;j++) nabla2R[noeud_geo[j][i]-1]+=(h1-2.*h2+h3)/(dx*dx);
   h1=R[noeud_geo[0][i]-1]*(ac[0][i]*xi[0][i]+bc[0][i]*(xi[1][i]+dy)+cc[0][i]*xi[2][i]+dc[0][i])
     +R[noeud_geo[1][i]-1]*(ac[1][i]*xi[0][i]+bc[1][i]*(xi[1][i]+dy)+cc[1][i]*xi[2][i]+dc[1][i])
     +R[noeud_geo[2][i]-1]*(ac[2][i]*xi[0][i]+bc[2][i]*(xi[1][i]+dy)+cc[2][i]*xi[2][i]+dc[2][i])
     +R[noeud_geo[3][i]-1]*(ac[3][i]*xi[0][i]+bc[3][i]*(xi[1][i]+dy)+cc[3][i]*xi[2][i]+dc[3][i]);
   h2=R[noeud_geo[0][i]-1]*(ac[0][i]*xi[0][i]+bc[0][i]*xi[1][i]+cc[0][i]*xi[2][i]+dc[0][i])
     +R[noeud_geo[1][i]-1]*(ac[1][i]*xi[0][i]+bc[1][i]*xi[1][i]+cc[1][i]*xi[2][i]+dc[1][i])
     +R[noeud_geo[2][i]-1]*(ac[2][i]*xi[0][i]+bc[2][i]*xi[1][i]+cc[2][i]*xi[2][i]+dc[2][i])
     +R[noeud_geo[3][i]-1]*(ac[3][i]*xi[0][i]+bc[3][i]*xi[1][i]+cc[3][i]*xi[2][i]+dc[3][i]);
   h3=R[noeud_geo[0][i]-1]*(ac[0][i]*xi[0][i]+bc[0][i]*(xi[1][i]-dy)+cc[0][i]*xi[2][i]+dc[0][i])
     +R[noeud_geo[1][i]-1]*(ac[1][i]*xi[0][i]+bc[1][i]*(xi[1][i]-dy)+cc[1][i]*xi[2][i]+dc[1][i])
     +R[noeud_geo[2][i]-1]*(ac[2][i]*xi[0][i]+bc[2][i]*(xi[1][i]-dy)+cc[2][i]*xi[2][i]+dc[2][i])
     +R[noeud_geo[3][i]-1]*(ac[3][i]*xi[0][i]+bc[3][i]*(xi[1][i]-dy)+cc[3][i]*xi[2][i]+dc[3][i]);
   for(j=0;j<4;j++) nabla2R[noeud_geo[j][i]-1]+=(h1-2.*h2+h3)/(dy*dy);
   h1=R[noeud_geo[0][i]-1]*(ac[0][i]*xi[0][i]+bc[0][i]*xi[1][i]+cc[0][i]*(xi[2][i]+dz)+dc[0][i])
     +R[noeud_geo[1][i]-1]*(ac[1][i]*xi[0][i]+bc[1][i]*xi[1][i]+cc[1][i]*(xi[2][i]+dz)+dc[1][i])
     +R[noeud_geo[2][i]-1]*(ac[2][i]*xi[0][i]+bc[2][i]*xi[1][i]+cc[2][i]*(xi[2][i]+dz)+dc[2][i])
     +R[noeud_geo[3][i]-1]*(ac[3][i]*xi[0][i]+bc[3][i]*xi[1][i]+cc[3][i]*(xi[2][i]+dz)+dc[3][i]);
   h2=R[noeud_geo[0][i]-1]*(ac[0][i]*xi[0][i]+bc[0][i]*xi[1][i]+cc[0][i]*xi[2][i]+dc[0][i])
     +R[noeud_geo[1][i]-1]*(ac[1][i]*xi[0][i]+bc[1][i]*xi[1][i]+cc[1][i]*xi[2][i]+dc[1][i])
     +R[noeud_geo[2][i]-1]*(ac[2][i]*xi[0][i]+bc[2][i]*xi[1][i]+cc[2][i]*xi[2][i]+dc[2][i])
     +R[noeud_geo[3][i]-1]*(ac[3][i]*xi[0][i]+bc[3][i]*xi[1][i]+cc[3][i]*xi[2][i]+dc[3][i]);
   h3=R[noeud_geo[0][i]-1]*(ac[0][i]*xi[0][i]+bc[0][i]*xi[1][i]+cc[0][i]*(xi[2][i]-dz)+dc[0][i])
     +R[noeud_geo[1][i]-1]*(ac[1][i]*xi[0][i]+bc[1][i]*xi[1][i]+cc[1][i]*(xi[2][i]-dz)+dc[1][i])
     +R[noeud_geo[2][i]-1]*(ac[2][i]*xi[0][i]+bc[2][i]*xi[1][i]+cc[2][i]*(xi[2][i]-dz)+dc[2][i])
     +R[noeud_geo[3][i]-1]*(ac[3][i]*xi[0][i]+bc[3][i]*xi[1][i]+cc[3][i]*(xi[2][i]-dz)+dc[3][i]);
   for(j=0;j<4;j++) nabla2R[noeud_geo[j][i]-1]+=(h1-2.*h2+h3)/(dz*dz);
 }

 for(i=0;i<Ng;i++) v[i]=0.; // just in case...
 
// updates the potential by means of Bohm potential
 for(i=0;i<Ne;i++){
  for(j=0;j<4;j++)
   if(R[noeud_geo[j][i]-1]!=0.)
     V[noeud_geo[j][i]-1]+=-(HBAR*HBAR/(2.*MSTAR[i_dom[i]][1]*M*Q))
                         *nabla2R[noeud_geo[j][i]-1]/R[noeud_geo[j][i]-1];
// printf("QV = %g\n",-(HBAR*HBAR/(2.*MSTAR[i_dom[i]][1]*M*Q))*nabla2R[noeud_geo[0][i]-1]/R[noeud_geo[0][i]-1]);
//printf("QV = %g\n",V[noeud_geo[0][i]-1]);
 }
 
// free precedently allocated memory
 free(v);
 free(R);
 free(nabla2R);
 for(i=0;i<3;i++) free(xi[i]);
 for(i=0;i<4;i++){
   free(ac[i]);
   free(bc[i]);
   free(cc[i]);
   free(dc[i]);
 }
}
