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 }