Esempio n. 1
0
def test_can_run_with_hex():
    """Test that model can run with hex model grid."""

    # Set up a 5x5 grid with open boundaries and low initial elevations.
    mg = HexModelGrid(7, 7)
    z = mg.add_zeros('node', 'topographic__elevation')
    z[:] = 0.01 * mg.x_of_node

    # Create a D8 flow handler
    fa = FlowAccumulator(mg, flow_director='FlowDirectorSteepest')

    # Parameter values for test 1
    U = 0.001
    dt = 10.0

    # Create the Space component...
    sp = Space(mg,
               K_sed=0.00001,
               K_br=0.00000000001,
               F_f=0.5,
               phi=0.1,
               H_star=1.,
               v_s=0.001,
               m_sp=0.5,
               n_sp=1.0,
               sp_crit_sed=0,
               sp_crit_br=0)

    # ... and run it to steady state.
    for i in range(2000):
        fa.run_one_step()
        sp.run_one_step(dt=dt)
        z[mg.core_nodes] += U * dt
Esempio n. 2
0
def test_mass_conserve_with_depression_finder_Space(grid2, H, solver,
                                                    depression_finder, phi,
                                                    v_s, H_star, dt):
    grid2.at_node["soil__depth"][:] = H
    assert grid2.status_at_node[1] == grid2.BC_NODE_IS_FIXED_VALUE

    z_init = grid2.at_node["topographic__elevation"].copy()

    if depression_finder is None:
        fa = FlowAccumulator(grid2)
    else:
        fa = FlowAccumulator(grid2,
                             depression_finder=depression_finder,
                             routing="D4")
    fa.run_one_step()

    ed = Space(grid2, solver=solver, phi=phi, v_s=v_s, H_star=H_star)
    ed.run_one_step(dt)

    # see above test for notes.
    dH = grid2.at_node["soil__depth"][:] - H
    dH *= 1 - phi
    dBr = grid2.at_node["bedrock__elevation"] - (z_init - H)
    mass_change = dH + dBr

    # assert that the mass loss over the surface is exported through the one
    # outlet.
    net_change = mass_change[grid2.core_nodes].sum() + (
        ed.sediment_influx[1] * dt / grid2.cell_area_at_node[11])
    assert_array_almost_equal(net_change, 0.0, decimal=10)
Esempio n. 3
0
def test_soil_field_already_on_grid():
    """
    Test that an existing soil grid field is not changed by instantiating
    SPACE.
    """

    # set up a 5x5 grid with one open outlet node and low initial elevations.
    nr = 5
    nc = 5
    mg = RasterModelGrid((nr, nc), xy_spacing=10.0)

    z = mg.add_zeros("topographic__elevation", at="node")
    br = mg.add_zeros("bedrock__elevation", at="node")
    soil = mg.add_zeros("soil__depth", at="node")
    soil += 1.0  # add 1m of soil everywehre

    mg["node"]["topographic__elevation"] += (
        mg.node_y / 10000 + mg.node_x / 10000 + np.random.rand(len(mg.node_y)) / 10000
    )
    mg.set_closed_boundaries_at_grid_edges(
        bottom_is_closed=True,
        left_is_closed=True,
        right_is_closed=True,
        top_is_closed=True,
    )
    mg.set_watershed_boundary_condition_outlet_id(
        0, mg["node"]["topographic__elevation"], -9999.0
    )
    br[:] = z[:] - soil[:]

    # Create a D8 flow handler
    FlowAccumulator(mg, flow_director="D8")

    # Instantiate SPACE
    sp = Space(
        mg,
        K_sed=0.01,
        K_br=0.01,
        F_f=0.0,
        phi=0.0,
        v_s=0.001,
        m_sp=0.5,
        n_sp=1.0,
        sp_crit_sed=0,
        sp_crit_br=0,
        solver="basic",
    )

    # ensure that 'soil__depth' field is everywhere equal to 1.0 m.
    testing.assert_array_equal(
        np.ones(mg.number_of_nodes),
        sp._soil__depth,
        err_msg="SPACE soil depth field test failed",
        verbose=True,
    )
