21 void dgeev_(
const char*,
const char*,
int*,
double*,
int*,
double*,
23 double*,
int*,
double*,
int*,
double*,
int*,
int*,
int,
int);
38 for(
long ihi=1; ihi < nlev; ++ihi )
40 double fac =
dsexp((ex[ihi]-ex[ihi-1])*TeInverse);
41 for(
long ilo=0; ilo < ihi-1; ++ilo )
45 excit[ihi][ihi-1] = fac;
52 for(
long ilo=0; ilo < nlev-1; ilo++ )
58 for(
long ihi=1; ihi < nlev; ihi++ )
61 for(
long ilo=0; ilo < ihi; ilo++ )
71 for(
long ilo=0; ilo < (nlev-1); ilo++ )
77 for(
long ihi=1; ihi < nlev; ihi++ )
80 for(
long ilo=0; ilo < ihi; ilo++ )
88 for(
long ihi=1; ihi < nlev; ihi++ )
90 for(
long ilo=0; ilo < ihi; ilo++ )
93 ASSERT( (col_str)[ihi][ilo]>= 0. );
95 (CollRate)[ihi][ilo] = (col_str)[ihi][ilo]/g[ihi]*
dense.
cdsqte;
97 (CollRate)[ilo][ihi] = (CollRate)[ihi][ilo]*g[ihi]/g[ilo]*
104 long int nLevelCalled,
131 const double source[],
140 const bool lgPrtMatrix,
174 if (grnd_excit != NULL) *grnd_excit = 0.0;
185 else if( chExUnits==
'w' )
195 for( ihi=1; ihi < nLevelCalled; ++ihi )
196 arg[ihi] = -(ex[ihi]-ex[0])*TeInverse;
197 vexp( arg.ptr0(), excit_gnd.
ptr0(), 1, nLevelCalled );
199 long int nlev = nLevelCalled;
201 while( nlev > 1 && excit_gnd[nlev-1]+AulPump[0][nlev-1] <
SMALLFLOAT &&
202 source[nlev-1] == 0. )
211 if( abund == 0. || nlev==1 )
221 for( level=1; level < nlev; level++ )
233 for( ihi=0; ihi < nlev; ihi++ )
235 for( ilo=0; ilo < nlev; ilo++ )
239 ASSERT( ihi == ilo || (AulDest)[ihi][ilo] >= 0. );
240 ASSERT( ihi == ilo || (AulEscp)[ihi][ilo] >= 0 );
244 for( ihi=1; ihi < nlev; ihi++ )
246 for( ilo=0; ilo < ihi; ilo++ )
248 ASSERT( (AulPump)[ihi][ilo] >= 0. );
255 fprintf(
ioQQQ,
" atom_levelN trace printout for atom=%s with tot abund %e \n", chLabel, abund);
260 for( ilo=0; ilo < nlev-1; ilo++ )
266 for( ihi=1; ihi < nlev; ihi++ )
269 for( ilo=0; ilo < ihi; ilo++ )
278 for( ilo=0; ilo < nlev-1; ilo++ )
284 for( ihi=1; ihi < nlev; ihi++ )
287 for( ilo=0; ilo < ihi; ilo++ )
297 for( ilo=0; ilo < nlev-1; ilo++ )
303 for( ihi=1; ihi < nlev; ihi++ )
306 for( ilo=0; ilo < ihi; ilo++ )
315 for( ilo=0; ilo < nlev-1; ilo++ )
321 for( ihi=1; ihi < nlev; ihi++ )
324 for( ilo=0; ilo < ihi; ilo++ )
346 for( level=0; level < nlev; level++ )
349 for( ilo=0; ilo < level; ilo++ )
351 double rate = (CollRate)[level][ilo] + (AulEscp)[level][ilo] +
352 (AulDest)[level][ilo] + (AulPump)[level][ilo];
353 amat[level][level] += rate;
354 amat[level][ilo] = -rate;
358 for( ihi=level + 1; ihi < nlev; ihi++ )
360 double rate = (CollRate)[level][ihi] + (AulPump)[level][ihi];
361 amat[level][level] += rate;
362 amat[level][ihi] = -rate;
365 if (grnd_excit != NULL) *grnd_excit =
amat[0][0];
370 double slowrate = -1.0;
373 for (level=1; level < nlev; ++level)
376 if (rate < slowrate || slowrate < 0.0)
382 if ( slowrate < 3.0 )
384 static map<string,double> failures;
386 oss << chLabel <<
"[level=" << slowlevel <<
']';
387 string str=oss.str();
388 if (failures.find(str) == failures.end())
390 failures[str] = slowrate;
394 "non-equilibrium appears important for %s, "
395 "rate * timestep is %g\n",
396 str.c_str(), slowrate);
400 if ( slowrate < failures[str])
401 failures[str] = slowrate;
407 for( level=0; level < nlev; level++ )
410 bvec[level] = source[level];
411 if(
amat[level][level] > maxdiag )
412 maxdiag =
amat[level][level];
413 amat[level][level] += sink[level];
436 const double CONDITION_SCALE = 1e-10;
437 double conserve_scale = maxdiag*CONDITION_SCALE;
438 ASSERT( conserve_scale > 0.0 );
440 for( level=0; level<nlev; ++level )
442 amat[level][0] += conserve_scale;
444 bvec[0] += abund*conserve_scale;
449 for( level=0; level < nlev; level++ )
451 for( j=0; j < nlev; j++ )
458 for( j=0; j < nlev; j++ )
469 vl(nlev,nlev),vr(nlev,nlev);
473 for( level=0; level < nlev; level++ )
476 for( ilo=0; ilo < level; ilo++ )
478 double rate = (*CollRate)[level][ilo];
479 mcol[level][level] += rate;
480 mcol[level][ilo] = -rate;
481 rate = (*AulEscp)[level][ilo] +
482 (*AulDest)[level][ilo] + (*AulPump)[level][ilo];
483 mrad[level][level] += rate;
484 mrad[level][ilo] = -rate;
487 for( ihi=level + 1; ihi < nlev; ihi++ )
489 double rate = (*CollRate)[level][ihi];
490 mcol[level][level] += rate;
491 mcol[level][ihi] = -rate;
492 rate = (*AulPump)[level][ihi];
493 mrad[level][level] += rate;
494 mrad[level][ihi] = -rate;
498 for( ilo=0; ilo < nlev; ilo++ )
500 for( ihi=0; ihi < nlev; ++ihi)
502 mtst[ilo][ihi] = mcol[ilo][ihi];
505 const char job[2] =
"V";
506 int lwork = 4*nlev,info,inlev=nlev;
507 vector<double> wr(nlev),wi(nlev),work(lwork);
512 for( level=0; level < nlev; level++ )
514 fprintf(
ioQQQ,
"%ld %15.8g+%15.8gi\n",level,wr[level],wi[level]);
523 for( level=0; level < nlev; level++ )
526 for( ilo=0; ilo < nlev; ilo++ )
528 tot += vl[level][ilo]*vr[level][ilo];
531 for( ilo=0; ilo < nlev; ilo++ )
533 vl[level][ilo] *= tot;
538 for( ilo=0; ilo < nlev; ilo++ )
540 for( ihi=0; ihi < nlev; ihi++ )
542 for( level=0; level < nlev; level++ )
544 mtst[ilo][ihi] += mrad[level][ihi] * vr[ilo][level];
550 for( ilo=0; ilo < nlev; ilo++ )
552 for( ihi=0; ihi < nlev; ihi++ )
554 for( level=0; level < nlev; level++ )
556 mtst1[ilo][ihi] += vl[ihi][level]*mtst[ilo][level];
560 for( level=0; level < nlev; level++ )
562 fprintf(
ioQQQ,
"%ld %15.8g %15.8g\n",level,wr[level],mtst1[level][level]);
576 fprintf(
ioQQQ,
" PROBLEM atom_levelN: dgetrs finds singular or ill-conditioned matrix for %s Search? %c Te:%.3e\n",
579 for( level=0; level < nlev; level++ )
588 for( level=0; level < nlev; level++ )
591 pops[level] =
bvec[level];
598 for( ihi=1; ihi < nlev; ihi++ )
600 for( ilo=0; ilo < ihi; ilo++ )
603 cool1 = (pops[ilo]*(CollRate)[ilo][ihi] - pops[ihi]*(CollRate)[ihi][ilo])*
604 (ex[ihi] - ex[ilo])*BOLTZMANN*TeConvFac;
607 (*Cool)[ihi][ilo] = cool1;
611 *coolder += dcooldT1;
612 if( dCooldT != NULL )
613 (*dCooldT)[ihi][ilo] = dcooldT1;
622 for( ihi=1; ihi < nlev; ihi++ )
625 depart[ihi] = (pops[ihi]/pops[0])*(g[0]/g[ihi])/excit_gnd[ihi];
632 for( ihi=0; ihi < nlev; ihi++ )
645 valarray<double> help1(nlev), help2(nlev);
646 double partfun = help1[0] = g[0];
647 double dpfdT = help2[0] = 0.;
648 for( level=1; level < nlev; level++ )
650 help1[level] = g[level]*excit_gnd[level];
651 partfun += help1[level];
652 help2[level] = help1[level]*(ex[level]-ex[0])*TeInverse/
phycon.
te;
653 dpfdT += help2[level];
658 valarray<double> dndT(nlev);
659 for( level=0; level < nlev; level++ )
661 pops[level] = abund*help1[level]/partfun;
662 dndT[level] = abund*(help2[level]*partfun - dpfdT*help1[level])/
pow2(partfun);
669 for( ihi=1; ihi < nlev; ihi++ )
671 for( ilo=0; ilo < ihi; ilo++ )
673 double deltaE = (ex[ihi] - ex[ilo])*BOLTZMANN*TeConvFac;
674 double cool1 = (pops[ihi]*((AulEscp)[ihi][ilo] + (AulPump)[ihi][ilo]) -
675 pops[ilo]*(AulPump)[ilo][ihi])*deltaE;
678 (*Cool)[ihi][ilo] = cool1;
679 double dcooldT1 = (dndT[ihi]*((AulEscp)[ihi][ilo] + (AulPump)[ihi][ilo]) -
680 dndT[ilo]*(AulPump)[ilo][ihi])*deltaE;
681 *coolder += dcooldT1;
682 if( dCooldT != NULL )
683 (*dCooldT)[ihi][ilo] = dcooldT1;
693 double poplimit = 1.0e-10;
695 if( pops[0]/abund > 0.99 )
698 for( level=0; level < nlev; level++ )
700 if( pops[level] < 0. )
702 if( fabs(pops[level]/abund) > poplimit )
705 *nNegPop = *nNegPop + 1;
720 fprintf(
ioQQQ,
"\n PROBLEM atom_levelN found negative population, nNegPop=%i, atom=%s lgSearch=%c Te=%10.2e fnzone %.2f \n",
725 for( level=0; level < nlev; level++ )
731 for( level=0; level < nlev; level++ )
737 for( level=0; level < nlev; level++ )
739 pops[level] = (double)
MAX2(0.,pops[level]);
745 fprintf(
ioQQQ,
"\n atom_leveln absolute population " );
746 for( level=0; level < nlev; level++ )
753 for( level=0; level < nlev; level++ )
764 for( ilo=0; ilo < nlev; ilo++ )
766 for( ihi=ilo+1; ihi < nlev; ihi++ )
769 AulDest[ilo][ihi] = 0.;
772 for( ihi=1; ihi < nlev; ihi++ )
774 for( ilo=0; ilo < ihi; ilo++ )
777 AulPump[ihi][ilo] = 0.;
780 for( ilo=0; ilo < nlev; ilo++ )
782 for( ihi=ilo+1; ihi < nlev; ihi++ )
784 AulEscp[ilo][ihi] = 0;
NORETURN void TotalInsanity(void)
double depart(const genericState &gs)
void resize(long int nlev)
void prtRates(const long nlevels_local, const multi_arr< double, 2, C_TYPE > &a, valarray< double > &b)
bool lgTimeDependentStatic
void vexp(const double x[], double y[], long nlo, long nhi)
int32 solve_system(const valarray< double > &a, valarray< double > &b, long int n, error_print_t error_print)
void operator()(long nLevelCalled, realnum abund, const double g[], const double ex[], char chExUnits, double pops[], double depart[], double **AulEscp, double **AulDest, double **AulPump, double **CollRate, const double create[], const double destroy[], double *cooltl, double *coolder, const char *chLabel, bool lgPrtMatrix, int *nNegPop, bool *lgZeroPop, bool lgDeBug, bool lgLTE=false, multi_arr< double, 2 > *Cool=NULL, multi_arr< double, 2 > *dCooldT=NULL, double *grnd_excit=NULL)
multi_arr< double, 2, C_TYPE > amat
#define DEBUG_ENTRY(funcname)
int fprintf(const Output &stream, const char *format,...)
void operator()(long nlev, double TeInverse, double **col_str, const double ex[], const double g[], double **CollRate)