00001 
00002 
00003 #include "cddefines.h"
00004 #include "atmdat.h"
00005 #include "conv.h"
00006 #include "dense.h"
00007 #include "heavy.h"
00008 #include "helike_cs.h"
00009 #include "hydrogenic.h"
00010 #include "hydro_vs_rates.h"
00011 #include "ionbal.h"
00012 #include "iso.h"
00013 #include "opacity.h"
00014 #include "phycon.h"
00015 #include "physconst.h"
00016 #include "rfield.h"
00017 #include "secondaries.h"
00018 #include "trace.h"
00019 #include "taulines.h"
00020 
00021 
00022 static double ColliderMass[4] = {ELECTRON_MASS/PROTON_MASS, 1.0, 4.0, 4.0};
00023 
00024 void iso_collisional_ionization( long ipISO, long nelem )
00025 {
00026         ASSERT( ipISO <= NISO );
00027 
00028         DEBUG_ENTRY( "iso_collisional_ionization()" );
00029 
00030         
00031         iso.ColIoniz[ipISO][nelem][0] = iso.lgColl_ionize[ipISO] *
00032                 t_ADfA::Inst().coll_ion( nelem+1, 1+ipISO, phycon.te );
00033 
00034         for( long ipHi=1; ipHi<iso.numLevels_max[ipISO][nelem]; ipHi++ )
00035         {
00036                 if( nelem == ipISO )
00037                 {
00038                         
00039                         
00040                         iso.ColIoniz[ipISO][nelem][ipHi] = hydro_vs_ioniz( ipISO, nelem, ipHi );
00041                 }
00042                 else
00043                 {
00044                         
00045                         
00046 
00047 
00048 
00049                         iso.ColIoniz[ipISO][nelem][ipHi] = Hion_coll_ioniz_ratecoef( ipISO, nelem, ipHi );
00050                 }
00051                 
00052                 
00053                 
00054                 if( ipHi < iso.numLevels_max[ipISO][nelem] - 1 )
00055                         iso.ColIoniz[ipISO][nelem][ipHi] *= iso.lgColl_ionize[ipISO];
00056         }
00057         
00058         
00059 
00060 
00061 
00062 
00063 
00064 
00065         if( !iso.lgLevelsLowered[ipISO][nelem] )
00066         {
00067                 iso.ColIoniz[ipISO][nelem][iso.numLevels_max[ipISO][nelem]-1] *= 10.;
00068                 iso.ColIoniz[ipISO][nelem][iso.numLevels_max[ipISO][nelem]-1] *= 10.;
00069         }
00070         
00071         return;
00072 }
00073 
00074 void iso_suprathermal( long ipISO, long nelem )
00075 {
00076         DEBUG_ENTRY( "iso_suprathermal()" );
00077 
00078         
00079         ASSERT( ipISO < NISO );
00080         ASSERT( nelem >= ipISO );
00081         ASSERT( nelem < LIMELM );
00082 
00083         
00084 
00085 
00086 
00087 
00088 
00089         for( long i=1; i < iso.numLevels_max[ipISO][nelem]; i++ )
00090         {
00091                 if( Transitions[ipISO][nelem][i][0].ipCont > 0 )
00092                 {
00093                         
00094 
00095 
00096                         secondaries.Hx12[ipISO][nelem][i] = secondaries.x12tot *
00097                                 (Transitions[ipISO][nelem][i][0].Emis->gf/
00098                                 Transitions[ipISO][nelem][i][0].EnergyWN) /
00099                                 (Transitions[ipH_LIKE][ipHYDROGEN][ipH2p][0].Emis->gf/
00100                                 Transitions[ipH_LIKE][ipHYDROGEN][ipH2p][0].EnergyWN);
00101                 }
00102                 else
00103                         secondaries.Hx12[ipISO][nelem][i] = 0.;
00104         }
00105 
00106         return;
00107 }
00108 
00109 
00110 
00111 void iso_collide( long ipISO, long nelem )
00112 {
00113         long ipHi, ipLo;
00114         double factor, ConvLTEPOP, edenCorr;
00115 
00116         
00117 
00118         static double TeUsed[NISO][LIMELM]={
00119                 {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0},
00120                 {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0} };
00121 
00122         
00123 
00124 
00125         static double TeUsedForCS[NISO][LIMELM]={
00126                 {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0},
00127                 {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0} };
00128 
00129         DEBUG_ENTRY( "iso_collide()" );
00130 
00131         
00132         ASSERT( ipISO < NISO );
00133         ASSERT( nelem >= ipISO );
00134         ASSERT( nelem < LIMELM );
00135         
00136         
00137 
00138 
00139         if( fp_equal( TeUsed[ipISO][nelem], phycon.te ) && conv.nTotalIoniz )
00140         {
00141                 ASSERT( Transitions[ipISO][nelem][ iso.nLyaLevel[ipISO] ][0].Coll.ColUL >= 0. );
00142 
00143                 if( trace.lgTrace )
00144                 {
00145                         fprintf( ioQQQ, 
00146                                 "     iso_collide called %s nelem %li - no reeval Boltz fac, LTE dens\n",
00147                                 iso.chISO[ipISO], nelem );
00148                 }
00149         }
00150         else
00151         {
00152                 TeUsed[ipISO][nelem] = phycon.te;
00153 
00154                 if( trace.lgTrace )
00155                 {
00156                         fprintf( ioQQQ, 
00157                                 "     iso_collide called %s nelem %li - will reeval Boltz fac, LTE dens\n",
00158                                 iso.chISO[ipISO], nelem );
00159                 }
00160                 
00161                 
00162 
00163 
00164 
00165 
00166 
00167 
00168                 for( ipHi=1; ipHi<iso.numLevels_max[ipISO][nelem]; ipHi++ )
00169                 {
00170                         for( ipLo=0; ipLo<ipHi; ipLo++ )
00171                         {
00172                                 iso.Boltzmann[ipISO][nelem][ipHi][ipLo] = 
00173                                         sexp( Transitions[ipISO][nelem][ipHi][ipLo].EnergyK / phycon.te );
00174                         }
00175                 }
00176 
00177                 
00178                 factor = HION_LTE_POP*dense.AtomicWeight[nelem]/
00179                         (dense.AtomicWeight[nelem]+ELECTRON_MASS/ATOMIC_MASS_UNIT);
00180 
00181                 
00182                 ConvLTEPOP = pow(factor,1.5)/(2.*iso.stat_ion[ipISO])/phycon.te32;
00183 
00184                 iso.lgPopLTE_OK[ipISO][nelem] = true;
00185 
00186                 
00187                 for( ipLo=0; ipLo<iso.numLevels_max[ipISO][nelem]; ipLo++ )
00188                 {
00189                         
00190                         StatesElem[ipISO][nelem][ipLo].ConBoltz =
00191                                 dsexp(iso.xIsoLevNIonRyd[ipISO][nelem][ipLo]/phycon.te_ryd);
00192 
00193                         
00194 
00195 
00196 
00197 
00198 
00199                         if( StatesElem[ipISO][nelem][ipLo].ConBoltz > SMALLDOUBLE )
00200                         {
00201                                 
00202                                 iso.PopLTE[ipISO][nelem][ipLo] = 
00203                                         StatesElem[ipISO][nelem][ipLo].g / StatesElem[ipISO][nelem][ipLo].ConBoltz * ConvLTEPOP;
00204                                 ASSERT( iso.PopLTE[ipISO][nelem][ipLo] < BIGDOUBLE );
00205                         }
00206                         else
00207                         {
00208                                 iso.PopLTE[ipISO][nelem][ipLo] = 0.;
00209                         }
00210 
00211                         
00212                         if( iso.PopLTE[ipISO][nelem][ipLo] <= 0. )
00213                         {
00214                                 iso.lgPopLTE_OK[ipISO][nelem] = false;
00215                         }
00216                 }
00217 
00218                 iso_collisional_ionization( ipISO, nelem );
00219 
00220                 
00221 
00222 
00223 
00224 
00225 
00226                 
00227 
00228                 if( (TeUsedForCS[ipISO][nelem] == 0.) || 
00229                         ( TeUsedForCS[ipISO][nelem]/phycon.te > 1.15 ) ||
00230                         ( TeUsedForCS[ipISO][nelem]/phycon.te < 0.85 ) )
00231                 {
00232                         
00233                         TeUsedForCS[ipISO][nelem] = phycon.te;
00234 
00235                         for( ipHi=1; ipHi<iso.numLevels_max[ipISO][nelem]; ipHi++ )
00236                         {
00237                                 for( ipLo=0; ipLo < ipHi; ipLo++ )
00238                                 {
00239                                         if( ipISO == ipH_LIKE )
00240                                         {
00241                                                 
00242                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.cs = 
00243                                                         HydroCSInterp( nelem , ipHi , ipLo, ipELECTRON );
00244                                                 
00245                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipPROTON] = 
00246                                                         HydroCSInterp( nelem , ipHi , ipLo, ipPROTON );
00247                                                 
00248                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipHE_PLUS] =
00249                                                         HydroCSInterp( nelem , ipHi , ipLo, ipHE_PLUS );
00250                                                 
00251                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipALPHA] =
00252                                                         HydroCSInterp( nelem , ipHi , ipLo, ipALPHA );
00253                                         }
00254                                         else if( ipISO == ipHE_LIKE )
00255                                         {
00256                                                 
00257                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.cs = 
00258                                                         HeCSInterp( nelem , ipHi , ipLo, ipELECTRON );
00259                                                 
00260                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipPROTON] = 
00261                                                         HeCSInterp( nelem , ipHi , ipLo, ipPROTON );
00262                                                 
00263                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipHE_PLUS] =
00264                                                         HeCSInterp( nelem , ipHi , ipLo, ipHE_PLUS );
00265 
00266                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipALPHA] = 0.;
00267                                         }
00268                                         else
00269                                                 TotalInsanity();
00270                                         
00271                                         if( N_(ipHi) != N_(ipLo) )
00272                                         {
00273                                                 
00274 
00275                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.cs *= iso.lgColl_excite[ipISO];
00276                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipPROTON] *= iso.lgColl_excite[ipISO];
00277                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipHE_PLUS] *= iso.lgColl_excite[ipISO];
00278                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipALPHA] *= iso.lgColl_excite[ipISO];
00279 
00280                                         }
00281                                         else
00282                                         {
00283                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.cs *= iso.lgColl_l_mixing[ipISO];
00284                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipPROTON] *= iso.lgColl_l_mixing[ipISO];
00285                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipHE_PLUS] *= iso.lgColl_l_mixing[ipISO];
00286                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipALPHA] *= iso.lgColl_excite[ipISO];
00287                                         }
00288                                         
00289                                         
00290                                         ASSERT( Transitions[ipISO][nelem][ipHi][ipLo].Coll.cs >= 0. );
00291                                         ASSERT( Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipPROTON] >= 0. );
00292                                         ASSERT( Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipHE_PLUS] >= 0. );
00293                                         ASSERT( Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipALPHA] >= 0. );
00294                                 }
00295                         }
00296                 }
00297                 
00298                 
00299 
00300                 if( opac.lgCaseB_HummerStorey && ipISO==ipH_LIKE )
00301                 {
00302                         for( ipLo=0; ipLo<iso.numLevels_max[ipISO][nelem]-1; ipLo++ )
00303                         {
00304                                 if( N_(ipLo)>=3 )
00305                                         break;
00306 
00307                                 iso.ColIoniz[ipISO][nelem][ipLo] = 0.;
00308 
00309                                 for( ipHi=ipLo+1; ipHi<iso.numLevels_max[ipISO][nelem]; ipHi++ )
00310                                 {
00311                                         Transitions[ipISO][nelem][ipHi][ipLo].Coll.cs = 0.;
00312                                         Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipPROTON] = 0.;
00313                                         Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipHE_PLUS] = 0.;
00314                                         Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipALPHA] = 0.;
00315                                 }
00316                         }
00317                 }
00318 
00319                 
00320 
00321 
00322 
00323 
00324                 for( ipHi=1; ipHi<iso.numLevels_max[ipISO][nelem]; ipHi++ )
00325                 {
00326                         for( ipLo=0; ipLo<ipHi; ipLo++ )
00327                         {
00328                                 double reduced_mass_proton = dense.AtomicWeight[nelem]*ColliderMass[ipPROTON]/
00329                                         (dense.AtomicWeight[nelem]+ColliderMass[ipPROTON])*ATOMIC_MASS_UNIT;
00330 
00331                                 double reduced_mass_heplus = dense.AtomicWeight[nelem]*ColliderMass[ipHE_PLUS]/
00332                                         (dense.AtomicWeight[nelem]+ColliderMass[ipHE_PLUS])*ATOMIC_MASS_UNIT;
00333 
00334                                 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.ColUL = (realnum)(
00348                                         (
00349                                         
00350                                         Transitions[ipISO][nelem][ipHi][ipLo].Coll.cs +
00351                                         
00352                                         Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipPROTON]*
00353                                         (realnum)(dense.xIonDense[ipHYDROGEN][1]/dense.EdenHCorr)*
00354                                         pow(ELECTRON_MASS/reduced_mass_proton, 1.5) +
00355                                         
00356                                         Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipHE_PLUS]*
00357                                         (realnum)(dense.xIonDense[ipHELIUM][1]/dense.EdenHCorr)*
00358                                         pow(ELECTRON_MASS/reduced_mass_heplus, 1.5) +
00359                                         
00360                                         Transitions[ipISO][nelem][ipHi][ipLo].Coll.csi[ipALPHA]*
00361                                         (realnum)(dense.xIonDense[ipHELIUM][2]/dense.EdenHCorr)*
00362                                         pow(ELECTRON_MASS/reduced_mass_heplus, 1.5) 
00363                                         ) / phycon.sqrte*COLL_CONST/(double)StatesElem[ipISO][nelem][ipHi].g );
00364 
00365                                 if( ipISO == ipH_LIKE )
00366                                 {
00367                                         if( N_(ipHi) > iso.n_HighestResolved_max[ipISO][nelem] &&
00368                                                 N_(ipLo) <= iso.n_HighestResolved_max[ipISO][nelem] )
00369                                         {
00370                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.ColUL *= 
00371                                                         (8.f/3.f)*(log((realnum)N_(ipHi))+2.f);
00372                                         }
00373                                 }
00374                                 else if( ipISO == ipHE_LIKE )
00375                                 {
00376                                         fixit();
00377                                         
00378 
00379 
00380                                         if( N_(ipHi) > iso.n_HighestResolved_max[ipISO][nelem] &&
00381                                                 N_(ipLo) <= iso.n_HighestResolved_max[ipISO][nelem] )
00382                                         {
00383                                                 Transitions[ipISO][nelem][ipHi][ipLo].Coll.ColUL *=
00384                                                         (2.f/3.f)*(log((realnum)N_(ipHi))+2.f);
00385                                         }
00386                                 }
00387                         }
00388                 }
00389 
00390                 if( (trace.lgTrace && trace.lgIsoTraceFull[ipISO]) && (nelem == trace.ipIsoTrace[ipISO]) )
00391                 {
00392                         fprintf( ioQQQ, "     iso_collide: %s Z=%li de-excitation rates coefficients\n", iso.chISO[ipISO], nelem + 1 );
00393                         for( ipHi=1; ipHi < iso.numLevels_max[ipISO][nelem]; ipHi++ )
00394                         {
00395                                 fprintf( ioQQQ, " %li\t", ipHi );
00396                                 for( ipLo=0; ipLo < ipHi; ipLo++ )
00397                                 {
00398                                         fprintf( ioQQQ,PrintEfmt("%10.3e", Transitions[ipISO][nelem][ipHi][ipLo].Coll.ColUL ));
00399                                 }
00400                                 fprintf( ioQQQ, "\n" );
00401                         }
00402 
00403                         fprintf( ioQQQ, "     iso_collide: %s Z=%li collisional ionization coefficients\n", iso.chISO[ipISO], nelem + 1 );
00404                         for( ipHi=0; ipHi < iso.numLevels_max[ipISO][nelem]; ipHi++ )
00405                         {
00406                                 fprintf( ioQQQ,PrintEfmt("%10.3e",  iso.ColIoniz[ipISO][nelem][ipHi] ));
00407                         }
00408                         fprintf( ioQQQ, "\n" );
00409 
00410                         fprintf( ioQQQ, "     iso_collide: %s Z=%li continuum boltzmann factor\n", iso.chISO[ipISO], nelem + 1 );
00411                         for( ipHi=0; ipHi < iso.numLevels_max[ipISO][nelem]; ipHi++ )
00412                         {
00413                                 fprintf( ioQQQ,PrintEfmt("%10.3e",  StatesElem[ipISO][nelem][ipHi].ConBoltz ));
00414                         }
00415                         fprintf( ioQQQ, "\n" );
00416 
00417                         fprintf( ioQQQ, "     iso_collide: %s Z=%li continuum boltzmann factor\n", iso.chISO[ipISO], nelem + 1 );
00418                         for( ipHi=0; ipHi < iso.numLevels_max[ipISO][nelem]; ipHi++ )
00419                         {
00420                                 fprintf( ioQQQ,PrintEfmt("%10.3e",  iso.PopLTE[ipISO][nelem][ipHi] ));
00421                         }
00422                         fprintf( ioQQQ, "\n" );
00423                 }
00424         }
00425 
00426         iso_suprathermal( ipISO, nelem );
00427 
00428         
00429 
00430 
00431 
00432 
00433         if( nelem==ipHYDROGEN )
00434         {
00435                 
00436                 edenCorr = dense.EdenHontoHCorr;
00437         }
00438         else
00439         {
00440                 edenCorr = dense.EdenHCorr;
00441         }
00442 
00443         
00444         
00445         ionbal.CollIonRate_Ground[nelem][nelem-ipISO][0] = 
00446                 iso.ColIoniz[ipISO][nelem][0]*edenCorr;
00447 
00448         
00449         ionbal.CollIonRate_Ground[nelem][nelem-ipISO][1] = 
00450                 ionbal.CollIonRate_Ground[nelem][nelem-ipISO][0]*
00451                 rfield.anu[Heavy.ipHeavy[nelem][nelem-ipISO]-1]*EN1RYD;
00452 
00453         return;
00454 }