Esempio n. 4
0
def test_br_field_already_on_grid():
    """
    Test that an existing bedrock elevation grid field is not changed by 
    instantiating SPACE.
    """

    #set up a 5x5 grid with one open outlet node and low initial elevations.
    nr = 5
    nc = 5
    mg = RasterModelGrid((nr, nc), 10.0)

    z = mg.add_zeros('node', 'topographic__elevation')
    br = mg.add_zeros('node', 'bedrock__elevation')
    br += 1.  #make bedrock elevation 5m below surface
    soil = mg.add_zeros('node', 'soil__depth')

    mg['node']['topographic__elevation'] += mg.node_y / 10000 \
        + mg.node_x / 10000 \
        + np.random.rand(len(mg.node_y)) / 10000
    mg.set_closed_boundaries_at_grid_edges(bottom_is_closed=True,
                                           left_is_closed=True,
                                           right_is_closed=True,
                                           top_is_closed=True)
    mg.set_watershed_boundary_condition_outlet_id(
        0, mg['node']['topographic__elevation'], -9999.)
    z[:] = br[:] + soil[:]

    # Create a D8 flow handler
    fa = FlowAccumulator(mg, flow_director='D8')

    #Instantiate SPACE
    sp = Space(mg,
               K_sed=0.01,
               K_br=0.01,
               F_f=0.0,
               phi=0.0,
               v_s=0.001,
               m_sp=0.5,
               n_sp=1.0,
               sp_crit_sed=0,
               sp_crit_br=0,
               solver='basic')

    #ensure that 'bedrock__elevation' field is everywhere equal to 1.0 m.
    testing.assert_array_equal(np.ones(mg.number_of_nodes),
                               sp.bedrock__elevation,
                               err_msg='SPACE bedrock field test failed',
                               verbose=True)
Esempio n. 5
0
def test_bad_solver_name():
    """
    Test that any solver name besides 'basic' and 'adaptive' raises an error.
    """

    # set up a 5x5 grid with one open outlet node and low initial elevations.
    nr = 5
    nc = 5
    mg = RasterModelGrid((nr, nc), xy_spacing=10.0)

    z = mg.add_zeros("topographic__elevation", at="node")
    br = mg.add_zeros("bedrock__elevation", at="node")
    soil = mg.add_zeros("soil__depth", at="node")

    mg["node"]["topographic__elevation"] += (
        mg.node_y / 10000 + mg.node_x / 10000 + np.random.rand(len(mg.node_y)) / 10000
    )
    mg.set_closed_boundaries_at_grid_edges(
        bottom_is_closed=True,
        left_is_closed=True,
        right_is_closed=True,
        top_is_closed=True,
    )
    mg.set_watershed_boundary_condition_outlet_id(
        0, mg["node"]["topographic__elevation"], -9999.0
    )
    br[:] = z[:] - soil[:]

    # Create a D8 flow handler
    FlowAccumulator(mg, flow_director="D8")

    # try to instantiate SPACE using a wrong solver name
    with pytest.raises(ValueError):
        Space(
            mg,
            K_sed=0.01,
            K_br=0.01,
            F_f=0.0,
            phi=0.0,
            v_s=0.001,
            m_sp=0.5,
            n_sp=1.0,
            sp_crit_sed=0,
            sp_crit_br=0,
            solver="something_else",
        )
Esempio n. 6
0
def test_route_to_multiple_error_raised():
    mg = RasterModelGrid((10, 10))
    z = mg.add_zeros('node', 'topographic__elevation')
    z += mg.x_of_node + mg.y_of_node
    fa = FlowAccumulator(mg, flow_director='MFD')
    fa.run_one_step()

    with pytest.raises(NotImplementedError):
        Space(mg,
              K_sed=0.1,
              K_br=0.1,
              F_f=0.5,
              phi=0.1,
              H_star=1.,
              v_s=0.001,
              m_sp=1.0,
              n_sp=0.5,
              sp_crit_sed=0,
              sp_crit_br=0)
    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)
