Ejemplo n.º 1
0
def Findlt_King62(l, sp, potential, xv):
    """
    Auxiliary function for 'ltidal', which returns the 
    
        left-hand side - right-hand side
        
    of the King62 equation for tidal radius, as in eq.(12.21) of 
    Mo, van den Bosch, White 10
    
    Syntax:
    
        Findlt_King62(l,sp,potential,xv)
    
    where
    
        l: radius in the satellite [kpc] (float)
        sp: satellite potential (an object define in profiles.py)
        potential: host potential (a density profile object, or a list of
            such objects that constitute a composite potential)
        xv: phase-space coordinates [R,phi,z,VR,Vphi,Vz] in units of 
            [kpc,radian,kpc,kpc/Gyr,kpc/Gyr,kpc/Gyr] (float array)
    """
    r = np.sqrt(xv[0]**2. + xv[2]**2.)
    r1 = r * (1. - cfg.eps)
    r2 = r * (1. + cfg.eps)
    Om = Omega(xv)
    m = sp.M(l)
    M = pr.M(potential, r)
    M1 = pr.M(potential, r1)
    M2 = pr.M(potential, r2)
    dlnMdlnr = (np.log(M2) - np.log(M1)) / (np.log(r2) - np.log(r1))
    return l - r * (m / M /
                    (2. + Om**2. * r**3 / cfg.G / M - dlnMdlnr))**(1. / 3.)
def get_T(r,
          params,
          m=0.,
          add_params=[],
          Ttype='jeans-alpha',
          do_smooth=False,
          polyorder=3,
          sigma=21,
          mode='interp',
          rlim=[-2, 0]):
    alpha, beta, gamma, p = params
    if Ttype[-5:] == 'Mreal':
        M = array(add_params) + array(m)
    else:
        M = prf.M(r, p, model='an') + m

    Rvir = p[-2]

    if Ttype == 'jeans-alpha' or Ttype == 'jeans' or Ttype == 'jeans-Mreal' or Ttype == 'alpha-p-Mreal':
        denominator = get_denominator(r, params, Ttype=Ttype)
        T = 0.5 * (3. - 2 * beta) / denominator * G * M / r
    elif Ttype == 'alpha' or Ttype == 'alpha-Mreal' or Ttype == 'betazero' or Ttype == 'gamma-Treal':
        denominator = get_denominator(r, params, Ttype=Ttype)
        T = 1.5 / denominator * G * M / r
    elif Ttype == 'zero':
        T = zeros_like(r)
    elif Ttype == 'virial' or Ttype == 'virial-Mreal':
        T = 0.5 * G * M / r
    elif Ttype == 'jeans-smooth':
        T = 0.5 * (3. - 2 * beta) / denominator * G * M / r
        do_smooth = True
    elif Ttype == 'Tdekel':
        # T from hydrostatic equilibrum (sigmar)
        (c, a, b, g, Rvir, Mvir) = p
        x = r / Rvir * c
        sigmar2 = prf.sigmar2_dekel_m(x, Mvir, Rvir, c, a, m=m, mtype='center')
        T = 1.5 * sigmar2
    elif Ttype == 'Tmulti':
        (c, a, b, g, Rvir, Mvir) = p
        [Mratio, n] = add_params
        x = r / Rvir * c
        T = prf.K_Mratio(x, Mvir, Rvir, c, a, Mratio, n, m)

    if do_smooth:
        r_range = where((log10(r / Rvir) >= rlim[0])
                        & (log10(r / Rvir) < rlim[1]))
        T_smooth = nan * ones(size(T))
        T_smooth[r_range] = savgol_filter(T[r_range],
                                          sigma,
                                          polyorder,
                                          deriv=0,
                                          mode=mode,
                                          delta=diff(log10(r))[0])
        T = T_smooth

    return T
Ejemplo n.º 3
0
def fit_prof_constrained(r,
                         data,
                         params,
                         constraint=(),
                         w=1,
                         model='an',
                         y='brho',
                         xi1=0.015,
                         xi2=1.000):
    #least squares fitting
    result = minimize(min_res,
                      params,
                      args=(r, data, w, model, y),
                      method='SLSQP',
                      constraints=constraint)
    p = result2p(result, model)
    Rvir = p[-2]
    Mvir = p[-1]
    brho = prf.brho(r, p, model)
    rho = prf.rho(r, p, model)
    bs = prf.bs(r, p, model)
    s = prf.s(r, p, model)
    M = prf.M(r, p, model)
    V = prf.V(r, p, model)
    if y == 'brho':
        rms = rmslog(brho, data)
    if y == 'rho':
        rms = rmslog(rho, data)
    try:
        c2 = Rvir / r[bisect(bs, 2) - 1]
    except:
        c2 = 0
    return {
        'p': p,
        'brho': brho,
        'rho': rho,
        'bs': bs,
        's': s,
        'M': M,
        'V': V,
        's1': prf.s(xi1 * Rvir, p, model),
        's2': prf.s(xi2 * Rvir, p, model),
        'bs1': prf.bs(xi1 * Rvir, p, model),
        'bs2': prf.bs(xi2 * Rvir, p, model),
        'c2': c2,
        'rms': rms,
        'Merr': (prf.calc_total_mass(r, rho, Rvir) - Mvir) / Mvir
    }
