예제 #1
0
def test_get_watershed_masks_with_area_threshold():
    rmg = RasterModelGrid((7, 7), 200)

    z = np.array([
        -9999., -9999., -9999., -9999., -9999., -9999., -9999., -9999., 26.,
        0., 26., 30., 34., -9999., -9999., 28., 1., 28., 5., 32., -9999.,
        -9999., 30., 3., 30., 10., 34., -9999., -9999., 32., 11., 32., 15.,
        38., -9999., -9999., 34., 32., 34., 36., 40., -9999., -9999., -9999.,
        -9999., -9999., -9999., -9999., -9999.
    ])

    rmg.at_node['topographic__elevation'] = z

    rmg.set_closed_boundaries_at_grid_edges(True, True, True, False)

    # Route flow.
    fr = FlowRouter(rmg)
    fr.run_one_step()

    # Get the masks of watersheds greater than or equal to 80,000
    # square-meters.
    critical_area = 80000
    mask = get_watershed_masks_with_area_threshold(rmg, critical_area)

    # Assert that mask null nodes have a drainage area below critical area.
    null_nodes = np.where(mask == -1)[0]
    A = rmg.at_node['drainage_area'][null_nodes]
    below_critical_area_nodes = A < critical_area
    trues = np.ones(len(A), dtype=bool)

    np.testing.assert_equal(below_critical_area_nodes, trues)
예제 #2
0
def test_get_watershed_outlet():
    grid = RasterModelGrid((7, 7), 1)

    z = np.array([
        -9999., -9999., -9999., -9999., -9999., -9999., -9999., -9999., 26.,
        0., 30., 32., 34., -9999., -9999., 28., 1., 25., 28., 32., -9999.,
        -9999., 30., 3., 3., 11., 34., -9999., -9999., 32., 11., 25., 18., 38.,
        -9999., -9999., 34., 32., 34., 36., 40., -9999., -9999., -9999.,
        -9999., -9999., -9999., -9999., -9999.
    ])

    grid.at_node['topographic__elevation'] = z

    imposed_outlet = 2

    grid.set_watershed_boundary_condition_outlet_id(imposed_outlet,
                                                    z,
                                                    nodata_value=-9999.)

    fr = FlowRouter(grid)
    fr.run_one_step()

    test_node = 32

    determined_outlet = get_watershed_outlet(grid, test_node)
    np.testing.assert_equal(determined_outlet, imposed_outlet)

    # Create a pit.
    pit_node = 38
    grid.at_node['topographic__elevation'][pit_node] -= 32
    fr.run_one_step()

    pit_outlet = get_watershed_outlet(grid, test_node)
    np.testing.assert_equal(pit_outlet, pit_node)
예제 #3
0
def test_get_watershed_nodes():
    grid = RasterModelGrid((7, 7), 1)

    z = np.array([
        -9999., -9999., -9999., -9999., -9999., -9999., -9999., -9999., 26.,
        0., 30., 32., 34., -9999., -9999., 28., 1., 25., 28., 32., -9999.,
        -9999., 30., 3., 3., 11., 34., -9999., -9999., 32., 11., 25., 18., 38.,
        -9999., -9999., 34., 32., 34., 36., 40., -9999., -9999., -9999.,
        -9999., -9999., -9999., -9999., -9999.
    ])

    grid.at_node['topographic__elevation'] = z

    outlet_id = 2

    grid.set_watershed_boundary_condition_outlet_id(outlet_id,
                                                    z,
                                                    nodata_value=-9999.)

    fr = FlowRouter(grid)
    fr.run_one_step()

    ws_nodes = get_watershed_nodes(grid, outlet_id)

    # Given the watershed boundary conditions, the number of watershed nodes
    # should be equal to the number of core nodes plus 1 for the outlet node.
    np.testing.assert_equal(len(ws_nodes), grid.number_of_core_nodes + 1)
