示例#1
0
    def phase_lagrange_matrices(self, given_set_name, eval_set_name, sparse=False):
        """
        Compute the matrices mapping values at some nodes to values and derivatives at new nodes.

        Parameters
        ----------
        given_set_name : str
            Name of the set of nodes with which to perform the interpolation.
        eval_set_name : str
            Name of the set of nodes at which to evaluate the values and derivatives.
        sparse : bool
            If True, the returned matrix will be in scipy CSR sparse format.  Otherwise, it is
            returned as a dense numpy.array.

        Returns
        -------
        ndarray[num_eval_set, num_given_set]
            Matrix containing the values at the new nodes.
        ndarray[num_eval_set, num_given_set]
            Matrix containing the time derivatives at the new nodes.

        Notes
        -----
        The values are mapped using the equation:

        .. math::

            x_{eval} = \\left[ L \\right] x_{given}

        And the derivatives are mapped with the equation:

        .. math::

            \\dot{x}_{eval} = \\left[ D \\right] x_{given} \\frac{d \\tau}{dt}
        """
        L_blocks = []
        D_blocks = []

        for iseg in range(self.num_segments):
            i1, i2 = self.subset_segment_indices[given_set_name][iseg, :]
            indices = self.subset_node_indices[given_set_name][i1:i2]
            nodes_given = self.node_stau[indices]

            i1, i2 = self.subset_segment_indices[eval_set_name][iseg, :]
            indices = self.subset_node_indices[eval_set_name][i1:i2]
            nodes_eval = self.node_stau[indices]

            L_block, D_block = lagrange_matrices(nodes_given, nodes_eval)

            L_blocks.append(L_block)
            D_blocks.append(D_block)

        L = block_diag(*L_blocks)
        D = block_diag(*D_blocks)

        if sparse:
            L = sp.csr_matrix(L)
            D = sp.csr_matrix(D)

        return L, D
示例#2
0
    def setup(self):
        """
        Define the independent variables as output variables.
        """
        igd = self.options['input_grid_data']
        ogd = self.options['output_grid_data']
        output_subset = self.options['output_subset']

        if ogd is None:
            ogd = igd

        self.input_num_nodes = igd.num_nodes
        self.output_num_nodes = ogd.subset_num_nodes[output_subset]

        # Build the interpolation matrix which maps from the input grid to the output grid.
        # Rather than a single phase-wide interpolating polynomial, map each segment.
        # To do this, find the nodes in the output grid which fall in each segment of the input
        # grid.  Then build a Lagrange interpolating polynomial for that segment
        L_blocks = []
        output_nodes_ptau = ogd.node_ptau[
            ogd.subset_node_indices[output_subset]].tolist()

        for iseg in range(igd.num_segments):
            i1, i2 = igd.segment_indices[iseg]
            iptau_segi = igd.node_ptau[i1:i2]
            istau_segi = igd.node_stau[i1:i2]

            # The indices of the output grid that fall within this segment of the input grid
            if ogd is igd:
                optau_segi = iptau_segi
            else:
                ptau_hi = igd.segment_ends[iseg + 1]
                if iseg < igd.num_segments - 1:
                    idxs_in_iseg = np.where(output_nodes_ptau <= ptau_hi)[0]
                else:
                    idxs_in_iseg = np.arange(len(output_nodes_ptau))
                optau_segi = np.asarray(output_nodes_ptau)[idxs_in_iseg]
                # Remove the captured nodes so we don't accidentally include them again
                output_nodes_ptau = output_nodes_ptau[len(idxs_in_iseg):]

            # # Now get the output nodes which fall in iseg in iseg's segment tau space.
            ostau_segi = 2.0 * (optau_segi - iptau_segi[0]) / (
                iptau_segi[-1] - iptau_segi[0]) - 1

            # Create the interpolation matrix and add it to the blocks
            L, _ = lagrange_matrices(istau_segi, ostau_segi)
            L_blocks.append(L)

        self.interpolation_matrix = block_diag(*L_blocks)

        for (name, kwargs) in self._timeseries_outputs:
            units = kwargs['units']
            desc = kwargs['units']
            shape = kwargs['shape']
            self._add_output_configure(name, units, shape, desc)
示例#3
0
    def phase_lagrange_matrices(self, given_set_name, eval_set_name):
        """
        Compute the matrices mapping values at some nodes to values and derivatives at new nodes.

        Parameters
        ----------
        given_set_name : str
            Name of the set of nodes with which to perform the interpolation.
        eval_set_name : str
            Name of the set of nodes at which to evaluate the values and derivatives.

        Returns
        -------
        ndarray[num_eval_set, num_given_set]
            Matrix that yields the values at the new nodes.
        ndarray[num_eval_set, num_given_set]
            Matrix that yields the time derivatives at the new nodes.

        Notes
        -----
        The values are mapped using the equation:

        .. math::

            x_{eval} = \\left[ L \\right] x_{given}

        And the derivatives are mapped with the equation:

        .. math::

            \\dot{x}_{eval} = \\left[ D \\right] x_{given} \\frac{d \\tau}{dt}

        """
        L_blocks = []
        D_blocks = []

        for iseg in range(self.num_segments):
            i1, i2 = self.subset_segment_indices[given_set_name][iseg, :]
            indices = self.subset_node_indices[given_set_name][i1:i2]
            nodes_given = self.node_stau[indices]

            i1, i2 = self.subset_segment_indices[eval_set_name][iseg, :]
            indices = self.subset_node_indices[eval_set_name][i1:i2]
            nodes_eval = self.node_stau[indices]

            L_block, D_block = lagrange_matrices(nodes_given, nodes_eval)

            L_blocks.append(L_block)
            D_blocks.append(D_block)

        L = block_diag(*L_blocks)
        D = block_diag(*D_blocks)

        return L, D
