Example #1
0
def rotated_hydro(hydro):
    """
    hydro: xarray Dataset with a grid and edge-centered fluxes in Q.
    returns a new Dataset with the dual grid, 90deg rotated edge velocities,
    and cell-centered vector velocities.
    """
    g = unstructured_grid.UnstructuredGrid.from_ugrid(hydro)

    # using centroids yields edges that aren't orthogonal, but the centers
    # are nicely centered in the cells.
    # As long as the grid is nice and orthogonal, it should be okay
    # use true circumcenters.
    gd = g.create_dual(center='circumcenter',
                       create_cells=True,
                       remove_1d=True)

    # Need to get the rotated Q
    en = g.edges_normals()  # edge normals that go with Q on the original grid
    enr = utils.rot(np.pi / 2, en)
    dual_en = gd.edges_normals()
    j_orig = gd.edges['dual_edge']
    edge_sign_to_dual = np.round((enr[j_orig] * dual_en).sum(axis=1))
    Qdual = hydro.Q.values[j_orig] * edge_sign_to_dual

    Urot_dual = U_perot(gd, Qdual, gd.cells_area())

    ds = gd.write_to_xarray()
    ds['Q'] = ('edge', ), Qdual
    ds['u'] = ('face', 'xy'), Urot_dual
    return ds
Example #2
0
def steady_streamline_across(x0, hydro):
    Uc = hydro['U']
    gtri = hydro['g']
    Ucrot = utils.rot(np.pi / 2, Uc)
    left, l_cells = steady_streamline_oneway(gtri, Ucrot, x0)
    right, r_cells = steady_streamline_oneway(gtri, -Ucrot, x0)
    return np.concatenate((left[::-1], right[1:]))
Example #3
0
    def __init__(self,
                 g,
                 U,
                 source_ds,
                 alongs=None,
                 acrosses=None,
                 g_rot=None,
                 U_rot=None):
        self.g = g
        self.U = U
        self.source_ds = source_ds
        self.g_rot = g_rot or self.g
        if U_rot is None:
            assert self.g == self.g_rot
            U_rot = utils.rot(np.pi / 2, self.U)
        self.U_rot = U_rot

        if alongs:
            self.alongs = alongs
        else:
            self.calc_alongs()
        if acrosses:
            self.acrosses = acrosses
        else:
            self.calc_acrosses()
Example #4
0
def data_to_hyperbola(data,a=0,b=1):
    s=np.linspace(-5,5,100)

    # Draw hyperbolas from data:
    pa=np.r_[ data['rx_x'][a], data['rx_y'][a] ]
    pb=np.r_[ data['rx_x'][b], data['rx_y'][b] ]

    f0=0.5*(pa+pb)

    dab=pb-pa
    theta=np.arctan2(dab[1],dab[0]) # for the rotation
    focus_dist=utils.dist(dab)

    delta_ab=(data['rx_t'][b] - data['rx_t'][a])*0.5*(data['rx_c'][a]+data['rx_c'][b])

    # well, I can get the eccentricity, right?
    hyp_c=0.5*utils.dist(pa-pb) # center to one focus
    # distance from a point to other focus
    #         distance to this focus
    # (c+a) - (c-a) = delta_ab
    hyp_a=-delta_ab/2

    ecc=hyp_c/hyp_a

    # ecc = sqrt(1+b^2/a^2)
    # ecc^2-1 = b^2/a^2
    # take a^2=1
    # b^2=ecc^2-1
    # b=sqrt( ecc^2-1)
    B=np.sqrt(ecc**2-1)

    hxy_sim=np.c_[np.cosh(s),
                  B*np.sinh(s)]
    if 0:
        hxy_sim_ref=np.c_[-np.cosh(s),
                          B*np.sinh(s)]
        # while working through this, include the reflection
        hxy_sim=np.concatenate( [hxy_sim,
                                 [[np.nan,np.nan]],
                                 hxy_sim_ref])

    # so a point on the hyperbola is at [1,0]
    # and then the focus is at [ecc,0]

    f1=np.array([ecc,0])
    f2=-f1

    deltas=utils.dist( hxy_sim-f1) - utils.dist(hxy_sim-f2)

    # scale it - focus is current at ecc, and I want it at
    # hyp_c
    # hyp_c/ ecc =hyp_a
    hxy_cong=hxy_sim * hyp_a

    hxy_final=utils.rot(theta,hxy_cong) + f0 + data['xy0']

    return hxy_final
