def test_deAlm_analytical(): from landlab import RasterModelGrid grid = RasterModelGrid((32, 240), spacing = 25) grid.add_zeros('node', 'surface_water__depth') grid.add_zeros('node', 'topographic__elevation') grid.set_closed_boundaries_at_grid_edges(True, True, True, True) left_inactive_ids = left_edge_horizontal_ids(grid.shape) deAlm = OverlandFlow(grid, mannings_n=0.01, h_init=0.001) time = 0.0 while time < 500.: grid['link']['surface_water__discharge'][left_inactive_ids] = ( grid['link']['surface_water__discharge'][left_inactive_ids + 1]) dt = deAlm.calc_time_step() deAlm.overland_flow(dt) h_boundary = (((7./3.) * (0.01**2) * (0.4**3) * time) ** (3./7.)) grid.at_node['surface_water__depth'][grid.nodes[1: -1, 1]] = h_boundary time += dt x = np.arange(0, ((grid.shape[1]) * grid.dx), grid.dx) h_analytical = (-(7./3.) * (0.01**2) * (0.4**2) * (x - (0.4 * 500))) h_analytical[np.where(h_analytical > 0)] = (h_analytical[np.where( h_analytical > 0)] ** (3./7.)) h_analytical[np.where(h_analytical < 0)] = 0.0 hdeAlm = deAlm.h.reshape(grid.shape) hdeAlm = hdeAlm[1][1:] hdeAlm = np.append(hdeAlm, [0]) np.testing.assert_almost_equal(h_analytical, hdeAlm, decimal=1)
def test_thickness_ids_wrong_shape(): """Test wrong size thickness and id shapes.""" # first with thicknesses and IDs both as ndim = 1 arrays mg = RasterModelGrid((3, 3)) mg.add_zeros("node", "topographic__elevation") thicknesses = [1, 2, 4, 1, 5] ids = [1, 2, 1, 2] attrs = {"K_sp": {1: 0.001, 2: 0.0001}} with pytest.raises(ValueError): Lithology(mg, thicknesses, ids, attrs) # next as both as ndim = 2 arrays ones = np.ones(mg.number_of_nodes) mg = RasterModelGrid((3, 3)) mg.add_zeros("node", "topographic__elevation") thicknesses = [1 * ones, 2 * ones, 4 * ones, 1 * ones, 5 * ones] ids = [1 * ones, 2 * ones, 1 * ones, 2 * ones] attrs = {"K_sp": {1: 0.001, 2: 0.0001}} with pytest.raises(ValueError): Lithology(mg, thicknesses, ids, attrs) # now with thickness as ndim 2 and id as ndim 1 ones = np.ones(mg.number_of_nodes) mg = RasterModelGrid((3, 3)) thicknesses = [1 * ones, 2 * ones, 4 * ones, 1 * ones, 5 * ones] ids = [1, 2, 1, 2] attrs = {"K_sp": {1: 0.001, 2: 0.0001}} with pytest.raises(ValueError): Lithology(mg, thicknesses, ids, attrs)
def test_run_one_step(): from landlab import RasterModelGrid import numpy as np from landlab.components.overland_flow import KinwaveOverlandFlowModel grid = RasterModelGrid((10, 10), spacing=0.5) grid.add_zeros('node', 'topographic__elevation', dtype=float) grid.add_zeros('node', 'topographic__gradient') topo_arr = np.ones(100).reshape(10, 10) i=0 while i <= 9: topo_arr[:, i] = 5 + (0.002*i) i+=1 topo_arr = topo_arr.flatten() grid['node']['topographic__elevation'] = topo_arr KinWaveOF = KinwaveOverlandFlowModel(grid, precip_rate=100., precip_duration=1.0, roughness=0.02) KinWaveOF.run_one_step(60) # I'll admit this is very non-robust. Solution roughly based on plot #9 # from Heng et. al, (2009): "Modeling overland flow and soil eroion on # non uniform hillslopes: A finite volume scheme." They do not provide the # numerical solution but the plots match... max_h_mm = max(grid['node']['surface_water__depth']) * 1000. np.testing.assert_almost_equal(max_h_mm, 1.66666666667)
def test_storms(): input_file_string = os.path.join(_THIS_DIR, 'drive_sp_params_storms.txt') inputs = ModelParameterDictionary(input_file_string) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') uplift = inputs.read_float('uplift_rate') mg = RasterModelGrid(nrows, ncols, dx) mg.add_zeros('topographic__elevation', at='node') z = mg.zeros(at='node') mg['node']['topographic__elevation'] = z + np.random.rand(len(z)) / 1000. mg.add_zeros('water__unit_flux_in', at='node') precip = PrecipitationDistribution(input_file=input_file_string) fr = FlowRouter(mg) sp = StreamPowerEroder(mg, **inputs) for (interval_duration, rainfall_rate) in \ precip.yield_storm_interstorm_duration_intensity(): if rainfall_rate != 0.: mg.at_node['water__unit_flux_in'].fill(rainfall_rate) mg = fr.route_flow() sp.run_one_step(dt) mg.at_node['topographic__elevation'][ mg.core_nodes] += uplift * interval_duration
def test_mask_is_stable(): mg = RasterModelGrid((10, 10)) mg.add_zeros("node", "topographic__elevation") np.random.seed(3542) noise = np.random.rand(mg.size("node")) mg.at_node["topographic__elevation"] += noise fr = FlowAccumulator(mg, flow_director="D8") fsc = FastscapeEroder(mg, K_sp=0.01, m_sp=0.5, n_sp=1) for x in range(2): fr.run_one_step() fsc.run_one_step(dt=10.0) mg.at_node["topographic__elevation"][mg.core_nodes] += 0.01 mask = np.zeros(len(mg.at_node["topographic__elevation"]), dtype=np.uint8) mask[np.where(mg.at_node["drainage_area"] > 0)] = 1 mask0 = mask.copy() dd = DrainageDensity(mg, channel__mask=mask) mask1 = mask.copy() dd.calc_drainage_density() mask2 = mask.copy() assert_array_equal(mask0, mask1) assert_array_equal(mask0[mg.core_nodes], mask2[mg.core_nodes])
def test_sp_discharges_new(): input_str = os.path.join(_THIS_DIR, 'test_sp_params_discharge_new.txt') inputs = ModelParameterDictionary(input_str, auto_type=True) nrows = 5 ncols = 5 dx = inputs.read_float('dx') dt = inputs.read_float('dt') mg = RasterModelGrid(nrows, ncols, dx) mg.add_zeros('topographic__elevation', at='node') z = np.array([5., 5., 0., 5., 5., 5., 2., 1., 2., 5., 5., 3., 2., 3., 5., 5., 4., 4., 4., 5., 5., 5., 5., 5., 5.]) mg['node']['topographic__elevation'] = z fr = FlowRouter(mg) sp = StreamPowerEroder(mg, **inputs) # perform the loop (once!) for i in range(1): fr.route_flow() sp.run_one_step(dt) z_tg = np.array([5. , 5. , 0. , 5. , 5. , 5. , 1.47759225, 0.43050087, 1.47759225, 5. , 5. , 2.32883687, 1.21525044, 2.32883687, 5. , 5. , 3.27261262, 3.07175015, 3.27261262, 5. , 5. , 5. , 5. , 5. , 5. ]) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_tg)
def test_rock_block_xarray(): """Test that the xarray method works as expected.""" sample_depths = np.arange(0, 10, 1) mg = RasterModelGrid((3, 3)) mg.add_zeros("node", "topographic__elevation") layer_ids = np.tile([0, 1, 2, 3], 5) layer_elevations = 3.0 * np.arange(-10, 10) layer_elevations[-1] = layer_elevations[-2] + 100 attrs = {"K_sp": {0: 0.0003, 1: 0.0001, 2: 0.0002, 3: 0.0004}} lith = LithoLayers( mg, layer_elevations, layer_ids, function=lambda x, y: x + y, attrs=attrs ) ds = lith.rock_cube_to_xarray(sample_depths) expected_array = np.array( [ [[3.0, 2.0, 2.0], [2.0, 2.0, 2.0], [2.0, 2.0, 1.0]], [[3.0, 3.0, 2.0], [3.0, 2.0, 2.0], [2.0, 2.0, 2.0]], [[3.0, 3.0, 3.0], [3.0, 3.0, 2.0], [3.0, 2.0, 2.0]], [[0.0, 3.0, 3.0], [3.0, 3.0, 3.0], [3.0, 3.0, 2.0]], [[0.0, 0.0, 3.0], [0.0, 3.0, 3.0], [3.0, 3.0, 3.0]], [[0.0, 0.0, 0.0], [0.0, 0.0, 3.0], [0.0, 3.0, 3.0]], [[1.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 3.0]], [[1.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]], [[1.0, 1.0, 1.0], [1.0, 1.0, 0.0], [1.0, 0.0, 0.0]], [[2.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0, 0.0]], ] ) assert_array_equal(ds.rock_type__id.values, expected_array)
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), 10.0) mg.add_zeros('node', 'topographic__elevation') 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.) # Create a D8 flow handler fa = FlowAccumulator(mg, flow_director='D8') #try to instantiate ErodionDeposition using a wrong solver name with pytest.raises(ValueError): ErosionDeposition(mg, K=0.01, phi=0.0, v_s=0.001, m_sp=0.5, n_sp=1.0, sp_crit=0, F_f=0.0, solver='something_else')
def test_Ff_bad_vals(): """ Test that instantiating ErosionDeposition with a F_f value > 1 throws a ValueError. """ #set up a 5x5 grid with one open outlet node and low initial elevations. nr = 5 nc = 5 mg = RasterModelGrid((nr, nc), 10.0) mg.add_zeros('node', 'topographic__elevation') 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.) # Create a D8 flow handler fa = FlowAccumulator(mg, flow_director='D8', depression_finder='DepressionFinderAndRouter') # Instantiate the ErosionDeposition component... with pytest.raises(ValueError): ErosionDeposition(mg, K=0.01, F_f=2.0, phi=0.5, v_s=0.001, m_sp=0.5, n_sp=1.0, sp_crit=0.0, solver='basic')
def test_tl_fluvial(): input_file = os.path.join(_THIS_DIR, 'stream_power_params_ideal.txt') inputs = ModelParameterDictionary(input_file) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') leftmost_elev = inputs.read_float('leftmost_elevation') initial_slope = inputs.read_float('initial_slope') uplift_rate = inputs.read_float('uplift_rate') runtime = inputs.read_float('total_time') dt = inputs.read_float('dt') nt = int(runtime // dt) uplift_per_step = uplift_rate * dt mg = RasterModelGrid(nrows, ncols, dx) mg.add_zeros('node', 'topographic__elevation') z = np.loadtxt(os.path.join(_THIS_DIR, 'tl_init.txt')) mg['node']['topographic__elevation'] = z mg.set_closed_boundaries_at_grid_edges(True, False, True, False) mg.set_fixed_value_boundaries_at_grid_edges( False, True, False, True, value_of='topographic__elevation') fr = FlowRouter(mg) tl = TransportLimitedEroder(mg, input_file) for i in range(nt): mg.at_node['topographic__elevation'][mg.core_nodes] += uplift_per_step mg = fr.route_flow() mg, _ = tl.erode(mg, dt, stability_condition='loose') z_tg = np.loadtxt(os.path.join(_THIS_DIR, 'tlz_tg.txt')) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_tg)
def test_deAlm_analytical_imposed_dt_short(): grid = RasterModelGrid((32, 240), xy_spacing=25) grid.add_zeros("node", "surface_water__depth") grid.add_zeros("node", "topographic__elevation") grid.set_closed_boundaries_at_grid_edges(True, True, True, True) left_inactive_ids = left_edge_horizontal_ids(grid.shape) deAlm = OverlandFlow(grid, mannings_n=0.01, h_init=0.001) time = 0.0 while time < 500.0: grid.at_link["surface_water__discharge"][left_inactive_ids] = grid.at_link[ "surface_water__discharge" ][left_inactive_ids + 1] dt = 10.0 deAlm.overland_flow(dt) h_boundary = ((7.0 / 3.0) * (0.01 ** 2) * (0.4 ** 3) * time) ** (3.0 / 7.0) grid.at_node["surface_water__depth"][grid.nodes[1:-1, 1]] = h_boundary time += dt x = np.arange(0, ((grid.shape[1]) * grid.dx), grid.dx) h_analytical = -(7.0 / 3.0) * (0.01 ** 2) * (0.4 ** 2) * (x - (0.4 * 500)) h_analytical[np.where(h_analytical > 0)] = h_analytical[ np.where(h_analytical > 0) ] ** (3.0 / 7.0) h_analytical[np.where(h_analytical < 0)] = 0.0 hdeAlm = deAlm.h.reshape(grid.shape) hdeAlm = hdeAlm[1][1:] hdeAlm = np.append(hdeAlm, [0]) np.testing.assert_almost_equal(h_analytical, hdeAlm, decimal=1)
def test_sed_dep(): input_file = os.path.join(_THIS_DIR, "sed_dep_params.txt") inputs = ModelParameterDictionary(input_file, auto_type=True) nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") uplift_rate = inputs.read_float("uplift_rate") runtime = inputs.read_float("total_time") dt = inputs.read_float("dt") nt = int(runtime // dt) uplift_per_step = uplift_rate * dt mg = RasterModelGrid((nrows, ncols), xy_spacing=(dx, dx)) mg.add_zeros("topographic__elevation", at="node") z = np.loadtxt(os.path.join(_THIS_DIR, "seddepinit.txt")) mg["node"]["topographic__elevation"] = z mg.set_closed_boundaries_at_grid_edges(True, False, True, False) fr = FlowAccumulator(mg, flow_director="D8") sde = SedDepEroder(mg, **inputs) for i in range(nt): mg.at_node["topographic__elevation"][mg.core_nodes] += uplift_per_step mg = fr.run_one_step() mg, _ = sde.erode(dt) z_tg = np.loadtxt(os.path.join(_THIS_DIR, "seddepz_tg.txt")) assert_array_almost_equal( mg.at_node["topographic__elevation"][mg.core_nodes], z_tg[mg.core_nodes] )
def test_closed_up_grid(): mg = RasterModelGrid((5, 5)) for edge in ("left", "right", "top", "bottom"): mg.status_at_node[mg.nodes_at_edge(edge)] = CLOSED_BOUNDARY mg.add_zeros("node", "topographic__elevation", dtype=float) with pytest.raises(ValueError): LakeMapperBarnes(mg)
def test_dx_equals_zero(): """Test a vertical fault trace.""" grid = RasterModelGrid((6, 6), xy_spacing=10) grid.add_zeros("node", "topographic__elevation") param_dict = { "faulted_surface": "topographic__elevation", "fault_dip_angle": 90.0, "fault_throw_rate_through_time": {"time": [0, 9, 10], "rate": [0, 0, 0.05]}, "fault_trace": {"y1": 0, "x1": 30, "y2": 30, "x2": 30}, "include_boundaries": True, } nf = NormalFault(grid, **param_dict) out = np.array( [ [True, True, True, False, False, False], [True, True, True, False, False, False], [True, True, True, False, False, False], [True, True, True, False, False, False], [True, True, True, False, False, False], [True, True, True, False, False, False], ], dtype=bool, ) assert_array_equal(nf.faulted_nodes.reshape(grid.shape), out)
def test_Bates_analytical(): from landlab import RasterModelGrid grid = RasterModelGrid((32, 240), xy_spacing=25) grid.add_zeros("node", "surface_water__depth") grid.add_zeros("node", "topographic__elevation") grid.set_closed_boundaries_at_grid_edges(True, True, True, True) bates = OverlandFlowBates(grid, mannings_n=0.01, h_init=0.001) time = 0.0 bates.dt = 1.0 while time < 500: bates.overland_flow(grid) h_boundary = ((7. / 3.) * (0.01 ** 2) * (0.4 ** 3) * time) ** (3. / 7.) grid.at_node["surface_water__depth"][grid.nodes[1:-1, 1]] = h_boundary time += bates.dt x = np.arange(0, ((grid.shape[1]) * grid.dx), grid.dx) h_analytical = -(7. / 3.) * (0.01 ** 2) * (0.4 ** 2) * (x - (0.4 * 500)) h_analytical[np.where(h_analytical > 0)] = h_analytical[ np.where(h_analytical > 0) ] ** (3. / 7.) h_analytical[np.where(h_analytical < 0)] = 0.0 hBates = bates.h.reshape(grid.shape) hBates = hBates[1][1:] hBates = np.append(hBates, [0]) np.testing.assert_almost_equal(h_analytical, hBates, decimal=1)
def setup_grid(): from landlab import RasterModelGrid grid = RasterModelGrid((32, 240), spacing = 25) grid.add_zeros('node', 'surface_water__depth') grid.add_zeros('node', 'topographic__elevation') bates = OverlandFlowBates(grid, mannings_n = 0.01, h_init=0.001) globals().update({ 'bates': bates})
def test_route_to_many(): mg = RasterModelGrid((5, 5)) mg.add_zeros("node", "topographic__elevation", dtype=float) fd = FlowDirectorDINF(mg, "topographic__elevation") fd.run_one_step() assert mg.at_node["flow__receiver_node"].shape == (mg.number_of_nodes, 2) with pytest.raises(NotImplementedError): LakeMapperBarnes(mg, method="D8", redirect_flow_steepest_descent=True)
def test_dip_geq_90(): """Test dip angles of >90 degrees.""" grid = RasterModelGrid((6, 6), xy_spacing=10) grid.add_zeros("node", "topographic__elevation") with pytest.raises(ValueError): NormalFault(grid, fault_dip_angle=90.001)
def setup_grid(): from landlab import RasterModelGrid grid = RasterModelGrid((10, 10), spacing=0.5) grid.add_zeros('node', 'topographic__elevation', dtype=float) grid.add_zeros('node', 'topographic__gradient') globals().update({ 'KinWaveOF': KinwaveOverlandFlowModel(grid)})
def test_atts_lack_ids(): """Test Lithology missing ID.""" mg = RasterModelGrid((3, 3)) mg.add_zeros("node", "topographic__elevation") thicknesses = [1, 2, 4, 1, 5] ids = [1, 2, 1, 2, 1] attrs = {"K_sp": {2: 0.0001}, "age": {1: 100, 2: 300}} with pytest.raises(ValueError): Lithology(mg, thicknesses, ids, attrs)
def test_add_ones_zeros_empty_to_at_grid(): """Test different add methods for keyword at='grid'""" grid = RasterModelGrid((4, 5)) with pytest.raises(ValueError): grid.add_zeros('value', at='grid') with pytest.raises(ValueError): grid.add_empty('value', at='grid') with pytest.raises(ValueError): grid.add_ones('value', at='grid')
def test_raise_kwargs_error(): mg = RasterModelGrid((5, 5)) soilTh = mg.add_zeros('node', 'soil__depth') z = mg.add_zeros('node', 'topographic__elevation') BRz = mg.add_zeros('node', 'bedrock__elevation') z += mg.node_x.copy()**2 BRz = z.copy() - 1.0 soilTh[:] = z - BRz assert_raises(TypeError, DepthDependentTaylorDiffuser, mg, diffusivity=1)
def test_bad_layer_method(): """Test passing a bad name for the layer method.""" mg = RasterModelGrid((3, 3)) mg.add_zeros("node", "topographic__elevation") thicknesses = [1, 2, 4, 1] ids = [1, 2, 1, 2] attrs = {"K_sp": {1: 0.001, 2: 0.0001}} with pytest.raises(ValueError): Lithology(mg, thicknesses, ids, attrs, layer_type="spam")
def test_thickness_nodes_wrong_shape(): """Test wrong size thickness and id shapes.""" mg = RasterModelGrid((3, 3)) mg.add_zeros("node", "topographic__elevation") ones = np.ones(mg.number_of_nodes + 1) thicknesses = [1 * ones, 2 * ones, 4 * ones, 1 * ones, 5 * ones] ids = [1 * ones, 2 * ones, 1 * ones, 2 * ones, 1 * ones] attrs = {"K_sp": {1: 0.001, 2: 0.0001}} with pytest.raises(ValueError): Lithology(mg, thicknesses, ids, attrs)
def test_updating_rock_type_that_doesnt_exist(): """Test adding an new rock type with an extra attribute.""" mg = RasterModelGrid((3, 3)) mg.add_zeros("node", "topographic__elevation") thicknesses = [1, 2, 4, 1, 5] ids = [1, 2, 1, 2, 1] attrs = {"K_sp": {1: 0.001, 2: 0.0001}} lith = Lithology(mg, thicknesses, ids, attrs) with pytest.raises(ValueError): lith.update_rock_properties("K_sp", 3, 4)
def test_deposit_with_no_rock_id(): """Test that adding a deposit to Lithology with no id raises an error.""" mg = RasterModelGrid((3, 3)) mg.add_zeros("node", "topographic__elevation") thicknesses = [1, 2, 4, 1, 5] ids = [1, 2, 1, 2, 1] attrs = {"K_sp": {1: 0.001, 2: 0.0001}} lith = Lithology(mg, thicknesses, ids, attrs) with pytest.raises(ValueError): lith.add_layer(100)
def test_erode_to_zero_thickness(): """Test that eroding Lithology to zero thickness raises an error.""" mg = RasterModelGrid((3, 3)) mg.add_zeros("node", "topographic__elevation") thicknesses = [1, 2, 4, 1, 5] ids = [1, 2, 1, 2, 1] attrs = {"K_sp": {1: 0.001, 2: 0.0001}} lith = Lithology(mg, thicknesses, ids, attrs) with pytest.raises(ValueError): lith.add_layer(-100)
def test_raise_kwargs_error(): mg = RasterModelGrid((5, 5)) soilTh = mg.add_zeros("node", "soil__depth") z = mg.add_zeros("node", "topographic__elevation") BRz = mg.add_zeros("node", "bedrock__elevation") z += mg.node_x.copy() ** 2 BRz = z.copy() - 1.0 soilTh[:] = z - BRz with pytest.raises(TypeError): DepthDependentTaylorDiffuser(mg, diffusivity=1)
def test_updating_attribute_that_doesnt_exist(): """Test updating an attribute that doesn't exist.""" mg = RasterModelGrid(3, 3) mg.add_zeros("node", "topographic__elevation") thicknesses = [1, 2, 4, 1, 5] ids = [1, 2, 1, 2, 1] attrs = {"K_sp": {1: 0.001, 2: 0.0001}} lith = Lithology(mg, thicknesses, ids, attrs) with pytest.raises(ValueError): lith.update_rock_properties("spam", 1, 4)
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("node", "topographic__elevation") br = mg.add_zeros("node", "bedrock__elevation") soil = mg.add_zeros("node", "soil__depth") soil += 1. # 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. ) 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 main(): # INITIALIZE # User-defined parameters nr = 5 # number of rows in grid nc = 5 # number of columns in grid plot_interval = 10.0 # time interval for plotting, sec run_duration = 10.0 # duration of run, sec report_interval = 10.0 # report interval, in real-time seconds # Remember the clock time, and calculate when we next want to report # progress. current_real_time = time.time() next_report = current_real_time + report_interval # Create grid mg = RasterModelGrid(nr, nc, 1.0) # Make the boundaries be walls mg.set_closed_boundaries_at_grid_edges(True, True, True, True) # Set up the states and pair transitions. ns_dict = {0: "black", 1: "white"} xn_list = setup_transition_list() # Create the node-state array and attach it to the grid node_state_grid = mg.add_zeros("node", "node_state_map", dtype=int) # For visual display purposes, set all boundary nodes to fluid node_state_grid[mg.closed_boundary_nodes] = 0 # Create the CA model ca = RasterCTS(mg, ns_dict, xn_list, node_state_grid) # Create a CAPlotter object for handling screen display ca_plotter = CAPlotter(ca) # Plot the initial grid ca_plotter.update_plot() # RUN current_time = 0.0 while current_time < run_duration: # Once in a while, print out simulation and real time to let the user # know that the sim is running ok current_real_time = time.time() if current_real_time >= next_report: print( "Current sim time", current_time, "(", 100 * current_time / run_duration, "%)", ) next_report = current_real_time + report_interval # Run the model forward in time until the next output step ca.run( current_time + plot_interval, ca.node_state, plot_each_transition=True, plotter=ca_plotter, ) current_time += plot_interval # Plot the current grid ca_plotter.update_plot() # FINALIZE # Plot ca_plotter.finalize() print("ok, here are the keys") print(ca.__dict__.keys())
def test_raster_cts(): """ Tests instantiation of a RasterCTS and implementation of one transition, with a callback function. """ # Set up a small grid with no events scheduled mg = RasterModelGrid(4, 4) mg.set_closed_boundaries_at_grid_edges(True, True, True, True) node_state_grid = mg.add_ones("node", "node_state_map", dtype=int) node_state_grid[6] = 0 ns_dict = {0: "black", 1: "white"} xn_list = [] xn_list.append(Transition((1, 0, 0), (0, 1, 0), 0.1, "", True, callback_function)) pd = mg.add_zeros("node", "property_data", dtype=int) pd[5] = 50 ca = RasterCTS( mg, ns_dict, xn_list, node_state_grid, prop_data=pd, prop_reset_value=0 ) # Test the data structures assert ca.num_link_states == 4, "wrong number of link states" assert ca.prop_data[5] == 50, "error in property data" assert ca.num_node_states == 2, "error in num_node_states" assert ca.link_orientation[-1] == 0, "error in link orientation array" assert ca.link_state_dict[(1, 0, 0)] == 2, "error in link state dict" assert ca.n_trn[2] == 1, "error in n_trn" assert ca.node_pair[1] == (0, 1, 0), "error in cell_pair list" assert len(ca.priority_queue._queue) == 1, "event queue has wrong size" assert ca.next_trn_id.size == 24, "wrong size next_trn_id" assert ca.trn_id.shape == (4, 1), "wrong size for trn_to" assert ca.trn_id[2][0] == 0, "wrong value in trn_to" assert ca.trn_to[0] == 1, "wrong trn_to state" assert ca.trn_rate[0] == 0.1, "wrong trn rate" assert ca.trn_propswap[0] == 1, "wrong trn propswap" assert ca.trn_prop_update_fn == callback_function, "wrong prop upd" # Manipulate the data in the event queue for testing: # pop the scheduled event off the queue (event_time, index, event_link) = ca.priority_queue.pop() assert ( ca.priority_queue._queue == [] ), "event queue should now be empty but is not" # engineer an event ca.priority_queue.push(8, 1.0) ca.next_update[8] = 1.0 ca.next_trn_id[8] = 0 # run the CA ca.run(2.0) # some more tests. # Is current time advancing correctly? (should only go to 1.0, not 2.0) # Did the two nodes (5 and 6) correctly exchange states? # Did the property ID and data arrays get updated? Note that the "propswap" # should switch propids between nodes 5 and 6, and the callback function # should increase the value of prop_data in the "swap" node from 50 to 150. assert ca.current_time == 1.0, "current time incorrect" assert ca.node_state[5] == 0, "error in node state 5" assert ca.node_state[6] == 1, "error in node state 6"
def test_raise_stability_error(): mg = RasterModelGrid((5, 5)) z = mg.add_zeros('node', 'topographic__elevation') z += mg.node_x.copy()**2 Cdiff = TaylorNonLinearDiffuser(mg) assert_raises(RuntimeError, Cdiff.soilflux, 10, if_unstable='raise')
def test_infinite_taylor_error(): mg = RasterModelGrid((5, 5)) z = mg.add_zeros('node', 'topographic__elevation') z += mg.node_x.copy()**4 Cdiff = TaylorNonLinearDiffuser(mg, nterms=400) assert_raises(RuntimeError, Cdiff.soilflux, 10)
def extend_perturbed_runs(total_iters_to_reach=0): """Load all perturbed runs in current folder, and extend them. Function should be called from within an experiment folder (extend all perturbations for all starting uplift rates), an 'uplift_rate_XXXX' folder (extend all perturbations for this rate) or an 'accel_XXX' folder (extend this accel only). Does NOT create a new expt or run ID, just extends the old ones. Adds a text file annotating what has happened. """ # look for the params to use. Also tells us where we are in the hierarchy level = 0 # 0: top, 1: uplift, 2: accel: cwd = os.getcwd() while True: try: paramdict = np.load('expt_ID_paramdict.npy').item() except IOError: os.chdir('..') level += 1 else: break # now back to where we started in the dir str: os.chdir(cwd) if level == 2: # in accel_ folder # get the accel that this is: accel_factors = [ get_float_of_folder_name(), ] # get the U of the host folder: uplift_rates = [ get_float_of_folder_name(directory=(cwd + '/..')), ] wd_stub = os.path.abspath(os.getcwd() + '/../..') elif level == 1: # in uplift_ folder accel_fnames = [ filename for filename in os.listdir('.') if filename.startswith('accel_') ] accel_factors = [ get_float_of_folder_name(directory=(cwd + '/' + filename)) for filename in accel_fnames ] uplift_rates = [ get_float_of_folder_name(), ] wd_stub = os.path.abspath(os.getcwd() + '/..') elif level == 0: # in top folder uplift_fnames = [ filename for filename in os.listdir('.') if filename.startswith('uplift_rate_') ] uplift_rates = [ get_float_of_folder_name(directory=(cwd + '/' + filename)) for filename in uplift_fnames ] accel_factors = paramdict['accel_factors'] wd_stub = os.path.abspath(os.getcwd()) for uplift_rate in uplift_rates: for accel_factor in accel_factors: wd = (wd_stub + '/uplift_rate_' + str(uplift_rate) + '/accel_' + str(accel_factor)) # get the saved filenames that already exist in this folder: runnames = [ filename for filename in os.listdir(wd) if filename.startswith('topographic__elevation') ] seddepthnames = [ filename for filename in os.listdir(wd) if filename.startswith('channel_sediment__depth') ] # as elsewhere, the final entry is the last run, so -- # establish the loop number of that run: run_ID = runnames[-1][-14:-4] # is a str _format = 0 while True: char = runnames[-1][-16 - _format] try: num = int(char) except ValueError: # was a str break else: _format += 1 finaliter = int(runnames[-1][(-15 - _format):-15]) finalsediter = int(seddepthnames[-1][(-15 - _format):-15]) assert finaliter == finalsediter # ...just in case # test we need to actually do more runs: if total_iters_to_reach < finaliter + paramdict['out_interval']: continue # check we aren't going to have a "zero problem"; correct if we do max_zeros = len(str(total_iters_to_reach)) if max_zeros + 1 > _format: # less won't be possible from continue extra_zeros = max_zeros + 1 - _format for allfile in os.listdir(wd): if allfile[-14:-4] == run_ID: os.rename( wd + '/' + allfile, (wd + '/' + allfile[:(-15 - _format)] + '0' * extra_zeros + allfile[(-15 - _format):])) runnames = [ filename for filename in os.listdir(wd) if filename.startswith('topographic__elevation') ] seddepthnames = [ filename for filename in os.listdir(wd) if filename.startswith('channel_sediment__depth') ] if max_zeros + 1 < _format: max_zeros = _format - 1 # in case of any bonus 0s from old run # build the structures: mg = RasterModelGrid(paramdict['shape'], paramdict['dx']) for edge in (mg.nodes_at_left_edge, mg.nodes_at_top_edge, mg.nodes_at_right_edge): mg.status_at_node[edge] = CLOSED_BOUNDARY z = mg.add_zeros('node', 'topographic__elevation') seddepth = mg.add_zeros('node', 'channel_sediment__depth') fr = FlowRouter(mg) eroder = SedDepEroder(mg, **paramdict) ld = LinearDiffuser(mg, **paramdict) # load the last available elev data: z[:] = np.loadtxt(wd + '/' + runnames[-1]) seddepth[:] = np.loadtxt(wd + '/' + seddepthnames[-1]) # save a note try: appendfile = open(wd + '/appended_run_readme.txt', 'a') except IOError: appendfile = open(wd + '/appended_run_readme.txt', 'w') appendfile.write('This run was appended at timestamp ' + str(int(time.time())) + '.\n') appendfile.write('New loops were added from iteration ' + str(finaliter) + ' and terminated at iteration ' + str(total_iters_to_reach) + '.\n\n') appendfile.close() # get runnin' print('Extending uplift ' + str(uplift_rate) + ' accel ' + str(accel_factor) + ' from iter number ' + str(finaliter)) dt = paramdict['dt'] for i in xrange(finaliter + 1, total_iters_to_reach): fr.route_flow() eroder.run_one_step(dt) ld.run_one_step(dt) z[mg.core_nodes] += accel_factor * uplift_rate * dt print(i) if i % out_interval == 0: zeros_to_add = max_zeros - len(str(i)) + 1 # note an OoM buffer! Just to be safe if zeros_to_add < 0: # ...just in case, though should never happen print('Problem allocating zeros on savefiles') ilabel = '0' * zeros_to_add + str(i) identifier = ilabel + '_' + str(run_ID) for field in out_fields: np.savetxt( wd + '/' + field + '_' + identifier + '.txt', mg.at_node[field])
def test_bad_init_method2(): rmg = RasterModelGrid((5, 5), xy_spacing=2.) rmg.add_zeros("node", "topographic__elevation", dtype=float) with pytest.raises(ValueError): LakeMapperBarnes(rmg, method="d8")
m_sp = 0.5 n_sp = 1. #5)model run total_t = 150 #number of years (000) dt = 0.4 #number of years (000) nt = int(total_t // dt) #number of time steps #6) random seed randno = 23456 #GRID SET-UP #create model x-y grid mg = RasterModelGrid((ncols, nrows), nodeint) #initialize with zero elevation values and random noise z = mg.add_zeros('node', 'topographic__elevation') np.random.seed(randno) initial_roughness = np.random.rand(z.size) / 100000. z += initial_roughness #set southcenter pixel to zero elevation #outlet=26 # #z[outlet]=0 #set boundary conditions of model grid (open only (fixed value) on south (bottom) edge) 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 ##set southwest pixel to FIXED VALUE #mg.status_at_node[outlet]=FIXED_VALUE_BOUNDARY #mg.status_at_node[outlet]=FIXED_VALUE_BOUNDARY
three_over_seven = 3. / 7. ten_thirds = 10. / 3. # Elapsed time starts at 1 second. This prevents errors when setting our # boundary conditions elapsed_time = 1.0 # Now we create our grid using the parameters set above. rmg = RasterModelGrid((numrows, numcols), xy_spacing=dx) # Set our boundaries to closed to prevent water from flowing out of the plane rmg.set_closed_boundaries_at_grid_edges(True, True, True, True) # Create fields in the grid for topographic elevation, water depth, discharge. rmg.add_zeros("topographic__elevation", at="node") # topographic elevation (m) rmg.add_zeros("surface_water__depth", at="node") # water depth (m) # Now we'll identify our leftmost, but interior, column and the IDs of those # nodes. One column in to prevent issues with BC. inside_left_edge = rmg.nodes[1:-1, 1] # Initializing our class... of = OverlandFlowBates(rmg, mannings_n=n, h_init=h_init) # Let's see how long this run takes... starttime = time() while elapsed_time < run_time:
def main(): # INITIALIZE # User-defined parameters nr = 200 # number of rows in grid nc = 200 # number of columns in grid plot_interval = 0.05 # time interval for plotting (unscaled) run_duration = 5.0 # duration of run (unscaled) report_interval = 10.0 # report interval, in real-time seconds frac_spacing = 10 # average fracture spacing, nodes outfilename = "wx" # name for netCDF files # Remember the clock time, and calculate when we next want to report # progress. current_real_time = time.time() next_report = current_real_time + report_interval # Counter for output files time_slice = 0 # Create grid mg = RasterModelGrid(nr, nc, 1.0) # Make the boundaries be walls mg.set_closed_boundaries_at_grid_edges(True, True, True, True) # Set up the states and pair transitions. ns_dict = {0: "rock", 1: "saprolite"} xn_list = setup_transition_list() # Create the node-state array and attach it to the grid. # (Note use of numpy's uint8 data type. This saves memory AND allows us # to write output to a netCDF3 file; netCDF3 does not handle the default # 64-bit integer type) node_state_grid = mg.add_zeros("node", "node_state_map", dtype=np.uint8) node_state_grid[:] = make_frac_grid(frac_spacing, model_grid=mg) # Create the CA model ca = RasterCTS(mg, ns_dict, xn_list, node_state_grid) # Set up the color map rock_color = (0.8, 0.8, 0.8) sap_color = (0.4, 0.2, 0) clist = [rock_color, sap_color] my_cmap = matplotlib.colors.ListedColormap(clist) # Create a CAPlotter object for handling screen display ca_plotter = CAPlotter(ca, cmap=my_cmap) # Plot the initial grid ca_plotter.update_plot() # Output the initial grid to file write_netcdf( (outfilename + str(time_slice) + ".nc"), mg, # format='NETCDF3_64BIT', names="node_state_map", ) # RUN current_time = 0.0 while current_time < run_duration: # Once in a while, print out simulation and real time to let the user # know that the sim is running ok current_real_time = time.time() if current_real_time >= next_report: print( "Current sim time", current_time, "(", 100 * current_time / run_duration, "%)", ) next_report = current_real_time + report_interval # Run the model forward in time until the next output step ca.run(current_time + plot_interval, ca.node_state, plot_each_transition=False) current_time += plot_interval # Plot the current grid ca_plotter.update_plot() # Output the current grid to a netCDF file time_slice += 1 write_netcdf( (outfilename + str(time_slice) + ".nc"), mg, # format='NETCDF3_64BIT', names="node_state_map", ) # FINALIZE # Plot ca_plotter.finalize()
from landlab import RasterModelGrid, imshow_grid_at_node from landlab.components import FlowAccumulator from landlab.components import SpatialPrecipitationDistribution from landlab.components import SoilInfiltrationGreenAmpt from matplotlib.pyplot import show, figure mg = RasterModelGrid((100, 100), 100.) z = mg.add_zeros('node', 'topographic__elevation', dtype=float) z[:] = mg.node_x / 100000. STORM = SpatialPrecipitationDistribution(mg) WUFI = mg.add_field('node', 'water__unit_flux_in', mg.at_node['rainfall__flux']) fa = FlowAccumulator(mg) count = 0 for storm in STORM.yield_storms(): fa.run_one_step() print storm count += 1 if count % 10 == 0: figure(count) imshow_grid_at_node(mg, 'rainfall__flux') figure(count + 1) imshow_grid_at_node(mg, 'surface_water__discharge') show()
from landlab.grid.mappers import map_link_end_node_max_value_to_link inputs = ModelParameterDictionary('./pot_fr_params.txt') nrows = 50 #inputs.read_int('nrows') ncols = 50 #inputs.read_int('ncols') dx = inputs.read_float('dx') init_elev = inputs.read_float('init_elev') mg = RasterModelGrid(nrows, ncols, dx) # attempt to implement diffusion with flow routing... #modify the fields in the grid z = mg.zeros(at='node') + init_elev mg.at_node['topographic__elevation'] = z + np.random.rand(len(z)) / 1000. mg.add_zeros('water__unit_flux_in', at='node') #Set boundary conditions mg.set_closed_boundaries_at_grid_edges(False, True, True, True) mg.set_fixed_value_boundaries_at_grid_edges(False, False, False, True) inlet_node = np.array((mg.number_of_node_columns + 1)) mg.at_node['water__unit_flux_in'].fill(0.) mg.at_node['water__unit_flux_in'][inlet_node] = 1. pfr = PotentialityFlowRouter(mg, 'pot_fr_params.txt') interior_nodes = mg.core_nodes # do the loop for i in range(2000): if i % 50 == 0: print('loop ' + str(i))
def main(): # INITIALIZE # User-defined parameters nr = 80 nc = 80 plot_interval = 2 run_duration = 200 report_interval = 5.0 # report interval, in real-time seconds # Remember the clock time, and calculate when we next want to report # progress. current_real_time = time.time() next_report = current_real_time + report_interval # Create grid mg = RasterModelGrid(nr, nc, 1.0) # Make the boundaries be walls mg.set_closed_boundaries_at_grid_edges(True, True, True, True) # Set up the states and pair transitions. ns_dict = {0: 'fluid', 1: 'particle'} xn_list = setup_transition_list() # Create the node-state array and attach it to the grid node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=int) # Initialize the node-state array middle_rows = where( bitwise_and(mg.node_y > 0.45 * nr, mg.node_y < 0.55 * nr))[0] node_state_grid[middle_rows] = 1 # Create the CA model ca = OrientedRasterCTS(mg, ns_dict, xn_list, node_state_grid) # Debug output if needed if _DEBUG: n = ca.grid.number_of_nodes for r in range(ca.grid.number_of_node_rows): for c in range(ca.grid.number_of_node_columns): n -= 1 print('{0:.0f}'.format(ca.node_state[n]), end=' ') print() # Create a CAPlotter object for handling screen display ca_plotter = CAPlotter(ca) # Plot the initial grid ca_plotter.update_plot() # RUN current_time = 0.0 while current_time < run_duration: # Once in a while, print out simulation and real time to let the user # know that the sim is running ok current_real_time = time.time() if current_real_time >= next_report: print('Current sim time', current_time, '(', 100 * current_time / run_duration, '%)') next_report = current_real_time + report_interval # Run the model forward in time until the next output step ca.run(current_time + plot_interval, ca.node_state, plot_each_transition=False) #, plotter=ca_plotter) current_time += plot_interval # Plot the current grid ca_plotter.update_plot() # for debugging if _DEBUG: n = ca.grid.number_of_nodes for r in range(ca.grid.number_of_node_rows): for c in range(ca.grid.number_of_node_columns): n -= 1 print('{0:.0f}'.format(ca.node_state[n]), end=' ') print() # FINALIZE # Plot ca_plotter.finalize()
Srange = df_params['Srange'][ID] b = df_params['b'][ID] ds = df_params['ds'][ID] tr = df_params['tr'][ID] tb = df_params['tb'][ID] Lh = df_params['Lh'][ID] D = df_params['D'][ID] U = df_params['U'][ID] sc = df_params['sc'][ID] Lh = df_params['Lh'][ID] # initialize grid grid = RasterModelGrid((Ny, Nx), xy_spacing=Lh / Nx) grid.set_status_at_node_on_edges(right=grid.BC_NODE_IS_CLOSED, top=grid.BC_NODE_IS_CLOSED, \ left=grid.BC_NODE_IS_FIXED_VALUE, bottom=grid.BC_NODE_IS_CLOSED) elev = grid.add_zeros('node', 'topographic__elevation') x = grid.x_of_node z = calc_z(x, sc, U, D) - calc_z(x[-1], sc, U, D) z = np.fliplr(z.reshape(grid.shape)) elev[:] = z.flatten() base = grid.add_zeros('node', 'aquifer_base__elevation') base[:] = elev - b wt = grid.add_zeros('node', 'water_table__elevation') wt[:] = elev # initialize landlab and DupuitLEM components gdp = GroundwaterDupuitPercolator( grid, porosity=n, hydraulic_conductivity=ks, recharge_rate=0.0,
def test_diffusion(): infile = os.path.join(_THIS_DIR, 'diffusion_params.txt') inputs = ModelParameterDictionary(infile, auto_type=True) nrows = inputs.read_int('nrows') ncols = inputs.read_int('ncols') dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') init_elev = inputs.read_float('init_elev') mg = RasterModelGrid((nrows, ncols), (dx, dx)) uplift_rate = mg.node_y[mg.core_cells] / 100000. # create the fields in the grid mg.add_zeros('topographic__elevation', at='node') z = mg.zeros(at='node') + init_elev np.random.seed(0) mg['node']['topographic__elevation'] = z + np.random.rand(len(z)) / 1000. mg.set_fixed_value_boundaries_at_grid_edges(True, True, True, True) # instantiate: dfn = LinearDiffuser(mg, **inputs) # perform the loop: elapsed_time = 0. # total time in simulation while elapsed_time < time_to_run: if elapsed_time + dt > time_to_run: dt = time_to_run - elapsed_time dfn.run_one_step(dt) mg.at_node['topographic__elevation'][mg.core_nodes] += uplift_rate * dt elapsed_time += dt z_target = np.array([ 5.48813504e-04, 7.15189366e-04, 6.02763376e-04, 5.44883183e-04, 4.23654799e-04, 6.45894113e-04, 4.37587211e-04, 8.91773001e-04, 9.63662761e-04, 3.83441519e-04, 7.91725038e-04, 9.18166135e-04, 1.02015039e-03, 1.10666198e-03, 1.14866514e-03, 1.20224288e-03, 1.12953135e-03, 1.12966219e-03, 1.00745155e-03, 8.70012148e-04, 9.78618342e-04, 1.12628772e-03, 1.41663596e-03, 2.66338249e-03, 2.80420703e-03, 2.82445061e-03, 2.69263914e-03, 2.44620140e-03, 2.04237613e-03, 4.14661940e-04, 2.64555612e-04, 2.15073330e-03, 2.77965579e-03, 3.22134736e-03, 3.45859244e-03, 4.47224671e-03, 4.25371135e-03, 3.82941648e-03, 3.25127747e-03, 6.81820299e-04, 3.59507901e-04, 3.36577718e-03, 4.20490812e-03, 4.81467159e-03, 5.14099588e-03, 5.15029835e-03, 4.83533539e-03, 5.22312276e-03, 4.37284689e-03, 3.63710771e-04, 5.70196770e-04, 4.65122535e-03, 5.67854747e-03, 6.44757828e-03, 6.85985389e-03, 6.86464781e-03, 6.45159799e-03, 5.65255723e-03, 4.54258827e-03, 2.44425592e-04, 1.58969584e-04, 5.85971567e-03, 7.16648352e-03, 8.10954246e-03, 8.61082386e-03, 8.61350727e-03, 8.10597021e-03, 7.12594182e-03, 5.75483957e-03, 9.60984079e-05, 9.76459465e-04, 6.29476234e-03, 7.70594852e-03, 9.79504842e-03, 1.03829367e-02, 1.03869062e-02, 9.79374998e-03, 8.65447904e-03, 7.07179252e-03, 1.18727719e-04, 3.17983179e-04, 7.43078552e-03, 9.18353155e-03, 1.04682910e-02, 1.11542648e-02, 1.21643980e-02, 1.14930584e-02, 1.02184219e-02, 8.53727126e-03, 9.29296198e-04, 3.18568952e-04, 8.68034110e-03, 1.06702554e-02, 1.21275181e-02, 1.29049224e-02, 1.29184938e-02, 1.21616788e-02, 1.17059081e-02, 9.66728348e-03, 4.69547619e-06, 6.77816537e-04, 1.00128306e-02, 1.21521279e-02, 1.37494046e-02, 1.46053573e-02, 1.46205669e-02, 1.37908840e-02, 1.22146332e-02, 1.01165765e-02, 9.52749012e-04, 4.47125379e-04, 1.12069867e-02, 1.35547122e-02, 1.52840440e-02, 1.62069802e-02, 1.62196380e-02, 1.53169489e-02, 1.35997836e-02, 1.12818577e-02, 6.92531590e-04, 7.25254280e-04, 1.14310516e-02, 1.38647655e-02, 1.66771925e-02, 1.76447108e-02, 1.76515649e-02, 1.66885162e-02, 1.48507549e-02, 1.23206170e-02, 2.90077607e-04, 6.18015429e-04, 1.24952067e-02, 1.49924260e-02, 1.68435913e-02, 1.78291009e-02, 1.88311310e-02, 1.78422046e-02, 1.59665841e-02, 1.34122052e-02, 4.31418435e-04, 8.96546596e-04, 1.34612553e-02, 1.58763600e-02, 1.76887976e-02, 1.86526609e-02, 1.86492669e-02, 1.76752679e-02, 1.68480793e-02, 1.44368883e-02, 9.98847007e-04, 1.49448305e-04, 1.40672989e-02, 1.64140227e-02, 1.81162514e-02, 1.90091351e-02, 1.89959971e-02, 1.80757625e-02, 1.63425116e-02, 1.39643530e-02, 6.91669955e-05, 6.97428773e-04, 1.47340964e-02, 1.66453353e-02, 1.80835612e-02, 1.88335770e-02, 1.88048458e-02, 1.80022362e-02, 1.65110248e-02, 1.44854151e-02, 1.71629677e-04, 5.21036606e-04, 1.40633664e-02, 1.54867652e-02, 1.75865008e-02, 1.81309867e-02, 1.80760242e-02, 1.74501109e-02, 1.63343931e-02, 1.48208186e-02, 3.18389295e-05, 1.64694156e-04, 1.41550038e-02, 1.49870334e-02, 1.57563641e-02, 1.60213295e-02, 1.69074625e-02, 1.64888825e-02, 1.58787450e-02, 1.50671910e-02, 3.11944995e-04, 3.98221062e-04, 2.09843749e-04, 1.86193006e-04, 9.44372390e-04, 7.39550795e-04, 4.90458809e-04, 2.27414628e-04, 2.54356482e-04, 5.80291603e-05, 4.34416626e-04 ]) assert_array_almost_equal(mg.at_node['topographic__elevation'], z_target)
def test_neighbor_shaping_no_fldir(): mg = RasterModelGrid((5, 5)) mg.add_zeros("node", "topographic__elevation", dtype=float) with pytest.raises(FieldError): LakeMapperBarnes(mg, method="D8", redirect_flow_steepest_descent=True)
import time inputs = ModelParameterDictionary('./drive_sp_params_discharge.txt') nrows = 5 ncols = 5 dx = inputs.read_float('dx') dt = inputs.read_float('dt') time_to_run = inputs.read_float('run_time') # nt needs defining uplift = inputs.read_float('uplift_rate') init_elev = inputs.read_float('init_elev') mg = RasterModelGrid(nrows, ncols, dx) # create the fields in the grid mg.add_zeros('topographic__elevation', at='node') z = np.array([ 5., 5., 0., 5., 5., 5., 2., 1., 2., 5., 5., 3., 2., 3., 5., 5., 4., 4., 4., 5., 5., 5., 5., 5., 5. ]) mg['node']['topographic__elevation'] = z print('Running ...') # instantiate the components: fr = FlowAccumulator(mg, flow_director='D8') sp = StreamPowerEroder(mg, './drive_sp_params_discharge.txt') # load the Fastscape module too, to allow direct comparison fsp = Fsc(mg, './drive_sp_params_discharge.txt') # perform the loop (once!)
elif direction == "S": dir_sed_flux = self._Qsed_s dir_water_flux = self._Qs thisslice = (slice(1, -1, 1), slice(0, -1, 1)) deadedge = (slice(0, 1, 1), slice(0, -1, 1)) else: raise NameError("direction must be {'E', 'N', 'S', 'W'}") slope_diff = (S_val - S_thresh).clip(0.0) dir_sed_flux[thisslice] = dir_water_flux[thisslice] * slope_diff[thisslice] dir_sed_flux[deadedge] = 0.0 def diffuse_sediment(self, Qw_in, Qsed_in): """""" pass if __name__ == "__main__": from landlab import imshow_grid_at_node S_crit = 0.25 mg = RasterModelGrid((20, 20), 0.5) mg.add_zeros("topographic__elevation", at="node") Qw_in = mg.add_zeros("water__discharge_in", at="node") Qs_in = mg.add_zeros("sediment__discharge_in", at="node") Qw_in[0] = 0.5 * np.pi Qs_in[0] = (1.0 - S_crit) * 0.5 * np.pi dd = DischargeDiffuser(mg, S_crit) for i in range(5): # 501 dd.run_one_step(0.01) # 0.08 imshow_grid_at_node(mg, "topographic__elevation")
# Sai Nudurupati and Erkan Istanbulluoglu- 16May2014 : # Example to use potential_evapotranspiration_field.py #import landlab from landlab import RasterModelGrid from landlab.components.radiation.radiation_field import Radiation from landlab.components.PET.potential_evapotranspiration_field import PotentialEvapotranspiration import numpy as np import matplotlib.pyplot as plt from landlab.plot.imshow import imshow_field grid = RasterModelGrid( 100, 100, 20. ) elevation = np.random.rand(grid.number_of_nodes) * 1000 grid.add_zeros('node','Elevation',units = 'm') grid['node']['Elevation'] = elevation rad = Radiation( grid ) PET = PotentialEvapotranspiration( grid ) current_time = 0.56 rad.update( current_time ) PET.update( ConstantPotentialEvapotranspiration = 10.0 ) plt.figure(0) imshow_field(grid,'RadiationFactor', values_at = 'cell', grid_units = ('m','m')) plt.figure(1) imshow_field(grid,'PotentialEvapotranspiration', values_at = 'cell', grid_units = ('m','m')) plt.savefig('PET_test') plt.show()
out_interval = 25 color = 'gnuplot2' # 'winter' out_fields = ['topographic__elevation', 'channel_sediment__volumetric_flux'] # build the structures: mg = RasterModelGrid(raster_params['shape'], raster_params['dx']) for edge in (mg.nodes_at_left_edge, mg.nodes_at_top_edge, mg.nodes_at_right_edge): mg.status_at_node[edge] = CLOSED_BOUNDARY z = mg.add_field('node', 'topographic__elevation', np.loadtxt(raster_params['initcond'])) sed = mg.add_zeros('node', 'channel_sediment__volumetric_flux', dtype=float) fr = FlowRouter(mg) eroder = FastscapeEroder(mg, **inputs_sp) ld = LinearDiffuser(mg, **inputs_ld) def build_master_dict(expt_ID): total_dict = inputs_sp.copy() total_dict.update(inputs_ld) total_dict.update(raster_params) total_dict['expt_ID'] = expt_ID total_dict['dt'] = dt total_dict['max_loops'] = max_loops total_dict['multiplierforstab'] = multiplierforstab total_dict['out_interval'] = out_interval
def test_steady_state_with_basic_solver_option(): """ Test that model matches the transport-limited analytical solution for slope/area relationship at steady state: S=((U * v_s) / (K * A^m) + U / (K * 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") 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) # 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 = 0.01 U = 0.0001 dt = 1.0 F_f = 0.0 # all sediment is considered coarse bedload m_sp = 0.5 n_sp = 1.0 v_s = 0.5 phi = 0.5 # Instantiate the ErosionDeposition component... ed = ErosionDeposition( mg, K=K, F_f=F_f, phi=phi, v_s=v_s, m_sp=m_sp, n_sp=n_sp, sp_crit=0, solver="basic", ) # ... 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] ed.run_one_step(dt=dt, flooded_nodes=flooded) z[mg.core_nodes] += U * dt # m # compare numerical and analytical slope solutions num_slope = mg.at_node["topographic__steepest_slope"][mg.core_nodes] analytical_slope = np.power( ((U * v_s) / (K * np.power(mg.at_node["drainage_area"][mg.core_nodes], m_sp))) + (U / (K * 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="E/D 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="E/D sediment flux test failed", verbose=True, )
def test_raise_kwargs_error(): mg = RasterModelGrid((5, 5)) z = mg.add_zeros('node', 'topographic__elevation') z += mg.node_x.copy()**2 assert_raises(TypeError, TaylorNonLinearDiffuser, mg, bad_name='true')
def test_fastscape(): input_str = os.path.join(_THIS_DIR, "drive_sp_params.txt") inputs = ModelParameterDictionary(input_str) nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") dt = inputs.read_float("dt") time_to_run = inputs.read_float("run_time") uplift = inputs.read_float("uplift_rate") init_elev = inputs.read_float("init_elev") mg = RasterModelGrid(nrows, ncols, xy_spacing=dx) mg.set_closed_boundaries_at_grid_edges(False, False, True, True) mg.add_zeros("topographic__elevation", at="node") z = mg.zeros(at="node") + init_elev numpy.random.seed(0) mg["node"]["topographic__elevation"] = z + numpy.random.rand( len(z)) / 1000.0 fr = FlowAccumulator(mg, flow_director="D8") fsp = Fsc(mg, input_str, method="D8") elapsed_time = 0.0 while elapsed_time < time_to_run: if elapsed_time + dt > time_to_run: dt = time_to_run - elapsed_time mg = fr.run_one_step() mg = fsp.erode(mg, dt=dt) mg.at_node["topographic__elevation"][mg.core_nodes] += uplift * dt elapsed_time += dt z_trg = numpy.array([ 5.48813504e-04, 7.15189366e-04, 6.02763376e-04, 5.44883183e-04, 4.23654799e-04, 6.45894113e-04, 1.01830760e-02, 9.58036770e-03, 6.55865452e-03, 3.83441519e-04, 7.91725038e-04, 1.00142749e-02, 8.80798884e-03, 5.78387585e-03, 7.10360582e-05, 8.71292997e-05, 9.81911417e-03, 9.52243406e-03, 7.55093226e-03, 8.70012148e-04, 9.78618342e-04, 1.00629755e-02, 8.49253798e-03, 5.33216680e-03, 1.18274426e-04, 6.39921021e-04, 9.88956320e-03, 9.47119567e-03, 6.43790696e-03, 4.14661940e-04, 2.64555612e-04, 1.00450743e-02, 8.37262908e-03, 5.21540904e-03, 1.87898004e-05, 6.17635497e-04, 9.21286940e-03, 9.34022513e-03, 7.51114450e-03, 6.81820299e-04, 3.59507901e-04, 6.19166921e-03, 7.10456176e-03, 6.62585507e-03, 6.66766715e-04, 6.70637870e-04, 2.10382561e-04, 1.28926298e-04, 3.15428351e-04, 3.63710771e-04, ]) assert_array_almost_equal(mg.at_node["topographic__elevation"], z_trg)
######################################################### ## ## Example for soil_moisture_field.py ## ## Sai Nudurupati and Erkan Istanbulluoglu - 15May2014 ## ######################################################### from landlab import RasterModelGrid from landlab.components.soil_moisture import SoilMoisture import numpy as np grid = RasterModelGrid(10, 10, 1.) grid.add_zeros('cell', 'VegetationCover', units='None') grid.add_zeros('cell', 'LiveLeafAreaIndex', units='None') grid.add_zeros('cell', 'PotentialEvapotranspiration', units='mm') grid['cell']['InitialSaturationFraction'] = np.random.rand( grid.number_of_cells) grid['cell']['VegetationsCover'] = np.random.rand(grid.number_of_cells) grid['cell']['LiveLeafAreaIndex'] = np.ones(grid.number_of_cells) * 3 grid['cell']['PotentialEvapotranspiration'] = np.ones(grid.number_of_cells) * 6 current_time = 0.56 SM = SoilMoisture(grid) #PD = PrecipitationDistribution() #PD.update() #precip = PD.get_storm_depth() #Tb = PD.get_interstorm_event_duration() #Tr = PD.get_precipitation_event_duration() current_time = SM.update(current_time)
nrows = inputs.read_int("nrows") ncols = inputs.read_int("ncols") dx = inputs.read_float("dx") dt = inputs.read_float("dt") time_to_run = inputs.read_float("run_time") # nt needs defining uplift = inputs.read_float("uplift_rate") init_elev = inputs.read_float("init_elev") mg = RasterModelGrid(nrows, ncols, dx) # mg.set_inactive_boundaries(False, False, False, False) # mg.set_inactive_boundaries(True,True,True,True) mg.set_looped_boundaries(True, True) # create the fields in the grid mg.add_zeros("topographic__elevation", at="node") z = mg.zeros(at="node") + init_elev mg["node"]["topographic__elevation"] = z + numpy.random.rand(len(z)) / 1000. # Now add a step to diffuse out: # mg.at_node['topographic__elevation'][mg.active_nodes[:(mg.active_nodes.shape[0]//2.)]] # += 0.05 #half block uplift # pylab.figure(1) # pylab.close() # elev = mg['node']['topographic__elevation'] # elev_r = mg.node_vector_to_raster(elev) # pylab.figure(1) # im = pylab.imshow(elev_r, cmap=pylab.cm.RdBu) # pylab.show()
def sm(): grid = RasterModelGrid((20, 20), spacing=10e0) grid.add_zeros("vegetation__plant_functional_type", at="cell", dtype=int) return SoilMoisture(grid)
# progress. current_real_time = time.time() next_report = current_real_time + report_interval # Create grid mg = RasterModelGrid(nr, nc, 1.0) # Make the boundaries be walls #right, bottom, left, top mg.set_closed_boundaries_at_grid_edges(False, True, True, True) # Set up the states and pair transitions. ns_dict = { 0 : 'fluid', 1 : 'particle' } xn_list = setup_transition_list() # Create the node-state array and attach it to the grid node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=int) # Initialize the node-state array: here, the initial condition is a pile of # resting grains at the bottom of a container. left_cols = np.where(mg.node_x<0.05*nc)[0] node_state_grid[left_cols] = 1 # For visual display purposes, set all boundary nodes to fluid node_state_grid[mg.closed_boundary_nodes] = 0 # Create the CA model ca = OrientedRasterCTS(mg, ns_dict, xn_list, node_state_grid) grain = '#5F594D' fluid = '#D0E4F2' clist = [fluid,grain]
"at_node:aquifer_base__elevation", "at_node:water_table__elevation", ] output["base_output_path"] = './data/steady_sp_gam_hi_' output["run_id"] = ID #make this task_id if multiple runs #initialize grid np.random.seed(12345) grid = RasterModelGrid((125, 125), xy_spacing=v0) grid.set_status_at_node_on_edges( right=grid.BC_NODE_IS_CLOSED, top=grid.BC_NODE_IS_CLOSED, left=grid.BC_NODE_IS_FIXED_VALUE, bottom=grid.BC_NODE_IS_CLOSED, ) elev = grid.add_zeros('node', 'topographic__elevation') elev[:] = b + 0.1 * hg * np.random.rand(len(elev)) base = grid.add_zeros('node', 'aquifer_base__elevation') wt = grid.add_zeros('node', 'water_table__elevation') wt[:] = elev.copy() #initialize components gdp = GroundwaterDupuitPercolator( grid, porosity=n, hydraulic_conductivity=ksat, regularization_f=0.01, recharge_rate=p, courant_coefficient=0.1, vn_coefficient=0.1, )
def main(): # INITIALIZE # User-defined parameters nr = 128 nc = 128 fracture_spacing = 10 # fracture spacing, cell widths plot_interval = 0.25 run_duration = 4.0 report_interval = 5.0 # report interval, in real-time seconds # Remember the clock time, and calculate when we next want to report # progress. current_real_time = time.time() next_report = current_real_time + report_interval # Create grid mg = RasterModelGrid(nr, nc, 1.0) # Set up the states and pair transitions. # Transition data here represent a body of fractured rock, with rock # represented by nodes with state 0, and saprolite (weathered rock) # represented by nodes with state 1. Node pairs (links) with 0-1 or 1-0 # can undergo a transition to 1-1, representing chemical weathering of the # rock. ns_dict = {0: 'rock', 1: 'saprolite'} xn_list = setup_transition_list() # Create the node-state array and attach it to the grid node_state_grid = mg.add_zeros('node', 'node_state_map', dtype=int) # Initialize the node-state array as a "fracture grid" in which randomly # oriented fractures are represented as lines of saprolite embedded in # bedrock. node_state_grid[:] = make_frac_grid(fracture_spacing, model_grid=mg) # Create the CA model ca = RasterLCA(mg, ns_dict, xn_list, node_state_grid) # Debug output if needed if _DEBUG: n = ca.grid.number_of_nodes for r in range(ca.grid.number_of_node_rows): for c in range(ca.grid.number_of_node_columns): n -= 1 print '{0:.0f}'.format(ca.node_state[n]), print # Create a CAPlotter object for handling screen display ca_plotter = CAPlotter(ca) # Plot the initial grid ca_plotter.update_plot() # RUN current_time = 0.0 while current_time < run_duration: # Once in a while, print out simulation and real time to let the user # know that the sim is running ok current_real_time = time.time() if current_real_time >= next_report: print 'Current sim time', current_time, '(', 100 * current_time / run_duration, '%)' next_report = current_real_time + report_interval # Run the model forward in time until the next output step ca.run(current_time + plot_interval, ca.node_state, plot_each_transition=False) #, plotter=ca_plotter) current_time += plot_interval # Plot the current grid ca_plotter.update_plot() # for debugging if _DEBUG: n = ca.grid.number_of_nodes for r in range(ca.grid.number_of_node_rows): for c in range(ca.grid.number_of_node_columns): n -= 1 print '{0:.0f}'.format(ca.node_state[n]), print # FINALIZE # Plot ca_plotter.finalize()
def test_raster_cts(): """ Tests instantiation of a RasterCTS and implementation of one transition, with a callback function. """ # Set up a small grid with no events scheduled mg = RasterModelGrid(4, 4, 1.0) mg.set_closed_boundaries_at_grid_edges(True, True, True, True) node_state_grid = mg.add_ones('node', 'node_state_map', dtype=int) node_state_grid[6] = 0 ns_dict = {0: 'black', 1: 'white'} xn_list = [] xn_list.append( Transition((1, 0, 0), (0, 1, 0), 0.1, '', True, callback_function)) pd = mg.add_zeros('node', 'property_data', dtype=int) pd[5] = 50 ca = RasterCTS(mg, ns_dict, xn_list, node_state_grid, prop_data=pd, prop_reset_value=0) # Test the data structures assert (ca.xn_to.size == 4), 'wrong size for xn_to' assert (ca.xn_to.shape == (4, 1)), 'wrong size for xn_to' assert (ca.xn_to[2][0] == 1), 'wrong value in xn_to' assert (len(ca.event_queue) == 1), 'event queue has wrong size' assert (ca.num_link_states == 4), 'wrong number of link states' assert (ca.prop_data[5] == 50), 'error in property data' assert (ca.xn_rate[2][0] == 0.1), 'error in transition rate array' assert (ca.active_links_at_node[1][6] == 8), 'error in active link array' assert (ca.num_node_states == 2), 'error in num_node_states' assert (ca.link_orientation[-1] == 0), 'error in link orientation array' assert (ca.link_state_dict[(1, 0, 0)] == 2), 'error in link state dict' assert (ca.n_xn[2] == 1), 'error in n_xn' assert (ca.node_pair[1] == (0, 1, 0)), 'error in cell_pair list' # Manipulate the data in the event queue for testing: # pop the scheduled event off the queue ev = heappop(ca.event_queue) assert (ca.event_queue == []), 'event queue should now be empty but is not' # engineer an event ev.time = 1.0 ev.link = 8 ev.xn_to = 1 ev.propswap = True ev.prop_update_fn = callback_function ca.next_update[8] = 1.0 # push it onto the event queue heappush(ca.event_queue, ev) # run the CA ca.run(2.0) # some more tests. # Is current time advancing correctly? (should only go to 1.0, not 2.0) # Did the two nodes (5 and 6) correctly exchange states? # Did the property ID and data arrays get updated? Note that the "propswap" # should switch propids between nodes 5 and 6, and the callback function # should increase the value of prop_data in the "swap" node from 50 to 150. assert (ca.current_time == 1.0), 'current time incorrect' assert (ca.node_state[5] == 0), 'error in node state 5' assert (ca.node_state[6] == 1), 'error in node state 6'
# from landlab.grid.mappers import map_link_end_node_max_value_to_link inputs = ModelParameterDictionary('./pot_fr_params.txt') nrows = 50 #inputs.read_int('nrows') ncols = 50 #inputs.read_int('ncols') dx = inputs.read_float('dx') init_elev = inputs.read_float('init_elev') mg = RasterModelGrid(nrows, ncols, dx) # attempt to implement diffusion with flow routing... #modify the fields in the grid z = mg.zeros(at='node') + init_elev mg.at_node['topographic__elevation'] = z + np.random.rand(len(z)) / 1000. mg.add_zeros('water__unit_flux_in', at='node') mg.add_zeros('surface_water__discharge', at='link') #Set boundary conditions inlet_node = np.array((int((1.5 * mg.number_of_node_columns) // 1))) section_col = int((0.5 * mg.number_of_node_columns) // 1) mg.at_node['topographic__elevation'][section_col] = 1. mg.set_closed_boundaries_at_grid_edges(False, False, False, True) mg.set_fixed_value_boundaries_at_grid_edges(False, True, True, True) mg.status_at_node[section_col] = 2 mg._update_links_nodes_cells_to_new_BCs() mg.at_node['water__unit_flux_in'].fill(0.) mg.at_node['water__unit_flux_in'][inlet_node] = 1. pfr = PotentialityFlowRouter(mg, 'pot_fr_params.txt') interior_nodes = mg.core_nodes