18         return gv.
bin[nd]->AvVol*
gv.
bin[nd]->dustp[0]/ATOMIC_MASS_UNIT/
gv.
bin[nd]->atomWeight;
 
   95 static const double RELAX = 15.;
 
  127 static const double tlim[5]={0.,50.,150.,500.,DBL_MAX};
 
  128 static const double ppower[4]={2.00,1.30,0.68,0.00};
 
  140                                   const vector<double>&,vector<double>&,
 
  141                                   vector<double>&,vector<double>&,
 
  145 STATIC double TryDoubleStep(vector<double>&,vector<double>&,vector<double>&,vector<double>&,
 
  146                             vector<double>&,
const vector<double>&,
const vector<double>&,
double,
 
  147                             double*,
double,
long,
size_t,
bool*);
 
  151 STATIC void ScanProbDistr(
const vector<double>&,
const vector<double>&,
long,
double,
long,
double,
 
  152                           long*,
long*,
long*,
long*,
QH_Code*);
 
  155                               vector<double>&,vector<double>&,vector<double>&,vector<double>&,
QH_Code*);
 
  158                                    vector<double>&,
double*,
 
  185                 return (x/2.f + 1.f)*x;
 
  187                 return ((x/6.f + 0.5f)*x +1.f)*x;
 
  189                 return expf(x) - 1.f;
 
  197         const realnum x = log(0.999f*FLT_MAX);
 
  199         double hokT = TE1RYD/Tgrain;
 
  201         for( 
long i=0; i < nflux; i++ )
 
  212         for( 
long i=0; i < nflux; i++ )
 
  213                 flux[i] += fracpop/val[i];
 
  215         for( 
long i=0; i < nflux; i++ )
 
  226         const double factor = 2.*PI4*
pow2(FR1RYD/SPEEDLIGHT)*FR1RYD;
 
  237         vector<double> qtemp(
NQGRID);
 
  238         vector<double> qprob(
NQGRID);
 
  241         for( 
size_t nd=0; nd < 
gv.
bin.size(); nd++ )
 
  244                 bool lgLocalQHeat = 
gv.
bin[nd]->lgQHeat;
 
  252                 if( lgLocalQHeat && 
gv.
bin[nd]->dstAbund >= threshold )
 
  254                         qheat(qtemp,qprob,&qnbin,nd);
 
  256                         if( 
gv.
bin[nd]->lgUseQHeat )
 
  264                         gv.
bin[nd]->lgUseQHeat = 
false;
 
  270                 if( lgLocalQHeat && 
gv.
bin[nd]->lgUseQHeat )
 
  272                         for( 
long j=0; j < qnbin; j++ )
 
  275                                 loopmax = 
max(loopmax, maxi);
 
  298                 double fac = factor*
gv.
bin[nd]->cnv_H_pCM3;
 
  300                 for( 
long i=0; i < loopmax; i++ )
 
  302                 for( 
long i=0; i < loopmax; i++ )
 
  307                         gt_ptr[i] += flux[i];
 
  366         bool lgNoTdustFailures = 
true;
 
  367         for( 
size_t nd=0; nd < 
gv.
bin.size(); nd++ )
 
  369                 if( !
gv.
bin[nd]->lgTdustConverged )
 
  371                         lgNoTdustFailures = 
false;
 
  382         double Comparison1 = 0.;
 
  383         for( 
size_t nd=0; nd < 
gv.
bin.size(); nd++ )
 
  385                 if( 
gv.
bin[nd]->tedust < 
gv.
bin[nd]->Tsublimat )
 
  398         for( 
size_t nd=0; nd < 
gv.
bin.size(); nd++ )
 
  400                 double ave = 0.5*(
gv.
bin[nd]->RateDn+
gv.
bin[nd]->RateUp);
 
  411                 for( 
size_t nd=0; nd < 
gv.
bin.size(); nd++ )
 
  413                         Comparison1 += 
gv.
bin[nd]->BolFlux;
 
  426                         fabs(Comparison1-Comparison2)/Comparison2 < 
CONSERV_TOL );
 
  448             vector<double>& qprob, 
 
  498         vector<double> dPdlnT(
NQGRID);
 
  502         check += 
gv.
bin[nd]->GrainHeatColl-
gv.
bin[nd]->GrainCoolTherm;
 
  511         for( i=
gv.
bin[nd]->qnflux-1; i >= 0; i-- )
 
  519                 y = -phiTilde[i]*
gv.
bin[nd]->cnv_H_pGR;
 
  528                 integral += phiTilde[i]*
gv.
bin[nd]->cnv_H_pCM3*
rfield.
anu(i)*EN1RYD;
 
  536                 lgNegRate = lgNegRate || ( phiTilde[i] < 0. );
 
  547                 sprintf(fnam,
"Lambda_%2.2ld.asc",nd);
 
  549                 for( i=0; i < 
NDEMS; ++i )
 
  553                                 exp(
gv.
bin[nd]->dstems[i])*
gv.
bin[nd]->cnv_H_pGR/EN1RYD);
 
  556                 sprintf(fnam,
"Phi_%2.2ld.asc",nd);
 
  558                 for( i=0; i < 
gv.
bin[nd]->qnflux; ++i )
 
  565         Tmax = 
gv.
bin[nd]->tedust;
 
  567         Umax = 
ufunct(Tmax,nd,&lgBoundErr);
 
  573         deriv = y*c0/(
uderiv(Tmax,nd)*Tmax);
 
  575         fwhm = sqrt(8.*LN_TWO*c1/deriv);
 
  577         NumEvents = 
