def test(): "check RT is working by comparing the fluxes from an optically thick and thin sphere to the analytic formulae" x, y, z = mgrid[-1:1:100j, -1:1:100j, -1:1:100j] rho = ones((100, 100, 100), dtype=float) * cns.m_p * 1000 * 1 rho[sqrt(x * x + y * y + z * z) > 0.999] *= 1.0e-10 temp = ones_like(rho) * 1.0e4 RT = freeFree( rho, zeros_like(rho), temp, zeros_like([rho, rho, rho]), 1.5e11 ) # RT for a sphere 1au in diameter @T=10,000 n=1/cc thinim = RT.rayTrace(2.0e9) ne = rho / (cns.m_p * 1000) thinAnalytic = ( (6.8e-38 * ne ** 2 * RT.gaunts[0] / sqrt(1.0e4) * exp(-cns.h * 2e9 / cns.Boltzmann / 1.0e4)).sum() * RT.length ** 3 * 1e23 / (4 * pi * (500 * PC2CM) ** 2) ) assert almost_eq(thinim.sum() / 1000, thinAnalytic, diff=0.1) print "optically thin test ok (ratio %.3f)" % ( thinim.sum() / 1000 / thinAnalytic ) # usually a bit out as analytic only inculdes hydrogen, within 10% at low temps thinPow = [log10(RT.rayTrace(x * 1e8, suppressOutput=True).sum()) for x in xrange(1, 11)] thinpf = polyfit([log10(x) for x in xrange(1, 11)], thinPow, 1)[0] # assert almost_eq(thinpf, -0.1, 0.05) print "powerlaw spectrum for thin sphere", thinpf # thin line test RT.cleartau() Bgam = 138475490718753.05 lineim = RT.rayTrace(Bgam, ff=0, lines=(7, 4)) lineAnalytic = ( line.Einf * (4.0 ** -2 - 7.0 ** -2) * line.LTE10K[7 - 1] * RT.rho.sum() * RT.length ** 3 / cns.m_p * line.einsteinA(7, 4) * 1e23 / (4 * pi * (500 * PC2CM) ** 2) ) print lineim.sum(), lineAnalytic rho *= 1e8 # optically thick sphere RT = freeFree(rho, zeros_like(rho), temp, zeros_like([rho, rho, rho]), 1.5e11) thickim = RT.rayTrace(1.0e9) thickAnalytic = pi * (RT.length * 50) ** 2 * bb(1.0e4, 1.0e9) * 1e23 / (500 * PC2CM) ** 2 # assert almost_eq(thickim.sum()/1000,thickAnalytic, diff=0.1) print "optically thin test ok (ratio %.3f)" % (thickim.sum() / 1000 / thickAnalytic) thickPow = [log10(RT.rayTrace(x * 1e9, suppressOutput=True).sum()) for x in xrange(1, 11)] thickpf = polyfit([log10(x) for x in xrange(1, 11)], thickPow, 1)[0] assert almost_eq(thickpf, 2, 0.01) print "powerlaw spectrum for thick sphere", thickpf return RT
def rayTrace( self, nu, theta=0, phi=0, dist=500, ff=1, lines=0, returnRotatedCube=0, transpose=0, suppressOutput=False ): "integrate along the specified axis after rotating the cube through phi and theta (in deg)" if dist < 1e9: dist *= PC2CM # assume distances less than 10^9 are given im parsecs, larger in cm try: flag = self.dt.any() and almost_eq(nu, self.lastnu) except: flag = 0 if theta == 0 and phi == 0: tempcube = self if flag: if not (suppressOutput): print "reusing dt" else: if not (suppressOutput): print "calculating taus" self.taus(nu, ff, lines) self.lastnu = nu else: tempcube = freeFree(self.rho.copy(), self.rhoN.copy(), self.t.copy(), self.V.copy(), self.length) tempcube.rotatecube(theta, phi) if not (suppressOutput): print "calculating taus" tempcube.taus(nu) # f=lambda x : Cfunc(x,self.length, x.size) # f=lambda x : integratePY(x,self.length) s = tempcube.dt.shape source = tempcube.eps / tempcube.kap source[source != source] = 0 tempcube.dt[tempcube.dt < 1e-30] = 1e-30 # dont allow tau of cell to be less than 1e-30 if not (suppressOutput): print ("integrating") if transpose: out = integrate( (source.T)[..., ::-1], (tempcube.dt.T)[..., ::-1] ) # integrate from back to front so we are looking down from from +z else: out = integrate(source[..., ::-1], tempcube.dt[..., ::-1]) pix = abs(self.length / dist) self.im = out * pix * pix * SQRAD2STR * 1e23 * 1000 if returnRotatedCube: return self.im, tempcube else: return self.im # output in mJy/pix
def gaunt(t,z,nu): if almost_eq(t,t.flat[0], 1e-6).all(): return ones_like(t)*ghelp(t.flat[0],z,nu) else: return gh(t,z,nu)