Example #5
0
    def __init__(self,
                 g,
                 U,
                 source_ds,
                 alongs=None,
                 acrosses=None,
                 bidir=False,
                 g_rot=None,
                 U_rot=None,
                 along_args={},
                 across_args={}):
        self.g = g
        prepare_grid(g)

        self.U = U
        self.source_ds = source_ds
        self.g_rot = g_rot or self.g

        if self.g_rot != self.g:
            prepare_grid(self.g_rot)

        if U_rot is None:
            assert self.g == self.g_rot
            U_rot = utils.rot(np.pi / 2, self.U)
        self.U_rot = U_rot

        self.bidir = bidir
        self.along_args = dict(bidir=bidir, max_t=20 * 3600, max_dist=500)
        self.along_args.update(along_args)
        self.across_args = dict(bidir=bidir, max_t=20 * 3600, max_dist=100)
        self.across_args.update(across_args)

        if alongs:
            self.alongs = alongs
        else:
            self.calc_alongs()
        if acrosses:
            self.acrosses = acrosses
        else:
            self.calc_acrosses()
Example #6
0
def steady_streamline_across(x0, hydro):
    Uc = hydro['U']
    g = hydro['g']
    Ucrot = utils.rot(np.pi / 2, Uc)
    return steady_streamline_twoways(x0, g, Ucrot)
Example #7
0
    x0 = source_ds.x.values[s, :]
    along = steady_streamline_along(x0, tri_hydro)
    across = steady_streamline_across(x0, tri_hydro)

    alongs.append(along)
    acrosses.append(across)

##

bad = 546
x0 = source_ds.x.values[546, :]

Uc = tri_hydro['U']
gtri = tri_hydro['g']
Ucrot = utils.rot(np.pi / 2, Uc)
#left,l_cells=steady_streamline_oneway(gtri,Ucrot,x0)
right, r_cells = steady_streamline_oneway(gtri, -Ucrot, x0)

#across=steady_streamline_across(x0,tri_hydro)

plt.figure(1).clf()
fig, ax = plt.subplots(1, 1, num=1)

gtri.plot_edges(ax=ax, color='k', lw=0.3)

slc = slice(bad, bad + 1)
#ax.add_collection(collections.LineCollection(alongs[slc],color='b'))
#ax.add_collection(collections.LineCollection(acrosses[slc],color='g'))
ax.plot(source_ds.x.values[slc, 0], source_ds.x.values[slc, 1], 'mo')
ax.plot(right[:, 0], right[:, 1], 'r-o')
Example #8
0
    p_ints=[ ll2utm(np.array(r)) for r in geom.interiors]
    p_geoms.append( geometry.Polygon(p_ext,p_ints))

##

g_cart=unstructured_grid.UnstructuredGrid()

L=290e3
W=160e3
dx=dy=2.0e3

g_cart.add_rectilinear([-W,-L/2],[0,L/2],
                       int(1+W/dx),int(1+L/dy))

# Rotate CCW and translate 0,0 of that grid to hit ~GG
g_cart.nodes['x']=utils.rot( 30*np.pi/180., g_cart.nodes['x']) + np.array([560e3,4191e3])
cart_poly=g_cart.boundary_polygon()

##

# Clear out a buffer region 
sfb_dx_min=200
cart_dx_typ=dx

