Esempio n. 1
0
def test_sed_mpi():
    model=base_model()
    
    g=unstructured_grid.UnstructuredGrid(max_sides=4)
    g.add_rectilinear([0,0],[1000,100],101,11)
    g.add_cell_field('depth',-6*np.ones(g.Ncells()))

    model.set_grid(g)

    model.num_procs=4
    model.config['dt']=3.

    # slow down the settling velocities to get some advection mixed in
    model.config['Ws01']= 0.0001     # constant settling velocity for fraction No.1 (m/s)
    model.config['Ws02']= 0.0005     # constant settling velocity for fraction No.2
    model.config['Ws03']=-0.0005     # constant settling velocity for fraction No.3

    geom=np.array([ [1000,0],
                    [1000,100]])
    Q_bc=sun_driver.FlowBC(name="Q_bc",
                           geom=geom,
                           Q=100.0)
    
    model.add_bcs( [Q_bc,
                    sun_driver.ScalarBC(parent=Q_bc,scalar="S",value=2),
                    sun_driver.ScalarBC(parent=Q_bc,scalar="T",value=0)] )

    point_bc=sun_driver.SourceSinkBC(name="bedPoint",
                                     geom=np.array([500,20]),
                                     Q=10)
    model.add_bcs( [point_bc,
                    sun_driver.ScalarBC(parent=point_bc,scalar="S",value=3),
                    sun_driver.ScalarBC(parent=point_bc,scalar="T",value=3)] )
                    
    model.write()

    # leave some dry layers at the surface
    model.ic_ds.eta.values[:]=model.bcs[0].z
    model.ic_ds.salt.values[:]=1.0
    model.ic_ds.temp.values[:]=1.0

    model.write_ic_ds()
        
    for sed_idx in range(3):
        name="sed%d"%(sed_idx+1)
        model.bc_ds['boundary_'+name]=model.bc_ds['boundary_S'].copy()
        model.bc_ds[name]=model.bc_ds['S'].copy()
        model.bc_ds['point_'+name]=model.bc_ds['point_S'].copy()
        
        model.bc_ds['boundary_'+name].values[:]=sed_idx*1.0
        model.bc_ds[name].values[:]=0.0
        model.bc_ds['point_'+name].values[:]=sed_idx*2.0

    model.write_bc_ds()
    
    model.partition()
    model.sun_verbose_flag='-v'
    model.run_simulation()
    return model
Esempio n. 2
0
def test_sed_bc():
    """
    basic BC
    """
    model=base_model()

    # slow down the settling velocities to get some advection mixed in
    model.config['Ws01']= 0.0001     # constant settling velocity for fraction No.1 (m/s)
    model.config['Ws02']= 0.0001     # constant settling velocity for fraction No.2
    model.config['Ws03']=-0.0001     # constant settling velocity for fraction No.3

    geom=np.array([ [1000,0],
                    [1000,100]])
    Q_bc=sun_driver.FlowBC(name="Q_bc",
                           geom=geom,
                           Q=100.0)
    
    model.add_bcs( [Q_bc,
                    sun_driver.ScalarBC(parent=Q_bc,scalar="S",value=2),
                    sun_driver.ScalarBC(parent=Q_bc,scalar="T",value=0)] )

    point_bc=sun_driver.SourceSinkBC(name="bedPoint",
                                     geom=np.array([500,20]),
                                     Q=10)
    model.add_bcs( [point_bc,
                    sun_driver.ScalarBC(parent=point_bc,scalar="S",value=3),
                    sun_driver.ScalarBC(parent=point_bc,scalar="T",value=3)] )
                    
    model.write()

    # leave some dry layers at the surface
    model.ic_ds.eta.values[:]=model.bcs[0].z
    model.ic_ds.salt.values[:]=1.0
    model.ic_ds.temp.values[:]=1.0

    model.write_ic_ds()
        
    for sed_idx in range(3):
        name="sed%d"%(sed_idx+1)
        model.bc_ds['boundary_'+name]=model.bc_ds['boundary_S'].copy()
        model.bc_ds[name]=model.bc_ds['S'].copy()
        model.bc_ds['point_'+name]=model.bc_ds['point_S'].copy()
        
        model.bc_ds['boundary_'+name].values[:]=sed_idx*1.0
        model.bc_ds[name].values[:]=0.0
        model.bc_ds['point_'+name].values[:]=sed_idx*2.0

    model.write_bc_ds()
    
    model.partition()
    model.sun_verbose_flag='-v'
    model.run_simulation()
    return model
