00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include "cddefines.h"
00010 #include "hmi.h"
00011 #include "thermal.h"
00012 #include "iso.h"
00013 #include "hydrogenic.h"
00014 #include "colden.h"
00015 #include "h2.h"
00016 #include "pressure.h"
00017 #include "dense.h"
00018 #include "trace.h"
00019 #include "phycon.h"
00020 #include "conv.h"
00021 
00022 
00023 
00024 
00025 
00026 
00027 static const int LIMDEF = 60;
00028 
00029 
00030 STATIC double CoolHeatError( double temp );
00031 
00032 
00033 STATIC double TeBrent(
00034           double x1, 
00035           double x2);
00036 
00037 
00038 STATIC void MakeDeriv(
00039   
00040   const char *job, 
00041   
00042   double *DerivNumer);
00043 
00044 
00045 STATIC void PutHetCol(double te, 
00046   double htot, 
00047   double ctot);
00048 
00049 
00050 
00051 
00052 int ConvTempEdenIoniz( void )
00053 {
00054         char chDEType;
00055         long int limtry,
00056                 nTemperature_loop;
00057         
00058         double CoolMHeat=0., 
00059           Damper, 
00060           dtl, 
00061           fneut;
00062         int kase;
00063         double DerivNumer;
00064         static double OldCmHdT = 0.;
00065         long int nTemp_oscil;
00066 
00067         
00068         double dCoolmHeatdT;
00069 
00070         DEBUG_ENTRY( "ConvTempEdenIoniz()" );
00071 
00072         
00073 
00074 
00075 
00076         if( trace.lgTrace )
00077         {
00078                 fprintf( ioQQQ, "\n ConvTempEdenIoniz called\n" );
00079         }
00080         if( trace.nTrConvg>=2 )
00081         {
00082                 fprintf( ioQQQ, "  ConvTempEdenIoniz1 called. Te:%.4e Htot:%11.4e Ctot:%11.4e error:%9.1e%%, eden=%11.4e\n", 
00083                         phycon.te, thermal.htot, thermal.ctot, (thermal.htot - thermal.ctot)*
00084                         100./MAX2(1e-36,thermal.htot), dense.eden );
00085         }
00086 
00087         if( strcmp( conv.chSolverTemp , "new" ) == 0 )
00088         {
00089                 
00090                 double t1 , t2 ,
00091                         error1 , error2;
00092                 double TeNew;
00093                 double factor = 1.02;
00094 
00095                 t1 = phycon.te;
00096                 error1 = CoolHeatError( t1 );
00097                 t2 = t1 * factor;
00098                 error2 = CoolHeatError( t2 );
00099                 TeNew = TeBrent( t1 , t2 );
00100                 fprintf(ioQQQ , "DEBUG new temp solver error1 %.2e error2 %.2e TeNew %.2e\n",
00101                         error1 , error2 , TeNew );
00102         }
00103 
00104         else if( strcmp( conv.chSolverTemp , "simple") == 0 )
00105         {
00106 
00107                 
00108 
00109 
00110                 conv.lgTOscl = false;
00111                 
00112                 conv.lgOscilOTS = false;
00113 
00114                 
00115                 Damper = 1.;
00116 
00117                 
00118 
00119                 if( nzone < 1 )
00120                 {
00121                         conv.lgCmHOsc = false;
00122                 }
00123 
00124                 
00125                 MakeDeriv("zero",&DerivNumer);
00126 
00127                 
00128                 limtry = LIMDEF;
00129 
00130                 
00131                 dtl = 0.;
00132 
00133                 
00134 
00135 
00136                 nTemperature_loop = 0;
00137                 nTemp_oscil = 0;
00138 
00139                 
00140                 thermal.dTemper = 1e-3f*phycon.te;
00141 
00142                 
00143 
00144                 while ( true )
00145                 {
00146 
00147                         
00148 
00149 
00150 
00151 
00152                         if( ConvEdenIoniz() ) 
00153                         {
00154                                 return 1;
00155                         }
00156                         PresTotCurrent();
00157 
00158                         
00159                         CoolMHeat = thermal.ctot - thermal.htot;
00160                         
00161 
00162 
00163 
00164 
00165                         if( thermal.lgTemperatureConstant )
00166                         {
00167                                 
00168                                 CoolMHeat = 0.;
00169                         }
00170 
00171                         if( thermal.lgTLaw )
00172                         {
00173                                 double TeNew = phycon.te;
00174                                 
00175                                 if( thermal.lgTeBD96 )
00176                                 {
00177                                         
00178                                         TeNew = thermal.T0BD96 / (1.f + thermal.SigmaBD96 * colden.colden[ipCOL_HTOT] );
00179                                 }
00180                                 else if( thermal.lgTeSN99 )
00181                                 {
00182                                         
00183 
00184 
00185                                         TeNew = thermal.T0SN99 / 
00186                                                 
00187                                                 (realnum)(1.f + 9.*pow(2.*hmi.H2_total/dense.gas_phase[ipHYDROGEN], 4.) );
00188                                 }
00189                                 else
00190                                         TotalInsanity();
00191 
00192                                 TempChange(TeNew ,false);
00193                         }
00194 
00195                         
00196 
00197 
00198                         
00199 
00200                         
00201 
00202                         
00203 
00204 
00205                         if( (lgConvTemp() ) 
00206                                         && conv.lgConvIoniz )
00207                         {
00208                                 
00209                                 if( trace.lgTrace )
00210                                         fprintf( ioQQQ, " ConvTempEdenIoniz returns ok.\n" );
00211 
00212                                 
00213 
00214                                 
00215 
00216                                 if( thermal.dCooldT < 0. )
00217                                 {
00218                                         thermal.lgUnstable = true;
00219                                 }
00220                                 else
00221                                 {
00222                                         thermal.lgUnstable = false;
00223                                 }
00224 
00225                                 
00226                                 thermal.thist = (realnum)MAX2(phycon.te,thermal.thist);
00227                                 thermal.tlowst = (realnum)MIN2(phycon.te,thermal.tlowst);
00228 
00229                                 
00230                                 conv.lgConvTemp = true;
00231 
00232                                 if( trace.nTrConvg>=2 )
00233                                 {
00234                                         fprintf( ioQQQ, "  ConvTempEdenIoniz2 converged. Te:%11.4e Htot:%11.4e Ctot:%11.4e error:%9.1e%%, eden=%11.4e\n", 
00235                                           phycon.te, thermal.htot, thermal.ctot, (thermal.htot - thermal.ctot)*
00236                                           100./MAX2(1e-36,thermal.htot), dense.eden );
00237                                 }
00238                                 
00239 
00240 
00241 
00242 
00243                                 return 0;
00244                         }
00245                         else if(nTemperature_loop >= limtry || lgAbort )
00246                         {
00247                                 
00248 
00249                                 
00250 
00251                                 if( nTemperature_loop == LIMDEF && !conv.lgTOscl && 
00252                                         conv.lgConvIoniz  )
00253                                 {
00254                                         
00255 
00256 
00257                                         limtry = LIMDEF*4;
00258                                         if( trace.nTrConvg>2 )
00259                                         {
00260                                                 fprintf( ioQQQ, "  ConvTempEdenIoniz9 increases limtry to%3ld\n", 
00261                                                                                  limtry );
00262                                         }
00263                                 }
00264                                 else
00265                                 {
00266                                         
00267                                         break;
00268                                 }
00269                         }
00270 
00271                         
00272                         MakeDeriv("incr",&DerivNumer);
00273 
00274                         
00275                         PutHetCol(phycon.te,thermal.htot,thermal.ctot);
00276 
00277                         
00278 
00279 
00280 
00281                         if( !conv.lgConvEden )
00282                         {
00283                                 
00284 
00285                                 CoolMHeat = 0.;
00286                                 if( trace.nTrConvg>=2 )
00287                                 {
00288                                         fprintf( ioQQQ, 
00289                                                 "  ConvTempEdenIoniz3 breaks since lgConvEden returns failed electron density.\n"); 
00290                                 }
00291                                 break;
00292                         }
00293 
00294                         
00295                         if( nzone < 1 )
00296                         {
00297                                 
00298                                 OldCmHdT = thermal.ctot/phycon.te;
00299                         }
00300 
00301 #                       define USENUMER false
00302                         if( USENUMER )
00303                         {
00304                                 dCoolmHeatdT = DerivNumer;
00305                                 chDEType = 'n';
00306                         }
00307                         else if( phycon.te < 1e4 && thermal.dCooldT < 0. )
00308                         {
00309                                 
00310 
00311                                 dCoolmHeatdT = (double)(thermal.htot)/phycon.te*2.;
00312                                 chDEType = 'd';
00313                         }
00314                         else
00315                         {
00316                                 
00317 
00318                                 dCoolmHeatdT = thermal.dCooldT - thermal.dHeatdT;
00319                                 chDEType = 'a';
00320                         }
00321 
00322                         
00323 
00324                         if( OldCmHdT*dCoolmHeatdT < 0. )
00325                         {
00326                                 conv.lgCmHOsc = true;
00327 
00328                                 
00329 
00330 
00331 
00332                                 dCoolmHeatdT = thermal.ctot/phycon.te;
00333                                 chDEType = 'o';
00334                         }
00335                         OldCmHdT = dCoolmHeatdT;
00336 
00337                         
00338 
00339                         thermal.dTemper = (realnum)(CoolMHeat/dCoolmHeatdT);
00340                         kase = 0;
00341 
00342                         
00343                         
00344 
00345 
00346 
00347 
00348 
00349                         
00350 
00351 
00352                         if( dtl*thermal.dTemper < 0. && nTemperature_loop > 3)
00353                         {
00354                                 conv.lgTOscl = true;
00355                                 
00356                                 
00357 
00358                                 Damper *= 0.5;
00359                                 nTemp_oscil = nTemperature_loop;
00360                         }
00361                         else if( Damper < 1. && nTemperature_loop-nTemp_oscil > 10 )
00362                         {
00363                                 
00364 
00365 
00366                                 conv.lgTOscl = false;
00367                                 if( !((nTemperature_loop-nTemp_oscil)%5) )
00368                                         Damper = MIN2( 1., Damper*1.5 );
00369                         }
00370 
00371                         
00372                         
00373                         
00374                         fneut = (dense.xIonDense[ipHYDROGEN][0] + 2.*hmi.H2_total)/dense.gas_phase[ipHYDROGEN];
00375                         
00376 
00377                         
00378 
00379 
00380 
00381 
00382                         if( 0 && h2.lgH2ON && fabs(hmi.HeatH2Dexc_BigH2)/thermal.ctot > conv.HeatCoolRelErrorAllowed )
00383                         {
00384                                 
00385 
00386 
00387 
00388 
00389 
00390                                 double absdt = fabs(thermal.dTemper);
00391                                 thermal.dTemper = (sign(MIN2(absdt,0.0025*phycon.te),
00392                                   thermal.dTemper));
00393                                 kase = 1;
00394                         }
00395                         else if( fneut > 0.08 && hydro.lgHColionImp )
00396                         {
00397                                 
00398 
00399                                 double absdt = fabs(thermal.dTemper);
00400                                 thermal.dTemper = (sign(MIN2(absdt,0.005*phycon.te),
00401                                   thermal.dTemper));
00402                                 kase = 2;
00403                         }
00404 #                       if 0
00405                         
00406 
00407                         else if( 0 && nTemperature_loop <= 3)
00408                         {
00409                                 
00410 
00411                                 double absdt = fabs(thermal.dTemper);
00412                                 thermal.dTemper = (sign(MIN2(absdt,0.002*phycon.te),
00413                                   thermal.dTemper));
00414                                 kase = 3;
00415                         }
00416 #                       endif
00417                         else
00418                         {
00419                                 
00420 
00421                                 double absdt = fabs(thermal.dTemper);
00422                                 thermal.dTemper = (sign(MIN2(absdt,0.02*phycon.te),
00423                                   thermal.dTemper));
00424                                 kase = 4;
00425                         }
00426 
00427                         
00428 
00429                         
00430 
00431                         if( 0 && h2.lgH2ON && fabs(thermal.dTemper)/ phycon.te > 0.01 )
00432                         {
00433                                 double absdt = fabs(thermal.dTemper);
00434                                 thermal.dTemper = (sign(MIN2(absdt,0.01*phycon.te),
00435                                   thermal.dTemper));
00436                                 kase = 5;
00437                         }
00438 
00439                         
00440 
00441 
00442 
00443 
00444                         
00445                         if( dense.xIonDense[ipHYDROGEN][1]/dense.gas_phase[ipHYDROGEN] < 0.9 &&
00446                                 
00447                                 dense.xIonDense[ipHYDROGEN][1]/dense.gas_phase[ipHYDROGEN] > 0.01 )
00448                         {
00449                                 if( iso.RecomCollisFrac[ipH_LIKE][ipHYDROGEN] > 0.8 )
00450                                         
00451                                         
00452                                         
00453 
00454                                 {
00455                                         double absdt = fabs(thermal.dTemper);
00456                                         
00457                                         
00458 
00459 
00460 
00461 
00462 
00463 
00464                                         thermal.dTemper = (sign(MIN2(absdt,0.001*
00465                                                 phycon.te),thermal.dTemper));
00466                                         kase = 6;
00467                                 }
00468                         }
00469 
00470                         
00471                         thermal.dTemper *= Damper;
00472 
00473                         
00474 
00475                         if( fabs(thermal.dTemper)/phycon.te <10.*DBL_EPSILON )
00476                         {
00477                                 kase = 7;
00478                                 thermal.dTemper = (sign( 10.*DBL_EPSILON*phycon.te , thermal.dTemper));
00479                         }
00480 
00481                         
00482                         dtl = thermal.dTemper;
00483 
00484                         
00485                         if( !thermal.lgTLaw )
00486                         {
00487                                 
00488                                 TempChange(phycon.te - thermal.dTemper , false);
00489                         }
00490 
00491                         if( trace.nTrConvg>=2 )
00492                         {
00493                                 fprintf( ioQQQ, 
00494                                         "  ConvTempEdenIoniz4 a %4li T:%.4e dt:%10.2e%7.2f%% C:%10.2e H:%10.2e"
00495                                         " CoolMHeat/h:%7.2f%% dC-H/dT:%.2e kase:%i%c damp%.2f\n", 
00496                                   nTemperature_loop, 
00497                                   phycon.te, 
00498                                   thermal.dTemper, 
00499                                   thermal.dTemper/(phycon.te+thermal.dTemper)*100,
00500                                   thermal.ctot, 
00501                                   thermal.htot, 
00502                                   CoolMHeat/MIN2(thermal.ctot , thermal.htot )*100. ,
00503                                   dCoolmHeatdT,
00504                                   kase,
00505                                   
00506                                   chDEType,
00507                                   Damper);
00508                                 
00509 
00510                         }
00511 
00512                         if( trace.lgTrace )
00513                         {
00514                                 fprintf( ioQQQ, 
00515                                         " ConvTempEdenIoniz TE:%.5e dT%.3e HTOT:%.5e CTOT:%.5e dCoolmHeatdT:%c%.4e C-H%.4e HDEN%.2e kase %i\n", 
00516                                   phycon.te, 
00517                                   thermal.dTemper, 
00518                                   thermal.htot, 
00519                                   thermal.ctot, 
00520                                   chDEType, 
00521                                   dCoolmHeatdT, 
00522                                   CoolMHeat, 
00523                                   dense.gas_phase[ipHYDROGEN],
00524                                   kase );
00525                         }
00526 
00527                         
00528                         ++nTemperature_loop;
00529                 }
00530 
00531                 
00532 
00533 
00534                 if( fabs(CoolMHeat/thermal.htot ) > conv.HeatCoolRelErrorAllowed )
00535                 {
00536                         conv.lgConvTemp = false;
00537                         if( trace.nTrConvg>=2 )
00538                         {
00539                                 fprintf( ioQQQ, "  ConvTempEdenIoniz7 fell through loop, heating cooling not converged, setting conv.lgConvTemp = false\n");
00540                         }
00541                 }
00542                 else
00543                 {
00544                         
00545 
00546                         conv.lgConvTemp = true;
00547                         if( trace.nTrConvg>=2 )
00548                         {
00549                                 fprintf( ioQQQ, "  ConvTempEdenIoniz8 fell through loop, heating cooling is converged (ion not?), setting conv.lgConvTemp = true\n");
00550                         }
00551                 }
00552         }
00553         else
00554         {
00555                 fprintf( ioQQQ, "ConvTempEdenIoniz finds insane solver%s \n" , conv.chSolverTemp );
00556                 ShowMe();
00557                 cdEXIT(EXIT_FAILURE);
00558         }
00559         return 0;
00560 }
00561 
00562 
00563 STATIC void MakeDeriv(
00564   const char *job, 
00565   double *DerivNumer)
00566 {
00567         static long int nstore;
00568         static double OldTe , OldCool , OldHeat;
00569 
00570         DEBUG_ENTRY( "MakeDeriv()" );
00571 
00572         if( strcmp(job,"zero") == 0 )
00573         {
00574                 nstore = 0;
00575                 OldTe = 0.;
00576                 OldCool = 0.;
00577                 OldHeat = 0.;
00578         }
00579 
00580         else if( strcmp(job,"incr") == 0 )
00581         {
00582 
00583                 if( nstore > 0 && !thermal.lgTemperatureConstant && fabs(phycon.te - OldTe)>SMALLFLOAT )
00584                 {
00585                         
00586                         double dCdT = (thermal.ctot - OldCool)/(phycon.te - OldTe);
00587                         double dHdT = (thermal.htot - OldHeat)/(phycon.te - OldTe);
00588                         *DerivNumer = dCdT - dHdT;
00589 #                       if 0
00590                         fprintf(ioQQQ,"derivderiv\t%li\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\n",
00591                           nzone, dCdT , thermal.dCooldT , 
00592                           thermal.ctot , OldCool,phycon.te , OldTe
00593                           );
00594 #                       endif
00595                 }
00596 
00597                 else
00598                 {
00599                         
00600                         *DerivNumer = 0.;
00601                 }
00602 
00603                 OldTe = phycon.te;
00604                 OldCool = thermal.ctot;
00605                 OldHeat = thermal.htot;
00606                 ++ nstore;
00607         }
00608 
00609         else
00610         {
00611                 fprintf( ioQQQ, " MakeDeriv called with insane job=%4.4s\n", 
00612                   job );
00613                 cdEXIT(EXIT_FAILURE);
00614         }
00615         return;
00616 }
00617 
00618 
00619 STATIC void PutHetCol(double te, 
00620   double htot, 
00621   double ctot)
00622 {
00623 
00624         DEBUG_ENTRY( "PutHetCol()" );
00625 
00626         if( nzone == 0 )
00627         {
00628                 
00629                 thermal.ipGrid = 0;
00630         }
00631         else
00632         {
00633                 if( thermal.ipGrid >= NGRID )
00634                         thermal.ipGrid = 0;
00635 
00636                 ASSERT( thermal.ipGrid >= 0 );
00637                 ASSERT( thermal.ipGrid < NGRID );
00638                 ASSERT( nzone>=0 );
00639 
00640                 thermal.TeGrid[thermal.ipGrid] = (realnum)te;
00641                 thermal.HtGrid[thermal.ipGrid] = (realnum)htot;
00642                 thermal.ClGrid[thermal.ipGrid] = (realnum)ctot;
00643                 thermal.nZonGrid[thermal.ipGrid] = nzone;
00644 
00645                 ++thermal.ipGrid;
00646         }
00647         return;
00648 }
00649 
00650 
00651 STATIC double CoolHeatError( double temp )
00652 {
00653         DEBUG_ENTRY( "CoolHeatError()" );
00654 
00655         TempChange(temp , false);
00656 
00657         
00658 
00659         
00660         if( ConvEdenIoniz() )
00661                 lgAbort = true;
00662 
00663         
00664         
00665         
00666         PresTotCurrent();
00667 
00668         
00669         PutHetCol(phycon.te,thermal.htot,thermal.ctot);
00670         return thermal.ctot - thermal.htot;
00671 }
00672 
00673 
00674 #define ITERMAX 100
00675 
00676 STATIC double TeBrent(
00677           double x1, 
00678           double x2)
00679 {
00680         long int iter;
00681         double c, 
00682           d, 
00683           e, 
00684           fx1, 
00685           fx2, 
00686           fc, 
00687           p, 
00688           q, 
00689           r, 
00690           s, 
00691           xm;
00692 
00693         DEBUG_ENTRY( "TeBrent()" );
00694 
00695         
00696 
00697         
00698 
00699         fx1 = CoolHeatError(x1);
00700         fx2 = CoolHeatError(x2);
00701 
00702         if( fx1*fx2 > 0. )
00703         {
00704                 
00705                 fprintf( ioQQQ, " TeBrent called without proper bracket - this is impossible\n" );
00706                 fprintf( ioQQQ, " Sorry.\n" );
00707                 cdEXIT(EXIT_FAILURE);
00708         }
00709 
00710         
00711         c = x2;
00712         fc = fx2;
00713         iter = 0;
00714         
00715         e = DBL_MAX;
00716         d = DBL_MAX;
00717         while(  iter < ITERMAX )
00718         {
00719                 if( (fx2 > 0. && fc > 0.) || (fx2 < 0. && fc < 0.) )
00720                 {
00721                         c = x1;
00722                         fc = fx1;
00723                         d = x2 - x1;
00724                         e = d;
00725                 }
00726                 if( fabs(fc) < fabs(fx2) )
00727                 {
00728                         x1 = x2;
00729                         x2 = c;
00730                         c = x1;
00731                         fx1 = fx2;
00732                         fx2 = fc;
00733                         fc = fx1;
00734                 }
00735 
00736                 xm = .5*(c - x2);
00737 
00738                 
00739                 if( fabs(xm) <= thermal.htot*conv.HeatCoolRelErrorAllowed || fx2 == 0. )
00740                         break;
00741 
00742                 if( fabs(e) >= thermal.htot*conv.HeatCoolRelErrorAllowed && fabs(fx1) > fabs(fx2) )
00743                 {
00744                         double aa , bb;
00745                         s = fx2/fx1;
00746                         if( fp_equal( x1, c ) )
00747                         {
00748                                 p = 2.*xm*s;
00749                                 q = 1. - s;
00750                         }
00751                         else
00752                         {
00753                                 q = fx1/fc;
00754                                 r = fx2/fc;
00755                                 p = s*(2.*xm*q*(q - r) - (x2 - x1)*(r - 1.));
00756                                 q = (q - 1.)*(r - 1.)*(s - 1.);
00757                         }
00758                         if( p > 0. )
00759                                 q = -q;
00760 
00761                         p = fabs(p);
00762                         aa = fabs(thermal.htot*conv.HeatCoolRelErrorAllowed*q);
00763                         bb = fabs(e*q);
00764                         if( 2.*p < MIN2(3.*xm*q-aa,bb) )
00765                         {
00766                                 e = d;
00767                                 d = p/q;
00768                         }
00769                         else
00770                         {
00771                                 d = xm;
00772                                 e = d;
00773                         }
00774                 }
00775                 else
00776                 {
00777                         d = xm;
00778                         e = d;
00779                 }
00780                 x1 = x2;
00781                 fx1 = fx2;
00782                 if( fabs(d) > thermal.htot*conv.HeatCoolRelErrorAllowed )
00783                 {
00784                         x2 += d;
00785                 }
00786                 else
00787                 {
00788                         x2 += sign(thermal.htot*conv.HeatCoolRelErrorAllowed,xm);
00789                 }
00790                 fx2 = CoolHeatError(x2);
00791 
00792                 ++iter;
00793         }
00794 
00795         
00796 
00797         if( iter == ITERMAX )
00798         {
00799                 
00800                 fprintf( ioQQQ, " TeBrent did not converge in %i iterations\n",ITERMAX );
00801                 fprintf( ioQQQ, " Sorry.\n" );
00802                 cdEXIT(EXIT_FAILURE);
00803         }
00804         return( x2 );
00805 
00806 }
00807 
00808 
00809 bool lgConvTemp(void)
00810 {
00811         bool lgRet;
00812         DEBUG_ENTRY( "lgConvTemp()" );
00813 
00814         
00815         if( fabs(thermal.htot - thermal.ctot)/thermal.htot <= conv.HeatCoolRelErrorAllowed ||
00816                 thermal.lgTemperatureConstant || phycon.te <= phycon.TEMP_LIMIT_LOW )
00817         {
00818                 
00819 
00820 
00821                 lgRet = true;
00822                 conv.lgConvTemp = true;
00823         }
00824         else
00825         {
00826                 
00827                 lgRet = false;
00828                 conv.lgConvTemp = false;
00829         }
00830         return lgRet;
00831 }