/home66/gary/public_html/cloudy/c08_branch/source/rt_line_one.cpp

Go to the documentation of this file.
00001 /* This file is part of Cloudy and is copyright (C)1978-2008 by Gary J. Ferland and
00002  * others.  For conditions of distribution and use see copyright notice in license.txt */
00003 /*RT_line_static do line radiative transfer,
00004  * evaluates escape and destruction probability, 
00005  * called by HydroPEsc, RT_line_all  */
00006 /* ND wind distinction is not here - that is done where optical depths are incremented
00007  * with line opacity - rt_line_one_tauinc and in line width for rad pressure, in 
00008  * rt escprob */
00009 #include "cddefines.h"
00010 #include "rfield.h"
00011 #include "doppvel.h"
00012 #include "dense.h"
00013 #include "opacity.h"
00014 #include "lines_service.h"
00015 #include "conv.h"
00016 #include "radius.h"
00017 #include "rt.h"
00018 #include "physconst.h"
00019 
00020 /*RT_line_static do line radiative transfer,
00021  * called by RT_line_all */
00022 STATIC void RT_line_static(
00023         /* the em line we will work on  */
00024         transition * t , 
00025         /* when this is true do both esc and dest probs,
00026          * when falst, only dest probs */
00027         bool lgDoEsc ,
00028         /* this is option to not include line self shielding across this zone.
00029          * this can cause pump to depend on zone thickness, and leads to unstable
00030          * feedback in some models with the large H2 molecule, due to Solomon
00031          * process depending on zone thickness and level populations. */
00032         bool lgShield_this_zone );
00033 
00034 /*RT_line_one do rt for emission line structure - calls RT_line_static or RT_line_wind */
00035 void RT_line_one(
00036         /* the em line we will work on  */
00037         transition *t , 
00038         /* when this is true do both esc and dest probs,
00039          * when falst, only dest probs */
00040         bool lgDoEsc ,
00041         /* if true then we want to update the fine opacity scale */
00042         bool lgDoFine_opac_update ,
00043         /* this is option to not include line self shielding across this zone.
00044          * this can cause pump to depend on zone thickness, and leads to unstable
00045          * feedback in some models with the large H2 molecule, due to Solomon
00046          * process depending on zone thickness and level populations. */
00047         bool lgShield_this_zone )
00048 {
00049                 static long int nTau[100],
00050                         n;
00051 
00052         DEBUG_ENTRY( "RT_line_one()" );
00053 
00054         /*>>chng 06 apr 05,  effects of simply returning upon call with no pop */
00055         /* skip line transfer if requested with 'no line transfer' command, but never skip Lya */
00056         if( (t->Lo->Pop<=SMALLFLOAT && conv.nTotalIoniz) || 
00057                 (!rfield.lgDoLineTrans && (t->Emis->iRedisFun != ipLY_A) ) )
00058         {
00059                 return;
00060         }
00061 
00062         {
00063                 /* option to keep track of population values during calls,
00064                  * print out data to make histogram */
00065                 /*@-redef@*/
00066                 enum {DEBUG_LOC=false};
00067                 /*@+redef@*/
00068                 if( DEBUG_LOC )
00069                 {
00070                         if( nzone==0 )
00071                         {
00072                                 for(n=0; n<100; ++n )
00073                                         nTau[n] = 0;
00074                         }
00075                         if( t->Lo->Pop<=SMALLFLOAT )
00076                                 n = 0;
00077                         else
00078                                 n = (long)log10( t->Lo->Pop )+37;
00079                         n = MIN2( n , 99 );
00080                         n = MAX2( n , 0 );
00081                         /*if( n==37 && nzone > 5 )
00082                         {
00083                                 fprintf(ioQQQ,"HIT\n");
00084                         }*/
00085                         ++nTau[n];
00086                         if( nzone > 183 )
00087                         {
00088                                 for(n=0; n<100; ++n )
00089                                         fprintf(ioQQQ,"%li\t%li\n", n , nTau[n] );
00090                                 cdEXIT(EXIT_SUCCESS);
00091                         }
00092                 }
00093         }
00094 
00095         /* always call single routine */
00096         RT_line_static(
00097                 /* the line we will work on  */
00098                 t , 
00099                 /* when this is true do both esc and dest probs,
00100                         * when falst, only dest probs */
00101                 lgDoEsc ,
00102                 lgShield_this_zone);
00103 
00104         /* this is line center frequency, including bulk motion of gas */
00105         long int ipLineCenter = t->Emis->ipFine + rfield.ipFineConVelShift;
00106 
00107         /* define fine opacity fine grid fine mesh */
00108         /* rfield.lgOpacityFine flag set flast with no fine opacities command */
00109         if( lgDoFine_opac_update && ipLineCenter >= 0 && t->Emis->PopOpc > 0. &&
00110                 ipLineCenter<rfield.nfine && rfield.lgOpacityFine )
00111         {
00112                 long int i;
00113 
00114                 /* number of fine opacity cells corresponding to one doppler width for current
00115                  * temperature, velocity field, and nuclear mass,
00116                  * rfield.fine_opac_velocity_width is width per cell, cm/s */
00117                 realnum cells_wide_1x = DoppVel.doppler[t->Hi->nelem-1]/rfield.fine_opac_velocity_width;
00118 
00119                 /* line center opacity - want realnum since will add to fine opacity array,
00120                  * which is realnum */
00121                 realnum opac_line =  (realnum)t->Emis->PopOpc * t->Emis->opacity / DoppVel.doppler[t->Hi->nelem-1];
00122 
00123                 /* this is effective optical depth to this point. Do not work with line if this product
00124                  * is substantially less than unity */
00125                 double dTauEffec = opac_line*radius.depth_x_fillfac;
00126 
00127                 /* this is line center for current velocity, which is measured
00128                 * relative to illuminated face */
00129 
00130                 /* use dTauEffec to choose whether line is important */
00131 
00132                 if( dTauEffec > SMALLFLOAT )
00133                 {
00134                         /* width of optically thick line, do 4x with exponential core,
00135                          * must be at least one cell, but profile is symmetric */
00136                         long int nCells_core = (long)(cells_wide_1x*4.f+1.5f);
00137                         realnum opacity;
00138 
00139                         /* core is symmetric - make sure both upper and lower bounds
00140                          * are within continuum energy bin */
00141                         if( ipLineCenter - nCells_core < 1 )
00142                                 nCells_core = ipLineCenter - 1;
00143                         if( ipLineCenter + nCells_core > rfield.nfine )
00144                                 nCells_core = ipLineCenter -rfield.nfine - 1;
00145 
00146                         /* want core to be at least one cell wide */
00147                         nCells_core = MAX2( 1 , nCells_core );
00148 
00149                         /* line center itself, must not double count here */
00150                         rfield.fine_opac_zone[ipLineCenter] += opac_line;
00151                         for( i=1; i<nCells_core; ++i )
00152                         {
00153                                 /* square of distance from line center in units of doppler width */
00154                                 realnum xsq = POW2(i/cells_wide_1x);
00155 
00156                                 /* the line opacity at that point, includes doppler core and damping wings */
00157                                 opacity = opac_line*( sexp(xsq) + t->Emis->damp / MAX2(1.f,(1.772f*xsq)) );
00158 
00159                                 rfield.fine_opac_zone[ipLineCenter+i] += opacity;
00160                                 rfield.fine_opac_zone[ipLineCenter-i] += opacity;
00161                         }
00162 
00163                         /* include damping wings if optical depth is large */
00164                         /* >>chng 04 mar 29, rewrite to use symmetry in two halves of line */
00165                         if( dTauEffec*t->Emis->damp/9. > 0.1 )
00166                         {
00167                                 /* do damping wings if very optically thick
00168                                  * this is number of cells to extend the damping wings - cells_wide is one dop width 
00169                                  * 56.419 is 1 / (0.01 * sqrt pi) ) */
00170                                 /* tests with th85orion, stopping at half -h2 point, showed that 0.01 was
00171                                  * needed for outer edge, given the definition of dTauEffec */
00172                                 realnum x = (realnum)sqrt( dTauEffec * t->Emis->damp *56.419 ) * cells_wide_1x;
00173                                 long int nCells_damp;
00174                                 /* >>chng 04 mar 24, add test on size of x, which can exceed
00175                                 * limits of long in extreme optical depths */
00176                                 if( x<LONG_MAX )
00177                                 {
00178                                         nCells_damp = (long)x;
00179 
00180                                         if( ipLineCenter-nCells_damp < 1 )
00181                                                 nCells_damp = ipLineCenter-1;
00182 
00183                                         if( ipLineCenter+nCells_damp > rfield.nfine )
00184                                                 nCells_damp = rfield.nfine - ipLineCenter-1;
00185                                 }
00186                                 else
00187                                 {
00188                                         /* x was too big, just set to extreme range, which is
00189                                          * number of cells to nearest boundary */
00190                                         nCells_damp = MIN2( rfield.nfine-ipLineCenter , ipLineCenter )-1;
00191                                 }
00192 
00193                                 ASSERT( nCells_core>0 );
00194                                 for( i=nCells_core; i<nCells_damp; ++i )
00195                                 {
00196                                         /* distance from line center in doppler units */
00197                                         realnum xsq = POW2(i/cells_wide_1x);
00198                                         /* term in denominator is x^2 */
00199                                         opacity = opac_line*t->Emis->damp/(1.772f*xsq );
00200                                         rfield.fine_opac_zone[ipLineCenter+i] += opacity;
00201                                         rfield.fine_opac_zone[ipLineCenter-i] += opacity;
00202                                 }
00203                         }
00204                 }
00205         }
00206         return;
00207 }
00208 
00209 /*RT_line_static do line radiative transfer for static geometry */
00210 STATIC void RT_line_static(
00211         /* the em line we will work on  */
00212         transition * t , 
00213         /* when this is true do both esc and dest probs,
00214          * when false, only dest probs */
00215         bool lgDoEsc ,
00216         /* this is option to not include line self shielding across this zone.
00217          * this can cause pump to depend on zone thickness, and leads to unstable
00218          * feedback in some models with the large H2 molecule, due to Solomon
00219          * process depending on zone thickness and level populations. */
00220         bool lgShield_this_zone )
00221 {
00222         bool lgGoodTau;
00223         long int nelem;
00224         int nRedis = -1;
00225 
00226         DEBUG_ENTRY( "RT_line_static()" );
00227 
00228         /* this is the routine that computes much of the radiative transfer
00229          * physics for lines for static case.  */
00230 
00231         /*ASSERT( t->IonStg < LIMELM+4 );*/
00232         /*ASSERT( t->nelem-1 < LIMELM+4 );*/
00233 
00234         /* >>chng 01 aug 18, do not evaluate if no population */
00235         /* molecules are evaluated here, these must be valid */
00236         /* >>chng 01 oct 25, add test for lgDoEsc, this is to make sure
00237          * that rates are evaluated at start of a new iteration */
00238         if( dense.xIonDense[ t->Hi->nelem-1][t->Hi->IonStg-1] == 0.  && !lgDoEsc )
00239         {
00240                 /* zero population, return after setting everything with side effects */
00241                 t->Emis->Pesc = 1.f;
00242 
00243                 /* inward escaping fraction */
00244                 t->Emis->FracInwd = 0.5;
00245 
00246                 /* pumping rate */
00247                 t->Emis->pump = 0.;
00248 
00249                 /* destruction probability */
00250                 t->Emis->Pdest = 0.;
00251                 t->Emis->Pelec_esc = 0.;
00252 
00253                 return;
00254         }
00255         /* check that we don't have a runaway maser */
00256         else if( t->Emis->TauIn < -30. )
00257         {
00258                 fprintf( ioQQQ, "PROBLEM RT_line_static called with large negative optical depth, zone %.2f, setting lgAbort true.\n",
00259                         fnzone );
00260                 DumpLine(t);
00261                 /* >>>chng 00 apr 23, return busted true instead of exit here, so that code will
00262                  * not hang under MPI */
00263                 lgAbort = true;
00264                 return;
00265         }
00266 
00267         /* this checks if we have overrun the optical depth scale,
00268          * in which case the inward optical depth is greater than the
00269          * previous iteration's total optical depth.
00270          * We do not reevaluate escape probabilities if the optical depth
00271          * scale has been overrun due to huge bogus change in solution
00272          * that would result */
00273         if( iteration == 1 || lgTauGood( t ) )
00274         {
00275                 lgGoodTau = true;
00276         }
00277         else
00278         {
00279                 /* do not reevaluate escape probabilities if we have overrun 
00280                  * the optical depth scale */
00281                 lgGoodTau = false;
00282         }
00283 
00284         /* atomic number of this element on the C scale*/
00285         nelem = t->Hi->nelem-1;
00286 
00287         /* damping constant for the line, save it */
00288         t->Emis->damp = t->Emis->dampXvel / DoppVel.doppler[t->Hi->nelem-1];
00289         /*if( t->damp <0. )
00290         {
00291                 fprintf(ioQQQ,"DEBUG hit it \n");
00292         }*/
00293         ASSERT( t->Emis->damp > 0. || 
00294                         (opac.lgCaseB && t->Emis->damp >= 0.) );
00295 
00296         /* static solution - which type of line will determine
00297          * which redistribution function */
00298         /* iRedisFun == 1 - alpha resonance line, partial redistribution,
00299          * ipPRD == 1 */
00300         if( t->Emis->iRedisFun == ipPRD )
00301         {
00302                 /* incomplete redistribution with wings */
00303                 if( lgDoEsc )
00304                 {
00305                         if( lgGoodTau )
00306                         {
00307                                 t->Emis->Pesc = (realnum)esc_PRD( t->Emis->TauIn , t->Emis->TauTot , t->Emis->damp );
00308 
00309                                 /* inward escaping fraction */
00310                                 t->Emis->FracInwd = rt.fracin;
00311                         }
00312                 }
00313                 nRedis = ipDEST_INCOM;
00314         }
00315 
00316         /* complete redistribution without wings - t->ipLnRedis is ipCRD == -1 */
00317         else if( t->Emis->iRedisFun == ipCRD )
00318         {
00319                 if( lgDoEsc )
00320                 {
00321                         if( lgGoodTau )
00322                         {
00323                                 /* >>chng 01 mar -6, escsub will call any of several esc prob routines,
00324                                  * depending of how core is set.  We always want core-only for this option,
00325                                  * so call  esca0k2(tau) directly */
00326                                 t->Emis->Pesc = (realnum)esc_CRDcore( t->Emis->TauIn , t->Emis->TauTot );
00327 
00328                                 /* inward escaping fraction */
00329                                 t->Emis->FracInwd = rt.fracin;
00330                         }
00331                 }
00332                 nRedis = ipDEST_K2;
00333         }
00334 
00335         /* chng 01 feb 27, add CRD with wings, = 2 */
00336         else if( t->Emis->iRedisFun == ipCRDW )
00337         {
00338                 /* complete redistribution with damping wings */
00339                 if( lgDoEsc )
00340                 {
00341                         if( lgGoodTau )
00342                         {
00343                                 t->Emis->Pesc = (realnum)esc_CRDwing( t->Emis->TauIn , t->Emis->TauTot , t->Emis->damp );
00344 
00345                                 /* inward escaping fraction */
00346                                 t->Emis->FracInwd = rt.fracin;
00347                         }
00348                 }
00349                 nRedis = ipDEST_K2;
00350         }
00351 
00352         /* chng 03 may 14, special Lya case*/
00353         else if( t->Emis->iRedisFun == ipLY_A )
00354         {
00355                 /* incomplete redistribution with wings, for special case of Lya
00356                  * uses fits to Hummer & Kunasz numerical results 
00357                  * this routine is different because escape and dest probs
00358                  * are evaluated together, so no test of lgDoEsc */
00359                 if( lgGoodTau )
00360                 {
00361                         double dest , esin;
00362 
00363                         /* this will always evaluate escape prob, no matter what lgDoEsc is.
00364                         * The destruction prob comes back as dest */
00365                         t->Emis->Pesc = (realnum)RTesc_lya(&esin , &dest , t->Emis->PopOpc , nelem);
00366 
00367                         /* this is current destruction rate */
00368                         t->Emis->Pdest = (realnum)dest;
00369 
00370                         /*  this is fraction of line which is inward escaping */
00371                         t->Emis->FracInwd = rt.fracin;
00372                 }
00373         }
00374         else
00375         {
00376                 fprintf( ioQQQ, " RT_line_static called with redistribution function zero\n" );
00377                 ShowMe();
00378                 cdEXIT(EXIT_FAILURE);
00379         }
00380 
00381         /* pumping by incident and diffuse continua */
00382         /* >>chng 03 may 15, this block had been repeated all four times above, move down
00383          * here to use common code, only rt.wayin is defined above */
00384         /* >>chng 03 may 17, do not evaluate when drad is zero, before first
00385          * zone thickness is established */
00386         /* >>chng 06 nov 29, reordered if clauses, no point in doing bigger loop if "no induced" is on. */
00387         /* option to kill induced processes */
00388         if( !rfield.lgInducProcess )
00389         {
00390                 t->Emis->pump = 0.;
00391         }
00392         else if( (lgDoEsc  || (t->Emis->iRedisFun == ipLY_A) ) )
00393         {
00394                 double dTau;
00395                 double pumpsave = t->Emis->pump;
00396                 double shield_continuum;
00397 
00398                 /* >>chng 04 apr 18, break out line continuum shielding into this function */
00399                 shield_continuum = RT_continuum_shield_fcn( t );
00400 
00401                 /* continuum upward pumping rate, A gu/gl abs prob occnum
00402                  * the "no induced" command causes continuum pumping to be set to 0 */
00403                 /*t->pump = t->Aul * t->gHi / t->gLo * rt.wayin **/
00404                 /* >>chng 05 feb 16, add outward diffuse emission */
00405                 /*t->pump = t->Aul * t->gHi / t->gLo * shield_continuum *
00406                         rfield.OccNumbIncidCont[t->ipCont-1];*/
00407                 t->Emis->pump = t->Emis->Aul * t->Hi->g / t->Lo->g * shield_continuum *(
00408                         rfield.OccNumbIncidCont[t->ipCont-1] + rfield.OccNumbContEmitOut[t->ipCont-1] );
00409 
00410                 /* >>chng 99 dec 02, add correction for line optical depth across zone */
00411                 /* correction for attenuation within line across zone */
00412                 /* >>chng 99 mar 18, from 0 to 1e-8 in following to avoid underflow, 
00413                  * this caused an overestimate of pumping rates */
00414                 /* >>chng 00 dec 19, nova.in oscillated since correction factor was
00415                  * very large across zones that were already very optically thick, dr changed,
00416                  * causing feedback between ionization and thickness
00417                  * the intention of this correction was to only apply when on the 
00418                  * verge of optically thick,
00419                  * change lower bound on product t->dTau * radius.drad_x_fillfac to 1e-3 to avoid
00420                  * constantly getting unity, also check on relative change optical depth/optical depth*/
00421                 /* this can drive oscillations in very neutral gas, as blr92.in, blr89.in
00422                  * or nova.in, when higher lyman lines have produce 
00423                  * t->dTau * radius.drad_x_fillfac about unity, where small changes in
00424                  * pump can change ionization, dTau, and hence pump */
00425                 /*if( t->dTau * radius.drad_x_fillfac > 1e-8 )*/
00426                 /* >>chng 02 jun 14, nova.in again - upper limit had been 10 - but
00427                  * there were major jumps in heating rate at this point - increase 10 -> 1e10
00428                  * not clear why there should be an upper limit at all, other than to save time? */
00429                 /* update dTau since affects pump rate */
00430                 /* >>chng 03 jun 18, include option to not shield across this zone */
00431                 /* >>chng 03 jul 19, add continuum opacity */
00432                 dTau =  (t->Emis->PopOpc * t->Emis->opacity / DoppVel.doppler[nelem] + opac.opacity_abs[t->ipCont-1])*
00433                          radius.drad_x_fillfac_mean;
00434                 /* >>chng 04 mar 04, do not want to include maser action across this zone */
00435                 dTau = MIN2(1., dTau);
00436                 /*if( 0 && lgShield_this_zone && dTau * radius.drad_x_fillfac > 1e-3 && dTau * radius.drad_x_fillfac < 1e10 )*/
00437                 /* >>chng 04 mar 04, use mean of past few zone thicknesses rather than
00438                  * current zone thickness since this can induce wild oscillations, see
00439                  * nova.in test case */
00440                 if( lgShield_this_zone && dTau > 1e-3 && dTau < 1e10 )
00441                 {
00442                         /* during very first search dTau is -1e38*/
00443                         /* >>chng 04 mar 04, use mean, see above comment */
00444                         /*t->pump *= log(1. + dTau * radius.drad_x_fillfac ) / (dTau * radius.drad_x_fillfac);*/
00445                         t->Emis->pump *= log(1. + dTau ) / dTau;
00446                 }
00447 
00448                 /* >>chng 00 Oct 03, add pumping by local diffuse continuum,
00449                  * rfield.DiffPumpOn is unity unless process disabled by setting to 0 in  parsedont.c
00450                  * with no DIFFuse LINE PUMPing command */
00451                 if( dTau*rfield.DiffPumpOn > SMALLFLOAT )
00452                 {
00453                         /* >>chng 02 mar 14, added brackets around scale*rfield.OccNumbDiffCont so
00454                          * that smallest and largest number are multiplied first to prevent overflow, PvH */
00455                         double scale;
00456                         if( iteration > 1 )
00457                         {
00458                                 if( lgGoodTau )
00459                                 {
00460                                         /* >>chng 03 jul 19, add check for tau = 1 in continuum */
00461                                         /* scale for tau = 1 in the continuum */
00462                                         double scale_con = 1. / SDIV(opac.opacity_abs[t->ipCont-1]+opac.opacity_sct[t->ipCont-1]);
00463                                         /* inward looking depth, dTau is opacity in line, cm^-1,
00464                                         * so multiplying by this scale is same as dividing by opacity in 
00465                                         * source function */
00466                                         double scale_in =  MIN3( 1./ dTau , radius.depth    , scale_con);
00467                                         double scale_out = MIN3( 1./ dTau , radius.Depth2Go , scale_con );
00468                                         t->Emis->pump += t->Emis->Aul * t->Hi->g / t->Lo->g * 0.5 *((scale_in+scale_out)*
00469                                                 rfield.OccNumbDiffCont[t->ipCont-1]);
00470                                 }
00471                         }
00472                         else 
00473                         {
00474                                 /* >>chng 03 jul 19, add check for tau = 1 in continuum */
00475                                 /* scale for tau = 1 in the continuum */
00476                                 double scale_con = 1. / SDIV(opac.opacity_abs[t->ipCont-1]+opac.opacity_sct[t->ipCont-1]);
00477                                 /* first iteration, only inward looking depths really known */
00478                                 scale = 1./ dTau;
00479                                 scale = MIN3( scale , radius.depth , scale_con );
00480                                 t->Emis->pump += t->Emis->Aul * t->Hi->g / t->Lo->g * (scale*
00481                                         rfield.OccNumbDiffCont[t->ipCont-1]);
00482                         }
00483                 }
00484                 /* this stop oscillations from developing in very deep blr models 
00485                  * like blr89 and blr98, but must not be applied too early since
00486                  * line optical depths change greatly in first few zones */
00487                 if( nzone>50 )
00488                         t->Emis->pump = (pumpsave + t->Emis->pump) / 2.;
00489         }
00490 
00491 
00492         /* escape following scattering off an electron */
00493         /* this is turned off with the no scattering escape command */
00494         if( !rt.lgElecScatEscape )
00495         {
00496                 t->Emis->Pelec_esc = 0.;
00497         }
00498         else
00499         {
00500                 /* in the transition structure PopOpc is the pop relative to the ion,
00501                  * but has been converted to a physical population before this routine
00502                  * was called.  No need to convert here */
00503                 double opac_line = t->Emis->PopOpc * t->Emis->opacity/DoppVel.doppler[nelem];
00504 
00505                 if( opac_line > SMALLFLOAT )
00506                 {
00507                         /* the old escape probability */
00508                         double eesc_save = t->Emis->Pelec_esc;
00509                         /* the opacity in electron scattering */
00510                         double es = dense.eden*6.65e-25;
00511                         fixit(); // should we use total opacity here instead of opac_line?
00512                         /* this is equation 5 of 
00513                          *>>refer       line    desp    Netzer, H., Elitzur, M., & Ferland, G. J. 1985, ApJ, 299, 752*/
00514                         double opacity_ratio = es/(es+opac_line) * (1.-t->Emis->Pesc);
00515                         /* keep total probability not more than 1. */
00516                         t->Emis->Pelec_esc = (realnum)opacity_ratio * MAX2(0.f,1.f-t->Emis->Pesc-t->Emis->Pdest);
00517                         /*KLUDGE >>chng 03 feb 02 
00518                          * take mean of old and new if electron scattering escape */
00519                         if( !conv.lgSearch )
00520                                 t->Emis->Pelec_esc = t->Emis->Pelec_esc*0.75f + (realnum)eesc_save*0.25f;  
00521                 }
00522                 else
00523                         t->Emis->Pelec_esc = 0.;
00524         }
00525 
00526         /* >>>chng 99 dec 18, did not have the test for lgGoodTau, and so clobbered
00527          * dest prob when overrun */
00528         /* only do this if not Lya special case, since dest prob already done */
00529         if( lgGoodTau && t->Emis->iRedisFun!=ipLY_A && t->Emis->opacity > 0. )
00530         {
00531                 double DestSave = t->Emis->Pdest;
00532                 t->Emis->Pdest = (realnum)RT_DestProb(
00533                         /* the abundance of the species */
00534                         t->Emis->PopOpc,
00535                         /* line center opacity in funny units (needs a vel) */
00536                         t->Emis->opacity,
00537                         /* array index for line in continuum array,
00538                          * on f not c scale */
00539                         t->ipCont,
00540                         /* line width in velocity units */
00541                         DoppVel.doppler[nelem],
00542                         /* escape probability */
00543                         t->Emis->Pesc,
00544                         /* redistribution function */
00545                         nRedis);
00546 
00547                 /* >>chng 03 may 10, this had been 3/4 new + 1/4 old, but had to be combined
00548                  ^ with half and half when this routine was called, to converge very high Z high U
00549                  * quasar models.  bring all these factors together here */
00550                 /*t->Pdest = 0.75f*t->Pdest + 0.25f * DestSave;*/
00551 #               define OLDFAC   (0.625)
00552                 if( nzone>1 )
00553                         t->Emis->Pdest = (realnum)((1.-OLDFAC)*t->Emis->Pdest + OLDFAC * DestSave);
00554         }
00555 
00556         /* zero escape probability and pumping term if energy is below plasma frequency */
00557         if( t->EnergyErg / EN1RYD < rfield.plsfrq )
00558         {
00559                 t->Emis->Pesc = 0.;
00560                 t->Emis->Pdest = 0.;
00561                 t->Emis->pump = 0.;
00562         }
00563 
00564         return;
00565 }
00566 
00567 #if 0
00568 /*RT_line_wind do line radiative transfer for wind geometry */
00569 STATIC void RT_line_wind(transition * t , bool lgDoEsc);
00570 /*RT_line_wind do line radiative transfer for wind geometry */
00571 STATIC void RT_line_wind(transition * t , bool lgDoEsc)
00572 {
00573         realnum velocity;
00574 
00575         DEBUG_ENTRY( "RT_line_wind()" );
00576 
00577         /* 
00578          * this is the routine that computes much of the radiative transfer
00579          * physics for lines in wind case.  Lines diveded into two types,
00580          * high quality (level1) and lower quality (atom_level2) g-bar lines
00581          */
00582 
00583         /* >>chng 01 aug 18, do not evaluation if no population */
00584         /* >>chng 01 oct 25, add test for lgDoEsc, this is to make sure
00585          * that rates are evaluated at start of a new iteration */
00586         if( dense.xIonDense[ t->nelem-1][t->IonStg-1] == 0.  && !lgDoEsc )
00587         {
00588                 /* zero population, return after setting everything with side effects */
00589                 t->Pesc = 1.f;
00590 
00591                 /* inward escaping fraction */
00592                 t->FracInwd = 0.5;
00593 
00594                 /* pumping rate */
00595                 t->pump = 0.;
00596 
00597                 /* destruction probability */
00598                 t->Pdest = 0.;
00599                 t->Pelec_esc = 0.;
00600                 return;
00601         }
00602 
00603         /*confirm pops and cs ok */
00604         ASSERT( t->ColOvTot <= 1. && t->ColOvTot >= 0. );
00605 
00606         /* t->nelem is atomic number of species */
00607         ASSERT( t->nelem >= 1 && t->ipCont > 0 );
00608 
00609         /* line width, thermal + turbulence */
00610         velocity = DoppVel.doppler[t->nelem-1];
00611 
00612         t->damp = 0.;
00613 
00614         /* use only one-sided escape probabilities
00615          * get escape probability, this gets fractions too */
00616         if( lgDoEsc )
00617         {
00618                 t->Pesc = esc_CRDwing_1side(t->TauIn,t->damp);
00619 
00620                 /* inward fraction */
00621                 t->FracInwd = 0.5;
00622 
00623                 /* continuum pumping */
00624                 if( rfield.lgInducProcess )
00625                 {
00626                         /* >>chng 05 feb 16, include diffuse outward emission */
00627                         /*t->pump = t->Aul*t->gHi/t->gLo*t->Pesc*
00628                           rfield.OccNumbIncidCont[t->ipCont-1];*/
00629                         t->pump = t->Aul*t->gHi/t->gLo*t->Pesc*(
00630                           rfield.OccNumbIncidCont[t->ipCont-1] + rfield.OccNumbContEmitOut[t->ipCont-1]);
00631                 }
00632                 else
00633                 {
00634                         t->pump = 0.;
00635                 }
00636         }
00637 
00638         /* get destruction probability */
00639         t->Pdest = 
00640                 RT_DestProb(
00641                 t->PopOpc,
00642             /* its line absorption cross section */
00643                 t->opacity,
00644                 /* index for line in continuum array, on f not c scale */
00645                 t->ipCont,
00646             velocity,
00647                 t->Pesc, 
00648                 ipDEST_K2);
00651         return;
00652 }
00653 #endif
00654 

Generated on Mon Feb 16 12:01:27 2009 for cloudy by  doxygen 1.4.7