00001 
00002 
00003 
00004 
00005  
00006  
00007  
00008 
00009 
00010 
00011 #include "cddefines.h"
00012 #include "lines_service.h"
00013 #include "phycon.h"
00014 #include "dense.h"
00015 #include "rfield.h"
00016 #include "taulines.h"
00017 #include "iso.h"
00018 #include "trace.h"
00019 #include "hyperfine.h"
00020 #include "physconst.h"  
00021 
00022 
00023 
00024 void H21_cm_pops( void )
00025 {
00026         
00027         
00028         
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042         double x,
00043                 PopTot;
00044         double a32,a31,a41,a42,a21, occnu_lya ,
00045                 rate12 , rate21 , pump12 , pump21 , coll12 , coll21,
00046                 texc , occnu_lya_23 , occnu_lya_13,occnu_lya_24,occnu_lya_14, texc1, texc2;
00047         a31 = 2.08e8;   
00048         a32 = 4.16e8;   
00049         a41 = 4.16e8;   
00050         a42 = 2.08e8;   
00051         
00052 
00053 
00054 
00055         a21 = 2.85e-15; 
00056 
00057         
00058 
00059         a21 *= (HFLines[0].Emis->Pdest + HFLines[0].Emis->Pesc + HFLines[0].Emis->Pelec_esc);
00060 
00061         
00062 
00063         occnu_lya = OccupationNumberLine( &Transitions[ipH_LIKE][ipHYDROGEN][ipH2p][ipH1s] ) *
00064                 hyperfine.lgLya_pump_21cm;
00065 
00066         
00067         texc = TexcLine( &Transitions[ipH_LIKE][ipHYDROGEN][ipH2p][ipH1s] );
00068         
00069         if( texc > 0. )
00070         {
00071                 
00072                 texc1 = sexp(0.068/texc);
00073                 texc2 = sexp(((82259.272-82258.907)*T1CM)/texc);
00074         }
00075         else
00076         {
00077                 texc1 = 0.;
00078                 texc2 = 0.;
00079         }
00080 
00081         
00082 
00083 
00084         occnu_lya_23 = occnu_lya;
00085         occnu_lya_13 = occnu_lya*texc1;
00086     occnu_lya_14 = occnu_lya_13*texc2;
00087     occnu_lya_24 = occnu_lya*texc2;
00088 
00089         
00090 
00091         pump12 = HFLines[0].Emis->pump;
00092         pump21 = pump12 * HFLines[0].Lo->g / HFLines[0].Hi->g;
00093 
00094         
00095 
00096         
00097         coll12 = HFLines[0].Coll.cs*dense.cdsqte/HFLines[0].Lo->g*rfield.ContBoltz[HFLines[0].ipCont-1];
00098         coll21 = HFLines[0].Coll.cs*dense.cdsqte/HFLines[0].Hi->g;
00099 
00100         
00101 
00102         rate12 = 
00103                 
00104                 coll12 + 
00105                 
00106                 pump12 +
00107                 
00108                 3.*a31*occnu_lya_13 *a32/(a31+a32)+
00109                 
00110                 
00111                 3.*a41*occnu_lya_14 *a42/(a41+a42);
00112 
00113         
00114 
00115         
00116         
00117         rate21 = 
00118                 
00119                 coll21 +
00120                 
00121                 pump21 +
00122                 
00123                 
00124                 occnu_lya_23*a32 * a31/(a31+a32)+
00125                 occnu_lya_24*a42*a41/(a41+a42);
00126 
00127         
00128         x = rate12 / SDIV(a21 + rate21);
00129 
00130         PopTot = StatesElem[ipH_LIKE][ipHYDROGEN][ipH1s].Pop*dense.xIonDense[ipHYDROGEN][1];
00131         
00132         HFLines[0].Hi->Pop = (x/(1.+x))* PopTot;
00133         HFLines[0].Lo->Pop = (1./(1.+x))* PopTot;
00134 
00135         
00136         HFLines[0].Emis->PopOpc = HFLines[0].Lo->Pop*((3*rate21- rate12) + 3*a21)/SDIV(3*(a21+ rate21));
00137 
00138         
00139         HFLines[0].Emis->phots = MAX2(0.,a21*HFLines[0].Hi->Pop);
00140 
00141         
00142         HFLines[0].Emis->xIntensity = HFLines[0].Emis->phots*HFLines[0].EnergyErg;
00143 
00144         
00145         HFLines[0].Emis->ColOvTot = coll12 / rate12;
00146 
00147         
00148         if( HFLines[0].Hi->Pop > SMALLFLOAT )
00149         {
00150                 hyperfine.Tspin21cm = TexcLine( &HFLines[0] );
00151                 
00152 
00153                 if( hyperfine.Tspin21cm == 0. )
00154                         hyperfine.Tspin21cm = phycon.te;
00155         }
00156         else
00157         {
00158                 hyperfine.Tspin21cm = phycon.te;
00159         }
00160 
00161         return;
00162 }
00163 
00164 
00165 
00166 double H21cm_electron( double temp )
00167 {
00168         double hold;
00169         temp = MIN2(1e4 , temp );
00170         
00171         
00172 
00173         hold = -9.607 + log10( sqrt(temp)) * sexp( pow(log10(temp) , 4.5 ) / 1800. );
00174         hold = pow(10.,hold );
00175         return( hold );
00176 }
00177 
00178 
00179 
00180 
00181 
00182 
00183 #if 0
00184 STATIC double h21_t_ge_20( double temp )
00185 {
00186         double y;
00187         double x1,
00188                 teorginal = temp;
00189         
00190         temp = MIN2( 1000.,temp );
00191         x1 =1.0/sqrt(temp);
00192         y =-21.70880995483007-13.76259674006133*x1;
00193         y = exp(y);
00194 
00195         
00196 
00197         
00198         if( teorginal > 1e3 )
00199         {
00200                 y *= pow(teorginal/1e3 , 0.33 );
00201         }
00202 
00203         return( y );
00204 }
00205 
00206 
00207 STATIC double h21_t_lt_20( double temp )
00208 {
00209         double y;
00210         double x1;
00211 
00212         
00213         temp = MAX2( 1., temp );
00214         x1 =temp*log(temp);
00215         y =9.720710314268267E-08+6.325515312006680E-08*x1;
00216         return(y*y);
00217 }
00218 #endif
00219 
00220 
00221 
00222 
00223 
00224 STATIC double h21_t_ge_10( double temp )
00225 {
00226         double y;
00227         double x1,x2,x3,
00228         teorginal = temp;
00229         
00230         temp = MIN2( 300., temp );
00231         x1 =temp;
00232         y =1.4341127e-9+9.4161077e-15*x1-9.2998995e-9/(log(x1))+6.9539411e-9/sqrt(x1)+1.7742293e-8*(log(x1))/pow(x1,2);
00233         if( teorginal > 300. )
00234         {
00235                 
00236                 x3 = MIN2( 1000., teorginal );
00237                 x2 =1.0/sqrt(x3);
00238                 y =-21.70880995483007-13.76259674006133*x2;
00239                 y = 1.236686*exp(y);
00240 
00241         }
00242         if( teorginal > 1e3 )
00243         {
00244                 
00245                 y *= pow(teorginal/1e3 , 0.33 );
00246         }
00247         return( y );
00248 }
00249 
00250 STATIC double h21_t_lt_10( double temp )
00251 {
00252         double y;
00253         double x1;
00254 
00255         
00256         temp = MAX2(1., temp );
00257         x1 =temp;
00258         y =8.5622857e-10+2.331358e-11*x1+9.5640586e-11*pow((log(x1)),2)-4.6220869e-10*sqrt(x1)-4.1719545e-10/sqrt(x1);
00259         return(y);
00260 }
00261 
00262 
00263 
00264 
00265 
00266 double H21cm_H_atom( double temp )
00267 {
00268         double hold;
00269         if( temp >= 10. )
00270         {
00271                 hold = h21_t_ge_10( temp );
00272         }
00273         else
00274         {
00275                 hold = h21_t_lt_10( temp );
00276         }
00277 
00278         return hold;
00279 }
00280 
00281 
00282 
00283 double H21cm_proton( double temp )
00284 {
00285         
00286 
00287 
00288 
00289         
00290         
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307         double hold;
00308         
00309 
00310         temp = MAX2( 2. , temp );
00311         temp = MIN2( 2e4 , temp );
00312 
00313         
00314         double x1,x2,x3,x4;
00315         x1 = temp;
00316         x2 = temp*temp;
00317         x3 = sqrt(temp);
00318         x4 = log(temp)/temp;
00319         hold =9.588389834316704E-11 - 5.158891920816405E-14*x1
00320                 +5.895348443553458E-19*x2 + 2.053049602324290E-11*x3
00321                 +9.122617940315725E-10*x4;
00322 
00323         return hold;
00324 }
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344    
00345 typedef struct 
00346 {
00347         double strengths[12];
00348 } Ion;
00349 
00350 static  Ion *Strengths;
00351 
00352 
00353 void HyperfineCreate(void)
00354 {
00355         FILE *ioDATA;
00356         char chLine[INPUT_LINE_LENGTH];
00357         bool lgEOL;
00358         
00359         realnum spin, wavelength;
00360         long int i, j, mass, nelec, ion, nelem;
00361 
00362         DEBUG_ENTRY( "HyperfineCreate()" );
00363 
00364         
00365         
00366         
00367 
00368         
00369 
00370         
00371         if( trace.lgTrace )
00372                 fprintf( ioQQQ," Hyperfine opening hyperfine.dat:");
00373 
00374         ioDATA = open_data( "hyperfine.dat", "r" );
00375 
00376         
00377         if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
00378         {
00379                 fprintf( ioQQQ, " Hyperfine could not read first line of hyperfine.dat.\n");
00380                 cdEXIT(EXIT_FAILURE);
00381         }
00382         
00383 
00384         nHFLines = 0;
00385         while( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) != NULL )
00386         {
00387                 
00388 
00389                 if( chLine[0] != '#')
00390                         ++nHFLines;
00391         }
00392 
00393         
00394         HFLines = (transition *)MALLOC( (size_t)(nHFLines)*sizeof(transition) );
00395         
00396         for( i=0; i< nHFLines; ++i )
00397         {
00398                 TransitionJunk( &HFLines[i] );
00399                 HFLines[i].Hi = AddState2Stack();
00400                 HFLines[i].Lo = AddState2Stack();
00401                 HFLines[i].Emis = AddLine2Stack( true );
00402         }
00403 
00404         Strengths = (Ion *)MALLOC( (size_t)(nHFLines)*sizeof(Ion) );
00405         hyperfine.HFLabundance = (realnum *)MALLOC( (size_t)(nHFLines)*sizeof(realnum) );
00406 
00407         
00408         if( fseek( ioDATA , 0 , SEEK_SET ) != 0 )
00409         {
00410                 fprintf( ioQQQ, " Hyperfine could not rewind hyperfine.dat.\n");
00411                 cdEXIT(EXIT_FAILURE);
00412         }
00413 
00414         
00415         if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
00416         {
00417                 fprintf( ioQQQ, " Hyperfine could not read first line of hyperfine.dat.\n");
00418                 cdEXIT(EXIT_FAILURE);
00419         }
00420 
00421         
00422         i = 1;
00423         nelem = (long)FFmtRead(chLine,&i,INPUT_LINE_LENGTH,&lgEOL);
00424         nelec = (long)FFmtRead(chLine,&i,INPUT_LINE_LENGTH,&lgEOL);
00425         ion = (long)FFmtRead(chLine,&i,INPUT_LINE_LENGTH,&lgEOL);
00426 
00427         {
00428                  
00429                 static int iYR=2,  iMN=10, iDY=28;
00430                 if( ( nelem != iYR ) || ( nelec != iMN ) || ( ion != iDY ) )
00431                 {
00432                         fprintf( ioQQQ, 
00433                                 " Hyperfine: the version of hyperfine.dat in the data directory is not the current version.\n" );
00434                         fprintf( ioQQQ, 
00435                                 " I expected to find the number %i %i %i and got %li %li %li instead.\n" ,
00436                                 iYR, iMN , iDY ,
00437                                 nelem , nelec , ion );
00438                         fprintf( ioQQQ, "Here is the line image:\n==%s==\n", chLine );
00439                         cdEXIT(EXIT_FAILURE);
00440                 }
00441         }
00442 
00443         
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452         
00453         j = 0;
00454 
00455         while( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) != NULL )
00456         {
00457                 
00458                 
00459                 if( chLine[0] != '#')
00460                 {
00461                         double Aul;
00462                         ASSERT( j < nHFLines );
00463 
00464                         double help[3];
00465                         sscanf(chLine, "%li%i%le%i%le%le%le%le%le%le%le%le%le%le%le%le%le%le%le", 
00466                                &mass, 
00467                                &HFLines[j].Hi->nelem,
00468                                &help[0],
00469                                &HFLines[j].Hi->IonStg,
00470                                &help[1],
00471                                &help[2],
00472                                &Aul,
00473                                &Strengths[j].strengths[0],
00474                                &Strengths[j].strengths[1],
00475                                &Strengths[j].strengths[2],
00476                                &Strengths[j].strengths[3],
00477                                &Strengths[j].strengths[4],
00478                                &Strengths[j].strengths[5],
00479                                &Strengths[j].strengths[6],
00480                                &Strengths[j].strengths[7],
00481                                &Strengths[j].strengths[8],
00482                                &Strengths[j].strengths[9],
00483                                &Strengths[j].strengths[10],
00484                                &Strengths[j].strengths[11]);
00485                         spin = (realnum)help[0];
00486                         hyperfine.HFLabundance[j] = (realnum)help[1];
00487                         wavelength = (realnum)help[2];
00488                         HFLines[j].Emis->Aul = (realnum)Aul;
00489                         HFLines[j].Hi->g = (realnum) (2*(spin + .5) + 1);
00490                         HFLines[j].Lo->g = (realnum) (2*(spin - .5) + 1);
00491                         HFLines[j].WLAng = wavelength * 1e8f;
00492                         HFLines[j].EnergyWN = (realnum) (1. / wavelength);
00493                         HFLines[j].Emis->gf = (realnum)(GetGF(HFLines[j].Emis->Aul, HFLines[j].EnergyWN, HFLines[j].Hi->g));
00494                         
00495 
00496 
00497                         ASSERT(HFLines[j].Emis->gf > 0.);
00498                         
00499                         j++;
00500                 }
00501 
00502         }
00503 
00504         
00505         fclose(ioDATA);
00506 
00507 #       if 0
00508         
00509         
00510         for(i = 0; i < nHFLines; i++)
00511         {
00512                 N = dense.xIonDense[HFLines[i].Hi->nelem-1][HFLines[i].Hi->IonStg-1];
00513                 Ne = dense.eden;
00514 
00515                 h = 6.626076e-27;                       
00516                 c = 3e10;                                       
00517                 k = 1.380658e-16;                       
00518 
00519                 upsilon = HyperfineCS(i);
00520                                 
00521                 q21 = COLL_CONST * upsilon / (phycon.sqrte * HFLines[i].Hi->g);
00522 
00523                 q12 = HFLines[i].Hi->g/ HFLines[i].Lo->g * q21 * exp(-1 * h * c * HFLines[i].EnergyWN / (k * phycon.te)); 
00524 
00525                 x = Ne * q12 / (HFLines[i].Emis->Aul * (1 + Ne * q21 / HFLines[i].Aul));
00526                 HFLines[i].xIntensity = N * HFLines[i].Emis->Aul * x / (1.0 + x) * h * c / (HFLines[i].WLAng / 1e8);
00527 
00528         }
00529 #       endif
00530 
00531         return;
00532 }
00533 
00534 
00535 
00536 double HyperfineCS( long i )
00537 {
00538 
00539         
00540         int  j = 0;
00541 #       define N_TE_TABLE 12
00542         double  slope, upsilon, TemperatureTable[N_TE_TABLE] = {.1e6, .15e6, .25e6, .4e6, .6e6, 
00543                 1.0e6, 1.5e6, 2.5e6, 4e6, 6e6, 10e6, 15e6};
00544 
00545         DEBUG_ENTRY( "HyperfineCS()" );
00546 
00547         
00548 
00549         ASSERT( i >= 0. && i <= nHFLines );
00550 
00551         
00552         
00553         
00554         
00555         
00556         
00557 
00558         if( phycon.te <= TemperatureTable[0])
00559         {
00560                 
00561                 upsilon = Strengths[i].strengths[0];
00562         }
00563         else if(  phycon.te >= TemperatureTable[N_TE_TABLE-1])
00564         {
00565                 
00566                 upsilon = Strengths[i].strengths[N_TE_TABLE-1];
00567         }
00568         else
00569         {
00570                 j = 1;
00571                 
00572                 
00573                 
00574                 while ( j < N_TE_TABLE && TemperatureTable[j] < phycon.te )
00575                         j++;
00576 
00577                 ASSERT( j >= 0 && j < N_TE_TABLE);
00578                 ASSERT( (TemperatureTable[j-1] <= phycon.te ) && (TemperatureTable[j] >= phycon.te) );
00579 
00580                 if( fp_equal( phycon.te, TemperatureTable[j] ) )
00581                 {
00582                         upsilon = Strengths[i].strengths[j];
00583                 }
00584                 
00585                 else if( phycon.te < TemperatureTable[j])
00586                 {
00587                         slope = (log10(Strengths[i].strengths[j-1]) - log10(Strengths[i].strengths[j])) /
00588                                   (log10(TemperatureTable[j-1]) - log10(TemperatureTable[j]));
00589 
00590                         upsilon = (log10((phycon.te)) - (log10(TemperatureTable[j-1])-6.))*slope + log10(Strengths[i].strengths[j-1]);
00591                         upsilon = pow(10., upsilon);
00592                 }
00593                 else 
00594                 {
00595                         upsilon = Strengths[i].strengths[j-1];
00596                 }
00597         }
00598 
00599         return upsilon;
00600 }