source: trunk/LMDZ.TITAN/libf/chimtitan/solve.c @ 3094

Last change on this file since 3094 was 1126, checked in by slebonnois, 11 years ago

SL: update of Titan photochemical module to include computation of chemistry up to 1300 km

File size: 4.0 KB
Line 
1/* matrix inversion */
2/* cf Numerical Recipes LU Method for equations numbers */
3/* GCCM */
4/* similaire a inv (GP) */
5/* la matrice a est inversee seulement sur le bloc [n0;n1][n0;n1] */
6
7#include "titan.h"
8
9void solve( double ***aa, int m, int n0, int n1 )
10{
11   int    i,ii,imax,j,k,l,ll;
12   double **a,aamax,dum,*indx,sum,**vv,tmp;
13   FILE   *out;
14
15   indx = dm1d( n0, n1 );
16   vv   = dm2d( n0, n1, n0, n1 );
17   a    = dm2d( n0, n1, n0, n1 );
18   imax = n0;
19
20   for( i = n0; i <= n1; i++ ) for( j = n0; j <= n1; j++ ) a[i][j]=aa[m][i][j];
21   
22   for( i = n0; i <= n1; i++ )
23   {
24      aamax = 0.0e0;
25      for( k = n0; k <= n1; k++ )
26         if( (tmp=fabs(a[i][k])) > aamax ) aamax = tmp;
27      if( aamax < 1.0e-20 )
28      {
29         out = fopen( "err.log", "a" );
30         fprintf( out, "Singular matrix. n0=%ld k=%ld aamax=%le\n",
31                        n0,k,aamax);
32         fclose( out );
33         exit(0);   
34/*         aamax = 1.e-30; */
35      }
36      vv[i][1] = 1.0e0 / aamax;   /* Save the scaling */
37/*
38      if( (aamax > 1.0e100)||(aamax < 1.0e-100) )
39      {
40         out = fopen( "err.log", "a" );
41         fprintf( out, "ATTENTION aamax = %le\n", aamax );
42         fclose( out );
43         exit( 0 );
44      }
45*/
46   }
47   for( k = n0; k <= n1; k++ )
48   {
49      for( i = n0; i < k; i++ )      /* This is equation 2.3.12 except for i = j */
50      {
51         sum = a[i][k];
52         for( l = n0; l < i; l++ )
53            sum -= ( a[i][l] * a[l][k] );
54         a[i][k] = sum;
55      }
56      aamax = 0.0e0;                 /* Initialize for the search for largest pivot element */
57      for( i = k; i <= n1; i++ )     /* This is i = j of equation 2.3.12 and */
58      {
59         sum = a[i][k];              /* i = J + 1,...,N of equation 2.3.13 */
60         for( l = n0; l < k; l++ )
61            sum -= ( a[i][l] * a[l][k] );
62         a[i][k] = sum;
63         dum        = vv[i][1] * fabs(sum); /* Figure of merit for the pivot */
64         if( dum >= aamax )          /* Is it better than the best so far ? */
65         {
66            imax  = i;
67            aamax = dum;
68         }
69      }
70      if( k != imax )                /* Do we need to interchange rows ? */
71      {
72         for( l = n0; l <= n1; l++ ) /* Yes, do so... */
73         {
74            dum        = a[imax][l];
75            a[imax][l] = a[k][l];
76            a[k][l]    = dum;
77         }
78         vv[imax][1] = vv[k][1];    /* Also interchange the scale factor */
79      }
80      indx[k] = imax;
81      if( fabs(a[k][k]) < 1.0e-20 )
82      {
83         out = fopen( "err.log", "a" );
84         fprintf( out, "Pivot too small. n0=%ld k=%ld fabs(a[k][k])=%le\n",
85                        n0,k,fabs(a[k][k]) );
86         fclose( out );
87         exit(0);   
88/*         a[k][k] = 1.e-20; */
89      }
90      if( k != n1 )                   /* If the pivot element is less than 1.0d-20 we */
91      {                               /* assume that the matrix is singular */
92          dum = a[k][k];              /* ( at least to the precision of the algorithm and the machine ) */
93         for( i = k+1; i <= n1; i++ ) /* Now, finally devide by the pivot element */
94            a[i][k] /= dum;
95      }
96   }                                  /* Go back to the next column in the reduction */
97
98   for( i = n0; i <= n1; i++ )
99   {
100      for( k = n0; k <= n1; k++ )
101         vv[i][k] = 0.0e0;
102      vv[i][i] = 1.0e0;
103   }
104
105   for( l = n0; l <= n1; l++ )
106   {
107      ii = n0-1;
108      for( i = n0; i <= n1; i++ )
109      {
110         ll    = indx[i];
111         sum   = vv[ll][l];
112         vv[ll][l] = vv[i][l];
113         if( ii != (n0-1) )
114            for( k = ii; k < i; k++ )
115               sum -= ( a[i][k] * vv[k][l] );
116         else if( sum != 0.0e0 ) ii = i;
117         vv[i][l] = sum;
118      }
119      for( i = n1; i >= n0; i-- )
120      {
121         sum = vv[i][l];
122         if( i < n1 )
123            for( k = i+1; k <= n1; k++ )
124               sum -= ( a[i][k] * vv[k][l] );
125         vv[i][l] = sum / a[i][i];
126      }
127   }
128         
129   for( i = n0; i <= n1; i++ ) 
130     for( l = n0; l <= n1; l++ ) 
131       aa[m][i][l]=vv[i][l];
132
133   fdm1d( indx, n0 );
134   fdm2d(   vv, n0, n1, n0 );
135   fdm2d(    a, n0, n1, n0 );
136}
Note: See TracBrowser for help on using the repository browser.