import numpy as np from hyperion.model import Model from hyperion.util.constants import pc, lsun # Initialize model m = Model() # Set one-cell cartesian grid w = np.linspace(-pc, pc, 32) m.set_cartesian_grid(w, w, w) # Add density grid with constant density m.add_density_grid(np.ones(m.grid.shape) * 4.e-20, 'kmh_lite.hdf5') # Add a point source in the center s = m.add_point_source() s.luminosity = 1000 * lsun s.temperature = 6000. # Add 10 SEDs for different viewing angles image = m.add_peeled_images(sed=True, image=False) image.set_wavelength_range(250, 0.01, 5000.) image.set_viewing_angles(np.linspace(0., 90., 10), np.repeat(20., 10)) image.set_track_origin('basic') # Add multi-wavelength image for a single viewing angle image = m.add_peeled_images(sed=False, image=True) image.set_wavelength_range(30, 1., 1000.) image.set_viewing_angles([30.], [20.]) image.set_image_size(200, 200)
import numpy as np from hyperion.model import Model from hyperion.util.constants import au, lsun, rsun from hyperion.dust import SphericalDust # Model m = Model() dist = 20000 * au x = np.linspace(-dist, dist, 101) y = np.linspace(-dist, dist, 101) z = np.linspace(-dist, dist, 101) m.set_cartesian_grid(x,y,z) # Dust d = SphericalDust('kmh.hdf5') d.set_sublimation_temperature('fast', temperature=1600.) m.add_density_grid(np.ones((100,100,100)) * 1.e-18,'kmh.hdf5') # Alpha centauri sourceA = m.add_spherical_source() sourceA.luminosity = 1.519 * lsun sourceA.radius = 1.227 * rsun sourceA.temperature = 5790. sourceA.position = (0., 0., 0.) # Beta centauri sourceB = m.add_spherical_source() sourceB.luminosity = 0.5 * lsun sourceB.radius = 0.865 * rsun sourceB.temperature = 5260.
# A simple model with no dust, just sources, to check that the Doppler Shifting # is working correctly. This model consists of a disk of sources that is # rotating in a solid body fashion around the origin. All sources have a # spectrum that consists of a single spectral line that is narrow enough that we # can easily see the rotation in a multi-wavelength image. We check that the # image looks sensible in both binned and peeled images. # Same as setup_indiv but using a point source collection import numpy as np from hyperion.model import Model from hyperion.util.constants import c m = Model() m.set_cartesian_grid([-1., 1], [-1., 1.], [-1., 1]) N = 100000 w = np.random.random(N)**0.5 p = np.random.uniform(0, 2 * np.pi, N) z = np.random.uniform(-0.1, 0.1, N) x = w * np.cos(p) y = w * np.sin(p) # solid body with 1000 km/s on the outside v = w * 1e8 # cm / s vx = - v * np.sin(p) vy = + v * np.cos(p) vz = np.repeat(0, N)
import numpy as np from hyperion.model import Model from hyperion.util.constants import pc, lsun # Initialize model m = Model() # Set up 64x64x64 cartesian grid w = np.linspace(-pc, pc, 64) m.set_cartesian_grid(w, w, w) # Add density grid with constant density and add a higher density cube inside to # cause a shadow. density = np.ones(m.grid.shape) * 1e-21 density[26:38, 26:38, 26:38] = 1.e-18 m.add_density_grid(density, 'kmh_lite.hdf5') # Add a point source in the center s = m.add_point_source() s.position = (0.4 * pc, 0., 0.) s.luminosity = 1000 * lsun s.temperature = 6000. # Add multi-wavelength image for a single viewing angle image = m.add_peeled_images(sed=False, image=True) image.set_wavelength_range(1, 190., 210.) image.set_viewing_angles(np.repeat(45., 36), np.linspace(5., 355., 36)) image.set_image_size(400, 400) image.set_image_limits(-1.5 * pc, 1.5 * pc, -1.5 * pc, 1.5 * pc)
# A simple model to check what happens when a source is moving towards dust and # we observe both the source and the dust. If we observe the source such that # the dust is directly behind, and the source is moving towards the dust, we # should see red-shifted emission from the source and blue-shifted scattered # light emission. import numpy as np from hyperion.model import Model from hyperion.util.constants import c m = Model() m.set_cartesian_grid([-1., 0, 1], [-1., 1.], [-1., 1]) density = np.zeros(m.grid.shape) density[:, :, 0] = 1. m.add_density_grid(density, 'kmh_lite.hdf5') # narrow emission line spectrum at 1 micron wav = np.array([0.9999, 1.0001]) fnu = np.array([1., 1.]) nu = c / (wav * 1.e-4) s = m.add_spherical_source() s.position = 0.5, 0., 0. s.velocity = -1e8, 0., 0. s.spectrum = nu[::-1], fnu[::-1] s.luminosity = 1 s.radius = 0.1
def run_thermal_hyperion(self, nphot=1e6, mrw=False, pda=False, \ niterations=20, percentile=99., absolute=2.0, relative=1.02, \ max_interactions=1e8, mpi=False, nprocesses=None): d = [] for i in range(len(self.grid.dust)): d.append(IsotropicDust( \ self.grid.dust[i].nu[::-1].astype(numpy.float64), \ self.grid.dust[i].albedo[::-1].astype(numpy.float64), \ self.grid.dust[i].kext[::-1].astype(numpy.float64))) m = HypModel() if (self.grid.coordsystem == "cartesian"): m.set_cartesian_grid(self.grid.w1*AU, self.grid.w2*AU, \ self.grid.w3*AU) elif (self.grid.coordsystem == "cylindrical"): m.set_cylindrical_polar_grid(self.grid.w1*AU, self.grid.w3*AU, \ self.grid.w2) elif (self.grid.coordsystem == "spherical"): m.set_spherical_polar_grid(self.grid.w1*AU, self.grid.w2, \ self.grid.w3) for i in range(len(self.grid.density)): if (self.grid.coordsystem == "cartesian"): m.add_density_grid(numpy.transpose(self.grid.density[i], \ axes=(2,1,0)), d[i]) if (self.grid.coordsystem == "cylindrical"): m.add_density_grid(numpy.transpose(self.grid.density[i], \ axes=(1,2,0)), d[i]) if (self.grid.coordsystem == "spherical"): m.add_density_grid(numpy.transpose(self.grid.density[i], \ axes=(2,1,0)), d[i]) sources = [] for i in range(len(self.grid.stars)): sources.append(m.add_spherical_source()) sources[i].luminosity = self.grid.stars[i].luminosity * L_sun sources[i].radius = self.grid.stars[i].radius * R_sun sources[i].temperature = self.grid.stars[i].temperature m.set_mrw(mrw) m.set_pda(pda) m.set_max_interactions(max_interactions) m.set_n_initial_iterations(niterations) m.set_n_photons(initial=nphot, imaging=0) m.set_convergence(True, percentile=percentile, absolute=absolute, \ relative=relative) m.write("temp.rtin") m.run("temp.rtout", mpi=mpi, n_processes=nprocesses) n = ModelOutput("temp.rtout") grid = n.get_quantities() self.grid.temperature = [] temperature = grid.quantities['temperature'] for i in range(len(temperature)): if (self.grid.coordsystem == "cartesian"): self.grid.temperature.append(numpy.transpose(temperature[i], \ axes=(2,1,0))) if (self.grid.coordsystem == "cylindrical"): self.grid.temperature.append(numpy.transpose(temperature[i], \ axes=(2,0,1))) if (self.grid.coordsystem == "spherical"): self.grid.temperature.append(numpy.transpose(temperature[i], \ axes=(2,1,0))) os.system("rm temp.rtin temp.rtout")
# A simple model to check what happens when a source is moving towards dust and # we observe both the source and the dust. If we observe the source such that # the dust is directly behind, and the source is moving towards the dust, we # should see red-shifted emission from the source and blue-shifted scattered # light emission. import numpy as np from hyperion.model import Model from hyperion.util.constants import c m = Model() m.set_cartesian_grid([-1.0, 0, 1], [-1.0, 1.0], [-1.0, 1]) density = np.zeros(m.grid.shape) density[:, :, 0] = 1.0 m.add_density_grid(density, "kmh_lite.hdf5") # narrow emission line spectrum at 1 micron wav = np.array([0.9999, 1.0001]) fnu = np.array([1.0, 1.0]) nu = c / (wav * 1.0e-4) s = m.add_spherical_source() s.position = 0.5, 0.0, 0.0 s.velocity = -1e8, 0.0, 0.0 s.spectrum = nu[::-1], fnu[::-1] s.luminosity = 1 s.radius = 0.1
# Global geometry: # # * slab # * system size = 10x10x10 pc # * system coordinates (x,y,z min/max) = -5 to +5 pc # * slab z extent = -2 to -5 pc # * slab xy extend = -5 pc to 5 pc # * z optical depth @0.55um in slab = 0.1, 1, 20 # * optical depth outside slab = 0 x = np.linspace(-5 * pc, 5 * pc, 100) y = np.linspace(-5 * pc, 5 * pc, 100) z = np.hstack([np.linspace(-5 * pc, -2 * pc, 100), 5 * pc]) m.set_cartesian_grid(x, y, z) # Grain Properties: d = SphericalDust('integrated_hg_scattering.hdf5') chi_v = d.optical_properties.interp_chi_wav(0.55) # Determine density in slab rho0 = tau_v / (3 * pc * chi_v) # Set up density grid density = np.ones(m.grid.shape) * rho0 density[-1,:,:] = 0. m.add_density_grid(density, d)
def __init__(self, par, **kwargs): #Set up dust model for Hyperion # Initalize the model m = Model() #Set central source position m.add_spherical_source(luminosity = par.get('lsource',1.0*lsun), radius = par.get('rsource',1.0*rsun), mass = par.get('msource',1.0*msun), temperature = par.get('tsource',5784.0), position = par.get('position',(0.0,0.0,0.0)) # Use raytracing to improve s/n of thermal/source emission m.set_raytracing(par.get('raytracing',True)) # Use the modified random walk m.set_mrw(par.get('modrndwlk',True), gamma=par.get('mrw_gamma',2)) # Set up spatial grid x = np.linspace(-1.5*par.get('rmax',100.*u.au), 1.5*par.get('rmax',100.*u.au), par.get('ngrid',257)) y = np.linspace(-1.5*par.get('rmax',100.*u.au), 1.5*par.get('rmax',100.*u.au), par.get('ngrid',257)) z = np.linspace(-1.5*par.get('rmax',100.*u.au), 1.5*par.get('rmax',100.*u.au), par.get('ngrid',257)) m.set_cartesian_grid(x,y,z) print("Spatial grid set up.") #Set up density grid rho0 = par.get('rho0',1.5e-19) alpha_in = par.get('alpha_in',-5.) alpha_out = par.get('alpha_out',5.) scaleheight= par.get('scaleheight',0.1) rmin = par.get('rmin',70.*u.au) rmax = par.get('rmax',100.*u.au) rmid = (rmax + rmin) / 2 rr = np.sqrt(m.grid.gx ** 2 + m.grid.gy ** 2 + m.grid.gz ** 2) #define density grid density = np.zeros(m.grid.shape) density = rho0 * ( (rr/rmid)**(2.*alpha_in) + (rr/rmid)**(2.*alpha_out) )**(-0.5) * np.exp(-((abs(m.grid.gz)/rr)**2/scaleheight**2)/2.0) m.add_density_grid(density, d) print("Density grid set up.") # Set up SED for 10 viewing angles sed = m.add_peeled_images(sed=par.get('api_sed',True), image=par.get('api_img',False)) sed.set_viewing_angles(np.linspace(0., 90., 10), np.repeat(45., 10)) sed.set_wavelength_range(par.get('nl',101), par.get('lmin',0.1), par.get('lmax',1000.)) sed.set_track_origin('basic') # Set number of photons m.set_n_photons(initial=par.get('nph_initial',1e4), imaging=par.get('nph_imging',1e5), raytracing_sources=par.get('nph_rtsrcs',1e5), raytracing_dust=par.get('nph_rtdust',1e5)) # Set number of temperature iterations m.set_n_initial_iterations(par.get('niter',5)) # Write out file m.write('HyperionRT_sed.rtin') print("Hyperion RT model created.") def __call__(self, *args, **kwargs): m.run('HyperionRT_sed.rtout', mpi=True,n_processes=6,overwrite=True) print("Hyperion RT model executed.") m = ModelOutput('HyperionRT_sed.rtout') self.modelFlux = sed.value def lnprior(self, theta, **kwargs): if self.flatprior: if (self.lims[0,0] < theta[0] < self.lims[0,1]) and \ (self.lims[1,0] < theta[1] < self.lims[1,1]) and \ (self.lims[2,0] < theta[2] < self.lims[2,1]) and \ (self.lims[3,0] < theta[3] < self.lims[3,1]) and \ np.sum(10**theta[4:]) <= 1. and np.all(theta[4:] < 0.): return 0 else: return -np.inf else: raise NotImplementedError() def __str__(self, **kwargs): raise NotImplementedError() def __repr__(self, **kwargs): raise NotImplementedError() def inputFile(self, **kwargs): #Create a dictionary with which to setup and run Hyperion RT models #Dust parameters par = {'dust':'"astrosilicate"', 'format':2, 'size':0.5, 'amin':0.5, 'amax':1000., 'na':101, 'nang':91, 'nanx':11, 'nchem':1, 'gtd':0, 'lmin':0.1, 'lmax':1000.0, 'nl':101, 'massfrac':1.0, 'rho0':1.5e-19, 'optconst':'"silicate_d03.lnk"', 'disttype':'power', 'q':3.5, #Source parameters 'lsource': 1.0*u.lsun, 'rsource': 1.0*u.rsun, 'msource': 1.0*u.msun, 'tsource': 5784., 'position':[0.0,0.0,0.0], #Disc parameters 'rmin': 70.*u.au, 'rmax': 100.*u.au, 'alpha_in': -5., 'alpha_out': 5., 'scaleheight': 0.1, #RT parameters 'niter':5, 'nph_initial':1e4, 'nph_imging':1e5, 'nph_rtsrcs':1e5, 'nph_rtdust':1e5, #Peel photons to get images 'api_sed':True, 'api_img':False, } return par #convenience function to plot the SED of the Hyperion RT output def plot_sed(par): #Set up figure import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(1, 1, 1) #Read in Hyperion model output try: m = ModelOutput('HyperionRT_sed.rtout') #Total SED sed = m.get_sed(inclination=0, aperture=-1, distance=par['distance'], component='total',units='Jy') ax.loglog(sed.wav, sed.val, color='black', lw=3, alpha=0.5) # Direct stellar photons sed = m.get_sed(inclination=0, aperture=-1, distance=par['distance'], component='source_emit',units='Jy') ax.loglog(sed.wav, sed.val, color='blue') # Scattered stellar photons sed = m.get_sed(inclination=0, aperture=-1, distance=par['distance'], component='source_scat',units='Jy') ax.loglog(sed.wav, sed.val, color='teal') # Direct dust photons sed = m.get_sed(inclination=0, aperture=-1, distance=par['distance'], component='dust_emit',units='Jy') ax.loglog(sed.wav, sed.val, color='red') # Scattered dust photons sed = m.get_sed(inclination=0, aperture=-1, distance=par['distance'], component='dust_scat',units='Jy') ax.loglog(sed.wav, sed.val, color='orange') ax.set_xlabel(r'$\lambda$ [$\mu$m]') ax.set_ylabel(r'Flux [Jy]') ax.set_xlim(par.get('lmin',0.1), par.get('lmax',1000.)) ax.set_ylim(1e-6*np.max(sed.value),1.1*np.max(sed.value)) fig.savefig('HyperionRT_sed_plot_components.png') plt.close(fig) except IOError: print("No Hyperion RT output found, SED not plotted.") #convenience function to write dust parameter file '<dust>.params' for Hyperion BHDust calculator (separate program) def write_bhmie_file(par): f=open(par.get('dust','astrosilicate')+'.params','w') f.write('"'+par['dust']+'_'+str(par['size'])+'"'+'\n') f.write(str(par['format'])+'\n') f.write(str(par['amin'])+'\n') f.write(str(par['amax'])+'\n') f.write(str(par['na'])+'\n') f.write(str(par['nang'])+'\n') f.write(str(par['nanx'])+'\n') f.write(str(par['nchem'])+'\n') f.write(str(par['gtd'])+'\n') f.write(str(par['lmin'])+' '+str(par['lmax'])+' '+str(par['nl'])+'\n') f.write(''+'\n') f.write(str(par['massfrac'])+'\n') f.write(str(par['rho0'])+'\n') f.write(str(par['optconst'])+'\n') f.write(str(par['disttype'])+'\n') f.write(str(par['amin'])+' '+str(par['amax'])+' '+str(par['q'])+'\n') f.close() print("BHMie dust input file created.") import subprocess subprocess.run(['bhmie',param_file]) print("BHMie dust output file created")