# This ends up being a bit overkill, since it buffers
# from parts of the bay grid which are not touching
# the ocean grid.  Still, the effect is kind of
# nice, giving some higher near-shore resolution, so
# don't fix it at this point.
buff_size=(cart_dx_typ - sfb_dx_min)*10
        # interpolate model to observation times
        mubar_i = np.interp(dtimes, mtimes, mubar[:,llind],left=np.nan,right=np.nan)
        mvbar_i = np.interp(dtimes, mtimes, mvbar[:,llind],left=np.nan,right=np.nan)
        # rotating model and obs to principle axis
        try:
            # Get NOAA reported flood direction
            flood_dir=float(dat['flood_dir'][:])
            # convert to "math" convention, and radians
            flood_dir=(90-flood_dir)*np.pi/180.
        except Exception:
            print("Failed to get flood dir?!")
            flood_dir=0.0 # east

        mvec=np.asarray([mubar_i, mvbar_i]).T
        mtheta=principal_theta(mvec,positive=flood_dir)
        muvbar = rot(-mtheta,mvec).T
        vec=np.asarray([ubar, vbar]).T
        # specifying positive=mtheta is supposed to help resolve
        # 180 degree ambiguity
        theta=principal_theta(vec,positive=mtheta)
        uvbar = rot(-theta,vec).T

        obs_color='green'
        mod_color='lightslategray'

        if 1: # plotting up model & observation time series
            fig, ax = plt.subplots(nrows=2, sharex=True, figsize=(8,7))
            if not rotate_series:
                ax[0].plot(mdtime[:], mubar[:,llind], color=mod_color, label='Model')
                ax[0].plot(dtime[:], ubar[:], '--', color=obs_color, label='ADCP')
                
centerline=np.concatenate([sec0,sec1,sec2])
from stompy.spatial import linestring_utils
centerline=linestring_utils.resample_linearring(centerline,dx_lon,closed_ring=0)


def profile(x,s):
    return np.linspace(-W/2.,W/2.,int(W/dy_lat))

ret=g.add_rectilinear_on_line(centerline,profile)

y=g.cells['d_lat']/(W/2.0)
bathy=depth_center+(y**2)*(depth_edge-depth_center)
g.add_cell_field('depth',bathy,on_exists='overwrite')

if rotate!=0.0:
    g.nodes['x']=utils.rot(rotate*np.pi/180., g.nodes['x'] )



inflow= g.nodes['x'][ret['nodes'][0,:]]
outflow=g.nodes['x'][ret['nodes'][-1,:]]

if 1:
    plt.figure(1).clf()
    plt.plot(centerline[:,0],
             centerline[:,1],'g-')
    g.plot_edges(color='k',lw=0.5)
    ccoll=g.plot_cells(values=g.cells['depth'],cmap='jet')
    plt.colorbar(ccoll)
    plt.axis('equal')
Example #11
0
adcp = xr.open_dataset('/home/rusty/data/noaa/ports/SFB1304-2013.nc')

##

U = np.array([adcp.u_davg, adcp.v_davg]).T

##

theta = utils.principal_theta(U)

print "Rotating to positive is %d compass" % ((90 -
                                               (theta * 180 / np.pi)) % 360)

# theta gives the direction of flood-positive currents.  To get that
# component into the 'x' component, rotate by -theta
Urot = utils.rot(-theta, U)

##

fig = plt.figure(2)
fig.clf()
fig.set_size_inches([14, 8], forward=True)

fig, (ax_spring, ax_neap) = plt.subplots(2, 1, sharey=True, num=2)

for ax in [ax_spring, ax_neap]:
    ax.plot(adcp.time, Urot[:, 0], label='Depth avg vel.')
    ax.set_ylabel('m/s floodward')
    ax.grid(1)

# starts with ebb, ends with flood
Example #12
0
alongs = []

for i in utils.progress(range(len(cutoff_xyz))):
    x0 = cutoff_xyz[i, :2]
    along = stream_tracer.steady_streamline_twoways(g_sub,
                                                    unit_flux_vec,
                                                    x0,
                                                    max_t=20 * 3600,
                                                    bidir=False,
                                                    max_dist=500.)
    alongs.append(along)

##
acrosses = []

unit_flux_vec_rot = utils.rot(np.pi / 2, unit_flux_vec)

for i in utils.progress(range(len(cutoff_xyz))):
    x0 = cutoff_xyz[i, :2]
    across = stream_tracer.steady_streamline_twoways(g_sub,
                                                     unit_flux_vec_rot,
                                                     x0,
                                                     max_t=20 * 3600,
                                                     bidir=False,
                                                     max_dist=100.)
    acrosses.append(across)

