Beispiel #1
0
    model.components[2] = agama.Component(df=dfDisk, disklike=True, \
        gridR=agama.nonuniformGrid(int(iniSCMDisk['sizeRadialCyl']), \
            float(iniSCMDisk['RminCyl']), float(iniSCMDisk['RmaxCyl'])), \
        gridz=agama.nonuniformGrid(int(iniSCMDisk['sizeVerticalCyl']), \
            float(iniSCMDisk['zminCyl']), float(iniSCMDisk['zmaxCyl'])) )

    # do a few more iterations to obtain the self-consistent density profile for both disks
    for iteration in range(6, 9):
        print "Starting iteration #%d" % iteration
        model.iterate()
        printoutInfo(model, iteration)

    print "Computing disk density and velocity profiles"
    R = numpy.linspace(0.2, 10, 50)
    xyz = numpy.vstack((R, R * 0, R * 0)).T
    Sigma, _ = agama.GalaxyModel(pot=model.pot, df=dfDisk,
                                 af=model.af).projectedMoments(R)
    rho, sigma = agama.GalaxyModel(pot=model.pot, df=dfDisk,
                                   af=model.af).moments(xyz)
    force, deriv = model.pot.forceDeriv(xyz)
    kappa = numpy.sqrt(-deriv[:, 0] - 3 * force[:, 0] / R)
    ToomreQ = sigma[:, 0]**0.5 * kappa / 3.36 / Sigma
    numpy.savetxt("disk_plane",
                  numpy.vstack((R, Sigma, rho, sigma[:, 0]**0.5,
                                sigma[:, 1]**0.5, ToomreQ)).T,
                  fmt="%.6g")

    # export model to an N-body snapshot
    print "Creating an N-body representation of the model"

    # first create a representation of density profiles without velocities
    # (just for demonstration), by drawing samples from the density distribution
