00001
00002
00003
00004
00005
00006 #include "cddefines.h"
00007 #include "taulines.h"
00008 #include "dense.h"
00009 #include "thermal.h"
00010 #include "hmi.h"
00011 #include "radius.h"
00012 #include "atoms.h"
00013 #include "phycon.h"
00014 #include "rt.h"
00015 #include "lines_service.h"
00016 #include "cddrive.h"
00017 #include "mole.h"
00018
00019
00020
00021
00022 static double *col12 , *col13;
00023
00024
00025 void CO_PopsEmisCool(
00026 transition ** Rotate ,
00027 long int nRotate ,
00028 realnum abundan,
00029 const char * chLabel ,
00030 realnum * Cooling ,
00031 realnum * dCoolingDT )
00032 {
00033
00034
00035 static double
00036 **AulEscp ,
00037 **col_str ,
00038 **AulDest,
00039
00040 **AulPump,
00041 **CollRate,
00042 *pops,
00043 *create,
00044 *destroy,
00045 *depart,
00046
00047 *stat ,
00048
00049 *excit;
00050
00051
00052
00053 static bool lgFirst=true;
00054 long int i,
00055 j,
00056 ilo ,
00057 ihi;
00058 static long int nUsed;
00059 bool lgDeBug;
00060 int nNegPop;
00061 bool lgZeroPop;
00062 double rot_cooling , dCoolDT;
00063 static long int ndimMalloced = 0;
00064
00065 DEBUG_ENTRY( "CO_PopsEmisCool()" );
00066
00067 if( lgFirst )
00068 {
00069
00070 lgFirst = false;
00071
00072 ndimMalloced = nRotate;
00073
00074 excit = (double *)MALLOC( sizeof(double)*(size_t)(nRotate+1) );
00075 stat = (double *)MALLOC( sizeof(double)*(size_t)(nRotate+1) );
00076 pops = (double *)MALLOC( sizeof(double)*(size_t)(nRotate+1) );
00077 create = (double *)MALLOC( sizeof(double)*(size_t)(nRotate+1) );
00078 destroy = (double *)MALLOC( sizeof(double)*(size_t)(nRotate+1) );
00079 depart = (double *)MALLOC( sizeof(double)*(size_t)(nRotate+1) );
00080
00081 AulPump = ((double **)MALLOC((size_t)(nRotate+1)*sizeof(double *)));
00082 CollRate = ((double **)MALLOC((size_t)(nRotate+1)*sizeof(double *)));
00083 AulDest = ((double **)MALLOC((size_t)(nRotate+1)*sizeof(double *)));
00084 AulEscp = ((double **)MALLOC((size_t)(nRotate+1)*sizeof(double *)));
00085 col_str = ((double **)MALLOC((size_t)(nRotate+1)*sizeof(double *)));
00086 for( i=0; i<(nRotate+1); ++i )
00087 {
00088 AulPump[i] = ((double *)MALLOC((size_t)(nRotate+1)*sizeof(double )));
00089 CollRate[i] = ((double *)MALLOC((size_t)(nRotate+1)*sizeof(double )));
00090 AulDest[i] = ((double *)MALLOC((size_t)(nRotate+1)*sizeof(double )));
00091 AulEscp[i] = ((double *)MALLOC((size_t)(nRotate+1)*sizeof(double )));
00092 col_str[i] = ((double *)MALLOC((size_t)(nRotate+1)*sizeof(double )));
00093 }
00094 }
00095
00096
00097 if( nRotate > ndimMalloced )
00098 {
00099 fprintf(ioQQQ," CO_PopsEmisCool has been called with the number of rotor levels greater than space allocated.\n");
00100 cdEXIT(EXIT_FAILURE);
00101 }
00102
00103
00104 for( i=0; i < (nRotate+1); i++ )
00105 {
00106 create[i] = 0.;
00107 destroy[i] = 0.;
00108 for( j=0; j < (nRotate+1); j++ )
00109 {
00110 col_str[j][i] = 0.;
00111 AulEscp[j][i] = 0.;
00112 AulDest[j][i] = 0.;
00113 AulPump[j][i] = 0.;
00114 }
00115 }
00116
00117
00118 for( j=0; j < nRotate; j++ )
00119 {
00120
00121 stat[j] = (*Rotate)[j].Lo->g;
00122 }
00123
00124 stat[nRotate] = (*Rotate)[nRotate-1].Hi->g;
00125
00126
00127
00128 excit[0] = 0.;
00129 for( j=1; j < nRotate; j++ )
00130 {
00131
00132 excit[j] = excit[j-1] + (*Rotate)[j-1].EnergyK;
00133 }
00134
00135
00136 excit[nRotate] = excit[nRotate-1] + (*Rotate)[nRotate-1].EnergyK;
00137
00138 nUsed = nRotate;
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 while ( (excit[nUsed] > phycon.te*25.) && (nUsed > 5) )
00152 {
00153 --nUsed;
00154 }
00155
00156 for( j=0; j < nRotate; j++ )
00157 {
00158
00159 AulEscp[j+1][j] = (*Rotate)[j].Emis->Aul*((*Rotate)[j].Emis->Pesc + (*Rotate)[j].Emis->Pelec_esc);
00160 AulDest[j+1][j] = (*Rotate)[j].Emis->Aul*(*Rotate)[j].Emis->Pdest;
00161
00162 (*Rotate)[j].Coll.cs = 1.;
00163
00164 col_str[j+1][j] = (*Rotate)[j].Coll.cs*hmi.H2_total/dense.eden;
00165
00166 AulPump[j][j+1] = (*Rotate)[j].Emis->pump;
00167
00168
00169
00170 }
00171
00172
00173 for( ilo=0; ilo < nRotate-1; ilo++ )
00174 {
00175
00176
00177 for( ihi=ilo+2; ihi <= nRotate; ihi++ )
00178 {
00179
00180
00181
00182 col_str[ihi][ilo] = 1. *hmi.H2_total/dense.eden;
00183
00184
00185 AulEscp[ihi][ilo] = 0;
00186 AulDest[ihi][ilo] = 0;
00187 }
00188 }
00189
00190
00191
00192 for( ilo=0; ilo < nRotate; ilo++ )
00193 {
00194
00195
00196 for( ihi=ilo+1; ihi <= MIN2(nRotate,ilo+5); ihi++ )
00197 {
00198
00199 double a[5]={1.66, 2.80, 1.19, 1.00, 1.30};
00200 double b[5]={1.67, 1.47, 1.85, 1.55, 2.24};
00201
00202
00203
00204
00205 double collid = hmi.H2_total + dense.xIonDense[ipHELIUM][0]/1.37;
00206
00207
00208 double TeUsed = MAX2(10., phycon.te );
00209
00210
00211 CollRate[ihi][ilo] = a[ihi-ilo-1]*1.e-10*(*Rotate)[ilo].Lo->g/(*Rotate)[ilo].Hi->g*
00212 (1.+(excit[ihi]-excit[ilo])/TeUsed) *
00213 sexp( b[ihi-ilo-1]*sqrt((excit[ihi]-excit[ilo])/TeUsed) )*collid;
00214
00215 if( ihi == ilo+1 )
00216 {
00217
00218 (*Rotate)[ilo].Coll.ColUL = (realnum)CollRate[ihi][ilo];
00219
00220 LineConvRate2CS( &(*Rotate)[ilo] , (*Rotate)[ilo].Coll.ColUL);
00221 }
00222
00223
00224 CollRate[ilo][ihi] = CollRate[ihi][ilo]*
00225 sexp( (excit[ihi]-excit[ilo])/phycon.te )*
00226 (*Rotate)[ilo].Hi->g / (*Rotate)[ilo].Lo->g;
00227
00228
00229
00230
00231 }
00232
00233 for( ihi=ilo+6; ihi <= nRotate; ihi++ )
00234 {
00235 CollRate[ihi][ilo] = 0.;
00236 CollRate[ilo][ihi] = 0.;
00237 }
00238 }
00239
00240 lgDeBug = false;
00241
00242 atom_levelN(
00243
00244
00245 nUsed+1,
00246 abundan,
00247 stat,
00248 excit,
00249 'K',
00250 pops,
00251 depart,
00252 &AulEscp,
00253 &col_str,
00254 &AulDest,
00255 &AulPump,
00256 &CollRate,
00257 create,
00258 destroy,
00259
00260 true,
00261
00262 &rot_cooling,
00263 &dCoolDT,
00264 chLabel,
00265
00266 &nNegPop,
00267 &lgZeroPop,
00268 lgDeBug );
00269
00270
00271 *Cooling = (realnum)rot_cooling;
00272
00273
00274
00275
00276 *dCoolingDT = (realnum)(rot_cooling/phycon.te);
00277
00278 # if 0
00279 if( lgMainCO )
00280 fprintf(ioQQQ,"COcool\t%i\t%.2f\t%e\t%e\t%e\t%e\t%e\n",
00281 nUsed,
00282 fnzone,
00283 phycon.te,
00284 *Cooling/abundan,
00285 *dCoolingDT ,
00286 *Cooling,
00287 thermal.htot );
00288 # endif
00289
00290
00291 for( i=nUsed+1; i<=nRotate; ++i )
00292 {
00293 pops[i] = 0.;
00294 depart[i] = 0.;
00295 }
00296
00297
00298 for( i=0; i< MIN2(LIMLEVELN,nRotate); ++i )
00299 {
00300 atoms.PopLevels[i] = pops[i];
00301 atoms.DepLTELevels[i] = depart[i];
00302 }
00303
00304 if( nNegPop > 0 )
00305 {
00306 fprintf(ioQQQ,"CO_PopsEmisCool called atom_levelN which returned negative populations.\n");
00307 }
00308
00309
00310 for( j=0; j<nRotate; ++j )
00311 {
00312 double EnrLU, EnrUL;
00313
00314 (*Rotate)[j].Lo->Pop = pops[j];
00315 (*Rotate)[j].Hi->Pop = pops[j+1];
00316 (*Rotate)[j].Emis->PopOpc = (pops[j] - pops[j+1]*(*Rotate)[j].Lo->g/(*Rotate)[j].Hi->g);
00317
00318
00319 (*Rotate)[j].Emis->phots = (*Rotate)[j].Emis->Aul*((*Rotate)[j].Emis->Pesc + (*Rotate)[j].Emis->Pelec_esc)*pops[j+1];
00320
00321 # if 0
00322
00323
00324 (*Rotate)[j].Emis->ots = (*Rotate)[j].Aul*(*Rotate)[j].Emis->Pdest*(realnum)(*Rotate)[j].Hi->Pop;
00325 RT_OTS_AddLine( (*Rotate)[j].Emis->ots , (*Rotate)[j].ipCont);
00326 # endif
00327
00328
00329 (*Rotate)[j].Emis->xIntensity = (*Rotate)[j].Emis->phots*(*Rotate)[j].EnergyErg;
00330
00331
00332 (*Rotate)[j].Emis->ColOvTot = (realnum)(CollRate[j][j+1]/(CollRate[j][j+1]+(*Rotate)[j].Emis->pump) );
00333
00334
00335
00336
00337 EnrLU = (*Rotate)[j].Lo->Pop*CollRate[j][j+1]*(*Rotate)[j].EnergyErg;
00338 EnrUL = (*Rotate)[j].Hi->Pop*CollRate[j+1][j]*(*Rotate)[j].EnergyErg;
00339
00340
00341 (*Rotate)[j].Coll.cool = EnrLU - EnrUL*(*Rotate)[j].Emis->ColOvTot;
00342
00343 (*Rotate)[j].Coll.heat = EnrUL*(1.f - (*Rotate)[j].Emis->ColOvTot);
00344
00345
00346 }
00347
00348
00349
00350 if( rot_cooling / thermal.ctot > 0.1 &&
00351 (*Rotate)[nUsed-1].Emis->xIntensity > (*Rotate)[nUsed-2].Emis->xIntensity &&
00352
00353
00354
00355 nUsed == nRotate )
00356 {
00357 co.lgCOCoolCaped = true;
00358 }
00359
00360 return;
00361 }
00362
00363
00364 void CO_Colden( const char *chLabel )
00365 {
00366 long int iRot;
00367
00368 DEBUG_ENTRY( "CO_Colden()" );
00369
00370 if( strcmp(chLabel,"ZERO") == 0 )
00371 {
00372 static bool lgFIRST=true;
00373 if( lgFIRST )
00374 {
00375 lgFIRST = false;
00376 col12 = (double *)MALLOC( sizeof(double)*(size_t)(nCORotate+1) );
00377 col13 = (double *)MALLOC( sizeof(double)*(size_t)(nCORotate+1) );
00378 }
00379
00380
00381 for( iRot=0; iRot<=nCORotate; ++iRot )
00382 {
00383
00384 col12[iRot] = 0.;
00385 col13[iRot] = 0.;
00386 }
00387 }
00388 else if( strcmp(chLabel,"ADD ") == 0 )
00389 {
00390
00391 for( iRot=0; iRot<nCORotate; ++iRot )
00392 {
00393
00394 col12[iRot] += C12O16Rotate[iRot].Lo->Pop*radius.drad_x_fillfac;
00395 col13[iRot] += C13O16Rotate[iRot].Lo->Pop*radius.drad_x_fillfac;
00396 }
00397 }
00398
00399
00400 else if( strcmp(chLabel,"PRIN") != 0 )
00401 {
00402 fprintf( ioQQQ, " CO_Colden does not understand the label %s\n",
00403 chLabel );
00404 cdEXIT(EXIT_FAILURE);
00405 }
00406 }
00407
00408
00409
00410 double cdCO_colden( long isotope , long iRot )
00411 {
00412
00413
00414 if( isotope !=12 && isotope != 13 )
00415 {
00416 fprintf(ioQQQ," cdCO_colden can only do 12CO and 13CO\n");
00417 return -1.;
00418 }
00419 if( iRot < 0 || iRot > nCORotate )
00420 {
00421 fprintf(ioQQQ," cdCO_colden - rotation quantum number must be 0 or greater, and less than %li\n",
00422 nCORotate);
00423 return -1.;
00424 }
00425
00426
00427 if( isotope == 12 )
00428 {
00429 return col12[iRot];
00430 }
00431 else
00432 {
00433 return col13[iRot];
00434 }
00435 }
00436
00437
00438 void CO_OTS( void )
00439 {
00440
00441 long int j;
00442
00443 DEBUG_ENTRY( "CO_OTS()" );
00444
00445
00446 for( j=0; j<nCORotate; ++j )
00447 {
00448 C12O16Rotate[j].Emis->ots = C12O16Rotate[j].Emis->Aul*C12O16Rotate[j].Emis->Pdest*
00449 C12O16Rotate[j].Hi->Pop;
00450 RT_OTS_AddLine( C12O16Rotate[j].Emis->ots , C12O16Rotate[j].ipCont);
00451
00452 C13O16Rotate[j].Emis->ots = C13O16Rotate[j].Emis->Aul*C13O16Rotate[j].Emis->Pdest*
00453 C13O16Rotate[j].Hi->Pop;
00454 RT_OTS_AddLine( C13O16Rotate[j].Emis->ots , C13O16Rotate[j].ipCont);
00455 }
00456
00457 return;
00458 }