NoDynSpectrum::NoDynSpectrum(float Tkelvin, float minNmVal, float maxNmVal, int numSamples) : N(numSamples), minNm(minNmVal), maxNm(maxNmVal), stepNm((maxNmVal - minNmVal)/float(numSamples-1)) { Assert(Tkelvin > 0); Assert(minNmVal <= maxNmVal); Assert(numSamples > 1 || minNmVal || maxNmVal); Assert(N <= SPECTRUM_MAX_NUM_SAMPLES && N > 0); if(minNmVal == maxNmVal && numSamples == 1){ //Delta spectrum case N = 1; minNm = maxNm = minNmVal; stepNm = 0.0f; data[0] = planck(minNm, Tkelvin); }else{ //Normal case float tempNm = minNmVal; for(int i = 0; i < N; i++){ data[i] = planck(tempNm, Tkelvin); tempNm += stepNm; } } assertInvariant(); }
int main( int argc, char *argv[]) { double nu, t; /* Check arguments... */ if (argc < 3) ERRMSG("Give parameters: <t> <nu>"); /* Read arguments... */ t = atof(argv[1]); nu = atof(argv[2]); /* Compute Planck function... */ printf("%.10g\n", planck(t, nu)); return EXIT_SUCCESS; }
int schwarzschild2(const double* deltatau, const double *T, const int nlev, const double Ts, double *edn, double *eup, const double lambdalow, const double lambdahigh, double* tmplev, double* tmplyr) { const double dmu = 0.1; // const double dtau = tau/(nlev-1); int ilev; double mu; /* Remove next for-loop for optimization, it is not needed */ for(ilev=0; ilev < nlev; ilev++) { eup[ilev] = 0; edn[ilev] = 0; } /* calculate planck for all layers(!!) */ for (ilev=0; ilev<nlev-1; ilev++) { tmplyr[ilev] = planck(T[ilev], lambdalow, lambdahigh); } /* * UP * ilev = 1, 2, ..., nlev-1 (=nlyr) * ilyr = 1, 2, ..., nlyr-1 * * Wegen up: ilev -1 = ilyr * * lup[ilev] = lup[ilev+1] exp(-dtau) + B(T[ilyr+1]) ( 1 - exp(-dtau) ) * quasi lup[ilyr] = lup[ilyr+1] exp(-dtau) + B(T[ilyr]) (1 - exp(-dtau)) * */ //Calculation of eup from surface tmplev[nlev-1] = planck(Ts, lambdalow, lambdahigh); eup[nlev-1] = tmplev[nlev-1]*M_PI; for (mu=dmu/2; mu <= 1; mu += dmu) { for (ilev=nlev-2;ilev>=0; ilev--) { // integration ueber raumwinkel -> 2*PI und Integration ueber mu tmplev[ilev] = TEmission_fast(deltatau[ilev]/mu, tmplev[ilev+1], tmplyr[ilev]); eup[ilev] += tmplev[ilev]*mu*dmu*2.0*M_PI; //printf(" eup[nlev-1] = %e\n", eup[nlev-1]); } } /* * DOWN * * ldn[ilev] = ldn[ilev-1] exp(-dtau) + B(T[ilyr-1]) ( 1-exp(-dtau)) * quasi ldn[ilyr] = ldn[ilyr-1] exp(-dtau) + B(T[ilyr]) (1-exp(-dtau)) * */ tmplev[0] = 0; edn[0] = 0; for (mu=dmu/2; mu <= 1; mu += dmu) { for (ilev=1; ilev<nlev; ilev++) { tmplev[ilev] = TEmission_fast(deltatau[ilev-1]/mu, tmplev[ilev-1], tmplyr[ilev-1]); edn[ilev] += tmplev[ilev]*mu*dmu*2.0*M_PI; } } // output of eup, L, edn // for (ilev=0; ilev < nlev; ilev++) { // if(ilev == 0) printf("\n"); // printf("--%02d-- ilev, eup = %f, ldn = %f, edn = %f \t--%02d--\n", ilev, eup[ilev], tmplev[ilev], edn[ilev], ilev); // } return EXIT_SUCCESS; }
double TEmission (double tau, const double Lbelow, const double Tlyr, const double lambda, const double lambda2) { //printf ("lup(): L = %f, tau=%f, Lbelow=%f, Tlyr=%f\n", tau, lup, Lbelow, Tlyr); return TEmission_fast(tau, Lbelow, planck(Tlyr, lambda, lambda2)); }
float * predict_thermal (long nGal, float * pGall, float * pGalb, float * pNu, char * pIPath, char * pResName, char * pUnitsName, int modelNum, int qInterp, int qNoloop, int qVerbose) { int ii; int im; int iz1 = -1; /* crash if Zindx not tabulated for alpha1 */ int iz2 = -1; /* crash if Zindx not tabulated for alpha2 */ int imap; int iGal; float * pI100; float * pRmapval; float * pInu; float alpha1; float alpha2; float f1; float q1q2; float RfitA[6]; float lnR; float lnRpow; float T1; float T2; float lnT1; float lnT2; float tcoeff; const float nu100 = 2997.92458; /* Frequency in GHz for 100-microns */ const float h_Pl = 6.6261e-27; /* cm^2 g s^-1 */ const float k_B = 1.3806e-16; /* erg K^-1 */ /* Declarations for command-line keyword names */ char pText_MJy[] = "MJy"; char pText_microK[] = "microK"; char pText_thermo[] = "thermo"; /* Declarations for data file names */ char pFileN[MAX_FILE_NAME_LEN]; char pFileS[MAX_FILE_NAME_LEN]; struct mapParms { char * pName; char * pFile1; char * pFile2; } ppMapAll[] = { { "D1024", "SFD_d100_1024_ngp.fits", "SFD_d100_1024_sgp.fits" }, { "I1024", "SFD_i100_1024_ngp.fits", "SFD_i100_1024_sgp.fits" }, { "I2048", "SFD_i100_2048_ngp.fits", "SFD_i100_2048_sgp.fits" }, { "I4096", "SFD_i100_4096_ngp.fits", "SFD_i100_4096_sgp.fits" } }; const int nmap = sizeof(ppMapAll) / sizeof(ppMapAll[0]); char * ppRmapFile[] = { "FINK_Rmap_ngp.fits" , "FINK_Rmap_sgp.fits" }; /* Set model parameters */ const float alpha1vec[] = {1.50, 1.70, 2.00, 2.20, 1.50, 2.00, 1.50, 1.67}; const float alpha2vec[] = {0.00, 0.00, 0.00, 0.00, 2.60, 2.00, 2.60, 2.70}; const float f1vec[] = {1.00, 1.00, 1.00, 1.00, 0.25, 0.00261, 0.0309, 0.0363}; const float q1q2vec[] = {1.00, 1.00, 1.00, 1.00, 0.61, 2480.0, 11.2, 13.0}; /* const int N_MODEL = sizeof(alpha1vec) / sizeof(alpha1vec[0]); */ /* Rfita contains fit coefficients for T2_of_R */ const float RfitAarr[][6] = {{2.9268E+00, 3.8419E-01, 5.0233E-02, 1.0852E-02, 3.0738E-03, 5.0595E-04}, {2.8483E+00, 3.8044E-01, 4.6584E-02, 9.0938E-03, 2.7038E-03, 5.4664E-04}, {2.7334E+00, 3.7537E-01, 4.1712E-02, 6.8839E-03, 2.0316E-03, 6.0311E-04}, {2.6556E+00, 3.7377E-01, 3.9898E-02, 5.7662E-03, 1.4638E-03, 6.3723E-04}, {2.9206E+00, 2.3254E-01, 2.3506E-02, 4.0781E-03, 1.0048E-03, 1.2004E-04}, {2.9900E+00, 2.5041E-01, 2.9688E-02, 6.5641E-03, 1.5688E-03, 1.6542E-04}, {2.8874E+00, 2.4172E-01, 2.9369E-02, 4.7867E-03, 9.7237E-04, 1.1410E-04}, {2.8723E+00, 2.4071E-01, 2.9625E-02, 4.7196E-03, 9.3207E-04, 1.1099E-04} }; /* Zeta integrals for alpha=[1.50, 1.67, 1.70, 2.00, 2.20, 2.60, 2.70] from equn (15) of Finkbeiner et al. */ const float Zindx[] = {1.50, 1.67, 1.70, 2.00, 2.20, 2.60, 2.70}; const float Zintegral[] = {5.3662E+01, 7.0562E+01, 7.4100E+01, 1.2208E+02, 1.7194E+02, 3.4855E+02, 4.1770E+02}; const int N_ZINDEX = sizeof(Zindx) / sizeof(Zindx[0]); /* Test that inputs are valid */ if (nGal == 0 || pGall == NULL || pGalb == NULL || pNu == NULL) { printf("ERROR: Must specify coordinates and frequencies.\n"); return NULL; } /* Select parameters for this model */ alpha1 = alpha1vec[modelNum-1]; alpha2 = alpha2vec[modelNum-1]; f1 = f1vec[modelNum-1]; q1q2 = q1q2vec[modelNum-1]; for (ii=0; ii < 6; ii++) RfitA[ii] = RfitAarr[modelNum-1][ii]; /* Determine the file names to use */ for (imap=0; imap < nmap; imap++) { if (strcmp(pResName,ppMapAll[imap].pName) == 0) { sprintf(pFileN, "%s/%s", pIPath, ppMapAll[imap].pFile1); sprintf(pFileS, "%s/%s", pIPath, ppMapAll[imap].pFile2); } } /* Read the 100-micron map */ pI100 = lambert_getval(pFileN, pFileS, nGal, pGall, pGalb, qInterp, qNoloop, qVerbose); /* Read the I100/240 ratio map */ sprintf(pFileN, "%s/%s", pIPath, ppRmapFile[0]); sprintf(pFileS, "%s/%s", pIPath, ppRmapFile[1]); pRmapval = lambert_getval(pFileN, pFileS, nGal, pGall, pGalb, qInterp, qNoloop, qVerbose); /* Allocate memory for output array */ pInu = ccvector_build_(nGal); if (modelNum <=4) { /* SINGLE-COMPONENT MODEL: Evaluate equn (1) from Finkbeiner et al */ for (iGal=0; iGal < nGal; iGal++) { /* Compute ln(T1) from ln(Rmap) */ lnR = log(pRmapval[iGal]); lnRpow = 1.0; lnT1 = RfitA[0]; for (ii=1; ii < 6; ii++) { lnRpow *= lnR; lnT1 += RfitA[ii] * lnRpow; } T1 = exp(lnT1); pInu[iGal] = pI100[iGal] * pow(pNu[iGal]/nu100,alpha1) * planck(T1,pNu[iGal]) / ( planck(T1,nu100) * kfactor(alpha1,T1) ); } } else { /* TWO-COMPONENT MODEL: Evaluate equn (6) from Finkbeiner et al */ /* Find Zintegral index for the model values of "alpha" */ for (im=0; im < N_ZINDEX; im++) { if (fabs(Zindx[im] - alpha1) < 1.e-4) iz1 = im; if (fabs(Zindx[im] - alpha2) < 1.e-4) iz2 = im; } tcoeff = pow( (Zintegral[iz2] / (q1q2*Zintegral[iz1])) * pow(h_Pl*nu100*1.e+9/k_B,alpha1-alpha2), 1./(4.+alpha1) ); for (iGal=0; iGal < nGal; iGal++) { /* Compute ln(T2) from ln(Rmap) */ lnR = log(pRmapval[iGal]); lnRpow = 1.0; lnT2 = RfitA[0]; for (ii=1; ii < 6; ii++) { lnRpow *= lnR; lnT2 += RfitA[ii] * lnRpow; } T2 = exp(lnT2); /* Compute T1 as a function of T2; equn (13) of Finkbeiner et al. */ T1 = tcoeff * pow( T2, ((4+alpha2)/(4+alpha1)) ); pInu[iGal] = pI100[iGal] * ( f1 * q1q2 * pow(pNu[iGal]/nu100,alpha1) * planck(T1,pNu[iGal]) + (1-f1) * pow(pNu[iGal]/nu100,alpha2) * planck(T2,pNu[iGal]) ) / ( f1 * q1q2 * planck(T1,nu100) * kfactor(alpha1,T1) + (1-f1) * planck(T2,nu100) * kfactor(alpha2,T2) ); } } /* Convert units */ if (strcmp(pUnitsName,pText_MJy) == 0) { /* MJy/sr */ } else if (strcmp(pUnitsName,pText_microK) == 0) { /* brightness temp micro-K */ for (iGal=0; iGal < nGal; iGal++) pInu[iGal] *= fac_flux2temp(pNu[iGal]); } else if (strcmp(pUnitsName,pText_thermo) == 0) { /* thermodynamic micro-K */ for (iGal=0; iGal < nGal; iGal++) pInu[iGal] *= fac_flux2temp(pNu[iGal]) * planckcorr(pNu[iGal]); } else { printf("ERROR: Invalid units name.\n"); for (iGal=0; iGal < nGal; iGal++) pInu[iGal] = 0.0; } ccvector_free_(pI100); ccvector_free_(pRmapval); return pInu; }
void nemo_main() { int colnr[2]; real *coldat[2], *xdat, *ydat, xmin, xmax, ymin, ymax; real *udat, *vdat, umin, umax, vmin, vmax; real x, y1, y2, dx, xscale, yscale, xQmin, xQmax; real tbb,sum,sum0; stream instr, tabstr; int i, n, ns, nmax; real *sdat, *spdat; string spectrum, filter = filtername(getparam("filter")); bool Qnorm = getbparam("normalize"); bool Qmin = hasvalue("xmin"); bool Qmax = hasvalue("xmax"); bool Qtab = hasvalue("out"); nmax = nemo_file_lines(filter,MAXLINES); xdat = coldat[0] = (real *) allocate(nmax*sizeof(real)); ydat = coldat[1] = (real *) allocate(nmax*sizeof(real)); colnr[0] = 1; /* wavelenght in angstrom */ colnr[1] = 2; /* normalized filter response [0,1] */ instr = stropen(filter,"r"); n = get_atable(instr,2,colnr,coldat,nmax); strclose(instr); if (Qtab) tabstr = stropen(getparam("out"),"w"); for(i=0; i<n; i++) { dprintf(2,"%g %g\n",xdat[i],ydat[i]); if (i==0) { xmin = xmax = xdat[0]; ymin = ymax = ydat[0]; } else { if (xdat[i] <= xdat[i-1]) error("Filter %s must be sorted in wavelength",filter); xmax = MAX(xmax,xdat[i]); ymax = MAX(ymax,ydat[i]); xmin = MIN(xmin,xdat[i]); ymin = MIN(ymin,ydat[i]); } } dprintf(1,"Filter wavelength range: %g : %g\n",xmin,xmax); dprintf(1,"Filter response range: %g : %g\n",ymin,ymax); if (ydat[0] != 0) warning("lower edge filter response not 0: %g",ydat[0]); if (ydat[n-1] != 0) warning("upper edge filter response not 0: %g",ydat[n-1]); dx = getdparam("step"); if ((xmax-xmin)/100 < dx) { warning("Integration step %g in Angstrom too large, resetting to %g", dx, (xmax-xmin)/100); dx = (xmax-xmin)/100; } /* setup a spline interpolation table into the filter */ sdat = (real *) allocate(sizeof(real)*n*3); spline(sdat,xdat,ydat,n); if (Qmin) { /* override any min/max rules ? */ xQmin = getdparam("xmin"); if (xQmin > xmin) warning("xmin=%g greater than minimum in filter (%g)",xQmin,xmin); } if (Qmax) { xQmax = getdparam("xmax"); if (xQmax < xmax) warning("xmax=%g less than maximum in filter (%g)",xQmax,xmax); } if (hasvalue("tbb")) { /* using a Planck curve */ tbb = getdparam("tbb"); if (Qmin) xmin = xQmin; if (Qmax) xmax = xQmax; sum = sum0 = 0; for (x = xmin; x <= xmax; x += dx) { y1 = seval(x,xdat,ydat,sdat,n); /* filter */ y2 = planck(x,tbb); dprintf(3,"%g %g %g\n",x,y1,y2); if (Qtab) fprintf(tabstr,"%g %g\n",x,MAX(DATAMIN,y1*y2)); sum += y1*y2; sum0 += y1; } if (Qnorm) sum /= sum0; else sum *= dx; if (Qtab) dprintf(0,"%g %g %g\n",tbb,sum,-2.5*log10(sum)); else printf("%g %g %g\n",tbb,sum,-2.5*log10(sum)); } else if (hasvalue("spectrum")) { warning("spectrum= is a new feature"); spectrum = getparam("spectrum"); nmax = nemo_file_lines(spectrum,MAXLINES); udat = coldat[0] = (real *) allocate(nmax*sizeof(real)); vdat = coldat[1] = (real *) allocate(nmax*sizeof(real)); colnr[0] = getiparam("xcol"); colnr[1] = getiparam("ycol"); instr = stropen(spectrum,"r"); ns = get_atable(instr,2,colnr,coldat,nmax); strclose(instr); xscale = getdparam("xscale"); yscale = getdparam("yscale"); for(i=0; i<ns; i++) { dprintf(2,"%g %g\n",udat[i],vdat[i]); udat[i] *= xscale; vdat[i] *= yscale; if (i==0) { umin = umax = udat[0]; vmin = vmax = vdat[0]; } else { if (udat[i] <= udat[i-1]) error("Spectrum %s must be sorted in wavelength",spectrum); umax = MAX(umax,udat[i]); vmax = MAX(vmax,vdat[i]); umin = MIN(umin,udat[i]); vmin = MIN(vmin,vdat[i]); } } dprintf(1,"Spectrum wavelength range: %g : %g\n",umin,umax); dprintf(1,"Spectrum response range: %g : %g\n",vmin,vmax); if (umax < xmin || umin >xmax) error("Spectrum and filter do not overlap"); /* setup a spline interpolation table into the spectrum */ spdat = (real *) allocate(sizeof(real)*n*3); spline(spdat,udat,vdat,ns); sum = sum0 = 0; if (Qmin) xmin = xQmin; if (Qmax) xmax = xQmax; for (x = xmin; x <= xmax; x += dx) { y1 = seval(x,xdat,ydat,sdat,n); /* filter */ if (umin < x && x <umax) y2 = seval(x,udat,vdat,spdat,ns); /* spectrum */ else y2 = 0.0; dprintf(3,"%g %g %g\n",x,y1,y2); if (Qtab) fprintf(tabstr,"%g %g\n",x,MAX(DATAMIN,y1*y2)); sum += y1*y2; sum0 += y1; } if (Qnorm) sum /= sum0; else sum *= dx; if (Qtab) dprintf(0,"0 %g %g\n",sum,-2.5*log10(sum)); else printf("0 %g %g\n",sum,-2.5*log10(sum)); } else warning("Either spectrum= or tbb= must be used"); }