Beispiel #2
0
    def plotProfiles(self, chain):
        '''
        plot the radial profiles of various quantities from the set of model in the MCMC chain,
        together with the true profiles.
        '''
        axes = plt.subplots(2, 2, figsize=(12, 8))[1].T.reshape(-1)
        rmin = 0.01
        rmax = 100.
        radii = numpy.logspace(numpy.log10(rmin), numpy.log10(rmax), 41)
        midradii = (radii[1:] * radii[:-1])**0.5
        xyz = numpy.column_stack((radii, radii * 0, radii * 0))

        # compute and store the profiles for each model in the chain, then take 68% and 95% percentiles
        dmdens = numpy.zeros((chain.shape[0], len(radii)))
        dmslope = numpy.zeros((chain.shape[0], len(midradii)))
        trdens = numpy.zeros((chain.shape[0], len(radii)))
        trbeta = numpy.zeros((chain.shape[0], len(radii)))
        print('Plotting profiles...')
        for i in range(len(chain)):
            pot, df = self.model.createModel(chain[i])
            dmdens[i] = pot.density(xyz)
            dmslope[i] = numpy.log(dmdens[i, 1:] / dmdens[i, :-1]) / numpy.log(
                radii[1:] / radii[:-1])
            trdens[i], trvel = agama.GalaxyModel(pot, df).moments(xyz,
                                                                  dens=True,
                                                                  vel=False,
                                                                  vel2=True)
            trbeta[i] = 1 - trvel[:, 1] / trvel[:, 0]

        # log-slope of the DM density profile  d(log rho) / d(log r)
        cntr = numpy.percentile(dmslope, [2.3, 15.9, 50, 84.1, 97.7], axis=0)
        axes[0].fill_between(midradii, cntr[0], cntr[4],
                             color='lightgray')  # 2 sigma
        axes[0].fill_between(midradii, cntr[1], cntr[3],
                             color='gray')  # 1 sigma
        axes[0].plot(midradii, cntr[2], color='k')  # median
        axes[0].set_xscale('log')
        axes[0].set_xlim(rmin, rmax)
        axes[0].set_ylim(-5, 1)
        axes[0].set_xlabel('$r$')
        axes[0].set_ylabel(r'$d(\ln\rho_{DM}) / d(\ln r)$')

        # DM density profile
        cntr = numpy.percentile(dmdens, [2.3, 15.9, 50, 84.1, 97.7], axis=0)
        axes[1].fill_between(radii, cntr[0], cntr[4],
                             color='lightgray')  # 2 sigma
        axes[1].fill_between(radii, cntr[1], cntr[3], color='gray')  # 1 sigma
        axes[1].plot(radii, cntr[2], color='k')  # median
        axes[1].set_xscale('log')
        axes[1].set_yscale('log')
        axes[1].set_xlim(rmin, rmax)
        axes[1].set_xlabel('$r$')
        axes[1].set_ylabel(r'$\rho_{DM}$')

        # velocity anisotropy coefficient (beta) of tracers
        cntr = numpy.percentile(trbeta, [2.3, 15.9, 50, 84.1, 97.7], axis=0)
        axes[2].fill_between(radii, cntr[0], cntr[4],
                             color='lightgray')  # 2 sigma
        axes[2].fill_between(radii, cntr[1], cntr[3], color='gray')  # 1 sigma
        axes[2].plot(radii, cntr[2], color='k')  # median
        axes[2].set_xscale('log')
        axes[2].set_xlim(rmin, rmax)
        axes[2].set_ylim(-1, 1)
        axes[2].set_xlabel('$r$')
        axes[2].set_ylabel(r'$\beta_\star$')

        # 3d density profile of tracers
        cntr = numpy.percentile(trdens, [2.3, 15.9, 50, 84.1, 97.7], axis=0)
        axes[3].fill_between(radii, cntr[0], cntr[4],
                             color='lightgray')  # 2 sigma
        axes[3].fill_between(radii, cntr[1], cntr[3], color='gray')  # 1 sigma
        axes[3].plot(radii, cntr[2], color='k')  # median
        axes[3].set_xscale('log')
        axes[3].set_yscale('log')
        axes[3].set_xlim(rmin, rmax)
        axes[3].set_xlabel('$r$')
        axes[3].set_ylabel(r'$\rho_\star$')

        # histogram of radial distribution of the original points on each of the four panels
        ptcount = numpy.histogram(
            (self.particles[:, 0]**2 + self.particles[:, 1]**2)**0.5,
            bins=radii)[0]
        for ax in axes:
            plt.twinx(ax)
            plt.plot(numpy.hstack(zip(radii[:-1], radii[1:])),
                     numpy.repeat(ptcount, 2),
                     'g-',
                     alpha=0.5)
            plt.ylim(0, 2 * max(ptcount))

        try:
            true_dmdens = self.model.truePotential.density(xyz)
            true_dmslope = numpy.log(
                true_dmdens[1:] / true_dmdens[:-1]) / numpy.log(
                    radii[1:] / radii[:-1])
            true_trdens = self.model.tracerDensity.density(xyz)
            true_trbeta = self.model.tracerBeta(radii)
            axes[0].plot(midradii,
                         true_dmslope,
                         color='r',
                         lw=3,
                         linestyle='--')
            axes[1].plot(radii, true_dmdens, color='r', lw=3, linestyle='--')
            axes[2].plot(radii, true_trbeta, color='r', lw=3, linestyle='--')
            axes[3].plot(radii, true_trdens, color='r', lw=3, linestyle='--')
            axes[1].set_ylim(true_dmdens[-1] * 0.5, true_dmdens[0] * 5)
            axes[3].set_ylim(true_trdens[-1] * 0.5, true_trdens[0] * 5)
        except AttributeError:
            pass  # no true values known

        plt.tight_layout()
        plt.savefig(self.filename + "_profiles.png")
        plt.close()
Beispiel #3
0
# original DF using a C++ object
df_orig = agama.DistributionFunction( \
    type="DoublePowerLaw", J0=J0, slopeIn=0, slopeOut=Beta, norm=2*numpy.pi**3)

# to compute the total mass, we create an proxy instance of DistributionFunction class
# with a composite DF consisting of a single component (the user-supplied function);
# this proxy class provides the totalMass() method
# that the user-defined Python function itself does not have
mass_orig = df_orig.totalMass()
mass_my = agama.DistributionFunction(MyDF).totalMass()
print "DF mass=%.8g  (orig value=%.8g)" % (mass_my, mass_orig)

# GalaxyModel objects constructed from the C++ DF and from the Python function
# (without the need of a proxy object; in fact, GalaxyModel.df is itself a proxy object)
gm_orig = agama.GalaxyModel(df=df_orig, potential=pot_orig)
gm_my = agama.GalaxyModel(df=MyDF, potential=pot_appr)
# note that different potentials were used for gm_orig and gm_my, so the results may slightly disagree

