Ejemplo n.º 1
0
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",
        )
Ejemplo n.º 2
0
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",
        )
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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)