Esempio n. 8
0
def test_mass_conserve_all_closed_Space(grid, H, solver, phi, v_s, H_star, dt):
    grid.at_node["soil__depth"][:] = H

    z_init = grid.at_node["topographic__elevation"].copy()

    fa = FlowAccumulator(grid)
    fa.run_one_step()

    ed = Space(grid, solver=solver, phi=phi, v_s=v_s, H_star=H_star)
    ed.run_one_step(dt)

    # in space, everything is either bedrock or sediment. check for
    # conservation.
    dH = grid.at_node["soil__depth"][:] - H

    # sediment is defined as having a porosity so all changes (up or down )
    # must be adjusted to mass.
    dH *= 1 - phi

    dBr = grid.at_node["bedrock__elevation"] - (z_init - H)
    mass_change = dH + dBr

    assert_array_almost_equal(mass_change.sum(), 0.0, decimal=10)
Esempio n. 9
0
    def __init__(self,
                 input_file=None,
                 params=None,
                 BaselevelHandlerClass=None):
        """Initialize the BasicSa."""

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

        self.K_br = self.get_parameter_from_exponent('K_rock_sp')
        self.K_sed = self.get_parameter_from_exponent('K_sed_sp')
        linear_diffusivity = (
            self._length_factor**2.) * self.get_parameter_from_exponent(
                'linear_diffusivity')  # has units length^2/time
        v_sc = self.get_parameter_from_exponent(
            'v_sc')  # normalized settling velocity. Unitless.

        linear_diffusivity = (
            self._length_factor**2.) * self.get_parameter_from_exponent(
                'linear_diffusivity')  # has units length^2/time
        try:
            initial_soil_thickness = (self._length_factor) * self.params[
                'initial_soil_thickness']  # has units length
        except KeyError:
            initial_soil_thickness = 1.0  # default value
        soil_transport_decay_depth = (self._length_factor) * self.params[
            'soil_transport_decay_depth']  # has units length
        max_soil_production_rate = (self._length_factor) * self.params[
            'max_soil_production_rate']  # has units length per time
        soil_production_decay_depth = (self._length_factor) * self.params[
            'soil_production_decay_depth']  # has units length

        # Instantiate a FlowAccumulator with DepressionFinderAndRouter using D8 method
        self.flow_router = FlowAccumulator(
            self.grid,
            flow_director='D8',
            depression_finder=DepressionFinderAndRouter)

        #set methods and fields. K's and sp_crits need to be field names
        method = 'simple_stream_power'
        discharge_method = 'discharge_field'
        area_field = None
        discharge_field = 'surface_water__discharge'

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

        # Create soil thickness (a.k.a. depth) field
        if 'soil__depth' in self.grid.at_node:
            soil_thickness = self.grid.at_node['soil__depth']
        else:
            soil_thickness = self.grid.add_zeros('node', 'soil__depth')

        # Create bedrock elevation field
        if 'bedrock__elevation' in self.grid.at_node:
            bedrock_elev = self.grid.at_node['bedrock__elevation']
        else:
            bedrock_elev = self.grid.add_zeros('node', 'bedrock__elevation')

        # Set soil thickness and bedrock elevation
        try:
            initial_soil_thickness = self.params['initial_soil_thickness']
        except KeyError:
            initial_soil_thickness = 1.0  # default value
        soil_thickness[:] = initial_soil_thickness
        bedrock_elev[:] = self.z - initial_soil_thickness

        # Instantiate diffusion and weathering components
        self.diffuser = DepthDependentDiffuser(
            self.grid,
            linear_diffusivity=linear_diffusivity,
            soil_transport_decay_depth=soil_transport_decay_depth)

        self.weatherer = ExponentialWeatherer(
            self.grid,
            max_soil_production_rate=max_soil_production_rate,
            soil_production_decay_depth=soil_production_decay_depth)

        self.grid.at_node['soil__depth'][:] = \
            self.grid.at_node['topographic__elevation'] - \
            self.grid.at_node['bedrock__elevation']