Esempio n. 3
0
def add_potw_bcs(model, cache_dir, temperature=20.0):
    # WWTP discharging into sloughs
    potw_dir = "../sfbay_potw"
    potw_ds = xr.open_dataset(
        os.path.join(potw_dir, "outputs", "sfbay_delta_potw.nc"))

    # the gazetteer uses the same names for potws as the source data
    # omits some of the smaller sources, and this does not include any
    # benthic discharges
    for potw_name in [
            'sunnyvale', 'san_jose', 'palo_alto', 'lg', 'sonoma_valley',
            'petaluma', 'cccsd', 'fs', 'ddsd', 'ebda', 'ebmud', 'sf_southeast'
    ]:
        # This has variously worked and not worked with strings vs bytes.
        # Brute force and try both.
        try:
            Q_da = potw_ds.flow.sel(site=potw_name)
        except KeyError:
            Q_da = potw_ds.flow.sel(site=potw_name.encode())

        # Have to seek back in time to find a year that has data for the
        # whole run
        offset = np.timedelta64(0, 'D')
        while model.run_stop > Q_da.time.values[-1] + offset:
            offset += np.timedelta64(365, 'D')
        if offset:
            log.info("Offset for POTW %s is %s" % (potw_name, offset))

        # use the geometry to decide whether this is a flow BC or a point source
        hits = model.match_gazetteer(name=potw_name)
        if hits[0]['geom'].type == 'LineString':
            log.info("%s: flow bc" % potw_name)
            Q_bc = drv.FlowBC(name=potw_name,
                              flow=Q_da,
                              filters=[hm.Lag(-offset)],
                              dredge_depth=model.dredge_depth)
        else:
            log.info("%s: source bc" % potw_name)
            Q_bc = drv.SourceSinkBC(name=potw_name,
                                    flow=Q_da,
                                    filters=[hm.Lag(-offset)],
                                    dredge_depth=model.dredge_depth)

        salt_bc = drv.ScalarBC(parent=Q_bc, scalar='salinity', value=0.0)
        temp_bc = drv.ScalarBC(parent=Q_bc,
                               scalar='temperature',
                               value=temperature)
        model.add_bcs([Q_bc, salt_bc, temp_bc])
Esempio n. 4
0
def base_model_setup(L=100, dx=10):
    g = unstructured_grid.UnstructuredGrid(max_sides=4)
    g.add_rectilinear([0, 0], [L, 10], 1 + int(L / dx), 2)

    g.add_cell_field('depth', -6 * np.ones(g.Ncells()))

    model = sun_driver.SuntansModel()
    model.num_procs = 1
    model.load_template('point_source_test.dat')
    model.set_grid(g)
    model.run_start = np.datetime64("2018-01-01 00:00")
    model.run_stop = np.datetime64("2018-01-02 00:00")

    # 50m2, 5.0 m3/s, 0.1m/s
    source = sun_driver.FlowBC(name='inflow',
                               geom=np.array([[0, 0], [0, 10]]),
                               Q=10.0)
    outlet = sun_driver.StageBC(name='outflow',
                                geom=np.array([[100, 0], [100, 10]]),
                                z=-1)
    model.add_bcs([source, outlet])

    model.set_run_dir('rundata_2d_average', mode='pristine')
    model.projection = 'EPSG:26910'

    model.config['dt'] = 2.5
    model.config['ntout'] = 100
    model.config['ntaverage'] = 100
    model.config['calcaverage'] = 1
    model.config['averageNetcdfFile'] = "average.nc"
    model.config['thetaramptime'] = 100

    model.config['Cmax'] = 2
    model.config['Nkmax'] = 1
    model.config['stairstep'] = 0
    model.config['mergeArrays'] = 0
    return model