예제 #4
0
def plot_and_calc_concavities_final_run(directory='.'):
    """
    Plots S-A for final topo saved in folder "directory".

    Returns (k_s, concavity) for lin regression on log log trend.

    Concavity is defined as positive.
    """
    mg2 = deepcopy(mg)
    z2 = mg2.add_zeros('node', 'topographic__elevation', noclobber=False)
    fr2 = FlowRouter(mg2)
    # search for topo saves, to establish the num files, codes etc:
    prefixed_z = [
        filename for filename in os.listdir(directory)
        if filename.startswith('topographic__elevation')
    ]
    # grab the unique ID, so we can differentiate plots (if desired)
    unique_ID = prefixed_z[0][-14:-4]
    # work on first save to establish num digits
    _format = 0
    while True:
        char = prefixed_z[-1][-16 - _format]
        try:
            num = int(char)
        except ValueError:  # was a str
            break
        else:
            _format += 1

    # load the final topo:
    z2[:] = np.loadtxt(directory + '/' + prefixed_z[-1])
    # create a new flow map:
    fr2.run_one_step()
    profile_IDs = channel_nodes(mg2,
                                mg2.at_node['topographic__steepest_slope'],
                                mg2.at_node['drainage_area'],
                                mg2.at_node['flow__receiver_node'])
    ch_dists = get_distances_upstream(
        mg2, len(mg2.at_node['topographic__steepest_slope']), profile_IDs,
        mg2.at_node['flow__link_to_receiver_node'])
    slopes = mg2.at_node['topographic__steepest_slope'][profile_IDs[0]]
    areas = mg2.at_node['drainage_area'][profile_IDs[0]]
    logslopes = np.log(slopes)
    logareas = np.log(areas)
    goodvals = np.logical_and(np.isfinite(logslopes), np.isfinite(logareas))
    concavity, log_k_s, _, _, _ = linregress(logareas[goodvals],
                                             logslopes[goodvals])
    k_s = np.exp(log_k_s)

    loglog(areas, slopes, 'x')
    loglog(areas, k_s * areas**concavity, '-')
    xlabel('Drainage area (m**2)')
    ylabel('Slope (m/m)')

    return k_s, -concavity
class DrainageAreaModel(_ErosionModel):
    """
    A DrainageAreaModel simply computes drainage area on a raster-grid DEM.
    """
    def __init__(self, input_file=None, params=None):
        """Initialize the LinearDiffusionModel."""

        # Call ErosionModel's init
        super(DrainageAreaModel, self).__init__(input_file=input_file,
                                                params=params)

        # Instantiate a FlowRouter and DepressionFinderAndRouter components
        self.flow_router = FlowRouter(self.grid, **self.params)
        self.lake_filler = DepressionFinderAndRouter(self.grid, **self.params)

    def run_one_step(self, dt):
        """
        Advance model for one time-step of duration dt.
        """
        self.flow_router.run_one_step()

        # for debug
        from landlab.io import write_esri_ascii
        import numpy

        write_esri_ascii('test_dr_area_before_temp.txt',
                         self.grid,
                         names='drainage_area',
                         clobber=True)
        loga = self.grid.add_zeros('node', 'loga')
        loga[:] = numpy.log10(self.grid.at_node['drainage_area'] + 1)
        write_esri_ascii('test_logdr_area_before_temp.txt',
                         self.grid,
                         names='loga',
                         clobber=True)
        write_esri_ascii('test_sink_flag_before_temp.txt',
                         self.grid,
                         names='flow__sink_flag',
                         clobber=True)

        self.lake_filler.map_depressions()
예제 #6
0
class EffectiveDrainageAreaModel(_ErosionModel):
    """
    A DrainageAreaModel simply computes drainage area on a raster-grid DEM.
    """
    def __init__(self, input_file=None, params=None):
        """Initialize the LinearDiffusionModel."""

        # Call ErosionModel's init
        super(EffectiveDrainageAreaModel, self).__init__(input_file=input_file,
                                                         params=params)

        # Instantiate a FlowRouter and DepressionFinderAndRouter components
        self.flow_router = FlowRouter(self.grid, **self.params)
        self.lake_filler = DepressionFinderAndRouter(self.grid, **self.params)

        # Add a field for effective drainage area
        self.eff_area = self.grid.add_zeros('node', 'effective_drainage_area')

        # Get the effective-area parameter
        self.sat_param = self.params['saturation_area_scale']

    def run_one_step(self, dt):
        """
        Advance model for one time-step of duration dt.
        """

        # Run flow routing and lake filler
        self.flow_router.run_one_step()
        self.lake_filler.map_depressions()

        # Calculate effective area
        area = self.grid.at_node['drainage_area']
        slope = self.grid.at_node['topographic__steepest_slope']
        cores = self.grid.core_nodes
        self.eff_area[cores] = (
            area[cores] * np.exp(-self.sat_param * slope[cores] / area[cores]))

        # Lower outlet
        self.z[self.outlet_node] -= self.outlet_lowering_rate * dt
        print(('lowering outlet to ', self.z[self.outlet_node]))
