Show
Ignore:
Timestamp:
03/16/08 03:11:06 (10 months ago)
Author:
rjrw
Message:

Deal with FPE in dense.cpp

Use iteratively improved matrix solver in ion_solver

Change criteria for effectively homogeneous matrix in ion_solver

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • branches/newmole/source/ion_solver.cpp

    r1838 r1851  
    3232        bool lgPrintIt) 
    3333{ 
    34         /* use tridiag or general matrix solver? */ 
    35         bool lgTriDiag=false; 
    3634        long int ion,  
    3735          limit,  
     
    4038          ns, 
    4139          jmax=-1; 
    42         double totsrc; 
     40        double totsrc, 
     41                totscl; 
    4342        double rateone; 
    4443        bool lgNegPop; 
    45         static bool lgMustMalloc=true; 
    46         static double *sink, *source , *sourcesave; 
    4744        int32 nerror; 
    48         static int32 *ipiv; 
    49         long ion_low, ion_range, i, j, ion_to , ion_from; 
     45        long ion_low, i, j, ion_to , ion_from; 
    5046        /* only used for debug printout */ 
    51         static double *auger; 
     47        const long ion_range = dense.IonHigh[nelem]-dense.IonLow[nelem]+1; 
    5248 
    5349        double abund_total, renormnew; 
    5450        bool lgHomogeneous = true; 
    55         static double *xmat , *xmatsave; 
     51        valarray<double> xmat(ion_range*ion_range),xmatsave(ion_range*ion_range); 
     52        valarray<double> sink(ion_range), source(ion_range) , sourcesave(ion_range); 
     53        valarray<int32> ipiv(ion_range); 
     54        valarray<double> auger(LIMELM+1); 
    5655 
    5756        DEBUG_ENTRY( "ion_solver()" ); 
     
    125124 
    126125        /* the full range of ionization - this is number of ionization stages */ 
    127         ion_range = dense.IonHigh[nelem]-dense.IonLow[nelem]+1; 
    128126        ASSERT( ion_range <= nelem+2 ); 
    129127 
     
    133131         * running in the same memory pool - we must have fresh instances of the  
    134132         * arrays for each */ 
    135         if( PARALLEL_MODE || lgMustMalloc ) 
    136         { 
    137                 long int ncell=LIMELM+1; 
    138                 lgMustMalloc = false; 
    139                 if( PARALLEL_MODE ) 
    140                         ncell = ion_range; 
    141  
    142                 /* this will be "new" matrix, with non-adjacent coupling included */ 
    143                 xmat=(double*)MALLOC( (sizeof(double)*(unsigned)(ncell*ncell) )); 
    144                 xmatsave=(double*)MALLOC( (sizeof(double)*(unsigned)(ncell*ncell) )); 
    145                 sink=(double*)MALLOC( (sizeof(double)*(unsigned)ncell )); 
    146                 source=(double*)MALLOC( (sizeof(double)*(unsigned)ncell )); 
    147                 sourcesave=(double*)MALLOC( (sizeof(double)*(unsigned)ncell )); 
    148                 ipiv=(int32*)MALLOC( (sizeof(int32)*(unsigned)ncell )); 
    149                 /* auger is used only for debug printout - it is special because with multi-electron 
    150                  * Auger ejection, very high stages of ionization can be produced, well beyond 
    151                  * the highest stage considered here.  so we malloc to the limit */ 
    152                 auger=(double*)MALLOC( (sizeof(double)*(unsigned)(LIMELM+1) )); 
    153         } 
     133 
     134        /* auger is used only for debug printout - it is special because with multi-electron 
     135         * Auger ejection, very high stages of ionization can be produced, well beyond 
     136         * the highest stage considered here.  so we malloc to the limit */ 
    154137 
    155138        for( i=0; i<ion_range;i++ ) 
     
    160143        /* this will be used to address the 2d arrays */ 
    161144#       undef MAT 
    162 #       define MAT(M_,I_,J_)    (*((M_)+(I_)*(ion_range)+(J_))) 
     145#       define MAT(M_,I_,J_)    ((M_)[(I_)*(ion_range)+(J_)]) 
    163146 
    164147        /* zero-out loop comes before main loop since there are off-diagonal 
     
    198181                        dense.IonHigh[nelem] = 3; 
    199182                        abund_total = 1.; 
    200                         ion_range = dense.IonHigh[nelem]-dense.IonLow[nelem]+1; 
    201183                        /* make up ionization and recombination rates */ 
    202184                        for( ion=dense.IonLow[nelem]; ion <= limit; ion++ ) 
     
    377359        /* this will be sum of source and sink terms, will be used to decide if 
    378360         * matrix is singular */ 
    379         totsrc = 0.; 
     361        totsrc = totscl = 0.; 
    380362 
    381363        for( i=0; i<ion_range;i++ ) 
     
    387369                source[i] -= mole.source[nelem][ion]; 
    388370                totsrc += mole.source[nelem][ion]; 
     371                totscl += -MAT( xmat, i, i )*dense.xIonDense[nelem][ion]; 
    389372                MAT( xmat, i, i ) -= mole.sink[nelem][ion]; 
    390373        } 
    391374 
    392375        /* matrix is not homogeneous if source is non-zero */ 
    393         if( totsrc != 0. ) 
     376        if( totsrc > 1e-10*totscl ) 
    394377                lgHomogeneous = false; 
    395378 
     
    530513                        } 
    531514                        fprintf(ioQQQ,"\n"); 
    532                 } 
    533         } 
    534  
    535         /* first branch is tridiag, following branch is just general matrix solver */ 
    536         if( lgTriDiag )  
    537         { 
    538                 bool lgLapack=false , lgTriOptimized=true; 
    539                 /* there are two choices for the tridiag solver */ 
    540                 if(lgLapack)  
    541                 { 
    542                         /* this branch uses lapack tridiag solver, and should work  
    543                          * it is hardwired to not be used because not extensively tested 
    544                          * issues - is this slower than others, and is it robust in 
    545                          * singular cases? */ 
    546                         bool lgBad = false; 
    547                         /* Use Lapack tridiagonal solver */ 
    548                         double *dl, *d, *du; 
    549  
    550                         d = (double *) MALLOC((unsigned)ion_range*sizeof(double)); 
    551                         du = (double *) MALLOC((unsigned)(ion_range-1)*sizeof(double)); 
    552                         dl = (double *) MALLOC((unsigned)(ion_range-1)*sizeof(double)); 
    553  
    554                         for(i=0;i<ion_range-1;i++)  
    555                         { 
    556                                 du[i] = MAT(xmat,i+1,i); 
    557                                 d[i] = MAT(xmat,i,i); 
    558                                 dl[i] = MAT(xmat,i,i+1); 
    559                         } 
    560                         d[i] = MAT(xmat,i,i); 
    561  
    562 #                       if 0 
    563                         int i1, i2; 
    564                         i1 = ion_range; 
    565                         i2 = 1; 
    566                         lgBad = dgtsv_wrapper(&i1, &i2, dl, d, du, source, &i2); 
    567 #                       endif 
    568                         if( lgBad ) 
    569                                 fprintf(ioQQQ," dgtsz error.\n"); 
    570  
    571                         free(dl);free(du);free(d); 
    572                 }  
    573                 else if(lgTriOptimized) 
    574                 { 
    575                         /* Use tridiagonal solver re-coded to avoid rounding errors 
    576                          * on diagonal -- uses determination of jmax for the 
    577                          * singular case, but is otherwise independent of the array 
    578                          * filling code above */ 
    579  
    580                         for(i=0;i<ion_range;i++)  
    581                         { 
    582                                 source[i] = sink[i] = 0.; 
    583                         } 
    584                         for(i=0;i<ion_range;i++)  
    585                         { 
    586                                 ion = i+ion_low; 
    587                                 source[i] += mole.source[nelem][ion]; 
    588                                 sink[i] += mole.sink[nelem][ion]; 
    589                         } 
    590                         if( iteration > dynamics.n_initial_relax+1 && dynamics.lgAdvection && radius.depth < dynamics.oldFullDepth ) 
    591                         { 
    592                                 for(i=0;i<ion_range;i++)  
    593                                 { 
    594                                         ion = i+ion_low; 
    595                                         source[i] += dynamics.Source[nelem][ion]; 
    596                                         sink[i] += dynamics.Rate; 
    597                                 } 
    598                         } 
    599  
    600                         solveions(ionbal.RateIonizTot[nelem]+ion_low,ionbal.RateRecomTot[nelem]+ion_low, 
    601                                                                 sink,source,ion_range,jmax); 
    602                 } 
    603         }  
     515                        fprintf(ioQQQ,"totsrc/totscl %g %g\n",totsrc,totscl); 
     516                } 
     517        } 
     518 
     519        if (1) 
     520        { 
     521                int32 solve_system(const valarray<double> &a, valarray<double> &b, const long int n); 
     522                nerror = solve_system(xmat,source,ion_range); 
     523        } 
    604524        else 
    605525        { 
     
    607527                nerror = 0; 
    608528                /* Use general matrix solver */ 
    609                 getrf_wrapper(ion_range, ion_range, xmat, ion_range, ipiv, &nerror); 
     529                getrf_wrapper(ion_range, ion_range, &xmat[0], ion_range, &ipiv[0], &nerror); 
    610530                if( nerror != 0 ) 
    611531                { 
    612532                        fprintf( ioQQQ,  
    613                                 " DISASTER ion_solver: dgetrf finds singular or ill-conditioned matrix nelem=%li %s ion_range=%li, limit=%li, nConv %li xmat follows\n", 
    614                                 nelem ,  
    615                                 elementnames.chElementSym[nelem], 
    616                                 ion_range, 
    617                                 limit ,  
    618                                 conv.nTotalIoniz ); 
     533                                                         " DISASTER ion_solver: dgetrf finds singular or ill-conditioned matrix nelem=%li %s ion_range=%li, limit=%li, nConv %li xmat follows\n", 
     534                                                         nelem ,  
     535                                                         elementnames.chElementSym[nelem], 
     536                                                         ion_range, 
     537                                                         limit ,  
     538                                                         conv.nTotalIoniz ); 
    619539                        for( i=0; i<ion_range; ++i ) 
    620540                        { 
     
    633553                        cdEXIT(EXIT_FAILURE); 
    634554                } 
    635                 getrs_wrapper('N', ion_range, 1, xmat, ion_range, ipiv, source, ion_range, &nerror); 
     555                getrs_wrapper('N', ion_range, 1, &xmat[0], ion_range, &ipiv[0], &source[0], ion_range, &nerror); 
    636556                if( nerror != 0 ) 
    637557                { 
    638558                        fprintf( ioQQQ, " DISASTER ion_solver: dgetrs finds singular or ill-conditioned matrix nelem=%li ionrange=%li\n", 
    639                                 nelem , ion_range ); 
     559                                                         nelem , ion_range ); 
    640560                        cdEXIT(EXIT_FAILURE); 
    641561                } 
     
    694614                        test += source[ion-ion_low]; 
    695615                } 
    696                 test += source[ion-ion_low]; 
    697616        } 
    698617 
     
    11261045        } 
    11271046 
    1128         if( PARALLEL_MODE ) 
    1129         { 
    1130                 free(ipiv); 
    1131                 free(source); 
    1132                 free(sink); 
    1133                 free(xmat); 
    1134                 free(xmatsave); 
    1135                 free(auger); 
    1136         } 
    11371047        return; 
    11381048}