def route_flow(self, **kwds): """Route surface-water flow over a landscape. Routes surface-water flow by (1) assigning to each node a single drainage direction, and then (2) adding up the number of nodes that contribute flow to each node on the grid (including the node itself). Stores as ModelGrid fields: - Node array of receivers (nodes that receive flow), or ITS OWN ID if there is no receiver: *'flow__receiver_node'* - Node array of drainage areas: *'drainage_area'* - Node array of discharges: *'surface_water__discharge'* - Node array of steepest downhill slopes: *'topographic__steepest_slope'* - Node array containing downstream-to-upstream ordered list of node IDs: *'flow__upstream_node_order'* - Node array containing ID of link that leads from each node to its receiver, or BAD_INDEX_VALUE if no link: *'flow__link_to_receiver_node'* - Boolean node array of all local lows: *'flow__sink_flag'* Returns ------- ModelGrid The modified grid object Examples -------- >>> import numpy as np >>> from landlab import RasterModelGrid >>> from landlab.components.flow_routing import FlowRouter >>> mg = RasterModelGrid((5, 4), spacing=(1, 1)) >>> elev = np.array([0., 0., 0., 0., ... 0., 21., 10., 0., ... 0., 31., 20., 0., ... 0., 32., 30., 0., ... 0., 0., 0., 0.]) >>> _ = mg.add_field('node','topographic__elevation', elev) >>> mg.set_closed_boundaries_at_grid_edges(True, True, True, False) >>> fr = FlowRouter(mg) >>> mg = fr.route_flow() >>> mg.at_node['flow__receiver_node'] # doctest: +NORMALIZE_WHITESPACE array([ 0, 1, 2, 3, 4, 1, 2, 7, 8, 6, 6, 11, 12, 10, 10, 15, 16, 17, 18, 19]) >>> mg.at_node['drainage_area'] # doctest: +NORMALIZE_WHITESPACE array([ 0., 1., 5., 0., 0., 1., 5., 0., 0., 1., 3., 0., 0., 1., 1., 0., 0., 0., 0., 0.]) Now let's change the cell area (100.) and the runoff rates: >>> mg = RasterModelGrid((5, 4), spacing=(10., 10)) Put the data back into the new grid. >>> _ = mg.add_field('node','topographic__elevation', elev) >>> mg.set_closed_boundaries_at_grid_edges(True, True, True, False) >>> fr = FlowRouter(mg) >>> runoff_rate = np.arange(mg.number_of_nodes) >>> _ = mg.add_field('node', 'water__unit_flux_in', runoff_rate, ... noclobber=False) >>> mg = fr.route_flow() >>> mg.at_node['surface_water__discharge'] # doctest: +NORMALIZE_WHITESPACE array([ 0., 500., 5200., 0., 0., 500., 5200., 0., 0., 900., 3700., 0., 0., 1300., 1400., 0., 0., 0., 0., 0.]) """ # this retained for back compatibility - method now set in __init__. if 'method' in kwds: warnings.warn("'method' should be set at initialization now. " + "Please update your code.", DeprecationWarning) # raise NameError if kwds['method'] not in ('D8', 'D4'): raise ValueError('method not understood ({method})'.format( method=method)) else: self.method = kwds['method'] if not self._is_raster: self.method = None if self._bc_set_code != self.grid.bc_set_code: self.updated_boundary_conditions() self._bc_set_code = self.grid.bc_set_code # We assume that elevations are provided in a field called # 'topographic__elevation' elevs = self._grid['node']['topographic__elevation'] node_cell_area = self._grid.cell_area_at_node.copy() node_cell_area[self._grid.closed_boundary_nodes] = 0. # closed cells can't contribute # Calculate the downhill-positive slopes at the d8 active links if self.method == 'D8': link_slope = - self._grid._calculate_gradients_at_d8_active_links( elevs) else: link_slope = - self._grid.calc_grad_of_active_link( elevs) # Find the baselevel nodes (baselevel_nodes, ) = numpy.where( numpy.logical_or(self._grid.status_at_node == FIXED_VALUE_BOUNDARY, self._grid.status_at_node == FIXED_GRADIENT_BOUNDARY)) # Calculate flow directions if self.method == 'D4': num_d4_active = self._grid.number_of_active_links # only d4 receiver, steepest_slope, sink, recvr_link = \ flow_direction_DN.flow_directions(elevs, self._active_links, self._activelink_tail[:num_d4_active], self._activelink_head[:num_d4_active], link_slope, grid=self._grid, baselevel_nodes=baselevel_nodes) else: # Voronoi or D8 receiver, steepest_slope, sink, recvr_link = \ flow_direction_DN.flow_directions(elevs, self._active_links, self._activelink_tail, self._activelink_head, link_slope, grid=self._grid, baselevel_nodes=baselevel_nodes) # TODO: either need a way to calculate and return the *length* of the # flow links, OR the caller has to handle the raster / non-raster case. # Calculate drainage area, discharge, and ... a, q, s = flow_accum_bw.flow_accumulation( receiver, sink, node_cell_area=node_cell_area, runoff_rate=self._grid.at_node['water__unit_flux_in']) # added DEJH March 2014: # store the generated data in the grid self._grid['node']['drainage_area'][:] = a self._grid['node']['flow__receiver_node'][:] = receiver self._grid['node']['topographic__steepest_slope'][:] = steepest_slope self._grid['node']['surface_water__discharge'][:] = q self._grid['node']['flow__upstream_node_order'][:] = s self._grid['node']['flow__link_to_receiver_node'][:] = recvr_link self._grid['node']['flow__sink_flag'][:] = numpy.zeros_like(receiver, dtype=bool) self._grid['node']['flow__sink_flag'][sink] = True return self._grid
def route_flow(self): """ Routes surface-water flow by (1) assigning to each node a single drainage direction, and then (2) adding up the number of nodes that contribute flow to each node on the grid (including the node itself). Stores as ModelGrid fields: - Node array of receivers (nodes that receive flow): *'flow_receiver'* - Node array of drainage areas: *'drainage_area'* - Node array of discharges: *'water__volume_flux'* - Node array of steepest downhill slopes: *'topographic__steepest_slope'* - Node array containing downstream-to-upstream ordered list of node IDs: *'upstream_ID_order'* - Node array containing ID of link that leads from each node to its receiver (or ITS OWN ID if there is no receiver): *'links_to_flow_receiver'* - Boolean node array of all local lows: *'flow_sinks'* Returns: - the modified grid object Examples -------- >>> import numpy as np >>> from landlab import RasterModelGrid >>> from landlab.components.flow_routing.route_flow_dn import FlowRouter >>> mg = RasterModelGrid(5, 4, 1.0) >>> elev = np.array([0., 0., 0., 0., ... 0., 21., 10., 0., ... 0., 31., 20., 0., ... 0., 32., 30., 0., ... 0., 0., 0., 0.]) >>> _ = mg.add_field('node','topographic__elevation', elev) >>> mg.set_closed_boundaries_at_grid_edges(False, True, True, True) >>> fr = FlowRouter(mg) >>> mg = fr.route_flow() >>> mg.at_node['flow_receiver'] array([ 0, 1, 2, 3, 4, 1, 2, 7, 8, 6, 6, 11, 12, 10, 10, 15, 16, 17, 18, 19]) >>> mg.at_node['drainage_area'] array([ 1., 2., 6., 1., 1., 1., 5., 1., 1., 1., 3., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) Now let's change the cell area and the runoff rates: >>> mg = RasterModelGrid(5, 4, 10.) #so cell area==100. >>> _ = mg.add_field('node','topographic__elevation', elev) #put the data back into the new grid >>> mg.set_closed_boundaries_at_grid_edges(False, True, True, True) >>> fr = FlowRouter(mg) >>> runoff_rate = np.arange(mg.number_of_nodes) >>> _ = mg.add_field('node', 'water__volume_flux_in', runoff_rate) >>> mg = fr.route_flow() >>> mg.at_node['water__volume_flux'] array([ 0., 600., 5400., 300., 400., 500., 5200., 700., 800., 900., 3700., 1100., 1200., 1300., 1400., 1500., 1600., 1700., 1800., 1900.]) """ #if elevs is not provided, default to stored grid values, which must be provided as grid elevs = self._grid['node'][self.value_field] node_cell_area = self._grid.forced_cell_areas # Calculate the downhill-positive slopes at the d8 active links #TODO: generalize to use EITHER D8, if raster, or just active links, # otherwise. link_slope = -self._grid.calculate_gradients_at_d8_active_links(elevs) # Find the baselevel nodes (baselevel_nodes, ) = numpy.where(numpy.logical_or(self._grid.node_status==1, self._grid.node_status==2)) # Calculate flow directions receiver, steepest_slope, sink, recvr_link = \ flow_direction_DN.flow_directions(elevs, self._active_links, self._activelink_from, self._activelink_to, link_slope, grid=self._grid, baselevel_nodes=baselevel_nodes) #############grid=None??? # TODO: either need a way to calculate and return the *length* of the # flow links, OR the caller has to handle the raster / non-raster case. #print 'sinks:', sink # Calculate drainage area, discharge, and ... a, q, s = flow_accum_bw.flow_accumulation(receiver, sink, node_cell_area=node_cell_area, runoff_rate=self._grid.at_node['water__volume_flux_in']) #added DEJH March 2014: #store the generated data in the grid self._grid['node']['drainage_area'] = a self._grid['node']['flow_receiver'] = receiver self._grid['node']['topographic__steepest_slope'] = steepest_slope self._grid['node']['water__volume_flux'] = q self._grid['node']['upstream_ID_order'] = s self._grid['node']['links_to_flow_receiver'] = recvr_link self._grid['node']['flow_sinks'] = numpy.zeros_like(receiver, dtype=bool) self._grid['node']['flow_sinks'][sink] = True return self._grid
def route_flow(self, **kwds): """Route surface-water flow over a landscape. Routes surface-water flow by (1) assigning to each node a single drainage direction, and then (2) adding up the number of nodes that contribute flow to each node on the grid (including the node itself). Stores as ModelGrid fields: - Node array of receivers (nodes that receive flow), or ITS OWN ID if there is no receiver: *'flow_receiver'* - Node array of drainage areas: *'drainage_area'* - Node array of discharges: *'water__volume_flux'* - Node array of steepest downhill slopes: *'topographic__steepest_slope'* - Node array containing downstream-to-upstream ordered list of node IDs: *'upstream_node_order'* - Node array containing ID of link that leads from each node to its receiver, or BAD_INDEX_VALUE if no link: *'links_to_flow_receiver'* - Boolean node array of all local lows: *'flow_sinks'* Returns ------- ModelGrid The modified grid object Examples -------- >>> import numpy as np >>> from landlab import RasterModelGrid >>> from landlab.components.flow_routing import FlowRouter >>> mg = RasterModelGrid((5, 4), spacing=(1, 1)) >>> elev = np.array([0., 0., 0., 0., ... 0., 21., 10., 0., ... 0., 31., 20., 0., ... 0., 32., 30., 0., ... 0., 0., 0., 0.]) >>> _ = mg.add_field('node','topographic__elevation', elev) >>> mg.set_closed_boundaries_at_grid_edges(True, True, True, False) >>> fr = FlowRouter(mg) >>> mg = fr.route_flow() >>> mg.at_node['flow_receiver'] # doctest: +NORMALIZE_WHITESPACE array([ 0, 1, 2, 3, 4, 1, 2, 7, 8, 6, 6, 11, 12, 10, 10, 15, 16, 17, 18, 19]) >>> mg.at_node['drainage_area'] # doctest: +NORMALIZE_WHITESPACE array([ 0., 1., 5., 0., 0., 1., 5., 0., 0., 1., 3., 0., 0., 1., 1., 0., 0., 0., 0., 0.]) Now let's change the cell area (100.) and the runoff rates: >>> mg = RasterModelGrid((5, 4), spacing=(10., 10)) Put the data back into the new grid. >>> _ = mg.add_field('node','topographic__elevation', elev) >>> mg.set_closed_boundaries_at_grid_edges(True, True, True, False) >>> fr = FlowRouter(mg) >>> runoff_rate = np.arange(mg.number_of_nodes) >>> _ = mg.add_field('node', 'water__unit_flux_in', runoff_rate, ... noclobber=False) >>> mg = fr.route_flow() >>> mg.at_node['water__volume_flux'] # doctest: +NORMALIZE_WHITESPACE array([ 0., 500., 5200., 0., 0., 500., 5200., 0., 0., 900., 3700., 0., 0., 1300., 1400., 0., 0., 0., 0., 0.]) """ # this retained for back compatibility - method now set in __init__. if 'method' in kwds: warnings.warn( "'method' should be set at initialization now. " + "Please update your code.", DeprecationWarning) # raise NameError if kwds['method'] not in ('D8', 'D4'): raise ValueError( 'method not understood ({method})'.format(method=method)) else: self.method = kwds['method'] if not self._is_raster: self.method = None # if elevs is not provided, default to stored grid values, which must # be provided as grid elevs = self._grid['node']['topographic__elevation'] node_cell_area = self._grid.cell_area_at_node.copy() node_cell_area[self._grid.closed_boundary_nodes] = 0. # closed cells can't contribute # Calculate the downhill-positive slopes at the d8 active links if self.method == 'D8': link_slope = -self._grid.calculate_gradients_at_d8_active_links( elevs) else: link_slope = -self._grid.calculate_gradients_at_active_links(elevs) # Find the baselevel nodes (baselevel_nodes, ) = numpy.where( numpy.logical_or(self._grid.status_at_node == 1, self._grid.status_at_node == 2)) # Calculate flow directions if self.method == 'D4': num_d4_active = self._grid.number_of_active_links # only d4 receiver, steepest_slope, sink, recvr_link = \ flow_direction_DN.flow_directions(elevs, self._active_links, self._activelink_from[:num_d4_active], self._activelink_to[:num_d4_active], link_slope, grid=self._grid, baselevel_nodes=baselevel_nodes) else: # Voronoi or D8 receiver, steepest_slope, sink, recvr_link = \ flow_direction_DN.flow_directions(elevs, self._active_links, self._activelink_from, self._activelink_to, link_slope, grid=self._grid, baselevel_nodes=baselevel_nodes) # TODO: either need a way to calculate and return the *length* of the # flow links, OR the caller has to handle the raster / non-raster case. # Calculate drainage area, discharge, and ... a, q, s = flow_accum_bw.flow_accumulation( receiver, sink, node_cell_area=node_cell_area, runoff_rate=self._grid.at_node['water__unit_flux_in']) # added DEJH March 2014: # store the generated data in the grid self._grid['node']['drainage_area'][:] = a self._grid['node']['flow_receiver'][:] = receiver self._grid['node']['topographic__steepest_slope'][:] = steepest_slope self._grid['node']['water__volume_flux'][:] = q self._grid['node']['upstream_node_order'][:] = s self._grid['node']['links_to_flow_receiver'][:] = recvr_link self._grid['node']['flow_sinks'][:] = numpy.zeros_like(receiver, dtype=bool) self._grid['node']['flow_sinks'][sink] = True return self._grid
def route_flow(self, elevs=None, grid=None, node_cell_area=1.0, runoff_rate=1.0, boundary_nodes=None): """ Routes surface-water flow by (1) assigning to each node a single drainage direction, and then (2) adding up the number of nodes that contribute flow to each node on the grid (including the node itself). If a scalar is specified for cell_area, computes the total surface contributing area by assuming that each cell has the same surface area. If an array is given (with length equal to the number of nodes), these areas are used for each cell. Likewise, runoff_rate, in length per time (volume per area per time) may be given either as a scalar (identical for each cell) or as an array whose length is the number of nodes in the grid. Takes: - Either *elevs*, an array of node elevations, or *grid*, a reference to a ModelGrid. Takes as optional inputs: - *node_cell_area*, a float of the cell areas, if a raster, or an array of the cell areas. - *runoff_rate*, a float (for constant rainfall) or array (for spatially variable rainfall) of runoff rates, such that drainage area is in volume, rather than number of upstream cells. Stores as ModelGrid fields, or returns, if *elevs* was provided rather than *grid*: - Node array of receivers (nodes that receive flow): *'flow_receiver'* - Node array of drainage areas: *'drainage_area'* - Node array of discharges: *'water_discharges'* - Node array of steepest downhill slopes: *'steepest_slope'* - Node array containing downstream-to-upstream ordered list of node IDs: *'upstream_ID_order'* - Node array containing ID of link that leads from each node to its receiver (or UNDEFINED_INDEX if there is no receiver): *'links_to_flow_receiver'* Returns, if *grid* was provided: - the modified grid object Example: >>> from landlab import RasterModelGrid >>> mg = RasterModelGrid(5, 4, 1.0) >>> elev = numpy.array([0., 0., 0., 0., ... 0., 21., 10., 0., ... 0., 31., 20., 0., ... 0., 32., 30., 0., ... 0., 0., 0., 0.]) >>> mg.set_inactive_boundaries(False, True, True, True) >>> fr = FlowRouter(mg) >>> r, a, q, ss, s, rl = fr.route_flow(elevs=elev) >>> r array([ 0, 1, 2, 3, 4, 1, 2, 7, 8, 6, 6, 11, 12, 10, 10, 15, 16, 17, 18, 19]) >>> a array([ 1., 2., 6., 1., 1., 1., 5., 1., 1., 1., 3., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) >>> r, a, q, ss, s, rl = fr.route_flow(elevs=elev, node_cell_area=10.0) >>> a array([ 10., 20., 60., 10., 10., 10., 50., 10., 10., 10., 30., 10., 10., 10., 10., 10., 10., 10., 10., 10.]) >>> cell_areas = 10.0 + numpy.arange(mg.number_of_nodes) >>> r, a, q, ss, s, rl = fr.route_flow(elevs=elev, node_cell_area=cell_areas) >>> a array([ 10., 26., 114., 13., 14., 15., 102., 17., 18., 19., 67., 21., 22., 23., 24., 25., 26., 27., 28., 29.]) >>> runoff_rate = numpy.arange(mg.number_of_nodes) >>> r, a, q, ss, s, rl = fr.route_flow(elevs=elev, node_cell_area=100.0, runoff_rate=runoff_rate) >>> q array([ 0., 600., 5400., 300., 400., 500., 5200., 700., 800., 900., 3700., 1100., 1200., 1300., 1400., 1500., 1600., 1700., 1800., 1900.]) >>> r, a, q, ss, s, rl = fr.route_flow(elevs=elev, node_cell_area=cell_areas, runoff_rate=runoff_rate) >>> q array([ 0., 86., 1126., 39., 56., 75., 1102., 119., 144., 171., 835., 231., 264., 299., 336., 375., 416., 459., 504., 551.]) """ #if elevs is not provided, default to stored grid values, which must be provided as grid if elevs is None: if grid is not None: self._grid = grid elevs = grid['node'][self.value_field] else: raise ValueError('Either an elevation array or a copy of the grid must be provided!') try: node_cell_area = self._grid.forced_cell_areas except: pass # Calculate the downhill-positive slopes at the d8 active links #TODO: generalize to use EITHER D8, if raster, or just active links, # otherwise. link_slope = -self._grid.calculate_gradients_at_d8_active_links(elevs) # Find the baselevel nodes (baselevel_nodes, ) = numpy.where( self._grid.node_status==1 ) # Calculate flow directions receiver, steepest_slope, sink, recvr_link = \ flow_direction_DN.flow_directions(elevs, self._active_links, self._activelink_from, self._activelink_to, link_slope, grid=grid, baselevel_nodes=baselevel_nodes) #############grid=None??? # TODO: either need a way to calculate and return the *length* of the # flow links, OR the caller has to handle the raster / non-raster case. #print 'sinks:', sink # Calculate drainage area, discharge, and ... a, q, s = flow_accum_bw.flow_accumulation(receiver, sink, node_cell_area, runoff_rate, boundary_nodes) #added DEJH March 2014: #store the generated data in the grid self._grid['node']['drainage_area'] = a self._grid['node']['flow_receiver'] = receiver self._grid['node']['steepest_slope'] = steepest_slope self._grid['node']['water_discharges'] = q self._grid['node']['upstream_ID_order'] = s self._grid['node']['links_to_flow_receiver'] = recvr_link if grid: return self._grid else: return receiver, a, q, steepest_slope, s, recvr_link
def route_flow(self, method='D8'): """Route surface-water flow over a landscape. Routes surface-water flow by (1) assigning to each node a single drainage direction, and then (2) adding up the number of nodes that contribute flow to each node on the grid (including the node itself). Stores as ModelGrid fields: - Node array of receivers (nodes that receive flow): *'flow_receiver'* - Node array of drainage areas: *'drainage_area'* - Node array of discharges: *'water__volume_flux'* - Node array of steepest downhill slopes: *'topographic__steepest_slope'* - Node array containing downstream-to-upstream ordered list of node IDs: *'upstream_node_order'* - Node array containing ID of link that leads from each node to its receiver (or ITS OWN ID if there is no receiver): *'links_to_flow_receiver'* - Boolean node array of all local lows: *'flow_sinks'* Parameters ---------- method : {'D8', 'D4'}, optional Routing method ('D8' is the default). This keyword has no effect for a Voronoi-based grid. Returns ------- ModelGrid The modified grid object Examples -------- >>> import numpy as np >>> from landlab import RasterModelGrid >>> from landlab.components.flow_routing.route_flow_dn import FlowRouter >>> mg = RasterModelGrid((5, 4), spacing=(1, 1)) >>> elev = np.array([0., 0., 0., 0., ... 0., 21., 10., 0., ... 0., 31., 20., 0., ... 0., 32., 30., 0., ... 0., 0., 0., 0.]) >>> _ = mg.add_field('node','topographic__elevation', elev) >>> mg.set_closed_boundaries_at_grid_edges(False, True, True, True) >>> fr = FlowRouter(mg) >>> mg = fr.route_flow() >>> mg.at_node['flow_receiver'] # doctest: +NORMALIZE_WHITESPACE array([ 0, 1, 2, 3, 4, 1, 2, 7, 8, 6, 6, 11, 12, 10, 10, 15, 16, 17, 18, 19]) >>> mg.at_node['drainage_area'] # doctest: +NORMALIZE_WHITESPACE array([ 0., 1., 5., 0., 0., 1., 5., 0., 0., 1., 3., 0., 0., 1., 1., 0., 0., 0., 0., 0.]) Now let's change the cell area (100.) and the runoff rates: >>> mg = RasterModelGrid((5, 4), spacing=(10., 10)) Put the data back into the new grid. >>> _ = mg.add_field('node','topographic__elevation', elev) >>> mg.set_closed_boundaries_at_grid_edges(False, True, True, True) >>> fr = FlowRouter(mg) >>> runoff_rate = np.arange(mg.number_of_nodes) >>> _ = mg.add_field('node', 'water__volume_flux_in', runoff_rate) >>> mg = fr.route_flow() >>> mg.at_node['water__volume_flux'] # doctest: +NORMALIZE_WHITESPACE array([ 0., 500., 5200., 0., 0., 500., 5200., 0., 0., 900., 3700., 0., 0., 1300., 1400., 0., 0., 0., 0., 0.]) """ if method not in ('D8', 'D4'): raise ValueError('method not understood ({method})'.format( method=method)) if not self._is_raster: method = None # if elevs is not provided, default to stored grid values, which must # be provided as grid elevs = self._grid['node'][self.value_field] node_cell_area = self._grid.cell_area_at_node.copy() node_cell_area[self._grid.closed_boundary_nodes] = 0. # closed cells can't contribute # Calculate the downhill-positive slopes at the d8 active links if method == 'D8': link_slope = - self._grid.calculate_gradients_at_d8_active_links( elevs) else: link_slope = - self._grid.calculate_gradients_at_active_links( elevs) # Find the baselevel nodes (baselevel_nodes, ) = numpy.where( numpy.logical_or(self._grid.status_at_node == 1, self._grid.status_at_node == 2)) # Calculate flow directions if method == 'D4': num_d4_active = self._grid.number_of_active_links # only d4 receiver, steepest_slope, sink, recvr_link = \ flow_direction_DN.flow_directions(elevs, self._active_links, self._activelink_from[:num_d4_active], self._activelink_to[:num_d4_active], link_slope, grid=self._grid, baselevel_nodes=baselevel_nodes) else: # Voronoi or D8 receiver, steepest_slope, sink, recvr_link = \ flow_direction_DN.flow_directions(elevs, self._active_links, self._activelink_from, self._activelink_to, link_slope, grid=self._grid, baselevel_nodes=baselevel_nodes) #############grid=None??? # TODO: either need a way to calculate and return the *length* of the # flow links, OR the caller has to handle the raster / non-raster case. #print 'sinks:', sink # Calculate drainage area, discharge, and ... a, q, s = flow_accum_bw.flow_accumulation( receiver, sink, node_cell_area=node_cell_area, runoff_rate=self._grid.at_node['water__volume_flux_in']) #added DEJH March 2014: #store the generated data in the grid self._grid['node']['drainage_area'] = a self._grid['node']['flow_receiver'] = receiver self._grid['node']['topographic__steepest_slope'] = steepest_slope self._grid['node']['water__volume_flux'] = q self._grid['node']['upstream_node_order'] = s self._grid['node']['links_to_flow_receiver'] = recvr_link self._grid['node']['flow_sinks'] = numpy.zeros_like(receiver, dtype=bool) self._grid['node']['flow_sinks'][sink] = True return self._grid