예제 #7
0
class StreamPowerThresholdModel(_ErosionModel):
    """
    A StreamPowerThresholdModel computes erosion using a form of the unit
    stream power model that represents a threshold using an exponential term.
    """
    def __init__(self, input_file=None, params=None):
        """Initialize the StreamPowerThresholdModel."""

        # Call ErosionModel's init
        super(StreamPowerThresholdModel, self).__init__(input_file=input_file,
                                                        params=params)

        # Instantiate a FlowRouter and DepressionFinderAndRouter components
        self.flow_router = FlowRouter(self.grid, **self.params)
        self.lake_filler = DepressionFinderAndRouter(self.grid, **self.params)

        # Instantiate a FastscapeEroder component
        self.eroder = StreamPowerSmoothThresholdEroder(
            self.grid,
            K_sp=self.params['K_sp'],
            threshold_sp=self.params['threshold_sp'])

    def run_one_step(self, dt):
        """
        Advance model for one time-step of duration dt.
        """

        # Route flow
        self.flow_router.run_one_step()
        self.lake_filler.map_depressions()

        # Get IDs of flooded nodes, if any
        flooded = np.where(self.lake_filler.flood_status == 3)[0]

        # Do some erosion (but not on the flooded nodes)
        self.eroder.run_one_step(dt, flooded_nodes=flooded)
예제 #8
0
    ## Landscape Evolution ##

    # Now that we have performed the tectonic deformation, lets apply our
    # landscape evolution and watch the landscape change as a result.

    # Uplift the landscape
    rmg['node']['topographic__elevation'][rmg.core_nodes] += uplift_rate * dt

    # set the lower boundary as fixed elevation
    rmg['node']['topographic__elevation'][rmg.node_y == 0] = 0

    # Diffuse the landscape simulating hillslope sediment transport
    lin_diffuse.run_one_step(dt)

    # Accumulate and route flow, fill any lakes, and erode under the rivers
    fr.run_one_step()  # route flow
    DepressionFinderAndRouter.map_depressions(fill)  # fill lakes
    sp.run_one_step(dt)  # fastscape stream power eroder

    ## Calculate the geomorphic metric ##

    # In the paper, we use a geomorphic metric, BR, to quantify the
    # reorientation of the channels as time goes on. The code to calculate this
    # value is below but turned off as it can slow the model. Set the
    # 'calculate_BR' variable to 'True' if you want to calculate it.

    if calculate_BR:

        aspects = rmg.calc_aspect_at_node()  # measure pixel aspect

        # classify and count the number of pixels with certain directions
from matplotlib import pyplot as plt

## Make a grid that is 100 by 100 with dx=dy=100. m
rmg1 = RasterModelGrid((100, 100), 100.)
## Add elevation field to the grid.
z1 = rmg1.add_ones('node', 'topographic__elevation')

## Instantiate process components
ld1 = LinearDiffuser(rmg1, linear_diffusivity=0.1)
fr1 = FlowRouter(rmg1, method='D8')
fse1 = FastscapeEroder(rmg1, K_sp=1e-5, m_sp=0.5, n_sp=1.)

## Set some variables
rock_up_rate = 1e-3  #m/yr
dt = 1000  # yr
rock_up_len = dt * rock_up_rate  # m

## Time loop where evolution happens
for i in range(500):
    z1[rmg1.core_nodes] += rock_up_len  #uplift only the core nodes
    ld1.run_one_step(dt)  #linear diffusion happens.
    fr1.run_one_step()  #flow routing happens, time step not needed
    fse1.run_one_step(dt)  #fluvial incision happens
    ## optional print statement
    print('i', i)

## Plotting the topography
plt.figure(1)
imshow_grid(rmg1, 'topographic__elevation')

#need to run for about 4000 time steps, or 4,000,000 years to reach SS
예제 #10
0
mg.status_at_node[outlet]=1