pow2(fwhm)*c0/(4.*LN_TWO*c2);
 
  578         FwhmRatio = fwhm/Umax;
 
  597         ErrorCode = ErrorStart;
 
  602                 for( 
int nz=0; nz < 
gv.
bin[nd]->nChrg; nz++ )
 
  603                         Rate2 += 
gv.
bin[nd]->chrg[nz]->FracPop*
gv.
bin[nd]->chrg[nz]->HeatingRate2;
 
  605                 fprintf( 
ioQQQ, 
"   grain heating: %.4e, integral %.4e, total rate %.4e lgNegRate %c\n",
 
  606                          gv.
bin[nd]->GrainHeat,integral,Phi[0],
TorF(lgNegRate));
 
  607                 fprintf( 
ioQQQ, 
"   av grain temp %.4e av grain enthalpy (Ryd) %.4e\n",
 
  608                          gv.
bin[nd]->tedust,Umax);
 
  609                 fprintf( 
ioQQQ, 
"   fwhm^2/(4ln2*c2/c0): %.4e fwhm (Ryd) %.4e fwhm/Umax %.4e\n",
 
  610                          NumEvents,fwhm,FwhmRatio );
 
  611                 fprintf( 
ioQQQ, 
"   HeatingRate1 %.4e HeatingRate2 %.4e lgQHTooWide %c\n",
 
  612                          gv.
bin[nd]->HeatingRate1*
gv.
bin[nd]->cnv_H_pCM3, Rate2*
gv.
bin[nd]->cnv_H_pCM3,
 
  618         maxBracket = 
gv.
bin[nd]->tedust;
 
  637         for( i=0; i < 
LOOP_MAX && !lgOK && !
gv.
bin[nd]->lgQHTooWide; i++ )
 
  643                         double Ulo = Umax*exp(-sqrt(-log(
PROB_CUTOFF_LO)/(4.*LN_TWO))*fwhm/Umax);
 
  644                         double MinEnth = exp(
gv.
bin[nd]->DustEnth[0]);
 
  645                         Ulo = 
MAX2(Ulo,MinEnth);
 
  649                         if( 
gv.
bin[nd]->qtmin <= minBracket || 
gv.
bin[nd]->qtmin >= maxBracket )
 
  650                                 gv.
bin[nd]->qtmin = sqrt(minBracket*maxBracket);
 
  654                 ASSERT( minBracket <= 
gv.
bin[nd]->qtmin && 
gv.
bin[nd]->qtmin <= maxBracket );
 
  656                 ErrorCode = ErrorStart;
 
  661                         GetProbDistr_LowLimit(nd,rel_tol,Umax,fwhm,Phi,PhiDrv,qtemp,qprob,dPdlnT,qnbin,
 
  662                                               &new_tmin,&nWideFail,&ErrorCode);
 
  678                                 GetProbDistr_HighLimit(nd,
STRICT,Umax,fwhm,qtemp,qprob,dPdlnT,&tol,qnbin,&dummy,
 
  691                                 if( new_tmin < minBracket || new_tmin > maxBracket )
 
  696                                         if( new_tmin <= minBracket )
 
  697                                                 new_tmin = sqrt(
gv.
bin[nd]->qtmin*minBracket);
 
  698                                         if( new_tmin >= maxBracket )
 
  699                                                 new_tmin = sqrt(
gv.
bin[nd]->qtmin*maxBracket);
 
  713                                 double help1 = 
gv.
bin[nd]->qtmin*sqrt(DefFac);
 
  714                                 double help2 = sqrt(
gv.
bin[nd]->qtmin*maxBracket);
 
  715                                 minBracket = 
gv.
bin[nd]->qtmin;
 
  716                                 new_tmin = 
MIN2(help1,help2);
 
  722                                 double help = sqrt(
gv.
bin[nd]->qtmin*minBracket);
 
  723                                 maxBracket = 
gv.
bin[nd]->qtmin;
 
  728                                 new_tmin = sqrt(minBracket*maxBracket);
 
  733                         GetProbDistr_HighLimit(nd,
STRICT,Umax,fwhm,qtemp,qprob,dPdlnT,&tol,qnbin,&new_tmin,
 
  737                 gv.
bin[nd]->qtmin = new_tmin;
 
  749                         fprintf( 
ioQQQ, 
"   GetProbDistr returns code %d\n", ErrorCode );
 
  752                                 fprintf( 
ioQQQ, 
" >>>>qheat trying another iteration, qtmin bracket %.4e %.4e",
 
  753                                          minBracket,maxBracket );
 
  760                 gv.
bin[nd]->lgQHTooWide = 
true;
 
  764         if( 
gv.
bin[nd]->lgQHTooWide && !lgDelta )
 
  782         if( !lgOK && !lgDelta )
 
  784                 double Umax2 = Umax*sqrt(tol);
 
  785                 double fwhm2 = fwhm*sqrt(tol);
 
  792                         GetProbDistr_HighLimit(nd,
RELAX,Umax2,fwhm2,qtemp,qprob,dPdlnT,&tol,qnbin,&dummy,
 
  798                                 gv.
bin[nd]->qtmin = dummy;
 
  799                                 ErrorCode = ErrorCode2;
 
  813         gv.
bin[nd]->lgUseQHeat = ( lgOK && !lgDelta );
 
  814         gv.
bin[nd]->lgEverQHeat = ( 
gv.
bin[nd]->lgEverQHeat || 
gv.
bin[nd]->lgUseQHeat );
 
  819                         fprintf( 
ioQQQ, 
" >>>>qheat converged with code: %d\n", ErrorCode );
 
  824                 ++
gv.
bin[nd]->QHeatFailures;
 
  825                 fprintf( 
ioQQQ, 
" PROBLEM  qheat did not converge grain %s in zone %ld, error code = %d\n",
 
  836                 if( 
gv.
bin[nd]->lgUseQHeat ) 
 
  841                         for( i=0; i < *qnbin; i++ ) 
 
  857                         vector<double>& phiTilde,  
 
  865         enum {DEBUG_LOC=
false};
 
  878         for( i=0; i < 
gv.
bin[nd]->qnflux; i++ )
 
  892         double NegHeatingRate = 0.;
 
  894         for( nz=0; nz < 
gv.
bin[nd]->nChrg; nz++ )
 
  932                                 double ehat = gptr->
ehat[i];
 
  933                                 double cool1, 
sign = 1.;
 
  936                                 if( gptr->
DustZ <= -1 )
 
  965                 *check += gptr->
FracPop*check1*EN1RYD*
gv.
bin[nd]->cnv_H_pCM3;
 
  967                 sum += gptr->
FracPop*check1*EN1RYD*
gv.
bin[nd]->cnv_H_pCM3;
 
  971                         double integral = 0.;
 
  972                         for( i=0; i < 
gv.
bin[nd]->qnflux; i++ )
 
  974                                 integral += phiTilde[i]*
gv.
bin[nd]->cnv_H_pCM3*
rfield.
anu(i)*EN1RYD;
 
  976                         dprintf( 
ioQQQ, 
" integral test 1: integral %.6e %.6e\n", integral, sum );
 
  994                         double Sum,ESum,DSum,E_av2,Corr;
 
  995                         double fac = BOLTZMANN/EN1RYD*
phycon.
te;
 
 1013                         double ylo = -exp(-E0/fac);
 
 1018                         double yhi = ((E0-Ehi)/fac-1.)*exp(-Ehi/fac);
 
 1026                         vector<double> RateArr(
gv.
bin[nd]->qnflux);
 
 1027                         Sum = ESum = DSum = 0.;
 
 1030                         for( i=0; i < 
gv.
bin[nd]->qnflux2; i++ ) 
 
 1036                                         yhi = ((E0-Ehi)/fac-1.)*exp(-Ehi/fac);
 
 1038                                         RateArr[i] = rate*
MAX2(yhi-ylo,0.);
 
 1051                         E_av2 = ESum/Sum*EN1RYD;
 
 1052                         ASSERT( fabs(E_av-E_av2) <= DSum/Sum*EN1RYD );
 
 1055                         for( i=0; i < 
gv.
bin[nd]->qnflux2; i++ ) 
 
 1057                                 phiTilde[i] += RateArr[i]*Corr;
 
 1064                                 double integral = 0.;
 
 1065                                 for( i=0; i < 
gv.
bin[nd]->qnflux; i++ )
 
 1067                                         integral += phiTilde[i]*
gv.
bin[nd]->cnv_H_pCM3*
rfield.
anu(i)*EN1RYD;
 
 1069                                 dprintf( 
ioQQQ, 
" integral test 2: integral %.6e %.6e\n", integral, sum );
 
 1100                 const double LIM2 = cbrt(3.e-6);
 
 1110                 double rate = 
gv.
bin[nd]->HeatingRate1/E_av;
 
 1117                 double yhi = -(Ehi/fac+1.)*exp(-Ehi/fac);
 
 1121                 for( i=0; i < 
gv.
bin[nd]->qnflux2; i++ ) 
 
 1130                                 yhi = -(x+1.)*exp(-x);
 
 1132                                 yhi = -(((1./3.)*x - 0.5)*x*x + 1.);
 
 1134                                 yhi = -(1. - 0.5*x*x);
 
 1137                         phiTilde[i] += rate*
MAX2(yhi-ylo,0.);
 
 1141                 sum += 
gv.
bin[nd]->HeatingRate1*
gv.
bin[nd]->cnv_H_pCM3;
 
 1145                         double integral = 0.;
 
 1146                         for( i=0; i < 
gv.
bin[nd]->qnflux; i++ )
 
 1148                                 integral += phiTilde[i]*
gv.
bin[nd]->cnv_H_pCM3*
rfield.
anu(i)*EN1RYD;
 
 1150                         dprintf( 
ioQQQ, 
" integral test 3: integral %.6e %.6e\n", integral, sum );
 
 1155                 NegHeatingRate += 
gv.
bin[nd]->HeatingRate1*
gv.
bin[nd]->cnv_H_pCM3;
 
 1161         if( NegHeatingRate < 0. )
 
 1163                 double scale_fac = (sum+NegHeatingRate)/sum;
 
 1164                 for( i=0; i < 
gv.
bin[nd]->qnflux; i++ )
 
 1165                         phiTilde[i] *= scale_fac;
 
 1169                         sum += NegHeatingRate;
 
 1171                         double integral = 0.;
 
 1172                         for( i=0; i < 
gv.
bin[nd]->qnflux; i++ )
 
 1174                                 integral += phiTilde[i]*
gv.
bin[nd]->cnv_H_pCM3*
rfield.
anu(i)*EN1RYD;
 
 1176                         dprintf( 
ioQQQ, 
" integral test 4: integral %.6e %.6e\n", integral, sum );
 
 1201                                    const vector<double>& Phi,    
 
 1202                                    const vector<double>& PhiDrv, 
 
 1203                                    vector<double>& qtemp,       
 
 1204                                    vector<double>& qprob,       
 
 1205                                    vector<double>& dPdlnT,      
 
 1233         vector<double> delu(
NQGRID);
 
 1234         vector<double> Lambda(
NQGRID);
 
 1235         vector<double> p(
NQGRID);
 
 1236         vector<double> u1(
NQGRID);
 
 1246                 fprintf( 
ioQQQ, 
"   GetProbDistr_LowLimit called for grain %s\n", 
gv.
bin[nd]->chDstLab );
 
 1250         qtmin1 = 
gv.
bin[nd]->qtmin;
 
 1253         u1[0] = 
ufunct(qtemp[0],nd,&lgBoundErr);
 
 1260         Lambda[0] = exp(y)*
gv.
bin[nd]->cnv_H_pGR/EN1RYD;
 
 1264         delu[0] = 2.*Lambda[0]/Phi[0];
 
 1266         dPdlnT[0] = p[0]*qtemp[0]*
uderiv(qtemp[0],nd);
 
 1267         RadCooling = 0.5*p[0]*Lambda[0]*delu[0];
 
 1268         NextStep = 0.01*Lambda[0]/Phi[0];
 
 1270         if( NextStep < 5.*DBL_EPSILON*u1[0] )
 
 1281         lgAllNegSlope = 
true;
 
 1284         double p_max = p[0];
 
 1291         dlnpdlnU = u1[0]*Phi[0]/Lambda[0] - dlnLdlnT*u1[0]/(qtemp[0]*
uderiv(qtemp[0],nd));
 
 1295                 (void)
TryDoubleStep(u1,delu,p,qtemp,Lambda,Phi,PhiDrv,NextStep,&dCool,p_max,k,nd,&lgBoundErr);
 
 1296                 dPdlnT[2] = p[2]*qtemp[2]*
uderiv(qtemp[2],nd);
 
 1298                 if( dPdlnT[2] < dPdlnT[0] )
 
 1310                 double rerr = 
TryDoubleStep(u1,delu,p,qtemp,Lambda,Phi,PhiDrv,NextStep,&dCool,p_max,k,nd,&lgBoundErr);
 
 1327                         NextStep *= sqrt(0.9*rel_tol*QHEAT_TOL/rerr);
 
 1330                         if( NextStep < 5.*DBL_EPSILON*u1[k] )
 
 1343                         p_max = 
max(p_max,p[k-1]);
 
 1344                         p_max = 
max(p_max,p[k]);
 
 1347                         NextStep *= 
MIN2(cbrt(0.9*rel_tol*QHEAT_TOL/
MAX2(rerr,1.e-50)),4.);
 
 1348                         NextStep = 
MIN2(NextStep,Lambda[k]/Phi[0]);
 
 1351                 dPdlnT[k-1] = p[k-1]*qtemp[k-1]*
uderiv(qtemp[k-1],nd);
 
 1352                 dPdlnT[k] = p[k]*qtemp[k]*
uderiv(qtemp[k],nd);
 
 1354                 lgAllNegSlope = lgAllNegSlope && ( dPdlnT[k] < dPdlnT[k-2] );
 
 1356                 if( dPdlnT[k-1] > maxVal )
 
 1358                         maxVal = dPdlnT[k-1];
 
 1361                 if( dPdlnT[k] > maxVal )
 
 1367                 RadCooling += dCool;
 
 1377                 if( p[k] > sqrt(DBL_MAX/100.) ) 
 
 1385                 ASSERT( p[k] > 0. && dPdlnT[k] > 0. && RadCooling > 0. );
 
 1388                 if( k > 0 && k%
NQTEST == 0 )
 
 1390                         double wid, avStep, factor;
 
 1403                         avStep = log(u1[k]/u1[0])/(double)k;
 
 1407                         factor = 1.1 + 3.9*(1.0 - sqrt((
double)k/(
double)
NQGRID));
 
 1408                         if( wid/avStep > factor*(
double)
NQGRID )
 
 1424                 fac = RadCooling*
gv.
bin[nd]->cnv_GR_pCM3*EN1RYD/
gv.
bin[nd]->GrainHeat;
 
 1445                 ScanProbDistr(u1,dPdlnT,nbin,maxVal,nmax,qtmin1,&nstart,&nstart2,&nend,nWideFail,ErrorCode);
 
 1452         for( j=0; j < nbin; j++ )
 
 1461         for( j=nstart; j < nbin; j++ ) 
 
 1465                         *new_tmin = qtemp[j];
 
 1479                                 if( dPdlnT[nstart2] < 0.999*dPdlnT[nstart2+
NSTARTUP] ) 
 
 1484                                         double T1 = qtemp[nstart2];
 
 1485                                         double T2 = qtemp[nstart2+
NSTARTUP];
 
 1486                                         double delta_y = log(dPdlnT[nstart2+
NSTARTUP]/dPdlnT[nstart2]);
 
 1487                                         double c2 = delta_y/(1./
pow3(T1)-1./
pow3(T2));
 
 1489                                         *new_tmin = cbrt(c2/help);
 
 1495                                         double delta_x = log(qtemp[nstart2+
NSTARTUP]/qtemp[nstart2]);
 
 1496                                         double delta_y = log(dPdlnT[nstart2+
NSTARTUP]/dPdlnT[nstart2]);
 
 1498                                         *new_tmin = qtemp[nstart2]*exp(delta_x);
 
 1499                                         if( *new_tmin < qtmin1 )
 
 1501                                                 *new_tmin = sqrt( *new_tmin*qtmin1 );
 
 1548         nbin = 
RebinQHeatResults(nd,nstart,nend,p,qtemp,qprob,dPdlnT,u1,delu,Lambda,ErrorCode);
 
 1559         for( j=0; j < nbin; j++ )
 
 1575                          "    zone %ld %s nbin %ld nok %ld nbad %ld total prob %.4e rel_tol %.3e new_tmin %.4e\n",
 
 1576                          nzone,
gv.
bin[nd]->chDstLab,nbin,nok,nbad,sum,rel_tol,*new_tmin );
 
 1587                             vector<double>& delu,
 
 1589                             vector<double>& qtemp,
 
 1590                             vector<double>& Lambda,
 
 1591                             const vector<double>& Phi,
 
 1592                             const vector<double>& PhiDrv,
 
 1634         for( i=1; i <= 2; i++ )
 
 1639                 long ipHi = 
gv.
bin[nd]->qnflux;
 
 1642                 u1[k] = u1[k-1] + delu[k];
 
 1645                 *lgBoundFail = *lgBoundFail || lgErr;
 
 1646                 Lambda[k] = exp(y)*
gv.
bin[nd]->cnv_H_pGR/EN1RYD;
 
 1649                 trap1 = trap2 = trap12 = 0.;
 
 1652                 for( j=jlo; j < k; j++ )
 
 1654                         umin = u1[k] - u1[j];
 
 1664                         else if( umin > ulo )
 
 1685                                 while( ipHi-ipLo > 1 )
 
 1687                                         long ipMd = (ipLo+ipHi)/2;
 
 1694                                 bval_jk = Phi[ipLo] + (umin - 
rfield.
anumin(ipLo))*PhiDrv[ipLo];
 
 1712                         trap2 = p[j]*bval_jk;
 
 1714                         sum += (trap1 + trap2)*delu[j];
 
 1723                 p[k] = (sum + trap1*delu[k])/(2.*Lambda[k] - Phi[0]*delu[k]);
 
 1731         p2k = (sum2 + trap12*step)/(2.*Lambda[k] - Phi[0]*step);
 
 1737         RelErrPk = fabs(p2k-p[k])/p[k];
 
 1742         vlog(z, u1[k-2], u1[k-1], u1[k], p[k-2]*Lambda[k-2], p[k-1]*Lambda[k-1], p[k]*Lambda[k], p2k*Lambda[k], 1.);
 
 1743         *cooling = 
log_integral(u1[k-2],p[k-2]*Lambda[k-2],u1[k-1],p[k-1]*Lambda[k-1],z[0],z[3],z[1],z[4]);
 
 1744         *cooling += 
log_integral(u1[k-1],p[k-1]*Lambda[k-1],u1[k],p[k]*Lambda[k],z[1],z[4],z[2],z[5]);
 
 1747         cooling2 = 
log_integral(u1[k-2],p[k-2]*Lambda[k-2],u1[k],p2k*Lambda[k],z[0],z[3],z[2],z[6]);
 
 1750         RelErrCool = ( index > 0 ) ? fabs(cooling2-(*cooling))/(*cooling) : 0.;
 
 1754         return MAX2(RelErrPk,RelErrCool)/3.;
 
 1770         double xx = log_xx2 - log_xx1;
 
 1771         double eps = xx + log_yy2 - log_yy1;
 
 1772         if( fabs(eps) < 1.e-4 )
 
 1774                 return xx1*yy1*xx*(((eps/24. + 1./6.)*eps + 0.5)*eps + 1.);
 
 1778                 return (xx2*yy2 - xx1*yy1)*xx/eps;
 
 1785                           const vector<double>& dPdlnT,  
 
 1801         const double MIN_FAC_LO = 1.e4;
 
 1802         const double MIN_FAC_HI = 1.e4;
 
 1807         ASSERT( nbin > 0 && nmax >= 0 && nmax < nbin && maxVal > 0. );
 
 1817         for( i=nmax; i >= 0; --i )
 
 1819                 if( dPdlnT[i] < minVal )
 
 1827         for( i=nmax; i > *nstart; --i )
 
 1829                 double deriv = log(dPdlnT[i]/dPdlnT[i-1])/log(u1[i]/u1[i-1]);
 
 1830                 if( deriv > deriv_max )
 
 1839         lgSetLo = ( nmax >= *nend || maxVal/dPdlnT[*nend] < MIN_FAC_HI );
 
 1845                 lgSetHi = ( nmax <= *nstart || maxVal/dPdlnT[*nstart] < MIN_FAC_LO );
 
 1847                 lgSetHi = ( nmax <= *nstart2 || maxVal/dPdlnT[*nstart2] < MIN_FAC_LO );
 
 1849         if( lgSetLo && lgSetHi )
 
 1873                 fprintf( 
ioQQQ, 
"    ScanProbDistr nstart %ld nstart2 %ld nend %ld nmax %ld maxVal %.3e",
 
 1874                          *nstart,*nstart2,*nend,nmax,maxVal );
 
 1875                 fprintf( 
ioQQQ, 
" dPdlnT[nstart] %.3e dPdlnT[nstart2] %.3e dPdlnT[nend] %.3e code %d\n",
 
 1876                          dPdlnT[*nstart],dPdlnT[*nstart2],dPdlnT[*nend],*ErrorCode );
 
 1894                               vector<double>& qtemp,
 
 1895                               vector<double>& qprob,
 
 1896                               vector<double>& dPdlnT,
 
 1898                               vector<double>& delu,
 
 1899                               vector<double>& Lambda,
 
 1921         ASSERT( nstart >= 0 && nstart < nend && nend < 
NQGRID );
 
 1934         vector<double> new_delu(
NQGRID);
 
 1935         vector<double> new_dPdlnT(
NQGRID);
 
 1936         vector<double> new_Lambda(
NQGRID);
 
 1937         vector<double> new_p(
NQGRID);
 
 1938         vector<double> new_qprob(
NQGRID);
 
 1939         vector<double> new_qtemp(
NQGRID);
 
 1940         vector<double> new_u1(
NQGRID);
 
 1950         help = 
pow(qtemp[nend]/qtemp[i],1./(1.5*
NQMIN));
 
 1969                         double p1,p2,L1,L2,
frac,slope;
 
 1970                         if( qtemp[i] <= T1 && T1 <= qtemp[i+1] )
 
 1974                                 double xrlog = log(qtemp[i+1]/qtemp[i]);
 
 1977                                         frac = log(T1/qtemp[i]);
 
 1978                                         slope = log(p[i+1]/p[i])/xrlog;
 
 1979                                         p1 = p[i]*exp(frac*slope);
 
 1980                                         slope = log(Lambda[i+1]/Lambda[i])/xrlog;
 
 1981                                         L1 = Lambda[i]*exp(frac*slope);
 
 1986                                         p1 = sqrt(p[i]*p[i+1]);
 
 1987                                         L1 = sqrt(Lambda[i]*Lambda[i+1]);
 
 1997                         if( qtemp[i] <= T2 && T2 <= qtemp[i+1] )
 
 2000                                 help = 
ufunct(T2,nd,&lgBoundErr);
 
 2001                                 uu2 = 
MIN2(help,u1[i+1]);
 
 2003                                 double xrlog = log(qtemp[i+1]/qtemp[i]);
 
 2006                                         frac = log(T2/qtemp[i]);
 
 2007                                         slope = log(p[i+1]/p[i])/xrlog;
 
 2008                                         p2 = p[i]*exp(frac*slope);
 
 2009                                         slope = log(Lambda[i+1]/Lambda[i])/xrlog;
 
 2010                                         L2 = Lambda[i]*exp(frac*slope);
 
 2015                                         p2 = sqrt(p[i]*p[i+1]);
 
 2016                                         L2 = sqrt(Lambda[i]*Lambda[i+1]);
 
 2038                         vlog(z,uu1,uu2,p1,p2,p1*L1,p2*L2,1.,1.);
 
 2040                         s1 += 
log_integral(uu1,p1*L1,uu2,p2*L2,z[0],z[4],z[1],z[5]);
 
 2043                 } 
while( i < nend && ! lgDone );
 
 2054                 new_qprob[newnbin] = s0;
 
 2055                 new_Lambda[newnbin] = s1/s0;
 
 2056                 xx = log(new_Lambda[newnbin]*EN1RYD*
gv.
bin[nd]->cnv_GR_pH);
 
 2059                 new_qtemp[newnbin] = exp(y);
 
 2060                 new_u1[newnbin] = 
ufunct(new_qtemp[newnbin],nd,&lgBoundErr);
 
 2062                 new_delu[newnbin] = wid;
 
 2063                 new_p[newnbin] = new_qprob[newnbin]/new_delu[newnbin];
 
 2064                 new_dPdlnT[newnbin] = new_p[newnbin]*new_qtemp[newnbin]*
uderiv(new_qtemp[newnbin],nd);
 
 2067                 RadCooling += new_qprob[newnbin]*new_Lambda[newnbin];
 
 2075         if( newnbin < 
NQMIN )
 
 2081         fac = RadCooling*EN1RYD*
gv.
bin[nd]->cnv_GR_pCM3/
gv.
bin[nd]->GrainHeat;
 
 2085                 fprintf( 
ioQQQ, 
"     RebinQHeatResults found tol1 %.4e tol2 %.4e\n",
 
 2086                          fabs(u1[nend]/Ucheck-1.), fabs(fac-1.) );
 
 2091         ASSERT( fabs(u1[nend]/Ucheck-1.) < 10.*sqrt((
double)(nend-nstart+newnbin))*DBL_EPSILON );
 
 2096         for( i=0; i < newnbin; i++ )
 
 2099                 p[i] = new_p[i]/fac;
 
 2100                 qtemp[i] = new_qtemp[i];
 
 2101                 qprob[i] = new_qprob[i]/fac;
 
 2102                 dPdlnT[i] = new_dPdlnT[i]/fac;
 
 2104                 delu[i] = new_delu[i];
 
 2105                 Lambda[i] = new_Lambda[i];
 
 2108                 ASSERT( qtemp[i] > 0. && qprob[i] > 0. );
 
 2121                                    vector<double>& qtemp,
 
 2122                                    vector<double>& qprob,
 
 2123                                    vector<double>& dPdlnT,
 
 2165                 fprintf( 
ioQQQ, 
"   GetProbDistr_HighLimit called for grain %s\n", 
gv.
bin[nd]->chDstLab );
 
 2168         c1 = sqrt(4.*LN_TWO/PI)/fwhm*exp(-
pow2(fwhm/Umax)/(16.*LN_TWO));
 
 2169         c2 = 4.*LN_TWO*
pow2(Umax/fwhm);
 
 2173         help1 = Umax*exp(-fac1);
 
 2174         help2 = exp(
gv.
bin[nd]->DustEnth[0]);
 
 2175         Ulo = 
MAX2(help1,help2);
 
 2181         if( fac2 > log(DBL_MAX/10.) )
 
 2186         Uhi = Umax*exp(fac2);
 
 2192         uu1 = 
ufunct(T1,nd,&lgErr);
 
 2193         lgBoundErr = lgBoundErr || lgErr;
 
 2194         help1 = log(uu1/Umax);
 
 2195         p1 = c1*exp(-c2*
pow2(help1));
 
 2197         lgBoundErr = lgBoundErr || lgErr;
 
 2198         L1 = exp(y)*
gv.
bin[nd]->cnv_H_pGR/EN1RYD;
 
 2201         if( uu1*p1*L1 < 1.e5*DBL_MIN )
 
 2208         help1 = 
pow(Thi/Tlo,1./(1.2*
NQMIN));
 
 2221                 uu2 = 
ufunct(T2,nd,&lgErr);
 
 2222                 lgBoundErr = lgBoundErr || lgErr;
 
 2223                 help1 = log(uu2/Umax);
 
 2224                 p2 = c1*exp(-c2*
pow2(help1));
 
 2226                 lgBoundErr = lgBoundErr || lgErr;
 
 2227                 L2 = exp(y)*
gv.
bin[nd]->cnv_H_pGR/EN1RYD;
 
 2230                 vlog(z,uu1,uu2,p1,p2,p1*L1,p2*L2,1.,1.);
 
 2232                 s1 = 
log_integral(uu1,p1*L1,uu2,p2*L2,z[0],z[4],z[1],z[5]);
 
 2235                 Lambda[nbin] = s1/s0;
 
 2236                 xx = log(Lambda[nbin]*EN1RYD*
gv.
bin[nd]->cnv_GR_pH);
 
 2238                 lgBoundErr = lgBoundErr || lgErr;
 
 2239                 qtemp[nbin] = exp(y);
 
 2241                 p[nbin] = qprob[nbin]/delu[nbin];
 
 2242                 dPdlnT[nbin] = p[nbin]*qtemp[nbin]*
uderiv(qtemp[nbin],nd);
 
 2245                 RadCooling += qprob[nbin]*Lambda[nbin];
 
 2254         } 
while( T2 < Thi && nbin < 
NQGRID );
 
 2256         fac = RadCooling*EN1RYD*
gv.
bin[nd]->cnv_GR_pCM3/
gv.
bin[nd]->GrainHeat;
 
 2258         for( i=0; i < nbin; ++i )
 
 2266         *new_tmin = qtemp[0];
 
 2284                 fprintf( 
ioQQQ, 
"     GetProbDistr_HighLimit found tol1 %.4e tol2 %.4e\n",
 
 2285                          fabs(sum-1.), fabs(sum/fac-1.) );
 
 2286                 fprintf( 
ioQQQ, 
"    zone %ld %s nbin %ld total prob %.4e new_tmin %.4e\n",
 
 2287                          nzone,
gv.
bin[nd]->chDstLab,nbin,sum/fac,*new_tmin );
 
 2303           hok[3] = {1275., 1670., 4359.},
 
 2315                 fprintf( 
ioQQQ, 
" uderiv called with non-positive temperature: %.6e\n" , temp );
 
 2320         const double CALORIE = 4.184e7; 
 
 2326                 numer = (4.15e-22/EN1RYD)*
pow(temp,3.3);
 
 2327                 dnumer = (3.3*4.15e-22/EN1RYD)*
pow(temp,2.3);
 
 2328                 denom = 1. + 6.51e-03*temp + 1.5e-06*temp*temp + 8.3e-07*
pow(temp,2.3);
 
 2329                 ddenom = 6.51e-03 + 2.*1.5e-06*temp + 2.3*8.3e-07*
pow(temp,1.3);
 
 2332                 deriv = (dnumer*denom - numer*ddenom)/
pow2(denom);
 
 2343                 for( j = 0; j < 4; j++ )
 
 2345                         if( temp > 
tlim[j] && temp <= 
tlim[j+1] )
 
 2361                 x = log10(
MIN2(temp,2000.));
 
 2362                 deriv = 
exp10(-21.26+3.1688*x-0.401894*
pow2(x))/EN1RYD;
 
 2374                 else if( N_C <= 100. )
 
 2376                         N_H = 2.5*sqrt(N_C);
 
 2383                 for( i=0; i < 3; i++ )
 
 2385                         double help1 = hok[i]/temp;
 
 2388                                 double help2 = exp(help1);
 
 2389                                 double help3 = ( help1 < 1.e-7 ) ? help1*(1.+0.5*help1) : help2-1.;
 
 2390                                 deriv += N_H/(N_C-2.)*
pow2(help1)*help2/
pow2(help3)*BOLTZMANN/EN1RYD;
 
 2401                         deriv = 13.250 - 2035./temp + 288.e5/
pow2(temp)*exp(-5680./temp); 
 
 2403                 deriv *= CALORIE/(EN1RYD*2.*AVOGADRO);
 
 2406                 fprintf( 
ioQQQ, 
" uderiv called with unknown type for enthalpy function: %d\n", ecase );
 
 2416                 fprintf( 
ioQQQ, 
" uderiv finds non-positive derivative: %.6e, what's up?\n" , deriv );
 
 2435                 fprintf( 
ioQQQ, 
" ufunct called with non-positive temperature: %.6e\n" , temp );
 
 2459         if( enthalpy <= 0. ) 
 
 2461                 fprintf( 
ioQQQ, 
" inv_ufunct called with non-positive enthalpy: %.6e\n" , enthalpy );
 
 2481         for( 
size_t nd=0; nd < 
gv.
bin.size(); nd++ )
 
 2484                 double C_V2 = 
uderiv(tdust2,nd);
 
 2486                 gv.
bin[nd]->DustEnth[0] = C_V2*tdust2/4.;
 
 2487                 double tdust1 = tdust2;
 
 2490                 for( 
long i=1; i < 
NDEMS; i++ )
 
 2494                         C_V2 = 
uderiv(tdust2,nd);
 
 2495                         tmid = sqrt(tdust1*tdust2);
 
 2497                         for( 
long j=1; j < 4; j++ )
 
 2499                                 if( tdust1 < 
tlim[j] && 
tlim[j] < tdust2 )
 
 2506                         vlog(z,tdust1,tmid,tdust2,C_V1,Cmid,C_V2,1.,1.);
 
 2507                         gv.
bin[nd]->DustEnth[i] = 
gv.
bin[nd]->DustEnth[i-1] +
 
 2508                                 log_integral(tdust1,C_V1,tmid,Cmid,z[0],z[3],z[1],z[4]) +
 
 2509                                 log_integral(tmid,Cmid,tdust2,C_V2,z[1],z[4],z[2],z[5]);
 
 2516         for( 
size_t nd=0; nd < 
gv.
bin.size(); nd++ )
 
 2538         ASSERT( n == 2 || n == 3 );
 
 2545                         res = 6.*1.202056903159594*
pow2(x);
 
 2549                         res = 24.*1.082323233711138*
pow3(x);
 
 2558                 nn = 4*
MAX2(4,2*(
long)(0.05/x));
 
 2559                 vector<double> xx(nn);
 
 2560                 vector<double> rr(nn);
 
 2561                 vector<double> aa(nn);
 
 2562                 vector<double> ww(nn);
 
 2567                 for( i=0; i < nn; i++ )
 
 2569                         double help1 = rr[i]/x;
 
 2572                                 double help2 = exp(help1);
 
 2573                                 double help3 = ( help1 < 1.e-7 ) ? help1*(1.+0.5*help1) : help2-1.;
 
 2574                                 res += ww[i]*
powi(rr[i],n+1)*help2/
pow2(help3);
 
 2579         return (
double)n*res;
 
static const long LOOP_MAX
STATIC void GetProbDistr_HighLimit(long, double, double, double, vector< double > &, vector< double > &, vector< double > &, double *, long *, double *, QH_Code *)
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
static const long NSTARTUP
void gauss_legendre(long int, vector< double > &, vector< double > &)
NORETURN void TotalInsanity(void)
static const double RELAX
double widflx(size_t i) const 
double no_atoms(size_t nd)
void spldrv_safe(const double xa[], const double ya[], const double y2a[], long int n, double x, double *y, bool *lgOutOfBounds)
STATIC double uderiv(double, size_t)
static const double DEF_FAC
static const realnum LIM1
static const long MAX_LOOP
flex_arr< realnum > yhat_primary
static const realnum LIM3
static const double tlim[5]
STATIC double ufunct(double, size_t, bool *)
void vlog(const double x[], double y[], long nlo, long nhi)
double anu(size_t i) const 
static const double MAX_EVENTS
vector< realnum > GraphiteEmission
STATIC double log_integral(double, double, double, double, double, double, double, double)
static const double STRICT
static const double ppower[4]
STATIC double DebyeDeriv(double, long)
void gauss_init(long int, double, double, const vector< double > &, const vector< double > &, vector< double > &, vector< double > &)
long int nflux_with_check
static const double FWHM_RATIO2
double xIonDense[LIMELM][LIMELM+1]
static const double QHEAT_TOL
static const double FWHM_RATIO
int dprintf(FILE *fp, const char *format,...)
size_t ipointC(double anu) const 
realnum dstAbundThresholdNear
void spline(const double x[], const double y[], long int n, double yp1, double ypn, double y2a[])
static const double DEN_SIL
void qheat(vector< double > &, vector< double > &, long *, size_t)
vector< realnum > GrainEmission
strg_type which_strg[MAT_TOP]
realnum fast_expm1(realnum x)
realnum dstAbundThresholdFar
enth_type which_enth[MAT_TOP]
STATIC void GetProbDistr_LowLimit(size_t, double, double, double, const vector< double > &, const vector< double > &, vector< double > &, vector< double > &, vector< double > &, long *, double *, long *, QH_Code *)
double powi(double, long int)
STATIC void ScanProbDistr(const vector< double > &, const vector< double > &, long, double, long, double, long *, long *, long *, long *, QH_Code *)
static const double PROB_TOL
double anu2(size_t i) const 
double heating(long nelem, long ion)
double anumin(size_t i) const 
static const long WIDE_FAIL_MAX
static const double SAFETY
STATIC double inv_ufunct(double, size_t, bool *)
static const realnum LIM2
#define DEBUG_ENTRY(funcname)
double powpq(double x, int p, int q)
realnum GrainHeatScaleFactor
static const double PROB_CUTOFF_LO
void splint_safe(const double xa[], const double ya[], const double y2a[], long int n, double x, double *y, bool *lgOutOfBounds)
STATIC void qheat_init(size_t, vector< double > &, double *)
int fprintf(const Output &stream, const char *format,...)
double pow(double x, int i)
static const double MW_SIL
static const double QT_RATIO
vector< realnum > SilicateEmission
double anumax(size_t i) const 
static const double PROB_CUTOFF_HI
void vexpm1(const double x[], double y[], long nlo, long nhi)
STATIC long RebinQHeatResults(size_t, long, long, vector< double > &, vector< double > &, vector< double > &, vector< double > &, vector< double > &, vector< double > &, vector< double > &, QH_Code *)
STATIC long GrainMakeDiffuseSingle(double Tgrain, double fracpop, avx_ptr< realnum > &flux, long nflux)
STATIC double TryDoubleStep(vector< double > &, vector< double > &, vector< double > &, vector< double > &, vector< double > &, const vector< double > &, const vector< double > &, double, double *, double, long, size_t, bool *)
static const double cval[4]