Changeset 2123 for branches/newmole

Show
Ignore:
Timestamp:
06/24/08 16:01:19 (7 months ago)
Author:
rjrw
Message:

Further finesse the finite-(pseudo-)timestep treatment for chemical
network stability.

Location:
branches/newmole/source
Files:
3 modified

Legend:

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

    r2118 r2123  
    4343 
    4444#define SMALLABUND 1e-24 
    45 #ifdef MINPACK 
    46 #include <minpack.h> 
    47 STATIC void fcn(const int *n, const double *x, double *fvec, double *fjac, 
    48                                                                 const int *ldfjac, int *iflag ); 
    49 #endif 
    5045 
    5146static double molnum[LIMELM]; 
     
    7368 
    7469        /* will test against this error for quitting */ 
    75 #       define BIGERROR         1e-4 
     70#       define BIGERROR         1e-8 
    7671        /* >>chng 04 jul 20, upper limit had been 6, why?  change to 20 
    7772         * to get closer to soln */ 
     
    8176        nBad = nPrevBad = 0; 
    8277        error = -1.; 
     78 
     79        valarray<double> escale(mole.num_compacted); 
     80        double rlimit=-1.; 
     81                 
    8382        for(i=0; i < LIM_LOOP;i++)  
    8483        { 
     
    105104 
    106105                MoleMap.setup(&oldmols[0]); 
    107                 if (1) 
    108                 { 
    109                         newton_step(oldmols, newmols, &error, mole.num_compacted, funjac);  
    110                 } 
    111                 else 
    112                 { 
    113 #ifdef MINPACK 
    114                         int info, lwa = (mole.num_compacted*(mole.num_compacted+13))/2; 
    115                         valarray<double> fvec(mole.num_compacted), 
    116                                 fjac(mole.num_compacted*mole.num_compacted), 
    117                                 wa(lwa); 
    118                         double tol = 1e-9; 
    119                         for ( long i=0; i < mole.num_compacted; i++ ) 
    120                         { 
    121                                 newmols[i] = oldmols[i]; 
    122                         } 
    123                         hybrj1_(fcn, &mole.num_compacted, &newmols[0], &fvec[0], &fjac[0], 
    124                                                         &mole.num_compacted, &tol, &info, &wa[0], &lwa); 
    125                         //fprintf(ioQQQ,"hybrj1_ returns info %d\n",info); 
    126 #else 
    127                         ; 
    128 #endif 
    129                 } 
    130  
    131                 /* check for negative populations */ 
    132                 nBad = 0;  
    133                 double fracneg = 0.; 
    134                 long iworst = -1; 
    135                 for( long i=0; i < mole.num_compacted; i++ ) 
    136                 { 
    137                         if( newmols[i] < 0. )  
    138                         { 
    139                                 if(-newmols[i] > fracneg*SDIV(oldmols[i]) && oldmols[i] > SMALLABUND)  
    140                                 { 
    141                                         fracneg = -newmols[i]/oldmols[i]; 
    142                                         iworst = i; 
    143                                 } 
    144                                 if (oldmols[i] > SMALLABUND || newmols[i] < -SMALLABUND) 
    145                                         ++nBad; 
    146                         } 
    147                 } 
    148106                 
     107                long j; 
     108 
     109                for (j=0; j<10; j++) 
     110                { 
     111                        newton_step(oldmols, newmols, &error, mole.num_compacted, &rlimit, escale, funjac);  
     112                         
     113                        /* check for negative populations */ 
     114                        nBad = 0;  
     115                        double fracneg = 0.; 
     116                        long iworst = -1; 
     117                        for( long mol=0; mol < mole.num_compacted; mol++ ) 
     118                        { 
     119                                if( newmols[mol] < 0. )  
     120                                { 
     121                                        if(-newmols[mol] > fracneg*SDIV(oldmols[mol]) && oldmols[mol] > SMALLABUND)  
     122                                        { 
     123                                                fracneg = -newmols[mol]/oldmols[mol]; 
     124                                                iworst = mol; 
     125                                        } 
     126                                        if (oldmols[mol] > SMALLABUND || newmols[mol] < -SMALLABUND) 
     127                                                ++nBad; 
     128                                } 
     129                        } 
     130                        if (0 == nBad) 
     131                        { 
     132                                //fprintf(ioQQQ,"OK at z %ld l %d j %ld t %g e %g\n",nzone,i,j,1./rlimit,error); 
     133                                break; 
     134                        } 
     135                        rlimit = 10.*rlimit; 
     136                } 
     137                 
     138                // If it got through with no problems, extend the time limit 
     139                if (0 == j) 
     140                        rlimit = 0.5*rlimit; 
     141 
    149142                MoleMap.updateMolecules( newmols ); 
    150143                 
     
    172165                ConvFail( "pops" , "Mole "); 
    173166        } 
     167         
     168        //fprintf(stdout,"Mole zone %ld -- %7.2f error %15.8g nBad %d loop %d\n",nzone,fnzone,error,nBad,i); 
    174169 
    175170        mole_return_cached_species(); 
     
    315310GroupMap MoleMap; 
    316311 
    317 #ifdef MINPACK 
    318 STATIC void fcn(const int *n, const double *x, double *fvec, double *fjac, 
    319                                                                 const int *ldfjac, int *iflag ) 
    320 { 
    321         /* Function to interface funjac with MINPACK routines */ 
    322         ASSERT (*ldfjac == *n); 
    323         valarray<double> b2vec(*n), tmpvec(*n); 
    324         for (long i=0; i < *n; i++)  
    325         { 
    326                 b2vec[i] = x[i]; 
    327         } 
    328         if (*iflag == 1) 
    329         { 
    330                 funjac(b2vec, fvec, &tmpvec[0], false); 
    331         } 
    332         else if (*iflag == 2) 
    333         { 
    334                 funjac(b2vec, &tmpvec[0], &fjac[0], true); 
    335         } 
    336 } 
    337 #endif 
    338  
    339312STATIC void funjac(const valarray<double> &b2vec, double * const ervals, double * const amat, const bool lgJac) 
    340313{ 
     
    363336                // Without pseudo-timestepping, need to apply conservation 
    364337                // constraint to maintain non-singular matrix 
    365                 lgConserve = false;  
     338                lgConserve = true;  
    366339        }                
    367340 
  • branches/newmole/source/newton_step.cpp

    r2118 r2123  
    2525 * descent direction, step limited to ensure improvement */ 
    2626void newton_step(const valarray<double> &b0vec, valarray<double> &b2vec,  
    27                                                                  realnum *error, const long n, 
     27                                                                 realnum *error, const long n, double *rlimit, valarray<double> &escale, 
    2828                                                                 void (*jacobn)(const valarray<double> &b2vec,  
    2929                                                                                                                                double * const ervals, double * const amat,  
     
    4545                erroreq, 
    4646                grad, 
    47                 pred, 
    48                 errstp; 
     47                pred; 
    4948 
    5049        valarray<double>  
    5150                amat(n*n), 
    5251                b1vec(n), 
    53                 escale(n), 
    5452                ervals(n), 
    5553                ervals1(n); 
     
    6462 
    6563        pred = error0 = error2 = erroreq = grad = f1 = f2 = 0.; 
    66         errstp = 0.0; 
    6764 
    6865        for (loop=0;loop<40;loop++)  
     
    7269                if (loop == 0)  
    7370                { 
    74                         // Limit timestep to value where linearizations are reasonable 
    7571                        iworst = -1; 
    7672                        for( i=0; i < n; i++ ) 
    7773                        { 
    7874                                escale[i] = MAT(amat,i,i); 
    79                                 if (b0vec[i] > 0 && errstp*b0vec[i] < fabs(ervals[i])) 
    80                                 { 
    81                                         errstp = fabs(ervals[i])/(1e-24+b0vec[i]); 
    82                                         iworst = i; 
    83                                 } 
    84                         } 
    85                         errstp *= 3.; 
    86                         for (i=0; i < n; i++) 
    87                         {  
    88                                 MAT(amat,i,i) -= errstp; 
    89                         } 
    90                         //if (iworst != -1) 
    91                         //      fprintf(stdout,"Timescale %g rate %g worst %s %g %g %g\n", 
    92                         //                                      1./SDIV(errstp),errstp,groupspecies[iworst]->label, 
    93                         //                                      ervals[iworst],b0vec[iworst],escale[iworst]); 
    94                 } 
    95  
    96                 // Error from fully relaxed equilibrium solution 
     75                        } 
     76                        // First time through this case, set rlimit by guesswork based on 
     77                        // maintaining matrix condition 
     78                        if (*rlimit < 0.0) 
     79                        { 
     80                                *rlimit=0.0; 
     81                                for( i=0; i<n; ++i ) 
     82                                { 
     83                                        if (-escale[i]>*rlimit) 
     84                                        { 
     85                                                *rlimit = -escale[i]; 
     86                                        } 
     87                                } 
     88                                *rlimit *= 1e-11; 
     89                        } 
     90                        for( i=0; i < n; i++ ) 
     91                        { 
     92                                MAT(amat,i,i) -= *rlimit; 
     93                        } 
     94                } 
     95 
     96                // External error limit based on difference to state relaxed to (quasi-)equilibrium 
    9797                erroreq = 0.; 
    9898                for( i=0; i < n; i++ ) 
    9999                { 
    100                         etmpeq = ervals[i];//(1e-24+fabs(b0vec[i]*escale[i])); 
     100                        etmpeq = ervals[i]/(1e-24+fabs(b0vec[i]*escale[i])); 
    101101                        erroreq += etmpeq*etmpeq; 
    102102                } 
    103103 
    104                 // Error from timestep-limited solution 
     104                // Internal (step) limit based on finite-(pseudo-)timestep solution 
    105105                for (i=0; i < n; i++) 
    106106                { 
    107                         ervals1[i] = ervals[i]-errstp*(b2vec[i]-b0vec[i]); 
     107                        ervals1[i] = ervals[i]-(*rlimit)*(b2vec[i]-b0vec[i]); 
    108108                } 
    109109                error1 = emax = 0.; 
     
    111111                for( i=0; i < n; i++ ) 
    112112                { 
    113                         /* Smooth the error mode tailoff */ 
    114                         etmp = ervals1[i];//(1e-24+fabs(b0vec[i]*escale[i])); 
     113                        /* Scale the errors weighting to ensure trace species are accurate */ 
     114                        etmp = ervals1[i]/(1e-24+fabs(b0vec[i]*escale[i])); 
    115115                        etmp *= etmp; 
    116116                        if (etmp > emax) 
  • branches/newmole/source/newton_step.h

    r2028 r2123  
    1010\param *error 
    1111*/ 
    12 void newton_step(const valarray<double> &oldmols, valarray<double> &newmols, realnum *error, const long n, 
    13                         void (*jacobn)(const valarray<double> &b2vec, double * const ervals, double * const amat, const bool lgJac)); 
     12void newton_step(const valarray<double> &oldmols, valarray<double> &newmols, realnum *error, const long n,  
     13                                                                 double *rlimit, valarray<double> &escale, 
     14                                                                 void (*jacobn)(const valarray<double> &b2vec, double * const ervals, double * const amat, const bool lgJac)); 
    1415 
    1516#endif /* _NEWTON_STEP_H_ */