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,...)
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]