Changeset 1851 for branches/newmole/source/ion_solver.cpp
- Timestamp:
- 03/16/08 03:11:06 (10 months ago)
- Files:
-
- 1 modified
-
branches/newmole/source/ion_solver.cpp (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/newmole/source/ion_solver.cpp
r1838 r1851 32 32 bool lgPrintIt) 33 33 { 34 /* use tridiag or general matrix solver? */35 bool lgTriDiag=false;36 34 long int ion, 37 35 limit, … … 40 38 ns, 41 39 jmax=-1; 42 double totsrc; 40 double totsrc, 41 totscl; 43 42 double rateone; 44 43 bool lgNegPop; 45 static bool lgMustMalloc=true;46 static double *sink, *source , *sourcesave;47 44 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; 50 46 /* only used for debug printout */ 51 static double *auger;47 const long ion_range = dense.IonHigh[nelem]-dense.IonLow[nelem]+1; 52 48 53 49 double abund_total, renormnew; 54 50 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); 56 55 57 56 DEBUG_ENTRY( "ion_solver()" ); … … 125 124 126 125 /* the full range of ionization - this is number of ionization stages */ 127 ion_range = dense.IonHigh[nelem]-dense.IonLow[nelem]+1;128 126 ASSERT( ion_range <= nelem+2 ); 129 127 … … 133 131 * running in the same memory pool - we must have fresh instances of the 134 132 * 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 */ 154 137 155 138 for( i=0; i<ion_range;i++ ) … … 160 143 /* this will be used to address the 2d arrays */ 161 144 # undef MAT 162 # define MAT(M_,I_,J_) ( *((M_)+(I_)*(ion_range)+(J_)))145 # define MAT(M_,I_,J_) ((M_)[(I_)*(ion_range)+(J_)]) 163 146 164 147 /* zero-out loop comes before main loop since there are off-diagonal … … 198 181 dense.IonHigh[nelem] = 3; 199 182 abund_total = 1.; 200 ion_range = dense.IonHigh[nelem]-dense.IonLow[nelem]+1;201 183 /* make up ionization and recombination rates */ 202 184 for( ion=dense.IonLow[nelem]; ion <= limit; ion++ ) … … 377 359 /* this will be sum of source and sink terms, will be used to decide if 378 360 * matrix is singular */ 379 totsrc = 0.;361 totsrc = totscl = 0.; 380 362 381 363 for( i=0; i<ion_range;i++ ) … … 387 369 source[i] -= mole.source[nelem][ion]; 388 370 totsrc += mole.source[nelem][ion]; 371 totscl += -MAT( xmat, i, i )*dense.xIonDense[nelem][ion]; 389 372 MAT( xmat, i, i ) -= mole.sink[nelem][ion]; 390 373 } 391 374 392 375 /* matrix is not homogeneous if source is non-zero */ 393 if( totsrc != 0.)376 if( totsrc > 1e-10*totscl ) 394 377 lgHomogeneous = false; 395 378 … … 530 513 } 531 514 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 } 604 524 else 605 525 { … … 607 527 nerror = 0; 608 528 /* 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); 610 530 if( nerror != 0 ) 611 531 { 612 532 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 ); 619 539 for( i=0; i<ion_range; ++i ) 620 540 { … … 633 553 cdEXIT(EXIT_FAILURE); 634 554 } 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); 636 556 if( nerror != 0 ) 637 557 { 638 558 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 ); 640 560 cdEXIT(EXIT_FAILURE); 641 561 } … … 694 614 test += source[ion-ion_low]; 695 615 } 696 test += source[ion-ion_low];697 616 } 698 617 … … 1126 1045 } 1127 1046 1128 if( PARALLEL_MODE )1129 {1130 free(ipiv);1131 free(source);1132 free(sink);1133 free(xmat);1134 free(xmatsave);1135 free(auger);1136 }1137 1047 return; 1138 1048 }