#PROCESS SET-UP
#initialize linear diffuser component
lin_diffuse = LinearDiffuser(mg, linear_diffusivity=lin_dif)
#iniitalize erosion by run-off
fr = FlowRouter(mg)
sp = FastscapeEroder(mg,K_sp=K_sp, m_sp=m_sp, n_sp=n_sp)



for i in range(nt):
    fr.run_one_step() 
    sp.run_one_step(dt)
    lin_diffuse.run_one_step(dt)
    z[mg.core_nodes] += uplift_rate * dt  # add the uplift
    
#    color_list=np.linspace(1,0.3,nt)
    if i % 20 == 0:
        print(i*dt)
        

mg.set_watershed_boundary_condition(z,remove_disconnected=True)

fig=plt.figure(figsize=(8,6))
fig.suptitle('Kd='+str(lin_dif)+' Ks='+str(K_sp)+' U='+str(uplift_rate)+'\n\n')
ax1=fig.add_subplot(221)
ax2=fig.add_subplot(222,sharex=ax1,sharey=ax1)
예제 #11
0
#Create boundary conditions of the model grid (either closed or fixed-head)
for edge in (mg.nodes_at_left_edge,mg.nodes_at_right_edge, mg.nodes_at_top_edge):
    mg.status_at_node[edge] = CLOSED_BOUNDARY
for edge in (mg.nodes_at_bottom_edge):
    mg.status_at_node[edge] = FIXED_VALUE_BOUNDARY

#Initialize Fastscape
fc = FastscapeEroder(mg,
                    K_sp = ksp ,
                    m_sp = msp,
                    n_sp = nsp,
                    rainfall_intensity = 1)
fr = FlowRouter(mg)
lm = DepressionFinderAndRouter(mg)

for i in range(nSteps):
    fr.run_one_step(dt=1)
    lm.map_depressions()
    fc.run_one_step(dt=1)
    mg.at_node['topographic__elevation'][mg.core_nodes] += 0.0002

z = mg.at_node['topographic__elevation']

plt.figure()
imshow_grid(mg,z)
plt.savefig('test.png')
plt.close()

np.save('iniTopo',z)
class HybridAlluviumModel(_ErosionModel):
    """
    A HybridAlluviumModel computes erosion of sediment and bedrock
    using dual mass conservation on the bed and in the water column. It
    applies exponential entrainment rules to account for bed cover.
    """
    def __init__(self, input_file=None, params=None):
        """Initialize the HybridAlluviumModel."""

        # Call ErosionModel's init
        super(HybridAlluviumModel, self).__init__(input_file=input_file,
                                                  params=params)

        # Instantiate a FlowRouter and DepressionFinderAndRouter components
        self.flow_router = FlowRouter(self.grid, **self.params)
        self.lake_filler = DepressionFinderAndRouter(self.grid, **self.params)

        #make area_field and/or discharge_field depending on discharge_method
        if self.params['discharge_method'] is not None:
            if self.params['discharge_method'] == 'area_field':
                area_field = self.grid.at_node['drainage_area']
                discharge_field = None
            elif self.params['discharge_method'] == 'discharge_field':
                discharge_field = self.grid.at_node['surface_water__discharge']
                area_field = None
            else:
                raise (KeyError)
        else:
            area_field = None
            discharge_field = None

        # Instantiate a HybridAlluvium component
        self.eroder = Space(self.grid,
                            K_sed=self.params['K_sed'],
                            K_br=self.params['K_br'],
                            F_f=self.params['F_f'],
                            phi=self.params['phi'],
                            H_star=self.params['H_star'],
                            v_s=self.params['v_s'],
                            m_sp=self.params['m_sp'],
                            n_sp=self.params['n_sp'],
                            sp_crit_sed=self.params['sp_crit_sed'],
                            sp_crit_br=self.params['sp_crit_br'],
                            method=self.params['method'],
                            discharge_method=self.params['discharge_method'],
                            area_field=area_field,
                            discharge_field=discharge_field)

    def run_one_step(self, dt):
        """
        Advance model for one time-step of duration dt.
        """

        # Route flow
        self.flow_router.run_one_step()
        self.lake_filler.map_depressions()

        # Get IDs of flooded nodes, if any
        flooded = np.where(self.lake_filler.flood_status == 3)[0]

        # Do some erosion (but not on the flooded nodes)
        self.eroder.run_one_step(dt, flooded_nodes=flooded)
