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 }