Luminosity sources

General notes

Sources can be added to the model using methods of the form m.add_*_source(). For example adding a point source can be done with:

source = m.add_point_source()

These methods return a source ‘object’ that can be used to set and modify the source parameters:

source = m.add_point_source()
source.luminosity = lsun
source.temperature = 10000.
source.position = (0., 0., 0.)

Note

It is also possible to specify the parameters using keyword arguments during initialization, e.g.:

m.add_point_source(luminosity=lsun, temperature=10000.,
                   position=(0., 0., 0.))

though this can be longer to read for sources with many arguments.

All sources require a luminosity, given by the luminosity attribute (or luminosity= argument), and the emission spectrum can be defined in one of three ways:

  • by specifying a spectrum using the spectrum attribute (or spectrum= argument). The spectrum should either be a (nu, fnu) pair or an instance of an atpy.Table with two columns named 'nu' and 'fnu'. For example, given a file spectrum.txt with two columns listing frequency and flux, the spectrum can be set using:

    import numpy
    spectrum = np.loadtxt('spectrum.txt', dtype=[('nu', float),
                                                 ('fnu', float)])
    source.spectrum = (spectrum['nu'], spectrum['fnu'])
    
  • by specifying a blackbody temperature using the temperature attribute (or temperature= argument). This should be a floating point value.

  • by using the local dust emissivity if neither a spectrum or temperature are specified.

Note

By default, the number of photons emitted is proportional to the luminosity, so in cases where several sources with very different luminosities are included in the models, some sources might be under-sampled. You can instead change the configuration to emit equal number of photons from all sources - see Multiple sources for more details.

Point sources

A point source is defined by a luminosity, a 3-d cartesian position (set to the origin by default), and a spectrum or temperature. The following examples demonstrate adding different point sources:

  • Set up a 1 solar luminosity 10,000K point source at the origin:

    source = m.add_point_source()
    source.luminosity = lsun  # [ergs/s]
    source.temperature = 10000.  # [K]
    
  • Set up two 0.1 solar luminosity 1,300K point sources at +/- 1 AU in the x direction:

    # Set up the first source
    source1 = m.add_point_source()
    source1.luminosity = 0.1 * lsun  # [ergs/s]
    source1.position = (au, 0, 0)  # [cm]
    source1.temperature = 1300.  # [K]
    
    # Set up the second source
    source2 = m.add_point_source()
    source2.luminosity = 0.1 * lsun  # [ergs/s]
    source2.position = (-au, 0, 0)  # [cm]
    source2.temperature = 1300.  # [K]
    
  • Set up a 10 solar luminosity source at the origin with a spectrum read in from a file with two columns giving wavelength (in microns) and monochromatic flux:

    # Use NumPy to read in the spectrum
    import numpy as np
    data = np.loadtxt('spectrum.txt', dtype=[('wav', float), ('fnu', float)])
    
    # Convert to nu, fnu
    nu = c / (data['wav'] * 1.e-4)
    fnu = data['fnu']
    
    # Set up the source
    source = m.add_point_source()
    source.luminosity = 10 * lsun  # [ergs/s]
    source.spectrum = (nu, fnu)
    

Note

Regardless of the grid type, the coordinates for the sources should always be specified in cartesian coordinates, and in the order (x, y, z).

If you want to set up many point sources (for example for a galaxy model) you may instead want to consider using a Point source collections.

Spherical sources

Adding spherical sources is very similar to adding point sources, with the exception that a radius can be specified:

source = m.add_spherical_source()
source.luminosity = lsun  # [ergs/s]
source.radius = rsun  # [cm]
source.temperature = 10000.  # [K]

It is possible to add limb darkening, using:

source.limb = True

Spots on spherical sources

Adding spots to a spherical source is straightforward. Spots behave the same as other sources, requiring a luminosity, spectrum, and additional geometrical parameters:

source = m.add_spherical_source()
source.luminosity = lsun  # [ergs/s]
source.radius = rsun  # [cm]
source.temperature = 10000.  # [K]