예제 #13
0
 #### Instantiate process components
 ld1 = LinearDiffuser(rmg1, linear_diffusivity=0.3)                             ### parameters defined
 fr1 = FlowRouter(rmg1, method='D8')
 #slp1 = FlowRouter(slps,method='D8')
 fse1 = FastscapeEroder(rmg1, K_sp = 1e-5, m_sp=0.5, n_sp=1.)                   ### parameters defined                  
 
 ## Set some variables
 rock_up_rate = 1e-4 # m/yr # uplift rate                                       ### parameter defined
 dt = 1000 # yr
 rock_up_len = dt*rock_up_rate # m
 
 ## Time loop where evolution happens
 for i in range(50000):
     z1[rmg1.core_nodes] += rock_up_len #uplift only the core nodes
     ld1.run_one_step(dt) #linear diffusion happens.
     fr1.run_one_step() #flow routing happens, time step not needed, as this is not time sensitive
     fse1.run_one_step(dt) #fluvial incision happens
     ## optional print statement
 #    print('i', i)
     
 ## Plotting the topography
 plt.figure(1)
 imshow_grid(rmg1, 'topographic__elevation', grid_units = ['m','m'],
                  var_name='Elevation (m)')
 plt.savefig('diffusive_%i.png' %seed_n)
 plt.close()
 #need to run for about 4000 time steps, or 4,000,000 years to reach SS
 
 
 ################### Waterhsed 2  ##############################################
 ###### Instantiate process components
frr = FlowRouter(mg) # water__unit_flux_in gets automatically ingested
spr = StreamPowerEroder(mg, K_sp=K_sp, m_sp=m_sp, n_sp=n_sp, threshold_sp=0,
                        use_Q=None)
lake = DepressionFinderAndRouter(mg)
    
# Hillslopes
dfn = LinearDiffuser(mg, linear_diffusivity=K_hs)

zr_last = -9999
keep_running = np.mean(np.abs(zr - zr_last)) >= end_thresh
ti = 0
while keep_running:
    zr_last = zr.copy()
    zr[mg.core_nodes] += uplift_rate*dt
    dfn.run_one_step(dt) # hillslopes always diffusive, even when dry
    frr.run_one_step()
    lake.map_depressions()
    spr.run_one_step(dt, flooded_nodes=lake.lake_at_node)
    keep_running = np.mean(np.abs(zr - zr_last)) >= end_thresh
    ti += dt
    print ti/1000., 'kyr elapsed; ', np.mean(zr-zr_last) / dt * 1E6, \
          'um/yr surface uplift'
print "Convergence reached! Landscape is at steady state."

A = mg.at_node['drainage_area']#[not_edge]
A = A.reshape(ncells_side, ncells_side)
S = mg.at_node['topographic__steepest_slope']
S = S.reshape(ncells_side, ncells_side)

