00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "cddefines.h"
00014 #include "physconst.h"
00015 #include "dense.h"
00016 #include "conv.h"
00017 #include "rfield.h"
00018 #include "opacity.h"
00019 #include "lines_service.h"
00020 #include "taulines.h"
00021 #include "doppvel.h"
00022 #include "pressure.h"
00023 #include "wind.h"
00024 #include "rt.h"
00025 #include "iso.h"
00026 #include "thirdparty.h"
00027
00028 inline double tau_from_here(double tau_tot, double tau_in)
00029 {
00030 const double SCALE = 2.;
00031 double tt = tau_tot - tau_in;
00032 if (1)
00033 {
00034
00035
00036
00037
00038 if( tt < 0. )
00039 {
00040 tt = tau_in/SCALE;
00041 }
00042 }
00043 else
00044 {
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 tt = fabs(tt);
00058 }
00059 return tt;
00060 }
00061
00062
00063 class my_Integrand_escConE2
00064 {
00065 public:
00066 double chnukt_ContTkt, chnukt_ctau;
00067
00068 double operator() (double x)
00069 {
00070 return exp(-chnukt_ContTkt*(x-1.))/x*e2(chnukt_ctau/POW3(x));
00071 }
00072 };
00073
00074
00075 class my_Integrand_conrec
00076 {
00077 public:
00078 double chnukt_ContTkt;
00079
00080 double operator() (double x)
00081 {
00082 return exp(-chnukt_ContTkt*(x-1.))/x;
00083 }
00084 };
00085
00086
00087
00088 STATIC double escmase(double tau);
00089
00090 STATIC void RTesc_lya_1side(double taume,
00091 double beta,
00092 realnum *esc,
00093 realnum *dest,
00094
00095 long ipLine );
00096
00097 double esc_PRD_1side(double tau,
00098 double a)
00099 {
00100 double atau,
00101 b,
00102 escinc_v;
00103
00104 DEBUG_ENTRY( "esc_PRD_1side()" );
00105 ASSERT( a>0.0 );
00106
00107
00108
00109
00110
00111 # if 0
00112 if( strcmp(rt.chEscFunSubord,"SIMP") == 0 )
00113 {
00114
00115 escinc_v = 1./(1. + tau);
00116 return escinc_v;
00117 }
00118 # endif
00119
00120 if( tau < 0. )
00121 {
00122
00123 escinc_v = escmase(tau);
00124 }
00125 else
00126 {
00127
00128 atau = a*tau;
00129 if( atau > 1. )
00130 {
00131 b = 1.6 + (3.*pow(2.*a,-0.12))/(1. + atau);
00132 }
00133 else
00134 {
00135 double sqrtatau = sqrt(atau);
00136 b = 1.6 + (3.*pow(2.*a,-0.12))*sqrtatau/(1. + sqrtatau);
00137 }
00138 b = MIN2(6.,b);
00139
00140 escinc_v = 1./(1. + b*tau);
00141 }
00142 return escinc_v;
00143 }
00144
00145
00146
00147
00148
00149 class k2DampArg
00150 {
00151 realnum damp, tau;
00152 public:
00153 k2DampArg(realnum damp, realnum tau) : damp(damp), tau(tau) {}
00154
00155 realnum operator()(realnum y) const
00156 {
00157 if (y >= 1.)
00158 return 0;
00159 realnum x = y/(1.-y);
00160 realnum phi;
00161 VoigtU(damp,&x,&phi,1);
00162 if (phi <= 0.)
00163 {
00164 return 0.;
00165 }
00166 else
00167 {
00168 return phi*expn(2,phi*tau)/POW2(1.-y);
00169 }
00170 }
00171 };
00172
00173 template<class F>
00174 double trapezium(realnum xmin, realnum xmax, const F func)
00175 {
00176 double tol = 1e-6;
00177 vector<double> vxmin, vxmax, fxmin, fxmax, step;
00178 vxmin.push_back(xmin);
00179 vxmax.push_back(xmax);
00180 fxmin.push_back(func(xmin));
00181 fxmax.push_back(func(xmax));
00182 step.push_back(0.5*(xmax-xmin)*(fxmin[0]+fxmax[0]));
00183 for (long level = 0; level < 25; ++level)
00184 {
00185 size_t nstep = step.size();
00186 double current = 0.0;
00187 for (size_t i=0; i<nstep; ++i)
00188 current += step[i];
00189 for (size_t i=0; i<nstep; ++i)
00190 {
00191 if (vxmax[i] > vxmin[i])
00192 {
00193 if (level <= 3 || step[i] > tol*current
00194 || (i == nstep-1 && current <= 0.0) )
00195 {
00196 double xbar=0.5*(vxmin[i]+vxmax[i]);
00197 vxmin.push_back(xbar);
00198 fxmin.push_back(func(xbar));
00199 vxmax.push_back(vxmax[i]);
00200 fxmax.push_back(fxmax[i]);
00201 long ilast = vxmax.size()-1;
00202 vxmax[i] = xbar;
00203 fxmax[i] = fxmin[ilast];
00204 step[i] = 0.5*(vxmax[i]-vxmin[i])*(fxmin[i]+fxmax[i]);
00205
00206
00207 step.push_back(0.5*(vxmax[ilast]-vxmin[ilast])*
00208 (fxmin[ilast]+fxmax[ilast]));
00209 }
00210 }
00211 }
00212 }
00213 double current = 0.0;
00214 for (size_t i=0; i<step.size(); ++i)
00215 current += step[i];
00216 return current;
00217 }
00218
00219
00220
00221 double esc_CRDwing_1side(double tau,
00222 double a )
00223 {
00224 DEBUG_ENTRY( "esc_CRDwing_1side()" );
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 if (0)
00237 {
00238
00239
00240 a = 1000.;
00241 double taustep = 2., taumin=1e-8,taumax=1e14;
00242 Integrator<k2DampArg,Gaussian32> IntDamp;
00243 for (tau = taumin; tau < taumax; tau *= taustep)
00244 {
00245 double esccom_v = esca0k2(tau);
00246 double sqrta = sqrt(a);
00247 double pwing = tau > 0.0 ? sqrta/(sqrta+0.5*3.0*sqrt(SQRTPI*tau)) :
00248 1.0;
00249 double esctot = esccom_v*(1.0-pwing)+pwing;
00250 double intgral = IntDamp.sum(0.,1.,k2DampArg(a,SQRTPI*tau));
00251 double intgralt = trapezium(0.,1.,k2DampArg(a,SQRTPI*tau));
00252 fprintf(ioQQQ,"cfesc %15.8g %15.8g %15.8g %15.8g %15.8g %15.8g\n",
00253 tau,a,esccom_v,esctot,2.0*intgral,2.0*intgralt);
00254 }
00255 exit(0);
00256 }
00257 double esccom_v = esca0k2(tau);
00258
00259
00260
00261
00262 double sqrta = sqrt(a);
00263 double scal = a*(1.0+a+tau)/(POW2(1.0+a)+a*tau);
00264 double pwing = scal*((tau > 0.0) ? sqrta/sqrt(a+2.25*SQRTPI*tau) : 1.0);
00265 return esccom_v*(1.0-pwing)+pwing;
00266 }
00267
00268
00269
00270
00271 double RTesc_lya(
00272
00273 double *esin,
00274
00275 double *dest,
00276
00277 double abund,
00278 const TransitionProxy& t,
00279 realnum DopplerWidth)
00280 {
00281 double beta,
00282 conopc,
00283 escla_v;
00284 realnum dstin,
00285 dstout;
00286
00287 DEBUG_ENTRY( "RTesc_lya()" );
00288
00289
00290
00291
00292
00293
00294
00295
00296 if( t.Emis().TauTot() - t.Emis().TauIn() < 0. )
00297 {
00298
00299
00300 escla_v = t.Emis().Pesc();
00301 rt.fracin = t.Emis().FracInwd();
00302 *esin = rt.fracin;
00303 *dest = t.Emis().Pdest();
00304 return escla_v;
00305 }
00306
00307
00308 conopc = opac.opacity_abs[ t.ipCont()-1 ];
00309 if( abund > 0. )
00310 {
00311
00312 beta = conopc/(abund/SQRTPI*t.Emis().opacity()/
00313 DopplerWidth + conopc);
00314 }
00315 else
00316 {
00317
00318 beta = 1e-10;
00319 }
00320
00321
00322 RTesc_lya_1side(
00323 t.Emis().TauIn(),
00324 beta,
00325 &rt.wayin,
00326 &dstin,
00327
00328 t.ipCont()-1);
00329
00330 ASSERT( (rt.wayin <= 1.) && (rt.wayin >= 0.) && (dstin <= 1.) && (dstin >= 0.) );
00331
00332
00333 RTesc_lya_1side(MAX2(t.Emis().TauTot()/100.,
00334 t.Emis().TauTot()-t.Emis().TauIn()),
00335 beta,
00336 &rt.wayout,
00337 &dstout,
00338 t.ipCont()-1);
00339
00340 ASSERT( (rt.wayout <= 1.) && (rt.wayout >= 0.) && (dstout <= 1.) && (dstout >= 0.) );
00341
00342
00343 escla_v = (rt.wayin + rt.wayout)/2.;
00344
00345 *esin = rt.wayin;
00346
00347
00348 *dest = (dstin + dstout)/2.f;
00349
00350
00351
00352 *dest = (realnum)MIN2( *dest , 1.-escla_v );
00353
00354 *dest = (realnum)MAX2(0., *dest );
00355
00356
00357 rt.fracin = rt.wayin/(rt.wayin + rt.wayout);
00358 ASSERT( escla_v >=0. && *dest>=0. && *esin>=0. );
00359 return escla_v;
00360 }
00361
00362
00363 double esc_PRD(double tau,
00364 double tau_out,
00365 double damp )
00366 {
00367 double escgrd_v,
00368 tt;
00369
00370 DEBUG_ENTRY( "esc_PRD()" );
00371
00372 ASSERT( damp > 0. );
00373
00374
00375
00376 if( iteration > 1 )
00377 {
00378 tt = tau_from_here(tau_out, tau);
00379
00380 rt.wayin = (realnum)esc_PRD_1side(tau,damp);
00381 rt.wayout = (realnum)esc_PRD_1side(tt,damp);
00382 rt.fracin = rt.wayin/(rt.wayin + rt.wayout);
00383 escgrd_v = 0.5*(rt.wayin + rt.wayout);
00384 }
00385 else
00386 {
00387
00388 rt.fracin = 0.;
00389 rt.wayout = 1.;
00390 escgrd_v = esc_PRD_1side(tau,damp);
00391 rt.wayin = (realnum)escgrd_v;
00392 }
00393
00394 ASSERT( escgrd_v > 0. );
00395 return escgrd_v;
00396 }
00397
00398
00399 double esc_CRDwing(double tau_in,
00400 double tau_out,
00401 double damp)
00402 {
00403 double escgrd_v,
00404 tt;
00405
00406 DEBUG_ENTRY( "esc_CRDwing()" );
00407
00408
00409
00410
00411 if( iteration > 1 )
00412 {
00413
00414
00415 if( tau_out <0 || tau_in < 0. )
00416 {
00417
00418 tt = MIN2( tau_out , tau_in );
00419 tau_in = tt;
00420 }
00421 else
00422 {
00423 tt = tau_from_here(tau_out, tau_in);
00424 }
00425
00426 rt.wayin = (realnum)esc_CRDwing_1side(tau_in,damp);
00427 rt.wayout = (realnum)esc_CRDwing_1side(tt,damp);
00428 rt.fracin = rt.wayin/(rt.wayin + rt.wayout);
00429 escgrd_v = 0.5*(rt.wayin + rt.wayout);
00430 }
00431 else
00432 {
00433
00434 rt.fracin = 0.;
00435 rt.wayout = 1.;
00436 escgrd_v = esc_CRDwing_1side(tau_in,damp);
00437 rt.wayin = (realnum)escgrd_v;
00438 }
00439
00440 ASSERT( escgrd_v > 0. );
00441 return escgrd_v;
00442 }
00443
00444
00445 double esc_CRDcore(double tau_in,
00446 double tau_out)
00447 {
00448 double escgrd_v,
00449 tt;
00450
00451 DEBUG_ENTRY( "esc_CRDcore()" );
00452
00453
00454
00455
00456 if( iteration > 1 )
00457 {
00458
00459
00460 if( tau_out <0 || tau_in < 0. )
00461 {
00462
00463 tt = MIN2( tau_out , tau_in );
00464 tau_in = tt;
00465 }
00466 else
00467 {
00468 tt = tau_from_here(tau_out, tau_in);
00469 }
00470
00471 rt.wayin = (realnum)esca0k2(tau_in);
00472 rt.wayout = (realnum)esca0k2(tt);
00473 rt.fracin = rt.wayin/(rt.wayin + rt.wayout);
00474 escgrd_v = 0.5*(rt.wayin + rt.wayout);
00475 }
00476 else
00477 {
00478
00479 rt.fracin = 0.;
00480 rt.wayout = 1.;
00481 escgrd_v = esca0k2(tau_in);
00482 rt.wayin = (realnum)escgrd_v;
00483 }
00484
00485 ASSERT( escgrd_v > 0. );
00486 return escgrd_v;
00487 }
00488
00489
00490 double esca0k2(double taume)
00491 {
00492 double arg,
00493 esca0k2_v,
00494 suma,
00495 sumb,
00496 sumc,
00497 sumd,
00498 tau;
00499 static const double a[5]={1.00,-0.1117897,-0.1249099917,-9.136358767e-3,
00500 -3.370280896e-4};
00501 static const double b[6]={1.00,0.1566124168,9.013261660e-3,1.908481163e-4,
00502 -1.547417750e-7,-6.657439727e-9};
00503 static const double c[5]={1.000,19.15049608,100.7986843,129.5307533,-31.43372468};
00504 static const double d[6]={1.00,19.68910391,110.2576321,169.4911399,-16.69969409,
00505 -36.664480000};
00506
00507 DEBUG_ENTRY( "esca0k2()" );
00508
00509
00510
00511
00512
00513
00514 tau = taume*SQRTPI;
00515
00516 if( tau < 0. )
00517 {
00518
00519 esca0k2_v = escmase(taume);
00520
00521 }
00522 else if( tau < 0.01 )
00523 {
00524 esca0k2_v = 1. - 2.*tau;
00525
00526 }
00527 else if( tau <= 11. )
00528 {
00529 suma = a[0] + tau*(a[1] + tau*(a[2] + tau*(a[3] + a[4]*tau)));
00530 sumb = b[0] + tau*(b[1] + tau*(b[2] + tau*(b[3] + tau*(b[4] +
00531 b[5]*tau))));
00532 esca0k2_v = tau/2.5066283*log(tau/SQRTPI) + suma/sumb;
00533
00534 }
00535 else
00536 {
00537
00538 arg = 1./log(tau/SQRTPI);
00539 sumc = c[0] + arg*(c[1] + arg*(c[2] + arg*(c[3] + c[4]*arg)));
00540 sumd = d[0] + arg*(d[1] + arg*(d[2] + arg*(d[3] + arg*(d[4] +
00541 d[5]*arg))));
00542 esca0k2_v = (sumc/sumd)/(2.*tau*sqrt(log(tau/SQRTPI)));
00543 }
00544 return esca0k2_v;
00545 }
00546
00547
00548 STATIC void FindNeg( void )
00549 {
00550 long int i;
00551
00552 DEBUG_ENTRY( "FindNeg()" );
00553
00554
00555 for( i=1; i <= nLevel1; i++ )
00556 {
00557
00558 if( TauLines[i].Emis().TauIn() < -1. )
00559 DumpLine(TauLines[i]);
00560 }
00561
00562
00563
00564 for (int ipSpecies=0; ipSpecies < nSpecies; ++ipSpecies)
00565 {
00566 for( EmissionList::iterator em=dBaseTrans[ipSpecies].Emis().begin();
00567 em != dBaseTrans[ipSpecies].Emis().end(); ++em)
00568 {
00569 if((*em).TauIn() < -1. )
00570 DumpLine((*em).Tran());
00571 }
00572 }
00573
00574
00575 for( i=0; i < nWindLine; i++ )
00576 {
00577 if( (*TauLine2[i].Hi()).IonStg() < (*TauLine2[i].Hi()).nelem()+1-NISO )
00578 {
00579
00580 if( TauLine2[i].Emis().TauIn() < -1. )
00581 DumpLine(TauLine2[i]);
00582 }
00583 }
00584
00585
00586 for( i=0; i < nHFLines; i++ )
00587 {
00588
00589 if( HFLines[i].Emis().TauIn() < -1. )
00590 DumpLine(HFLines[i]);
00591 }
00592
00593 return;
00594 }
00595
00596 STATIC double escmase(double tau)
00597 {
00598 double escmase_v;
00599
00600 DEBUG_ENTRY( "escmase()" );
00601
00602
00603 ASSERT( tau <= 0. );
00604
00605 if( tau > -0.1 )
00606 {
00607 escmase_v = 1. - tau*(0.5 + tau/6.);
00608 }
00609 else if( tau > -30. )
00610 {
00611 escmase_v = (1. - exp(-tau))/tau;
00612 }
00613 else
00614 {
00615 fprintf( ioQQQ, " DISASTER escmase called with 2big tau%10.2e\n",
00616 tau );
00617 fprintf( ioQQQ, " This is zone number%4ld\n", nzone );
00618 FindNeg();
00619 ShowMe();
00620 cdEXIT(EXIT_FAILURE);
00621 }
00622
00623 ASSERT( escmase_v >= 1. );
00624 return escmase_v;
00625 }
00626
00627
00628 double esccon(double tau,
00629 double hnukt)
00630 {
00631 double dinc,
00632 escpcn_v,
00633 sumesc,
00634 sumrec;
00635
00636 DEBUG_ENTRY( "esccon()" );
00637
00638
00639 if( tau < 0.01 )
00640 {
00641 escpcn_v = 1.;
00642 return escpcn_v;
00643 }
00644
00645 else if( hnukt > 1. && tau > 100. )
00646 {
00647 escpcn_v = 1e-20;
00648 return escpcn_v;
00649 }
00650
00651 my_Integrand_conrec func_conrec;
00652 func_conrec.chnukt_ContTkt = hnukt;
00653 Integrator<my_Integrand_conrec,Gaussian32> conrec;
00654
00655 my_Integrand_escConE2 func_escConE2;
00656 func_escConE2.chnukt_ContTkt = hnukt;
00657 func_escConE2.chnukt_ctau = tau;
00658 Integrator<my_Integrand_escConE2,Gaussian32> escConE2;
00659
00660 dinc = 10./hnukt;
00661 sumrec = conrec.sum(1.,1.+dinc,func_conrec);
00662 sumesc = escConE2.sum(1.,1.+dinc,func_escConE2);
00663
00664 if( sumrec > 0. )
00665 {
00666 escpcn_v = sumesc/sumrec;
00667 }
00668 else
00669 {
00670 escpcn_v = 0.;
00671 }
00672 return escpcn_v;
00673 }
00674
00675
00676 STATIC void RTesc_lya_1side(double taume,
00677 double beta,
00678 realnum *esc,
00679 realnum *dest,
00680
00681 long ipLine )
00682 {
00683 double esc0,
00684 fac,
00685 fac1,
00686 fac2,
00687 tau,
00688 taucon,
00689 taulog;
00690
00691
00692
00693
00694
00695 DEBUG_ENTRY( "RTesc_lya_1side()" );
00696
00697
00698 tau = taume*SQRTPI;
00699
00700
00701 esc0 = 1./((0.6451 + tau)*(0.47 + 1.08/(1. + 7.3e-6*tau)));
00702
00703 esc0 = MAX2(0.,esc0);
00704 esc0 = MIN2(1.,esc0);
00705
00706 if( tau > 0. )
00707 {
00708 taulog = log10(MIN2(1e8,tau));
00709 }
00710 else
00711 {
00712
00713
00714
00715 taulog = 0.;
00716 *dest = 0.;
00717 *esc = (realnum)esc0;
00718 }
00719
00720 if( beta > 0. )
00721 {
00722 taucon = MIN2(2.,beta*tau);
00723
00724 if( taucon > 1e-3 )
00725 {
00726 fac1 = -1.25 + 0.475*taulog;
00727 fac2 = -0.485 + 0.1615*taulog;
00728 fac = -fac1*taucon + fac2*POW2(taucon);
00729 fac = pow(10.,fac);
00730 fac = MIN2(1.,fac);
00731 }
00732 else
00733 {
00734 fac = 1.;
00735 }
00736
00737 *esc = (realnum)(esc0*fac);
00738
00739 *dest = (realnum)(beta/(0.30972 - MIN2(.28972,0.03541667*taulog)));
00740 }
00741
00742 else
00743 {
00744 *dest = 0.;
00745 *esc = (realnum)esc0;
00746 }
00747
00748 *dest = MIN2(*dest,1.f-*esc);
00749 *dest = MAX2(0.f,*dest);
00750
00751
00752
00753 *dest = (realnum)( (1. - opac.albedo[ipLine]) * *dest + opac.albedo[ipLine]*DEST0);
00754
00755 {
00756
00757 enum {BUG=false};
00758
00759 if( BUG )
00760 {
00761 fprintf(ioQQQ,"scatdest tau %.2e beta%.2e 1-al%.2e al%.2e dest%.2e \n",
00762 taume,
00763 beta,
00764 (1. - opac.albedo[ipLine]),
00765 opac.albedo[ipLine] ,
00766 *dest
00767 );
00768 }
00769 }
00770 return;
00771 }
00772
00773
00774 double RT_DestProb(
00775
00776 double abund,
00777
00778 double crsec,
00779
00780
00781 long int ipanu,
00782
00783 double widl,
00784
00785 double escp,
00786
00787 int nCore)
00788 {
00789
00790 double eovrlp_v;
00791
00792 double conopc,
00793 beta;
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 DEBUG_ENTRY( "RT_DestProb()" );
00809
00810
00811
00812
00813
00814
00815
00816
00817 if( escp >= 1.0 || !conv.nTotalIoniz || ipanu >= rfield.nflux )
00818 {
00819 eovrlp_v = 0.;
00820 return eovrlp_v;
00821 }
00822
00823
00824 conopc = opac.opacity_abs[ipanu-1];
00825
00826 ASSERT( crsec > 0. );
00827
00828
00829 if( abund <= 0. || conopc <= 0. )
00830 {
00831
00832 eovrlp_v = 0.;
00833 return eovrlp_v;
00834 }
00835
00836
00837 beta = conopc/(abund*SQRTPI*crsec/widl + conopc);
00838
00839
00840
00841 if( nCore == ipDEST_INCOM )
00842 {
00843
00844
00845
00846
00847
00850 eovrlp_v = MIN2(1e-3,8.5*beta);
00851 }
00852 else if( nCore == ipDEST_K2 )
00853 {
00854
00855
00856 eovrlp_v = MIN2(1e-3,8.5*beta);
00857 }
00858 else if( nCore == ipDEST_SIMPL )
00859 {
00860
00861
00862
00863 eovrlp_v = MIN2(1e-3,8.5*beta);
00864 }
00865 else
00866 {
00867 fprintf( ioQQQ, " chCore of %i not understood by RT_DestProb.\n",
00868 nCore );
00869 cdEXIT(EXIT_FAILURE);
00870 }
00871
00872
00873 eovrlp_v /= 1. + eovrlp_v;
00874
00875
00876 eovrlp_v *= 1. - escp;
00877
00878
00879 ASSERT( eovrlp_v >= 0. );
00880 ASSERT( eovrlp_v <= 1. );
00881
00882 {
00883
00884
00885 enum {DEBUG_LOC=false};
00886
00887 if( DEBUG_LOC )
00888 {
00889 if( rfield.anu[ipanu-1]>0.73 && rfield.anu[ipanu-1]<0.76 &&
00890 fp_equal( abund, iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH2p,ipH1s).Emis().PopOpc() ) )
00891 {
00892 fprintf(ioQQQ,"%li RT_DestProb\t%g\n",
00893 nzone, eovrlp_v );
00894 }
00895 }
00896 }
00897
00898
00899
00900
00901 # if 0
00902
00903
00904
00905
00906
00907
00908
00909 eovrlp_v = POW2(1. - opac.albedo[ipanu-1]) * eovrlp_v +
00910 opac.albedo[ipanu-1]*0.;
00911 # endif
00912
00913 return eovrlp_v;
00914 }
00915
00916
00917
00918 double RT_LineWidth(const TransitionProxy& t, realnum DopplerWidth)
00919 {
00920 double RT_LineWidth_v,
00921 aa,
00922 atau,
00923 b,
00924 r,
00925 vth;
00926 realnum tau;
00927
00928 DEBUG_ENTRY( "RT_LineWidth()" );
00929
00930
00931
00932
00933
00934
00935
00936 vth = DopplerWidth;
00937
00938
00939
00940
00941 if( iteration > 1 )
00942 {
00943
00944 realnum tauout = t.Emis().TauTot() - t.Emis().TauIn();
00945
00946
00947 tau = MIN2( t.Emis().TauIn() , tauout );
00948 }
00949 else
00950 {
00951 tau = t.Emis().TauIn();
00952 }
00953
00954
00955 if( tau <1e-3 )
00956 return 0;
00957
00958 t.Emis().damp() = t.Emis().dampXvel() / DopplerWidth;
00959 ASSERT( t.Emis().damp() > 0. );
00960
00961 double Pesc = esc_PRD_1side( tau , t.Emis().damp());
00962
00963
00964 realnum therm = (realnum)(5.3e16/MAX2(1e-15,dense.eden));
00965 if( tau > therm )
00966 {
00967
00968
00969
00970 pressure.lgPradDen = true;
00971 tau = therm;
00972 }
00973
00974
00975
00980 if( ! wind.lgBallistic() )
00981 {
00982
00983
00984 if( (tau-opac.taumin)/100. < FLT_EPSILON )
00985 {
00986 RT_LineWidth_v = 0.;
00987 }
00988 else if( tau <= 20. )
00989 {
00990 atau = -6.907755;
00991 if( tau > 1e-3 )
00992 atau = log(tau);
00993 aa = 4.8 + 5.2*tau + (4.*tau - 1.)*atau;
00994 b = 6.5*tau - atau;
00995 double escProb = Pesc + t.Emis().Pelec_esc() + t.Emis().Pdest();
00996 RT_LineWidth_v = vth*0.8862*aa/b*(1. - MIN2( 1., escProb ) );
00997
00998 if( escProb >= 1. - 100. * FLT_EPSILON )
00999 RT_LineWidth_v = 0.;
01000 }
01001 else
01002 {
01003 ASSERT( t.Emis().damp()*tau >= 0.);
01004 atau = log(MAX2(0.0001,tau));
01005 aa = 1. + 2.*atau/pow(1. + 0.3*t.Emis().damp()*tau,0.6667) + pow(6.5*
01006 t.Emis().damp()*tau,0.333);
01007 b = 1.6 + 1.5/(1. + 0.20*t.Emis().damp()*tau);
01008 RT_LineWidth_v = vth*0.8862*aa/b*(1. - MIN2( 1. ,
01009 (Pesc+ t.Emis().Pelec_esc() + t.Emis().Pdest())) );
01010 }
01011
01012
01013 RT_LineWidth_v *= 2.;
01014
01015 }
01016 else
01017 {
01018
01019 r = t.Emis().damp()*tau/PI;
01020 if( r <= 1. )
01021 {
01022 RT_LineWidth_v = vth*sqrt(log(MAX2(1.,tau))*.2821);
01023 }
01024 else
01025 {
01026 RT_LineWidth_v = 2.*fabs(wind.windv0);
01027 if( r*vth <= RT_LineWidth_v )
01028 {
01029 RT_LineWidth_v = vth*r*log(RT_LineWidth_v/(r*vth));
01030 }
01031 }
01032 }
01033
01034 ASSERT( RT_LineWidth_v >= 0. );
01035 return RT_LineWidth_v;
01036 }
01037
01038
01039 double RT_DestHummer(double beta)
01040
01041 {
01042 double fhummr_v,
01043 x;
01044
01045 DEBUG_ENTRY( "RT_DestHummer()" );
01046
01047
01048
01049
01050
01051
01052
01053
01054 ASSERT( beta >= 0.);
01055 if( beta <= 0. )
01056 {
01057 fhummr_v = 0.;
01058 }
01059 else
01060 {
01061 x = log10(beta);
01062 if( x < -5.5 )
01063 {
01064 fhummr_v = 3.8363 - 0.56329*x;
01065 }
01066 else if( x < -3.5 )
01067 {
01068 fhummr_v = 2.79153 - 0.75325*x;
01069 }
01070 else if( x < -2. )
01071 {
01072 fhummr_v = 1.8446 - 1.0238*x;
01073 }
01074 else
01075 {
01076 fhummr_v = 0.72500 - 1.5836*x;
01077 }
01078 fhummr_v *= beta;
01079 }
01080 return fhummr_v;
01081 }