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
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)
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, )
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)
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", )
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)
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)
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']
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)
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)
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
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"] )
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)