Пример #1
0
def getRayleighVelocities(fname, direction=[]):
    """Returns positions of the shock, and both inner an outer rayleigh line velocities joining 
    both sides of the shocked cell.
    (xin, xout, cjin, cjout, float(ray.ds.current_time), ray.ds.parameters['x_match'])
    """
#     fields = ['sound_speed', 'density', 'pressure']
#     data, _ = reader.getLineout(fname, fields=fields, species=False, geom=geom)
#     time, params, _, _, _ = reader.getMeta(fname)
#     rad, cs, dens, pres = data[0], data[1], data[2], data[3]
    
    fields = ['sound_speed', 'density', 'pressure']
    time, pars, _, _, paths = directMeta(fname)
    if len(direction)>(pars['dimensionality']-1):
        print("Direction doesn't match dimensionality: {}".format(pars['dimensionality']))
        return None
    data, _ = getLineout(fname, fields=fields, species=False, direction=direction, geom=pars['geometry'])
    #time, params, _, _, _ = directMeta(fname)
    rad, cs, dens, pres = data[0], data[1], data[2], data[3]
    
    # this fails for x_match = y_match = z_match = 0.0
    linepos = ut.estimateMatch(direction, pars, vvv=False)
    # print(linepos)
    shockin, shockout = ut.locateShock(rad, cs, linepos, vvv=False)
#     shockin, shockout = ut.locateShock(rad, cs, pars['x_match'], vvv=False)
    
    xin, xout = rad[shockin], rad[shockout]
    cjin = ut.roughCJ(dens, pres, shockin)
    cjout = ut.roughCJ(dens, pres, shockout)
    return xin, xout, cjin, cjout, time, pars['x_match']
Пример #2
0
def getShockConditions(fname, inward=False, addvar='temp', direction=[]):
    """(1D) Returns bulk conditions at both sides of shock.
    Conditions are sorted so that output has the form: [ash, shock, fuel]

    Args:
        fname(str): filepath
        inward(bool): toggle for inward/outward bound shock.
        addvar(float): extra variable to get from lineout.
        **kwargs: arguments for lineout (direction, geometry, etc.)

    Returns:
        (list): radii of states.
        (list): densities of states.
        (list): pressures of states.
        (list): addvar at each state.
            (float): direct Rayleigh speed for the ash state.
        (float): match head position
        (float): timestamp of file.

    """
    fields = ['sound_speed', 'density', 'pressure', addvar]
    time, pars, _, _, _ = directMeta(fname)
    if len(direction) > (pars['dimensionality'] - 1):
        print("Direction doesn't match dimensionality: "
              "{}".format(pars['dimensionality']))
        return None
    data, _ = getLineout(fname,
                         fields=fields,
                         species=False,
                         direction=direction,
                         geom=pars['geometry'])
    # time, params, _, _, _ = directMeta(fname)
    rad, cs, dens, pres, var = data[0], data[1], data[2], data[3], data[4]

    # this fails for x_match = y_match = z_match = 0.0
    linepos = ut.estimateMatch(direction, pars, vvv=False)
    # print(linepos)
    shockin, shockout = ut.locateShock(rad, cs, linepos, vvv=False)
    # print('check shockConditions')
    if inward:
        ind = shockin
        offset = -1
    else:
        ind = shockout
        offset = 1
    # directly calculate the rayleigh speed joining both points
    cjest = rayleighSpeed(pres[ind + offset], 1.0 / dens[ind + offset],
                          pres[ind - offset], 1.0 / dens[ind - offset])
    pos = [rad[ind - offset], rad[ind], rad[ind + offset]]
    condd = [dens[ind - offset], dens[ind], dens[ind + offset]]
    condp = [pres[ind - offset], pres[ind], pres[ind + offset]]
    xvar = [var[ind - offset], var[ind], var[ind + offset]]
    return pos, condd, condp, xvar, cjest, linepos, time
