def test_with_hex_grid(): grid = HexModelGrid((5, 5), node_layout="rect") grid.add_zeros("topographic__elevation", at="node") ListricKinematicExtender(grid) ListricKinematicExtender(grid, fault_location=2.0) grid = HexModelGrid((5, 5), node_layout="rect", orientation="vertical") grid.add_zeros("topographic__elevation", at="node") assert_raises(NotImplementedError, ListricKinematicExtender, grid)
def test_hex_grid_link_order(): """Test the order of links in a small hex grid.""" hg = HexModelGrid(3, 2) assert_array_equal(hg.node_at_link_tail, [0, 0, 0, 1, 1, 2, 3, 2, 3, 3, 4, 5]) assert_array_equal(hg.node_at_link_head, [1, 2, 3, 3, 4, 3, 4, 5, 5, 6, 6, 6]) hg = HexModelGrid(2, 3, orientation="vertical") assert_array_equal(hg.node_at_link_tail, [1, 0, 0, 1, 3, 1, 2, 4, 3, 3, 4, 6]) assert_array_equal(hg.node_at_link_head, [0, 2, 3, 3, 2, 4, 5, 3, 5, 6, 6, 5])
def test_number_of_patches(): grid = HexModelGrid((4, 3)) assert grid.number_of_patches == 19 grid = HexModelGrid((3, 4)) assert grid.number_of_patches == 14 grid = HexModelGrid((4, 3), node_layout="rect") assert grid.number_of_patches == 12 grid = HexModelGrid((3, 4), node_layout="rect") assert grid.number_of_patches == 12
def test_initial_state_grid(): """Test passing in an initial array of node states.""" nr = 4 nc = 3 hg = HexModelGrid(shape=(nr, nc), node_layout='rect', orientation='vertical') ins = hg.add_zeros('node', 'node_state', dtype=np.int) ins[hg.y_of_node < 2] = 8 params = { 'grid_size': (nr, nc), 'report_interval': 5.0, 'output_interval': 1.0e99, 'disturbance_rate': 0.0, 'weathering_rate': 0.0, 'dissolution_rate': 1.0, 'run_duration': 3.0e3, 'plot_interval': 1.0e99, 'uplift_interval': 1.0e7, 'friction_coef': 1.0, 'fault_x': -0.001, 'cell_width': 1.0, 'grav_accel': 9.8, 'plot_file_name': 'test_column_dissolution', 'init_state_grid': ins, 'seed': 0, } gfs = GrainFacetSimulator(**params) assert_equal(np.count_nonzero(gfs.ca.node_state), 6)
def test_non_raster(): """Test a hex model grid.""" grid = HexModelGrid(7, 3, dx=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': 30.0, 'x1': 30.0, 'y2': 20.0, 'x2': 0.0}, 'include_boundaries': True} nf = NormalFault(grid, **param_dict) # plotting, to test this. it works! #import matplotlib.pyplot as plt #plt.figure() #imshow_grid(grid, nf.faulted_nodes, color_for_background='y') #plt.plot(grid.x_of_node, grid.y_of_node, 'c.') #plt.plot([param_dict['fault_trace']['x1'], param_dict['fault_trace']['x2']], # [param_dict['fault_trace']['y1'], param_dict['fault_trace']['y2']], 'r') #plt.show() out = np.array([ True, True, True, True, True, True, True, False, True, True, True, True, False, False, False, False, True, True, False, False, False, False, False, False, False, False, False, False, False, False], dtype=bool) assert_array_equal(nf.faulted_nodes, out)
def test_hex_mfd(): mg = HexModelGrid(5, 3) z = mg.add_field("topographic__elevation", mg.node_x + mg.node_y, at="node") fa = FlowAccumulator(mg, flow_director="MFD") fa.run_one_step()
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_hex_grid(): mg = HexModelGrid((5, 5)) mg.add_zeros("soil__depth", at="node") dt = 1000.0 expw3 = ExponentialWeathererIntegrated( mg, soil_production__maximum_rate=1.0, soil_production__decay_depth=1.0, soil_production__expansion_factor=1.3, ) expw3.run_one_step(dt) errors = [] # replace assertions by conditions if not np.allclose( mg.at_node["soil_production__dt_weathered_depth"][mg.core_nodes], 5.5161 ): errors.append("error in weathered depth") if not np.allclose( mg.at_node["soil_production__dt_produced_depth"][mg.core_nodes], 7.1709 ): errors.append("error in produced depth") if not np.allclose(dt * mg.at_node["soil_production__rate"][mg.core_nodes], 1000.0): errors.append("error in basic euler integration") # assert no error message has been registered, else print messages assert not errors, "errors occured:\n{}".format("\n".join(errors))
def test_along_links(orientation, node_layout, angle): if orientation == "horizontal": east = np.deg2rad(0.0) nne = np.deg2rad(60.0) nnw = np.deg2rad(120.0) angle = np.deg2rad(angle) else: east = np.deg2rad(330.0) nne = np.deg2rad(30.0) nnw = np.deg2rad(90.0) angle = np.deg2rad(angle - 30.0) grid = HexModelGrid((3, 3), node_layout=node_layout, orientation=orientation) value_at_link = np.empty(grid.number_of_links) is_core_node = grid.status_at_node == grid.BC_NODE_IS_CORE east_links = np.isclose(grid.angle_of_link, east) nne_links = np.isclose(grid.angle_of_link, nne) nnw_links = np.isclose(grid.angle_of_link, nnw) value_at_link[east_links] = np.cos(angle - east) value_at_link[nne_links] = np.cos(angle - nne) value_at_link[nnw_links] = np.cos(angle - nnw) vx, vy = map_link_vector_components_to_node(grid, value_at_link) assert np.sqrt(vx[is_core_node] ** 2 + vy[is_core_node] ** 2) == pytest.approx(1.0) assert vx[~is_core_node] == pytest.approx(0.0) assert vy[~is_core_node] == pytest.approx(0.0) assert vx[is_core_node] == pytest.approx(np.cos(angle)) assert vy[is_core_node] == pytest.approx(np.sin(angle))
def __init__(self, grid=None, node_state=None): # If needed, create grid if grid is None: num_rows = _DEFAULT_NUM_ROWS num_cols = _DEFAULT_NUM_COLS self.grid = HexModelGrid(num_rows, num_cols, dx=1.0, orientation='vertical', shape='rect', reorient_links=True) else: # Make sure caller passed the right type of grid assert (grid.orientation=='vertical'), \ 'Grid must have vertical orientation' # Keep a reference to the grid self.grid = grid # If needed, create node-state grid if node_state is None: self.node_state = self.grid.add_zeros('node', 'node_state_map') else: print 'setting node state' self.node_state = node_state # Remember the # of rows and cols self.nr = self.grid.number_of_node_rows self.nc = self.grid.number_of_node_columns
def test_symmetry_of_solution(): """test that water table is symmetric under constant recharge Notes: ---- Under constant recharge with radially symmetric aquifer base elevation, the model should produce a water table that is radially symmetric. This test demonstrates this is the case where topographic elevation and aquifer base elevation are radially symmetric parabolas on a hexagonal grid. """ hmg = HexModelGrid(shape=(7, 4), spacing=10.0) x = hmg.x_of_node y = hmg.y_of_node elev = hmg.add_zeros("topographic__elevation", at="node") elev[:] = 1e-3 * (x * (max(x) - x) + y * (max(y) - y)) + 2 base = hmg.add_zeros("aquifer_base__elevation", at="node") base[:] = elev - 2 wt = hmg.add_zeros("water_table__elevation", at="node") wt[:] = elev wt[hmg.open_boundary_nodes] = 0.0 gdp = GroundwaterDupuitPercolator(hmg, recharge_rate=1e-7, hydraulic_conductivity=1e-4) for _ in range(1000): gdp.run_one_step(1e3) tc = hmg.at_node["aquifer__thickness"] assert_almost_equal(tc[5], tc[31]) # SW-NE assert_almost_equal(tc[29], tc[7]) # NW-SE assert_almost_equal(tc[16], tc[20]) # W-E
def test_with_lake_mapper_barnes(): hmg_hole = HexModelGrid((9, 5)) z = hmg_hole.add_field( "topographic__elevation", hmg_hole.x_of_node + np.round(hmg_hole.y_of_node), at="node", ) hole_nodes = [21, 22, 23, 30, 31, 39, 40] z[hole_nodes] = z[hole_nodes] * 0.1 hmg_hole.add_zeros("filled__elevation", at="node") fa = FlowAccumulator( hmg_hole, flow_director="Steepest", depression_finder="LakeMapperBarnes", fill_flat=False, redirect_flow_steepest_descent=True, reaccumulate_flow=True, fill_surface="filled__elevation", ) fa.run_one_step() rcvrs = hmg_hole.at_node["flow__receiver_node"] assert_array_equal(rcvrs[[13, 21, 46]], [6, 13, 39]) from landlab.components import LakeMapperBarnes fa = FlowAccumulator(hmg_hole, depression_finder=LakeMapperBarnes) lmb = LakeMapperBarnes(hmg_hole) fa = FlowAccumulator(hmg_hole, depression_finder=lmb)
def test_function_of_four_variables(): mg = HexModelGrid((5, 5)) mg.add_zeros("node", "topographic__elevation") with pytest.raises(ValueError): GenericFuncBaselevelHandler(mg, function=lambda x, y, t, q: (10 * x + 10 * y + 10 * t, +10 * q))
def test_outlet_lowering_object_bad_file(): """Test using an outlet lowering object with a bad file.""" mg = HexModelGrid((5, 5)) mg.add_zeros("node", "topographic__elevation") with pytest.raises(ValueError): NotCoreNodeBaselevelHandler(mg, lowering_file_path="foo.txt")
def test_nodes_at_link(): """Test nodes_at_link shares data with tail and head.""" grid = HexModelGrid((3, 2)) assert_array_equal(grid.nodes_at_link[:, 0], grid.node_at_link_tail) assert_array_equal(grid.nodes_at_link[:, 1], grid.node_at_link_head) assert np.may_share_memory(grid.nodes_at_link, grid.node_at_link_tail) assert np.may_share_memory(grid.nodes_at_link, grid.node_at_link_head)
def test_neighbor_shaping_hex(): hmg = HexModelGrid((6, 5), spacing=1.0) hmg.add_zeros("topographic__elevation", at="node", dtype=float) _ = FlowAccumulator(hmg) lmb = LakeMapperBarnes(hmg, redirect_flow_steepest_descent=True) for arr in (lmb._neighbor_arrays, lmb._link_arrays): assert len(arr) == 1 assert arr[0].shape == (hmg.number_of_nodes, 6) assert len(lmb._neighbor_lengths) == hmg.number_of_links
def __init__( self, grid=None, node_state=None, propid=None, prop_data=None, prop_reset_value=None, ): """ Create and initialize a HexLatticeTectonicizer. Examples -------- >>> from landlab import HexModelGrid >>> hg = HexModelGrid(6, 6, shape='rect') >>> hlt = HexLatticeTectonicizer() >>> hlt.grid.number_of_nodes 25 >>> hlt.nr 5 >>> hlt.nc 5 """ # If needed, create grid if grid is None: num_rows = _DEFAULT_NUM_ROWS num_cols = _DEFAULT_NUM_COLS self.grid = HexModelGrid( num_rows, num_cols, dx=1.0, orientation="vertical", shape="rect", reorient_links=True, ) else: # Make sure caller passed the right type of grid assert grid.orientation == "vertical", "Grid must have vertical orientation" # Keep a reference to the grid self.grid = grid # If needed, create node-state grid if node_state is None: self.node_state = self.grid.add_zeros("node", "node_state_map", dtype=int) else: self.node_state = node_state # Remember the # of rows and cols self.nr = self.grid.number_of_node_rows self.nc = self.grid.number_of_node_columns # propid should be either a reference to a CA model's "property id" # array, or None self.propid = propid self.prop_data = prop_data self.prop_reset_value = prop_reset_value
def test_functions_with_Hex(): mg = HexModelGrid(10, 10) z = mg.add_zeros("node", "topographic__elevation") z += mg.x_of_node + mg.y_of_node fa = FlowAccumulator(mg) fa.run_one_step() ch = ChiFinder(mg, min_drainage_area=1.0, reference_concavity=1.0) ch.calculate_chi()
def test_flow__distance_irregular_grid_d4(): """Test to demonstrate that flow__distance utility works as expected with irregular grids""" # instantiate a model grid dx = 1.0 hmg = HexModelGrid((5, 3), spacing=dx) # instantiate and add the elevation field hmg.add_field( "topographic__elevation", hmg.node_x + np.round(hmg.node_y), at="node" ) # instantiate the expected flow__distance array flow__distance_expected = np.array( [ 0.0, 0.0, 0.0, 0.0, 0.0, dx, 0.0, 0.0, dx, dx, 2.0 * dx, 0.0, 0.0, 2.0 * dx, 2.0 * dx, 0.0, 0.0, 0.0, 0.0, ] ) # setting boundary conditions hmg.status_at_node[hmg.boundary_nodes] = hmg.BC_NODE_IS_CLOSED # calculating flow directions with FlowAccumulator component: D4 algorithm fr = FlowAccumulator(hmg, flow_director="D4") fr.run_one_step() # calculating flow distance map flow__distance = calculate_flow__distance(hmg, add_to_grid=True, clobber=True) # test that the flow__distance utility works as expected assert_almost_equal(flow__distance_expected, flow__distance, decimal=10)
def test_function_that_returns_wrong_size(): mg = HexModelGrid((5, 5)) mg.add_zeros("node", "topographic__elevation") with pytest.raises(ValueError): GenericFuncBaselevelHandler( mg, function=lambda mg, t: np.mean(10 * mg.x_of_node + 10 * mg. y_of_node + 10 * t), )
def test_transitions_as_ids(): """Test passing from-state and to-state IDs instead of tuples """ mg = HexModelGrid(3, 2, 1.0, orientation="vertical", reorient_links=True) nsd = {0: "zero", 1: "one"} xnlist = [] xnlist.append(Transition(2, 3, 1.0, "transitioning")) nsg = mg.add_zeros("node", "node_state_grid") cts = HexCTS(mg, nsd, xnlist, nsg) assert cts.num_link_states == 4, "wrong number of transitions"
def test_write_hex_to_path(tmpdir, fname): grid = HexModelGrid((3, 2), spacing=2.0) z = grid.add_zeros("topographic__elevation", at="node") z[3] = 1.0 with tmpdir.as_cwd(): actual = write_obj(fname, grid) assert actual == fname with open(fname, "r") as fp: assert fp.read() == LITTLE_HEX_OBJ
def test_save_and_load_hex(): """Test saving and loading of a HexModelGrid.""" mg1 = HexModelGrid(3, 3, 1.0) mg1.add_zeros("node", "topographic__elevation") save_grid(mg1, "testsavedgrid.grid") mg2 = load_grid("testsavedgrid.grid") assert mg1.x_of_node[0] == mg2.x_of_node[0] assert_array_equal(mg1.status_at_node, mg2.status_at_node) for name in mg1.at_node: assert_array_equal(mg1.at_node[name], mg2.at_node[name])
def test_stream_power_save_output_hex(tmpdir): mg = HexModelGrid((3, 3), node_layout="rect", spacing=10.0) mg.status_at_node[mg.status_at_node == 1] = 4 mg.status_at_node[1] = 1 mg.add_ones("node", "topographic__elevation") mg.add_zeros("node", "aquifer_base__elevation") mg.add_ones("node", "water_table__elevation") gdp = GroundwaterDupuitPercolator(mg, recharge_rate=1e-4) hm = HydrologySteadyStreamPower(mg, groundwater_model=gdp, routing_method="Steepest") sp = FastscapeEroder( mg, K_sp=1e-10, m_sp=1, n_sp=1, discharge_field="surface_water_area_norm__discharge", ) ld = LinearDiffuser(mg, linear_diffusivity=1e-10) rm = RegolithConstantThickness(mg, uplift_rate=0.0) output = {} output["output_interval"] = 1000 output["output_fields"] = [ "at_node:topographic__elevation", "at_node:aquifer_base__elevation", "at_node:water_table__elevation", ] output["base_output_path"] = tmpdir.strpath + "/" output["run_id"] = 0 # make this task_id if multiple runs mdl = StreamPowerModel( mg, hydrology_model=hm, diffusion_model=ld, erosion_model=sp, regolith_model=rm, total_morphological_time=1e8, output_dict=output, ) mdl.run_model() file = tmpdir.join("0_grid_0.nc") mg1 = from_netcdf(file.strpath) keys = [ "topographic__elevation", "aquifer_base__elevation", "water_table__elevation", ] assert isinstance(mg1, HexModelGrid) assert set(mg1.at_node.keys()) == set(keys) assert_equal(mg1.status_at_node, mg.status_at_node)
def test_neighbor_shaping_hex(): hmg = HexModelGrid(6, 5, dx=1.) hmg.add_zeros("node", "topographic__elevation", dtype=float) hmg.add_zeros("node", "topographic__steepest_slope", dtype=float) hmg.add_zeros("node", "flow__receiver_node", dtype=int) hmg.add_zeros("node", "flow__link_to_receiver_node", dtype=int) lmb = LakeMapperBarnes(hmg, redirect_flow_steepest_descent=True) for arr in (lmb._neighbor_arrays, lmb._link_arrays): assert len(arr) == 1 assert arr[0].shape == (hmg.number_of_nodes, 6) assert len(lmb._neighbor_lengths) == hmg.number_of_links
def test_links_to_update(): """Test that update list includes lower 2 rows and fault-crossing links""" # Create a 6x6 test grid hg = HexModelGrid(6, 6, shape="rect", orientation="vert") lnf = LatticeNormalFault(grid=hg, fault_x_intercept=-0.1) assert_array_equal( lnf.links_to_update, [ 8, 9, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 38, 40, 41, 43, 46, 51, 54, 56, 60, 62, 68, 70, 73, 76, 77, 80, ], )
def test_hex_cts(): """Tests instantiation of a HexCTS() object""" mg = HexModelGrid(3, 2, 1.0, orientation="vertical", reorient_links=True) nsd = {0: "zero", 1: "one"} xnlist = [] xnlist.append(Transition((0, 1, 0), (1, 1, 0), 1.0, "transitioning")) nsg = mg.add_zeros("node", "node_state_grid") hcts = HexCTS(mg, nsd, xnlist, nsg) assert hcts.num_link_states == 4 assert_array_equal(hcts.link_orientation, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
def test_hex_cts(): """Tests instantiation of a HexCTS() object""" mg = HexModelGrid(3, 2, 1.0, orientation='vertical', reorient_links=True) nsd = {0 : 'zero', 1 : 'one'} xnlist = [] xnlist.append(Transition((0,1,0), (1,1,0), 1.0, 'transitioning')) nsg = mg.add_zeros('node', 'node_state_grid') hcts = HexCTS(mg, nsd, xnlist, nsg) assert_equal(hcts.num_link_states, 4) assert_array_equal(hcts.link_orientation, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
def test_hex(): """Test using a hex grid.""" mg = HexModelGrid(5, 5) z = mg.add_zeros("node", "topographic__elevation") bh = SingleNodeBaselevelHandler(mg, outlet_id=0, lowering_rate=-0.1) bh.run_one_step(10.0) assert z[1] == 0.0 assert z[0] == -1.0
def test_not_passing_infiltration_capacity(): mg = HexModelGrid(5, 5) with pytest.raises(ValueError): PrecipChanger( mg, daily_rainfall__intermittency_factor=0.3, daily_rainfall__intermittency_factor_time_rate_of_change=0.001, rainfall__mean_rate=3.0, rainfall__mean_rate_time_rate_of_change=0.2, rainfall__shape_factor=0.65, )