# DF moments (density and velocity dispersion) computed from the C++ DF object
dens_orig, veldisp_orig = gm_orig.moments(point=(1, 0, 0))
print "original DF at r=1: density=%.8g, sigma_r=%.8g, sigma_t=%.8g" % \
    ( dens_orig, veldisp_orig[0], veldisp_orig[1] )

# DF moments computed from the Python distribution function
dens_my, veldisp_my = gm_my.moments(point=(1, 0, 0))
print "user-def DF at r=1: density=%.8g, sigma_r=%.8g, sigma_t=%.8g" % \
    ( dens_my, veldisp_my[0], veldisp_my[1] )
# gm_my.df.totalMass()  will give the same result as mass_my

if abs(pot0_orig - pot0_appr) < 1e-6 and abs(
Beispiel #4
0
def contraction(pot_dm,
                pot_bar,
                method='C20',
                beta_dm=0.0,
                rmin=1e-2,
                rmax=1e4):
    '''
    Construct the contracted halo density profile for the given
    initial halo density and the baryonic density profiles.
    Arguments:
      pot_dm:  initial halo potential (assumed to be spherical!).
      pot_bar: potential of baryons (a spherical approximation to it will be used even if it was not spherical).
      method:  choice between two alternative approaches:
        'C20'  (default) uses the approximate correction procedure from Cautun+2020;
        'adiabatic'  uses the invariance of actions in conjunction with an internally constructed halo DF.
      beta_dm: anisotropy coefficient for the halo DF
        (only used with the adiabatic method, must be between -0.5 and 1, default 0 means isotropy).
      rmin (1e-2), rmax(1e4): min/max grid radii for representing the contracted density profile
        (default values are suitable for Milky Way-sized galaxies if expressed in kpc).
    Return:
      the spherically symmetric contracted halo potential.
    '''
    gridr = numpy.logspace(numpy.log10(rmin), numpy.log10(rmax), 101)
    xyz = numpy.column_stack((gridr, gridr * 0, gridr * 0))
    if method == 'adiabatic':
        # create a spherical DF for the DM-only potential/density pair with a constant anisotropy coefficient beta
        df_dm = agama.DistributionFunction(type='QuasiSpherical',
                                           potential=pot_dm,
                                           beta0=beta_dm)
        # create a sphericalized total potential (DM+baryons)
        pot_total_sph = agama.Potential(type='multipole',
                                        potential=agama.Potential(
                                            pot_dm, pot_bar),
                                        lmax=0,
                                        rmin=0.1 * rmin,
                                        rmax=10 * rmax)
        # compute the density generated by the DF in the new total potential at the radial grid
        dens_contracted = agama.GalaxyModel(pot_total_sph,
                                            df_dm).moments(xyz,
                                                           dens=True,
                                                           vel=False,
                                                           vel2=False)
    elif method == 'C20':
        # use the differential (d/dr) form of Eq. (11) from Cautun et al (2020) to approximate the effect of contraction
        cumul_mass_dm = pot_dm.enclosedMass(
            gridr)  # cumulative mass profile of DM
        cumul_mass_bar = pot_bar.enclosedMass(
            gridr)  # same for baryons (sphericalized)
        valid_r = numpy.hstack([
            True, cumul_mass_bar[:-1] < cumul_mass_bar[1:] * 0.999
        ])  # use only those radii where mass keeps increasing
        sph_dens_bar = agama.Density(cumulmass=numpy.column_stack(
            (gridr[valid_r],
             cumul_mass_bar[valid_r])))  # sphericalized baryon density profile
        f_bar = 0.157  # cosmic baryon fraction; the formula is calibrated against simulations only for this value
        eta_bar = cumul_mass_bar / cumul_mass_dm * (
            1. - f_bar
        ) / f_bar  # the last two terms account for transforming the DM mass into the corresponding baryonic mass in dark-matter-only simulations
        first_factor = 0.45 + 0.41 * (eta_bar + 0.98)**0.53
        dens_dm_orig = pot_dm.density(xyz)
        temp = sph_dens_bar.density(
            xyz) - eta_bar * dens_dm_orig * f_bar / (1. - f_bar)
        const_term = 0.41 * 0.53 * (eta_bar + 0.98)**(0.53 - 1.) * (
            1. - f_bar) / f_bar * temp
        dens_contracted = dens_dm_orig * first_factor + const_term  # new values of DM density at the radial grid
    else:
        raise RuntimeError('Invalid choice of method')

    # create a cubic spline interpolator in log-log space
    valid_r = dens_contracted > 0  # make sure the input for log-spline is positive
    dens_contracted_interp = agama.CubicSpline(numpy.log(gridr[valid_r]),
                                               numpy.log(
                                                   dens_contracted[valid_r]),
                                               reg=True)
    # convert the grid-based density profile into a full-fledged potential
    contracted_pot = agama.Potential(
        type="Multipole",
        symmetry="spherical",
        rmin=rmin,
        rmax=rmax,
        density=lambda xyz: numpy.exp(
            dens_contracted_interp(numpy.log(numpy.sum(xyz**2, axis=1)) * 0.5)
        ))
    return contracted_pot
Beispiel #5
0
import agama

mass_unit = (1.0/4.3)*(10.0**(6.0))

agama.setUnits(mass=mass_unit, length=1, velocity=1)

pot = agama.Potential(type='Spheroid', gamma=1.0, beta=3.1, scaleRadius=2.5, outerCutoffRadius=15.0)
df = agama.DistributionFunction(type='QuasiSpherical',potential=pot)
model = agama.GalaxyModel(pot,df)
M = model.sample(10000)

print(M[0][9999,0])
agama.writeSnapshot('test_snapshot.snp',M,'n')


Beispiel #6
0
# original DF using a C++ object
df_orig = agama.DistributionFunction( \
    type="DoublePowerLaw", J0=J0, slopeIn=0, slopeOut=Beta, norm=2*numpy.pi**3)

# to compute the total mass, we create an proxy instance of DistributionFunction class
# with a composite DF consisting of a single component (the user-supplied function);
# this proxy class provides the totalMass() method
# that the user-defined Python function itself does not have
mass_orig = df_orig.totalMass()
mass_user = agama.DistributionFunction(MyDF).totalMass()
print("Integration in the 3d action space: DF mass=%.8g  (orig value=%.8g)" %
      (mass_user, mass_orig))

# GalaxyModel objects constructed from the C++ DF and from the Python function
# (without the need of a proxy object; in fact, GalaxyModel.df is itself a proxy object)
gm_orig = agama.GalaxyModel(df=df_orig, potential=pot_orig)
gm_user = agama.GalaxyModel(df=MyDF, potential=pot_appr)
# note that different potentials were used for gm_orig and gm_user, so the results may slightly disagree
mass_gm_orig = gm_orig.totalMass()
mass_gm_user = gm_user.totalMass()
print("Integration in the 6d phase space:  DF mass=%.8g  (orig value=%.8g)" %
      (mass_gm_user, mass_gm_orig))

# DF moments (density and velocity dispersion) computed from the C++ DF object
dens_orig, veldisp_orig = gm_orig.moments(point=(1, 0, 0))
print("original DF at r=1: density=%.8g, sigma_r=%.8g, sigma_t=%.8g" % \
    ( dens_orig, veldisp_orig[0]**0.5, veldisp_orig[1]**0.5 ))

# DF moments computed from the Python distribution function
dens_user, veldisp_user = gm_user.moments(point=(1, 0, 0))
print("user-def DF at r=1: density=%.8g, sigma_r=%.8g, sigma_t=%.8g" % \
Beispiel #7
0
    # first create a representation of density profiles without velocities
    # (just for demonstration), by drawing samples from the density distribution
    print(
        "Writing N-body sampled density profile for the stellar bulge, disk and halo"
    )
    # recall that component[0] contains stellar disks and stellar halo, and component[1] - bulge
    densStars = agama.Density(model.components[0].getDensity(),
                              model.components[1].getDensity())
    agama.writeSnapshot("dens_stars_final", densStars.sample(200000), format)
    print("Writing N-body sampled density profile for the dark matter halo")
    agama.writeSnapshot("dens_dm_final",
                        model.components[2].getDensity().sample(800000),
                        format)

    # now create genuinely self-consistent models of all components,
    # by drawing positions and velocities from the DF in the given (self-consistent) potential
    print("Writing a complete DF-based N-body model for the dark matter halo")
    agama.writeSnapshot("model_dm_final", \
        agama.GalaxyModel(potential=model.potential, df=dfHalo, af=model.af).sample(800000), format)
    print(
        "Writing a complete DF-based N-body model for the stellar bulge, disk and halo"
    )
    agama.writeSnapshot("model_stars_final", \
        agama.GalaxyModel(potential=model.potential, df=dfStellarAll, af=model.af).sample(200000), format)
    # we didn't use an action-based DF for the gas disk, leaving it as a static component;
    # to create an N-body representation, we sample the density profile and assign velocities
    # from the axisymmetric Jeans equation with equal velocity dispersions in R,z,phi
    print("Writing an N-body model for the gas disk")
    agama.writeSnapshot("model_gas_final", \
        model.components[3].getDensity().sample(24000, potential=model.potential, beta=0, kappa=1), format)
Beispiel #8
0
def plotModel(model, df):
    print('Creating density and kinematic plots...')
    gridx = numpy.linspace(0, 0.70, 141)
    gridz = numpy.linspace(0, 0.25, 51)
    gridxz = numpy.column_stack(
        (numpy.tile(gridx, len(gridz)), numpy.repeat(gridz, len(gridx))))
    gridxyz = numpy.column_stack(
        (numpy.tile(gridx, len(gridz)), numpy.zeros(len(gridx) * len(gridz)),
         numpy.repeat(gridz, len(gridx))))
    nsc = model.components[0].getDensity()
    nsd = model.components[1].getDensity()
    rho_nsd = nsd.density(gridxyz).reshape(len(gridz), len(gridx))
    Sig_nsd = nsd.projectedDensity(gridxz, beta=numpy.pi / 2).reshape(
        len(gridz), len(gridx))
    plt.figure(figsize=(20, 15))
    ax = numpy.array(
        [plt.axes([0.035, 0.81 - 0.195 * i, 0.38, 0.18]) for i in range(5)] +
        [plt.axes([0.425, 0.81 - 0.195 * i, 0.38, 0.18])
         for i in range(5)]).reshape(2, 5).T
    ax[0, 0].contour(gridx,
                     gridz,
                     numpy.log10(rho_nsd),
                     levels=numpy.log10(numpy.max(rho_nsd)) +
                     numpy.linspace(-6, -0, 16),
                     cmap='Blues')
    ax[0, 1].contour(gridx,
                     gridz,
                     numpy.log10(Sig_nsd),
                     levels=numpy.log10(numpy.max(Sig_nsd)) +
                     numpy.linspace(-6, -0, 16),
                     cmap='Blues')
    # compute moments on a coarser grid
    gridx = agama.nonuniformGrid(20, 0.02, 0.70)
    gridz = agama.nonuniformGrid(10, 0.02, 0.25)
    gridxz = numpy.column_stack(
        (numpy.tile(gridx, len(gridz)), numpy.repeat(gridz, len(gridx))))
    gridxyz = numpy.column_stack(
        (numpy.tile(gridx, len(gridz)), numpy.zeros(len(gridx) * len(gridz)),
         numpy.repeat(gridz, len(gridx))))
    gm = agama.GalaxyModel(model.potential, df)
    gridv = numpy.linspace(0, 100, 11)
    # intrinsic moments
    vel, vel2 = gm.moments(gridxyz,
                           dens=False,
                           vel=True,
                           vel2=True,
                           beta=numpy.pi / 2)
    plt.clabel(ax[1, 0].contour(gridx,
                                gridz,
                                -vel[:, 2].reshape(len(gridz), len(gridx)),
                                levels=gridv,
                                cmap='Blues'),
               fmt='%.0f')
    plt.clabel(ax[2, 0].contour(gridx,
                                gridz,
                                numpy.sqrt(vel2[:, 2] - vel[:, 2]**2).reshape(
                                    len(gridz), len(gridx)),
                                levels=gridv,
                                cmap='Blues'),
               fmt='%.0f')
    plt.clabel(ax[3, 0].contour(gridx,
                                gridz,
                                numpy.sqrt(vel2[:, 0] - vel[:, 0]**2).reshape(
                                    len(gridz), len(gridx)),
                                levels=gridv,
                                cmap='Blues'),
               fmt='%.0f')
    plt.clabel(ax[4, 0].contour(gridx,
                                gridz,
                                numpy.sqrt(vel2[:, 1] - vel[:, 1]**2).reshape(
                                    len(gridz), len(gridx)),
                                levels=gridv,
                                cmap='Blues'),
               fmt='%.0f')
    # projected moments
    vel, vel2 = gm.moments(gridxz,
                           dens=False,
                           vel=True,
                           vel2=True,
                           beta=numpy.pi / 2)
    plt.clabel(ax[1, 1].contour(gridx,
                                gridz,
                                -vel[:, 2].reshape(len(gridz), len(gridx)),
                                levels=gridv,
                                cmap='Blues'),
               fmt='%.0f')
    plt.clabel(ax[2, 1].contour(gridx,
                                gridz,
                                numpy.sqrt(vel2[:, 2] - vel[:, 2]**2).reshape(
                                    len(gridz), len(gridx)),
                                levels=gridv,
                                cmap='Blues'),
               fmt='%.0f')
    plt.clabel(ax[3, 1].contour(gridx,
                                gridz,
                                numpy.sqrt(vel2[:, 0] - vel[:, 0]**2).reshape(
                                    len(gridz), len(gridx)),
                                levels=gridv,
                                cmap='Blues'),
               fmt='%.0f')
    plt.clabel(ax[4, 1].contour(gridx,
                                gridz,
                                numpy.sqrt(vel2[:, 1] - vel[:, 1]**2).reshape(
                                    len(gridz), len(gridx)),
                                levels=gridv,
                                cmap='Blues'),
               fmt='%.0f')
    labels = ['density', 'v_los', 'sigma_los', 'sigma_R', 'sigma_z']
    colors = ['c', 'm', 'b', 'r', 'g']
    # fiducial fields for computing projected velocity distributions
    points = [[0.05, 0.01], [0.15, 0.01], [0.15, 0.10], [0.30, 0.01]]
    for i in range(5):
        ax[i, 0].set_ylabel('z [kpc]', labelpad=4)
        ax[i, 1].set_yticklabels([])
        ax[i, 0].text(0.5,
                      0.98,
                      'intrinsic ' + labels[i],
                      ha='center',
                      va='top',
                      transform=ax[i, 0].transAxes,
                      color=colors[i])
        ax[i, 1].text(0.5,
                      0.98,
                      'projected ' + labels[i],
                      ha='center',
                      va='top',
                      transform=ax[i, 1].transAxes,
                      color=colors[i])
        if i < 4:
            ax[i, 0].set_xticklabels([])
            ax[i, 1].set_xticklabels([])
        else:
            ax[i, 0].set_xlabel('R [kpc]', labelpad=2)
            ax[i, 1].set_xlabel('R [kpc]', labelpad=2)
        ax[i, 0].set_xlim(min(gridx), max(gridx))
        ax[i, 1].set_xlim(min(gridx), max(gridx))
        ax[i, 0].set_ylim(min(gridz), max(gridz))
        ax[i, 1].set_ylim(min(gridz), max(gridz))
        for k, point in enumerate(points):
            ax[i, 1].text(point[0],
                          point[1],
                          chr(k + 65),
                          ha='center',
                          va='center',
                          color='olive')
    gridv = numpy.linspace(
        -250, 250, 26)  # coarse grid for computing the velocity distribution
    gridV = numpy.linspace(
        -250, 250,
        101)  # fine grid for plotting a smoother spline-interpolated VDF
    vdfx, vdfz, vdfd = gm.vdf(points, gridv, beta=numpy.pi / 2)
    for i in range(4):
        ax = plt.axes([0.845, 0.75 - 0.24 * i, 0.15, 0.225])
        ax.plot(gridV, vdfd[i](-gridV), 'b', label='f(v_los)')
        ax.plot(gridV, vdfx[i](-gridV), 'r', label='f(v_R)')
        ax.plot(gridV, vdfz[i](-gridV), 'g', label='f(v_z)')
        ax.set_yscale('log')
        ax.text(0.02,
                0.98,
                'field %s' % chr(i + 65),
                ha='left',
                va='top',
                transform=ax.transAxes,
                color='olive')
        ax.set_xlim(min(gridv), max(gridv))
        ax.set_ylim(1e-5, 3e-2)
        if i < 3:
            ax.set_xticklabels([])
        else:
            ax.set_xlabel('V [km/s]')
        if i == 0:
            ax.legend(loc='lower center', frameon=False)
            ax.text(1.0,
                    1.05,
                    'projected velocity distributions in fields',
                    ha='right',
                    va='center',
                    transform=ax.transAxes)
        ax.set_ylabel('f(V)', labelpad=3)
    plt.savefig('nsd_model.pdf')
    plt.show()
Beispiel #9
0
            float(iniSCMDisc['RminCyl']), float(iniSCMDisc['RmaxCyl'])), \
        gridz=agama.nonuniformGrid(int(iniSCMDisc['sizeVerticalCyl']), \
            float(iniSCMDisc['zminCyl']), float(iniSCMDisc['zmaxCyl'])) )

    # do a few more iterations to obtain the self-consistent density profile for both discs
    for iteration in range(6, 11):
        print "Starting iteration #%d" % iteration
        model.iterate()
        printoutInfo(model, iteration)

    # export model to an N-body snapshot
    print "Creating an N-body representation of the model"

    # first create a representation of density profiles without velocities
    # (just for demonstration), by drawing samples from the density distribution
    print "Sampling halo density"
    writeNbodySnapshot("dens_halo_iter10",
                       model.components[0].getDensity().sample(100000))
    print "Sampling disc density"
    writeNbodySnapshot("dens_disc_iter10",
                       model.components[1].getDensity().sample(100000))

    # now create genuinely self-consistent models of both components,
    # by drawing positions and velocities from the DF in the given (self-consistent) potential
    print "Sampling halo DF"
    writeNbodySnapshot("model_halo_iter10", \
        agama.GalaxyModel(pot=model.pot, df=dfHalo, af=model.af).sample(100000))
    print "Sampling disc DF"
    writeNbodySnapshot("model_disc_iter10", \
        agama.GalaxyModel(pot=model.pot, df=dfStellar, af=model.af).sample(100000))
