00001 /* 00002 This file belongs to Aeneas. Aeneas is a GNU package released under GPL 3. 00003 This code is a simulator for Submicron 3D Semiconductor Devices. 00004 It implements the Monte Carlo transport in 3D tetrahedra meshes 00005 for the simulation of the semiclassical Boltzmann equation for both electrons. 00006 It also includes all the relevant quantum effects for nanodevices. 00007 00008 Copyright (C) 2007 Jean Michel Sellier <sellier@dmi.unict.it> 00009 00010 This program is free software; you can redistribute it and/or modify 00011 it under the terms of the GNU General Public License as published by 00012 the Free Software Foundation; either version 3, or (at your option) 00013 any later version. 00014 00015 This program is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 along with this program. If not, see <http://www.gnu.org/licenses/>. 00022 */ 00023 00024 // Created on : 08 june 2007, Siracusa, Jean Michel Sellier 00025 // Last modified : 16 september 2007, Siracusa, Jean Michel Sellier 00026 00027 // given a matrix a[1..n][1..n], this routine replaces it by the LU decomposition 00028 // of a rowwise permutation of itself. a and n are input. a is output, arranged 00029 // as a lu decomposition; indx[1..n] is an output vector that records the row 00030 // permutation effected by the partial pivoting; d is the output as +-1 depending 00031 // on whether the number of row interchanges was even or odd, respectively. 00032 // This routine is used in combination with lubksb to solve linear equations 00033 // or invert a matrix. 00034 00035 { 00036 int i, imax, j, k; 00037 double big, dum, sum, temp; 00038 double *vv; 00039 00040 // imax=0; // dummy value, just to avoid warnings during the compilation... 00041 00042 vv = malloc((n+1)*sizeof(double)); // vv[1..n] 00043 if(vv==NULL){ 00044 printf("ludcmp error : not enough memory!\n"); 00045 exit(0); 00046 } 00047 /* {int ii,jj; 00048 for(ii=1;ii<=4;ii++){ 00049 for(jj=1;jj<=4;jj++) printf("*[%d][%d] = %g ",ii,jj,a[ii][jj]); 00050 printf("\n"); 00051 }}*/ 00052 00053 d=1.0; 00054 for(i=1;i<=n;i++){ 00055 big=0.0; 00056 for(j=1;j<=n;j++) 00057 if((temp=fabs(a[i][j]))>big) big=temp; 00058 if(big==0.0){ 00059 int ii,jj; 00060 for(ii=1;ii<=4;ii++){ 00061 for(jj=1;jj<=4;jj++) printf("a[%d][%d] = %g ",ii,jj,a[ii][jj]); 00062 printf("\n"); 00063 } 00064 printf("ludcmp error : singular matrix!\n"); 00065 exit(0); 00066 } 00067 // non zero largest element 00068 vv[i]=1.0/big; // save the scaling 00069 } 00070 for(j=1;j<=n;j++){ 00071 for(i=1;i<j;i++){ 00072 sum=a[i][j]; 00073 for(k=1;k<i;k++) sum-=a[i][k]*a[k][j]; 00074 a[i][j]=sum; 00075 } 00076 big=0.0; // initialise for the search for largest pivot element 00077 for(i=j;i<=n;i++){ 00078 sum=a[i][j]; 00079 for(k=1;k<j;k++) sum-=a[i][k]*a[k][j]; 00080 a[i][j]=sum; 00081 if((dum=vv[i]*fabs(sum))>=big){ 00082 // Is the figure of merit for the pivot better than the best so far? 00083 big=dum; 00084 imax=i; 00085 } 00086 } 00087 if(j!=imax){ // do we need to interchage the row? 00088 for(k=1;k<=n;k++){ 00089 dum=a[imax][k]; 00090 a[imax][k]=a[j][k]; 00091 a[j][k]=dum; 00092 } 00093 d=-d; // ...and change the parity of d. 00094 vv[imax]=vv[j]; 00095 } 00096 indx[j]=imax; 00097 if(a[j][j]==0.0) a[j][j]=TINY; 00098 // if the pivot element is zero the matrix is singular (at least to the precision 00099 // of the algorithm). For some applications on singular matrices, it is desirable 00100 // to substitute TINY for zero. 00101 if(j!=n){ 00102 dum=1.0/(a[j][j]); 00103 for(i=j+1;i<=n;i++) a[i][j]*=dum; 00104 } 00105 } 00106 free(vv); 00107 } 00108