np.savetxt('Synthetic_data/z.txt', zr, fmt='%.2f')
np.savetxt('Synthetic_data/A.txt', A, fmt='%d')
class StochasticDischargeHortonianModel(_ErosionModel):
    """
    A StochasticDischargeHortonianModel generates a random sequency of
    runoff events across a topographic surface, calculating the resulting
    water discharge at each node.
    """
    
    def __init__(self, input_file=None, params=None):
        """Initialize the StochasticDischargeHortonianModel."""

        # Call ErosionModel's init
        super(StochasticDischargeHortonianModel,
              self).__init__(input_file=input_file, params=params)

        # Instantiate components
        self.flow_router = FlowRouter(self.grid, **self.params)

        self.lake_filler = DepressionFinderAndRouter(self.grid, **self.params)

        self.rain_generator = \
            PrecipitationDistribution(delta_t=self.params['dt'],
                                      total_time=self.params['run_duration'],
                                      **self.params)

        # Add a field for discharge
        if 'surface_water__discharge' not in self.grid.at_node:
            self.grid.add_zeros('node', 'surface_water__discharge')
        self.discharge = self.grid.at_node['surface_water__discharge']                                    

        # Get the infiltration-capacity parameter
        self.infilt = self.params['infiltration_capacity']

        # Run flow routing and lake filler (only once, because we are not
        # not changing topography)
        self.flow_router.run_one_step()
        self.lake_filler.map_depressions()


    def reset_random_seed(self):
        """Re-set the random number generation sequence."""
        try:
            seed = self.params['random_seed']
        except KeyError:
            seed = 0
        self.rain_generator.seed_generator(seedval=seed)


    def run_one_step(self, dt):
        """
        Advance model for one time-step of duration dt.
        """

        # Calculate discharge field
        area = self.grid.at_node['drainage_area']
        if self.infilt > 0.0:
            runoff = self.rain_rate - (self.infilt * 
                                       (1.0 - 
                                        np.exp(-self.rain_rate / self.infilt)))
        else:
            runoff = self.rain_rate
        self.discharge[:] = runoff * area


    def run_for(self, dt, runtime):
        """
        Run model without interruption for a specified time period.
        """
        self.rain_generator.delta_t = dt
        self.rain_generator.run_time = runtime
        for (tr, p) in self.rain_generator.yield_storm_interstorm_duration_intensity(): 
            self.rain_rate = p
            self.run_one_step(tr)


    def write_storm_sequence_to_file(self, filename=None):
        """
        Write event duration and intensity to a formatted text file.
        """

        # Re-seed the random number generator, so we get the same sequence.
        self.reset_random_seed()
        
        # Generate a set of event parameters. This is needed because the
        # PrecipitationDistribution component automatically generates a
        # parameter set on initialization. Therefore, to get to the same
        # starting point that we used in the sequence-through-time, we need
        # to regenerate these.
        self.rain_generator.get_precipitation_event_duration()
        self.rain_generator.get_interstorm_event_duration()
        self.rain_generator.get_storm_depth()
        self.rain_generator.get_storm_intensity()
        
        # Open a file for writing
        if filename is None:
            filename = 'event_sequence.txt'
        stormfile = open(filename, 'w')

        # Set the generator's time step and run time to the full duration of
        # the run. This ensures that we get a sequence that is as long as the
        # model run, and does not split events by time step (unlike the actual
        # model run)
        self.rain_generator.delta_t = self.params['run_duration']
        self.rain_generator.run_time = self.params['run_duration']
        tt = 0.0
        for (tr, p) in self.rain_generator.yield_storm_interstorm_duration_intensity():        
            runoff = p - self.infilt * (1.0 - np.exp(-p / self.infilt))
            stormfile.write(str(tt) + ',' + str(p) + ',' + str(runoff) + '\n')
            tt += tr
        stormfile.write(str(tt) + ',' + str(p) + ',' + str(runoff) + '\n')

        # Close the file
        stormfile.close()
예제 #16
0
class StreamPowerVarThresholdModel(_ErosionModel):
    """
    A StreamPowerVarThresholdModel computes erosion using a form of the unit
    stream power model that represents a threshold using an exponential term.
    The threshold value itself depends on incision depth below an initial
    reference surface. This is meant to mimic coarsening of sediment in the
    channel with progressive incision, similar to the model of 
    Gran et al. (2013)
    """
    
    def __init__(self, input_file=None, params=None):
        """Initialize the StreamPowerVarThresholdModel."""

        # Call ErosionModel's init
        super(StreamPowerVarThresholdModel, self).__init__(input_file=input_file,
                                                params=params)

        # Instantiate a FlowRouter and DepressionFinderAndRouter components
        self.flow_router = FlowRouter(self.grid, **self.params)
        self.lake_filler = DepressionFinderAndRouter(self.grid, **self.params)
        
        # Create a field for the (initial) erosion threshold
        self.threshold = self.grid.add_zeros('node', 'erosion__threshold')
        self.threshold[:] = self.params['threshold_sp']
        
        # Instantiate a FastscapeEroder component
        self.eroder = StreamPowerSmoothThresholdEroder(
            self.grid,
            K_sp=self.params['K_sp'],
            threshold_sp=self.threshold)

        # Get the parameter for rate of threshold increase with erosion depth
        self.thresh_change_per_depth = self.params['thresh_change_per_depth']


    def run_one_step(self, dt):
        """
        Advance model for one time-step of duration dt.
        """

        # Route flow
        self.flow_router.run_one_step()
        self.lake_filler.map_depressions()

        # Get IDs of flooded nodes, if any
        flooded = np.where(self.lake_filler.flood_status==3)[0]

        # Set the erosion threshold.
        #
        # Note that a minus sign is used because cum ero depth is negative for
        # erosion, positive for deposition.
        # The second line handles the case where there is growth, in which case
        # we want the threshold to stay at its initial value rather than 
        # getting smaller.
        cum_ero = self.grid.at_node['cumulative_erosion__depth']
        cum_ero[:] = (self.z
                      - self.grid.at_node['initial_topographic__elevation'])
        self.threshold[:] = (self.params['threshold_sp']
                             - (self.thresh_change_per_depth
                                * cum_ero))
        self.threshold[self.threshold < self.params['threshold_sp']] = \
            self.params['threshold_sp']

        # Do some erosion (but not on the flooded nodes)
        self.eroder.run_one_step(dt, flooded_nodes=flooded)