Пример #3
0
def buildHelmTrojan(fname, offset=1, geom='spherical'):
    """Frankensteinian bridge between flash checkpoints and
    J.Schwab's Helmholtz python module.
    Joined inward/outward and spewing cj data to avoid
    calling yt more than once.

    Args:
        fname(str): filename.
        offset(int): zone offset from shock.

    """
    props = ['dens', 'temp', 'pres', 'eint']
    nprops = len(props)
    data, species = hdf5yt.getLineout(fname,
                                      fields=props,
                                      species=True,
                                      geom=geom)
    nspecs = len(species)
    xin, xout, cjin, cjout, time, xmatch = getRayleighVelocities(fname)
    # get fuel and ash for outward shock
    # xin/xout == ray @ len([x for x in ray['r'][rsort] if x<xout])
    inw = len([x for x in data[0] if x < xout]) + offset
    ouw = inw - 2 * offset
    inv, ouv = [], []
    for i in range(1, nprops + 1):
        inv.append(data[i][inw])
        ouv.append(data[i][ouw])
    xmin, xmou = [], []
    for i in range(nprops + 1, nprops + 1 + nspecs):
        xmin.append(data[i][inw])
        xmou.append(data[i][ouw])
    _, abar, zbar = convXmass2Abun(species, xmin)
    # [pressure, eint], [rho], [temp], [abar], [zbar]]
    fuelo = [[inv[-2], inv[-1]], [inv[0]], [inv[1]], [abar], [zbar]]
    _, abar, zbar = convXmass2Abun(species, xmou)
    asho = [[ouv[-2], ouv[-1]], [ouv[0]], [ouv[1]], [abar], [zbar]]

    # get fuel and ash for inward shock
    inw = len([x for x in data[0] if x < xin]) - offset
    ouw = inw + 2 * offset
    inv, ouv = [], []
    for i in range(1, nprops + 1):
        inv.append(data[i][inw])
        ouv.append(data[i][ouw])
    xmin, xmou = [], []
    for i in range(nprops + 1, nprops + 1 + nspecs):
        xmin.append(data[i][inw])
        xmou.append(data[i][ouw])
    _, abar, zbar = convXmass2Abun(species, xmin)
    fueli = [[inv[-2], inv[-1]], [inv[0]], [inv[1]], [abar], [zbar]]
    _, abar, zbar = convXmass2Abun(species, xmou)
    ashi = [[ouv[-2], ouv[-1]], [ouv[0]], [ouv[1]], [abar], [zbar]]
    return fueli, ashi, fuelo, asho, [xin, xout, cjin, cjout, time, xmatch]
Пример #4
0
def flashProfile(fname, thresh=1e-6, xrange=[0.0, 0.0], 
                 filetag='prof', batch=False, byM=True, direction=[]):
    """Plot bulk properties and species in a chekpoint through a ray.
    
    Args:
        fname(str): path of file.
        thresh(float): threshold for species fraction.
        xrange(float list): abscissa range.
        filetag(str): prefix for batch mode. 
        batch(bool): skips returning figure, saving it to a structured directory instead.
        byM(bool): plot by mass instead of radius.
        direction(float list): list of spherical angles (alt, azimuth), empty for 1D.
    
    Returns:
        (mpl figure) or (None)
    
    """
    time, pars, _, _, paths = directMeta(fname)
    if len(direction)>(pars['dimensionality']-1):
        print("Direction doesn't match dimensionality: {}".format(pars['dimensionality']))
        return None
    ad, allsp = getLineout(fname, geom=pars['geometry'], 
                           direction=direction, srcnames=False)
    keys = ['radius', 'density', 'temperature', 'pressure']
    keys +=allsp
    prof = dataMatrix([keys, ad.transpose()])
    fig = plotDMatMerged(prof, byM=byM, 
                   thresh=thresh, xrange=xrange)
    ax = plt.gca()
    a = ax.annotate("{:.5f} s".format(time),
                    xy=(0.0, 0.0), xytext=(0.82, 0.10), size=12,
                    textcoords='figure fraction', xycoords='figure fraction', 
                    bbox=dict(boxstyle='round', fc='w', ec='k'))
    if not batch:
        return fig
    else:
        num = paths[1][-5:]  # checkpoint number 'flash_hdf5_chk_0001'
        dest = os.path.join(os.path.dirname(paths[0]), filetag)
        name = os.path.join(dest, '{}{}.png'.format(filetag, num))
        os.makedirs(dest, exist_ok=True)  # bless you, p3
        plt.savefig(name, format='png')
        plt.close(fig)
        print("Wrote: {}".format(name))
Пример #5
0
def radialSpeeds(fname,
                 elevation=5,
                 depth=5,
                 geom='cartesian',
                 dimension=2,
                 ref='x',
                 antipode=False):
    """radius vs radial speed for a wedge centered at the equator.
    """
    if dimension == 2:
        rawd = wedge2d(fname,
                       elevation,
                       depth,
                       fields=['x', 'y', 'z', 'velx', 'vely', 'velz'])
        rs, vrs = [], []
        for x, y, z, vx, vy, vz in zip(*rawd):
            vec = np.array([x, y, z])
            vel = np.array([vx, vy, vz])
            r = np.sqrt(vec.dot(vec))
            v = np.sqrt(vel.dot(vel))
            rxv = np.cross(vec, vel)
            normrxv = np.sqrt(rxv.dot(rxv))
            angle = np.arcsin(normrxv / r / v)
            vrad = v * np.cos(angle)
            rs.append(r)
            vrs.append(vrad)
    elif dimension == 3:
        rawd = wedge3d(
            fname,
            elevation,
            depth,
            fields=['spherical_radius', 'velocity_spherical_radius'],
            reference=ref,
            antipode=antipode)
        rs, vrs = rawd
    else:
        rawd, _ = getLineout(fname, fields=['velx'], geom=geom, species=False)
        rs, vrs = rawd
    return rs, vrs