Esempio n. 10
0
def test_matches_bedrock_alluvial_solution():
    """
    Test that model matches the bedrock-alluvial analytical solution
    for slope/area relationship at steady state:
    S=((U * v_s * (1 - F_f)) / (K_sed * A^m) + U / (K_br * A^m))^(1/n).

    Also test that the soil depth everywhere matches the bedrock-alluvial
    analytical solution at steady state:
    H = -H_star * ln(1 - (v_s / (K_sed / (K_br * (1 - F_f)) + v_s))).
    """

    #set up a 5x5 grid with one open outlet node and low initial elevations.
    nr = 5
    nc = 5
    mg = RasterModelGrid((nr, nc), 10.0)

    z = mg.add_zeros('node', 'topographic__elevation')
    br = mg.add_zeros('node', 'bedrock__elevation')
    soil = mg.add_zeros('node', 'soil__depth')

    mg['node']['topographic__elevation'] += (
        mg.node_y / 100000 + mg.node_x / 100000 +
        np.random.rand(len(mg.node_y)) / 10000)
    mg.set_closed_boundaries_at_grid_edges(bottom_is_closed=True,
                                           left_is_closed=True,
                                           right_is_closed=True,
                                           top_is_closed=True)
    mg.set_watershed_boundary_condition_outlet_id(
        0, mg['node']['topographic__elevation'], -9999.)
    soil[:] += 0.  #initial condition of no soil depth.
    br[:] = z[:]
    z[:] += soil[:]

    #Instantiate DepressionFinderAndRouter
    df = DepressionFinderAndRouter(mg)

    # Create a D8 flow handler
    fa = FlowAccumulator(mg,
                         flow_director='D8',
                         depression_finder='DepressionFinderAndRouter')

    # Parameter values for detachment-limited test
    K_br = 0.02
    K_sed = 0.02
    U = 0.0001
    dt = 1.0
    F_f = 0.2  #all detached rock disappears; detachment-ltd end-member
    m_sp = 0.5
    n_sp = 1.0
    v_s = 0.25
    H_star = 0.1

    # Instantiate the Space component...
    sp = Space(mg,
               K_sed=K_sed,
               K_br=K_br,
               F_f=F_f,
               phi=0.0,
               H_star=H_star,
               v_s=v_s,
               m_sp=m_sp,
               n_sp=n_sp,
               sp_crit_sed=0,
               sp_crit_br=0)

    # ... and run it to steady state (10000x1-year timesteps).
    for i in range(10000):
        fa.run_one_step()
        flooded = np.where(df.flood_status == 3)[0]
        sp.run_one_step(dt=dt, flooded_nodes=flooded)
        br[mg.core_nodes] += U * dt  #m
        soil[0] = 0.  #enforce 0 soil depth at boundary to keep lowering steady
        z[:] = br[:] + soil[:]

    #compare numerical and analytical slope solutions
    num_slope = mg.at_node['topographic__steepest_slope'][mg.core_nodes]
    analytical_slope = (np.power(
        ((U * v_s * (1 - F_f)) /
         (K_sed * np.power(mg.at_node['drainage_area'][mg.core_nodes], m_sp)))
        +
        (U /
         (K_br * np.power(mg.at_node['drainage_area'][mg.core_nodes], m_sp))),
        1. / n_sp))

    #test for match with analytical slope-area relationship
    testing.assert_array_almost_equal(
        num_slope,
        analytical_slope,
        decimal=8,
        err_msg='SPACE bedrock-alluvial slope-area test failed',
        verbose=True)

    #compare numerical and analytical soil depth solutions
    num_h = mg.at_node['soil__depth'][mg.core_nodes]
    analytical_h = -H_star * np.log(1 - (v_s / (K_sed / (K_br *
                                                         (1 - F_f)) + v_s)))

    #test for match with analytical sediment depth
    testing.assert_array_almost_equal(
        num_h,
        analytical_h,
        decimal=5,
        err_msg='SPACE bedrock-alluvial soil thickness test failed',
        verbose=True)
