def setup_grid(): from landlab import RasterModelGrid grid = RasterModelGrid((32, 240), spacing=25) grid.add_zeros('node', 'water__depth') grid.add_zeros('node', 'topographic__elevation') grid.add_zeros('water__discharge', at='active_link') deAlm = OverlandFlow(grid, mannings_n=0.01, h_init=0.001) globals().update({'deAlm': OverlandFlow(grid)})
def run_day(mg, precipitation: float, duration=1800): """ Calculates the mm of water that has infiltrated into soil after a rainfall event. Rainfall events are assumed to be instantaneous and constant over the model grid. :param dem: model grid :param precipitation: rainfall in mm/hr :param duration: seconds of rainfall :return: mm of water infiltrated into the soil at every coordinate in the grid """ elapsed_time = 0.0 swd = mg.add_zeros('surface_water__depth', at='node', clobber=True) swd += precipitation swid = mg.add_zeros('soil_water_infiltration__depth', at='node', clobber=True) swid += 1e-6 siga = SoilInfiltrationGreenAmpt(mg) of = OverlandFlow(mg, steep_slopes=True) while elapsed_time < duration: dt = of.calc_time_step() dt = dt if dt + elapsed_time < duration else duration - elapsed_time of.run_one_step(dt=dt) siga.run_one_step(dt=dt) elapsed_time += dt return xr.DataArray(mg.at_node['soil_water_infiltration__depth'].reshape( mg.shape), dims=('x', 'y'))
def test_deAlm_analytical_imposed_dt_short(): grid = RasterModelGrid((32, 240), xy_spacing=25) grid.add_zeros("surface_water__depth", at="node") grid.add_zeros("topographic__elevation", at="node") 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_deAlm_analytical(): from landlab import RasterModelGrid grid = RasterModelGrid((32, 240), spacing=25) grid.add_zeros('node', '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']['water__discharge'][left_inactive_ids] = ( grid['link']['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['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 deAlm(): grid = RasterModelGrid((32, 240), xy_spacing=25) grid.add_zeros("surface_water__depth", at="node") grid.add_zeros("topographic__elevation", at="node") grid.add_zeros("surface_water__discharge", at="link") return OverlandFlow(grid, mannings_n=0.01, h_init=0.001)
hydrograph_time_hrs = [] # Setting initial fields... rmg["node"]["topographic__elevation"] = z rmg["link"]["surface_water__discharge"] = np.zeros(rmg.number_of_links) rmg["node"]["surface_water__depth"] = np.zeros(rmg.number_of_nodes) # and fixed link boundary conditions... rmg.set_fixed_link_boundaries_at_grid_edges( True, True, True, True, fixed_link_value_of="surface_water__discharge") # Setting the outlet node to OPEN_BOUNDARY rmg.status_at_node[100] = 1 # Initialize the OverlandFlow() class. of = OverlandFlow(rmg, use_fixed_links=True, steep_slopes=True) # Record the start time so we know how long it runs. start_time = time.time() # Link to sample at the outlet link_to_sample = 299 # Storm duration in seconds storm_duration = 7200.0 # Running the overland flow component. while elapsed_time < model_run_time: # The storm starts when the model starts. While the elapsed time is less # than the storm duration, we add water to the system as rainfall.
infBandWidthNorm = 0.5 infBandWidth = length * dx / 2 * infBandWidthNorm channel_left = (length * dx + channel_width) / 2 channel_right = (length * dx - channel_width) / 2 isChannel = np.logical_and(rmg.x_of_node < channel_left, rmg.x_of_node > channel_right) highInfBand = np.logical_and(rmg.x_of_node < channel_left + infBandWidth, rmg.x_of_node > channel_right - infBandWidth) inf_mask = np.logical_xor(highInfBand, isChannel) hc[inf_mask] *= 10 of = OverlandFlow(rmg, steep_slopes=True) SI = SoilInfiltrationGreenAmpt(rmg, hydraulic_conductivity=hc) elapsed_time = 0 run_time = 1e4 iters = 0 while elapsed_time < run_time: # First, we calculate our time step. dt = of.calc_time_step() # Now, we can generate overland flow. of.overland_flow() SI.run_one_step(dt) # Increased elapsed time if iters % 1000 == 0:
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('water__depth', at='node') # water depth (m) rmg.add_zeros('water__discharge', at='link') # unit discharge (m2/s) # Add our initial thin layer of water to the field of water depth. #rmg['node']['water_depth'] += h_init # 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 = OverlandFlow(rmg, mannings_n=n, theta=0.8, h_init=0.001) # Now, we need to set a fixed value on the left edge, so we find the # link neighbor arrays... of.set_up_neighbor_arrays() # ... and get a list of all horizonal ids, not just active ids (which is what # the deAlmeida solution uses) all_horizontal_ids = links.horizontal_link_ids(rmg.shape) # from there, we are going to reset our west neighbor array... of.west_neighbors = (links.horizontal_west_link_neighbor( rmg.shape, all_horizontal_ids)) # and find the ids of the arrays along the west edge of the grid. We actually # will set the discharge values here at every time step in the loop.
def deAlm(): grid = RasterModelGrid((32, 240), spacing=25) grid.add_zeros('surface_water__depth', at='node') grid.add_zeros('topographic__elevation', at='node') grid.add_zeros('surface_water__discharge', at='link') return OverlandFlow(grid, mannings_n=0.01, h_init=0.001)
# DEM, depth, and discharge assignment rmg['node']['topographic__elevation'] = z rmg.add_zeros('node', 'surface_water__depth') rmg.add_zeros('node', 'surface_water__discharge') # Assign the outlet and boundary conditions print("\tSetting Boundary Conditions...") # If more than one outlet, errors out and show which outlets # outlet_id = rmg.set_watershed_boundary_condition(z.flatten(), nodata_value=-9999, return_outlet_id=True) outlet_id = 2615 rmg.set_watershed_boundary_condition_outlet_id(outlet_id, z.flatten()) # Object for managing the simulation of = OverlandFlow(rmg, mannings_n=0.03, steep_slopes=True) # Flow Routing print("\tProcessing DEM for routing...") sf = SinkFiller(rmg, routing='D4', apply_slope=False, fill_slope=1.e-5) print("\tFilling pits...") #sf.fill_pits() print("\tOutputting topo from Landlab...") write_netcdf('ll_topo.nc', rmg, names=['topographic__elevation']) ################################# FLOW SIM ##################################### # Show the user whats going on with the progress print()
def reset(self): """ Reset function. Resets the world to its initial state. """ super(FloodWorld, self).reset() # Terrain generation shape = (self.grid_size,) * 2 size = self.grid_size * self.grid_size # Set initial simple topography z = self.vertical_scale * self.simple_topography(shape) # Create raster model if it does not exist if self.mg is None: self.mg = RasterModelGrid(shape, int(round(self.world_size/self.grid_size))) self.mg.set_closed_boundaries_at_grid_edges(True, True, True, True) self.z = self.mg.add_field('node', 'topographic__elevation', z) self.swd = self.mg.add_zeros('node', 'surface_water__depth') else: self.mg.at_node['topographic__elevation'] = z self.swd[:] = np.zeros(size) import matplotlib.pyplot as plt plt.figure() from landlab.plot import imshow_grid imshow_grid(self.mg, 'topographic__elevation', colorbar_label='m') plt.draw() # Set evolution parameters uplift_rate = self.inputs['uplift_rate'] total_t = self.inputs['total_time'] dt = self.inputs['dt'] nt = int(total_t // dt) # Loops uplift_per_step = uplift_rate * dt self.fr = FlowAccumulator(self.mg, **self.inputs) self.sp = FastscapeEroder(self.mg, **self.inputs) # Erode terrain for i in range(nt): self.fr.run_one_step() # Not time sensitive self.sp.run_one_step(dt) self.mg.at_node['topographic__elevation'][self.mg.core_nodes] += uplift_per_step # add the uplift if i % 10 == 0: print('Erode: Completed loop %d' % i) plt.figure() imshow_grid(self.mg, 'topographic__elevation', colorbar_label='m') plt.draw() plt.show() # Setup surface water flow self.of = OverlandFlow(self.mg, steep_slopes=True, mannings_n=0.01) # Setup initial flood self.swd[[5050, 5051, 5150, 5151]] += self.h_init self.active = np.greater(np.flip(np.reshape(self.swd, shape), axis=0), self.flood_threshold)