Пример #6
0
def speedHisto(fname,
               resolution=4e7,
               velrange=[1e9, 5e9],
               elevation=5,
               depth=5,
               geom='cartesian',
               dimension=2,
               ref='x',
               antipode=False,
               cylvel=False,
               species=_alphas):
    """Calculate speeds within a wedge and return masses.
    histogram bin range is fixed so that one can mix wedges.
    # recommended resolution: 100 km/s (Fink, 2010)
    # default resolution: 400 km/s
    # default max velocity: a sixth of c.

    Args:
        fname(str): filename.
        resolution(float): bin size in cm/s.
        velrange(float list): historgram range.
        elevation(float): equator-north pole degree.
        depth(float): equator-south pole degree.
        geom(str): specify geometry for 1d file.
        dimension(int): specify file dimension.
        ref(str): reference axis (3D only, see datahaul.hdf5yt.wedge3d).
        antipode(bool): antipodal wedge (see datahaul.hdf5yt.wedge3d).
        cylvel(bool): take velx (axial velocity in cylindrical) as speed.
        species(str list): specify which species data to get.

    Returns:
        np.array list, np.array: Masses for species queries, bin limits.

    """
    # split into wedges process each, then read outputs...
    # wedge2d call without 'fields' calculates cylindrical volumes
    if dimension == 2:
        rawd, ispecies = wedge2d(fname, elevation, depth, cylvel=cylvel)
    elif dimension == 3:
        rawd, ispecies = wedge3d(fname,
                                 elevation,
                                 depth,
                                 reference=ref,
                                 antipode=antipode)
    else:
        rawd, ispecies = getLineout(
            fname, fields=['velx', 'vely', 'velz', 'cell_mass'], geom=geom)
        rawd = rawd[1:]  # remove the radius column

    offset = len(rawd) - len(ispecies)
    # see datahaul.hdf5yt.wedge2d for positions of data in rawd
    speeds = rawd[0][:]

    celltpls = []
    for i in range(len(rawd[0])):
        # multiply each X_i by the cell_masses
        masses = [
            rawd[j][i] * rawd[1][i] for j in range(offset,
                                                   len(ispecies) + offset)
        ]
        celltpls.append((speeds[i], masses))

    sortedcells = sorted(celltpls)
    speeds, massgrid = zip(*sortedcells)
    # massgrid = [[Mh1_0, Mhe4_0,...], [Mh1_1, Mhe4_1,...]]
    # respecting increasing speed order

    # get ranges for histogram bins
    vmin, vmax = velrange
    binnum = int((vmax - vmin) / resolution)
    print("post.speedHisto: Velocity range: {:e} {:e}".format(vmin, vmax))
    print("post.speedHisto: Bins: {}".format(binnum))
    try:
        counts, bins = np.histogram(speeds, bins=int(binnum))
    except ValueError:
        print('post.speedHisto: zero speed range.')
        return None

    # sort by species
    species = [s.strip() for s in species]
    buckets = []
    for s in species:
        buckets.append(np.zeros(len(bins)))
    psp = dict(zip(species, range(len(species))))
    for i in range(len(ispecies)):
        if ispecies[i] in species:  # main species filter
            weights = [0]
            start = 0
            for c in counts:
                # since the data is already sorted by speed
                # counts follows the data in each bin
                totalspmass = sum([m[i] for m in massgrid[start:start + c]])
                # force the summed data value as histo "weight"
                weights.append(totalspmass)
                start += c
            weights = np.array(weights)
            # finally sum the array of masses to the corresponding histo
            buckets[psp[ispecies[i]]] += weights
        else:
            continue
    return buckets, bins
