00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "cddefines.h"
00035 #include "physconst.h"
00036 #include "phycon.h"
00037 #include "lines.h"
00038 #include "radius.h"
00039 #include "geometry.h"
00040 #include "elementnames.h"
00041 #include "rt.h"
00042 #include "dense.h"
00043 #include "rfield.h"
00044 #include "opacity.h"
00045 #include "ipoint.h"
00046 #include "iso.h"
00047 #include "taulines.h"
00048 #include "hydrogenic.h"
00049 #include "lines_service.h"
00050
00051
00052 void outline( transition *t )
00053 {
00054 long int ip = t->ipCont-1;
00055 double xInWrd = t->Emis->phots*t->Emis->FracInwd;
00056
00057 DEBUG_ENTRY( "outline()" );
00058
00059 ASSERT( t->Emis->phots >= 0. );
00060 ASSERT( t->Emis->FracInwd >= 0. );
00061 ASSERT( radius.BeamInIn >= 0. );
00062 ASSERT( radius.BeamInOut >= 0. );
00063
00064
00065 rfield.reflin[ip] += (realnum)(xInWrd*radius.BeamInIn);
00066
00067
00068 rfield.outlin[ip] += (realnum)(xInWrd*radius.BeamInOut*opac.tmn[ip]*
00069 t->Emis->ColOvTot);
00070
00071
00073 rfield.outlin[ip] += (realnum)(t->Emis->phots*
00074 (1. - t->Emis->FracInwd)*radius.BeamOutOut* t->Emis->ColOvTot);
00075 return;
00076 }
00077
00078
00079 double emit_frac( transition *t )
00080 {
00081 DEBUG_ENTRY( "emit_frac()" );
00082
00083 ASSERT( t->ipCont > 0 );
00084
00085
00086
00087 double deexcit_loss = t->Coll.cs * dense.cdsqte + t->Emis->Aul*t->Emis->Pdest;
00088
00089 double rad_deexcit = t->Emis->Aul*(t->Emis->Pelec_esc + t->Emis->Pesc);
00090 return rad_deexcit/(deexcit_loss + rad_deexcit);
00091 }
00092
00093
00094
00095 void DumpLine(transition * t)
00096 {
00097 char chLbl[11];
00098
00099 DEBUG_ENTRY( "DumpLine()" );
00100
00101 ASSERT( t->ipCont > 0 );
00102
00103
00104 strcpy( chLbl, chLineLbl(t) );
00105
00106 fprintf( ioQQQ,
00107 " %10.10s Te%.2e eden%.1e CS%.2e Aul%.1e Tex%.2e cool%.1e het%.1e conopc%.1e albdo%.2e\n",
00108 chLbl,
00109 phycon.te,
00110 dense.eden,
00111 t->Coll.cs,
00112 t->Emis->Aul,
00113 TexcLine(t),
00114 t->Coll.cool,
00115 t->Coll.heat ,
00116 opac.opacity_abs[t->ipCont-1],
00117 opac.albedo[t->ipCont-1]);
00118
00119 fprintf( ioQQQ,
00120 " Tin%.1e Tout%.1e Esc%.1e eEsc%.1e DesP%.1e Pump%.1e OTS%.1e PopL,U %.1e %.1e PopOpc%.1e\n",
00121 t->Emis->TauIn,
00122 t->Emis->TauTot,
00123 t->Emis->Pesc,
00124 t->Emis->Pelec_esc,
00125 t->Emis->Pdest,
00126 t->Emis->pump,
00127 t->Emis->ots,
00128 t->Lo->Pop,
00129 t->Hi->Pop ,
00130 t->Emis->PopOpc );
00131 return;
00132 }
00133
00134
00135
00136 double OccupationNumberLine( transition * t )
00137 {
00138 double OccupationNumberLine_v;
00139
00140 DEBUG_ENTRY( "OccupationNumberLine()" );
00141
00142 ASSERT( t->ipCont > 0 );
00143
00144
00145 if( t->Lo->Pop > SMALLFLOAT )
00146 {
00147
00148 double PopLo_corr = t->Lo->Pop / t->Lo->g - t->Hi->Pop / t->Hi->g;
00149 OccupationNumberLine_v = ( t->Hi->Pop / t->Hi->g )/SDIV(PopLo_corr ) *
00150 (1. - t->Emis->Pesc);
00151 }
00152 else
00153 {
00154 OccupationNumberLine_v = 0.;
00155 }
00156 return( OccupationNumberLine_v );
00157 }
00158
00159
00160 double TexcLine(transition * t)
00161 {
00162 double TexcLine_v;
00163
00164 DEBUG_ENTRY( "TexcLine()" );
00165
00166
00167
00168 if( t->Hi->Pop * t->Lo->Pop > 0. )
00169 {
00170 TexcLine_v = ( t->Hi->Pop / t->Hi->g )/( t->Lo->Pop / t->Lo->g );
00171 TexcLine_v = log(TexcLine_v);
00172
00173 if( fabs(TexcLine_v) > SMALLFLOAT )
00174 {
00175 TexcLine_v = - t->EnergyK / TexcLine_v;
00176 }
00177 }
00178 else
00179 {
00180 TexcLine_v = 0.;
00181 }
00182 return( TexcLine_v );
00183 }
00184
00185
00186 double eina(double gf,
00187 double enercm,
00188 double gup)
00189 {
00190 double eina_v;
00191
00192 DEBUG_ENTRY( "eina()" );
00193
00194
00195
00196
00197
00198 eina_v = (gf/gup)*TRANS_PROB_CONST*POW2(enercm);
00199 return( eina_v );
00200 }
00201
00202
00203 double GetGF(double trans_prob,
00204 double enercm,
00205 double gup)
00206 {
00207 double GetGF_v;
00208
00209 DEBUG_ENTRY( "GetGF()" );
00210
00211 ASSERT( enercm > 0. );
00212 ASSERT( trans_prob > 0. );
00213 ASSERT( gup > 0.);
00214
00215
00216
00217
00218
00219 GetGF_v = trans_prob*gup/TRANS_PROB_CONST/POW2(enercm);
00220 return( GetGF_v );
00221 }
00222
00223
00224 double abscf(double gf,
00225 double enercm,
00226 double gl)
00227 {
00228 double abscf_v;
00229
00230 DEBUG_ENTRY( "abscf()" );
00231
00232 ASSERT(gl > 0. && enercm > 0. && gf > 0. );
00233
00234
00235
00236
00237 abscf_v = 1.4974e-6*(gf/gl)*(1e4/enercm);
00238 return( abscf_v );
00239 }
00240
00241
00242 void chIonLbl(char *chIonLbl_v , transition * t )
00243 {
00244
00245
00246 DEBUG_ENTRY( "chIonLbl()" );
00247
00248
00249
00250
00251
00252 if( t->Hi->nelem < 0 )
00253 {
00254
00255 strcpy( chIonLbl_v, "Dumy" );
00256 }
00257 else if( t->Hi->nelem-1 >= LIMELM )
00258 {
00259
00260
00261
00262 strcpy( chIonLbl_v , elementnames.chElementNameShort[t->Hi->nelem-1] );
00263
00264
00265
00266 }
00267
00268 else
00269 {
00270 ASSERT( t->Hi->nelem >= 1 );
00271
00272
00273 strcpy( chIonLbl_v , elementnames.chElementSym[t->Hi->nelem -1] );
00274
00275
00276 strcat( chIonLbl_v, elementnames.chIonStage[t->Hi->IonStg-1]);
00277 }
00278
00279 return;
00280 }
00281
00282
00283
00284
00285 char* chLineLbl(transition * t )
00286 {
00287 static char chLineLbl_v[11];
00288
00289 DEBUG_ENTRY( "chLineLbl()" );
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 if( t->WLAng > (realnum)INT_MAX )
00301 {
00302 sprintf( chLineLbl_v, "%2.2s%2.2s%5i%c",
00303 elementnames.chElementSym[t->Hi->nelem -1],
00304 elementnames.chIonStage[t->Hi->IonStg-1],
00305 (int)(t->WLAng/1e8), 'c' );
00306 }
00307 else if( t->WLAng > 9999999. )
00308 {
00309
00310 sprintf( chLineLbl_v, "%2.2s%2.2s%5.2f%c",
00311 elementnames.chElementSym[t->Hi->nelem -1],
00312 elementnames.chIonStage[t->Hi->IonStg-1],
00313 t->WLAng/1e8, 'c' );
00314 }
00315 else if( t->WLAng > 999999. )
00316 {
00317
00318 sprintf( chLineLbl_v, "%2.2s%2.2s%5i%c",
00319 elementnames.chElementSym[t->Hi->nelem -1],
00320 elementnames.chIonStage[t->Hi->IonStg-1],
00321 (int)(t->WLAng/1e4), 'm' );
00322 }
00323 else if( t->WLAng > 99999. )
00324 {
00325
00326 sprintf( chLineLbl_v, "%2.2s%2.2s%5.1f%c",
00327 elementnames.chElementSym[t->Hi->nelem -1],
00328 elementnames.chIonStage[t->Hi->IonStg-1],
00329 t->WLAng/1e4, 'm' );
00330 }
00331 else if( t->WLAng > 9999. )
00332 {
00333 sprintf( chLineLbl_v, "%2.2s%2.2s%5.2f%c",
00334 elementnames.chElementSym[ t->Hi->nelem -1],
00335 elementnames.chIonStage[t->Hi->IonStg-1],
00336 t->WLAng/1e4, 'm' );
00337 }
00338 else if( t->WLAng >= 100. )
00339 {
00340 sprintf( chLineLbl_v, "%2.2s%2.2s%5i%c",
00341 elementnames.chElementSym[ t->Hi->nelem -1],
00342 elementnames.chIonStage[t->Hi->IonStg-1],
00343 (int)t->WLAng, 'A' );
00344 }
00345
00346
00347 else if( t->WLAng >= 10. )
00348 {
00349 sprintf( chLineLbl_v, "%2.2s%2.2s%5.1f%c",
00350 elementnames.chElementSym[ t->Hi->nelem -1],
00351 elementnames.chIonStage[t->Hi->IonStg-1],
00352 t->WLAng, 'A' );
00353 }
00354 else
00355 {
00356 sprintf( chLineLbl_v, "%2.2s%2.2s%5.2f%c",
00357 elementnames.chElementSym[ t->Hi->nelem -1],
00358 elementnames.chIonStage[t->Hi->IonStg-1],
00359 t->WLAng, 'A' );
00360 }
00361
00362
00363 ASSERT( chLineLbl_v[10]==0 );
00364 return( chLineLbl_v );
00365 }
00366
00367
00368
00369 double RefIndex(double EnergyWN )
00370 {
00371 double RefIndex_v,
00372 WaveMic,
00373 xl,
00374 xn;
00375
00376 DEBUG_ENTRY( "RefIndex()" );
00377
00378 ASSERT( EnergyWN > 0. );
00379
00380
00381 WaveMic = 1.e4/EnergyWN;
00382
00383
00384 if( WaveMic > 0.2 )
00385 {
00386
00387
00388 xl = 1.0/WaveMic/WaveMic;
00389
00390
00391
00392 xn = 255.4/(41. - xl);
00393 xn += 29498.1/(146. - xl);
00394 xn += 64.328;
00395 RefIndex_v = xn/1.e6 + 1.;
00396 }
00397 else
00398 {
00399 RefIndex_v = 1.;
00400 }
00401 ASSERT( RefIndex_v > 0. );
00402 return( RefIndex_v );
00403 }
00404
00405
00406 void PutCS(double cs,
00407 transition * t)
00408 {
00409
00410 DEBUG_ENTRY( "PutCS()" );
00411
00412
00413
00414 ASSERT( cs >= 0. );
00415
00416 t->Coll.cs = (realnum)cs;
00417 return;
00418 }
00419
00420
00421
00422
00423
00424
00425 realnum WavlenErrorGet( realnum wavelength )
00426 {
00427 double a;
00428 realnum errorwave;
00429
00430 DEBUG_ENTRY( "WavlenErrorGet()" );
00431
00432 ASSERT( LineSave.sig_figs <= 6 );
00433
00434 if( wavelength > 0. )
00435 {
00436
00437 a = log10( wavelength+FLT_EPSILON);
00438 a = floor(a);
00439 }
00440 else
00441 {
00442
00443
00444 a = 0.;
00445 }
00446
00447 errorwave = 5.f * (realnum)pow( 10., a - (double)LineSave.sig_figs );
00448 return errorwave;
00449 }
00450
00451
00452 void linadd(
00453 double xInten,
00454 realnum wavelength,
00455 const char *chLab,
00456 char chInfo,
00457
00458 const char *chComment )
00459 {
00460 DEBUG_ENTRY( "linadd()" );
00461
00462
00463
00464
00465
00466
00467
00468 if( LineSave.ipass > 0 )
00469 {
00470
00471
00472 LineSv[LineSave.nsum].sumlin[0] += xInten*radius.dVeff;
00473
00474 LineSv[LineSave.nsum].emslin[0] = xInten;
00475
00476
00477 if( wavelength > 0 )
00478 {
00479
00480
00481
00482 LineSv[LineSave.nsum].emslin[1] = LineSv[LineSave.nsum].emslin[0];
00483 LineSv[LineSave.nsum].sumlin[1] = LineSv[LineSave.nsum].sumlin[0];
00484 }
00485 }
00486
00487 else if( LineSave.ipass == 0 )
00488 {
00489
00490
00491
00492 ASSERT( (chInfo == 'c') || (chInfo == 'h') || (chInfo == 'i') || (chInfo == 'r' ) );
00493
00494
00495 LineSv[LineSave.nsum].chSumTyp = (char)chInfo;
00496
00497
00498 LineSv[LineSave.nsum].sumlin[0] = 0.;
00499 LineSv[LineSave.nsum].emslin[0] = 0.;
00500 LineSv[LineSave.nsum].wavelength = wavelength;
00501 LineSv[LineSave.nsum].sumlin[1] = 0.;
00502 LineSv[LineSave.nsum].emslin[1] = 0.;
00503 LineSv[LineSave.nsum].chComment = chComment;
00504
00505
00506 ASSERT( strlen( chLab )<5 );
00507 strcpy( LineSv[LineSave.nsum].chALab, chLab );
00508 }
00509
00510
00511 ++LineSave.nsum;
00512
00513
00514
00515 return;
00516 }
00517
00518
00519
00520 static double EnergyRyd;
00521
00522
00523 double emergent_line(
00524
00525 double emissivity_in ,
00526
00527 double emissivity_out ,
00528
00529 long int ipCont )
00530 {
00531
00532 double emergent_in , emergent_out;
00533 long int i = ipCont-1;
00534
00535 DEBUG_ENTRY( "emergent_line()" );
00536
00537 ASSERT( i >= 0 && i < rfield.nupper-1 );
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 if( iteration == 1 )
00549 {
00550
00551
00552 emergent_in = emissivity_in*opac.E2TauAbsFace[i];
00553 emergent_out = emissivity_out;
00554 }
00555 else
00556 {
00557 if( geometry.lgSphere )
00558 {
00559
00560
00561
00562 emergent_in = emissivity_in * opac.E2TauAbsFace[i] *opac.E2TauAbsTotal[i];
00563
00564
00565 emergent_out = emissivity_out * opac.E2TauAbsOut[i];
00566 }
00567 else
00568 {
00569
00570
00571
00572 double reflected = emissivity_out * opac.albedo[i] * (1.-opac.E2TauAbsOut[i]);
00573
00574 emergent_in = (emissivity_in + reflected) * opac.E2TauAbsFace[i];
00575
00576 emergent_out = (emissivity_out - reflected) * opac.E2TauAbsOut[i];
00577 }
00578 }
00579
00580 return( (emergent_in + emergent_out) );
00581 }
00582
00583
00584 void lindst(
00585
00586 double xInten,
00587
00588 realnum wavelength,
00589
00590 const char *chLab,
00591
00592 long int ipnt,
00593
00594 char chInfo,
00595
00596 bool lgOutToo,
00597
00598 const char *chComment )
00599 {
00600 double saveemis;
00601 DEBUG_ENTRY( "lindst()" );
00602
00603
00604
00605 if( LineSave.ipass > 0 && xInten > 0. )
00606 {
00607
00608
00609 LineSv[LineSave.nsum].emslin[0] = xInten;
00610
00611 LineSv[LineSave.nsum].sumlin[0] += xInten*radius.dVeff;
00612
00613
00614
00615
00616
00617
00618
00619 if( lgOutToo )
00620 {
00621 rfield.outlin[ipnt-1] += (realnum)(xInten/(rfield.anu[ipnt-1]*EN1RYD)*
00622 radius.dVolOutwrd*opac.ExpZone[ipnt-1]);
00623 rfield.reflin[ipnt-1] += (realnum)(xInten/(rfield.anu[ipnt-1]*EN1RYD)*
00624 radius.dVolReflec);
00625 }
00626
00627 if( ipnt <= rfield.nflux )
00628 {
00629
00630
00631 saveemis = emergent_line(
00632 xInten*rt.fracin , xInten*(1.-rt.fracin) , ipnt );
00633 LineSv[LineSave.nsum].emslin[1] = saveemis;
00634 LineSv[LineSave.nsum].sumlin[1] += saveemis*radius.dVeff;
00635 }
00636 }
00637 else if( LineSave.ipass == 0 )
00638 {
00639 ASSERT( ipnt > 0 );
00640
00641
00642
00643
00644 ASSERT( (chInfo == 'c') || (chInfo == 'h') || (chInfo == 'i') || (chInfo == 'r' ) );
00645 LineSv[LineSave.nsum].chSumTyp = (char)chInfo;
00646
00647 LineSv[LineSave.nsum].sumlin[0] = 0.;
00648 LineSv[LineSave.nsum].emslin[0] = 0.;
00649 LineSv[LineSave.nsum].wavelength = fabs(wavelength);
00650 LineSv[LineSave.nsum].emslin[1] = 0.;
00651 LineSv[LineSave.nsum].sumlin[1] = 0.;
00652 LineSv[LineSave.nsum].chComment = chComment;
00653
00654
00655
00656 ASSERT( strlen( chLab )<5 );
00657 strcpy( LineSv[LineSave.nsum].chALab, chLab );
00658
00659
00660
00661
00662
00663 double error = MAX2(0.1*rfield.AnuOrg[ipnt-1] , rfield.widflx[ipnt-1] );
00664 ASSERT( wavelength<=0 ||
00665 fabs( rfield.AnuOrg[ipnt-1] - RYDLAM / wavelength) < error );
00666 }
00667
00668
00669 ++LineSave.nsum;
00670
00671 EnergyRyd = 0.;
00672 return;
00673 }
00674
00675
00676 void PntForLine(
00677
00678 double wavelength,
00679
00680 const char *chLabel,
00681
00682
00683 long int *ipnt)
00684 {
00685
00686
00687
00688
00689
00690 # define MAXFORLIN 1000
00691 static long int ipForLin[MAXFORLIN]={0};
00692
00693
00694 static long int nForLin;
00695
00696 DEBUG_ENTRY( "PntForLine()" );
00697
00698
00699 ASSERT( wavelength >= 0. );
00700
00701 if( wavelength == 0. )
00702 {
00703
00704 nForLin = 0;
00705
00706 EnergyRyd = 0.;
00707 }
00708 else
00709 {
00710
00711 if( LineSave.ipass > 0 )
00712 {
00713
00714 *ipnt = ipForLin[nForLin];
00715 }
00716 else if( LineSave.ipass == 0 )
00717 {
00718
00719 if( nForLin >= MAXFORLIN )
00720 {
00721 fprintf( ioQQQ, "PROBLEM %5ld lines is too many for PntForLine.\n",
00722 nForLin );
00723 fprintf( ioQQQ, " Increase the value of maxForLine everywhere in the code.\n" );
00724 cdEXIT(EXIT_FAILURE);
00725 }
00726
00727
00728 EnergyRyd = RYDLAM/wavelength;
00729 ipForLin[nForLin] = ipLineEnergy(EnergyRyd,chLabel , 0);
00730 *ipnt = ipForLin[nForLin];
00731 }
00732 else
00733 {
00734
00735 *ipnt = 0;
00736 }
00737 ++nForLin;
00738 }
00739 return;
00740 }
00741
00742 static realnum ExtraInten;
00743
00744
00745 void PutLine(transition * t, const char *chComment, const char *chLabelTemp)
00746 {
00747 char chLabel[5];
00748 double xIntensity,
00749 other,
00750 xIntensity_in;
00751
00752 DEBUG_ENTRY( "PutLine()" );
00753
00754
00755
00756 ASSERT( t->ipCont > 0. );
00757
00758 strcpy( chLabel, chLabelTemp );
00759 chLabel[4] = '\0';
00760
00761
00762
00763 if( LineSave.ipass == 0 )
00764 {
00765 xIntensity = 0.;
00766 }
00767 else
00768 {
00769
00770
00771 chLabel[0] = '\n';
00772
00773
00774 xIntensity = t->Emis->xIntensity + ExtraInten;
00775 }
00776
00777
00778
00779
00780
00781
00782 ExtraInten = 0.;
00783
00784
00785 rt.fracin = t->Emis->FracInwd;
00786 lindst(xIntensity,
00787 t->WLAng,
00788 chLabel,
00789 t->ipCont,
00790
00791 'i',
00792
00793 false,
00794 chComment);
00795 rt.fracin = 0.5;
00796
00797
00798
00799 xIntensity_in = xIntensity*t->Emis->FracInwd;
00800 linadd(xIntensity_in,t->WLAng,"Inwd",'i',chComment);
00801
00802
00803 other = t->Coll.cool;
00804 linadd(other,t->WLAng,"Coll",'i',chComment);
00805
00806
00807 other = t->Emis->PopOpc * t->Emis->pump * (1.-t->Emis->ColOvTot) * t->EnergyErg;
00808 linadd(other,t->WLAng,"Pump",'i',chComment);
00809
00810
00811 other = t->Coll.heat;
00812 linadd(other,t->WLAng,"Heat",'i',chComment);
00813 return;
00814 }
00815
00816
00817 void PutLine(transition * t,
00818 const char *chComment)
00819 {
00820 char chLabel[5];
00821 double xIntensity,
00822 other,
00823 xIntensity_in;
00824
00825 DEBUG_ENTRY( "PutLine()" );
00826
00827
00828
00829 ASSERT( t->ipCont > 0. );
00830
00831
00832
00833 if( LineSave.ipass == 0 )
00834 {
00835
00836
00837 chIonLbl(chLabel, t);
00838
00839 xIntensity = 0.;
00840 }
00841 else
00842 {
00843
00844
00845
00846 chLabel[0] = '\n';
00847
00848
00849 xIntensity = t->Emis->xIntensity + ExtraInten;
00850 }
00851
00852
00853
00854
00855
00856
00857 ExtraInten = 0.;
00858
00859 rt.fracin = t->Emis->FracInwd;
00860 lindst(xIntensity,
00861 t->WLAng,
00862 chLabel,
00863 t->ipCont,
00864
00865 'i',
00866
00867 false,
00868 chComment);
00869 rt.fracin = 0.5;
00870
00871
00872
00873 xIntensity_in = xIntensity*t->Emis->FracInwd;
00874 linadd(xIntensity_in,t->WLAng,"Inwd",'i',chComment);
00875
00876
00877 other = t->Coll.cool;
00878 linadd(other,t->WLAng,"Coll",'i',chComment);
00879
00880
00881 other = t->Emis->PopOpc * t->Emis->pump * (1.-t->Emis->ColOvTot) * t->EnergyErg;
00882 linadd(other,t->WLAng,"Pump",'i',chComment);
00883
00884
00885 other = t->Coll.heat;
00886 linadd(other,t->WLAng,"Heat",'i',chComment);
00887 return;
00888 }
00889
00890
00891
00892 void PutExtra(double Extra)
00893 {
00894
00895 DEBUG_ENTRY( "PutExtra()" );
00896
00897 ExtraInten = (realnum)Extra;
00898 return;
00899 }
00900
00901 void TransitionJunk( transition *t )
00902 {
00903
00904 DEBUG_ENTRY( "TransitionJunk()" );
00905
00906
00907 t->WLAng = -FLT_MAX;
00908
00909
00910 t->EnergyK = -FLT_MAX;
00911
00912 t->EnergyErg = -FLT_MAX;
00913
00914 t->EnergyWN = -FLT_MAX;
00915
00916
00917
00918 t->ipCont = -10000;
00919
00920 CollisionJunk( &t->Coll );
00921
00922
00923
00924 t->Emis = &DummyEmis;
00925
00926 t->Lo = NULL;
00927 t->Hi = NULL;
00928 return;
00929 }
00930
00931
00932
00933 void EmLineJunk( emission *t )
00934 {
00935
00936 DEBUG_ENTRY( "EmLineJunk()" );
00937
00938
00939 t->TauCon = -FLT_MAX;
00940
00941
00942 t->TauIn = -FLT_MAX;
00943 t->TauTot = -FLT_MAX;
00944
00945
00946 t->iRedisFun = INT_MIN;
00947
00948
00949 t->ipFine = -10000;
00950
00951
00952 t->FracInwd = -FLT_MAX;
00953
00954
00955 t->pump = -FLT_MAX;
00956
00957
00958 t->xIntensity = -FLT_MAX;
00959
00960
00961 t->phots = -FLT_MAX;
00962
00963
00964 t->gf = -FLT_MAX;
00965
00966
00967 t->Pesc = -FLT_MAX;
00968 t->Pdest = -FLT_MAX;
00969 t->Pelec_esc = -FLT_MAX;
00970
00971
00972 t->dampXvel = -FLT_MAX;
00973 t->damp = -FLT_MAX;
00974
00975
00976 t->ColOvTot = -FLT_MAX;
00977
00978
00979 t->opacity = -FLT_MAX;
00980
00981 t->PopOpc = -FLT_MAX;
00982
00983
00984 t->Aul = -FLT_MAX;
00985
00986
00987 t->ots = -FLT_MAX;
00988 return;
00989 }
00990
00991
00992 void CollisionJunk( collision * t )
00993 {
00994
00995 DEBUG_ENTRY( "CollisionJunk()" );
00996
00998 t->ColUL = -FLT_MAX;
00999
01000
01001 t->cool = -FLT_MAX;
01002 t->heat = -FLT_MAX;
01003
01004
01005 t->cs = -FLT_MAX;
01006 for( long i=0; i<ipNCOLLIDER; i++ )
01007 t->csi[i] = -FLT_MAX;
01008 return;
01009 }
01010
01011
01012 void StateJunk( quantumState * t )
01013 {
01014
01015 DEBUG_ENTRY( "StateJunk()" );
01016
01017
01018
01020 t->g = -FLT_MAX;
01021
01023 t->Pop = -FLT_MAX;
01024
01026 t->IonStg = -10000;
01027
01029 t->nelem = -10000;
01030 return;
01031 }
01032
01033
01034 void TransitionZero( transition *t )
01035 {
01036
01037 DEBUG_ENTRY( "TransitionZero()" );
01038
01039 CollisionZero( &t->Coll );
01040
01041 StateZero( t->Lo );
01042 StateZero( t->Hi );
01043 EmLineZero( t->Emis );
01044
01045 return;
01046 }
01047
01048
01049 void EmLineZero( emission * t )
01050 {
01051
01052 DEBUG_ENTRY( "EmLineZero()" );
01053
01054
01055
01056 t->TauCon = opac.taumin;
01057
01058
01059
01060 t->TauIn = opac.taumin;
01061
01062
01063 t->TauTot = 1e20f;
01064
01065
01066
01067 t->FracInwd = 1.;
01068
01069
01070 t->pump = 0.;
01071
01072
01073 t->xIntensity = 0.;
01074
01075
01076 t->phots = 0.;
01077
01078
01079
01080 t->Pesc = 1.;
01081 t->Pdest = 0.;
01082 t->Pelec_esc = 0.;
01083
01084
01085 t->ColOvTot = 0.;
01086
01087
01088 t->PopOpc = 0.;
01089
01090
01091 t->ots = 0.;
01092 return;
01093 }
01094
01095
01096 void CollisionZero( collision * t )
01097 {
01098
01099 DEBUG_ENTRY( "CollisionZero()" );
01100
01101
01102 t->cool = 0.;
01103 t->heat = 0.;
01104 return;
01105 }
01106
01107
01108 void StateZero( quantumState * t )
01109 {
01110
01111 DEBUG_ENTRY( "StateZero()" );
01112
01114 t->Pop = 0.;
01115 return;
01116 }
01117
01118
01119 void LineConvRate2CS( transition* t , realnum rate )
01120 {
01121
01122 DEBUG_ENTRY( "LineConvRate2CS()" );
01123
01124
01125
01126
01127 t->Coll.cs = rate * t->Hi->g / (realnum)dense.cdsqte;
01128
01129
01130
01131 ASSERT( t->Coll.cs >= 0. );
01132 return;
01133 }
01134
01135
01136 double ConvRate2CS( realnum gHi , realnum rate )
01137 {
01138
01139 double cs;
01140
01141 DEBUG_ENTRY( "ConvRate2CS()" );
01142
01143
01144
01145
01146 cs = rate * gHi / dense.cdsqte;
01147
01148
01149
01150 ASSERT( cs >= 0. );
01151 return cs;
01152 }
01153
01154
01155 bool lgTauGood( transition * t)
01156 {
01157 bool lgGoodTau;
01158
01159 DEBUG_ENTRY( "lgTauGood()" );
01160
01161 if( (t->Emis->TauTot*0.9 - t->Emis->TauIn < 0. && t->Emis->TauIn > 0.) &&
01162 ! fp_equal( t->Emis->TauTot, opac.taumin ) )
01163 {
01164
01165 lgGoodTau = false;
01166 }
01167 else
01168 {
01169 lgGoodTau = true;
01170 }
01171 return lgGoodTau;
01172 }
01173
01174
01175 STATIC void gbar0(double ex,
01176 realnum *g)
01177 {
01178 double a,
01179 b,
01180 c,
01181 d,
01182 y;
01183
01184 DEBUG_ENTRY( "gbar0()" );
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199 y = ex/phycon.te;
01200 if( y < 0.01 )
01201 {
01202 *g = (realnum)(0.29*(log(1.0+1.0/y) - 0.4/POW2(y + 1.0))/exp(y));
01203 }
01204 else
01205 {
01206 if( y > 10.0 )
01207 {
01208 *g = (realnum)(0.066/sqrt(y));
01209 }
01210 else
01211 {
01212 a = 1.5819068e-02;
01213 b = 1.3018207e00;
01214 c = 2.6896230e-03;
01215 d = 2.5486007e00;
01216 d = log(y/c)/d;
01217 *g = (realnum)(a + b*exp(-0.5*POW2(d)));
01218 }
01219 }
01220 return;
01221 }
01222
01223
01224 STATIC void gbar1(double ex,
01225 realnum *g)
01226 {
01227 double y;
01228
01229 DEBUG_ENTRY( "gbar1()" );
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 y = ex/phycon.te;
01245 *g = (realnum)(0.6 + 0.28*(log(1.0+1.0/y) - 0.4/POW2(y + 1.0)));
01246 return;
01247 }
01248
01249
01250 void MakeCS(transition * t)
01251 {
01252 long int ion;
01253 double Abun,
01254 cs;
01255 realnum
01256 gbar;
01257
01258 DEBUG_ENTRY( "MakeCS()" );
01259
01260
01261
01262
01263 ion = t->Hi->IonStg;
01264
01265 Abun = dense.xIonDense[ t->Hi->nelem -1 ][ ion-1 ];
01266 if( Abun <= 0. )
01267 {
01268 gbar = 1.;
01269 }
01270 else
01271 {
01272
01273 if( ion == 1 )
01274 {
01275
01276 gbar0(t->EnergyK,&gbar);
01277 }
01278 else
01279 {
01280
01281 gbar1(t->EnergyK,&gbar);
01282 }
01283 }
01284
01285
01286 cs = gbar*(14.5104/WAVNRYD)*t->Emis->gf/t->EnergyWN;
01287
01288
01289 t->Coll.cs = (realnum)cs;
01290 return;
01291 }
01292
01293
01294 double totlin(
01295
01296
01297
01298
01299 int chInfo)
01300 {
01301 long int i;
01302 double totlin_v;
01303
01304 DEBUG_ENTRY( "totlin()" );
01305
01306
01307
01308
01309
01310
01311 if( (chInfo != 'i' && chInfo != 'r') && chInfo != 'c' )
01312 {
01313 fprintf( ioQQQ, " TOTLIN does not understand chInfo=%c\n",
01314 chInfo );
01315 cdEXIT(EXIT_FAILURE);
01316 }
01317
01318
01319
01320 totlin_v = 0.;
01321 for( i=0; i < LineSave.nsum; i++ )
01322 {
01323 if( LineSv[i].chSumTyp == chInfo )
01324 {
01325 totlin_v += LineSv[i].sumlin[0];
01326 }
01327 }
01328 return( totlin_v );
01329 }
01330
01331
01332
01333 void FndLineHt(long int *level,
01334
01335 long int *ipStrong,
01336 double *Strong)
01337 {
01338 long int i;
01339
01340 DEBUG_ENTRY( "FndLineHt()" );
01341
01342 *Strong = 0.;
01343 *level = 0;
01344
01345
01346 for( i=1; i <= nLevel1; i++ )
01347 {
01348
01349 if( TauLines[i].Coll.heat > *Strong )
01350 {
01351 *ipStrong = i;
01352 *level = 1;
01353 *Strong = TauLines[i].Coll.heat;
01354 }
01355 }
01356
01357
01358 for( i=0; i < nWindLine; i++ )
01359 {
01360 if( TauLine2[i].Hi->IonStg < TauLine2[i].Hi->nelem+1-NISO )
01361 {
01362
01363 if( TauLine2[i].Coll.heat > *Strong )
01364 {
01365 *ipStrong = i;
01366 *level = 2;
01367 *Strong = TauLine2[i].Coll.heat;
01368 }
01369 }
01370 }
01371
01372
01373 for( i=0; i < nCORotate; i++ )
01374 {
01375
01376 if( C12O16Rotate[i].Coll.heat > *Strong )
01377 {
01378 *ipStrong = i;
01379 *level = 3;
01380 *Strong = C12O16Rotate[i].Coll.heat;
01381 }
01382 }
01383 for( i=0; i < nCORotate; i++ )
01384 {
01385
01386 if( C13O16Rotate[i].Coll.heat > *Strong )
01387 {
01388 *ipStrong = i;
01389 *level = 4;
01390 *Strong = C13O16Rotate[i].Coll.heat;
01391 }
01392 }
01393
01394
01395 for( i=0; i < nHFLines; i++ )
01396 {
01397
01398 if( HFLines[i].Coll.heat > *Strong )
01399 {
01400 *ipStrong = i;
01401 *level = 5;
01402 *Strong = HFLines[i].Coll.heat;
01403 }
01404 }
01405
01406
01407 for( i=0; i <linesAdded2; i++)
01408 {
01409
01410 if( atmolEmis[i].tran->Coll.heat > *Strong )
01411 {
01412 *ipStrong = i;
01413 *level = 6;
01414 *Strong = atmolEmis[i].tran->Coll.heat;
01415 }
01416 }
01417 return;
01418 }
01419
01420 quantumState *AddState2Stack( void )
01421 {
01422 DEBUG_ENTRY( "AddState2Stack()" );
01423
01424 ASSERT( !lgStatesAdded );
01425
01426 currentState = new quantumState;
01427
01428 StateJunk( currentState );
01429
01430 if( statesAdded == 0 )
01431 {
01432 GenericStates = currentState;
01433 GenericStates->next = NULL;
01434 lastState = GenericStates;
01435 }
01436 else
01437 {
01438 StateZero( currentState );
01439 lastState->next = currentState;
01440 lastState = lastState->next;
01441 }
01442
01443 statesAdded++;
01444
01445 return currentState;
01446 }
01447
01448 emission *AddLine2Stack( bool lgRadiativeTrans )
01449 {
01450 DEBUG_ENTRY( "AddLine2Stack()" );
01451
01452 if( !lgRadiativeTrans )
01453 {
01454 return &DummyEmis;
01455 }
01456 else
01457 {
01458 ASSERT( lgLinesAdded == false );
01459
01460 currentLine = new emission;
01461
01462 EmLineJunk( currentLine );
01463
01464 if( linesAdded == 0 )
01465 {
01466 GenericLines = currentLine;
01467 GenericLines->next = NULL;
01468 lastLine = GenericLines;
01469 }
01470 else
01471 {
01472
01473
01474
01475
01476 EmLineZero( currentLine );
01477
01478 lastLine->next = currentLine;
01479 lastLine = lastLine->next;
01480 }
01481
01482 linesAdded++;
01483 return currentLine;
01484 }
01485 }