Esempio n. 5
0
                   nx=int(L/dx_lon),ny=int(W/dy_lat))

g.add_cell_field('depth',bathy(g.cells_center()))


model.set_grid(g)
model.config['maxFaces']=4

model.z_offset=0

from shapely import geometry
feats=np.zeros( 2, [ ('name','O'),
                     ('geom','O') ] )
feats[0]['name']='left'
# HALF STEP:
feats[0]['geom']=geometry.LineString( [ [0,W/2], [0,W] ] )
feats[1]['name']='right'
feats[1]['geom']=geometry.LineString( [ [L,0], [L,W] ] )

model.add_gazetteer(feats)

Q_left=drv.FlowBC(name='left',Q=200.0)
h_right=drv.StageBC(name='right',z=0.0)

model.add_bcs([Q_left,h_right])

model.write()
model.partition()
#model.run_simulation()

Esempio n. 6
0
# freesurface BC is 2.2 (plus offset)
#  there is that deep hole down to -10m.
# what are the options for specifying layers?
# rstretch?
#

# Annoying, but suntans doesn't like signed elevations
# this offset will be applied to grid depths and freesurface boundary conditions.
# this was -10, but that leaves a lot of dead space on top.
model.z_offset = -4

model.config['maxFaces'] = 4

model.add_gazetteer("gis/forcing-v00.shp")

Q_upstream = drv.FlowBC(name='SJ_upstream', Q=250.0)
Qdown = -100  # target outflow
# ramp up to the full outflow over 1h
h = np.timedelta64(1, 'h')
Qdown = xr.DataArray(
    data=[0, 0, Qdown, Qdown, Qdown],
    name='Q',
    dims=['time'],
    coords=dict(time=[
        model.run_start - 24 * h, model.run_start, model.run_start +
        ramp_hours * h, model.run_stop, model.run_stop + 24 * h
    ]))
Q_downstream = drv.FlowBC(name='SJ_downstream', Q=Qdown)
h_old_river = drv.StageBC(name='Old_River', z=2.2 - 0.65)

model.add_bcs([Q_upstream, Q_downstream, h_old_river])
Esempio n. 7
0
edges = g.shortest_path(n1, n2, return_type='edges')
# sloping weir, initially totally dry, will overtop
# during run
# test both signs of the edge depth
g.edges['edge_depth'][edges] = np.linspace(-2, 2, len(edges))

model = sun_driver.SuntansModel()
model.use_edge_depths = True
model.load_template('sun-template.dat')
model.set_grid(g)

model.num_procs = 4

inflow = sun_driver.FlowBC(name='inflow',
                           geom=np.array([[0, 0], [0, 100]]),
                           Q=50.0)
model.add_bcs(inflow)

model.set_run_dir('rundata', mode='pristine')
model.run_start = np.datetime64("2018-01-01 00:00")
model.run_stop = np.datetime64("2018-01-01 20:00")
model.projection = 'EPSG:26910'
model.sun_bin_dir = "/home/rusty/src/suntans/main"