예제 #17
0
def draw_profile_evolution(start,
                           stop,
                           step,
                           format,
                           directory='.',
                           force_same_nodes=False,
                           plot_field_downstream=None,
                           different_runs_different_plots=True):
    """Plot a set of long profiles, loaded from saved data.

    "format" is the number of numbers in the file string.
    e.g., "00150" is 5. "012345" is 6.
    "plot_field_downstream" is the string of a field at which values should
    also be plotted, on a second figure.
    """
    mg2 = deepcopy(mg)
    z2 = mg2.add_zeros('node', 'topographic__elevation', noclobber=False)
    fr2 = FlowRouter(mg2)
    first = True
    for i in xrange(start, stop, step):
        num_zeros = format - len(str(i))
        numberstr = '0' * num_zeros + str(i) + '_'
        # search for this string as a topo:
        prefixed = [
            filename for filename in os.listdir(directory)
            if filename.startswith('topographic__elevation_' + numberstr)
        ]
        # grab the unique ID, so we can differentiate plots (if desired)
        unique_ID = prefixed[0][-14:-4]
        print('Plotting the profile with unique ID: ' + unique_ID)
        try:
            z2[:] = np.loadtxt(directory + '/' + prefixed[0])
        except IndexError:
            raise IndexError(
                "it's likely you've mis-set directory, or end is out of range")
        if plot_field_downstream is not None:
            prefixedvals = [
                filename for filename in os.listdir(directory)
                if filename.startswith(plot_field_downstream + '_' + numberstr)
            ]
            field_vals = np.loadtxt(directory + '/' + prefixedvals[0])
        fr2.run_one_step()
        if force_same_nodes:
            if first:
                if different_runs_different_plots:
                    draw_profile(mg2, figure_name=('profile_' + unique_ID))
                else:
                    draw_profile(mg2)
                first = False
                if plot_field_downstream is not None:
                    if different_runs_different_plots:
                        figure('field_values_downstream_' + unique_ID)
                    else:
                        figure('field_values_downstream')
                    plot(ch_dists[0], field_vals[profile_IDs[0]])
            else:
                if different_runs_different_plots:
                    figure('profile_' + unique_ID)
                else:
                    figure('profile')
                plot(ch_dists[0],
                     mg2.at_node['topographic__elevation'][profile_IDs[0]])
                if plot_field_downstream is not None:
                    if different_runs_different_plots:
                        figure('field_values_downstream_' + unique_ID)
                    else:
                        figure('field_values_downstream')
                    plot(ch_dists[0], field_vals[profile_IDs[0]])
        else:
            if different_runs_different_plots:
                draw_profile(mg2, figure_name=('profile_' + unique_ID))
            else:
                draw_profile(mg2)
            if plot_field_downstream is not None:
                profile_IDs = channel_nodes(
                    mg2, mg2.at_node['topographic__steepest_slope'],
                    mg2.at_node['drainage_area'],
                    mg2.at_node['flow__receiver_node'])
                ch_dists = get_distances_upstream(
                    mg2, len(mg2.at_node['topographic__steepest_slope']),
                    profile_IDs, mg2.at_node['flow__link_to_receiver_node'])
                if different_runs_different_plots:
                    figure('field_values_downstream_' + unique_ID)
                else:
                    figure('field_values_downstream')
                plot(ch_dists[0], field_vals[profile_IDs[0]])
    if plot_field_downstream is not None:
        if different_runs_different_plots:
            figure('field_values_downstream_' + unique_ID)
        else:
            figure('field_values_downstream')
        xlabel('Distance downstream (m)')
        ylabel('Field value')
