52 static const int NSD = 7;
140 for(
int j=0; j <
NAX; j++ )
147 for(
int j=0; j <
NDAT; j++ )
152 vector< complex<double> >
n[
NAX];
208 double*,
double*,
double*,
int*),
209 double*,
double*,
double*,
int*);
212 double*,
double*,
double*,
int*),
213 double*,
double*,
const double[],
double*,
214 double*,
double*,
int*);
219 double*,
double*,
double*,
int*);
232 inline double Drude(
double,
double,
double,
double);
238 STATIC void mie_repair(
const char*,
long,
int,
int,
const double[],
double[],vector<int>&,
241 long,
long,
int,
bool,
bool*);
244 STATIC void init_eps(
double,
long,
const vector<grain_data>&,vector< complex<double> >&);
246 void(*)(complex<double>,
const vector<double>&,
const vector< complex<double> >&,
247 long,complex<double>*,
double*,
double*),
248 const vector<double>&,
const vector< complex<double> >&,
long,complex<double>,
double);
249 STATIC void Stognienko(complex<double>,
const vector<double>&,
const vector< complex<double> >&,
250 long,complex<double>*,
double*,
double*);
251 STATIC void Bruggeman(complex<double>,
const vector<double>&,
const vector< complex<double> >&,
252 long,complex<double>*,
double*,
double*);
266 STATIC void sinpar(
double,
double,
double,
double*,
double*,
double*,
267 double*,
double*,
long*);
268 STATIC void anomal(
double,
double*,
double*,
double*,
double*,
double,
double);
269 STATIC void bigk(complex<double>,complex<double>*);
275 const char *szd_file,
304 const long NPTS_TABLE = 100L;
316 fprintf(
ioQQQ,
" The number should be between 1 and 99.\n" );
321 vector<grain_data> gdArr(2);
325 string rfi_string ( rfi_file );
326 if( rfi_string.find(
".rfi" ) != string::npos )
330 else if( rfi_string.find(
".mix" ) != string::npos )
336 fprintf(
ioQQQ,
" Refractive index file name %s has wrong extention\n", rfi_file );
337 fprintf(
ioQQQ,
" It should have extention .rfi or .mix.\n" );
344 fprintf(
ioQQQ,
" The number should always be 1 for OPC_TABLE files.\n" );
349 fprintf(
ioQQQ,
" Illegal value for the specific density: %.4e\n", gd.
rho );
361 strcpy(chFile,rfi_file);
367 strcpy(chFile2,szd_file);
375 sprintf(ext,
"%02ld",nbin);
376 strcat(strcat(strcat(strcat(strcat(chFile,
"_"),chFile2),
"_"),ext),
".opc");
380 strcat(strcat(strcat(chFile,
"_"),chFile2),
".opc");
395 fprintf(
ioQQQ,
"\n Starting mie_write_opc, output will be written to %s\n\n", chFile );
401 lgErr = lgErr || (
fprintf(fdes,
"# this file was created by Cloudy %s (%s) on %s",
403 lgErr = lgErr || (
fprintf(fdes,
"# ===========================================\n#\n") < 0 );
404 lgErr = lgErr || (
fprintf(fdes,
"%12ld # magic number opacity file\n",
MAGIC_OPC) < 0 );
405 lgErr = lgErr || (
fprintf(fdes,
"%12ld # magic number rfi/mix file\n",gd.
magic) < 0 );
406 lgErr = lgErr || (
fprintf(fdes,
"%12ld # magic number szd file\n",sd.
magic) < 0 );
410 strncpy(hlp1,chFile,(
size_t)(
LABELSUB1+1));
417 strncpy(hlp2,chFile2,(
size_t)(
LABELSUB2+1));
424 strcpy(chGrainLabel,
" ");
429 strcat(strcat(strcat(strcat(chGrainLabel,hlp1),
"-"),hlp2),
"xx");
430 lgErr = lgErr || (
fprintf(fdes,
"%-12.12s # grain type label, xx will be replaced by bin no.\n",
435 strcat(strcat(strcat(chGrainLabel,hlp1),
"-"),hlp2);
436 lgErr = lgErr || (
fprintf(fdes,
"%-12.12s # grain type label\n", chGrainLabel) < 0 );
439 lgErr = lgErr || (
fprintf(fdes,
"%.6e # specific weight (g/cm^3)\n",gd.
rho) < 0 );
440 lgErr = lgErr || (
fprintf(fdes,
"%.6e # molecular weight of grain molecule (amu)\n",gd.
mol_weight) < 0 );
441 lgErr = lgErr || (
fprintf(fdes,
"%.6e # average molecular weight per atom (amu)\n", gd.
atom_weight) < 0 );
442 lgErr = lgErr || (
fprintf(fdes,
"%.6e # abundance of grain molecule at max depletion\n",gd.
abun) < 0 );
443 lgErr = lgErr || (
fprintf(fdes,
"%.6e # depletion efficiency\n",gd.
depl) < 0 );
444 lgErr = lgErr || (
fprintf(fdes,
"%.6e # average grain radius <a^3>/<a^2>, full size distr (cm)\n",
446 lgErr = lgErr || (
fprintf(fdes,
"%.6e # average grain surface area <4pi*a^2>, full size distr (cm^2)\n",
448 lgErr = lgErr || (
fprintf(fdes,
"%.6e # average grain volume <4/3pi*a^3>, full size distr (cm^3)\n",
450 lgErr = lgErr || (
fprintf(fdes,
"%.6e # total grain radius Int(a) per H, full size distr (cm/H)\n",
452 lgErr = lgErr || (
fprintf(fdes,
"%.6e # total grain area Int(4pi*a^2) per H, full size distr (cm^2/H)\n",
454 lgErr = lgErr || (
fprintf(fdes,
"%.6e # total grain vol Int(4/3pi*a^3) per H, full size distr (cm^3/H)\n",
456 lgErr = lgErr || (
fprintf(fdes,
"%.6e # work function (Ryd)\n",gd.
work) < 0 );
457 lgErr = lgErr || (
fprintf(fdes,
"%.6e # gap between valence and conduction band (Ryd)\n",gd.
bandgap) < 0 );
458 lgErr = lgErr || (
fprintf(fdes,
"%.6e # efficiency of thermionic emission\n",gd.
therm_eff) < 0 );
459 lgErr = lgErr || (
fprintf(fdes,
"%.6e # sublimation temperature (K)\n",gd.
subl_temp) < 0 );
460 lgErr = lgErr || (
fprintf(fdes,
"%12d # material type, 1=carbonaceous, 2=silicate\n",gd.
matType) < 0 );
461 lgErr = lgErr || (
fprintf(fdes,
"#\n# abundances of constituent elements rel. to hydrogen\n#\n") < 0 );
463 for( nelem=0; nelem <
LIMELM; nelem++ )
471 lgErr = lgErr || (
fprintf(fdes,
"#\n# entire size distribution, amin=%.5f amax=%.5f micron\n",
473 lgErr = lgErr || (
fprintf(fdes,
"#\n%.6e # ratio a_max/a_min in each size bin\n",
475 lgErr = lgErr || (
fprintf(fdes,
"#\n# size distribution function\n#\n") < 0 );
476 lgErr = lgErr || (
fprintf(fdes,
"%12ld # number of table entries\n#\n",NPTS_TABLE+1) < 0 );
477 lgErr = lgErr || (
fprintf(fdes,
"# ============================\n") < 0 );
478 lgErr = lgErr || (
fprintf(fdes,
"# size (micr) a^4*dN/da (cm^3/H)\n#\n") < 0 );
479 for( i=0; i <= NPTS_TABLE; i++ )
485 lgErr = lgErr || (
fprintf(fdes,
"%.6e %.6e\n",radius,a4dNda) < 0 );
490 lgErr = lgErr || (
fprintf(fdes,
"#\n") < 0 );
491 lgErr = lgErr || (
fprintf(fdes,
"%.6e # a_max/a_min = 1 for single sized grain\n", 1. ) < 0 );
492 lgErr = lgErr || (
fprintf(fdes,
"%12ld # no size distribution table\n",0L) < 0 );
500 lgErr = lgErr || (
fprintf(fdes,
"#\n") < 0 );
504 lgErr = lgErr || (
fprintf(fdes,
"%23.8x %8.8x # check 2\n",u.i[0],u.i[1]) < 0 );
506 lgErr = lgErr || (
fprintf(fdes,
"%23.8x %8.8x # check 2\n",u.i[1],u.i[0]) < 0 );
509 lgErr = lgErr || (
fprintf(fdes,
"%23.8x %8.8x # check 3\n",u.i[0],u.i[1]) < 0 );
511 lgErr = lgErr || (
fprintf(fdes,
"%23.8x %8.8x # check 3\n",u.i[1],u.i[0]) < 0 );
514 lgErr = lgErr || (
fprintf(fdes,
"%23.8x %8.8x # check 4\n",u.i[0],u.i[1]) < 0 );
516 lgErr = lgErr || (
fprintf(fdes,
"%23.8x %8.8x # check 4\n",u.i[1],u.i[0]) < 0 );
518 lgErr = lgErr || (
fprintf(fdes,
"%32ld # number of size distr. bins\n#\n",sd.
nPart) < 0 );
534 for( p=0; p < sd.
nPart; p++ )
548 volfrac = sd.
vol*frac/volnorm;
549 fprintf(
ioQQQ,
" Starting size bin %ld, amin=%.5f amax=%.5f micron\n",
551 lgErr = lgErr || (
fprintf(fdes,
"# size bin %ld, amin=%.5f amax=%.5f micron\n",
553 lgErr = lgErr || (
fprintf(fdes,
"%.6e # average grain ",3.*sd.
vol/sd.
area) < 0 );
554 lgErr = lgErr || (
fprintf(fdes,
"radius <a^3>/<a^2>, this bin (cm)\n") < 0 );
555 lgErr = lgErr || (
fprintf(fdes,
"%.6e # average ",sd.
area) < 0 );
556 lgErr = lgErr || (
fprintf(fdes,
"grain area <4pi*a^2>, this bin (cm^2)\n") < 0 );
557 lgErr = lgErr || (
fprintf(fdes,
"%.6e # average ",sd.
vol) < 0 );
558 lgErr = lgErr || (
fprintf(fdes,
"grain volume <4/3pi*a^3>, this bin (cm^3)\n") < 0 );
559 lgErr = lgErr || (
fprintf(fdes,
"%.6e # total grain ",sd.
radius*frac/gd.
norm) < 0 );
560 lgErr = lgErr || (
fprintf(fdes,
"radius Int(a) per H, this bin (cm/H)\n") < 0 );
561 lgErr = lgErr || (
fprintf(fdes,
"%.6e # total grain area ",sd.
area*frac/gd.
norm) < 0 );
562 lgErr = lgErr || (
fprintf(fdes,
"Int(4pi*a^2) per H, this bin (cm^2/H)\n") < 0 );
563 lgErr = lgErr || (
fprintf(fdes,
"%.6e # total grain volume ",sd.
vol*frac/gd.
norm) < 0 );
564 lgErr = lgErr || (
fprintf(fdes,
"Int(4/3pi*a^3) per H, this bin (cm^3/H)\n#\n") < 0 );
567 lgErrorOccurred =
false;
585 ErrorIndex[i] =
max(ErrorIndex[i],Error);
586 acs_abs[p][i] += cs_abs*gd.
wt[gd.
cAxis];
587 acs_sct[p][i] += cs_sct*gd.
wt[gd.
cAxis];
588 a1g[p][i] += cs_sct*(1.-cosb)*gd.
wt[gd.
cAxis];
590 lgErrorOccurred =
mie_auxiliary2(ErrorIndex,acs_abs,acs_sct,a1g,p,i);
595 ErrorIndex[i] =
min(Error,2);
596 lgErrorOccurred = lgErrorOccurred || ( Error > 0 );
597 acs_abs[p][i] = cs_abs*gd.
norm;
598 acs_sct[p][i] = cs_sct*gd.
norm;
603 acs_abs[p][i] = 1.3121e-23*volfrac*gd.
norm;
604 acs_sct[p][i] = 2.6242e-23*volfrac*gd.
norm;
612 ErrorIndex[i] =
max(ErrorIndex[i],Error);
613 acs_abs[p][i] += cs_abs*gd2.
wt[gd2.
cAxis];
614 acs_sct[p][i] += 0.1*cs_abs*gd2.
wt[gd2.
cAxis];
615 a1g[p][i] += 0.1*cs_abs*1.*gd2.
wt[gd2.
cAxis];
617 lgErrorOccurred =
mie_auxiliary2(ErrorIndex,acs_abs,acs_sct,a1g,p,i);
627 ErrorIndex[i] =
max(ErrorIndex[i],Error);
628 acs_abs[p][i] += cs_abs*gd2.
wt[gd2.
cAxis];
629 acs_sct[p][i] += 0.1*cs_abs*gd2.
wt[gd2.
cAxis];
630 a1g[p][i] += 0.1*cs_abs*1.*gd2.
wt[gd2.
cAxis];
632 lgErrorOccurred =
mie_auxiliary2(ErrorIndex,acs_abs,acs_sct,a1g,p,i);
642 ErrorIndex[i] =
max(ErrorIndex[i],Error);
643 acs_abs[p][i] += cs_abs*gd2.
wt[gd2.
cAxis];
644 acs_sct[p][i] += 0.1*cs_abs*gd2.
wt[gd2.
cAxis];
645 a1g[p][i] += 0.1*cs_abs*1.*gd2.
wt[gd2.
cAxis];
647 lgErrorOccurred =
mie_auxiliary2(ErrorIndex,acs_abs,acs_sct,a1g,p,i);
657 if( lgErrorOccurred )
659 strcpy(chString,
"absorption cs");
661 strcpy(chString,
"scattering cs");
663 strcpy(chString,
"asymmetry parameter");
669 acs_abs[p][i] /= gd.
norm;
672 acs_sct[p][i] /= gd.
norm;
676 lgErr = lgErr || (
fprintf(fdes,
"#\n") < 0 );
677 lgErr = lgErr || (
fprintf(fdes,
"# ===========================================\n") < 0 );
678 lgErr = lgErr || (
fprintf(fdes,
"# anu (Ryd) abs_cs_01 (cm^2/H) abs_cs_02.....\n#\n") < 0 );
683 for( p=0; p < sd.
nPart; p++ )
685 lgErr = lgErr || (
fprintf(fdes,
"%.6e ",acs_abs[p][i]) < 0 );
687 lgErr = lgErr || (
fprintf(fdes,
"\n") < 0 );
690 lgErr = lgErr || (
fprintf(fdes,
"#\n") < 0 );
691 lgErr = lgErr || (
fprintf(fdes,
"# ===========================================\n") < 0 );
692 lgErr = lgErr || (
fprintf(fdes,
"# anu (Ryd) sct_cs_01 (cm^2/H) sct_cs_02.....\n#\n") < 0 );
697 for( p=0; p < sd.
nPart; p++ )
699 lgErr = lgErr || (
fprintf(fdes,
"%.6e ",acs_sct[p][i]) < 0 );
701 lgErr = lgErr || (
fprintf(fdes,
"\n") < 0 );
704 lgErr = lgErr || (
fprintf(fdes,
"#\n") < 0 );
705 lgErr = lgErr || (
fprintf(fdes,
"# ===========================================\n") < 0 );
706 lgErr = lgErr || (
fprintf(fdes,
"# anu (Ryd) (1-g)_bin_01 (1-g)_bin_02.....\n#\n") < 0 );
711 for( p=0; p < sd.
nPart; p++ )
714 lgErr = lgErr || (
fprintf(fdes,
"%.6e ",
min(a1g[p][i],1.)) < 0 );
716 lgErr = lgErr || (
fprintf(fdes,
"\n") < 0 );
719 fprintf(
ioQQQ,
" Starting calculation of inverse attenuation length\n" );
720 strcpy(chString,
"inverse attenuation length");
737 fprintf(
ioQQQ,
" mie_write_opc detected unknown ial type: %d\n" , icase );
746 lgErr = lgErr || (
fprintf(fdes,
"#\n") < 0 );
747 lgErr = lgErr || (
fprintf(fdes,
"# ===========================================\n") < 0 );
748 lgErr = lgErr || (
fprintf(fdes,
"# anu (Ryd) inverse attenuation length (cm^-1)\n#\n") < 0 );
752 lgErr = lgErr || (
fprintf(fdes,
"%.6e %.6e\n",
rfield.
anu(i),inv_att_len[i]) < 0 );
759 fprintf(
ioQQQ,
"\n Error writing file: %s\n", chFile );
760 if(
remove(chFile) == 0 )
768 fprintf(
ioQQQ,
"\n Opacity file %s written succesfully\n\n", chFile );
771 fprintf(
ioQQQ,
"\n !!! Warnings were detected !!!\n\n" );
789 const double TOLER = 1.e-3;
792 if( strcmp(auxCase,
"init") == 0 )
794 double mass,
radius, CpMolecule;
811 fprintf(
ioQQQ,
"\n This size distribution can only be combined with"
812 " carbonaceous material, bailing out...\n" );
819 radius = cbrt(3.*mass/(PI4*gd->
rho));
823 sd->
vol = 4./3.*PI*
pow3(radius);
846 delta = fabs(sd->
vol-oldvol)/sd->
vol;
848 }
while( sd->
nmul <= 1024 && delta > TOLER );
852 fprintf(
ioQQQ,
" could not converge integration of size distribution\n" );
868 else if( strcmp(auxCase,
"step") == 0 )
885 step = (amax - amin)/(
double)sd->
nPart;
886 amin = amin + (double)sd->
cPart*step;
887 amax =
min(amax,amin + step);
907 fprintf(
ioQQQ,
" mie_auxiliary called with insane argument: %s\n", auxCase );
924 bool lgErrorOccurred =
false;
925 if( ErrorIndex[i] > 0 )
927 ErrorIndex[i] =
min(ErrorIndex[i],2);
928 lgErrorOccurred =
true;
931 switch( ErrorIndex[i] )
944 a1g[p][i] /= acs_sct[p][i];
947 fprintf(
ioQQQ,
" Insane value for ErrorIndex: %d\n", ErrorIndex[i] );
953 if( ErrorIndex[i] < 2 )
954 ASSERT( acs_abs[p][i] > 0. && acs_sct[p][i] > 0. );
955 if( ErrorIndex[i] < 1 )
958 return lgErrorOccurred;
965 double *normalization)
976 sd->
xx.resize(sd->
nn);
977 sd->
aa.resize(sd->
nn);
978 sd->
rr.resize(sd->
nn);
979 sd->
ww.resize(sd->
nn);
989 for( j=0; j < sd->
nn; j++ )
996 sd->
rr[j] = exp(sd->
rr[j]);
997 sd->
ww[j] *= sd->
rr[j];
1005 *normalization = unity;
1006 sd->
radius *= 1.e-4/unity;
1007 sd->
area *= 4.*PI*1.e-8/unity;
1008 sd->
vol *= 4./3.*PI*1.e-12/unity;
1039 const double RATIO_MAX = cbrt(100.);
1047 size_t flen = strlen(chFile);
1050 chLine2 = string(chFile) + string(40-flen,
' ');
1054 chLine2 = string(chFile).substr(0, 37) +
"...";
1057 fprintf(
ioQQQ,
" * >>>> mie_read_opc reading file -- %40s <<<< *\n", chLine2.c_str() );
1064 fprintf(
ioQQQ,
" File %s has already been read before, was this intended ?\n", chFile );
1072 nd =
gv.
bin.size()-1;
1081 fprintf(
ioQQQ,
" Opacity file %s has obsolete magic number\n",chFile );
1082 fprintf(
ioQQQ,
" I found magic number %ld, but expected %ld on line #%ld\n",
1105 gv.
bin[nd]->chDstLab[i] = chLine[i];
1106 gv.
bin[nd]->chDstLab[LABELSIZE] =
'\0';
1112 gv.
bin[nd]->eec = pow((
double)
gv.
bin[nd]->dustp[0],-0.85);
1131 gv.
bin[nd]->dustp[4] = 1.;
1136 gv.
bin[nd]->eyc = 1./
gv.
bin[nd]->AvRadius + 1.e7;
1179 for( nelem=0; nelem <
LIMELM; nelem++ )
1184 gv.
bin[nd]->elmAbund[nelem] = RefAbund[nelem];
1196 lgDefaultQHeat = ( RadiusRatio < RATIO_MAX && !gp.
lgGreyGrain );
1199 gv.
bin[nd]->cnv_GR_pH = 1./
gv.
bin[nd]->cnv_H_pGR;
1202 gv.
bin[nd]->Capacity = PI4*ELECTRIC_CONST*
gv.
bin[nd]->IntRadius/100.*
gv.
bin[nd]->cnv_H_pGR;
1207 for( i=0; i < nup; i++ )
1218 double mesh_lo, mesh_hi;
1223 sscanf( chLine,
"%x %x", &u.i[0], &u.i[1] );
1225 sscanf( chLine,
"%x %x", &u.i[1], &u.i[0] );
1231 sscanf( chLine,
"%x %x", &u.i[0], &u.i[1] );
1233 sscanf( chLine,
"%x %x", &u.i[1], &u.i[0] );
1240 fprintf(
ioQQQ,
" Opacity file %s has an incompatible energy grid.\n", chFile );
1241 fprintf(
ioQQQ,
" Please recompile this file using the COMPILE GRAINS command.\n" );
1248 sscanf( chLine,
"%x %x", &u.i[0], &u.i[1] );
1250 sscanf( chLine,
"%x %x", &u.i[1], &u.i[0] );
1252 gv.
bin[nd]->RSFCheck = u.x;
1266 VolTotal =
gv.
bin[nd]->IntVol;
1268 for( i=0; i < nbin; i++ )
1276 nd2 =
gv.
bin.size()-1;
1309 gv.
bin[nd2]->cnv_GR_pH = 1./
gv.
bin[nd2]->cnv_H_pGR;
1312 gv.
bin[nd2]->Capacity =
1313 PI4*ELECTRIC_CONST*
gv.
bin[nd2]->IntRadius/100.*
gv.
bin[nd2]->cnv_H_pGR;
1318 gv.
bin[nd2]->dustp[4] =
gv.
bin[nd2]->IntVol/VolTotal;
1319 for( nelem=0; nelem <
LIMELM; nelem++ )
1320 gv.
bin[nd2]->elmAbund[nelem] = RefAbund[nelem]*
gv.
bin[nd2]->dustp[4];
1324 for( i=0; i < nbin; i++ )
1330 sprintf(str,
"%02ld",i+1);
1335 for( i=0; i < nbin; i++ )
1338 gv.
bin[nd2]->dstab1.resize(nup);
1339 gv.
bin[nd2]->pure_sc1.resize(nup);
1340 gv.
bin[nd2]->asym.resize(nup);
1341 gv.
bin[nd2]->dstab1_x_anu.resize(nup);
1342 gv.
bin[nd2]->inv_att_len.resize(nup);
1346 for( i=0; i < 5; i++ )
1350 for( i=0; i < nup; i++ )
1353 if( (res = fscanf(io2,
"%le",&anu)) != 1 )
1363 fprintf(
ioQQQ,
"\n\n PROBLEM while reading frequencies: point %li should "
1364 "have value %e, but actually has %e\n", (
unsigned long)i,
rfield.
anu(i), anu );
1365 fprintf(
ioQQQ,
" Please recompile the grain opacity file %s.\n", chFile );
1368 for( j=0; j < nbin; j++ )
1371 if( (res = fscanf(io2,
"%le",&
gv.
bin[nd2]->dstab1[i])) != 1 )
1384 for( i=0; i < 5; i++ )
1388 for( i=0; i < nup; i++ )
1390 if( (res = fscanf(io2,
"%le",&anu)) != 1 )
1397 for( j=0; j < nbin; j++ )
1400 if( (res = fscanf(io2,
"%le",&
gv.
bin[nd2]->pure_sc1[i])) != 1 )
1412 for( i=0; i < 5; i++ )
1416 for( i=0; i < nup; i++ )
1418 if( (res = fscanf(io2,
"%le",&anu)) != 1 )
1425 for( j=0; j < nbin; j++ )
1428 if( (res = fscanf(io2,
"%le",&
gv.
bin[nd2]->asym[i])) != 1 )
1442 for( i=0; i < 5; i++ )
1446 for( i=0; i < nup; i++ )
1449 if( (res = fscanf(io2,
"%le %le",&anu,&help)) != 2 )
1459 for( j=1; j < nbin; j++ )
1462 gv.
bin[nd2]->inv_att_len[i] =
gv.
bin[nd]->inv_att_len[i];
1476 void(*cs_fun)(
double,
const sd_data*,
1492 const double TOLER = 1.e-3;
1493 double rr, h, absval, sctval, mycosb, toler[3];
1502 (*cs_fun)(wavlen,sd,gd,cs_abs,cs_sct,cosb,error);
1523 rr = sd->clim[
ipBHi];
1524 h =
min(0.03*rr*sqrt(TOLER),sd->clim[
ipBHi]-sd->clim[
ipBLo]);
1530 mie_step(wavlen,sd,gd,cs_fun,&rr,&h,toler,&absval,&sctval,&mycosb,error);
1539 else if( *error == 1 )
1547 toler[0] = (*cs_abs)*
TOLER;
1548 toler[1] = (*cs_sct)*
TOLER;
1549 toler[2] = abs(*cosb)*
TOLER;
1550 if( rr-h < sd->clim[
ipBLo] )
1551 h = rr-sd->clim[
ipBLo];
1564 *cs_abs /= sd->unity;
1565 *cs_sct /= sd->unity;
1569 fprintf(
ioQQQ,
" insane case for grain size distribution: %d\n" , sd->sdCase );
1575 ASSERT( *cs_abs > 0. && *cs_sct > 0. );
1577 ASSERT( fabs(*cosb) <= 1.+10.*DBL_EPSILON );
1585 void(*cs_fun)(
double,
const sd_data*,
1591 const double toler[],
1599 const int MAX_ITER = 8;
1600 const int MAX_DIVS = 3;
1601 const int MAX_ABS = (1<<MAX_DIVS) + 1;
1603 double y1[MAX_DIVS+1], y2[MAX_DIVS+1], y3[MAX_DIVS+1];
1604 double y1a[MAX_ABS], y2a[MAX_ABS], y3a[MAX_ABS];
1606 for(
int k=0; k < MAX_ITER; ++k )
1608 for(
int i=0; i <= MAX_DIVS; ++i )
1611 int stride = 1<<(MAX_DIVS-i);
1612 double h1 = (*h)/double(nabs);
1614 if( k == 0 || i > 0 )
1616 for(
int j=0; j <= nabs; ++j )
1618 int index = j*stride;
1621 if( i == 0 || j%2 == 1 )
1625 double myabsval, mysctval, myg;
1626 (*cs_fun)(wavlen,sd,gd,&myabsval,&mysctval,&myg,&myerror);
1628 y1a[index] = weight*myabsval;
1629 y2a[index] = weight*mysctval;
1630 y3a[index] = weight*mysctval*myg;
1631 *error =
max(*error,myerror);
1638 y1[i] = (y1a[0]+y1a[nabs*stride])/2.;
1639 y2[i] = (y2a[0]+y2a[nabs*stride])/2.;
1640 y3[i] = (y3a[0]+y3a[nabs*stride])/2.;
1641 for(
int j=1; j < nabs; ++j )
1643 y1[i] += y1a[j*stride];
1644 y2[i] += y2a[j*stride];
1645 y3[i] += y3a[j*stride];
1656 const double TINY_G = 1.e-15;
1660 double e1 =
safe_div(abs((y1[i]-y1[i-1])/toler[0]),y1[i],0.);
1661 double e2 =
safe_div(abs((y2[i]-y2[i-1])/toler[1]),y2[i],0.);
1665 double e3 = abs(y3[i]-y3[i-1])/
max(abs(toler[2]*y3[i]),TINY_G);
1672 double e1 = abs(y1[i]-y1[i-1])/toler[0];
1673 double e2 = abs(y2[i]-y2[i-1])/toler[1];
1677 double e3 = abs(y3[i]-y3[i-1])/
max(toler[2],TINY_G);
1686 double fac = 0.9*sqrt(1./
max(err,0.1));
1695 y1a[MAX_ABS-1] = y1a[1];
1696 y2a[MAX_ABS-1] = y2a[1];
1697 y3a[MAX_ABS-1] = y3a[1];
1698 *h /= double(MAX_ABS-1);
1702 fprintf(
ioQQQ,
"=================================================\n");
1703 for(
int j=0; j <= MAX_DIVS; ++j )
1706 for(
int j=0; j <= (1<<MAX_DIVS); ++j )
1707 fprintf(
ioQQQ,
"%d %e %e %e\n",j,y1a[j],y2a[j],y3a[j]);
1708 fprintf(
ioQQQ,
"=================================================\n");
1769 ASSERT( frac > 0.-10.*DBL_EPSILON && frac < 1.+10.*DBL_EPSILON );
1770 nre = (1.-
frac)*gd->
n[gd->
cAxis][ind].real() + frac*gd->
n[gd->
cAxis][ind+1].real();
1772 nim = (1.-
frac)*gd->
n[gd->
cAxis][ind].imag() + frac*gd->
n[gd->
cAxis][ind+1].imag();
1775 ASSERT( fabs(nre-1.-nr1) < 10.*
max(nre,1.)*DBL_EPSILON );
1780 x = sd->
cSize/wavlen*2.*PI;
1785 sinpar(nre,nim,x,&qext,&qphase,&qscatt,&ctbrqs,&qback,&iflag);
1793 *cs_abs = area*(qext - qscatt);
1794 *cs_sct = area*qscatt;
1795 *cosb = ctbrqs/qscatt;
1800 if( x >= 100. && sqrt(nr1*nr1+nim*nim) <= 0.001 )
1805 anomal(x,&aqext,&aqabs,&aqphas,&xistar,delta,beta);
1809 *cs_abs = area*aqabs;
1810 *cs_sct = area*(aqext - aqabs);
1824 if( *cs_abs <= 0. || *cs_sct <= 0. )
1826 fprintf(
ioQQQ,
" illegal opacity found: wavl=%.4e micron," , wavlen );
1827 fprintf(
ioQQQ,
" abs_cs=%.2e, sct_cs=%.2e\n" , *cs_abs , *cs_sct );
1828 fprintf(
ioQQQ,
" please check refractive index file...\n" );
1834 if( fabs(*cosb) > 1.+10.*DBL_EPSILON )
1836 fprintf(
ioQQQ,
" illegal asymmetry parameter found: wavl=%.4e micron," , wavlen );
1838 fprintf(
ioQQQ,
" please check refractive index file...\n" );
1866 const double a_xi = 50.e-4;
1867 double xi_PAH, cs_abs1, cs_abs2;
1870 (*pah_fun)(wavl,sd,&gdArr[0],&cs_abs1,cs_sct,cosb,error);
1871 xi_PAH = (1.-q_gra)*
min(1.,
pow3(a_xi/sd->cSize));
1880 mie_cs(wavl,sd,&gdArr[1],&cs_abs2,cs_sct,cosb,error);
1881 *cs_abs = xi_PAH*cs_abs1 + (1.-xi_PAH)*cs_abs2;
1905 static const double pah1_strength[7] = { 1.4e-21,1.8e-21,1.2e-20,6.0e-21,4.0e-20,1.9e-20,1.9e-20 };
1906 static const double pah1_wlBand[7] = { 3.3, 6.18, 7.7, 8.6, 11.3, 12.0, 13.3 };
1907 static const double pah1_width[7] = { 0.024, 0.102, 0.24, 0.168, 0.086, 0.174, 0.174 };
1926 const double p1 = 4.0e-18;
1927 const double p2 = 1.1e-18;
1928 const double p3 = 3.3e-21;
1929 const double p4 = 6.0e-21;
1930 const double p5 = 2.4e-21;
1931 const double wl1a = 5.0;
1932 const double wl1b = 7.0;
1933 const double wl1c = 9.0;
1934 const double wl1d = 9.5;
1935 const double wl2a = 11.0;
1936 const double delwl2 = 0.3;
1938 const double wl2b = wl2a + delwl2;
1939 const double wl2c = 15.0;
1940 const double wl3a = 3.2;
1941 const double wl3b = 3.57;
1942 const double wl3m = (wl3a+wl3b)/2.;
1943 const double wl3sig = 0.1476;
1944 const double x1 = 4.0;
1945 const double x2 = 5.9;
1946 const double x2a = RYD_INF/1.e4;
1947 const double x3 = 0.1;
1950 double vol = 4.*PI/3.*
pow3(sd->
cSize)*1.e-12;
1955 double xnh = floor(sqrt(6.*xnc));
1957 double xnhoc = xnh/xnc;
1959 double ftoc3p3 = 100.;
1971 double anu_ev = x/x2a*EVRYD;
1978 for( j=1; j <= 3; ++j )
1981 csVal1 = (xnh*term1 + xnc*term2)*1.e-18;
1986 cval1 = log(sqrt(xnc)*ftoc3p3/1.2328)/12.2;
1990 term1 = (0.1*x + 0.41)*
pow2(
max(x-x2,0.));
2014 term2 = exp(cval1*(1. - (x1/
min(x,x1))));
2016 term3 = p3*exp(-
pow2(x/x3))*
min(x,x3)/x3;
2018 csVal2 = xnc*((p1*term + p2*term1)*term2 + term3);
2021 if( x2a <= x && x <= 2.*x2a )
2025 pah1_fun_v = exp((1.-frac)*log(csVal1) + frac*log(csVal2));
2030 pah1_fun_v = csVal1 + csVal2;
2035 if( wl1a <= wavl && wl1d >= wavl )
2038 term = p4*(wavl - wl1a)/(wl1b - wl1a);
2040 term = ( wavl > wl1c ) ? p4*(wl1d - wavl)/(wl1d - wl1c) : p4;
2041 pah1_fun_v += term*xnc;
2043 if( wl2a <= wavl && wl2c >= wavl )
2045 term = ( wavl < wl2b ) ? p5*((wavl - wl2a)/delwl2) : p5*sqrt(1.-
pow2((wavl-wl2a)/(wl2c-wl2a)));
2046 pah1_fun_v += term*xnc;
2048 if( wl3m-10.*wl3sig <= wavl && wavl <= wl3m+10.*wl3sig )
2051 term = 1.1*pah1_strength[0]*exp(-0.5*
pow2((wavl-wl3m)/wl3sig));
2052 pah1_fun_v += term*xnh;
2056 for( j=0; j < 7; j++ )
2058 term1 = (wavl - pah1_wlBand[j])/pah1_width[j];
2066 if( term1 >= -1. && term1 < -0.5 )
2068 term = pah1_strength[j]/(3.*pah1_width[j]);
2069 term *= 2. + 2.*term1;
2071 if( term1 >= -0.5 && term1 <= 1.5 )
2072 term = pah1_strength[j]/(3.*pah1_width[j]);
2073 if( term1 > 1.5 && term1 <= 3. )
2075 term = pah1_strength[j]/(3.*pah1_width[j]);
2076 term *= 2. - term1*2./3.;
2085 if( term1 >= -2. && term1 < -1. )
2087 term = pah1_strength[j]/(3.*pah1_width[j]);
2090 if( term1 >= -1. && term1 <= 1. )
2091 term = pah1_strength[j]/(3.*pah1_width[j]);
2092 if( term1 > 1. && term1 <= 2. )
2094 term = pah1_strength[j]/(3.*pah1_width[j]);
2098 if( j == 0 || j > 2 )
2100 pah1_fun_v += term*xnc;
2103 *cs_abs = pah1_fun_v;
2106 *cs_sct = 0.1*pah1_fun_v;
2129 static const double pah2_wavl[14] = { 0.0722, 0.2175, 3.3, 6.2, 7.7, 8.6, 11.3,
2130 11.9, 12.7, 16.4, 18.3, 21.2, 23.1, 26.0 };
2131 static const double pah2_width[14] = { 0.195, 0.217, 0.012, 0.032, 0.091, 0.047, 0.018,
2132 0.025, 0.024, 0.010, 0.036, 0.038, 0.046, 0.69 };
2133 static const double pah2n_strength[14] = { 7.97e-13, 1.23e-13, 1.97e-18, 1.96e-19, 6.09e-19, 3.47e-19, 4.27e-18,
2134 7.27e-19, 1.67e-18, 5.52e-20, 6.04e-20, 1.08e-19, 2.78e-20, 1.52e-19 };
2135 static const double pah2c_strength[14] = { 7.97e-13, 1.23e-13, 4.47e-19, 1.57e-18, 5.48e-18, 2.42e-18, 4.00e-18,
2136 6.14e-19, 1.49e-18, 5.52e-20, 6.04e-20, 1.08e-19, 2.78e-20, 1.52e-19 };
2152 const double E62 = 3.;
2153 const double E77 = 2.;
2154 const double E86 = 2.;
2157 double vol = 4.*PI/3.*
pow3(sd->
cSize)*1.e-12;
2165 else if( xnc <= 100. )
2166 xnhoc = 2.5/sqrt(xnc);
2172 double pah2_fun_v = 0.;
2175 double M = ( xnc <= 40. ) ? 0.3*xnc : 0.4*xnc;
2179 cutoff = 1./(3.804/sqrt(M) + 1.052);
2181 cutoff = 1./(2.282/sqrt(M) + 0.889);
2182 double y = cutoff/wavl;
2184 double cutoff_fun = atan(1.e3*
pow3(y-1.)/y)/PI + 0.5;
2186 pah2_fun_v = 34.58*
exp10( -18.-3.431/x )*cutoff_fun;
2187 for(
int j=2; j < 14; ++j )
2189 double strength = ( gd->
charge == 0 ) ? pah2n_strength[j] : pah2c_strength[j];
2197 strength *= E86*xnhoc;
2198 else if( j == 6 || j == 7 || j == 8 )
2199 strength *= xnhoc/3.;
2200 pah2_fun_v +=
Drude( wavl, pah2_wavl[j], pah2_width[j], strength );
2206 pah2_fun_v =
Drude( wavl, pah2_wavl[1], pah2_width[1], pah2n_strength[1] );
2207 pah2_fun_v += (1.8687 + 0.1905*x)*1.e-18;
2212 pah2_fun_v =
Drude( wavl, pah2_wavl[1], pah2_width[1], pah2n_strength[1] );
2214 pah2_fun_v += (1.8687 + 0.1905*x +
pow2(y)*(0.4175 + 0.04370*y))*1.e-18;
2219 pah2_fun_v = (((-0.1057*x + 2.950)*x - 24.367)*x + 66.302)*1.e-18;
2224 pah2_fun_v =
Drude( wavl, pah2_wavl[0], pah2_width[0], pah2n_strength[0] );
2225 pah2_fun_v += (-3. + 1.35*x)*1.e-18;
2227 else if( x < 17.26 )
2230 pah2_fun_v = (126.0 - 6.4943*x)*1.e-18;
2240 *cs_abs = pah2_fun_v;
2242 *cs_sct = 0.1*pah2_fun_v;
2265 static const double pah3_wavl[30] = { 0.0722, 0.2175, 1.05, 1.26, 1.905, 3.3, 5.27, 5.7, 6.22, 6.69, 7.417, 7.598,
2266 7.85, 8.33, 8.61, 10.68, 11.23, 11.33, 11.99, 12.62, 12.69, 13.48, 14.19,
2267 15.9, 16.45, 17.04, 17.375, 17.87, 18.92, 15. };
2268 static const double pah3_width[30] = { 0.195, 0.217, 0.055, 0.11, 0.09, 0.012, 0.034, 0.035, 0.03, 0.07, 0.126,
2269 0.044, 0.053, 0.052, 0.039, 0.02, 0.012, 0.032, 0.045, 0.042, 0.013, 0.04,
2270 0.025, 0.02, 0.014, 0.065, 0.012, 0.016, 0.1, 0.8 };
2271 static const double pah3n_strength[30] = { 7.97e-13, 1.23e-13, 0., 0., 0., 3.94e-18, 2.5e-20, 4.e-20, 2.94e-19,
2272 7.35e-20, 2.08e-19, 1.81e-19, 2.19e-19, 6.94e-20, 2.78e-19, 3.e-21,
2273 1.89e-19, 5.2e-19, 2.42e-19, 3.5e-19, 1.3e-20, 8.e-20, 4.5e-21,
2274 4.e-22, 5.e-21, 2.22e-20, 1.1e-21, 6.7e-22, 1.e-21, 5.e-19 };
2275 static const double pah3c_strength[30] = { 7.97e-13, 1.23e-13, 2.e-16, 7.8e-17, -1.465e-18, 8.94e-19, 2.e-19,
2276 3.2e-19, 2.35e-18, 5.9e-19, 1.81e-18, 1.63e-18, 1.97e-18, 4.8e-19,
2277 1.94e-18, 3.e-21, 1.77e-19, 4.9e-19, 2.05e-19, 3.1e-19, 1.3e-20,
2278 8.e-20, 4.5e-21, 4.e-22, 5.e-21, 2.22e-20, 1.1e-21, 6.7e-22, 1.7e-21,
2281 static const bool pah3_hoc[30] = {
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
false,
2282 false,
false,
true,
true,
true,
true,
true,
true,
true,
true,
true,
false,
2283 false,
false,
false,
false,
false,
false,
false };
2298 double vol = 4.*PI/3.*
pow3(sd->
cSize)*1.e-12;
2306 else if( xnc <= 100. )
2307 xnhoc = 2.5/sqrt(xnc);
2314 double pah3_fun_v = ( gd->
charge == 0 ) ? 0. : 3.5*
exp10(-19.-1.45/x)*exp(-0.1*
pow2(x));
2318 double M = ( xnc <= 40. ) ? 0.3*xnc : 0.4*xnc;
2322 cutoff = 1./(3.804/sqrt(M) + 1.052);
2324 cutoff = 1./(2.282/sqrt(M) + 0.889);
2325 double y = cutoff/wavl;
2327 double cutoff_fun = atan(1.e3*
pow3(y-1.)/y)/PI + 0.5;
2329 pah3_fun_v += 34.58*
exp10( -18.-3.431/x )*cutoff_fun;
2330 for(
int j=2; j < 30; ++j )
2332 double strength = ( gd->
charge == 0 ) ? pah3n_strength[j] : pah3c_strength[j];
2335 pah3_fun_v +=
Drude( wavl, pah3_wavl[j], pah3_width[j], strength );
2341 pah3_fun_v +=
Drude( wavl, pah3_wavl[1], pah3_width[1], pah3n_strength[1] );
2342 pah3_fun_v += (1.8687 + 0.1905*x)*1.e-18;
2347 pah3_fun_v +=
Drude( wavl, pah3_wavl[1], pah3_width[1], pah3n_strength[1] );
2349 pah3_fun_v += (1.8687 + 0.1905*x +
pow2(y)*(0.4175 + 0.04370*y))*1.e-18;
2354 pah3_fun_v += (((-0.1057*x + 2.950)*x - 24.367)*x + 66.302)*1.e-18;
2359 pah3_fun_v +=
Drude( wavl, pah3_wavl[0], pah3_width[0], pah3n_strength[0] );
2360 pah3_fun_v += (-3. + 1.35*x)*1.e-18;
2362 else if( x < 17.26 )
2365 pah3_fun_v += (126.0 - 6.4943*x)*1.e-18;
2375 *cs_abs = pah3_fun_v;
2377 *cs_sct = 0.1*pah3_fun_v;
2391 double x = lambda/lambdac;
2393 return 2.e-4/PI*gamma*lambdac*sigma/(
pow2(x - 1./x) +
pow2(gamma));
2407 double anu = WAVNRYD/wavl*1.e4;
2418 if( !lgOutOfBounds )
2423 *cs_abs = exp((1.-frac)*log(gd->
opcData[0][ind])+frac*log(gd->
opcData[0][ind+1]));
2426 *cs_sct = exp((1.-frac)*log(gd->
opcData[1][ind])+frac*log(gd->
opcData[1][ind+1]));
2428 *cs_sct = 0.1*(*cs_abs);
2431 a1g = exp((1.-frac)*log(gd->
opcData[2][ind])+frac*log(gd->
opcData[2][ind+1]));
2474 res = pow(size,sd->
a[
ipExp]);
2476 res /= (1. - sd->
a[
ipBeta]*size);
2478 res *= (1. + sd->
a[
ipBeta]*size);
2481 if( size > sd->
a[ipBHi] && sd->
a[
ipSHi] > 0. )
2486 res = exp(-0.5*
pow2(x))/size;
2490 res = exp(-0.5*
pow2(x))/size;
2496 fprintf(
ioQQQ,
" size distribution table has insufficient range\n" );
2497 fprintf(
ioQQQ,
" requested size: %.5f table range %.5f - %.5f\n",
2501 frac = (log(size)-sd->
ln_a[ind])/(sd->
ln_a[ind+1]-sd->
ln_a[ind]);
2502 ASSERT( frac > 0.-10.*DBL_EPSILON && frac < 1.+10.*DBL_EPSILON );
2505 res = exp(res)/
POW4(size);
2539 const double TOLER = 1.e-6;
2544 ASSERT( rel_cutoff > 0. && rel_cutoff < 1. );
2559 f1 = -log(rel_cutoff);
2564 for( i=0; i < 20 && f2 > 0.; ++i )
2582 while( 2.*fabs(x1-x2)/(x1+x2) > TOLER )
2607 vector<double>& invlen,
2608 const char *chString,
2611 bool lgErrorOccurred=
true,
2628 for( i=0; i < n; i++ )
2633 lgErrorOccurred =
false;
2636 for( j=0; j < gd->
nAxes; j++ )
2643 lgErrorOccurred =
true;
2648 nim = (1.-
frac)*gd->
n[j][ind].imag() + frac*gd->
n[j][ind+1].imag();
2651 InvDep = PI4*nim/wavlen*1.e4;
2654 invlen[i] += InvDep*gd->
wt[j];
2658 if( lgErrorOccurred )
2677 vector<int>& ErrorIndex,
2697 const long BIG_INTERPOLATION = 10;
2701 lgVerbose = ( chString[0] !=
'\0' );
2703 for( ind1=0; ind1 < n; )
2705 if( ErrorIndex[ind1] == val )
2709 bool lgValid =
true;
2712 while( ind2 < n && ErrorIndex[ind2] == val )
2717 for( j=ind2; ind1 == 0 && j <
min(ind2+NPTS_DERIV,n); j++ )
2719 if( ErrorIndex[j] == val )
2725 for( j=ind2; !lgValid && j <
min(ind2+NPTS_DERIV,n); j++ )
2727 if( ErrorIndex[j] == val )
2734 ErrorIndex[j] = val;
2738 while( !lgValid && ind2 < n );
2747 i2 = ind2+NPTS_DERIV-1;
2748 lgExtrapolate =
true;
2752 fprintf(
ioQQQ,
" extrapolated below %.4e Ryd\n",anu[i1] );
2755 else if( ind2 == n )
2760 lgExtrapolate =
true;
2764 fprintf(
ioQQQ,
" extrapolated above %.4e Ryd\n",anu[i2] );
2772 lgExtrapolate =
false;
2776 fprintf(
ioQQQ,
" interpolated between %.4e and %.4e Ryd\n",
2779 if( i2-i1-1 > BIG_INTERPOLATION )
2783 fprintf(
ioQQQ,
" ***Warning: extensive interpolation used\n" );
2789 if( i1 < 0 || i2 >= n )
2791 fprintf(
ioQQQ,
" Insufficient data for extrapolation\n" );
2795 xlg1 = log(anu[i1]);
2796 y1lg1 = log(data[i1]);
2799 slp1 =
mie_find_slope(anu,data,ErrorIndex,i1,i2,val,lgVerbose,lgWarning);
2802 xlg2 = log(anu[i2]);
2803 y1lg2 = log(data[i2]);
2804 slp1 = (y1lg2-y1lg1)/(xlg2-xlg1);
2806 if( lgRound && lgExtrapolate && sgn > 0. )
2811 slp1 =
max(slp1,0.);
2814 else if( lgExtrapolate && sgn*slp1 < 0. )
2816 fprintf(
ioQQQ,
" Unphysical value for slope in extrapolation %.6e\n", slp1 );
2817 fprintf(
ioQQQ,
" The most likely cause is that your refractive index or "
2818 "opacity data do not extend to low or high enough frequencies. "
2819 "See Hazy 1 for more details.\n" );
2823 for( j=ind1; j < ind2; j++ )
2825 dx = log(anu[j]) - xlg1;
2826 data[j] = exp(y1lg1 + dx*slp1);
2827 ErrorIndex[j] -= del;
2838 for( j=0; j < n; j++ )
2840 if( ErrorIndex[j] > val-del )
2842 fprintf(
ioQQQ,
" Internal error in mie_repair, index=%ld, val=%d\n",j,ErrorIndex[j] );
2852 const double data[],
2853 const vector<int>& ErrorIndex,
2862 const double LARGE_STDEV = 0.2;
2867 for(
long i=i1; i <= i2; i++ )
2869 if( ! ( ErrorIndex[i] < val && anu[i] > 0. && data[i] > 0. ) )
2871 fprintf(
ioQQQ,
"invalid parameter for mie_find_slope\n" );
2877 vector<double> slp1;
2878 for(
long i=i1; i < i2; i++ )
2879 for(
long j=i+1; j <= i2; j++ )
2880 slp1.push_back( log(data[j]/data[i])/log(anu[j]/anu[i]) );
2882 size_t n = slp1.size()/2;
2883 partial_sort( slp1.begin(), slp1.begin()+n+1, slp1.end() );
2885 double slope = ( slp1.size()%2 == 1 ) ? slp1[n] : (slp1[n-1]+slp1[n])/2.;
2890 for(
size_t i=0; i < slp1.size(); i++ )
2893 s2 +=
pow2(slp1[i]);
2896 double stdev = sqrt(
max(s2/(
double)slp1.size() -
pow2(s1/(
double)slp1.size()),0.));
2899 if( stdev > LARGE_STDEV )
2902 fprintf(
ioQQQ,
" ***Warning: slope for extrapolation may be unreliable\n" );
2913 bool lgLogData=
false;
2946 fprintf(
ioQQQ,
" Refractive index file %s has obsolete magic number\n",chFile );
2948 fprintf(
ioQQQ,
" Please replace this file with an up to date version\n" );
2970 fprintf(
ioQQQ,
" Illegal value for default depletion in %s\n",chFile );
2975 for( nelem=0; nelem <
LIMELM; nelem++ )
2988 fprintf(
ioQQQ,
" Illegal value for material type in %s\n",chFile );
3002 fprintf(
ioQQQ,
" Illegal value for bandgap in %s\n",chFile );
3004 fprintf(
ioQQQ,
" Bandgap should always be less than work function\n");
3013 fprintf(
ioQQQ,
" Illegal value for thermionic efficiency in %s\n",chFile );
3015 fprintf(
ioQQQ,
" Allowed values are 0. < efficiency <= 1.\n");
3027 if(
nMatch(
"RFI_", chWord ) )
3029 else if(
nMatch(
"OPC_", chWord ) )
3031 else if(
nMatch(
"GREY", chWord ) )
3033 else if(
nMatch(
"PAH1", chWord ) )
3035 else if(
nMatch(
"PH2N", chWord ) )
3037 else if(
nMatch(
"PH2C", chWord ) )
3039 else if(
nMatch(
"PH3N", chWord ) )
3041 else if(
nMatch(
"PH3C", chWord ) )
3047 fprintf(
ioQQQ,
" Allowed values are: RFI_TBL, OPC_TBL, GREY, PAH1, PH2N, PH2C, PH3N, PH3C\n");
3061 fprintf(
ioQQQ,
" Line #%ld, data code=%ld\n",dl,nridf);
3071 fprintf(
ioQQQ,
" Illegal no. of axes in %s\n",chFile );
3085 if( sscanf( chLine,
"%lf %lf", &gd->
wt[0], &gd->
wt[1] ) != 2 )
3091 if( gd->
wt[0] <= 0. || gd->
wt[1] <= 0. )
3097 total = gd->
wt[0] + gd->
wt[1];
3100 if( sscanf( chLine,
"%lf %lf %lf", &gd->
wt[0], &gd->
wt[1], &gd->
wt[2] ) != 3 )
3106 if( gd->
wt[0] <= 0. || gd->
wt[1] <= 0. || gd->
wt[2] <= 0. )
3112 total = gd->
wt[0] + gd->
wt[1] + gd->
wt[2];
3119 for( j=0; j < gd->
nAxes; j++ )
3126 if( gd->
ndata[j] < 2 )
3128 fprintf(
ioQQQ,
" Illegal number of data points in %s\n",chFile );
3135 gd->
n[j].resize( gd->
ndata[j] );
3138 for( i=0; i < gd->
ndata[j]; i++ )
3143 if( sscanf( chLine,
"%lf %lf %lf", &gd->
wavlen[j][i], &nr, &ni ) != 3 )
3149 if( gd->
wavlen[j][i] <= 0. )
3151 fprintf(
ioQQQ,
" Illegal value for wavelength in %s\n",chFile);
3162 fprintf(
ioQQQ,
" Illegal value for wavelength in %s\n",chFile);
3171 fprintf(
ioQQQ,
" Illegal value for wavelength in %s\n",chFile);
3184 dftori(&nr,&ni,eps1,eps2);
3185 gd->
nr1[j][i] = nr - 1.;
3192 gd->
nr1[j][i] = nr - 1.;
3195 fprintf(
ioQQQ,
" insane case for nridf: %ld\n", nridf );
3199 gd->
n[j][i] = complex<double>(nr,ni);
3202 if( nr <= 0. || ni < 0. )
3204 fprintf(
ioQQQ,
" Illegal value for refractive index in %s\n",chFile);
3205 fprintf(
ioQQQ,
" Line #%ld, (nr,ni)=(%14.6e,%14.6e)\n",dl,nr,ni);
3208 ASSERT( fabs(nr-1.-gd->
nr1[j][i]) < 10.*nr*DBL_EPSILON );
3223 fprintf(
ioQQQ,
" Illegal no. of data columns in %s\n",chFile );
3232 if(
nMatch(
"LINE", chWord ) )
3234 else if(
nMatch(
"LOG", chWord ) )
3238 fprintf(
ioQQQ,
" Keyword not recognized in %s\n",chFile );
3249 fprintf(
ioQQQ,
" Illegal number of data points in %s\n",chFile );
3259 tmp1 = -log10(1.01*DBL_MIN);
3260 tmp2 = log10(0.99*DBL_MAX);
3261 LargestLog =
min(tmp1,tmp2);
3278 if( sscanf( chLine,
"%lf %lf", &gd->
opcAnu[i], &gd->
opcData[0][i] ) != 2 )
3286 if( sscanf( chLine,
"%lf %lf %lf", &gd->
opcAnu[i], &gd->
opcData[0][i],
3295 if( sscanf( chLine,
"%lf %lf %lf %lf", &gd->
opcAnu[i], &gd->
opcData[0][i],
3304 if( sscanf( chLine,
"%lf %lf %lf %lf %lf", &gd->
opcAnu[i], &gd->
opcData[0][i],
3320 if( fabs(gd->
opcAnu[i]) > LargestLog )
3322 fprintf(
ioQQQ,
" Illegal value for frequency in %s\n",chFile );
3329 if( fabs(gd->
opcData[j][i]) > LargestLog )
3331 fprintf(
ioQQQ,
" Illegal data value in %s\n",chFile );
3338 if( gd->
opcAnu[i] <= 0. )
3340 fprintf(
ioQQQ,
" Illegal value for frequency in %s\n",chFile );
3348 fprintf(
ioQQQ,
" Illegal data value in %s\n",chFile );
3360 double dataVal = lgLogData ? log10(gd->
opcAnu[1]) : gd->
opcAnu[1];
3361 fprintf(
ioQQQ,
" Illegal value for frequency in %s\n",chFile );
3362 fprintf(
ioQQQ,
" Line #%ld, freq=%14.6e\n",dl,dataVal );
3370 double dataVal = lgLogData ? log10(gd->
opcAnu[i]) : gd->
opcAnu[i];
3371 fprintf(
ioQQQ,
" Illegal value for frequency in %s\n",chFile);
3372 fprintf(
ioQQQ,
" Line #%ld, freq=%14.6e\n",dl,dataVal);
3413 double maxIndex = DBL_MAX,
3421 complex<double> eps_eff(-DBL_MAX,-DBL_MAX);
3438 fprintf(
ioQQQ,
" Mixed grain file %s has obsolete magic number\n",chFile );
3440 fprintf(
ioQQQ,
" Please replace this file with an up to date version\n" );
3449 fprintf(
ioQQQ,
" Illegal value for default depletion in %s\n",chFile );
3459 fprintf(
ioQQQ,
" Illegal number of materials in mixed grain file %s\n",chFile );
3460 fprintf(
ioQQQ,
" I found %ld on line #%ld\n",nMaterial,dl );
3461 fprintf(
ioQQQ,
" This number should be at least 2\n" );
3465 vector<double>
frac(nMaterial);
3466 vector<double> frac2(nMaterial);
3467 vector<grain_data> gdArr(nMaterial);
3472 for( i=0; i < nMaterial; i++ )
3486 strcpy( chFile2, ++str );
3493 fprintf(
ioQQQ,
" No pair of double quotes was found on line #%ld of file %s\n",dl,chFile );
3494 fprintf(
ioQQQ,
" Please supply the refractive index file name between double quotes\n" );
3501 fprintf(
ioQQQ,
" Input error on line #%ld of file %s\n",dl,chFile );
3502 fprintf(
ioQQQ,
" File %s is not of type RFI_TBL, this is illegal\n",chFile2 );
3507 if( i == nMaterial-1 && gdArr[i].mol_weight == 0. )
3509 fprintf(
ioQQQ,
" Input error on line #%ld of file %s\n",dl,chFile );
3510 fprintf(
ioQQQ,
" Last entry in list of materials is vacuum, this is not allowed\n" );
3511 fprintf(
ioQQQ,
" Please move this entry to an earlier position in the file\n" );
3515 frac2[i] = ( gdArr[i].mol_weight > 0. ) ? frac[i] : 0.;
3518 sumAxes += gdArr[i].nAxes;
3525 if(
nMatch(
"FA00", chWord ) )
3527 else if(
nMatch(
"ST95", chWord ) )
3529 else if(
nMatch(
"BR35", chWord ) )
3533 fprintf(
ioQQQ,
" Keyword not recognized in %s\n",chFile );
3539 for( i=0; i < nMaterial; i++ )
3544 for( nelem=0; nelem <
LIMELM; nelem++ )
3546 gdArr[i].elmAbun[nelem] /= gdArr[i].abun*gdArr[i].depl;
3553 for( nelem=0; nelem <
LIMELM; nelem++ )
3568 for( i=0; i < nMaterial; i++ )
3570 for( k=0; k < gdArr[i].nAxes; k++ )
3572 double wavMin =
min(gdArr[i].wavlen[k][0],gdArr[i].wavlen[k][gdArr[i].ndata[k]-1]);
3573 double wavMax =
max(gdArr[i].wavlen[k][0],gdArr[i].wavlen[k][gdArr[i].ndata[k]-1]);
3574 wavLo =
max(wavLo,wavMin);
3575 wavHi =
min(wavHi,wavMax);
3579 for( nelem=0; nelem <
LIMELM; nelem++ )
3581 gd->
elmAbun[nelem] += frac[i]*gdArr[i].elmAbun[nelem];
3588 gd->
mol_weight += frac[i]*gdArr[i].mol_weight;
3589 gd->
rho += frac[i]*gdArr[i].rho;
3591 if( gdArr[i].mol_weight > 0. )
3598 gd->
work = gdArr[i].work;
3599 gd->
bandgap = gdArr[i].bandgap;
3607 gd->
therm_eff += frac2[i]*gdArr[i].therm_eff;
3614 gd->
matType = gdArr[i].matType;
3629 if( maxIndex <= 0. )
3631 fprintf(
ioQQQ,
" No atoms were found in the grain molecule\n" );
3636 ASSERT( wavLo > 0. && wavHi < DBL_MAX && wavLo < wavHi );
3642 ASSERT( minIndex > 0. && minIndex < DBL_MAX );
3645 wavLo *= 1. + 10.*DBL_EPSILON;
3646 wavHi *= 1. - 10.*DBL_EPSILON;
3650 for( nelem=0; nelem <
LIMELM; nelem++ )
3652 gd->
elmAbun[nelem] /= minIndex;
3656 gd->
abun *= minIndex;
3662 fprintf(
ioQQQ,
"\n The chemical formula of the new grain molecule is: %s\n", chWord );
3663 fprintf(
ioQQQ,
" The abundance wrt H at maximum depletion of this molecule is: %.3e\n",
3665 fprintf(
ioQQQ,
" The abundance wrt H at standard depletion of this molecule is: %.3e\n",
3669 for( nelem=0; nelem <
LIMELM; nelem++ )
3674 vector<double> delta(sumAxes);
3675 vector<double> frdelta(sumAxes);
3676 vector< complex<double> > eps(sumAxes);
3679 for( i=0; i < nMaterial; i++ )
3681 for( k=0; k < gdArr[i].nAxes; k++ )
3683 frdelta[l] = gdArr[i].wt[k]*frac[i];
3684 delta[l] = ( l == 0 ) ? frdelta[l] : delta[l-1] + frdelta[l];
3688 ASSERT( l == sumAxes && fabs(delta[l-1]-1.) < 10.*DBL_EPSILON );
3692 gd->
n[0].resize( gd->
ndata[0] );
3695 wavStep = log(wavHi/wavLo)/(double)(gd->
ndata[0]-1);
3706 for( j=0; j < gd->
ndata[0]; j++ )
3709 complex<double>
a1,
a2,a1c,a2c,a11,a12,a21,a22,ratio;
3711 gd->
wavlen[0][j] = wavLo*exp((
double)j*wavStep);
3715 ratio = eps[0]/eps[1];
3718 a2 = (1.-ratio)*delta[0];
3720 for( l=1; l < sumAxes-1; l++ )
3722 ratio = eps[l]/eps[l+1];
3726 a11 = (ratio+2.)/3.;
3727 a12 = (2.-2.*ratio)/(9.*delta[l]);
3728 a21 = (1.-ratio)*delta[l];
3729 a22 = (2.*ratio+1.)/3.;
3731 a1 = a11*a1c + a12*a2c;
3732 a2 = a21*a1c + a22*a2c;
3739 a21 = eps[sumAxes-1];
3740 a22 = -2./3.*eps[sumAxes-1];
3742 a1 = a11*a1c + a12*a2c;
3743 a2 = a21*a1c + a22*a2c;
3746 dftori(&nre,&nim,ratio.real(),ratio.imag());
3748 gd->
n[0][j] = complex<double>(nre,nim);
3749 gd->
nr1[0][j] = nre-1.;
3754 for( j=0; j < gd->
ndata[0]; j++ )
3756 const double EPS_TOLER = 10.*DBL_EPSILON;
3758 complex<double> eps0;
3760 gd->
wavlen[0][j] = wavLo*exp((
double)j*wavStep);
3769 for( l=0; l < sumAxes; l++ )
3770 eps0 += frdelta[l]*eps[l];
3793 dftori(&nre,&nim,eps_eff.real(),eps_eff.imag());
3795 gd->
n[0][j] = complex<double>(nre,nim);
3796 gd->
nr1[0][j] = nre-1.;
3811 const vector<grain_data>& gdArr,
3812 vector< complex<double> >& eps)
3820 for( i=0; i < nMaterial; i++ )
3822 for( k=0; k < gdArr[i].nAxes; k++ )
3826 double eps1,eps2,frc,nim,nre;
3828 find_arr(wavlen,gdArr[i].wavlen[k],gdArr[i].ndata[k],&ind,&lgErr);
3830 frc = (wavlen-gdArr[i].wavlen[k][ind])/(gdArr[i].wavlen[k][ind+1]-gdArr[i].wavlen[k][ind]);
3831 ASSERT( frc > 0.-10.*DBL_EPSILON && frc < 1.+10.*DBL_EPSILON );
3832 nre = (1.-frc)*gdArr[i].n[k][ind].real() + frc*gdArr[i].n[k][ind+1].real();
3834 nim = (1.-frc)*gdArr[i].n[k][ind].imag() + frc*gdArr[i].n[k][ind+1].imag();
3836 ritodf(nre,nim,&eps1,&eps2);
3837 eps[l++] = complex<double>(eps1,eps2);
3854 void(*fun)(complex<double>,
const vector<double>&,
const vector< complex<double> >&,
3855 long,complex<double>*,
double*,
double*),
3856 const vector<double>& frdelta,
3857 const vector< complex<double> >& eps,
3865 const double TINY = 1.e-12;
3870 complex<double>
x1,y;
3871 double dudx,dudy,norm2;
3873 (*fun)(
x0,frdelta,eps,sumAxes,&y,&dudx,&dudy);
3877 if( norm2 < TINY*norm(y) )
3883 x1 = x0 - complex<double>( y.real()*dudx-y.imag()*dudy, y.imag()*dudx+y.real()*dudy )/norm2;
3886 if( fabs(x0.real()/x1.real()-1.) + fabs(x0.imag()/x1.imag()-1.) < tol )
3904 const vector<double>& frdelta,
3905 const vector< complex<double> >& eps,
3914 static const double L[4] = { 0., 1./2., 1., 1./3. };
3915 static const double fl[4] = { 5./9., 2./9., 2./9., 1. };
3918 *f = complex<double>(0.,0.);
3921 for( l=0; l < sumAxes; l++ )
3923 complex<double> hlp = eps[l] - x;
3924 double h1 = eps[l].imag()*x.real() - eps[l].real()*x.imag();
3926 for( i=0; i < 4; i++ )
3928 double f1 = fl[i]*frdelta[l];
3929 double xx = ( i < 3 ) ? sin(PI*frdelta[l]) : cos(PI*frdelta[l]);
3930 complex<double> f2 = f1*xx*xx;
3931 complex<double> one = x + hlp*L[i];
3932 complex<double> two = f2*hlp/one;
3933 double h2 = norm(one);
3935 *dudx -= f2.real()*(eps[l].real()*h2 + h1*2.*one.imag()*(1.-L[i]))/
pow2(h2);
3936 *dudy -= f2.real()*(eps[l].imag()*h2 - h1*2.*one.real()*(1.-L[i]))/
pow2(h2);
3946 const vector<double>& frdelta,
3947 const vector< complex<double> >& eps,
3955 static const double L = 1./3.;
3958 *f = complex<double>(0.,0.);
3961 for( l=0; l < sumAxes; l++ )
3963 complex<double> hlp = eps[l] - x;
3964 double h1 = eps[l].imag()*x.real() - eps[l].real()*x.imag();
3965 complex<double> f2 = frdelta[l];
3966 complex<double> one = x + hlp*L;
3967 complex<double> two = f2*hlp/one;
3968 double h2 = norm(one);
3970 *dudx -= f2.real()*(eps[l].real()*h2 + h1*2.*one.imag()*(1.-L))/
pow2(h2);
3971 *dudy -= f2.real()*(eps[l].imag()*h2 - h1*2.*one.real()*(1.-L))/
pow2(h2);
3981 bool lgTryOverride =
false;
3998 const double FRAC_CUTOFF = 1.e-4;
3999 const double MUL_CO1 = -log(FRAC_CUTOFF);
4000 const double MUL_CO2 = sqrt(MUL_CO1);
4001 const double MUL_CO3 = cbrt(MUL_CO1);
4002 const double MUL_LND = sqrt(-2.*log(FRAC_CUTOFF));
4003 const double MUL_NRM = MUL_LND;
4016 fprintf(
ioQQQ,
" Size distribution file %s has obsolete magic number\n",chFile );
4018 fprintf(
ioQQQ,
" Please replace this file with an up to date version\n" );
4026 if(
nMatch(
"SSIZ", chWord ) )
4030 else if(
nMatch(
"NCAR", chWord ) )
4034 else if(
nMatch(
"POWE", chWord ) )
4038 else if(
nMatch(
"EXP1", chWord ) )
4044 else if(
nMatch(
"EXP2", chWord ) )
4050 else if(
nMatch(
"EXP3", chWord ) )
4056 else if(
nMatch(
"LOGN", chWord ) )
4062 else if(
nMatch(
"NORM", chWord ) )
4067 else if(
nMatch(
"TABL", chWord ) )
4085 fprintf(
ioQQQ,
" Grain sizes should be between %.5f and %.0f micron\n",
4102 fprintf(
ioQQQ,
" Illegal value for grain size (lower limit)\n" );
4103 fprintf(
ioQQQ,
" Grain sizes should be between %.5f and %.0f micron\n",
4115 fprintf(
ioQQQ,
" Illegal value for grain size (upper limit)\n" );
4116 fprintf(
ioQQQ,
" Grain sizes should be between %.5f and %.0f micron\n",
4118 fprintf(
ioQQQ,
" and upper limit should be greater than lower limit\n" );
4125 if( sscanf( chLine,
"%lf", &sd->
a[
ipExp] ) != 1 )
4154 if( sscanf( chLine,
"%lf", &sd->
a[
ipExp] ) != 1 )
4163 if( sscanf( chLine,
"%lf", &sd->
a[
ipBeta] ) != 1 )
4179 step_neg = -mul*sd->
a[
ipSLo];
4181 step_pos = mul*sd->
a[
ipSHi];
4182 lgTryOverride =
true;
4196 step_pos = sd->
a[
ipGCen]*(exp(mul*sd->
a[ipGSig]) - 1.);
4197 lgTryOverride =
true;
4210 step_neg = -mul*sd->
a[
ipGSig];
4212 lgTryOverride =
true;
4220 fprintf(
ioQQQ,
" Illegal value for grain size (lower limit)\n" );
4221 fprintf(
ioQQQ,
" Grain sizes should be between %.5f and %.0f micron\n",
4233 fprintf(
ioQQQ,
" Illegal value for grain size (upper limit)\n" );
4234 fprintf(
ioQQQ,
" Grain sizes should be between %.5f and %.0f micron\n",
4236 fprintf(
ioQQQ,
" and upper limit should be greater than lower limit\n" );
4246 fprintf(
ioQQQ,
" Illegal value for no. of points in table\n" );
4256 for( i=0; i < sd->
npts; ++i )
4258 double help1, help2;
4262 if( sscanf( chLine,
"%le %le", &help1, &help2 ) != 2 )
4269 if( help1 <= 0. || help2 <= 0. )
4271 fprintf(
ioQQQ,
" Reading table failed on line #%ld of %s\n",dl,chFile );
4272 fprintf(
ioQQQ,
" Illegal data value %.6e or %.6e\n", help1, help2 );
4276 sd->
ln_a[i] = log(help1);
4279 if( i > 0 && sd->
ln_a[i] <= sd->
ln_a[i-1] )
4281 fprintf(
ioQQQ,
" Reading table failed on line #%ld of %s\n",dl,chFile );
4282 fprintf(
ioQQQ,
" Grain radii should be monotonically increasing\n" );
4292 fprintf(
ioQQQ,
" unimplemented case for grain size distribution in file %s\n" , chFile );
4318 fprintf(
ioQQQ,
" Illegal size limits: lower %.5f and/or upper %.5f\n",
4320 fprintf(
ioQQQ,
" Grain sizes should be between %.5f and %.0f micron\n",
4322 fprintf(
ioQQQ,
" and upper limit should be greater than lower limit\n" );
4323 fprintf(
ioQQQ,
" Please alter the size distribution file\n" );
4334 const char chLine[],
4340 if( sscanf( chLine,
"%ld", data ) != 1 )
4346 if( *data < 0 || (*data == 0 && lgZeroIllegal) )
4357 const char chLine[],
4364 if( sscanf( chLine,
"%lf", &help ) != 1 )
4371 if( *data < 0. || (*data == 0. && lgZeroIllegal) )
4382 const char chLine[],
4388 if( sscanf( chLine,
"%lf", data ) != 1 )
4394 if( *data < 0. || (*data == 0. && lgZeroIllegal) )
4418 string strWord( chWord );
4419 for( nelem=0; nelem <
LIMELM; nelem++ )
4423 if( chElmName[1] ==
' ' )
4424 chElmName[1] =
'\0';
4425 string::size_type ptr = strWord.find( chElmName );
4426 if( ptr != string::npos )
4428 len = (long)strlen(chElmName);
4430 if( !islower((
unsigned char)chWord[ptr+len]) )
4432 if( isdigit((
unsigned char)chWord[ptr+len]) )
4434 sscanf(chWord+ptr+len,
"%lf",&frac);
4442 elmAbun[nelem] =
frac;
4449 if( *no_atoms == 0. )
4464 for( nelem=0; nelem <
LIMELM; nelem++ )
4466 if( elmAbun[nelem] > 0. )
4469 long index100 =
nint(100.*elmAbun[nelem]);
4472 if( chElmName[1] ==
' ' )
4473 chElmName[1] =
'\0';
4475 if( index100 == 100 )
4476 sprintf( &chWord[len],
"%s", chElmName );
4477 else if( index100%100 == 0 )
4478 sprintf( &chWord[len],
"%s%ld", chElmName, index100/100 );
4481 double xIndex = (double)index100/100.;
4482 sprintf( &chWord[len],
"%s%.2f", chElmName, xIndex );
4484 len = (long)strlen( chWord );
4503 while( chLine[ip] ==
' ' || chLine[ip] ==
'"' )
4506 while( op < n-1 && chLine[ip] !=
' ' && chLine[ip] !=
'"' )
4508 chWord[op++] =
toupper(chLine[ip++]);
4510 chWord[op++] = chLine[ip++];
4531 while( chLine[0] ==
'#' )
4557 fprintf(
ioQQQ,
" This grain data file does not have the expected format.\n");
4580 const vector<double>& x,
4581 const vector<double>& a,
4591 bpa = (xtop+xbot)/2.;
4592 bma = (xtop-xbot)/2.;
4594 for( i=0; i < nn; i++ )
4596 rr[i] = bpa + bma*x[nn-1-i];
4625 const double SAFETY = 5.;
4636 vector<double> c(nn);
4641 for( j=1; j < nn; j++ )
4647 c[j] =
pow2(fj)/((fj-0.5)*(fj+0.5));
4651 for( i=0; i < nn/2; i++ )
4656 xt = 1. - 2.78/(4. +
pow2(fn));
4659 xt = xt - 4.1*(1. + 0.06*(1. - 8./fn))*(1. - xt);
4662 xt = xt - 1.67*(1. + 0.22*(1. - 8./fn))*(x[0] - xt);
4665 xt = 3.*(x[i-1] - x[i-2]) + x[i-3];
4668 for( iter=1; (iter < 20) && (fabs(d) > DBL_EPSILON); iter++ )
4677 for( j=1; j < nn; j++ )
4681 q = 2.*xt*pn - c[j]*pn1;
4682 dq = 2.*xt*dpn - c[j]*dp1 + 2.*pn;
4695 a[i] = cc/(dpn*2.*pn1);
4702 if( fabs(1.-csa) > SAFETY*fn*DBL_EPSILON )
4704 fprintf(
ioQQQ,
" gauss_legendre failed to converge: delta = %.4e\n", fabs(1.-csa) );
4716 const vector<double>& xa,
4719 bool *lgOutOfBounds)
4738 sgn =
sign3(xa[i3]-xa[i1]);
4745 *lgOutOfBounds = x <
min(xa[0],xa[n-1]) || x >
max(xa[0],xa[n-1]);
4746 if( *lgOutOfBounds )
4753 while( (i3-i1) > 1 )
4755 sgn2 =
sign3(x-xa[i2]);
4839 complex<double> cdum1,
4862 ci = complex<double>(0.,1.);
4863 nc = complex<double>(nre,-nim);
4887 t1 = x + 4.*xrd + 3.;
4891 if( !(x <= 8. || x >= 4200.) )
4892 t1 += 0.05*xrd + 3.;
4903 t4 = x*sqrt(nre*nre+nim*nim);
4920 vector< complex<double> > a(nmx1+1);
4928 for( n=0; n < nmx1; n++ )
4931 a[nn-1] = (double)(nn+1)*rrfx - 1./((double)(nn+1)*rrfx+a[nn]);
4940 wn2 = complex<double>(t1,-t2);
4941 wn1 = complex<double>(t2,t1);
4943 tc1 = a[0]*rrf + rx;
4945 sman = (tc1*wn.real() - wn1.real())/(tc1*wn - wn1);
4946 smbn = (tc2*wn.real() - wn1.real())/(tc2*wn - wn1);
4954 nc212 = (nc2-1.)/(nc2+2.);
4958 sman = ci*2.*x3*nc212*(1./3.+x*x*0.2*(nc2-2.)/(nc2+2.)) + 4.*x5*x*nc212*nc212/9.;
4959 smbn = ci*x5*(nc2-1.)/45.;
4968 *qext = 2.*(sman.real() + smbn.real());
4969 *qphase = 2.*(sman.imag() + smbn.imag());
4971 qbck = -2.*(sman - smbn);
4972 *qscat = (norm(sman) + norm(smbn))/.75;
4980 t1 = 2.*(double)n - 1.;
4981 t3 = 2.*(double)n + 1.;
4984 wn = t1*rx*wn1 - wn2;
4987 tc1 = cdum1*rrf + cdum2;
4988 tc2 = cdum1*nc + cdum2;
4989 sman = (tc1*wn.real() - wn1.real())/(tc1*wn - wn1);
4990 smbn = (tc2*wn.real() - wn1.real())/(tc2*wn - wn1);
4994 if( x < xcut && n == 2 )
4997 sman = ci*x5*(nc2-1.)/(15.*(2.*nc2+3.));
5001 eqext = t3*(sman.real() + smbn.real());
5003 eqpha = t3*(sman.imag() + smbn.imag());
5006 eqb = t3*(sman - smbn)*(
double)nsqbk;
5008 tx = norm(sman) + norm(smbn);
5011 t2 = (double)(n - 1);
5014 t2 = (t2*(t5 + 1.))/t5;
5015 ectb = t2*(sman1.real()*sman.real()+sman1.imag()*sman.imag() + smbn1.real()*smbn.real() +
5016 smbn1.imag()*smbn.imag()) +
5017 t4*(sman1.real()*smbn1.real()+sman1.imag()*smbn1.imag());
5025 eqext = fabs(eqext/ *qext);
5026 eqpha = fabs(eqpha/ *qphase);
5027 eqscat = fabs(eqscat/ *qscat);
5028 ectb = ( n == 2 ) ? 0. : fabs(ectb/ *ctbrqs);
5029 eqb = complex<double>( fabs(eqb.real()/qbck.real()), fabs(eqb.imag()/qbck.imag()) );
5031 error =
MAX4(eqext,eqpha,eqscat,ectb);
5033 error1 =
max(eqb.real(),eqb.imag());
5034 if( error < 1.e-07 && error1 < 1.e-04 )
5057 *qback = norm(qbck)*
pow2(rx);
5086 complex<double> cbigk,
5096 *xistar = sqrt(
pow2(xi)+
pow2(xii));
5098 ci = complex<double>(0.,1.);
5099 cw = -complex<double>(xi,xii)*ci;
5101 *qext = 4.*cbigk.real();
5102 *qphase = 4.*cbigk.imag();
5105 *qabs = 2.*cbigk.real();
5112 complex<double> *cbigk)
5120 if( abs(cw) < 1.e-2 )
5125 *cbigk = cw*((1./3.)-cw*((1./8.)-cw*((1./30.)-cw*((1./144.)-cw*((1./840.)-cw*(1./5760.))))));
5129 *cbigk = 0.5 + (exp(-cw)*(1.+cw)-1.)/(cw*cw);
5144 *eps1 = nr*nr - ni*ni;
5160 eps = sqrt(eps2*eps2+eps1*eps1);
5161 *nr = sqrt((eps+eps1)/2.);
5166 *ni = eps2/(2.*(*nr));
STATIC void mie_read_szd(const char *, sd_data *)
STATIC void mie_next_line(const char *, FILE *, char *, long int *)
static const double pah2c_strength[14]
STATIC void pah1_fun(double, const sd_data *, const grain_data *, double *, double *, double *, int *)
static const long LOOP_MAX
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
static const long MAGIC_OPC
static const double pah1_strength[7]
double Drude(double, double, double, double)
void gauss_legendre(long int, vector< double > &, vector< double > &)
vector< double > opcData[NDAT]
const int FILENAME_PATH_LENGTH_2
NORETURN void TotalInsanity(void)
void sincos(double x, double *s, double *c)
double no_atoms(size_t nd)
STATIC void Stognienko(complex< double >, const vector< double > &, const vector< complex< double > > &, long, complex< double > *, double *, double *)
void car2_fun(double, const sd_data *, const grain_data[], double *, double *, double *, int *)
STATIC void bigk(complex< double >, complex< double > *)
STATIC void ritodf(double, double, double *, double *)
string mesh_md5sum() const
STATIC double size_distr(double, const sd_data *)
STATIC void mie_read_long(const char *, const char[], long int *, bool, long int)
static const double pah1_width[7]
long nMatch(const char *chKey, const char *chCard)
static const double pah1_wlBand[7]
bool fp_equal_tol(sys_float x, sys_float y, sys_float tol)
const char * strstr_s(const char *haystack, const char *needle)
static const double pah3c_strength[30]
STATIC void anomal(double, double *, double *, double *, double *, double, double)
STATIC void mie_read_realnum(const char *, const char[], realnum *, bool, long int)
STATIC void ld01_fun(void(*)(double, const sd_data *, const grain_data[], double *, double *, double *, int *), double, double, double, const sd_data *, const grain_data[], double *, double *, double *, int *)
static const bool pah3_hoc[30]
STATIC void mie_write_form(const double[], char[])
double anu(size_t i) const
STATIC double search_limit(double, double, double, sd_data)
static t_version & Inst()
STATIC void mie_step(double, sd_data *, const grain_data *, void(*)(double, const sd_data *, const grain_data *, double *, double *, double *, int *), double *, double *, const double[], double *, double *, double *, int *)
void gauss_init(long int, double, double, const vector< double > &, const vector< double > &, vector< double > &, vector< double > &)
t_elementnames elementnames
STATIC void dftori(double *, double *, double, double)
long int nflux_with_check
STATIC void pah2_fun(double, const sd_data *, const grain_data *, double *, double *, double *, int *)
const double * anuptr() const
STATIC void Bruggeman(complex< double >, const vector< double > &, const vector< complex< double > > &, long, complex< double > *, double *, double *)
const multi_geom< d, ALLOC > & clone() const
bool fp_equal(sys_float x, sys_float y, int n=3)
static const int LABELSIZE
void find_arr(double, const vector< double > &, long int, long int *, bool *)
static const double pah2_width[14]
STATIC void sinpar(double, double, double, double *, double *, double *, double *, double *, long *)
vector< complex< double > > n[NAX]
STATIC void mie_repair(const char *, long, int, int, const double[], double[], vector< int > &, bool, bool *)
void mie_write_opc(const char *, const char *, long int)
static const double pah3_width[30]
static const double TOLER
static const double LARGEST_GRAIN
static const int LABELSUB1
void mie_read_opc(const char *, const GrainPar &)
void car1_fun(double, const sd_data *, const grain_data[], double *, double *, double *, int *)
STATIC void mie_read_form(const char *, double[], double *, double *)
static const double pah2n_strength[14]
double powi(double, long int)
STATIC void mie_cs(double, const sd_data *, const grain_data *, double *, double *, double *, int *)
const char * strchr_s(const char *s, int c)
diatomics h2("h2", 4100.,&hmi.H2_total, Yan_H2_CS)
STATIC void mie_read_rfi(const char *, grain_data *)
sys_float safe_div(sys_float x, sys_float y, sys_float res_0by0)
static const double SMALLEST_GRAIN
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
STATIC void mie_read_word(const char[], char[], long, bool)
vector< double > nr1[NAX]
STATIC void mie_cs_size_distr(double, sd_data *, const grain_data *, void(*)(double, const sd_data *, const grain_data *, double *, double *, double *, int *), double *, double *, double *, int *)
realnum AtomicWeight[LIMELM]
static const double SAFETY
ial_type which_ial[MAT_TOP]
static const long MAGIC_RFI
STATIC void mie_read_mix(const char *, grain_data *)
static const int LABELSUB2
vector< double > ln_a4dNda
static const long MAGIC_MIX
void car3_fun(double, const sd_data *, const grain_data[], double *, double *, double *, int *)
#define DEBUG_ENTRY(funcname)
STATIC complex< double > cnewton(void(*)(complex< double >, const vector< double > &, const vector< complex< double > > &, long, complex< double > *, double *, double *), const vector< double > &, const vector< complex< double > > &, long, complex< double >, double)
STATIC void pah3_fun(double, const sd_data *, const grain_data *, double *, double *, double *, int *)
static const unsigned int NMD5
STATIC void init_eps(double, long, const vector< grain_data > &, vector< complex< double > > &)
STATIC void mie_next_data(const char *, FILE *, char *, long int *)
int fprintf(const Output &stream, const char *format,...)
static const long MIX_TABLE_SIZE
static const double pah3_wavl[30]
STATIC void mie_auxiliary(sd_data *, const grain_data *, const char *)
STATIC void mie_integrate(sd_data *, double, double, double *)
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
STATIC double mie_find_slope(const double[], const double[], const vector< int > &, long, long, int, bool, bool *)
vector< string > ReadRecord
vector< double > wavlen[NAX]
STATIC void tbl_fun(double, const sd_data *, const grain_data *, double *, double *, double *, int *)
STATIC void mie_read_double(const char *, const char[], double *, bool, long int)
void set_version(phfit_version val)
double phfit(long int nz, long int ne, long int is, double e)
double getResolutionScaleFactor() const
static const double pah2_wavl[14]
STATIC bool mie_auxiliary2(vector< int > &, multi_arr< double, 2 > &, multi_arr< double, 2 > &, multi_arr< double, 2 > &, long, long)
static const long MAGIC_SZD
static const double pah3n_strength[30]
STATIC void mie_calc_ial(const grain_data *, long, vector< double > &, const char *, bool *)