# for 2D, dt=30 is okay.
# for 3D, start getting some CmaxW, so scale it back.
#     10 or 15 would probably be okay. 30 is unstable.
model.config['dt'] = 5
model.config['Cmax'] = 30
model.config['Nkmax'] = 10
def base_model(run_dir,run_start,run_stop,
               restart_from=None,
               grid_option=None,
               steady=False):
    if restart_from is None:
        model=SuntansModel()
        model.load_template(os.path.join(here,"sun-template.dat"))
        model.num_procs=num_procs
    else:
        old_model=SuntansModel.load(restart_from)
        model=old_model.create_restart()

    model.manual_z_offset=-4
    model.z_offset=0.0 # moving away from the semi-automated datum shift to manual shift
    
    model.projection="EPSG:26910"

    model.set_run_dir(run_dir,mode='pristine')

    if model.restart:
        model.run_start=model.restart_model.restartable_time()
    else:
        model.run_start=run_start
    
    model.run_stop=run_stop

    model.config['grid_option']=grid_option or 'snubby'

    if restart_from is None:
        ramp_hours=1 # how quickly to increase the outflow
    else:
        ramp_hours=0

    if not model.restart:
        # dt=0.25 # for lower friction run on refined shore grid
        # with new grid that's deformed around the barrier can probably
        # get away with 0.5
        # dt=0.5 # for lower friction run on refined shore grid
        dt=0.25 # bit of safety for high res grid.
        # dt=0.1 # for shaved cell grid. still not stable.
        model.config['dt']=dt
        model.config['metmodel']=0 # 0: no wind, 4: wind only

        model.config['nonlinear']=1

        if 0:
            model.config['Nkmax']=1
            model.config['stairstep']=0 
        if 1:
            model.config['Nkmax']=50
            model.config['stairstep']=1 # 3D, stairstep
        
        model.config['thetaM']=-1 # with 1, seems to be unstable
        model.config['z0B']=5e-4 # maybe with ADCP bathy need more friction
        # slow, doesn't make a huge difference, but does make w nicer.
        model.config['nonhydrostatic']=0
        model.config['nu_H']=0.0
        model.config['nu']=1e-5
        model.config['turbmodel']=10 # 1: my25, 10: parabolic
        model.config['CdW']=0.0 # 
        model.config['wetdry']=1
        model.config['maxFaces']=4
        model.config['mergeArrays']=1 # hopefully easier to use than split up.

        if model.config['grid_option']=='snubby':
            # 2019-07-11: refine near-shore swaths of grid, snubby-01 => snubby-04
            # 2019-07-12: further refinements 04 => 06
            #grid_src="../grid/snubby_junction/snubby-06.nc"
            #grid_src="../grid/snubby_junction/snubby-07-edit45.nc"
            #grid_src="../grid/snubby_junction/snubby-08-edit06.nc" 
            #grid_src="../grid/snubby_junction/snubby-08-edit24.nc"
            #grid_src="../grid/snubby_junction/snubby-08-edit50.nc" # good
            grid_src="../grid/snubby_junction/snubby-08-edit60.nc" # higher res in hole
            #grid_src="../grid/snubby_junction/snubby-08-refine-edit03.nc" # double res of edit60
        elif model.config['grid_option']=='large':
            grid_src="../grid/merge_v16/merge_v16_edit09.nc"
        else:
            raise Exception("Unknown grid option %s"%grid_option)

        # bathy_suffix=''
        # post_suffix='med0' # on-grid bathy postprocessesing:

        #bathy_suffix='smooth' # pre-smoothed just in sand wave areas
        bathy_suffix='smoothadcp' # pre-smoothed just in sand wave areas, and revisit ADCP data.
        #bathy_suffix='smoothadcp2' # same, but extend ADCP data upstream.
        post_suffix=''
        
        # bathy_suffix='adcp'
        # post_suffix=''

        grid_bathy=os.path.basename(grid_src).replace('.nc',f"-with_bathy{bathy_suffix}{post_suffix}.nc")

        if utils.is_stale(grid_bathy,[grid_src]):
            g_src=unstructured_grid.UnstructuredGrid.from_ugrid(grid_src)
            g_src.cells_center(refresh=True)
            bare_edges=g_src.orient_edges(on_bare_edge='return')
            if len(bare_edges):
                ec=g_src.edges_center()
                for j in bare_edges[:50]:
                    print("Bare edge: j=%d  xy=%g %g"%(j, ec[j,0], ec[j,1]))
                raise Exception('Bare edges in grid')
            add_bathy.add_bathy(g_src,suffix=bathy_suffix)
            add_bathy.postprocess(g_src,suffix=post_suffix)
            
            g_src.write_ugrid(grid_bathy,overwrite=True)
            
        g=unstructured_grid.UnstructuredGrid.from_ugrid(grid_bathy)
        g.cells['z_bed'] += model.manual_z_offset

        g.delete_edge_field('edge_z_bed')
        #g.edges['edge_z_bed'] += model.manual_z_offset

        model.set_grid(g)
        model.grid.modify_max_sides(4)
    dt=float(model.config['dt'])

    # with 0.01, was getting many CmaxW problems.
    model.config['dzmin_surface']=0.05 # may have to bump this up..
    model.config['ntout']=int(1800./dt) 
    model.config['ntaverage']=int(1800./dt)
    model.config['ntoutStore']=int(86400./dt)
    # isn't this just duplicating the setting from above?
    model.z_offset=0.0 # moving away from the semi-automated datum shift to manual shift

    if model.config['grid_option']=='snubby':
        model.add_gazetteer(os.path.join(here,"../grid/snubby_junction/forcing-snubby-01.shp"))
    elif model.config['grid_option']=='large':
        model.add_gazetteer(os.path.join(here,"../grid/merge_v16/forcing-merge_16-01.shp"))
        
    def fill(da):
        return utils.fill_tidal_data(da,fill_time=False)

    if steady:
        # Would like to ramp these up at the very beginning.
        # Mossdale, tested at 220.0 m3/s
        Q_upstream=drv.FlowBC(name='SJ_upstream',flow=220.0,dredge_depth=None)
        Q_downstream=drv.FlowBC(name='SJ_downstream',flow=-100,dredge_depth=None)
        # had been 1.75.  but that's showing about 0.75m too much water.
        # could be too much friction, or too high BC.
        h_old_river=drv.StageBC(name='Old_River',water_level=1.75 + model.manual_z_offset)
    else:
        # 15 minute data. The flows in particular have enough overtide energy
        # that the lowpass interval shouldn't be too large. Spot checks of plots
        # show 1.0h is pretty good
        lp_hours=1.0
        
        data_upstream=common.msd_flow(model.run_start,model.run_stop)
        Q_upstream=drv.FlowBC(name="SJ_upstream",flow=data_upstream.flow_m3s,dredge_depth=None,
                              filters=[hm.Lowpass(cutoff_hours=1.0)])

        data_downstream=common.sjd_flow(model.run_start,model.run_stop)
        # flip sign to get outflow.
        Q_downstream=drv.FlowBC(name="SJ_downstream",flow=-data_downstream.flow_m3s,dredge_depth=None,
                                filters=[hm.Lowpass(cutoff_hours=1.0)])

        or_stage=common.oh1_stage(model.run_start,model.run_stop)
        h_old_river=drv.StageBC(name='Old_River',water_level=or_stage.stage_m,
                                filters=[hm.Transform(fn=lambda x: x+model.manual_z_offset),
                                         hm.Lowpass(cutoff_hours=1.0)])

    model.add_bcs([Q_upstream,Q_downstream,h_old_river])
    
    model.write()

    assert np.all(np.isfinite(model.bc_ds.boundary_Q.values))

    if not model.restart:
        # bathy rms ranges from 0.015 to 1.5
        # 0.5 appears a little better than 1.0 or 0.1
        # cfg007 used 0.1, and the shape was notably not as good
        # as steady008.
        # cfg008 will return to 0.5...
        # BUT - now that I have more metrics in place, it looks like cfg007
        # was actually better, in terms of MAE over top 2m, and smaller bias.
        # with that in mind, steady012 will try an even smaller factor, and infact
        # something more in line with Nikuradse.
        # best roughness using constant z0B was 5e-4.
        # so map 0.1 to that...
        if 1:
            print("Adding roughness")
            grid_roughness.add_roughness(model.grid)
            cell_z0B=(1./30)*model.grid.cells['bathy_rms']
            e2c=model.grid.edge_to_cells()
            nc1=e2c[:,0]
            nc2=e2c[:,1]
            nc2[nc2<0]=nc1[nc2<0]
            edge_z0B=0.5*( cell_z0B[nc1] + cell_z0B[nc2] )
            model.ic_ds['z0B']=('time','Ne'), edge_z0B[None,:]
        model.write_ic_ds()

        if int(model.config['metmodel'])>=4:
            # and how about some wind?
            times=np.array( [model.run_start - np.timedelta64(10,'D'),
                             model.run_start,
                             model.run_stop,
                             model.run_stop  + np.timedelta64(10,'D')] )
            nt=len(times)
            met_ds=model.zero_met(times=times)
            pnts=model.grid.cells_center()[:1]
            for comp in ['Uwind','Vwind']:
                met_ds['x_'+comp]=("N"+comp,),pnts[:,0]
                met_ds['y_'+comp]=("N"+comp,),pnts[:,1]
                met_ds['z_'+comp]=("N"+comp,),10*np.ones_like(pnts[:,1])

            met_ds['Uwind']=('nt',"NUwind"), 0.0 * np.ones((nt,len(pnts)))
            met_ds['Vwind']=('nt',"NVwind"),-5.0 * np.ones((nt,len(pnts)))
            model.met_ds=met_ds
            model.write_met_ds()

    model.partition()
    model.sun_verbose_flag='-v'
    return model
