00001
00002
00003
00004 #include "cddefines.h"
00005 #include "physconst.h"
00006 #include "hydrogenic.h"
00007 #include "taulines.h"
00008 #include "wind.h"
00009 #include "coolheavy.h"
00010 #include "radius.h"
00011 #include "conv.h"
00012 #include "h2.h"
00013 #include "opacity.h"
00014 #include "ionbal.h"
00015 #include "dense.h"
00016 #include "trace.h"
00017 #include "dynamics.h"
00018 #include "rfield.h"
00019 #include "grainvar.h"
00020 #include "atoms.h"
00021 #include "called.h"
00022 #include "hmi.h"
00023 #include "numderiv.h"
00024 #include "magnetic.h"
00025 #include "phycon.h"
00026 #include "lines_service.h"
00027 #include "hyperfine.h"
00028 #include "iso.h"
00029 #include "thermal.h"
00030 #include "cooling.h"
00031
00032 STATIC void fndneg(void);
00033
00034 STATIC void fndstr(double tot,
00035 double dc);
00036
00037
00038 static const bool PRT_DERIV = false;
00039
00040 void CoolEvaluate(double *tot)
00041 {
00042 long int ion,
00043 i,
00044 ipISO,
00045 nelem;
00046
00047 static long int nhit = 0,
00048 nzSave=0;
00049
00050 static double TeEvalCS = 0., TeEvalCS_21cm=0.;
00051 static double TeUsedBrems=-1.f;
00052 static int nzoneUsedBrems=-1;
00053
00054 static double electron_rate_21cm,
00055 atomic_rate_21cm,
00056 proton_rate_21cm;
00057
00058 double
00059 cs ,
00060 deriv,
00061 factor,
00062 qn,
00063 rothi=-SMALLFLOAT,
00064 rotlow=-SMALLFLOAT,
00065 x;
00066
00067 static double oltcool=0.,
00068 oldtemp=0.;
00069
00070 DEBUG_ENTRY( "CoolEvaluate()" );
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 if( trace.lgTrace )
00085 fprintf( ioQQQ, " COOLR TE:%.4e zone %li %li Cool:%.4e Heat:%.4e eden:%.4e edenTrue:%.4e\n",
00086 phycon.te,
00087 nzone, conv.nPres2Ioniz ,
00088 thermal.ctot , thermal.htot,dense.eden,dense.EdenTrue );
00089
00090
00091
00092 TempChange(phycon.te , false);
00093
00094
00095 CoolZero();
00096 if( PRT_DERIV )
00097 fprintf(ioQQQ,"DEBUG dcdt 0 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00098 if( gv.lgGrainPhysicsOn )
00099 {
00100
00101
00102
00103 CoolAdd("dust",0,MAX2(0.,gv.GasCoolColl));
00104
00105
00106 thermal.dCooldT += MAX2(0.,gv.GasCoolColl)*3./(2.*phycon.te);
00107
00108
00109
00110 if( gv.lgDustOn && gv.lgDHetOn )
00111 {
00112
00113 thermal.heating[0][13] = gv.GasHeatPhotoEl;
00114
00115
00116
00117
00118 thermal.heating[0][14] = MAX2(0.,-gv.GasCoolColl);
00119
00120
00121 thermal.heating[0][25] = gv.GasHeatTherm;
00122 }
00123 else
00124 {
00125 thermal.heating[0][13] = 0.;
00126 thermal.heating[0][14] = 0.;
00127 thermal.heating[0][25] = 0.;
00128 }
00129 }
00130 else if( gv.lgBakesPAH_heat )
00131 {
00132
00133
00134 thermal.heating[0][13] = gv.GasHeatPhotoEl;
00135 }
00136
00137
00138 H2_Cooling("CoolEvaluate");
00139 if( PRT_DERIV )
00140 fprintf(ioQQQ,"DEBUG dcdt 1 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00141
00142
00143 if( hmi.lgNoH2Mole )
00144 {
00145
00146 hmi.hmicol = 0.;
00147 CoolHeavy.brems_cool_hminus = 0.;
00148
00149 CoolHeavy.h2line = 0.;
00150
00151 CoolHeavy.H2PlsCool = 0.;
00152 CoolHeavy.HD = 0.;
00153
00154
00155 thermal.heating[0][8] = 0.;
00156
00157 thermal.heating[0][15] = 0.;
00158
00159 thermal.heating[0][16] = 0.;
00160 hmi.HeatH2Dish_used = 0.;
00161 hmi.HeatH2Dexc_used = 0.;
00162 }
00163
00164 else
00165 {
00166
00167 thermal.heating[0][15] = hmi.hmihet;
00168 thermal.heating[0][16] = hmi.h2plus_heat;
00169
00170 if( h2.lgH2ON && hmi.lgH2_Thermal_BigH2 )
00171 {
00172 if( hmi.lgBigH2_evaluated )
00173 {
00174
00175
00176
00177
00178 hmi.HeatH2Dish_used = hmi.HeatH2Dish_BigH2;
00179 hmi.HeatH2Dexc_used = hmi.HeatH2Dexc_BigH2;
00180
00181
00182
00183
00184
00185 hmi.deriv_HeatH2Dexc_used = -hmi.deriv_HeatH2Dexc_BigH2;
00186 }
00187 else
00188 {
00189 hmi.HeatH2Dish_used = 0;
00190 hmi.HeatH2Dexc_used = 0;
00191 hmi.deriv_HeatH2Dexc_used = 0;
00192 }
00193 }
00194
00195 else if( hmi.chH2_small_model_type == 'T' )
00196 {
00197
00198
00199 hmi.HeatH2Dish_used = hmi.HeatH2Dish_TH85;
00200 hmi.HeatH2Dexc_used = hmi.HeatH2Dexc_TH85;
00201 hmi.deriv_HeatH2Dexc_used = hmi.deriv_HeatH2Dexc_TH85;
00202 }
00203 else if( hmi.chH2_small_model_type == 'H' )
00204 {
00205
00206 hmi.HeatH2Dish_used = hmi.HeatH2Dish_BHT90;
00207 hmi.HeatH2Dexc_used = hmi.HeatH2Dexc_BHT90;
00208 hmi.deriv_HeatH2Dexc_used = hmi.deriv_HeatH2Dexc_BHT90;
00209 }
00210 else if( hmi.chH2_small_model_type == 'B')
00211 {
00212
00213 hmi.HeatH2Dish_used = hmi.HeatH2Dish_BD96;
00214 hmi.HeatH2Dexc_used = hmi.HeatH2Dexc_BD96;
00215 hmi.deriv_HeatH2Dexc_used = hmi.deriv_HeatH2Dexc_BD96;
00216 }
00217 else if(hmi.chH2_small_model_type == 'E')
00218 {
00219
00220 hmi.HeatH2Dish_used = hmi.HeatH2Dish_ELWERT;
00221 hmi.HeatH2Dexc_used = hmi.HeatH2Dexc_ELWERT;
00222 hmi.deriv_HeatH2Dexc_used = hmi.deriv_HeatH2Dexc_ELWERT;
00223 }
00224 else
00225 TotalInsanity();
00226
00227
00228 thermal.heating[0][17] = hmi.HeatH2Dish_used;
00229
00230
00231
00232 thermal.heating[0][8] = MAX2(0.,hmi.HeatH2Dexc_used);
00233
00234
00235 CoolAdd("H2cX",0,MAX2(0.,-hmi.HeatH2Dexc_used));
00236
00237
00238
00239
00240
00241
00242
00243 if( hmi.HeatH2Dexc_used < 0. )
00244 thermal.dCooldT -= hmi.deriv_HeatH2Dexc_used;
00245
00246
00247 CoolHeavy.H2PlsCool = (realnum)(MAX2((2.325*phycon.te-1875.)*1e-20,0.)*
00248 dense.xIonDense[ipHYDROGEN][0]*dense.xIonDense[ipHYDROGEN][1]*1.66e-11);
00249
00250 if( h2.lgH2ON )
00251 {
00252
00253
00254 CoolHeavy.h2line = 0.;
00255 }
00256 else
00257 {
00258
00259
00260 x = phycon.alogte - 4.;
00261 if( phycon.te > 1087. )
00262 {
00263 rothi = 3.90e-19*sexp(6118./phycon.te);
00264 }
00265 else
00266 {
00267 rothi = pow(10.,-19.24 + 0.474*x - 1.247*x*x);
00268 }
00269
00270
00271
00272 qn = pow(MAX2(hmi.H2_total,1e-37),0.77) + 1.2*pow(MAX2(dense.xIonDense[ipHYDROGEN][0],1e-37),0.77);
00273
00274 if( phycon.te > 4031. )
00275 {
00276 rotlow = 1.38e-22*sexp(9243./phycon.te)*qn;
00277 }
00278 else
00279 {
00280 rotlow = pow(10.,-22.90 - 0.553*x - 1.148*x*x)*qn;
00281 }
00282
00283 if( rotlow > 0. )
00284 {
00285
00286 CoolHeavy.h2line = hmi.H2_total*rothi/(1. + rothi/rotlow);
00287 }
00288 else
00289 {
00290 CoolHeavy.h2line = 0.;
00291 }
00292 }
00293
00294 {
00295 enum {DEBUG_LOC=false};
00296 if( DEBUG_LOC && nzone>187&& iteration > 1)
00297 {
00298 fprintf(ioQQQ,"h2coolbug\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\n",
00299 phycon.te,
00300 CoolHeavy.h2line,
00301 hmi.H2_total,
00302 hmi.Hmolec[ipMHm],
00303 hmi.HMinus_photo_rate,
00304 rothi,
00305 rotlow );
00306 }
00307 }
00308
00309
00310
00311 factor = sexp(128.6/phycon.te);
00312
00313
00314 CoolHeavy.HD = 2.66e-21 * hydro.D2H_ratio * POW2((double)hmi.H2_total) * phycon.sqrte *
00315
00316 factor/(1416.+phycon.sqrte*hmi.H2_total * (1. + 3.*factor));
00317 }
00318
00319
00320 CoolAdd("CT C" , 0. , thermal.char_tran_cool );
00321
00322
00323
00324 CoolAdd("H-fb",0,hmi.hmicol);
00325
00326
00327
00328
00329 thermal.dCooldT += 2.*hmi.hmicol*phycon.teinv;
00330 if( PRT_DERIV )
00331 fprintf(ioQQQ,"DEBUG dcdt 2 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00332
00333 CoolAdd("H2ln",0,CoolHeavy.h2line);
00334
00335
00336
00337
00338
00339
00340
00341
00342 thermal.dCooldT += 3.0*CoolHeavy.h2line*phycon.teinv;
00343
00344 {
00345
00346 enum {DEBUG_LOC=false};
00347 if( DEBUG_LOC )
00348 {
00349 fprintf(ioQQQ,"CoolEvaluate debuggg\t%.2f\t%.5e\t%.5e\t%.5e\t%.5e\t%.5e\n",
00350 fnzone,
00351 phycon.te,
00352 hmi.H2_total ,
00353 CoolHeavy.h2line,
00354 hmi.Hmolec[ipMHm] ,
00355 dense.eden);
00356 }
00357 }
00358
00359 CoolAdd("HDro",0,CoolHeavy.HD);
00360 thermal.dCooldT += CoolHeavy.HD*phycon.teinv;
00361
00362 CoolAdd("H2+ ",0,CoolHeavy.H2PlsCool);
00363 thermal.dCooldT += CoolHeavy.H2PlsCool*phycon.teinv;
00364
00365
00366 CoolAdd("CO C",12,CoolHeavy.C12O16Rot);
00367 thermal.dCooldT += CoolHeavy.dC12O16Rot;
00368
00369
00370 CoolAdd("CO C",13,CoolHeavy.C13O16Rot);
00371 thermal.dCooldT += CoolHeavy.dC13O16Rot;
00372
00373
00374 thermal.heating[0][3] = 0.;
00375
00376 thermal.heating[0][23] = 0.;
00377
00378 thermal.heating[0][1] = 0.;
00379
00380
00381 for( ipISO=ipH_LIKE; ipISO<NISO; ++ipISO )
00382 {
00383 for( nelem=ipISO; nelem < LIMELM; nelem++ )
00384 {
00385
00386
00387 iso_cool( ipISO , nelem );
00388 }
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398 if( (fabs(CoolHeavy.brems_cool_net)/SDIV(thermal.ctot)>0.001 ) ||
00399 conv.lgSearch ||
00400 fabs((phycon.te-TeUsedBrems)/phycon.te-1.)>0.01 ||
00401 nzone!=nzoneUsedBrems )
00402 {
00403 double BremsThisEnergy;
00404
00405 long int limit;
00406
00407
00408 TeUsedBrems = phycon.te;
00409 nzoneUsedBrems = nzone;
00410
00411 limit = MIN2( rfield.ipMaxBolt , rfield.nflux );
00412
00413 CoolHeavy.brems_cool_hminus = 0.;
00414 CoolHeavy.brems_cool_h = 0.;
00415 CoolHeavy.brems_cool_metals = 0.;
00416 CoolHeavy.brems_cool_he = 0.;
00417 CoolHeavy.brems_heat_total = 0.;
00418
00419 {
00420 double bhfac;
00421 realnum sumion[LIMELM+1];
00422 long int ion_lo , ion_hi;
00423
00424 ASSERT(rfield.ipEnergyBremsThin < rfield.nupper);
00425 ASSERT(limit < rfield.nupper);
00426
00427
00428
00429
00430
00431
00432
00433 nelem = ipHYDROGEN;
00434 ion = 1;
00435 CoolHeavy.brems_cool_h = 0.;
00436 CoolHeavy.brems_cool_hminus = 0.;
00437
00438 for( i=rfield.ipEnergyBremsThin; i < limit; i++ )
00439 {
00440
00441
00442
00443 BremsThisEnergy = rfield.gff[ion][i]*rfield.widflx[i]*rfield.ContBoltz[i];
00444
00445 CoolHeavy.brems_cool_h += BremsThisEnergy;
00446
00447
00448
00449 CoolHeavy.brems_cool_hminus += BremsThisEnergy * opac.OpacStack[i-1+opac.iphmra]*StatesElem[ipH_LIKE][ipHYDROGEN][ipH1s].Pop;
00450
00451 }
00452 bhfac = dense.xIonDense[nelem][ion]*CoolHeavy.lgFreeOn* dense.eden*1.032e-11/phycon.sqrte*EN1RYD;
00453 CoolHeavy.brems_cool_h *= bhfac;
00454 CoolHeavy.brems_cool_hminus*= bhfac;
00455
00456
00457 nelem = ipHELIUM;
00458 CoolHeavy.brems_cool_he = 0.;
00459 for( i=rfield.ipEnergyBremsThin; i < limit; i++ )
00460 {
00461
00462 BremsThisEnergy =
00463 (dense.xIonDense[nelem][1]*rfield.gff[1][i] + 4.*dense.xIonDense[nelem][2]*rfield.gff[2][i])*
00464 rfield.widflx[i]*rfield.ContBoltz[i];
00465 CoolHeavy.brems_cool_he += BremsThisEnergy;
00466 }
00467 CoolHeavy.brems_cool_he *=
00468 CoolHeavy.lgFreeOn * dense.eden*1.032e-11/phycon.sqrte*EN1RYD;
00469
00470
00471
00472
00473 sumion[0] = 0.;
00474 for(ion=1; ion<=LIMELM; ++ion )
00475 {
00476 sumion[ion] = 0.;
00477 for( nelem=ipLITHIUM; nelem < LIMELM; ++nelem )
00478 {
00479 if( dense.lgElmtOn[nelem] && ion<=nelem+1 )
00480 {
00481 sumion[ion] += dense.xIonDense[nelem][ion];
00482 }
00483 }
00484
00485 sumion[ion] *= POW2((realnum)ion);
00486 }
00487
00488
00489
00490
00491 ion_lo = 1;
00492 while( sumion[ion_lo]==0 && ion_lo<LIMELM-1 )
00493 ++ion_lo;
00494 ion_hi = LIMELM;
00495 while( sumion[ion_hi]==0 && ion_hi>0 )
00496 --ion_hi;
00497
00498
00499 CoolHeavy.brems_cool_metals = 0.;
00500 CoolHeavy.brems_heat_total = 0.;
00501 for( i=rfield.ipEnergyBremsThin; i < limit; i++ )
00502 {
00503 BremsThisEnergy = 0.;
00504 for(ion=ion_lo; ion<=ion_hi; ++ion )
00505 {
00506 BremsThisEnergy += sumion[ion]*rfield.gff[ion][i];
00507 }
00508 CoolHeavy.brems_cool_metals += BremsThisEnergy*rfield.widflx[i]*rfield.ContBoltz[i];
00509
00510 CoolHeavy.brems_heat_total += opac.FreeFreeOpacity[i]*rfield.flux[i]*rfield.anu[i]*EN1RYD*CoolHeavy.lgFreeOn;
00511 }
00512 CoolHeavy.brems_cool_metals *=
00513 CoolHeavy.lgFreeOn * dense.eden*1.032e-11/phycon.sqrte*EN1RYD;
00514 {
00515 enum {DEBUG_LOC=false};
00516 if( DEBUG_LOC && nzone>60 )
00517 {
00518 double sumfield = 0., sumtot=0., sum1=0., sum2=0.;
00519 for( i=rfield.ipEnergyBremsThin; i<limit; i++ )
00520 {
00521 sumtot += opac.FreeFreeOpacity[i]*rfield.flux[i]*rfield.anu[i];
00522 sumfield += rfield.flux[i]*rfield.anu[i];
00523 sum1 += opac.FreeFreeOpacity[i]*rfield.flux[i]*rfield.anu[i];
00524 sum2 += opac.FreeFreeOpacity[i]*rfield.flux[i];
00525 }
00526 fprintf(ioQQQ,"DEBUG brems heat\t%.2f\t%.3e\t%.3e\t%.3e\t%e\t%.3e\t%.3e\n",
00527 fnzone,
00528 CoolHeavy.brems_heat_total,
00529 sumtot/SDIV(sumfield) ,
00530 sum1/SDIV(sum2),
00531 phycon.te ,
00532 rfield.gff[1][1218],
00533 opac.FreeFreeOpacity[1218]);
00534 }
00535 }
00536 }
00537 }
00538
00539
00540
00541 CoolHeavy.brems_cool_net =
00542 CoolHeavy.brems_cool_h +
00543 CoolHeavy.brems_cool_he +
00544 CoolHeavy.brems_cool_hminus +
00545 CoolHeavy.brems_cool_metals -
00546 CoolHeavy.brems_heat_total;
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 CoolAdd( "FF c" , 0, MAX2(0.,CoolHeavy.brems_cool_net) );
00559
00560
00561 thermal.heating[0][11] = MAX2(0.,-CoolHeavy.brems_cool_net);
00562
00563
00564
00565 thermal.dCooldT += CoolHeavy.brems_cool_h*thermal.halfte;
00566 if( PRT_DERIV )
00567 fprintf(ioQQQ,"DEBUG dcdt 3 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00568
00569
00570
00571
00572
00573
00574
00575 CoolHeavy.heavfb = 0.;
00576 for( nelem=ipLITHIUM; nelem < LIMELM; nelem++ )
00577 {
00578 if( dense.lgElmtOn[nelem] )
00579 {
00580
00581
00582
00583 long limit_lo = MAX2( 1 , dense.IonLow[nelem] );
00584
00585 long limit_hi = MIN2( nelem-NISO+1-1 , dense.IonHigh[nelem] );
00586 for( ion=limit_lo; ion<=limit_hi; ++ion )
00587
00588 {
00589
00590
00591
00592
00593
00594
00595 double one = dense.xIonDense[nelem][ion] * ionbal.RR_rate_coef_used[nelem][ion-1]*
00596 dense.eden * phycon.te * BOLTZMANN;
00597
00598
00599 CoolHeavy.heavfb += one;
00600 }
00601 }
00602 }
00603
00604
00605
00606 CoolAdd("hvFB",0,CoolHeavy.heavfb);
00607 thermal.dCooldT += CoolHeavy.heavfb*.113*phycon.teinv;
00608 if( PRT_DERIV )
00609 fprintf(ioQQQ,"DEBUG dcdt 4 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00610
00611
00612
00613
00614 CoolHeavy.eebrm = POW2(dense.eden*phycon.te*1.84e-21);
00615
00616
00617 thermal.dCooldT += CoolHeavy.eebrm*thermal.halfte;
00618 CoolAdd("eeff",0,CoolHeavy.eebrm);
00619
00620
00621
00622 CoolAdd("adve",0,dynamics.Cool );
00623
00624 thermal.dCooldT += dynamics.dCooldT;
00625
00626 thermal.heating[1][5] = dynamics.Heat;
00627 thermal.dHeatdT += dynamics.dHeatdT;
00628
00629
00630 CoolHeavy.tccool = rfield.cmcool*phycon.te;
00631 CoolAdd("Comp",0,CoolHeavy.tccool);
00632 thermal.dCooldT += rfield.cmcool;
00633
00634
00635
00636 if( thermal.lgCExtraOn )
00637 {
00638 CoolHeavy.cextxx =
00639 (realnum)(thermal.CoolExtra*pow(phycon.te/1e4,(double)thermal.cextpw));
00640 }
00641 else
00642 {
00643 CoolHeavy.cextxx = 0.;
00644 }
00645 CoolAdd("Extr",0,CoolHeavy.cextxx);
00646
00647
00648 if( wind.windv > 0. )
00649 {
00650 dynamics.dDensityDT = (realnum)(wind.AccelTot/wind.windv + 2.*wind.windv/
00651 radius.Radius);
00652 CoolHeavy.expans = dense.pden*phycon.te*BOLTZMANN*dynamics.dDensityDT;
00653 }
00654 else
00655 {
00656 dynamics.dDensityDT = 0.;
00657 CoolHeavy.expans = 0.;
00658 }
00659 CoolAdd("Expn",0,CoolHeavy.expans);
00660 thermal.dCooldT += CoolHeavy.expans/phycon.te;
00661
00662
00663
00664 CoolHeavy.cyntrn = 4.5433e-25f*magnetic.pressure*PI8*dense.eden*phycon.te;
00665 CoolAdd("Cycl",0,CoolHeavy.cyntrn);
00666 thermal.dCooldT += CoolHeavy.cyntrn/phycon.te;
00667
00668
00669
00670
00671 CoolAdd("Hvin",0,CoolHeavy.colmet);
00672
00673
00674 if( fabs(phycon.te-TeEvalCS_21cm)/phycon.te > 0.001 )
00675 {
00676 {
00677
00678 enum {DEBUG_LOC=false};
00679 if( DEBUG_LOC )
00680 {
00681 # define N21CM_TE 16
00682 int n;
00683 double teval[N21CM_TE]={2.,5.,10.,20.,50.,100.,200.,500.,1000.,
00684 2000.,3000.,5000.,7000.,10000.,15000.,20000.};
00685 for( n = 0; n<N21CM_TE; ++n )
00686 {
00687 fprintf(
00688 ioQQQ,"DEBUG 21 cm deex Te=\t%.2e\tH0=\t%.2e\tp=\t%.2e\te=\t%.2e\n",
00689 teval[n],
00690 H21cm_H_atom( teval[n] ),
00691 H21cm_proton( teval[n] ),
00692 H21cm_electron( teval[n] ) );
00693 }
00694 cdEXIT(EXIT_FAILURE);
00695 # undef N21CM_TE
00696 }
00697 }
00698
00699
00700 atomic_rate_21cm = H21cm_H_atom( phycon.te );
00701 proton_rate_21cm = H21cm_proton( phycon.te );
00702 electron_rate_21cm = H21cm_electron( phycon.te );
00703 TeEvalCS_21cm = phycon.te;
00704 }
00705
00706
00707 cs = (electron_rate_21cm * dense.eden +
00708 atomic_rate_21cm * dense.xIonDense[ipHYDROGEN][0] +
00709 proton_rate_21cm * dense.xIonDense[ipHYDROGEN][1] ) *
00710 3./ dense.cdsqte;
00711 PutCS( cs , &HFLines[0] );
00712
00713
00714 if( fabs(phycon.te-TeEvalCS)/phycon.te > 0.05 )
00715 {
00716
00717 for( i=1; i < nHFLines; i++ )
00718 {
00719 cs = HyperfineCS( i );
00720
00721 PutCS( cs , &HFLines[i] );
00722 }
00723 TeEvalCS = phycon.te;
00724 }
00725
00726
00727 H21_cm_pops();
00728 if( PRT_DERIV )
00729 fprintf(ioQQQ,"DEBUG dcdt 5 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00730
00731
00732 hyperfine.cooling_total = HFLines[0].Coll.cool;
00733
00734
00735 for( i=1; i < nHFLines; i++ )
00736 {
00737
00738 realnum save = dense.xIonDense[HFLines[i].Hi->nelem-1][HFLines[i].Hi->IonStg-1];
00739
00740
00741 if( save<=0. ) continue;
00742
00743
00744 dense.xIonDense[HFLines[i].Hi->nelem-1][HFLines[i].Hi->IonStg-1] *=
00745 hyperfine.HFLabundance[i];
00746
00747
00748 atom_level2( &HFLines[i] );
00749
00750
00751 dense.xIonDense[HFLines[i].Hi->nelem-1][HFLines[i].Hi->IonStg-1] = save;
00752
00753
00754 hyperfine.cooling_total += HFLines[i].Coll.cool;
00755 }
00756 if( PRT_DERIV )
00757 fprintf(ioQQQ,"DEBUG dcdt 6 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00758
00759
00760 CoolCarb();
00761 if( PRT_DERIV )
00762 fprintf(ioQQQ,"DEBUG dcdt C %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00763
00764
00765 CoolNitr();
00766 if( PRT_DERIV )
00767 fprintf(ioQQQ,"DEBUG dcdt N %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00768
00769
00770 CoolOxyg();
00771 if( PRT_DERIV )
00772 fprintf(ioQQQ,"DEBUG dcdt 7 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00773
00774
00775 CoolFluo();
00776
00777
00778 CoolNeon();
00779 if( PRT_DERIV )
00780 fprintf(ioQQQ,"DEBUG dcdt Ne %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00781
00782
00783 CoolMagn();
00784 if( PRT_DERIV )
00785 fprintf(ioQQQ,"DEBUG dcdt 8 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00786
00787
00788 CoolSodi();
00789 if( PRT_DERIV )
00790 fprintf(ioQQQ,"DEBUG dcdt Na %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00791
00792
00793 CoolAlum();
00794 if( PRT_DERIV )
00795 fprintf(ioQQQ,"DEBUG dcdt Al %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00796
00797
00798 CoolSili();
00799 if( PRT_DERIV )
00800 fprintf(ioQQQ,"DEBUG dcdt 9 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00801
00802
00803 CoolPhos();
00804
00805
00806 CoolSulf();
00807
00808
00809 CoolChlo();
00810
00811
00812 CoolArgo();
00813 if( PRT_DERIV )
00814 fprintf(ioQQQ,"DEBUG dcdt 10 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00815
00816
00817 CoolPota();
00818
00819
00820 CoolCalc();
00821
00822
00823 CoolScan();
00824
00825
00826 CoolTita();
00827 if( PRT_DERIV )
00828 fprintf(ioQQQ,"DEBUG dcdt 11 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00829
00830
00831 CoolVana();
00832
00833
00834 CoolChro();
00835
00836
00837 CoolIron();
00838 if( PRT_DERIV )
00839 fprintf(ioQQQ,"DEBUG dcdt 12 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00840
00841
00842 CoolMang();
00843
00844
00845 CoolCoba();
00846
00847
00848 CoolNick();
00849
00850
00851 CoolZinc();
00852 if( PRT_DERIV )
00853 fprintf(ioQQQ,"DEBUG dcdt 13 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00854
00855
00856 CoolDima();
00857
00858
00859 atmol_popsolve();
00860
00861
00862 CoolSum(tot);
00863 if( PRT_DERIV )
00864 fprintf(ioQQQ,"DEBUG dcdt 14 %.3e %.3e\n",thermal.dCooldT , thermal.dHeatdT);
00865
00866
00867 if( *tot <= 0. )
00868 {
00869 fprintf( ioQQQ, " COOLR; cooling is <=0, this is impossible.\n" );
00870 ShowMe();
00871 cdEXIT(EXIT_FAILURE);
00872 }
00873
00874
00875 if( thermal.dCooldT == 0. )
00876 {
00877 fprintf( ioQQQ, " COOLR; cooling slope <=0, this is impossible.\n" );
00878 if( *tot > 0. && dense.gas_phase[ipHYDROGEN] < 1e-4 )
00879 {
00880 fprintf( ioQQQ, " Probably due to very low density.\n" );
00881 }
00882 ShowMe();
00883 cdEXIT(EXIT_FAILURE);
00884 }
00885
00886 if( trace.lgTrace )
00887 {
00888 fndstr(*tot,thermal.dCooldT);
00889 }
00890
00891
00892 if( (((((!thermal.lgTemperatureConstant) && *tot < 0.) && called.lgTalk) &&
00893 !conv.lgSearch) && thermal.lgCNegChk) && nzone > 0 )
00894 {
00895 fprintf( ioQQQ,
00896 " NOTE Negative cooling, zone %4ld, =%10.2e coola=%10.2e CHION=%10.2e Te=%10.2e\n",
00897 nzone,
00898 *tot,
00899 iso.cLya_cool[ipH_LIKE][ipHYDROGEN],
00900 iso.coll_ion[ipH_LIKE][ipHYDROGEN],
00901 phycon.te );
00902 fndneg();
00903 }
00904
00905
00906
00907 if( NumDeriv.lgNumDeriv )
00908 {
00909 if( ((nzone > 2 && nzone == nzSave) && ! fp_equal( oldtemp, phycon.te )) && nhit > 4 )
00910 {
00911
00912
00913 deriv = (oltcool - *tot)/(oldtemp - phycon.te);
00914 thermal.dCooldT = deriv;
00915 }
00916 else
00917 {
00918 deriv = thermal.dCooldT;
00919 }
00920 if( nzone != nzSave )
00921 nhit = 0;
00922
00923 nzSave = nzone;
00924 nhit += 1;
00925 oltcool = *tot;
00926 oldtemp = phycon.te;
00927 }
00928 return;
00929 }
00930
00931
00932 #ifdef EPS
00933 # undef EPS
00934 #endif
00935 #define EPS 0.01
00936
00937
00938 STATIC void fndneg(void)
00939 {
00940 long int i;
00941 double trig;
00942
00943 DEBUG_ENTRY( "fndneg()" );
00944
00945 trig = fabs(thermal.htot*EPS);
00946 for( i=0; i < thermal.ncltot; i++ )
00947 {
00948 if( thermal.cooling[i] < 0. && fabs(thermal.cooling[i]) > trig )
00949 {
00950 fprintf( ioQQQ, " negative line=%s %.2f fraction of heating=%.3f\n",
00951 thermal.chClntLab[i], thermal.collam[i], thermal.cooling[i]/
00952 thermal.htot );
00953 }
00954
00955 if( thermal.heatnt[i] > trig )
00956 {
00957 fprintf( ioQQQ, " heating line=%s %.2f fraction of heating=%.3f\n",
00958 thermal.chClntLab[i], thermal.collam[i], thermal.heatnt[i]/
00959 thermal.htot );
00960 }
00961 }
00962 return;
00963 }
00964
00965
00966 STATIC void fndstr(double tot,
00967 double dc)
00968 {
00969 char chStrngLab[NCOLNT_LAB_LEN+1];
00970 long int i;
00971 realnum wl;
00972 double str,
00973 strong;
00974
00975 DEBUG_ENTRY( "fndstr()" );
00976
00977 strong = 0.;
00978 wl = -FLT_MAX;
00979 for( i=0; i < thermal.ncltot; i++ )
00980 {
00981 if( fabs(thermal.cooling[i]) > strong )
00982 {
00983
00984 wl = thermal.collam[i];
00985
00986
00987 ASSERT( strlen( thermal.chClntLab[i] ) <= NCOLNT_LAB_LEN );
00988 strcpy( chStrngLab, thermal.chClntLab[i] );
00989 strong = fabs(thermal.cooling[i]);
00990 }
00991 }
00992
00993 str = strong;
00994
00995 fprintf( ioQQQ,
00996 " fndstr cool: TE=%10.4e Ne=%10.4e C=%10.3e dC/dT=%10.2e ABS(%s %.1f)=%.2e nz=%ld\n",
00997 phycon.te, dense.eden, tot, dc, chStrngLab
00998 , wl, str, nzone );
00999
01000
01001 if( trace.lgCoolTr )
01002 {
01003 realnum ratio;
01004
01005
01006 coolpr(ioQQQ,(char*)thermal.chClntLab[0],1,0.,"ZERO");
01007
01008
01009 for( i=0; i < thermal.ncltot; i++ )
01010 {
01011
01012
01013 ratio = (realnum)(thermal.cooling[i]/thermal.ctot);
01014 if( ratio >= EPS )
01015 {
01016
01017 coolpr(ioQQQ,(char*)thermal.chClntLab[i],thermal.collam[i], ratio,"DOIT");
01018 }
01019 }
01020
01021
01022 coolpr(ioQQQ,"DONE",1,0.,"DONE");
01023
01024
01025 if( thermal.heating[0][22]/thermal.ctot > 0.05 )
01026 {
01027 fprintf( ioQQQ,
01028 " All coolant heat greater than%6.2f%% of the total will be printed.\n",
01029 EPS*100. );
01030
01031 coolpr(ioQQQ,"ZERO",1,0.,"ZERO");
01032 for( i=0; i < thermal.ncltot; i++ )
01033 {
01034 ratio = (realnum)(thermal.heatnt[i]/thermal.ctot);
01035 if( fabs(ratio) >=EPS )
01036 {
01037 coolpr(ioQQQ,(char*)thermal.chClntLab[i],thermal.collam[i],
01038 ratio,"DOIT");
01039 }
01040 }
01041 coolpr(ioQQQ,"DONE",1,0.,"DONE");
01042 }
01043 }
01044 return;
01045 }