Esempio n. 11
0
def test_matches_detachment_solution():
    """
    Test that model matches the detachment-limited analytical solution
    for slope/area relationship at steady state: S=(U/K_br)^(1/n)*A^(-m/n).
    """

    #set up a 5x5 grid with one open outlet node and low initial elevations.
    nr = 5
    nc = 5
    mg = RasterModelGrid((nr, nc), 10.0)

    z = mg.add_zeros('node', 'topographic__elevation')
    br = mg.add_zeros('node', 'bedrock__elevation')
    soil = mg.add_zeros('node', 'soil__depth')

    mg['node']['topographic__elevation'] += mg.node_y / 10000 \
        + mg.node_x / 10000 \
        + np.random.rand(len(mg.node_y)) / 10000
    mg.set_closed_boundaries_at_grid_edges(bottom_is_closed=True,
                                           left_is_closed=True,
                                           right_is_closed=True,
                                           top_is_closed=True)
    mg.set_watershed_boundary_condition_outlet_id(
        0, mg['node']['topographic__elevation'], -9999.)
    br[:] = z[:] - soil[:]

    # Create a D8 flow handler
    fa = FlowAccumulator(mg, flow_director='D8')

    # Parameter values for detachment-limited test
    K_br = 0.01
    U = 0.0001
    dt = 1.0
    F_f = 1.0  #all detached rock disappears; detachment-ltd end-member
    m_sp = 0.5
    n_sp = 1.0

    # Instantiate the Space component...
    sp = Space(mg,
               K_sed=0.00001,
               K_br=K_br,
               F_f=F_f,
               phi=0.1,
               H_star=1.,
               v_s=0.001,
               m_sp=m_sp,
               n_sp=n_sp,
               sp_crit_sed=0,
               sp_crit_br=0)

    # ... and run it to steady state (2000x1-year timesteps).
    for i in range(2000):
        fa.run_one_step()
        sp.run_one_step(dt=dt)
        z[mg.core_nodes] += U * dt  #m
        br[mg.core_nodes] = z[mg.core_nodes] - soil[mg.core_nodes]

    #compare numerical and analytical slope solutions
    num_slope = mg.at_node['topographic__steepest_slope'][mg.core_nodes]
    analytical_slope = np.power(U / K_br, 1./n_sp) \
        * np.power(mg.at_node['drainage_area'][mg.core_nodes], -m_sp / n_sp)

    #test for match with analytical slope-area relationship
    testing.assert_array_almost_equal(
        num_slope,
        analytical_slope,
        decimal=8,
        err_msg='SPACE detachment-limited test failed',
        verbose=True)
Esempio n. 12
0
def test_matches_transport_solution():
    """
    Test that model matches the transport-limited analytical solution
    for slope/area relationship at steady state: S=((U * v_s) / (K_sed * A^m)
    + U / (K_sed * A^m))^(1/n).

    Also test that model matches the analytical solution for steady-state
    sediment flux: Qs = U * A * (1 - phi).
    """

    # set up a 5x5 grid with one open outlet node and low initial elevations.
    nr = 5
    nc = 5
    mg = RasterModelGrid((nr, nc), xy_spacing=10.0)

    z = mg.add_zeros("node", "topographic__elevation")
    br = mg.add_zeros("node", "bedrock__elevation")
    soil = mg.add_zeros("node", "soil__depth")

    mg["node"]["topographic__elevation"] += (
        mg.node_y / 100000 + mg.node_x / 100000 +
        np.random.rand(len(mg.node_y)) / 10000)
    mg.set_closed_boundaries_at_grid_edges(
        bottom_is_closed=True,
        left_is_closed=True,
        right_is_closed=True,
        top_is_closed=True,
    )
    mg.set_watershed_boundary_condition_outlet_id(
        0, mg["node"]["topographic__elevation"], -9999.0)
    soil[:] += 100.0  # initial soil depth of 100 m
    br[:] = z[:]
    z[:] += soil[:]

    # Instantiate DepressionFinderAndRouter
    df = DepressionFinderAndRouter(mg)

    # Create a D8 flow handler
    fa = FlowAccumulator(mg,
                         flow_director="D8",
                         depression_finder="DepressionFinderAndRouter")

    # Parameter values for detachment-limited test
    K_sed = 0.01
    U = 0.0001
    dt = 1.0
    F_f = 1.0  # all detached rock disappears; detachment-ltd end-member
    m_sp = 0.5
    n_sp = 1.0
    v_s = 0.5
    phi = 0.5

    # Instantiate the Space component...
    sp = Space(
        mg,
        K_sed=K_sed,
        K_br=0.01,
        F_f=F_f,
        phi=phi,
        H_star=1.0,
        v_s=v_s,
        m_sp=m_sp,
        n_sp=n_sp,
        sp_crit_sed=0,
        sp_crit_br=0,
    )

    # ... and run it to steady state (5000x1-year timesteps).
    for i in range(5000):
        fa.run_one_step()
        flooded = np.where(df.flood_status == 3)[0]
        sp.run_one_step(dt=dt, flooded_nodes=flooded)
        br[mg.core_nodes] += U * dt  # m
        soil[
            0] = 100.0  # enforce constant soil depth at boundary to keep lowering steady
        z[:] = br[:] + soil[:]

    # compare numerical and analytical slope solutions
    num_slope = mg.at_node["topographic__steepest_slope"][mg.core_nodes]
    analytical_slope = np.power(
        ((U * v_s * (1 - phi)) /
         (K_sed * np.power(mg.at_node["drainage_area"][mg.core_nodes], m_sp)))
        +
        ((U * (1 - phi)) /
         (K_sed * np.power(mg.at_node["drainage_area"][mg.core_nodes], m_sp))),
        1.0 / n_sp,
    )

    # test for match with analytical slope-area relationship
    testing.assert_array_almost_equal(
        num_slope,
        analytical_slope,
        decimal=8,
        err_msg="SPACE transport-limited slope-area test failed",
        verbose=True,
    )

    # compare numerical and analytical sediment flux solutions
    num_sedflux = mg.at_node["sediment__flux"][mg.core_nodes]
    analytical_sedflux = U * mg.at_node["drainage_area"][mg.core_nodes] * (1 -
                                                                           phi)

    # test for match with anakytical sediment flux
    testing.assert_array_almost_equal(
        num_sedflux,
        analytical_sedflux,
        decimal=8,
        err_msg="SPACE transport-limited sediment flux test failed",
        verbose=True,
    )