Beispiel #10
0
    format = 'text'  # one could also use 'nemo' or 'gadget' here

    # first create a representation of density profiles without velocities
    # (just for demonstration), by drawing samples from the density distribution
    print("Sampling disk density")
    agama.writeSnapshot("dens_disk_final",  model.components[0].getDensity().sample(160000), format)
    print("Sampling bulge density")
    agama.writeSnapshot("dens_bulge_final", model.components[1].getDensity().sample(40000), format)
    print("Sampling halo density")
    agama.writeSnapshot("dens_halo_final",  model.components[2].getDensity().sample(800000), format)

    # now create genuinely self-consistent models of both components,
    # by drawing positions and velocities from the DF in the given (self-consistent) potential
    print("Sampling disk DF")
    agama.writeSnapshot("model_disk_final", \
        agama.GalaxyModel(potential=model.potential, df=dfDisk,  af=model.af).sample(1600000), format)
    print("Sampling bulge DF")
    agama.writeSnapshot("model_bulge_final", \
        agama.GalaxyModel(potential=model.potential, df=dfBulge, af=model.af).sample(400000), format)
    print("Sampling halo DF")
    # note: use a 10x larger particle mass for halo than for bulge/disk
    agama.writeSnapshot("model_halo_final", \
        agama.GalaxyModel(potential=model.potential, df=dfHalo,  af=model.af).sample(3000000), format)

    # the remaining part computes and plots various diagnostics
    print("\033[1;33mComputing disk density and velocity profiles\033[0m")
    ax=plt.subplots(2, 3, figsize=(16,10))[1].reshape(-1)
    # take only the disk component
    modelDisk = agama.GalaxyModel(potential=model.potential, df=dfDisk, af=model.af)
    # radial grid for computing various quantities in the disk plane
    Sigma0 = float(iniPotenDisk["surfacedensity"])
scm = agama.SelfConsistentModel(**params)
scm.components=[comp]

# prepare visualization
r=numpy.logspace(-2.,2.)
xyz=numpy.vstack((r,r*0,r*0)).T
plt.plot(r, dens.density(xyz), label='Init density', color='k')

# perform several iterations of self-consistent modelling procedure
for i in range(6):
    scm.iterate()
    print('Iteration %i, Phi(0)=%g, Mass=%g' % \
        (i, scm.potential.potential(0,0,0), scm.potential.totalMass()))
    plt.plot(r, scm.potential.density(xyz), label='Iteration #'+str(i))

# save the final density/potential profile and create an N-body snapshot
comp.getDensity().export('flattened_sersic_density.ini')
scm.potential.export('flattened_sersic_potential.ini')
agama.writeSnapshot('flattened_sersic_nbody.nemo',
    agama.GalaxyModel(scm.potential, df).sample(1000000), 'nemo')

# show the results
plt.legend(loc='lower left')
plt.xlabel("r")
plt.ylabel(r'$\rho$')
plt.xscale('log')
plt.yscale('log')
plt.ylim(1e-5, 2e2)
plt.xlim(0.01, 10)
plt.show()