def get_ordered_cells_for_soil_moisture(grid, outlet_id=None):
    """
    Runs Landlab's FlowRouter and DepressionFinderAndRouter to
    route flow. Also orders the cells in the descending order of
    channel length (upstream cell order).
    
    Parameters:
    ==========    
    grid: grid object
        RasterModelGrid
    outlet_id: int (Optional)
        Outlet id to be set

    Returns:
    =======
    ordered_cells: np.array(dtype=int)
        cells ordered in descending order of channel length
    grid: grid object
        updated RasterModelGrid
    """

    if outlet_id == None:
        outlet_id = np.argmin(grid.at_node['topographic__elevation'])    
    outlet = grid.set_watershed_boundary_condition_outlet_id(outlet_id,
        grid.at_node['topographic__elevation'], nodata_value=-9999.,)
    grid.set_closed_boundaries_at_grid_edges(True, True, True, True)
    flw_r = FlowRouter(grid)
    flw_r.run_one_step()
    df = DepressionFinderAndRouter(grid)
    df.map_depressions()
    r = grid.at_node['flow__receiver_node'][grid.node_at_core_cell]
    R = np.zeros(grid.number_of_nodes, dtype=int)
    R[grid.node_at_core_cell] = r
    channel_length = np.zeros(grid.number_of_nodes, dtype=int)
    # Compute channel lengths for each node in the wtrshd (node_at_core_cell)
    for node in grid.node_at_core_cell:
        node_c = node.copy()
        while R[node_c] != node_c:
            channel_length[node] += 1
            node_c = R[node_c]
    grid.at_node['channel_length'] = channel_length
    # Sorting nodes in the ascending order of channel length
    # NOTE: length of ordered_nodes = grid.number_of_core_cells
    ordered_nodes = grid.node_at_core_cell[
        np.argsort(channel_length[grid.node_at_core_cell])]
    # Sorting nodes in the descending order of channel length
    ordered_nodes = ordered_nodes[::-1]
    dd = 1    # switch 2 for while loop
    count_loops = 0 # No. of loops while runs
    while dd:
        dd = 0
        count_loops += 1
        sorted_order = list(ordered_nodes)
        alr_counted_ = []
        for node_ in sorted_order:
            donors = []
            donors = list(grid.node_at_core_cell[np.where(r==node_)[0]])
            if len(donors) != 0:
                for k in range(0, len(donors)):
                    if donors[k] not in alr_counted_:
                        sorted_order.insert(donors[k], sorted_order.pop(sorted_order.index(node_)))
                        dd = 1    
            alr_counted_.append(node_)
        ordered_nodes = np.array(sorted_order)
    ordered_cells = grid.cell_at_node[ordered_nodes]
    return ordered_cells, grid
    model_run_time = durations_s[i] + (interstorm_durs[i] * 3600.)

    storm_events.append(
        [durations[i], intensities[i], durations[i] * intensities[i]])
    dt = float(durations_s[i])
    uplift_dt = float(durations_s[i] +
                      (interstorm_durs[i] * 3600.)) * 3.17098e-8

    rainfall_ms = intensities[i] * 2.777777777778e-7

    fr = FlowRouter(rmg, method='D4', runoff_rate=float(rainfall_ms))
    fr1 = FlowRouter(rmg1, method='D4', runoff_rate=float(rainfall_ms))
    fr5 = FlowRouter(rmg5, method='D4', runoff_rate=float(rainfall_ms))
    fr10 = FlowRouter(rmg10, method='D4', runoff_rate=float(rainfall_ms))

    fr.run_one_step()
    fr1.run_one_step()
    fr5.run_one_step()
    fr10.run_one_step()

    last_z = copy.deepcopy(z)
    last_z1 = copy.deepcopy(z1)
    last_z5 = copy.deepcopy(z5)
    last_z10 = copy.deepcopy(z10)

    rmg, z, _ = dle.erode(rmg, dt=dt)
    rmg1, z1, e1 = dle1.erode(rmg1, dt=dt)
    rmg5, z5, e5 = dle5.erode(rmg5, dt=dt)
    rmg10, z10, e10 = dle10.erode(rmg10, dt=dt)

    total_incision_depth += last_z - z