Пример #7
0
def PARsimProfile(fname, simfolder='', thresh=1e-4, xrange=[0.0, 0.0], 
                  filetag='metaprof', batch=False, byM=False, direction=[], meta=False):
    """bloated method for IPP.
    WARN: slowest pos will not match for non x-axis directions.
    
    Args:
        fname(str): path to checkpoint file.
        simfolder(str): simulation run metadata folder.
        thresh(float): species threshold.
        xrange(float list): abscissa range for all plots.
        filetag(str): prefix for output files (if any).
        batch(bool): write file instead of returning figure.
        byM(bool): plot by mass coordinate instead of radius.
        direction(str list): altitude and azimuthal direction of profile ray.
    
    Return:
        (mpl figure) or (None)
    
    """
    time, pars, _, _, paths = directMeta(fname)
    if len(direction)>(pars['dimensionality']-1):
        print("Direction doesn't match dimensionality: {}".format(pars['dimensionality']))
        return None
    ad, allsp = getLineout(fname, geom=pars['geometry'], 
                           direction=direction, srcnames=False)
    sim = simulation(simfolder)
    n, t = sim.time2step(time)
    step = sim.steps[int(n)]
    xm, ym, zm = step.slowx, step.slowy, step.slowz
    rm = np.sqrt(xm**2+ym**2+zm**2)
    
    keys = ['radius', 'density', 'temperature', 'pressure']
    keys +=allsp
    prof = dataMatrix([keys, ad.transpose()])
    fig = plotDMatMerged(prof, byM=byM, 
                         thresh=thresh, xrange=xrange)
    # add extra marks from simulation obj
    ax = plt.gca()
    a = ax.annotate("{:.5f} s".format(time),
                    xy=(0.0, 0.0), xytext=(0.84, 0.10), size=12,
                    textcoords='figure fraction', xycoords='figure fraction', 
                    bbox=dict(boxstyle='round', fc='w', ec='k'))
    axlist = fig.axes
    for ax in axlist[1:]:
        p = rm if not byM else prof.masses[np.where(prof.radius>rm)[0][0]]
        ax.axvline(p, ls=':', color='brown', alpha=0.5, label='slowest')
    if sim.CJ:
        times, xins, cjins, xouts, cjouts = np.genfromtxt(sim.CJ[0], unpack=True)
        if byM:
            xo, xi = xouts[pars['checkpointfilenumber']], xins[pars['checkpointfilenumber']]
            no = np.where(prof.radius>xo)[0][0]
            ni = np.where(prof.radius>xi)[0][0]
            po, pi = prof.masses[no], prof.masses[ni]
        else:
            po, pi = xouts[pars['checkpointfilenumber']], xins[pars['checkpointfilenumber']]
        ax.axvline(po, ls=':', color='green', alpha=0.5, label='shock')
        ax.axvline(pi, ls=':', color='red', alpha=0.5, label='shock')
    lgd = ax.legend(ncol=1, loc='upper left', bbox_to_anchor=(1.00, 0.50), 
                      columnspacing=0.0, labelspacing=0.0, markerfirst=False, 
                      numpoints=3, handletextpad=0.0, edgecolor='k')
    if meta:
        markings = [po, pi, p, paths]
        return fig, markings
    #I/O
    if not batch:
        return fig
    else:
        num = paths[1][-5:]  # checkpoint number 'flash_hdf5_chk_0001'
        dest = os.path.join(os.path.dirname(paths[0]), filetag)
        name = os.path.join(dest, '{}{}.png'.format(filetag, num))
        os.makedirs(dest, exist_ok=True)  # bless you, p3
        plt.savefig(name, format='png')
        plt.close(fig)
        print("Wrote: {}".format(name))