示例#4
0
                 axes[0],
                 color='b',
                 scale=.25)
    plot_tangent(time[state_disc_idxs],
                 vy[state_disc_idxs],
                 vydot[state_disc_idxs],
                 axes[1],
                 color='b',
                 scale=.25)

    if i == 0:
        plt.savefig('lgr_animation_1.png')

    # Plot the interpolating polynomials
    t_dense = np.linspace(time[0], time[-1], 100)
    L, D = lagrange_matrices(time[state_disc_idxs], t_dense)
    y_dense = L.dot(y[state_disc_idxs])
    vy_dense = L.dot(vy[state_disc_idxs])

    axes[0].plot(t_dense, y_dense, ms=None, ls=':')
    axes[1].plot(t_dense, vy_dense, ms=None, ls=':')

    if i == 0:
        plt.savefig('lgr_animation_2.png')

    # # Plot the values and rates at the collocation nodes
    # tau_s, _ = lgr(3, include_endpoint=True)
    # tau_disc = tau_s
    # tau_col = tau_s[:-1]
    # L, D = lagrange_matrices(tau_disc, tau_col)
    #
示例#5
0
    def setup(self):
        """
        Define the independent variables as output variables.
        """
        igd = self.options['input_grid_data']
        ogd = self.options['output_grid_data']
        output_subset = self.options['output_subset']

        if ogd is None:
            ogd = igd

        input_num_nodes = igd.num_nodes
        output_num_nodes = ogd.subset_num_nodes[output_subset]

        # Build the interpolation matrix which maps from the input grid to the output grid.
        # Rather than a single phase-wide interpolating polynomial, map each segment.
        # To do this, find the nodes in the output grid which fall in each segment of the input
        # grid.  Then build a Lagrange interpolating polynomial for that segment
        L_blocks = []
        output_nodes_ptau = ogd.node_ptau[ogd.subset_node_indices[output_subset]].tolist()

        for iseg in range(igd.num_segments):
            i1, i2 = igd.segment_indices[iseg]
            iptau_segi = igd.node_ptau[i1:i2]
            istau_segi = igd.node_stau[i1:i2]

            # The indices of the output grid that fall within this segment of the input grid
            if ogd is igd:
                optau_segi = iptau_segi
            else:
                ptau_hi = igd.segment_ends[iseg+1]
                if iseg < igd.num_segments - 1:
                    idxs_in_iseg = np.where(output_nodes_ptau <= ptau_hi)[0]
                else:
                    idxs_in_iseg = np.arange(len(output_nodes_ptau))
                optau_segi = np.asarray(output_nodes_ptau)[idxs_in_iseg]
                # Remove the captured nodes so we don't accidentally include them again
                output_nodes_ptau = output_nodes_ptau[len(idxs_in_iseg):]

            # # Now get the output nodes which fall in iseg in iseg's segment tau space.
            ostau_segi = 2.0 * (optau_segi - iptau_segi[0]) / (iptau_segi[-1] - iptau_segi[0]) - 1

            # Create the interpolation matrix and add it to the blocks
            L, _ = lagrange_matrices(istau_segi, ostau_segi)
            L_blocks.append(L)

        self.interpolation_matrix = block_diag(*L_blocks)

        for (name, kwargs) in self._timeseries_outputs:
            input_kwargs = {k: kwargs[k] for k in ('units', 'desc')}
            input_name = 'input_values:{0}'.format(name)
            shape = kwargs['shape']

            self.add_input(input_name,
                           shape=(input_num_nodes,) + shape,
                           **input_kwargs)

            output_name = name
            output_kwargs = {k: kwargs[k] for k in ('units', 'desc')}
            output_kwargs['shape'] = (output_num_nodes,) + kwargs['shape']
            self.add_output(output_name, **output_kwargs)

            self._vars.append((input_name, output_name, shape))

            size = np.prod(shape)
            val_jac = np.zeros((output_num_nodes, size, input_num_nodes, size))

            for i in range(size):
                val_jac[:, i, :, i] = self.interpolation_matrix

            val_jac = val_jac.reshape((output_num_nodes * size, input_num_nodes * size),
                                      order='C')

            val_jac_rows, val_jac_cols = np.where(val_jac != 0)

            rs, cs = val_jac_rows, val_jac_cols
            self.declare_partials(of=output_name,
                                  wrt=input_name,
                                  rows=rs, cols=cs, val=val_jac[rs, cs])