##

a_segs = [a.x.values for a in alongs]
acoll = collections.LineCollection(a_segs, color='r', lw=0.5, alpha=0.5)
Example #13
0
    def summary_figure(self, num=3):
        fig = plt.figure(num)
        fig.clf()

        ax_map = fig.add_subplot(1, 2, 1)
        ax_V = fig.add_subplot(1, 2, 2)

        xyxy = self.region_poly.bounds
        clip = [xyxy[0], xyxy[2], xyxy[1], xyxy[3]]
        hyp = self.hyp

        # hyp.g.plot_edges(clip=clip,ax=ax_map,color='k',lw=0.4,alpha=0.4)
        plot_wkb.plot_wkb(hyp.g_poly,
                          fc='0.8',
                          ec='none',
                          ax=ax_map,
                          zorder=-4)
        hyp.g.plot_cells(mask=self.region_cells, ax=ax_map, color='orange')

        # Show the location of the reference station
        ax_map.plot([
            self.hyp.his.station_x_coordinate.isel(
                stations=self.region_station)
        ], [
            self.hyp.his.station_y_coordinate.isel(
                stations=self.region_station)
        ], 'go')
        # bound_xs=self.bounding_cross_sections()
        xys = []
        uvs = []
        for k in self.bound_xs.keys():
            sgn = self.bound_xs[k]
            sec_x = self.hyp.his.cross_section_x_coordinate.isel(
                cross_section=k).values
            sec_y = self.hyp.his.cross_section_y_coordinate.isel(
                cross_section=k).values
            sec_xy = np.c_[sec_x, sec_y]
            sec_xy = sec_xy[sec_xy[:, 0] < 1e10]
            ax_map.plot(sec_xy[:, 0], sec_xy[:, 1], 'r-')
            uvs.append(sgn * (sec_xy[-1] - sec_xy[0]))
            xys.append(sec_xy.mean(axis=0))
        xys = np.array(xys)
        uvs = np.array(uvs)
        uvs = utils.rot(-np.pi / 2, utils.to_unit(uvs))
        ax_map.quiver(xys[:, 0], xys[:, 1], uvs[:, 0], uvs[:, 1])

        ax_map.axis('equal')

        order = np.argsort(self.eta)
        ax_V.plot(self.eta[order], self.vol_and_Q[order], label="model")
        ax_V.plot(self.dem_etas,
                  self.dem_volumes,
                  label='DEM',
                  color='k',
                  lw=0.6)

        # and what we expect from the model, assuming nonlin2d=0
        cell_etas, cell_vols = self.calculate_cell_volumes()
        ax_V.plot(cell_etas, cell_vols, label='Cell depth', color='r', lw=0.6)

        ax_V.set_ylabel('Vol')
        ax_V.set_xlabel('eta')

        ax_V.legend()
        return fig
Example #14
0
        'g-',
        lw=1.5)

##


def ll_to_lonilati(ll, coastal_ds):
    """
    Match lon/lat coordinates to a cell in the coastal_ds
    dataset.
    ll: [lon,lat]
    coastal_ds: xarray dataset, assumed to be lon/lat grid, rectilinear.
    """
    loni = utils.nearest(snap_lon % 360, g_map_ll[c, 0] % 360)
    lati = utils.nearest(snap_lat, g_map_ll[c, 1])
    err_km = utils.haversine([snap_lon[loni], snap_lat[lati]], g_map_ll[c, :])


# HERE - instead of reinventing here, generalize the ROMS
# code.  even if that means repeated BC sources.

# match contiguous runs of nodes/edges with sources
# of hycom/roms cells
probes = []

for na, nb in zip(boundary_nodes[:-1], boundary_nodes[1:]):
    jab = g.nodes_to_edge([na, nb])
    vec_AB = utils.rot(-np.pi / 2, g_ll.nodes['x'][nb] - g_ll.nodes['x'][na])
    probe_xy = g_ll.nodes['x'][[na, nb]].mean(axis=0) + 0.5 * vec_AB
    probes.append(probe_xy)