Пример #8
0
def flashSpecies(fname, thresh=1e-6, filetag='spec', batch=False, 
                 byM=True, direction=[], plotall=False):
    """Plot species and aggregated masses in a chekpoint through a ray.
    
    Args:
        fname(str): path of file.
        thresh(float): threshold for species fraction and mass yields.
        filetag(str): prefix for batch mode. 
        batch(bool): skips returning figure, saving it to a structured directory instead.
        byM(bool): plot by mass instead of radius.
        direction(float list): list of spherical angles (alt, azimuth), empty for 1D.
        plotall(bool): force plotting every species found.
    
    Returns:
        (mpl figure) or (None)
    
    """
    fields = ['density', 'temperature', 'pressure', 'velx']
    time, pars, _, _, paths = directMeta(fname)
    if len(direction)>(pars['dimensionality']-1):
        print("Direction doesn't match dimensionality: {}".format(pars['dimensionality']))
        return None
    ad, allsp = getLineout(fname, geom=pars['geometry'], 
                           direction=direction, fields=fields, srcnames=False)

    keys = ['radius'] + fields
    keys +=allsp
    prof = dataMatrix([keys, ad.transpose()])

    fig = plt.figure(figsize=(10, 8))
    layout = (3,3)
    # plot species
    ax1 = plt.subplot2grid(layout, (0, 0), colspan=2)
    skip = plotSpecies(ax1, prof, byMass=byM, thresh=thresh, plotall=plotall)
    ax1.set_xlabel('Mass ($M_{\odot}$)')
    # timestamp and legend
    a = ax1.annotate("{:.5f} s".format(time),
                    xy=(0.0, 0.0), xytext=(0.65, 0.1), size=12,
                    textcoords='figure fraction', xycoords='figure fraction', 
                    bbox=dict(boxstyle='round', fc='w', ec='k'))
    lgd = ax1.legend(ncol=4, loc='upper left', bbox_to_anchor=(1.05, 1.0), 
                    columnspacing=0.0, labelspacing=0.0, markerfirst=False, 
                    numpoints=3, handletextpad=0.0)
    lgd.get_frame().set_edgecolor('k')
    
    # write otp files for yields
    massfiletuples = []
    
    # plot masses
    ax2 = plt.subplot2grid(layout, (1,0), colspan=2)
    for i, sp in enumerate(prof.species):
        props = next(ax2._get_lines.prop_cycler)
        spmass = trapz(getattr(prof, sp), x=prof.masses)
        massfiletuples.append((sp, spmass))
        if i in skip:
            continue
        a = elemSplit(sp)[1]
        spmass = trapz(getattr(prof, sp), x=prof.masses)
        ax2.scatter(a, spmass, label=sp, color=props['color'])
    ax2.set_ylabel('Total Mass ($M_\odot$)', rotation=90, labelpad=5)
    ax2.set_xlabel('Mass Number (A)')
    ax2.set_ylim([thresh, 1.5])
    ax2.set_yscale("log", nonposy='clip')
    #ax2.yaxis.set_major_formatter(StrMethodFormatter('{x:.2f}'))
    ax2.yaxis.set_minor_formatter(StrMethodFormatter(''))
    ax2.xaxis.set_major_formatter(StrMethodFormatter('{x:.0f}'))
    ax2.xaxis.set_minor_formatter(StrMethodFormatter(''))
    
    # decay yield
    names, decmasses = decayYield(*zip(*massfiletuples))

    # plot mass vs speed
    ax3 = plt.subplot2grid(layout, (2, 0), colspan=2)
    nbins = 60
    for i, sp in enumerate(prof.species):
        props = next(ax2._get_lines.prop_cycler)
        if i in skip:
            continue
        counts, bins = np.histogram(abs(prof.velx), bins=nbins)
        joined = sorted(zip(abs(prof.velx), getattr(prof, sp)))
        speeds, masses = zip(*joined)
        start = 0
        weights = []
        for c in counts:
            massf = sum(masses[start:start+c])
            weights.append(massf/c)
            start+=c
        weights = np.array(weights)
        bins = bins[1:]
        mpln, mplbins, patches = ax3.hist(bins, bins=len(bins), weights=weights, histtype='step', log=True, label=sp)
        ax3.set_ylim([1e-6, 2])
    ax3.yaxis.set_minor_formatter(StrMethodFormatter(''))
    ax3.xaxis.set_major_formatter(customFormatter(10))
    ax3.xaxis.set_minor_formatter(StrMethodFormatter(''))
    ax3.set_xlabel('Speed ($10^{10}$ cm/s)')
    fig.subplots_adjust(hspace=0.4)
    
    if not batch:
        return fig
    else:
        num = paths[1][-5:]  # checkpoint number 'flash_hdf5_chk_0001'
        dest = os.path.join(os.path.dirname(paths[0]), filetag)
        name = os.path.join(dest, '{}{}.png'.format(filetag, num))
        os.makedirs(dest, exist_ok=True)  # bless you, p3
        plt.savefig(name, format='png')
        plt.close(fig)
        print("Wrote: {}".format(name))
        yieldfile = os.path.join(dest, '{}{}.yield'.format(filetag, num))
        with open(yieldfile, 'w') as f:
            f.write('# {}\n'.format(paths[1]))
            f.write('# time: {}\n'.format(time))
            f.write('\n'.join(['{} {}'.format(*a) for a in massfiletuples]))
            f.write('\n')
        print("Wrote: {}".format(yieldfile))
        decayfile = os.path.join(dest, '{}{}.decayed'.format(filetag, num))
        with open(decayfile, 'w') as f:
            f.write('# {}\n'.format(paths[1]))
            f.write('# time: {}\n'.format(time))
            f.write('\n'.join(['{} {}'.format(*a) for a in zip(names, decmasses)]))
            f.write('\n')
        print("Wrote: {}".format(decayfile))