00001 
00002 
00003 
00004 #include "cddefines.h"
00005 
00006 #ifdef EPS
00007 #       undef EPS
00008 #endif
00009 #define EPS     1.00001
00010 #include "lines.h"
00011 #include "mole.h"
00012 #include "conv.h"
00013 #include "rfield.h"
00014 #include "iterations.h"
00015 #include "trace.h"
00016 #include "dense.h"
00017 #include "colden.h"
00018 #include "taulines.h"
00019 #include "hmi.h"
00020 #include "prt.h"
00021 #include "phycon.h"
00022 #include "geometry.h"
00023 #include "stopcalc.h"
00024 #include "opacity.h"
00025 #include "thermal.h"
00026 #include "cooling.h"
00027 #include "predcont.h"
00028 #include "pressure.h"
00029 #include "radius.h"
00030 #include "called.h"
00031 #include "wind.h"
00032 #include "hcmap.h"
00033 
00034 
00035 STATIC void dmpary(void);
00036 
00037 int iter_end_check(void)
00038 {
00039         bool lgDone, 
00040           lgEndFun_v, 
00041           lgPrinted;
00042         long int i;
00043         double oxy_in_grains;
00044 
00045         DEBUG_ENTRY( "iter_end_check()" );
00046 
00047         
00048 
00049 
00050         oxy_in_grains = 0.0f;
00051         for(i=0;i<mole.num_comole_calc;++i)
00052         {
00053                 
00054                 oxy_in_grains += (1 - COmole[i]->lgGas_Phase)*COmole[i]->hevmol*COmole[i]->nElem[ipOXYGEN];
00055         }
00056         
00057 
00058 
00059 
00060         if( trace.lgTrace )
00061         {
00062                 fprintf( ioQQQ, " iter_end_check called, zone %li.\n" , nzone);
00063         }
00064         ASSERT( hcmap.MapZone >= 00 || !conv.lgSearch );
00065 
00066         
00067         if( nzone == 0 )
00068         {
00069                 lgEndFun_v = false;
00070 
00071                 if( trace.lgTrace )
00072                 {
00073                         fprintf( ioQQQ, " iter_end_check returns, doing nothing since zone 0.\n" );
00074                 }
00075                 return( lgEndFun_v );
00076         }
00077 
00078         
00079         if( (nzone >= trace.nznbug && iteration >= trace.npsbug) && trace.lgTrOvrd )
00080         {
00081                 if( trace.nTrConvg==0 )
00082                 {
00083                         geometry.nprint = 1;
00084                         trace.lgTrace = true;
00085                 }
00086                 else
00087                         
00088 
00089                         trace.nTrConvg = abs( trace.nTrConvg );
00090         }
00091 
00092         
00093         if( prt.lgPrtStart && prt.nstart == nzone )
00094         {
00095                 called.lgTalk = cpu.lgMPI_talk();
00096         }
00097 
00098         
00099         lgDone = false;
00100 
00101         
00102         conv.lgBadStop = false;
00103 
00104         
00105 
00106 
00107         if( phycon.te < StopCalc.TeFloor )
00108         {
00109                 thermal.lgTemperatureConstant = true;
00110                 thermal.ConstTemp = (realnum)StopCalc.TeFloor;
00111                 phycon.te = thermal.ConstTemp;
00112                 TempChange(thermal.ConstTemp , false);
00113                 TotalInsanity();
00114         }
00115 
00116         
00117 
00118         if( (pressure.lgPres_radiation_ON && pressure.pbeta > 1.0) && 
00119                 (strcmp(dense.chDenseLaw ,"CPRE") == 0) && 
00120                 
00121                 (iterations.lgLastIt||(pressure.pbeta>1000.)) &&
00122                 
00123 
00124 
00125                 (pressure.lgRadPresAbortOK||(pressure.pbeta>1000.)) )
00126         {
00127                 
00128                 if( called.lgTalk )
00129                 {
00130                         fprintf( ioQQQ, "\n STOP since P(rad)/P(gas)=%7.3f >1.0\n", 
00131                           pressure.pbeta );
00132 
00133                         fprintf( ioQQQ, " Line contributors to radiation pressure follows:\n" );
00134                         PrtLinePres(ioQQQ);
00135                 }
00136                 lgDone = true;
00137                 conv.lgBadStop = true;
00138                 strncpy( StopCalc.chReasonStop, "of radiation pressure.", sizeof(StopCalc.chReasonStop) );
00139         }
00140 
00141         
00142         if( radius.drad_x_fillfac*radius.r1r0sq > BIGFLOAT/10.)
00143         {
00144                 
00145                 lgDone = true;
00146                 strncpy( StopCalc.chReasonStop, "volume too large for this cpu.", sizeof(StopCalc.chReasonStop) );
00147         }
00148         
00149 
00150         else if( !wind.lgVelPos && wind.lgBallistic() )
00151         {
00152                 
00153                 lgDone = true;
00154                 strncpy( StopCalc.chReasonStop, "wind veloc too small.", sizeof(StopCalc.chReasonStop) );
00155         }
00156 
00157         else if( !wind.lgStatic() && fabs(wind.windv) < StopCalc.StopVelocity )
00158         {
00159                 
00160                 lgDone = true;
00161                 strncpy( StopCalc.chReasonStop, "wind V too small.", sizeof(StopCalc.chReasonStop) );
00162         }
00163 
00164         else if( (StopCalc.nTotalIonizStop>0) && conv.nTotalIoniz> StopCalc.nTotalIonizStop )
00165         {
00166                 
00167 
00168                 lgDone = true;
00169                 strncpy( StopCalc.chReasonStop, "nTotalIonizStop reached.", sizeof(StopCalc.chReasonStop) );
00170         }
00171 
00172         
00173         else if( StopCalc.lgStop21cm && (HFLines[0].Emis->TauCon >=  StopCalc.tauend) )
00174         {
00175                 lgDone = true;
00176                 strncpy( StopCalc.chReasonStop, "21 cm optical depth.", sizeof(StopCalc.chReasonStop) );
00177         }
00178 
00179         else if( rfield.extin_mag_V_extended >= StopCalc.AV_extended )
00180         {
00181                 
00182                 lgDone = true;
00183                 strncpy( StopCalc.chReasonStop, "A_V reached.", sizeof(StopCalc.chReasonStop) );
00184         }
00185 
00186         else if( rfield.extin_mag_V_point >= StopCalc.AV_point )
00187         {
00188                 
00189                 lgDone = true;
00190                 strncpy( StopCalc.chReasonStop, "A_V reached.", sizeof(StopCalc.chReasonStop) );
00191         }
00192 
00193         else if( StopCalc.xMass!=0. &&
00194                 log10(SDIV(dense.xMassTotal))+1.0992099+ 2.*log10(radius.rinner) >= StopCalc.xMass )
00195         {
00196                 
00197                 lgDone = true;
00198                 strncpy( StopCalc.chReasonStop, "mass reached.", sizeof(StopCalc.chReasonStop) );
00199         }
00200 
00201         
00202         
00203  
00204         else if( pressure.lgSonicPoint && pressure.lgSonicPointAbortOK )
00205         {
00206                 
00207                 lgDone = true;
00208                 strncpy( StopCalc.chReasonStop, "sonic point reached.", sizeof(StopCalc.chReasonStop) );
00209         }
00210 
00211         else if( dense.EdenTrue==0 )
00212         {
00213                 
00214                 conv.lgBadStop = true;
00215                 lgDone = true;
00216                 strncpy( StopCalc.chReasonStop, "zero electron density.", sizeof(StopCalc.chReasonStop) );
00217         }
00218 
00219         else if( radius.lgdR2Small )
00220         {
00221                 lgDone = true;
00222                 conv.lgBadStop = true;
00223                 strncpy( StopCalc.chReasonStop, "DR small rel to thick.", sizeof(StopCalc.chReasonStop) );
00224         }
00225 
00226         else if( dense.eden < StopCalc.StopElecDensity )
00227         {
00228                 lgDone = true;
00229                 strncpy( StopCalc.chReasonStop, "lowest EDEN reached.", sizeof(StopCalc.chReasonStop) );
00230         }
00231 
00232         else if( dense.eden/dense.gas_phase[ipHYDROGEN] < StopCalc.StopElecFrac )
00233         {
00234                 lgDone = true;
00235                 strncpy( StopCalc.chReasonStop, "low electron fraction.", sizeof(StopCalc.chReasonStop) );
00236         }
00237 
00238         
00239 
00240 
00241         else if( dense.lgElmtOn[ipOXYGEN] &&
00242                 (oxy_in_grains/MAX2(SMALLFLOAT,dense.gas_phase[ipOXYGEN])) > StopCalc.StopDepleteFrac )
00243         {
00244                 lgDone = true;
00245                 strncpy( StopCalc.chReasonStop, "freeze out fraction.", sizeof(StopCalc.chReasonStop) );
00246         }
00247 
00248         
00249         else if( 2.*hmi.H2_total/dense.gas_phase[ipHYDROGEN] > StopCalc.StopH2MoleFrac )
00250         {
00251                 lgDone = true;
00252                 strncpy( StopCalc.chReasonStop, "large H_2/H fraction.", sizeof(StopCalc.chReasonStop) );
00253         }
00254 
00255         else if( dense.xIonDense[ipHYDROGEN][1]/dense.gas_phase[ipHYDROGEN] < 
00256                 StopCalc.StopHPlusFrac )
00257         {
00258                 lgDone = true;
00259                 strncpy( StopCalc.chReasonStop, "low H_+/H fraction.", sizeof(StopCalc.chReasonStop) );
00260         }
00261 
00262         else if( radius.lgDrMinUsed )
00263         {
00264                 
00265                 conv.lgBadStop = true;
00266                 lgDone = true;
00267                 strncpy( StopCalc.chReasonStop, "DRAD small- set DRMIN.", sizeof(StopCalc.chReasonStop) );
00268         }
00269 
00270         else if( radius.depth >= radius.StopThickness[iteration-1]/EPS )
00271         {
00272                 lgDone = true;
00273                 strncpy( StopCalc.chReasonStop, "outer radius reached.", sizeof(StopCalc.chReasonStop) );
00274         }
00275 
00276         else if( StopCalc.iptnu >= 0 && 
00277                 opac.TauAbsGeo[0][StopCalc.iptnu-1] >= StopCalc.tauend/EPS )
00278         {
00279                 lgDone = true;
00280                 strncpy( StopCalc.chReasonStop, "optical depth reached.", sizeof(StopCalc.chReasonStop) );
00281         }
00282 
00283         else if( StopCalc.lgStopSpeciesColumn && 
00284                 findspecies( StopCalc.chSpeciesColumn )->hevcol >= StopCalc.col_species/EPS )
00285         {
00286                 
00287                 lgDone = true;
00288                 sprintf( StopCalc.chReasonStop, "%s column dens reached.", StopCalc.chSpeciesColumn );
00289                 
00290         }
00291 
00292         else if( colden.colden[ipCOL_HTOT] >= StopCalc.HColStop/EPS )
00293         {
00294                 
00295                 lgDone = true;
00296                 strncpy( StopCalc.chReasonStop, "H column dens reached.", sizeof(StopCalc.chReasonStop) );
00297         }
00298 
00299         else if( colden.colden[ipCOL_Hp] >= StopCalc.colpls/EPS )
00300         {
00301                 lgDone = true;
00302                 strncpy( StopCalc.chReasonStop, "H+ column dens reached.", sizeof(StopCalc.chReasonStop) );
00303         }
00304 
00305         else if( (colden.colden[ipCOL_H2g]+colden.colden[ipCOL_H2s]) >= StopCalc.col_h2/EPS )
00306         {
00307                 
00308                 lgDone = true;
00309                 strncpy( StopCalc.chReasonStop, "H2 column dens reached.", sizeof(StopCalc.chReasonStop) );
00310         }
00311 
00312         else if( (2.*(colden.colden[ipCOL_H2g]+colden.colden[ipCOL_H2s]) + colden.colden[ipCOL_H0]) >= StopCalc.col_h2_nut/EPS )
00313         {
00314                 
00315                 lgDone = true;
00316                 strncpy( StopCalc.chReasonStop, "H2+H0 column dens reached.", sizeof(StopCalc.chReasonStop) );
00317         }
00318 
00319         else if( colden.H0_ov_Tspin >= StopCalc.col_H0_ov_Tspin/EPS )
00320         {
00321                 
00322                 lgDone = true;
00323                 strncpy( StopCalc.chReasonStop, "N(H0)/Tspin column dens reached.", sizeof(StopCalc.chReasonStop) );
00324         }
00325 
00326         else if( findspecies("CO")->hevcol >= StopCalc.col_monoxco/EPS )
00327         {
00328                 
00329                 lgDone = true;
00330                 strncpy( StopCalc.chReasonStop, "CO column dens reached.", sizeof(StopCalc.chReasonStop) );
00331         }
00332 
00333         else if( colden.colden[ipCOL_H0] >= StopCalc.colnut/EPS )
00334         {
00335                 lgDone = true;
00336                 strncpy( StopCalc.chReasonStop, "H0 column dens reached.", sizeof(StopCalc.chReasonStop) );
00337         }
00338 
00339         
00340 
00341         else if( hmi.lgNoH2Mole &&
00342                 ( (colden.colden[ipCOL_H0]+2.*(colden.colden[ipCOL_H2g]+colden.colden[ipCOL_H2s])) >= StopCalc.colnut/EPS)  )
00343         {
00344                 lgDone = true;
00345                 strncpy( StopCalc.chReasonStop, "H0-H0+H2 column dens reached.", sizeof(StopCalc.chReasonStop) );
00346         }
00347 
00348         else if( phycon.te > StopCalc.TempHiStopZone )
00349         {
00350                 lgDone = true;
00351                 strncpy( StopCalc.chReasonStop, "highest Te reached.", sizeof(StopCalc.chReasonStop) );
00352         }
00353 
00354         else if( phycon.te < StopCalc.TempLoStopZone )
00355         {
00356                 lgDone = true;
00357                 strncpy( StopCalc.chReasonStop, "lowest Te reached.", sizeof(StopCalc.chReasonStop) );
00358         }
00359 
00360         else if( nzone >= geometry.nend[iteration-1] )
00361         {
00362                 lgDone = true;
00363                 geometry.lgZoneTrp = true;
00364                 strncpy( StopCalc.chReasonStop, "NZONE reached.", sizeof(StopCalc.chReasonStop) );
00365         }
00366 
00367         
00368 
00369         else if( StopCalc.nstpl > 0 || StopCalc.ContIndex.size() > 0 )
00370         {
00371                 
00372 
00373                 for( i=0; i < StopCalc.nstpl; i++ )
00374                 {
00375                         
00376                         if( LineSv[StopCalc.ipStopLin2[i]].SumLine[StopCalc.nEmergent[i]] > 0. )
00377                         {
00378                                 char chString[10];
00379                                 if( LineSv[StopCalc.ipStopLin1[i]].SumLine[StopCalc.nEmergent[i]]/
00380                                         LineSv[StopCalc.ipStopLin2[i]].SumLine[StopCalc.nEmergent[i]] > 
00381                                         StopCalc.stpint[i] )
00382                                 {
00383                                         lgDone = true;
00384                                         sprt_wl( chString , StopCalc.StopLineWl1[i] );
00385                                         sprintf( StopCalc.chReasonStop, "line %s %s reached", 
00386                                                 StopCalc.chStopLabel1[i] , chString );
00387                                 }
00388                         }
00389                 }
00390                 
00391                 for( size_t k=0; k < StopCalc.ContIndex.size(); ++k )
00392                 {
00393                         
00394                         long ind = t_PredCont::Inst().offset() + 4*StopCalc.ContIndex[k];
00395                         double nFnu_model = LineSv[ind].SumLine[0]*pow(10.,radius.Conv2PrtInten);
00396                         if( nFnu_model >= StopCalc.ContNFnu[k].get("erg/s/cm2") )
00397                         {
00398                                 char chTemp[10];
00399                                 lgDone = true;
00400                                 sprt_wl( chTemp, LineSv[ind].wavelength );
00401                                 sprintf( StopCalc.chReasonStop, "flux %s %s reached", 
00402                                          LineSv[ind].chALab, chTemp );
00403                         }
00404                 }
00405         }
00406 
00407         else if( radius.drNext <= 0. )
00408         {
00409                 
00410                 if( called.lgTalk )
00411                 {
00412                         fprintf( ioQQQ, " drNext=%10.2e STOP\n", radius.drNext );
00413                 }
00414                 lgDone = true;
00415                 conv.lgBadStop = true;
00416                 strncpy( StopCalc.chReasonStop, "internal error - DRAD.", sizeof(StopCalc.chReasonStop) );
00417                 ShowMe();
00418                 cdEXIT(EXIT_FAILURE);
00419         }
00420 
00421         else if( lgAbort )
00422         {
00423                 
00424                 conv.lgBadStop = true;
00425                 lgDone = true;
00426                 strncpy( StopCalc.chReasonStop, "calculation aborted.", sizeof(StopCalc.chReasonStop) );
00427         }
00428 
00429         lgPrinted = false;
00430         if( lgDone )
00431         {
00432                 
00433                 lgEndFun_v = true;
00434                 PrtZone();
00435                 lgPrinted = true;
00436         }
00437 
00438         else
00439         {
00440                 
00441                 
00442                 if( ((nzone/geometry.nprint)*geometry.nprint == nzone || 
00443                   nzone == 1) || trace.nTrConvg )
00444                 {
00445                         PrtZone();
00446                         lgPrinted = true;
00447                 }
00448                 
00449                 lgEndFun_v = false;
00450         }
00451 
00452         
00453         if( prt.nzdump == nzone || prt.nzdump == 0 )
00454                 dmpary();
00455 
00456         
00457         
00458         
00459 
00460         if( !hcmap.lgMapDone && (hcmap.MapZone == 0 || nzone == hcmap.MapZone) )
00461         {
00462                 
00463                 if( !lgPrinted )
00464                 {
00465                         PrtZone();
00466                 }
00467 
00468                 
00469                 hcmap.lgMapBeingDone = true;
00470 
00471                 
00472                 
00473                 if( ioMAP != NULL )
00474                         map_do(ioMAP, " map");
00475                 else
00476                         map_do(ioQQQ, " map");
00477 
00478                 
00479                 lgEndFun_v = true;
00480                 strncpy( StopCalc.chReasonStop, "MAP command used-stop.", sizeof(StopCalc.chReasonStop) );
00481 
00482                 
00483 
00484                 iterations.itermx = 0;
00485 
00486                 
00487                 StopCalc.chReasonStop[sizeof(StopCalc.chReasonStop)-1] = '\0';
00488 
00489                 if( trace.lgTrace )
00490                 {
00491                         fprintf( ioQQQ, " iter_end_check returns after map.\n" );
00492                 }
00493                 return( lgEndFun_v );
00494         }
00495 
00496         if( lgEndFun_v && prt.lgOnlyZone )
00497         {
00498                 cdEXIT(EXIT_FAILURE);
00499         }
00500 
00501         
00502 
00503 
00504         if( strlen( StopCalc.chReasonStop ) >= nCHREASONSTOP-1 )
00505                 TotalInsanity();
00506 
00507         if( trace.lgTrace )
00508         {
00509                 fprintf( ioQQQ, " iter_end_check bottom return.\n" );
00510         }
00511         return( lgEndFun_v );
00512 }
00513 
00514 #ifdef EPS
00515 #       undef EPS
00516 #endif
00517 #define EPS     0.005
00518 
00519 STATIC void dmpary(void)
00520 {
00521         long int i;
00522         realnum ratio;
00523 
00524         DEBUG_ENTRY( "dmpary()" );
00525 
00526         fprintf( ioQQQ, 
00527                 " This is a print out of the cooling array for zone number %3ld\n", 
00528           nzone );
00529 
00530         fprintf( ioQQQ, 
00531                 " The total heating was HTOT=%10.2e erg/s/cm3, the total cooling was CTOT=%10.2e, and the temperature was%10.3eK.\n", 
00532           thermal.htot, thermal.ctot, phycon.te );
00533 
00534         fprintf( ioQQQ, 
00535                 " All coolants greater than%6.2f%% of the total will be printed.\n", 
00536           EPS*100. );
00537 
00538         
00539         coolpr(ioQQQ,"ZERO",1,0.,"ZERO");
00540         for( i=0; i < thermal.ncltot; i++ )
00541         {
00542                 ratio = (realnum)(thermal.cooling[i]/thermal.ctot);
00543                 if( fabs(ratio) > EPS )
00544                 {
00545                         coolpr(ioQQQ,(char*)thermal.chClntLab[i],thermal.collam[i],
00546                           ratio,"DOIT");
00547                 }
00548 
00549                 ratio = (realnum)(thermal.heatnt[i]/thermal.ctot);
00550                 if( fabs(ratio) > EPS )
00551                 {
00552                         coolpr(ioQQQ,(char*)thermal.chClntLab[i],thermal.collam[i],
00553                           ratio,"DOIT");
00554                 }
00555         }
00556         coolpr(ioQQQ,"DONE",1,0.,"DONE");
00557         return;
00558 }