Esempio n. 9
0
    model.config['thetaM'] = -1

model.run_start = old_model.restartable_time()
model.run_stop = model.run_start + np.timedelta64(900, 's')

dt = float(model.config['dt'])
model.config['ntout'] = int(900. / dt)
##
# Annoying, but suntans doesn't like signed elevations
# this offset will be applied to grid depths and freesurface boundary conditions.
# this was -10, but that leaves a lot of dead space on top.
model.z_offset = -4

model.add_gazetteer("gis/forcing-v00.shp")

Q_upstream = drv.FlowBC(name='SJ_upstream', Q=210.0)
Q_downstream = drv.FlowBC(name='SJ_downstream', Q=-100.0)
h_old_river = drv.StageBC(name='Old_River', z=2.2)

model.add_bcs([Q_upstream, Q_downstream, h_old_river])

model.write()
model.partition()
model.run_simulation()

##
from stompy.spatial import wkb2shp
from stompy import xr_transect

tran_shp = "../../gis/model_transects.shp"
tran_geoms = wkb2shp.shp2geom(tran_shp)
model.set_grid(g)

model.grid.modify_max_sides(4)

##

# Annoying, but suntans doesn't like signed elevations
# this offset will be applied to grid depths and freesurface boundary conditions.
# this was -10, but that leaves a lot of dead space on top.
model.z_offset = -4

model.config['maxFaces'] = 4

model.add_gazetteer("../grid/snubby_junction/forcing-snubby-01.shp")

Q_upstream = drv.FlowBC(name='SJ_upstream', Q=220.0, dredge_depth=None)
Qdown = -100  # target outflow
# ramp up to the full outflow over 1h
h = np.timedelta64(1, 'h')
Qdown = xr.DataArray(
    data=[0, 0, Qdown, Qdown, Qdown],
    name='Q',
    dims=['time'],
    coords=dict(time=[
        model.run_start - 24 * h, model.run_start, model.run_start +
        ramp_hours * h, model.run_stop, model.run_stop + 24 * h
    ]))
Q_downstream = drv.FlowBC(name='SJ_downstream', Q=Qdown, dredge_depth=None)
# 2.5 crashed.
# h_old_river=drv.StageBC(name='Old_River',z=2.2-0.65)
h_old_river = drv.StageBC(name='Old_River', z=2.5)