31 #define FREE_CHECK(PTR) { ASSERT( PTR != NULL ); free( PTR ); PTR = NULL; }
32 #define FREE_SAFE(PTR) { if( PTR != NULL ) free( PTR ); PTR = NULL; }
71 static const double AC0 = 3.e-9;
72 static const double AC1G = 4.e-8;
73 static const double AC2G = 7.e-8;
76 static const double ETILDE = 2.*SQRT2/EVRYD;
89 return ELEM_CHARGE/EVRYD/
gv.
bin[nd]->Capacity;
111 if( e <=
gv.
bin[nd]->le_thres )
114 return 3.e-6*
gv.
bin[nd]->eec*
powpq(e*EVRYD*1.e-3,3,2);
173 double*,
double*,
double*,
bool);
189 STATIC void PE_init(
size_t,
long,
long,
double*,
double*,
double*,
190 double*,
double*,
double*,
double*);
255 for(
unsigned int ns=0; ns <
sd.size(); ns++ )
259 for(
int nz=0; nz <
NCHS; nz++ )
335 for(
int nz=0; nz <
NCHS; nz++ )
341 for(
size_t nd=0; nd <
bin.size(); nd++ )
345 for(
int nelem=0; nelem <
LIMELM; nelem++ )
363 for(
int nelem=0; nelem <
LIMELM; nelem++ )
459 for(
int nelem=0; nelem <
LIMELM; nelem++ )
461 for(
int ion=0; ion <= nelem+1; ion++ )
463 for(
int ion_to=0; ion_to <= nelem+1; ion_to++ )
505 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
507 gv.
bin[nd]->ZloSave =
gv.
bin[nd]->chrg[0]->DustZ;
508 gv.
bin[nd]->qtmin = (
gv.
bin[nd]->qtmin_zone1 > 0. ) ?
509 gv.
bin[nd]->qtmin_zone1 : DBL_MAX;
510 gv.
bin[nd]->avdust = 0.;
511 gv.
bin[nd]->avdpot = 0.;
512 gv.
bin[nd]->avdft = 0.;
513 gv.
bin[nd]->avDGRatio = 0.;
514 gv.
bin[nd]->TeGrainMax = -1.f;
515 gv.
bin[nd]->lgEverQHeat =
false;
516 gv.
bin[nd]->QHeatFailures = 0L;
517 gv.
bin[nd]->lgQHTooWide =
false;
518 gv.
bin[nd]->lgPAHsInIonizedRegion =
false;
534 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
536 gv.
bin[nd]->lgIterStart =
true;
578 for( nelem=0; nelem <
LIMELM; nelem++ )
624 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
626 double help,
atoms,p_rad,ThresInf,ThresInfVal,Emin,d[5];
627 long low1,low2,low3,lowm;
635 fprintf(
ioQQQ,
" Grain work function for %s has insane value: %.4e\n",
636 gv.
bin[nd]->chDstLab,
gv.
bin[nd]->DustWorkFcn );
643 gv.
bin[nd]->lgQHeat =
true;
649 gv.
bin[nd]->lgQHeat =
false;
655 gv.
bin[nd]->lgQHeat =
false;
660 gv.
bin[nd]->lgQHTooWide =
false;
661 gv.
bin[nd]->qtmin = DBL_MAX;
664 gv.
bin[nd]->lgIterStart =
true;
672 gv.
bin[nd]->dstAbund = -FLT_MAX;
674 gv.
bin[nd]->GrnDpth = 1.f;
676 gv.
bin[nd]->qtmin_zone1 = -1.;
682 for(
long nz=0; nz <
NCHS; nz++ )
695 help =
gv.
bin[nd]->AvRadius*1.e7;
696 help = ceil(-(1.2*
POW2(help)+3.9*help+0.2)/1.44);
700 help =
gv.
bin[nd]->AvRadius*1.e7;
701 help = ceil(-(0.7*
POW2(help)+2.5*help+0.8)/1.44);
704 fprintf(
ioQQQ,
" GrainsInit detected unknown Zmin type: %d\n" , zcase );
709 ASSERT( help > (
double)(LONG_MIN+1) );
724 while( low3-low2 > 1 )
726 lowm = (low2+low3)/2;
740 gv.
bin[nd]->ZloSave = LONG_MIN;
748 gv.
bin[nd]->sd[ns]->nelem = -1;
749 gv.
bin[nd]->sd[ns]->ns = -1;
750 gv.
bin[nd]->sd[ns]->ionPot =
gv.
bin[nd]->DustWorkFcn;
755 if(
gv.
bin[nd]->elmAbund[nelem] > 0. )
759 fprintf(
ioQQQ,
" Grain Auger data are missing for element %s\n",
761 fprintf(
ioQQQ,
" Please include the NO GRAIN X-RAY TREATMENT command "
762 "to disable the Auger treatment in grains.\n" );
772 gv.
bin[nd]->sd[ns]->nelem = nelem;
773 gv.
bin[nd]->sd[ns]->ns = j;
781 for( ns=0; ns <
gv.
bin[nd]->sd.size(); ns++ )
784 double Ethres = ( ns == 0 ) ? ThresInfVal :
gv.
bin[nd]->sd[ns]->ionPot;
793 sptr->p.reserve( len );
796 sptr->y01.reserve( len );
803 sptr->AvNr.resize( sptr->nData );
804 sptr->Ener.resize( sptr->nData );
805 sptr->y01A.resize( sptr->nData );
807 for(
long n=0; n < sptr->nData; n++ )
812 sptr->y01A[n].reserve( len );
831 atoms =
gv.
bin[nd]->AvVol*
gv.
bin[nd]->dustp[0]/ATOMIC_MASS_UNIT/
gv.
bin[nd]->atomWeight;
832 p_rad = 1./(1.+exp(20.-atoms));
833 gv.
bin[nd]->StickElecNeg =
gv.
bin[nd]->StickElecPos*p_rad;
843 gv.
bin[nd]->cnv_CM3_pH = 1./
gv.
bin[nd]->cnv_H_pCM3;
845 gv.
bin[nd]->cnv_CM3_pGR =
gv.
bin[nd]->cnv_H_pGR/
gv.
bin[nd]->cnv_H_pCM3;
846 gv.
bin[nd]->cnv_GR_pCM3 = 1./
gv.
bin[nd]->cnv_CM3_pGR;
854 for( nelem=0; nelem <
LIMELM; nelem++ )
859 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
861 for( nelem=0; nelem <
LIMELM; nelem++ )
885 fprintf(
ioQQQ,
" There are %ld grain types turned on.\n", (
unsigned long)
gv.
bin.size() );
887 fprintf(
ioQQQ,
" grain depletion factors, dstfactor*GrainMetal=" );
888 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
895 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
902 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
908 fprintf(
ioQQQ,
" nDustFunc flag for user requested custom depth dependence:" );
909 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
916 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
923 fprintf(
ioQQQ,
" NU(Ryd), Abs cross sec per proton\n" );
926 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
935 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
942 fprintf(
ioQQQ,
" NU(Ryd), Sct cross sec per proton\n" );
945 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
954 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
964 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
973 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
983 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
992 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
1002 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
1011 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
1032 static const char chFile[] =
"auger_spectrum.dat";
1036 sscanf( chString,
"%ld", &version );
1039 fprintf(
ioQQQ,
" File %s has wrong version number\n", chFile );
1040 fprintf(
ioQQQ,
" please update your installation...\n" );
1051 if( sscanf( chString,
"%ld", &nelem ) != 1 )
1065 if( sscanf( chString,
"%u", &ptr->
nSubShell ) != 1 )
1082 if( sscanf( chString,
"%u", &ss ) != 1 )
1090 if( sscanf( chString,
"%le", &ptr->
IonThres[ns] ) != 1 )
1098 if( sscanf( chString,
"%u", &ptr->
nData[ns] ) != 1 )
1108 for(
unsigned int n=0; n < ptr->
nData[ns]; n++ )
1111 if( sscanf(chString,
"%le %le",&ptr->
Energy[ns][n],&ptr->
AvNumber[ns][n]) != 2 )
1116 ptr->
Energy[ns][n] /= EVRYD;
1135 long i, ipLo, nelem;
1142 double norm =
gv.
bin[nd]->cnv_H_pGR/
gv.
bin[nd]->AvVol;
1145 for( ns=0; ns <
gv.
bin[nd]->sd.size(); ns++ )
1147 ipLo =
max(
gv.
bin[nd]->sd[ns]->ipLo, ipBegin );
1149 gv.
bin[nd]->sd[ns]->p.realloc( ipEnd );
1153 for( i=ipLo; i < ipEnd; i++ )
1164 gv.
bin[nd]->sd[ns]->p[i] = 0.;
1168 if(
gv.
bin[nd]->elmAbund[nelem] == 0. )
1177 gv.
bin[nd]->sd[ns]->p[i] +=
1182 temp[i] +=
gv.
bin[nd]->sd[ns]->p[i];
1187 nelem =
gv.
bin[nd]->sd[ns]->nelem;
1189 nsh =
gv.
bin[nd]->sd[ns]->ns;
1191 gv.
bin[nd]->sd[ns]->p[i] =
1193 temp[i] +=
gv.
bin[nd]->sd[ns]->p[i];
1198 for( i=ipBegin; i < ipEnd && !
gv.
lgWD01; i++ )
1202 gv.
bin[nd]->inv_att_len[i] = temp[i];
1205 for( ns=0; ns <
gv.
bin[nd]->sd.size(); ns++ )
1207 ipLo =
max(
gv.
bin[nd]->sd[ns]->ipLo, ipBegin );
1209 for( i=ipLo; i < ipEnd; i++ )
1212 gv.
bin[nd]->sd[ns]->p[i] /= temp[i];
1214 gv.
bin[nd]->sd[ns]->p[i] = ( ns == 0 ) ? 1.f : 0.f;
1220 for( ns=0; ns <
gv.
bin[nd]->sd.size(); ns++ )
1225 ipLo =
max( sptr->
ipLo, ipBegin );
1230 for( i=ipLo; i < ipEnd; i++ )
1232 double elec_en,yzero,yone;
1235 yzero =
y0psa( nd, ns, i, elec_en );
1239 yone =
y1psa( nd, i, elec_en );
1256 for( n=0; n < sptr->
nData; n++ )
1258 sptr->
y01A[n].realloc( ipEnd );
1260 for( i=ipLo; i < ipEnd; i++ )
1262 double yzero = sptr->
AvNr[n] *
y0psa( nd, ns, i, sptr->
Ener[n] );
1266 double yone =
y1psa( nd, i, sptr->
Ener[n] );
1294 while( chLine[0] ==
'#' );
1315 fprintf(
ioQQQ,
" ND Tdust Emis BB Check 4pi*a^2*<Q>\n" );
1324 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
1336 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
1348 mul = sqrt((
double)(NDEMS-NTOP));
1350 mul = (double)NTOP + sqrt((
double)
NDEMS);
1355 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
1366 for( i=0; i < 2000; i++ )
1369 z =
exp10(-40. + (
double)i/50.);
1374 printf(
" input %.6e temp %.6e output %.6e rel. diff. %.6e\n",z,exp(y),x,(x-z)/z);
1400 double TDustRyg = TE1RYD/tdust;
1401 double x = 0.999*log(DBL_MAX);
1408 if( arg[i] < 0.9999e-5 )
1410 if( arg[i] > x+0.0001 )
1416 vexp( arg.ptr0(), expval.
ptr0(), mini, maxi );
1418 double integral1 = 0.;
1419 double integral2 = 0.;
1421 for(
long i=0; i < maxi; i++ )
1425 if( arg[i] < 1.e-5 )
1428 ExpM1 = arg[i]*(1. + arg[i]/2.);
1433 ExpM1 = expval[i] - 1.;
1436 double Planck1 = PI4*2.*HPLANCK/
POW2(SPEEDLIGHT)*
POW2(FR1RYD)*
POW2(FR1RYD)*
1438 double Planck2 = Planck1*
gv.
bin[nd]->dstab1[i];
1447 if( Planck1/integral1 < DBL_EPSILON && Planck2/integral2 < DBL_EPSILON )
1450 integral1 += Planck1;
1451 integral2 += Planck2;
1457 fprintf(
ioQQQ,
" %4ld %11.4e %11.4e %11.4e %11.4e\n", (
unsigned long)nd, tdust,
1458 integral2, integral1/4./5.67051e-5/
powi(tdust,4), integral2*4./integral1 );
1461 ASSERT( integral2 > 0. );
1473 for( nz=0; nz <
NCHS; nz++ )
1475 gv.
bin[nd]->chrg[nz]->RSum1 = -DBL_MAX;
1476 gv.
bin[nd]->chrg[nz]->RSum2 = -DBL_MAX;
1477 gv.
bin[nd]->chrg[nz]->ESum1a = -DBL_MAX;
1478 gv.
bin[nd]->chrg[nz]->ESum1b = -DBL_MAX;
1479 gv.
bin[nd]->chrg[nz]->ESum2 = -DBL_MAX;
1481 gv.
bin[nd]->chrg[nz]->hots1 = -DBL_MAX;
1482 gv.
bin[nd]->chrg[nz]->bolflux1 = -DBL_MAX;
1483 gv.
bin[nd]->chrg[nz]->pe1 = -DBL_MAX;
1486 gv.
bin[nd]->chrg[nz]->ThermRate = -DBL_MAX;
1487 gv.
bin[nd]->chrg[nz]->GrainHeat = -DBL_MAX;
1488 gv.
bin[nd]->chrg[nz]->HeatingRate2 = -DBL_MAX;
1493 for( nz=0; nz <
NCHS; nz++ )
1495 memset(
gv.
bin[nd]->chrg[nz]->eta, 0, (
LIMELM+2)*
sizeof(
double) );
1496 memset(
gv.
bin[nd]->chrg[nz]->xi, 0, (
LIMELM+2)*
sizeof(
double) );
1502 for( nz=0; nz <
NCHS; nz++ )
1504 gv.
bin[nd]->chrg[nz]->hcon1 = -DBL_MAX;
1515 double GrnStdDpth_v;
1579 GrnStdDpth_v =
max(1.e-10,GrnStdDpth_v);
1581 return GrnStdDpth_v;
1593 static double tesave = -1.;
1594 static long int nzonesave = -1;
1632 long nelem, ion, ion_to;
1637 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
1642 gv.
bin[nd]->lgPAHsInIonizedRegion =
false;
1644 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
1646 gv.
bin[nd]->chrg[nz]->DustZ = nz;
1647 gv.
bin[nd]->chrg[nz]->FracPop = ( nz == 0 ) ? 1. : 0.;
1648 gv.
bin[nd]->chrg[nz]->nfill = 0;
1649 gv.
bin[nd]->chrg[nz]->tedust = 100.f;
1652 gv.
bin[nd]->AveDustZ = 0.;
1655 gv.
bin[nd]->tedust = 100.f;
1656 gv.
bin[nd]->TeGrainMax = 100.;
1659 gv.
bin[nd]->BolFlux = 0.;
1660 gv.
bin[nd]->GrainCoolTherm = 0.;
1661 gv.
bin[nd]->GasHeatPhotoEl = 0.;
1662 gv.
bin[nd]->GrainHeat = 0.;
1663 gv.
bin[nd]->GrainHeatColl = 0.;
1664 gv.
bin[nd]->ChemEn = 0.;
1665 gv.
bin[nd]->ChemEnH2 = 0.;
1666 gv.
bin[nd]->thermionic = 0.;
1668 gv.
bin[nd]->lgUseQHeat =
false;
1669 gv.
bin[nd]->lgEverQHeat =
false;
1670 gv.
bin[nd]->QHeatFailures = 0;
1672 gv.
bin[nd]->DustDftVel = 0.;
1675 gv.
bin[nd]->avdft = 0.f;
1677 gv.
bin[nd]->avDGRatio = -1.f;
1701 for( nelem=0; nelem <
LIMELM; nelem++ )
1703 for( ion=0; ion <= nelem+1; ion++ )
1705 for( ion_to=0; ion_to <= nelem+1; ion_to++ )
1759 static long int oldZone = -1;
1760 static double oldTe = -DBL_MAX,
1786 for( nelem=0; nelem <
LIMELM; nelem++ )
1788 for( ion=0; ion <= nelem+1; ion++ )
1790 for( ion_to=0; ion_to <= nelem+1; ion_to++ )
1800 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
1803 double ChTdBracketLo = 0., ChTdBracketHi = -DBL_MAX;
1811 gv.
bin[nd]->lgPAHsInIonizedRegion =
true;
1822 fprintf(
ioQQQ,
" >>GrainChargeTemp starting grain %s\n",
1823 gv.
bin[nd]->chDstLab );
1828 for( i=0; i < relax*CT_LOOP_MAX && delta >
TOLER; ++i )
1832 double TdBracketLo = 0., TdBracketHi = -DBL_MAX;
1833 double ThresEst = 0.;
1834 oldtemp =
gv.
bin[nd]->tedust;
1849 gv.
bin[nd]->lgTdustConverged =
false;
1852 double oldTemp2 =
gv.
bin[nd]->tedust;
1853 double oldHeat2 =
gv.
bin[nd]->GrainHeat;
1854 double oldCool =
gv.
bin[nd]->GrainGasCool;
1859 gv.
bin[nd]->GrainGasCool = dccool;
1863 fprintf(
ioQQQ,
" >>loop %ld BracketLo %.6e BracketHi %.6e",
1864 j, TdBracketLo, TdBracketHi );
1874 gv.
bin[nd]->lgTdustConverged =
true;
1881 if(
gv.
bin[nd]->tedust < oldTemp2 )
1882 TdBracketHi = oldTemp2;
1884 TdBracketLo = oldTemp2;
1894 if( TdBracketHi > TdBracketLo )
1898 if( ( j >= 2 && TdBracketLo > 0. ) ||
1899 gv.
bin[nd]->tedust <= TdBracketLo ||
1900 gv.
bin[nd]->tedust >= TdBracketHi )
1902 gv.
bin[nd]->tedust = (
realnum)(0.5*(TdBracketLo + TdBracketHi));
1921 if(
gv.
bin[nd]->lgTdustConverged )
1924 if(
gv.
bin[nd]->tedust < oldtemp )
1925 ChTdBracketHi = oldtemp;
1927 ChTdBracketLo = oldtemp;
1932 double y, x = log(
gv.
bin[nd]->tedust);
1935 gv.
bin[nd]->GrainHeat = exp(y)*
gv.
bin[nd]->cnv_H_pCM3;
1937 fprintf(
ioQQQ,
" PROBLEM temperature of grain species %s (Tg=%.3eK) not converged\n",
1955 ratio =
gv.
bin[nd]->tedust/oldtemp;
1956 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
1958 ThresEst +=
gv.
bin[nd]->chrg[nz]->FracPop*
gv.
bin[nd]->chrg[nz]->ThresInf;
1960 delta = ThresEst*TE1RYD/
gv.
bin[nd]->tedust*(ratio - 1.);
1962 delta = ( delta < 0.9*log(DBL_MAX) ) ?
1963 ThermRatio*fabs(
POW2(ratio)*exp(delta)-1.) : DBL_MAX;
1969 which =
"iteration";
1979 if( ChTdBracketHi > ChTdBracketLo )
1983 if( ( i >= 2 && ChTdBracketLo > 0. ) ||
1984 gv.
bin[nd]->tedust <= ChTdBracketLo ||
1985 gv.
bin[nd]->tedust >= ChTdBracketHi )
1987 gv.
bin[nd]->tedust = (
realnum)(0.5*(ChTdBracketLo + ChTdBracketHi));
1989 which =
"bisection";
1996 fprintf(
ioQQQ,
" >>GrainChargeTemp finds delta=%.4e, ", delta );
2006 fprintf(
ioQQQ,
" PROBLEM charge/temperature not converged for %s zone %.2f\n",
2049 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
2051 one +=
gv.
bin[nd]->chrg[nz]->FracPop*(double)
gv.
bin[nd]->chrg[nz]->DustZ*
2052 gv.
bin[nd]->cnv_GR_pCM3;
2058 enum {DEBUG_LOC=
false};
2062 fprintf(
ioQQQ,
" DEBUG grn chr nz\t%.2f\teden\t%.3e\tnd\t%li",
2066 fprintf(
ioQQQ,
"\tne\t%.2e\tAveDustZ\t%.2e\t%.2e\t%.2e\t%.2e",
2068 gv.
bin[nd]->AveDustZ,
2069 gv.
bin[nd]->chrg[0]->FracPop,(
double)
gv.
bin[nd]->chrg[0]->DustZ,
2070 gv.
bin[nd]->cnv_GR_pCM3);
2077 fprintf(
ioQQQ,
" %s Pot %.5e Thermal %.5e GasCoolColl %.5e" ,
2078 gv.
bin[nd]->chDstLab,
gv.
bin[nd]->dstpot,
gv.
bin[nd]->GrainHeat, dccool );
2079 fprintf(
ioQQQ,
" GasPEHeat %.5e GasThermHeat %.5e ChemHeat %.5e\n\n" ,
2080 gv.
bin[nd]->GasHeatPhotoEl,
gv.
bin[nd]->thermionic,
gv.
bin[nd]->ChemEn );
2142 printf(
"wd test: proton fraction %.5e Total DustZ %.6f heating/cooling rate %.5e %.5e\n",
2151 enum {DEBUG_LOC=
false};
2157 for( nelem=0; nelem <
LIMELM; nelem++ )
2164 for( ion_to=0; ion_to <= nelem+1; ion_to++ )
2168 printf(
" %ld->%ld %.2e", ion, ion_to,
2178 fprintf(
ioQQQ,
" %.2f Grain contribution to electron density %.2e\n",
2182 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
2185 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
2187 sum +=
gv.
bin[nd]->chrg[nz]->FracPop*(double)
gv.
bin[nd]->chrg[nz]->DustZ*
2188 gv.
bin[nd]->cnv_GR_pCM3;
2195 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
2202 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
2240 netloss0 = -DBL_MAX,
2241 netloss1 = -DBL_MAX,
2256 for( nz=0; nz <
NCHS; nz++ )
2258 gv.
bin[nd]->chrg[nz]->FracPop = -DBL_MAX;
2309 backup =
gv.
bin[nd]->nChrg;
2312 stride0 =
gv.
bin[nd]->nChrg-1;
2315 if(
gv.
bin[nd]->lgIterStart )
2325 double anuav =
safe_div( sum2, sum1, 0. );
2336 Zlo = -long(
nint(step/4.));
2338 power = (int)(log(step)/log((
double)stride0));
2339 power =
MAX2(power,0);
2340 double xxx =
powi((
double)stride0,power);
2347 Zlo =
gv.
bin[nd]->ZloSave;
2354 Zlo =
gv.
bin[nd]->chrg[0]->DustZ;
2356 Zlo =
max(Zlo,
gv.
bin[nd]->LowestZg);
2357 UpdatePot( nd, Zlo, stride, rate_up, rate_dn );
2362 netloss0 = rate_up[0] - rate_dn[0];
2363 netloss1 = rate_up[
gv.
bin[nd]->nChrg-1] - rate_dn[
gv.
bin[nd]->nChrg-1];
2365 if( netloss0*netloss1 <= 0. )
2369 Zlo += (
gv.
bin[nd]->nChrg-1)*stride;
2375 Zlo -= (
gv.
bin[nd]->nChrg-1)*stride;
2378 UpdatePot( nd, Zlo, stride, rate_up, rate_dn );
2381 if( netloss0*netloss1 > 0. ) {
2382 fprintf(
ioQQQ,
" insanity: could not bracket grain charge for %s\n",
gv.
bin[nd]->chDstLab );
2392 netloss0 = rate_up[0] - rate_dn[0];
2393 for( nz=0; nz <
gv.
bin[nd]->nChrg-1; nz++ )
2395 netloss1 = rate_up[nz+1] - rate_dn[nz+1];
2397 if( netloss0*netloss1 <= 0. )
2399 Zlo =
gv.
bin[nd]->chrg[nz]->DustZ;
2403 netloss0 = netloss1;
2405 UpdatePot( nd, Zlo, stride, rate_up, rate_dn );
2408 ASSERT( netloss0*netloss1 <= 0. );
2410 gv.
bin[nd]->nChrg = backup;
2413 loopMax = (
gv.
bin[nd]->lgIterStart ) ? 4*
gv.
bin[nd]->nChrg : 2*
gv.
bin[nd]->nChrg;
2416 for( i=0; i < loopMax; i++ )
2418 GetFracPop( nd, Zlo, rate_up, rate_dn, &newZlo );
2427 UpdatePot( nd, Zlo, 1, rate_up, rate_dn );
2431 fprintf(
ioQQQ,
" insanity: could not converge grain charge for %s\n",
gv.
bin[nd]->chDstLab );
2436 gv.
bin[nd]->AveDustZ = 0.;
2438 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
2442 gv.
bin[nd]->AveDustZ +=
gv.
bin[nd]->chrg[nz]->FracPop*
gv.
bin[nd]->chrg[nz]->DustZ;
2445 csum3 +=
gv.
bin[nd]->chrg[nz]->FracPop*d[3];
2448 *ThermRatio = ( crate > 0. ) ? csum3/crate : 0.;
2450 ASSERT( *ThermRatio >= 0. );
2452 gv.
bin[nd]->lgIterStart =
false;
2460 crate = csum1a = csum1b = csum2 = csum3 = 0.;
2461 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
2463 crate +=
gv.
bin[nd]->chrg[nz]->FracPop*
2465 csum1a +=
gv.
bin[nd]->chrg[nz]->FracPop*d[0];
2466 csum1b +=
gv.
bin[nd]->chrg[nz]->FracPop*d[1];
2467 csum2 +=
gv.
bin[nd]->chrg[nz]->FracPop*d[2];
2468 csum3 +=
gv.
bin[nd]->chrg[nz]->FracPop*d[3];
2471 fprintf(
ioQQQ,
" ElecEm rate1a=%.4e, rate1b=%.4e, ", csum1a, csum1b );
2472 fprintf(
ioQQQ,
"rate2=%.4e, rate3=%.4e, sum=%.4e\n", csum2, csum3, crate );
2475 fprintf(
ioQQQ,
" rate1a/sum=%.4e, rate1b/sum=%.4e, ", csum1a/crate, csum1b/crate );
2476 fprintf(
ioQQQ,
"rate2/sum=%.4e, rate3/sum=%.4e\n", csum2/crate, csum3/crate );
2479 crate = csum1 = csum2 = 0.;
2480 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
2483 csum1 +=
gv.
bin[nd]->chrg[nz]->FracPop*d[0];
2484 csum2 +=
gv.
bin[nd]->chrg[nz]->FracPop*d[1];
2487 fprintf(
ioQQQ,
" ElecRc rate1=%.4e, rate2=%.4e, sum=%.4e\n", csum1, csum2, crate );
2490 fprintf(
ioQQQ,
" rate1/sum=%.4e, rate2/sum=%.4e\n", csum1/crate, csum2/crate );
2494 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
2497 gv.
bin[nd]->chrg[nz]->DustZ, rate_up[nz], rate_dn[nz] );
2501 fprintf(
ioQQQ,
" FracPop: fnzone %.2f nd %ld AveZg %.5e",
2502 fnzone, (
unsigned long)nd,
gv.
bin[nd]->AveDustZ );
2503 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
2510 gv.
bin[nd]->chDstLab,
gv.
bin[nd]->dstpot*EVRYD );
2511 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
2513 fprintf(
ioQQQ,
" Thres[%ld]: %.4f V ThresVal[%ld]: %.4f V",
2514 gv.
bin[nd]->chrg[nz]->DustZ,
gv.
bin[nd]->chrg[nz]->ThresInf*EVRYD,
2515 gv.
bin[nd]->chrg[nz]->DustZ,
gv.
bin[nd]->chrg[nz]->ThresInfVal*EVRYD );
2544 if(
gv.
bin[nd]->chrg[nz]->RSum1 >= 0. )
2546 *sum1 =
gv.
bin[nd]->chrg[nz]->RSum1;
2547 *sum2 =
gv.
bin[nd]->chrg[nz]->RSum2;
2548 rate = *sum1 + *sum2;
2556 ve = sqrt(8.*BOLTZMANN/PI/ELECTRON_MASS*
phycon.
te);
2558 Stick = (
gv.
bin[nd]->chrg[nz]->DustZ <= -1 ) ?
gv.
bin[nd]->StickElecNeg :
gv.
bin[nd]->StickElecPos;
2563 *sum1 = (
gv.
bin[nd]->chrg[nz]->DustZ >
gv.
bin[nd]->LowestZg ) ? Stick*
dense.
eden*ve*eta : 0.;
2568 #ifndef IGNORE_GRAIN_ION_COLLISIONS
2569 for( ion=0; ion <=
LIMELM; ion++ )
2571 double CollisionRateAll = 0.;
2573 for( nelem=
MAX2(ion-1,0); nelem <
LIMELM; nelem++ )
2576 gv.
bin[nd]->chrg[nz]->RecomZ0[nelem][ion] > ion )
2581 (double)(
gv.
bin[nd]->chrg[nz]->RecomZ0[nelem][ion]-ion);
2585 if( CollisionRateAll > 0. )
2591 *sum2 += CollisionRateAll*eta;
2596 rate = *sum1 + *sum2;
2599 gv.
bin[nd]->chrg[nz]->RSum1 = *sum1;
2600 gv.
bin[nd]->chrg[nz]->RSum2 = *sum2;
2602 ASSERT( *sum1 >= 0. && *sum2 >= 0. );
2622 if(
gv.
bin[nd]->chrg[nz]->ESum1a >= 0. )
2624 *sum1a =
gv.
bin[nd]->chrg[nz]->ESum1a;
2625 *sum1b =
gv.
bin[nd]->chrg[nz]->ESum1b;
2626 *sum2 =
gv.
bin[nd]->chrg[nz]->ESum2;
2628 *sum3 = 4.*
gv.
bin[nd]->chrg[nz]->ThermRate;
2629 return *sum1a + *sum1b + *sum2 + *sum3;
2653 *sum1a /=
gv.
bin[nd]->IntArea/4.;
2656 if( gptr->
DustZ <= -1 )
2665 *sum1b /=
gv.
bin[nd]->IntArea/4.;
2670 # ifndef IGNORE_GRAIN_ION_COLLISIONS
2671 for(
long ion=0; ion <=
LIMELM; ion++ )
2673 double CollisionRateAll = 0.;
2674 for(
long nelem=
MAX2(ion-1,0); nelem <
LIMELM; nelem++ )
2677 ion > gptr->
RecomZ0[nelem][ion] )
2682 (double)(ion-gptr->
RecomZ0[nelem][ion]);
2687 if( CollisionRateAll > 0. )
2694 *sum2 += CollisionRateAll*eta;
2702 *sum3 = 4.*
gv.
bin[nd]->chrg[nz]->ThermRate;
2709 gptr->
ESum2 = *sum2;
2711 ASSERT( *sum1a >= 0. && *sum1b >= 0. && *sum2 >= 0. && *sum3 >= 0. );
2712 return *sum1a + *sum1b + *sum2 + *sum3;
2732 if(
gv.
bin[nd]->chrg[nz]->eta[ind] > 0. )
2734 *eta =
gv.
bin[nd]->chrg[nz]->eta[ind];
2735 *xi =
gv.
bin[nd]->chrg[nz]->xi[ind];
2754 double nu = (double)
gv.
bin[nd]->chrg[nz]->DustZ/(
double)ion;
2755 double tau =
gv.
bin[nd]->Capacity*BOLTZMANN*
phycon.
te*1.e-7/
POW2((
double)ion*ELEM_CHARGE);
2758 *eta = (1. - nu/tau)*(1. + sqrt(2./(tau - 2.*nu)));
2759 *xi = (1. - nu/(2.*tau))*(1. + 1./sqrt(tau - nu));
2763 *eta = 1. + sqrt(PI/(2.*tau));
2764 *xi = 1. + 0.75*sqrt(PI/(2.*tau));
2768 double theta_nu =
ThetaNu(nu);
2770 double xxx = 1. + 1./sqrt(4.*tau+3.*nu);
2771 *eta =
POW2(xxx)*exp(-theta_nu/tau);
2773 *xi = (1. + nu/(2.*tau))*(1. + 1./sqrt(3./(2.*tau)+3.*nu))*exp(-theta_nu/tau);
2778 xxx = 0.25*
powpq(nu/tau,3,4)/(
powpq(nu/tau,3,4) +
powpq((25.+3.*nu)/5.,3,4)) +
2779 (1. + 0.75*sqrt(PI/(2.*tau)))/(1. + sqrt(PI/(2.*tau)));
2780 *xi = (
MIN2(xxx,1.) + theta_nu/(2.*tau))*(*eta);
2784 ASSERT( *eta >= 0. && *xi >= 0. );
2787 gv.
bin[nd]->chrg[nz]->eta[ind] = *eta;
2788 gv.
bin[nd]->chrg[nz]->xi[ind] = *xi;
2802 const double REL_TOLER = 10.*DBL_EPSILON;
2805 double xi_nu = 1. + 1./sqrt(3.*nu);
2806 double xi_nu2 =
POW2(xi_nu);
2812 double fnu = 2.*xi_nu2 - 1. - nu*xi_nu*
POW2(xi_nu2 - 1.);
2813 double dfdxi = 4.*xi_nu - nu*((5.*xi_nu2 - 6.)*xi_nu2 + 1.);
2815 xi_nu2 =
POW2(xi_nu);
2816 xxx = fabs(old-xi_nu);
2817 }
while( xxx > REL_TOLER*xi_nu );
2819 theta_nu = nu/xi_nu - 1./(2.*xi_nu2*(xi_nu2-1.));
2867 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
2873 Zg = Zlo + nz*stride;
2877 for( zz=0; zz <
NCHS-1; zz++ )
2879 if(
gv.
bin[nd]->chrg[zz]->DustZ == Zg )
2888 ptr =
gv.
bin[nd]->chrg[ind];
2891 for( zz=ind-1; zz >= nz; zz-- )
2892 gv.
bin[nd]->chrg[zz+1] =
gv.
bin[nd]->chrg[zz];
2894 gv.
bin[nd]->chrg[nz] = ptr;
2896 if(
gv.
bin[nd]->chrg[nz]->DustZ != Zg )
2909 ASSERT( rate_up[nz] >= 0. && rate_dn[nz] >= 0. );
2917 BoltzFac = (-log(
CONSERV_TOL) + 8.)*BOLTZMANN/EN1RYD;
2919 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
2922 HighEnergy =
MAX2(HighEnergy,
2946 double netloss[2], pop[2][
NCHU-1];
2957 for(
long i=0; i < 2; i++ )
2959 double sum = pop[i][0] = 1.;
2960 long nlim =
gv.
bin[nd]->nChrg-1;
2961 for(
long j=1; j < nlim; j++ )
2964 if( rate_dn[nz] > 10.*rate_up[nz-1]/sqrt(DBL_MAX) )
2966 pop[i][j] = pop[i][j-1]*rate_up[nz-1]/rate_dn[nz];
2971 for(
long k=0; k < j; k++ )
2979 if( pop[i][j] > sqrt(DBL_MAX) )
2981 for(
long k=0; k <= j; k++ )
2983 pop[i][k] /= DBL_MAX/10.;
2989 for(
long j=0; j < nlim; j++ )
2993 netloss[i] += pop[i][j]*(rate_up[nz] - rate_dn[nz]);
2999 if( netloss[0]*netloss[1] > 0. )
3000 *newZlo = ( netloss[1] > 0. ) ? Zlo + 1 : Zlo - 1;
3009 if(
gv.
bin[nd]->nChrg > 2 &&
3010 ( *newZlo <
gv.
bin[nd]->LowestZg ||
3011 ( *newZlo == Zlo && pop[1][
gv.
bin[nd]->nChrg-2] < DBL_EPSILON ) ) )
3013 gv.
bin[nd]->nChrg--;
3022 printf(
" fnzone %.2f nd %ld Zlo %ld newZlo %ld netloss %.4e %.4e nChrg %ld lgRedo %d\n",
3023 fnzone, nd, Zlo, *newZlo, netloss[0], netloss[1],
gv.
bin[nd]->nChrg, lgRedo );
3028 if( *newZlo <
gv.
bin[nd]->LowestZg )
3030 fprintf(
ioQQQ,
" could not converge charge state populations for %s\n",
gv.
bin[nd]->chDstLab );
3035 if( *newZlo == Zlo )
3038 double frac0 = netloss[1]/(netloss[1]-netloss[0]);
3039 double frac1 = -netloss[0]/(netloss[1]-netloss[0]);
3041 gv.
bin[nd]->chrg[0]->FracPop = frac0*pop[0][0];
3042 gv.
bin[nd]->chrg[
gv.
bin[nd]->nChrg-1]->FracPop = frac1*pop[1][
gv.
bin[nd]->nChrg-2];
3043 for(
long nz=1; nz <
gv.
bin[nd]->nChrg-1; nz++ )
3045 gv.
bin[nd]->chrg[nz]->FracPop = frac0*pop[0][nz] + frac1*pop[1][nz-1];
3049 double test1 = 0., test2 = 0., test3 = 0.;
3050 for(
long nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
3053 test1 +=
gv.
bin[nd]->chrg[nz]->FracPop;
3054 test2 +=
gv.
bin[nd]->chrg[nz]->FracPop*rate_up[nz];
3055 test3 +=
gv.
bin[nd]->chrg[nz]->FracPop*(rate_up[nz]-rate_dn[nz]);
3057 double x1 = fabs(test1-1.);
3058 double x2 = fabs(
safe_div(test3, test2, 0.) );
3059 ASSERT(
MAX2(x1,x2) < 10.*sqrt((
double)
gv.
bin[nd]->nChrg)*DBL_EPSILON );
3085 const double INV_DELTA_E = EVRYD/3.;
3086 const double CS_PDT = 1.2e-17;
3096 gv.
bin[nd]->chrg[nz]->DustZ = Zg;
3099 memset(
gv.
bin[nd]->chrg[nz]->eta, 0, (
LIMELM+2)*
sizeof(
double) );
3100 memset(
gv.
bin[nd]->chrg[nz]->xi, 0, (
LIMELM+2)*
sizeof(
double) );
3103 &
gv.
bin[nd]->chrg[nz]->ThresSurf,&
gv.
bin[nd]->chrg[nz]->ThresSurfVal,
3117 long ipLo =
gv.
bin[nd]->chrg[nz]->ipThresInfVal;
3121 long nfill =
gv.
bin[nd]->chrg[nz]->nfill;
3127 gv.
bin[nd]->chrg[nz]->yhat.reserve( len );
3128 gv.
bin[nd]->chrg[nz]->yhat_primary.reserve( len );
3129 gv.
bin[nd]->chrg[nz]->ehat.reserve( len );
3130 gv.
bin[nd]->chrg[nz]->yhat.alloc( ipLo, nfill );
3131 gv.
bin[nd]->chrg[nz]->yhat_primary.alloc( ipLo, nfill );
3132 gv.
bin[nd]->chrg[nz]->ehat.alloc( ipLo, nfill );
3136 gv.
bin[nd]->chrg[nz]->yhat.realloc( nfill );
3137 gv.
bin[nd]->chrg[nz]->yhat_primary.realloc( nfill );
3138 gv.
bin[nd]->chrg[nz]->ehat.realloc( nfill );
3146 double DustWorkFcn =
gv.
bin[nd]->DustWorkFcn;
3147 double Elo = -
gv.
bin[nd]->chrg[nz]->PotSurf;
3148 double ThresInfVal =
gv.
bin[nd]->chrg[nz]->ThresInfVal;
3149 double Emin =
gv.
bin[nd]->chrg[nz]->Emin;
3150 double Wcorr = ThresInfVal + Emin - GrainPot;
3159 long ipBegin =
max(ipLo,ipStart);
3161 y0b(nd, nz, yzero.
ptr0(), ipBegin, nfill);
3164 avx_ptr<double> Ehi(ipBegin, nfill), Ehi_band(ipBegin, nfill), Eel(ipBegin, nfill);
3166 for(
long i=ipBegin; i < nfill; i++ )
3168 Ehi[i] = anu[i] - ThresInfVal - Emin;
3169 Ehi_band[i] = Ehi[i];
3170 Eel[i] = anu[i] - DustWorkFcn;
3173 avx_ptr<realnum> yp(ipBegin, nfill), ya(ipBegin, nfill), ys(ipBegin, nfill), eyp(ipBegin, nfill),
3174 eya(ipBegin, nfill), eys(ipBegin, nfill), Yp1(ipBegin, nfill), Ys1(ipBegin, nfill),
3175 Ehp(ipBegin, nfill), Ehs(ipBegin, nfill);
3178 Yp1.ptr0(), Ys1.ptr0(), Ehp.ptr0(), Ehs.
ptr0(), ipBegin, nfill);
3180 if( nfill > ipBegin )
3182 memset( ya.data(), 0, size_t((nfill-ipBegin)*
sizeof(ya[ipBegin])) );
3183 memset( eya.data(), 0, size_t((nfill-ipBegin)*
sizeof(eya[ipBegin])) );
3187 for(
long i=ipBegin; i < nfill; i++ )
3190 eyp[i] = Yp1[i]*Ehp[i];
3192 for(
long i=ipBegin; i < nfill; i++ )
3195 eys[i] = Ys1[i]*Ehs[i];
3199 unsigned int nsmax =
gv.
bin[nd]->sd.size();
3200 for(
unsigned int ns=1; ns < nsmax; ns++ )
3202 sptr =
gv.
bin[nd]->sd[ns];
3204 long ipBeginShell =
max(ipBegin, sptr->
ipLo);
3205 double ionPot = sptr->
ionPot;
3206 for(
long i=ipBeginShell; i < nfill; i++ )
3208 Ehi[i] = Ehi_band[i] + Wcorr - ionPot;
3209 Eel[i] = anu[i] - ionPot;
3212 Yfunc(nd, nz, sptr->
y01.
ptr0(), NULL, sptr->
p.
ptr0(), Elo, Ehi.ptr0(), Eel.ptr0(),
3213 Yp1.ptr0(), Ys1.ptr0(), Ehp.ptr0(), Ehs.
ptr0(), ipBeginShell, nfill);
3216 for(
long i=ipBeginShell; i < nfill; i++ )
3219 eyp[i] += Yp1[i]*Ehp[i];
3221 for(
long i=ipBeginShell; i < nfill; i++ )
3224 eys[i] += Ys1[i]*Ehs[i];
3228 long nmax = sptr->
nData;
3229 for(
long n=0; n < nmax; n++ )
3232 double AvNr = sptr->
AvNr[n];
3233 double Ener = sptr->
Ener[n];
3234 double Ehic = Ener - GrainPot;
3236 for(
long i=ipBeginShell; i < nfill; i++ )
3237 max[i] = AvNr*sptr->
p[i];
3239 Yfunc(nd, nz, sptr->
y01A[n].ptr0(), max.
ptr0(), Elo, Ehic, Eelc,
3240 Yp1.ptr0(), Ys1.ptr0(), Ehp.ptr0(), Ehs.
ptr0(), ipBeginShell, nfill);
3243 for(
long i=ipBeginShell; i < nfill; i++ )
3246 eya[i] += Yp1[i]*Ehp[i];
3248 for(
long i=ipBeginShell; i < nfill; i++ )
3251 eys[i] += Ys1[i]*Ehs[i];
3257 for(
long i=ipBegin; i < nfill; i++ )
3259 gv.
bin[nd]->chrg[nz]->yhat[i] = yp[i] + ya[i] + ys[i];
3260 gv.
bin[nd]->chrg[nz]->yhat_primary[i] =
min(yp[i],1.f);
3263 gv.
bin[nd]->chrg[nz]->ehat[i] = (
gv.
bin[nd]->chrg[nz]->yhat[i] > 0.f ) ?
3264 (eyp[i] + eya[i] + eys[i])/
gv.
bin[nd]->chrg[nz]->yhat[i] : 0.f;
3266 ASSERT( yp[i] <= 1.00001f );
3279 ipLo =
gv.
bin[nd]->chrg[nz]->ipThresInf;
3288 gv.
bin[nd]->chrg[nz]->cs_pdt.reserve( len );
3291 double c1 = -CS_PDT*(double)Zg;
3292 double ThresInf =
gv.
bin[nd]->chrg[nz]->ThresInf;
3293 double cnv_GR_pH =
gv.
bin[nd]->cnv_GR_pH;
3297 double x = (anu[i] - ThresInf)*INV_DELTA_E;
3298 double cs = c1*x/
POW2(1.+(1./3.)*
POW2(x));
3301 gv.
bin[nd]->chrg[nz]->cs_pdt[i] =
MAX2(cs,0.)*cnv_GR_pH;
3309 gv.
bin[nd]->chrg[nz]->fac1.reserve( len );
3310 gv.
bin[nd]->chrg[nz]->fac2.reserve( len );
3311 gv.
bin[nd]->chrg[nz]->fac1.alloc( ipLo, nfill );
3312 gv.
bin[nd]->chrg[nz]->fac2.alloc( ipLo, nfill );
3316 gv.
bin[nd]->chrg[nz]->fac1.realloc( nfill );
3317 gv.
bin[nd]->chrg[nz]->fac2.realloc( nfill );
3322 for(
long i=
max(ipLo,ipStart); i < nfill; i++ )
3324 double cs1,cs2,cs_tot,cool1,cool2,ehat1,ehat2;
3327 PE_init(nd,nz,i,&cs1,&cs2,&cs_tot,&cool1,&cool2,&ehat1,&ehat2);
3329 gv.
bin[nd]->chrg[nz]->fac1[i] = cs_tot*anu[i]-cs1*cool1-cs2*cool2;
3330 gv.
bin[nd]->chrg[nz]->fac2[i] = cs1*ehat1 + cs2*ehat2;
3332 ASSERT(
gv.
bin[nd]->chrg[nz]->fac1[i] >= 0. &&
gv.
bin[nd]->chrg[nz]->fac2[i] >= 0. );
3344 gv.
bin[nd]->chrg[nz]->FracPop = -DBL_MAX;
3346 gv.
bin[nd]->chrg[nz]->RSum1 = -DBL_MAX;
3347 gv.
bin[nd]->chrg[nz]->RSum2 = -DBL_MAX;
3348 gv.
bin[nd]->chrg[nz]->ESum1a = -DBL_MAX;
3349 gv.
bin[nd]->chrg[nz]->ESum1b = -DBL_MAX;
3350 gv.
bin[nd]->chrg[nz]->ESum2 = -DBL_MAX;
3352 gv.
bin[nd]->chrg[nz]->tedust = 1.f;
3354 gv.
bin[nd]->chrg[nz]->hcon1 = -DBL_MAX;
3355 gv.
bin[nd]->chrg[nz]->hots1 = -DBL_MAX;
3356 gv.
bin[nd]->chrg[nz]->bolflux1 = -DBL_MAX;
3357 gv.
bin[nd]->chrg[nz]->pe1 = -DBL_MAX;
3359 gv.
bin[nd]->chrg[nz]->BolFlux = -DBL_MAX;
3360 gv.
bin[nd]->chrg[nz]->GrainHeat = -DBL_MAX;
3361 gv.
bin[nd]->chrg[nz]->GrainHeatColl = -DBL_MAX;
3362 gv.
bin[nd]->chrg[nz]->GasHeatPhotoEl = -DBL_MAX;
3363 gv.
bin[nd]->chrg[nz]->GasHeatTherm = -DBL_MAX;
3364 gv.
bin[nd]->chrg[nz]->GrainCoolTherm = -DBL_MAX;
3365 gv.
bin[nd]->chrg[nz]->ChemEnIon = -DBL_MAX;
3366 gv.
bin[nd]->chrg[nz]->ChemEnH2 = -DBL_MAX;
3368 gv.
bin[nd]->chrg[nz]->HeatingRate2 = -DBL_MAX;
3371 ASSERT(
gv.
bin[nd]->chrg[nz]->ipThresInf <=
gv.
bin[nd]->chrg[nz]->ipThresInfVal );
3391 double ThermExp =
gv.
bin[nd]->chrg[nz]->ThresInf*TE1RYD/
gv.
bin[nd]->tedust;
3394 # if defined( WD_TEST2 ) || defined( IGNORE_THERMIONIC )
3395 gv.
bin[nd]->chrg[nz]->ThermRate = 0.;
3422 long Zg =
gv.
bin[nd]->chrg[nz]->DustZ;
3428 else if( pcase ==
PE_SIL )
3432 fprintf(
ioQQQ,
" Yfunc: unknown type for PE effect: %d\n" , pcase );
3438 y2pa( Elo, Ehi, Zg, Ehp, y2pr.ptr0(), ilo, ihi );
3439 y2s( Elo, Ehi, Zg, y2pr.ptr0(), Ehs, y2sec.ptr0(), ilo, ihi );
3443 for(
long i=ilo; i < ihi; ++i )
3444 y01cap[i] =
min(y0[i],maxval[i]);
3448 for(
long i=ilo; i < ihi; ++i )
3449 y01cap[i] =
min(y0[i]*y1[i],maxval[i]);
3452 for(
long i=ilo; i < ihi; ++i )
3458 Yp[i] = y2pr[i]*y01cap[i];
3463 Ys[i] = y2sec[i]*f3*y01cap[i];
3505 long Zg =
gv.
bin[nd]->chrg[nz]->DustZ;
3507 y2pa( Elo, Ehiloc.
ptr0(), Zg, Ehp, y2pr.ptr0(), ilo, ilo+1 );
3509 if( y2pr[ilo] > 0.f )
3511 y2s( Elo, Ehiloc.
ptr0(), Zg, y2pr.ptr0(), Ehs, y2sec.
ptr0(), ilo, ilo+1 );
3513 for(
long i=ilo+1; i < ihi; ++i )
3523 else if( pcase ==
PE_SIL )
3527 fprintf(
ioQQQ,
" Yfunc: unknown type for PE effect: %d\n" , pcase );
3535 for(
long i=ilo; i < ihi; ++i )
3538 Yp[i] = y2pr[ilo]*y01cap;
3539 Ys[i] = y2sec[ilo]*f3*y01cap;
3544 memset( Yp+ilo, 0,
size_t((ihi-ilo)*
sizeof(Yp[ilo])) );
3545 memset( Ys+ilo, 0,
size_t((ihi-ilo)*
sizeof(Ys[ilo])) );
3546 memset( Ehp+ilo, 0,
size_t((ihi-ilo)*
sizeof(Ehp[ilo])) );
3547 memset( Ehs+ilo, 0,
size_t((ihi-ilo)*
sizeof(Ehs[ilo])) );
3565 y0b01( nd, nz, yzero, ilo, ihi );
3568 realnum Ethres_low = 20./EVRYD;
3569 realnum Ethres_high = 50./EVRYD;
3574 long ipr2a =
max(ilo,ip20);
3575 long ipr2b =
min(ip50,ihi);
3576 long ipr3a =
max(ilo,ip50);
3579 y0b01( nd, nz, yzero, ipr1a, ipr2b );
3581 for(
int i=ipr2a; i < ipr2b; i++ )
3583 vlog( arg.ptr0(), val.ptr0(), ipr2a, ipr2b );
3584 for(
int i=ipr2a; i < ipr2b; i++ )
3585 arg[i] =
gv.
bin[nd]->y0b06[i]/yzero[i];
3586 vlog( arg.ptr0(), val2.
ptr0(), ipr2a, ipr2b );
3587 for(
int i=ipr2a; i < ipr2b; i++ )
3589 arg[i] = val2[i]*val[i]*1.0913566679f;
3590 vexp( arg.ptr0(), val.ptr0(), ipr2a, ipr2b );
3591 for(
int i=ipr2a; i < ipr2b; i++ )
3593 for(
int i=ipr3a; i < ipr3b; i++ )
3594 yzero[i] =
gv.
bin[nd]->y0b06[i];
3597 ASSERT( yzero[ilo] >= 0.f );
3598 for(
int i=ilo+1; i < ihi; i++ )
3599 ASSERT( yzero[i] > 0.f );
3617 for(
int i=ilo; i < ihi; i++ )
3622 yzero[i] =
realnum(xv/((1./9.e-3) + (3.7e-2/9.e-3)*xv));
3627 for(
int i=ilo; i < ihi; i++ )
3630 yzero[i] =
realnum(xv/(2.+10.*xv));
3634 fprintf(
ioQQQ,
" y0b01: unknown type for PE effect: %d\n" , pcase );
3658 yzero =
gv.
bin[nd]->sd[ns]->p[i]*leola*(1. - leola*log(1.+1./leola));
3661 double x = 1./leola;
3662 yzero =
gv.
bin[nd]->sd[ns]->p[i]*(((-1./5.*x+1./4.)*x-1./3.)*x+1./2.);
3676 double bf, beta =
gv.
bin[nd]->AvRadius*
gv.
bin[nd]->inv_att_len[i];
3678 bf =
pow2(beta) - 2.*beta + 2. - 2.*exp(-beta);
3680 bf = ((1./60.*beta - 1./12.)*beta + 1./3.)*
pow3(beta);
3684 af =
pow2(alpha) - 2.*alpha + 2. - 2.*exp(-alpha);
3686 af = ((1./60.*alpha - 1./12.)*alpha + 1./3.)*
pow3(alpha);
3688 double yone =
pow2(beta/alpha)*af/bf;
3708 for(
long i=ilo; i < ihi; ++i )
3712 double x = Elo/Ehi[i];
3713 Ehp[i] = 0.5f*
realnum(Ehi[i]*(1.-2.*x)/(1.-3.*x));
3715 y2pr[i] = ( abs(x) > 1e-4 ) ?
3717 ASSERT( Ehp[i] > 0.f && Ehp[i] <=
realnum(Ehi[i]) && y2pr[i] > 0.f && y2pr[i] <= 1.f );
3728 for(
long i=ilo; i < ihi; ++i )
3732 Ehp[i] = 0.5f*
realnum(Elo+Ehi[i]);
3764 memset( arg.data(), 0, size_t((ihi-ilo)*
sizeof(arg[ilo])) );
3765 memset( arg2.data(), 0, size_t((ihi-ilo)*
sizeof(arg2[ilo])) );
3766 memset( lgVecFun.
data(), 0, size_t((ihi-ilo)*
sizeof(lgVecFun[ilo])) );
3767 long iveclo = -1, ivechi = -1;
3770 double sR0 = (1. + yl*yl);
3771 double sqR0 = sqrt(sR0);
3775 double asinh_yl = asinh(yl);
3778 for(
long i=ilo; i < ihi; ++i )
3784 vsqrt(arg2.ptr0(), val2.ptr0(), ilo, ihi);
3786 for(
long i=ilo; i < ihi; ++i )
3788 if( !
gv.
lgWD01 && Ehi[i] > 0. && y2pr[i] > 0.f )
3795 double x2 = x*x, x3 = x2*x, x4 = x3*x, x5 = x4*x;
3796 double yh2 = yh*yh, yh3 = yh2*yh, yh4 = yh3*yh, yh5 = yh4*yh;
3797 double help1 = 2.*x-yh;
3798 double help2 = (6.*x3-15.*yh*x2+12.*yh2*x-3.*yh3)/4.;
3799 double help3 = (22.*x5-95.*yh*x4+164.*yh2*x3-141.*yh3*x2+60.*yh4*x-10.*yh5)/16.;
3800 N0[i] = yh*(help1 - help2 + help3)/x2;
3802 help1 = (3.*x-yh)/3.;
3803 help2 = (15.*x3-25.*yh*x2+15.*yh2*x-3.*yh3)/20.;
3804 help3 = (1155.*x5-3325.*yh*x4+4305.*yh2*x3-2961.*yh3*x2+1050.*yh4*x-150.*yh5)/
3806 E0[i] =
ETILDE*yh2*(help1 - help2 + help3)/x2;
3810 double sqRh = val2[i];
3811 alpha[i] = sqRh/(sqRh - 1.);
3812 if( yh/sqR0 < 0.01 )
3815 double z = yh*(yh - 2.*yl)/sR0;
3816 N0[i] = ((((7./256.*z-5./128.)*z+1./16.)*z-1./8.)*z+1./2.)*z/(sqRh-1.);
3818 double yl2 = yl*yl, yl3 = yl2*yl, yl4 = yl3*yl;
3819 double help1 = yl/2.;
3820 double help2 = (2.*yl2-1.)/3.;
3821 double help3 = (6.*yl3-9.*yl)/8.;
3822 double help4 = (8.*yl4-24.*yl2+3.)/10.;
3824 E0[i] = -alpha[i]*Ehi[i]*(((help4*h+help3)*h+help2)*h+help1)*h/sqR0;
3828 N0[i] = alpha[i]*(1./sqR0 - 1./sqRh);
3834 E0[i] = alpha[i]*
ETILDE*(asinh_yl - yh/sqRh);
3837 ASSERT( N0[i] > 0. && N0[i] <= 1. );
3842 for(
long i=ilo; i < ihi; ++i )
3844 if( !
gv.
lgWD01 && Ehi[i] > 0. && y2pr[i] > 0.f )
3847 E0[i] += alpha[i]*
ETILDE*val[i];
3848 Ehs[i] =
realnum(E0[i]/N0[i]);
3861 for(
long i=ilo; i < ihi; ++i )
3867 vsqrt(arg2.ptr0(), val2.ptr0(), ilo, ihi);
3869 for(
long i=ilo; i < ihi; ++i )
3871 if( !
gv.
lgWD01 && Ehi[i] > Elo && y2pr[i] > 0.f )
3878 double sqRh = val2[i];
3879 alpha[i] = sqRh/(sqRh - 1.);
3890 Ehs[i] =
realnum(Ehi[i] - (Ehi[i]-Elo)*((-37./840.*x2 + 1./10.)*x2 + 1./3.));
3896 for(
long i=ilo; i < ihi; ++i )
3898 if( !
gv.
lgWD01 && Ehi[i] > Elo && y2pr[i] > 0.f )
3920 long Zg =
gv.
bin[nd]->chrg[nz]->DustZ;
3922 double d[5], phi_s_up[
LIMELM+1], phi_s_dn[2];
3923 phi_s_up[0] =
gv.
bin[nd]->chrg[nz]->ThresSurf;
3924 for(
long i=1; i <=
LIMELM; i++ )
3926 phi_s_dn[0] =
gv.
bin[nd]->chrg[nz]->ThresSurfInc;
3930 for(
long nelem=0; nelem <
LIMELM; nelem++ )
3934 for(
long ion=0; ion <= nelem+1; ion++ )
3937 &
gv.
bin[nd]->chrg[nz]->RecomZ0[nelem][ion],
3938 &
gv.
bin[nd]->chrg[nz]->RecomEn[nelem][ion],
3939 &
gv.
bin[nd]->chrg[nz]->ChemEn[nelem][ion]);
3949 double *ThresInfVal,
3951 double *ThresSurfVal,
3954 bool lgUseTunnelCorr)
3962 double dZg = (double)Zg;
3969 double IP_v =
gv.
bin[nd]->DustWorkFcn + dstpot - 0.5*
one_elec(nd) +
3991 fprintf(
ioQQQ,
" GetPotValues detected unknown type for ionization pot: %d\n" , pcase );
3997 IP_v =
MAX2(IP,IP_v);
4002 double help = fabs(dZg+1);
4005 if( lgUseTunnelCorr )
4008 *Emin *= 1. - 2.124e-4/(pow(
gv.
bin[nd]->AvRadius,(
realnum)0.45)*pow(help,0.26));
4016 *ThresInf = IP - *Emin;
4017 *ThresInfVal = IP_v - *Emin;
4018 *ThresSurf = *ThresInf;
4019 *ThresSurfVal = *ThresInfVal;
4025 *ThresInfVal = IP_v;
4026 *ThresSurf = *ThresInf - dstpot;
4027 *ThresSurfVal = *ThresInfVal - dstpot;
4042 const double phi_s_up[],
4043 const double phi_s_dn[],
4057 long Zg =
gv.
bin[nd]->chrg[nz]->DustZ;
4058 double phi_s = phi_s_up[0];
4066 *ChemEn -= (
realnum)(phi_s - phi_s_up[0]);
4069 phi_s = phi_s_up[save-ion];
4074 else if( ion <= nelem &&
gv.
bin[nd]->chrg[nz]->DustZ >
gv.
bin[nd]->LowestZg &&
4080 long Zg =
gv.
bin[nd]->chrg[nz]->DustZ;
4081 double phi_s = phi_s_dn[0];
4089 *ChemEn += (
realnum)(phi_s - phi_s_dn[0]);
4095 phi_s = phi_s_dn[ion-
save];
4099 }
while( ion <= nelem && Zg >
gv.
bin[nd]->LowestZg &&
4122 # ifndef IGNORE_GRAIN_ION_COLLISIONS
4124 for(
long nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
4127 double fac1 = gptr->
FracPop*fac0;
4132 for(
long ion=0; ion <=
LIMELM; ion++ )
4139 double fac2 = eta*fac1;
4144 for(
long nelem=
MAX2(0,ion-1); nelem <
LIMELM; nelem++ )
4165 for(
long nelem=0; nelem <
LIMELM; nelem++ )
4171 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
4179 gv.
bin[nd]->cnv_CM3_pH = 1./
gv.
bin[nd]->cnv_H_pCM3;
4181 gv.
bin[nd]->cnv_CM3_pGR =
gv.
bin[nd]->cnv_H_pGR/
gv.
bin[nd]->cnv_H_pCM3;
4182 gv.
bin[nd]->cnv_GR_pCM3 = 1./
gv.
bin[nd]->cnv_CM3_pGR;
4187 for(
long nelem=0; nelem <
LIMELM; nelem++ )
4207 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
4209 double dstAbund =
gv.
bin[nd]->dstAbund;
4227 for(
long nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
4230 if( gptr->
DustZ <= -1 )
4232 double FracAbund = gptr->
FracPop*dstAbund;
4263 fprintf(
ioQQQ,
" GrainTemperature starts for grain %s\n",
gv.
bin[nd]->chDstLab );
4280 gv.
bin[nd]->GasHeatPhotoEl = 0.;
4282 gv.
bin[nd]->GrainCoolTherm = 0.;
4283 gv.
bin[nd]->thermionic = 0.;
4288 gv.
bin[nd]->BolFlux = 0.;
4292 for(
long nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
4297 bool lgReEvaluate1 = gptr->
hcon1 < 0.;
4298 bool lgReEvaluate2 = gptr->
hots1 < 0.;
4303 double hcon1, hots1, pe1, bolflux1, hla1;
4308 gptr->
hcon1 = hcon1;
4312 hcon1 = gptr->
hcon1;
4325 if( gptr->
DustZ <= -1 )
4331 gptr->
hots1 = hots1;
4337 hots1 = gptr->
hots1;
4360 ASSERT( hcon1 >= 0. && hots1 >= 0. && hla1 >= 0. && bolflux1 >= 0. && pe1 >= 0. );
4373 gptr->
FracPop*bolflux1*EN1RYD*
gv.
bin[nd]->cnv_H_pCM3 );
4385 double EhatThermionic = 2.*BOLTZMANN*
gv.
bin[nd]->tedust +
MAX2(gptr->
PotSurf*EN1RYD,0.);
4386 gv.
bin[nd]->GrainCoolTherm += rate * (EhatThermionic + gptr->
ThresSurf*EN1RYD);
4387 gv.
bin[nd]->thermionic += rate * (EhatThermionic - gptr->
PotSurf*EN1RYD);
4391 double norm = EN1RYD*
gv.
bin[nd]->cnv_H_pCM3;
4402 gv.
bin[nd]->BolFlux *= norm;
4413 gv.
bin[nd]->GasHeatPhotoEl *= norm;
4444 gv.
bin[nd]->GrainHeat = *hcon + *hots + dcheat -
gv.
bin[nd]->GrainCoolTherm;
4447 gv.
bin[nd]->GrainHeatColl = dcheat;
4453 if(
gv.
bin[nd]->GrainHeat > 0. )
4458 double y, x = log(
MAX2(DBL_MIN,
gv.
bin[nd]->GrainHeat*
gv.
bin[nd]->cnv_CM3_pH));
4465 gv.
bin[nd]->GrainHeat = -1.;
4466 gv.
bin[nd]->tedust = -1.;
4475 double y, x = log(
gv.
bin[nd]->tedust);
4477 gv.
bin[nd]->GrainHeat = exp(y)*
gv.
bin[nd]->cnv_H_pCM3;
4485 fprintf(
ioQQQ,
" >GrainTemperature finds %s Tdst %.5e hcon %.4e ",
4486 gv.
bin[nd]->chDstLab,
gv.
bin[nd]->tedust, *hcon);
4487 fprintf(
ioQQQ,
"hots %.4e dcheat %.4e GrainCoolTherm %.4e\n",
4488 *hots, dcheat,
gv.
bin[nd]->GrainCoolTherm );
4523 *cs1 =
gv.
bin[nd]->dstab1[i]*gptr->
yhat[i];
4526 *ehat1 = gptr->
ehat[i];
4547 if( gptr->
DustZ <= -1 )
4562 if( gptr->
DustZ <= -1 && i >= ipLo2 )
4571 ASSERT( *ehat2 >= 0. && *cool2 > 0. );
4580 *cs_tot =
gv.
bin[nd]->dstab1[i] + *cs2;
4594 double Accommodation,
4595 CollisionRateElectr,
4622 const double H2_FORMATION_GRAIN_HEATING[
H2_TOP] = { 0.20, 0.4, 1.72 };
4642 gv.
bin[nd]->ChemEn = 0.;
4645 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
4653 double ChemEn1 = 0.;
4659 for( ion=0; ion <=
LIMELM; ion++ )
4668 CollisionRateIon = 0.;
4670 CoolPotentialGas = 0.;
4671 HeatRecombination = 0.;
4678 for( nelem=
MAX2(0,ion-1); nelem <
LIMELM; nelem++ )
4682 double CollisionRateOne;
4687 #if defined( IGNORE_GRAIN_ION_COLLISIONS )
4689 #elif defined( WD_TEST2 )
4690 Stick = ( ion == gptr->
RecomZ0[nelem][ion] ) ?
4693 Stick = ( ion == gptr->
RecomZ0[nelem][ion] ) ?
4701 CollisionRateIon += CollisionRateOne;
4710 if( ion >= gptr->
RecomZ0[nelem][ion] )
4712 CoolPotential += CollisionRateOne * (double)ion *
4714 CoolPotentialGas += CollisionRateOne *
4715 (
double)gptr->
RecomZ0[nelem][ion] *
4720 CoolPotential += CollisionRateOne * (double)ion *
4722 CoolPotentialGas += CollisionRateOne *
4723 (
double)gptr->
RecomZ0[nelem][ion] *
4730 HeatRecombination += CollisionRateOne *
4732 HeatChem += CollisionRateOne * gptr->
ChemEn[nelem][ion];
4741 HeatCollisions = CollisionRateIon * 2.*BOLTZMANN*
phycon.
te*xi;
4746 CoolPotential *= eta*EN1RYD;
4747 CoolPotentialGas *= eta*EN1RYD;
4749 HeatRecombination *= eta*EN1RYD;
4750 HeatChem *= eta*EN1RYD;
4752 CoolEmitted = CollisionRateIon * 2.*BOLTZMANN*
gv.
bin[nd]->tedust*eta;
4755 Heat1 += HeatCollisions - CoolPotential + HeatRecombination - CoolEmitted;
4760 Cool1 += HeatCollisions - CoolEmitted - CoolPotentialGas;
4762 ChemEn1 += HeatChem;
4766 HeatIons += gptr->
FracPop*Heat1;
4779 Stick = ( gptr->
DustZ <= -1 ) ?
gv.
bin[nd]->StickElecNeg :
gv.
bin[nd]->StickElecPos;
4782 ve = sqrt(8.*BOLTZMANN/PI/ELECTRON_MASS*
phycon.
te);
4785 CollisionRateElectr = Stick*
dense.
eden*ve;
4793 HeatCollisions = CollisionRateElectr*2.*BOLTZMANN*
phycon.
te*xi;
4796 CoolPotential = CollisionRateElectr * (double)ion*gptr->
PotSurfInc*eta*EN1RYD;
4798 HeatRecombination = CollisionRateElectr * gptr->
ThresSurfInc*eta*EN1RYD;
4804 HeatCollisions = 0.;
4806 HeatRecombination = 0.;
4811 HeatBounce = CollisionRateElectr * 2.*BOLTZMANN*
phycon.
te*xi;
4814 CoolBounce = CollisionRateElectr *
4816 CoolBounce =
MAX2(CoolBounce,0.);
4821 HeatElectrons = HeatCollisions-CoolPotential+HeatRecombination+HeatBounce-CoolBounce;
4822 Heat1 += HeatElectrons;
4824 CoolElectrons = HeatCollisions+HeatBounce-CoolBounce;
4825 Cool1 += CoolElectrons;
4846 gv.
bin[nd]->GrainCoolTherm*
gv.
bin[nd]->cnv_CM3_pH;
4852 HeatTot += gptr->
FracPop*Heat1;
4855 CoolTot += gptr->
FracPop*Cool1;
4868 Accommodation = 2.*
gv.
bin[nd]->atomWeight*WeightMol/
POW2(
gv.
bin[nd]->atomWeight+WeightMol);
4870 #ifndef IGNORE_GRAIN_ION_COLLISIONS
4873 sqrt(8.*BOLTZMANN/PI/ATOMIC_MASS_UNIT/WeightMol*
phycon.
te);
4880 H2_FORMATION_GRAIN_HEATING[
ipH2]*EN1EV;
4882 gv.
bin[nd]->ChemEnH2 /=
gv.
bin[nd]->IntArea/4.*
gv.
bin[nd]->cnv_H_pCM3;
4884 CollisionRateMol = 0.;
4885 gv.
bin[nd]->ChemEnH2 = 0.;
4890 Accommodation = 2.*
gv.
bin[nd]->atomWeight*WeightMol/
POW2(
gv.
bin[nd]->atomWeight+WeightMol);
4891 #ifndef IGNORE_GRAIN_ION_COLLISIONS
4893 sqrt(8.*BOLTZMANN/PI/ATOMIC_MASS_UNIT/WeightMol*
phycon.
te);
4895 CollisionRateMol = 0.;
4899 HeatCollisions = CollisionRateMol * 2.*BOLTZMANN*
phycon.
te;
4900 CoolEmitted = CollisionRateMol * 2.*BOLTZMANN*
gv.
bin[nd]->tedust;
4902 HeatMolecules = HeatCollisions - CoolEmitted +
gv.
bin[nd]->ChemEnH2;
4903 HeatTot += HeatMolecules;
4906 CoolMolecules = HeatCollisions - CoolEmitted;
4907 CoolTot += CoolMolecules;
4909 gv.
bin[nd]->RateUp = 0.;
4910 gv.
bin[nd]->RateDn = 0.;
4912 for( nz=0; nz <
gv.
bin[nd]->nChrg; nz++ )
4918 gv.
bin[nd]->RateUp +=
gv.
bin[nd]->chrg[nz]->FracPop*rate_up;
4919 gv.
bin[nd]->RateDn +=
gv.
bin[nd]->chrg[nz]->FracPop*rate_dn;
4922 HeatCor += (
gv.
bin[nd]->chrg[nz]->FracPop*rate_up*
gv.
bin[nd]->chrg[nz]->ThresSurf -
4923 gv.
bin[nd]->chrg[nz]->FracPop*rate_dn*
gv.
bin[nd]->chrg[nz]->ThresSurfInc +
4924 gv.
bin[nd]->chrg[nz]->FracPop*rate_up*
gv.
bin[nd]->chrg[nz]->PotSurf -
4925 gv.
bin[nd]->chrg[nz]->FracPop*rate_dn*
gv.
bin[nd]->chrg[nz]->PotSurfInc)*EN1RYD;
4933 fprintf(
ioQQQ,
" molecules heat/cool: %.4e %.4e heatcor: %.4e\n",
4934 HeatMolecules*
gv.
bin[nd]->IntArea/4.*
gv.
bin[nd]->cnv_H_pCM3,
4935 CoolMolecules*
gv.
bin[nd]->IntArea/4.*
gv.
bin[nd]->cnv_H_pCM3,
4936 HeatCor*
gv.
bin[nd]->IntArea/4.*
gv.
bin[nd]->cnv_H_pCM3 );
4943 gv.
bin[nd]->ChemEnH2 *=
gv.
bin[nd]->IntArea/4.*
gv.
bin[nd]->cnv_H_pCM3;
4960 gv.
bin[nd]->HeatingRate1 = (HeatMolecules+HeatIons+HeatCor)*
gv.
bin[nd]->IntArea/4.;
4995 for(
size_t nd=0; nd <
gv.
bin.size(); nd++ )
5002 dmomen += help[i]*(
gv.
bin[nd]->dstab1[i] +
gv.
bin[nd]->pure_sc1[i]*
gv.
bin[nd]->asym[i]);
5005 dmomen *= EN1RYD*4./
gv.
bin[nd]->IntArea;
5023 phi2lm =
POW2(psi)*alam;
5026 for( loop = 0; loop < 50 && fabs(corr-1.) > 0.001; loop++ )
5028 vdold =
gv.
bin[nd]->DustDftVel;
5032 g0 = 1.5045*si*sqrt(1.+0.4418*si*si);
5033 g2 = si/(1.329 +
POW3(si));
5041 g0 = 1.5045*si*sqrt(1.+0.4418*si*si);
5042 g2 = si/(1.329 +
POW3(si));
5043 fdrag += fac*
dense.
eden*(g0 + phi2lm*g2);
5047 g0 = 1.5045*si*sqrt(1.+0.4418*si*si);
5052 g0 = 1.5045*si*sqrt(1.+0.4418*si*si);
5053 g2 = si/(1.329 +
POW3(si));
5059 volmom = dmomen/SPEEDLIGHT;
5063 corr = sqrt(volmom/fdrag);
5070 gv.
bin[nd]->DustDftVel = 0.;
5075 fprintf(
ioQQQ,
" %2ld new drift velocity:%10.2e momentum absorbed:%10.2e\n",
5076 loop,
gv.
bin[nd]->DustDftVel, volmom );
5096 if( nd >=
gv.
bin.size() )
5098 fprintf(
ioQQQ,
"invalid parameter for GrnVryDpth\n" );
5117 return max(1.e-10,GrnVryDpth_v);
STATIC double GrainElecRecomb1(size_t, long, double *, double *)
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
static const double ETILDE
STATIC void UpdatePot(size_t, long, long, double[], double[])
double rate_h2_form_grains_used
const int FILENAME_PATH_LENGTH_2
flex_arr< double > cs_pdt
STATIC double PlanckIntegral(double, size_t, long)
NORETURN void TotalInsanity(void)
double widflx(size_t i) const
STATIC void GrainIonColl(size_t, long, long, long, const double[], const double[], long *, realnum *, realnum *)
void vfast_asinh(const double x[], double y[], long nlo, long nhi)
STATIC void GetPotValues(size_t, long, double *, double *, double *, double *, double *, double *, bool)
STATIC void GrainChargeTemp()
static const bool NO_TUNNEL
long int IonHigh[LIMELM+1]
AEInfo * AugerData[LIMELM]
double pot2chrg(double x, long nd)
vector< realnum > inv_att_len
STATIC void GrainChrgTransferRates(long)
STATIC void Yfunc(long, long, const realnum[], const realnum[], const realnum[], double, const double[], const double[], realnum[], realnum[], realnum[], realnum[], long, long)
STATIC void InitEmissivities()
flex_arr< realnum > yhat_primary
const char * strstr_s(const char *haystack, const char *needle)
pe_type which_pe[MAT_TOP]
STATIC void y0b01(size_t, long, realnum[], long, long)
sys_float sexp(sys_float x)
double fudge(long int ipnt)
realnum elmSumAbund[LIMELM]
molezone * findspecieslocal(const char buf[])
static const double THERMCONST
void vlog(const double x[], double y[], long nlo, long nhi)
double anu(size_t i) const
vector< vector< double > > AvNumber
STATIC void UpdateRecomZ0(size_t, long)
double elec_esc_length(double e, long nd)
void splint(const double xa[], const double ya[], const double y2a[], long int n, double x, double *y)
vector< realnum > GraphiteEmission
H2_type which_H2distr[MAT_TOP]
t_elementnames elementnames
t_iso_sp iso_sp[NISO][LIMELM]
void vexp(const double x[], double y[], long nlo, long nhi)
long int nflux_with_check
static long int nCalledGrainDrive
double xIonDense[LIMELM][LIMELM+1]
vector< vector< double > > Energy
static const long T_LOOP_MAX
const double * anuptr() const
vector< double > dstab1_x_anu
bool fp_equal(sys_float x, sys_float y, int n=3)
STATIC double y0psa(size_t, long, long, double)
size_t ipointC(double anu) const
long ipoint(double energy_ryd)
realnum dstAbundThresholdNear
void spline(const double x[], const double y[], long int n, double yp1, double ypn, double y2a[])
void y2pa(double, const double[], long, realnum[], realnum[], long, long)
long int IonLow[LIMELM+1]
double chrg2pot(double x, long nd)
long int nsShells[LIMELM][LIMELM]
const bool ENABLE_QUANTUM_HEATING
vector< realnum > GrainEmission
strg_type which_strg[MAT_TOP]
pot_type which_pot[MAT_TOP]
realnum dstAbundThresholdFar
STATIC void GrainTemperature(size_t, realnum *, double *, double *, double *)
enth_type which_enth[MAT_TOP]
static const long MAGIC_AUGER_DATA
STATIC void GrainCollHeating(size_t, realnum *, realnum *)
static const double TOLER
STATIC void GrainUpdateRadius1()
STATIC void UpdatePot2(size_t, long)
double rate_h2_form_grains_CT02
double powi(double, long int)
STATIC void InitBinAugerData(size_t, long, long)
STATIC void GrainScreen(long, size_t, long, double *, double *)
double rate_h2_form_grains_ELRD
STATIC void GetFracPop(size_t, long, double[], double[], long *)
sys_float safe_div(sys_float x, sys_float y, sys_float res_0by0)
static const bool INCL_TUNNEL
realnum GetAveVelocity(realnum massAMU)
double anu3(size_t i) const
realnum HeatCoolRelErrorAllowed
void ConvFail(const char chMode[], const char chDetail[])
double rate_h2_form_grains_HM79
double heating(long nelem, long ion)
static const long CT_LOOP_MAX
TransitionProxy trans(const long ipHi, const long ipLo)
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
STATIC void ReadAugerData()
void setHeating(long nelem, long ion, double heating)
realnum gas_phase[LIMELM]
STATIC double ThetaNu(double)
realnum AtomicWeight[LIMELM]
ial_type which_ial[MAT_TOP]
static const double STICK_ELEC
vector< flex_arr< realnum > > y01A
double reduce_ab(const double *a, const double *b, long ilo, long ihi)
STATIC void NewChargeData(long)
void y2s(double, const double[], long, const realnum[], realnum[], realnum[], long, long)
zmin_type which_zmin[MAT_TOP]
double reduce_ab_a(const double *a, const double *b, long ilo, long ihi, double *sum_a)
realnum ChemEn[LIMELM][LIMELM+1]
void vsqrt(const double x[], double y[], long nlo, long nhi)
void realloc(size_type end)
vector< double > pure_sc1
STATIC void GrainUpdateRadius2()
STATIC void y0b(size_t, long, realnum[], long, long)
#define DEBUG_ENTRY(funcname)
double powpq(double x, int p, int q)
STATIC double GrnVryDpth(size_t)
static const long BRACKET_MAX
realnum RecomEn[LIMELM][LIMELM+1]
realnum GrainHeatScaleFactor
long RecomZ0[LIMELM][LIMELM+1]
vector< double > IonThres
STATIC void GetNextLine(const char *, FILE *, char[])
void splint_safe(const double xa[], const double ya[], const double y2a[], long int n, double x, double *y, bool *lgOutOfBounds)
double reduce_abc(const double *a, const double *b, const double *c, long ilo, long ihi)
size_t ithreshC(double threshold) const
STATIC double GrnStdDpth(long)
realnum UV_Cont_rel2_Habing_TH85_depth
int fprintf(const Output &stream, const char *format,...)
static const double INV_ETILDE
sys_float SDIV(sys_float x)
void setConvIonizFail(const char *reason, double oldval, double newval)
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
STATIC double y1psa(size_t, long, double)
STATIC double GrainElecEmis1(size_t, long, double *, double *, double *, double *)
vector< unsigned int > nData
char chElementName[LIMELM][CHARS_ELEMENT_NAME]
vector< realnum > SilicateEmission
STATIC void GrainCharge(size_t, double *)
vector< string > ReadRecord
STATIC void UpdatePot1(size_t, long, long, long)
STATIC void PE_init(size_t, long, long, double *, double *, double *, double *, double *, double *, double *)
void SetNChrgStates(long nChrg)
realnum GrainChTrRate[LIMELM][LIMELM+1][LIMELM+1]
bool lgPAHsInIonizedRegion
double phfit(long int nz, long int ne, long int is, double e)
long int ipHeavy[LIMELM][LIMELM]
static double HEAT_TOLER_BIN
static const double STICK_ION