spot = source.add_spot()
spot.luminosity = 0.1 * lsun  # [ergs/s]
spot.longitude = 45.  # [degrees]
spot.latitude = 30.  # [degrees]
spot.radius = 5.  # [degrees]
spot.temperature = 20000.  # [K]

Diffuse sources

Diffuse sources are defined by a total luminosity, and a probability distribution map for the emission, defined on the same grid as the density. For example, if the grid is defined on a 10x10x10 grid, the following will add a source which emits photons from all cells equally:

source = m.add_map_source()
source.luminosity = lsun  # [ergs/s]
source.map = np.ones((10, 10, 10))

By default, if no spectrum or temperature is provided, photons will be emitted using the local emissivity of the dust. However, you can also specify either a temperature or a spectrum as for Point Sources and Spherical Sources, e.g:

source.temperature = 10000.  # [K]

or:

source.spectrum = (nu, fnu)

Note

The map array does not need to be normalized.

External sources

There are two kinds of external illumination sources, spherical and box sources - the former being more suited to spherical polar grids, and the latter to cartesian, AMR, and octree grids (there is no cylindrical external source for cylindrical grids at this time). In both cases, photons are emitted inwards isotropically. For example, an external spherical source can be added with:

source = m.add_external_spherical_source()
source.luminosity = lsun  # [ergs/s]
source.radius = pc  # [cm]
source.temperature = 10000.  # [K]

As for point and spherical sources, the position of the center can also be set, and defaults to the origin. External box sources have a bounds attribute instead of radius and position:

source = m.add_external_box_source()
source.luminosity = lsun  # [ergs/s]
source.bounds = [[-pc, pc], [-pc, pc], [-pc, pc]]  # [cm]
source.temperature = 10000.  # [K]

where the bounds attribute is given as [[xmin, xmax], [ymin, ymax], [zmin, zmax]].

See How to set the luminosity for an external radiation field for information on setting the luminosity correctly in order to reproduce a given intensity field.

Note

Even though these sources are referred to as ‘external’, they have to be placed inside the outermost walls of the grid. The sources are not box-shared source or spherical source that can be placed outside the grid, but rather sources that emit inwards instead of outwards, making it possible to simulate an external radiation field.

Plane parallel sources

Finally, it is possible to add circular plane parallel sources (essentially a circular beam with a given origin and direction):

source = m.add_plane_parallel_source()
source.luminosity = lsun  # [ergs/s]
source.radius = rsun  # [cm]
source.temperature = 10000.  # [K]
source.position = (au, 0., 0.)  # [cm]
source.direction = (45., 0.)  # [degrees]

where direction is a tuple of (theta, phi) that gives the direction of the beam.

Point source collections

In cases where you want to set up more than a few dozen point sources, it may be worth instead using a point source collection, which can contain an arbitrary number of point sources with different luminosities, and a common temperature or spectrum. To add a point source collection, use e.g.:

source = m.add_point_source_collection()

The attributes are the same as for the Point Sources but the source.luminosity attribute should be set to an array with as many elements as sources, and the source.position attribute should be set to a 2-d array where the first dimension matches source.luminosity, and with 3 elements in the second dimension (x, y, and z). The following example shows how to set up 1000 random point sources with random positions from -1au to 1au in all directions, and with random luminosities between 0 and lsun:

N = 1000
x = np.random.uniform(-1., 1, N) * au
y = np.random.uniform(-1., 1, N) * au
z = np.random.uniform(-1., 1, N) * au

source = m.add_point_source_collection()
source.luminosity = np.random.random(N) * lsun
source.position = np.vstack([x, y, z]).transpose()
source.temperature = 6000.

In terms of photon sampling, a point source collection acts as a single source with a luminosity given by the sum of the components - so if you have one point source collection and one spherical source with the same total luminosity, the number of photons will be evenly split between the two. Within the point source collection, the number of photons is split according to luminosity.