F_f = 0.
phi = 0.
H_star = 1.
v_s = 5.0
m_sp = 0.5
n_sp = 1.0
sp_crit_sed = 0.
sp_crit_br = 0.

#Instantiate SPACE model with chosen parameters
sp = Space(mg,
           K_sed=K_sed,
           K_br=K_br,
           F_f=F_f,
           phi=phi,
           H_star=H_star,
           v_s=v_s,
           m_sp=m_sp,
           n_sp=n_sp,
           sp_crit_sed=sp_crit_sed,
           sp_crit_br=sp_crit_br,
           method='simple_stream_power')

##Run time loop###########################################################
#Set model timestep
timestep = 1.0  #years

#Set elapsed time to zero
elapsed_time = 0

#Set model run time
run_time = 100000  #years
Esempio n. 14
0
    def __init__(
        self,
        clock,
        grid,
        m_sp=0.5,
        n_sp=1.0,
        water_erodibility_sediment=0.001,
        water_erodibility_rock=0.0001,
        regolith_transport_parameter=0.1,
        settling_velocity=0.001,
        sediment_porosity=0.3,
        fraction_fines=0.5,
        roughness__length_scale=0.5,
        solver="basic",
        soil_production__maximum_rate=0.001,
        soil_production__decay_depth=0.5,
        soil_transport_decay_depth=0.5,
        sp_crit_br=0,
        sp_crit_sed=0,
        **kwargs
    ):
        """
        Parameters
        ----------
        clock : terrainbento Clock instance
        grid : landlab model grid instance
            The grid must have all required fields.
        m_sp : float, optional
            Drainage area exponent (:math:`m`). Default is 0.5.
        n_sp : float, optional
            Slope exponent (:math:`n`). Default is 1.0.
        water_erodibility : float, optional
            Water erodibility (:math:`K`). Default is 0.0001.
        regolith_transport_parameter : float, optional
            Regolith transport efficiency (:math:`D`). Default is 0.1.
        settling_velocity : float, optional
            Normalized settling velocity of entrained sediment (:math:`V_s`).
            Default is 0.001.
        sediment_porosity : float, optional
            Sediment porosity (:math:`\phi`). Default is 0.3.
        fraction_fines : float, optional
            Fraction of fine sediment that is permanently detached
            (:math:`F_f`). Default is 0.5.
        roughness__length_scale : float, optional
            Bedrock roughness length scale. Default is 0.5.
        solver : str, optional
            Solver option to pass to the Landlab
            `Space <https://landlab.readthedocs.io/en/master/reference/components/space.html>`_
            component. Default is "basic".
        soil_production__maximum_rate : float, optional
            Maximum rate of soil production (:math:`P_{0}`). Default is 0.001.
        soil_production__decay_depth : float, optional
            Decay depth for soil production (:math:`H_{s}`). Default is 0.5.
        soil_transport_decay_depth : float, optional
            Decay depth for soil transport (:math:`H_{0}`). Default is 0.5.
        **kwargs :
            Keyword arguments to pass to :py:class:`ErosionModel`. Importantly
            these arguments specify the precipitator and the runoff generator
            that control the generation of surface water discharge (:math:`Q`).

        Returns
        -------
        BasicHySa : model object

        Examples
        --------
        This is a minimal example to demonstrate how to construct an instance
        of model **BasicHySa**. For more detailed examples, including
        steady-state test examples, see the terrainbento tutorials.

        To begin, import the model class.

        >>> from landlab import RasterModelGrid
        >>> from landlab.values import random
        >>> from terrainbento import Clock, BasicHySa
        >>> clock = Clock(start=0, stop=100, step=1)
        >>> grid = RasterModelGrid((5,5))
        >>> _ = random(grid, "topographic__elevation")
        >>> _ = random(grid, "soil__depth")

        Construct the model.

        >>> model = BasicHySa(clock, grid)

        Running the model with ``model.run()`` would create output, so here we
        will just run it one step.

        >>> model.run_one_step(1.)
        >>> model.model_time
        1.0

        """
        # Call ErosionModel"s init
        super().__init__(clock, grid, **kwargs)

        # verify correct fields are present.
        self._verify_fields(self._required_fields)

        soil_thickness = self.grid.at_node["soil__depth"]
        bedrock_elev = self.grid.add_zeros("node", "bedrock__elevation")
        bedrock_elev[:] = self.z - soil_thickness

        self.m = m_sp
        self.n = n_sp
        self.K_br = water_erodibility_rock
        self.K_sed = water_erodibility_sediment

        # Instantiate a SPACE component
        self.eroder = Space(
            self.grid,
            K_sed=self.K_sed,
            K_br=self.K_br,
            sp_crit_br=sp_crit_br,
            sp_crit_sed=sp_crit_sed,
            F_f=fraction_fines,
            phi=sediment_porosity,
            H_star=roughness__length_scale,
            v_s=settling_velocity,
            m_sp=self.m,
            n_sp=self.n,
            discharge_field="surface_water__discharge",
            solver=solver,
        )

        # Instantiate diffusion and weathering components
        self.weatherer = ExponentialWeatherer(
            self.grid,
            soil_production__maximum_rate=soil_production__maximum_rate,
            soil_production__decay_depth=soil_production__decay_depth,
        )

        self.diffuser = DepthDependentDiffuser(
            self.grid,
            linear_diffusivity=regolith_transport_parameter,
            soil_transport_decay_depth=soil_transport_decay_depth,
        )

        self.grid.at_node["soil__depth"][:] = (
            self.grid.at_node["topographic__elevation"]
            - self.grid.at_node["bedrock__elevation"]
        )
Esempio n. 15
0
lm = DepressionFinderAndRouter(mg)

expWeath = ExponentialWeatherer(
    mg,
    soil_production__maximum_rate=soilProductionRate,
    soil_production__decay_depth=soilProductionDecayDepth)

sf = SteepnessFinder(mg, min_drainage_area=1e6)

sp = Space(mg,
           K_sed=Kvs,
           K_br=Kvb,
           F_f=Ff,
           phi=phi,
           H_star=Hstar,
           v_s=vs,
           m_sp=m,
           n_sp=n,
           sp_crit_sed=sp_crit_sedi,
           sp_crit_br=sp_crit_bedrock,
           solver=solver)

lc = landformClassifier(mg)

DDdiff = DepthDependentDiffuser(mg,
                                linear_diffusivity=linDiff,
                                soil_transport_decay_depth=2)

lpj = DynVeg_LpjGuess(LPJGUESS_INPUT_PATH, LPJGUESS_TEMPLATE_PATH,
                      LPJGUESS_FORCINGS_PATH, LPJGUESS_INS_FILE_TPL,
                      LPJGUESS_BIN, LPJGUESS_CO2FILE, LPJGUESS_FORCINGS_STRING)