def E_diff(ri,
           pi,
           pf,
           m,
           alphai=0.,
           alphaf=0.,
           gammai=0.,
           gammaf=0.,
           betai=0.,
           betaf=0.,
           Ttype='jeans',
           model='an',
           method='halo',
           add_params=[],
           do_smooth=False):
    #returns the energy difference of the mass enclosing shell between the before and after states. the difference should be ideally zero according to the model

    if Ttype[-5:] == 'Mreal':
        Mi = array(add_params)
    else:
        Mi = prf.M(ri, pi, model)

    rf = prf.inv_M(Mi, pf, model)  #the new radii that enclose the same masses
    Ui = prf.U(ri, pi, model)
    Uf = prf.U(rf, pf, model)

    if Ttype == 'gamma-Treal':
        Treal = add_params
        gammai = 1.5 * G * Mi / ri / Treal - prf.alpha_Dekel(ri, pi)
        gammaf = gammai

    Ti = get_T(ri, [alphai, betai, gammai, pi],
               m=0.,
               add_params=add_params,
               Ttype=Ttype,
               do_smooth=do_smooth)
    Tf = get_T(rf, [alphaf, betaf, gammaf, pf],
               m=m,
               add_params=add_params,
               Ttype=Ttype,
               do_smooth=do_smooth)

    Ei = Ui - G * m / ri + Ti  #0.5*G*Mi/ri
    Ef = Uf - G * m / rf + Tf  #0.5*G*Mi/rf

    return array([Ef - Ei, (Ef - Ei) / abs(Ei)], dtype=float)
def evolve(r,
           ri,
           Mi,
           pi,
           m,
           alphai=0.,
           alphaf=0.,
           gammai=0.,
           gammaf=0.,
           betai=0.,
           betaf=0.,
           Ttype='jeans',
           Mcen=0,
           w=1,
           model='an',
           method='halo',
           add_params=[],
           Rvirf=0.,
           Mvirf=0.,
           component='d'):

    gamma = 0.

    if method == 'halo' or method == 'halo_noUex':
        if model == 'an':
            (ci, ai, bi, gi, Rviri, Mviri) = pi
            if Rvirf == 0.: Rvirf = Rviri
            if Mvirf == 0.: Mvirf = Mviri

            paramsf = Parameters()
            paramsf.add('c', value=ci, min=1e-16, vary=True)
            paramsf.add('a', value=ai, vary=True)
            paramsf.add('b', value=bi, vary=False)
            paramsf.add('g', value=gi, vary=False)
            paramsf.add('Rvir', value=float(Rvirf), vary=False)
            if component == 'd':
                paramsf.add('Mvir', value=float(Mvirf), vary=False)
            else:
                paramsf.add('Mvir', value=float(Mvirf), vary=True)
            if Ttype == 'jeans-gamma':
                paramsf.add('gamma',
                            value=float(gamma),
                            min=-1.,
                            max=1.,
                            vary=True)
        result = minimize(min_E_diff,
                          paramsf,
                          args=(r, pi, m, alphai, alphaf, gammai, gammaf,
                                betai, betaf, Ttype, w, model, method,
                                add_params))
        if Ttype == 'jeans-gamma':
            gamma = result.values['gamma']
        pf = fit.result2p(result, model)

        #energy error calc
        ere = E_diff(r, pi, pf, m, alphai, alphaf, gammai, gammaf, betai,
                     betaf, Ttype, model, method, add_params)[1]
        errterms = [
            log10(r / Rviri) < -1.33,  #inner region
            (log10(r / Rviri) >= -1.33) &
            (log10(r / Rviri) <= -0.67),  #middle region
            log10(r / Rviri) > -0.67,  #outer region
            r == r
        ]  #all
        ererms = [sqrt(mean(ere[errterm]**2)) for errterm in errterms]

        #cosider mass bath at center - important for a sequence
        Mcenf = Mcen + m
        rf = r
        rf0 = prf.inv_M(Mi, pf)
        Mf = prf.M(rf, pf, model)

    return {
        'ri': ri,  #initial radii
        'rf0': rf0,  #final radii
        'rf': rf,  #final radii, sorted
        'Mf': Mf,  #final mass profile
        'Mcenf': Mcenf,  #final mass at center
        'pi': pi,  #initial profile parameters
        'pf': pf,  #final profile parameters
        'gammaf': gamma,  # gamma
        'm': m,  #added mass
        'model': model,  #profile model used
        'method': method,  #evolution method used
        'ere': ere,  #energy relative error array
        'ererms': ererms
    }  #rms of energy relative error