def test_bad_argument_mfd(): mg = RasterModelGrid((5, 5), spacing=(1, 1)) z = mg.add_field("topographic__elevation", mg.node_x + mg.node_y, at="node") neighbors_at_node = mg.adjacent_nodes_at_node links_at_node = mg.links_at_node active_link_dir_at_node = mg.active_link_dirs_at_node link_slope = np.arctan(mg.calc_grad_at_link(z)) slopes_to_neighbors_at_node = link_slope[links_at_node] * active_link_dir_at_node with pytest.raises(ValueError): flow_direction_mfd.flow_directions_mfd( z, neighbors_at_node, links_at_node, active_link_dir_at_node, link_slope, partition_method="foo", )
def test_bad_argument_mfd(): mg = RasterModelGrid((5, 5), xy_spacing=(1, 1)) z = mg.add_field("topographic__elevation", mg.node_x + mg.node_y, at="node") neighbors_at_node = mg.adjacent_nodes_at_node links_at_node = mg.links_at_node active_link_dir_at_node = mg.active_link_dirs_at_node link_slope = np.arctan(mg.calc_grad_at_link(z)) link_slope[links_at_node] * active_link_dir_at_node with pytest.raises(ValueError): flow_direction_mfd.flow_directions_mfd( z, neighbors_at_node, links_at_node, active_link_dir_at_node, link_slope, partition_method="foo", )
def direct_flow(self): """ Find flow directions, save to the model grid, and return receivers. direct_flow() checks for updated boundary conditions, calculates slopes on links, finds basself.surface_valuesel nodes based on the status at node, calculates flow directions, saves results to the grid, and returns a at-node array of receiver nodes. This array is stored in the grid at: grid['node']['flow__receiver_nodes'] An alternative to direct_flow() is run_one_step() which does the same things but also returns a at-node array of receiver nodes. This array is stored in the grid at: grid['node']['flow__receiver_nodes'] """ # step 0. Check and update BCs if self._bc_set_code != self.grid.bc_set_code: self.updated_boundary_conditions() self._bc_set_code = self.grid.bc_set_code # step 1. Required inumpyuts for flow_directions_MFD # this is where diagonals are or are not included in # flow direction calculations # Option for no diagonals (default) if self.diagonals == False: neighbors_at_node = self.grid.adjacent_nodes_at_node links_at_node = self.grid.links_at_node active_link_dir_at_node = self.grid.active_link_dirs_at_node # this needs to be the gradient link_slope = self.grid.calc_grad_at_link(self.surface_values) # Option with diagonals. else: # need to create a list of diagonal links since it doesn't exist. diag_links = numpy.sort(numpy.unique(self.grid.d8s_at_node[:, 4:])) diag_links = diag_links[diag_links > 0] # get diagonal active links (though this actually includes ALL # active links) dal = self.grid.active_d8 # calculate graidents across diagonals diag_grads = numpy.zeros(diag_links.shape) where_active_diag = dal >= diag_links.min() active_diags_inds = dal[where_active_diag] - diag_links.min() active_diag_grads = self.grid._calculate_gradients_at_d8_active_links( self.surface_values) diag_grads[active_diags_inds] = active_diag_grads[ where_active_diag] # calculate gradients on orthogonal links ortho_grads = self.grid.calc_grad_at_link(self.surface_values) # concatenate the diagonal and orthogonal grid elements neighbors_at_node = numpy.hstack( (self.grid.adjacent_nodes_at_node, self.grid.diagonal_adjacent_nodes_at_node)) active_link_dir_at_node = numpy.hstack( (self.grid.active_link_dirs_at_node, self.grid.active_diagonal_dirs_at_node)) link_slope = numpy.hstack((ortho_grads, diag_grads)) links_at_node = self.grid.d8s_at_node # Step 2. Find and save base level 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 (self.receivers, self.proportions, steepest_slope, steepest_receiver, sink, receiver_links, steepest_link) = \ flow_direction_mfd.flow_directions_mfd(self.surface_values, neighbors_at_node, links_at_node, active_link_dir_at_node, link_slope, baselevel_nodes=baselevel_nodes, partition_method=self.partition_method) # Save the four ouputs of this component. self._grid['node']['flow__receiver_nodes'][:] = self.receivers self._grid['node']['flow__receiver_node'][:] = steepest_receiver self._grid['node']['flow__receiver_proportions'][:] = self.proportions self._grid['node']['topographic__steepest_slope'][:] = steepest_slope self._grid['node']['flow__link_to_receiver_node'][:] = steepest_link self._grid['node']['flow__links_to_receiver_nodes'][:] = receiver_links self._grid['node']['flow__sink_flag'][:] = numpy.zeros_like( steepest_link, dtype=bool) self._grid['node']['flow__sink_flag'][sink] = True return (self.receivers, self.proportions)
def direct_flow(self): """Find flow directions, save to the model grid, and return receivers. direct_flow() checks for updated boundary conditions, calculates slopes on links, finds basself._surface_valuesel nodes based on the status at node, calculates flow directions, saves results to the grid, and returns a at-node array of receiver nodes. This array is stored in the grid at: grid['node']['flow__receiver_nodes'] An alternative to direct_flow() is run_one_step() which does the same things but also returns a at-node array of receiver nodes. This array is stored in the grid at: grid['node']['flow__receiver_nodes'] """ self._check_updated_bc() # step 1. Required inumpyuts for flow_directions_MFD # this is where diagonals are or are not included in # flow direction calculations # Option for no diagonals (default) if self._diagonals is False: neighbors_at_node = self._grid.adjacent_nodes_at_node links_at_node = self._grid.links_at_node active_link_dir_at_node = self._grid.active_link_dirs_at_node # this needs to be the gradient link_slope = self._grid.calc_grad_at_link(self._surface_values) # Option with diagonals. else: # concatenate the diagonal and orthogonal grid elements neighbors_at_node = numpy.hstack(( self._grid.adjacent_nodes_at_node, self._grid.diagonal_adjacent_nodes_at_node, )) active_link_dir_at_node = numpy.hstack(( self._grid.active_link_dirs_at_node, self._grid.active_diagonal_dirs_at_node, )) link_slope = self._grid.calc_grad_at_d8(self._surface_values) links_at_node = self._grid.d8s_at_node # Step 2. Find and save base level nodes. (baselevel_nodes, ) = numpy.where( numpy.logical_or( self._grid.status_at_node == NodeStatus.FIXED_VALUE, self._grid.status_at_node == NodeStatus.FIXED_GRADIENT, )) # Calculate flow directions ( self._receivers, self._proportions, slopes_to_receivers, steepest_slope, steepest_receiver, sink, receiver_links, steepest_link, ) = flow_direction_mfd.flow_directions_mfd( self._surface_values, neighbors_at_node, links_at_node, active_link_dir_at_node, link_slope, baselevel_nodes=baselevel_nodes, partition_method=self._partition_method, ) # Save the four ouputs of this component. self._grid["node"]["flow__receiver_node"][:] = self._receivers self._grid["node"]["flow__receiver_proportions"][:] = self._proportions self._grid["node"][ "topographic__steepest_slope"][:] = slopes_to_receivers self._grid["node"]["flow__link_to_receiver_node"][:] = receiver_links self._grid["node"]["flow__sink_flag"][:] = False self._grid["node"]["flow__sink_flag"][sink] = True return (self._receivers, self._proportions)
def direct_flow(self): """ Find flow directions, save to the model grid, and return receivers. direct_flow() checks for updated boundary conditions, calculates slopes on links, finds basself.surface_valuesel nodes based on the status at node, calculates flow directions, saves results to the grid, and returns a at-node array of receiver nodes. This array is stored in the grid at: grid['node']['flow__receiver_nodes'] An alternative to direct_flow() is run_one_step() which does the same things but also returns a at-node array of receiver nodes. This array is stored in the grid at: grid['node']['flow__receiver_nodes'] """ # step 0. Check and update BCs if self._bc_set_code != self.grid.bc_set_code: self.updated_boundary_conditions() self._bc_set_code = self.grid.bc_set_code # step 1. Required inumpyuts for flow_directions_MFD # this is where diagonals are or are not included in # flow direction calculations # Option for no diagonals (default) if self.diagonals == False: neighbors_at_node = self.grid.adjacent_nodes_at_node links_at_node = self.grid.links_at_node active_link_dir_at_node = self.grid.active_link_dirs_at_node # this needs to be the gradient link_slope = self.grid.calc_grad_at_link(self.surface_values) # Option with diagonals. else: # need to create a list of diagonal links since it doesn't exist. diag_links = numpy.sort(numpy.unique(self.grid.d8s_at_node[:, 4:])) diag_links = diag_links[diag_links > 0] # get diagonal active links (though this actually includes ALL # active links) dal = self.grid.active_d8 # calculate graidents across diagonals diag_grads = numpy.zeros(diag_links.shape) where_active_diag = dal >= diag_links.min() active_diags_inds = dal[where_active_diag]-diag_links.min() active_diag_grads = self.grid._calculate_gradients_at_d8_active_links(self.surface_values) diag_grads[active_diags_inds] = active_diag_grads[where_active_diag] # calculate gradients on orthogonal links ortho_grads = self.grid.calc_grad_at_link(self.surface_values) # concatenate the diagonal and orthogonal grid elements neighbors_at_node = numpy.hstack((self.grid.adjacent_nodes_at_node, self.grid.diagonal_adjacent_nodes_at_node)) active_link_dir_at_node = numpy.hstack((self.grid.active_link_dirs_at_node, self.grid.active_diagonal_dirs_at_node)) link_slope = numpy.hstack((ortho_grads, diag_grads)) links_at_node = self.grid.d8s_at_node # Step 2. Find and save base level 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 (self.receivers, self.proportions, steepest_slope, steepest_receiver, sink, receiver_links, steepest_link) = \ flow_direction_mfd.flow_directions_mfd(self.surface_values, neighbors_at_node, links_at_node, active_link_dir_at_node, link_slope, baselevel_nodes=baselevel_nodes, partition_method=self.partition_method) # Save the four ouputs of this component. self._grid['node']['flow__receiver_nodes'][:] = self.receivers self._grid['node']['flow__receiver_node'][:] = steepest_receiver self._grid['node']['flow__receiver_proportions'][:] = self.proportions self._grid['node']['topographic__steepest_slope'][:] = steepest_slope self._grid['node']['flow__link_to_receiver_node'][:] = steepest_link self._grid['node']['flow__links_to_receiver_nodes'][:] = receiver_links self._grid['node']['flow__sink_flag'][:] = numpy.zeros_like(steepest_link, dtype=bool) self._grid['node']['flow__sink_flag'][sink] = True return (self.receivers, self.proportions)