def _setup_controls(self):
        control_options = self.options['control_options']
        num_nodes_all = self.num_nodes_all
        num_nodes_output = self.num_nodes_output
        num_control_input_nodes = self.options['grid_data'].subset_num_nodes['control_input']
        time_units = self.options['time_units']

        for name, options in iteritems(control_options):
            self._input_names[name] = 'controls:{0}'.format(name)
            self._output_val_all_names[name] = 'control_values_all:{0}'.format(name)
            self._output_val_names[name] = 'control_values:{0}'.format(name)
            self._output_rate_names[name] = 'control_rates:{0}_rate'.format(name)
            self._output_rate2_names[name] = 'control_rates:{0}_rate2'.format(name)
            shape = options['shape']
            input_shape = (num_control_input_nodes,) + shape
            all_shape = (num_nodes_all,) + shape
            output_shape = (num_nodes_output,) + shape

            units = options['units']
            rate_units = get_rate_units(units, time_units)
            rate2_units = get_rate_units(units, time_units, deriv=2)

            self._dynamic_names.append(name)

            self.add_input(self._input_names[name], val=np.ones(input_shape), units=units)

            self.add_output(self._output_val_all_names[name], shape=all_shape, units=units)

            self.add_output(self._output_val_names[name], shape=output_shape, units=units)

            self.add_output(self._output_rate_names[name], shape=output_shape, units=rate_units)

            self.add_output(self._output_rate2_names[name], shape=output_shape,
                            units=rate2_units)
示例#2
0
文件: test_misc.py 项目: thearn/dymos
    def test_get_rate_units(self):
        rate_units = get_rate_units('m', 's', deriv=1)

        self.assertEqual(rate_units, 'm/s')

        rate2_units = get_rate_units('m', 's', deriv=2)

        self.assertEqual(rate2_units, 'm/s**2')
示例#3
0
    def configure_io(self):
        """
        Create inputs/outputs on this component.
        """
        state_options = self.options['state_options']
        time_units = self.options['time_units']

        for name, options in state_options.items():
            self._input_names[name] = f'state_rates_in:{name}_rate'
            self._output_names[name] = f'state_rates:{name}_rate'
            shape = options['shape']
            size = np.prod(shape, dtype=int)
            units = options['units']

            rate_units = get_rate_units(units, time_units)

            self.add_input(self._input_names[name],
                           shape=shape,
                           units=rate_units)
            self.add_output(self._output_names[name],
                            shape=shape,
                            units=rate_units)

            ar = np.arange(size, dtype=int)
            self.declare_partials(of=self._output_names[name],
                                  wrt=self._input_names[name],
                                  rows=ar,
                                  cols=ar,
                                  val=1.0)
    def setup(self):
        """
        Create inputs/outputs for this component.
        """
        time_units = self.options['time_units']

        self.add_input('time', val=1.0, units=time_units)

        for control_name, options in self.options['control_options'].items():
            shape = options['shape']
            units = options['units']
            rate_units = get_rate_units(units, time_units, deriv=1)
            rate2_units = get_rate_units(units, time_units, deriv=2)

            self.add_output('controls:{0}'.format(control_name),
                            shape=shape,
                            units=units)

            self.add_output('control_rates:{0}_rate'.format(control_name),
                            shape=shape,
                            units=rate_units)

            self.add_output('control_rates:{0}_rate2'.format(control_name),
                            shape=shape,
                            units=rate2_units)

        for control_name, options in self.options[
                'polynomial_control_options'].items():
            shape = options['shape']
            units = options['units']
            rate_units = get_rate_units(units, time_units, deriv=1)
            rate2_units = get_rate_units(units, time_units, deriv=2)

            self.add_output('polynomial_controls:{0}'.format(control_name),
                            shape=shape,
                            units=units)

            self.add_output(
                'polynomial_control_rates:{0}_rate'.format(control_name),
                shape=shape,
                units=rate_units)

            self.add_output(
                'polynomial_control_rates:{0}_rate2'.format(control_name),
                shape=shape,
                units=rate2_units)
示例#5
0
    def configure_io(self):
        """
        I/O creation is delayed until configure so that we can determine the shape and units for
        the states.
        """
        self._var_names = {}

        num_seg = self.options['num_segments']
        rk_data = rk_methods[self.options['method']]
        num_stages = rk_data['num_stages']

        self.add_input('h',
                       val=np.ones(num_seg),
                       units=self.options['time_units'],
                       desc='step size for current Runge-Kutta segment.')

        for name, options in self.options['state_options'].items():
            shape = options['shape']
            units = options['units']
            rate_units = get_rate_units(units, self.options['time_units'])

            self._var_names[name] = {}
            self._var_names[name]['f'] = 'f:{0}'.format(name)
            self._var_names[name]['k'] = 'k:{0}'.format(name)

            self.add_input(
                self._var_names[name]['f'],
                shape=(num_seg, num_stages) + shape,
                units=rate_units,
                desc=
                'The predicted values of the state at the ODE evaluation points.'
            )

            self.add_output(
                self._var_names[name]['k'],
                shape=(num_seg, num_stages) + shape,
                units=units,
                desc='RK multiplier k for each stage in the segment.')

            size = np.prod(shape)
            ar = np.arange(size * num_stages * num_seg, dtype=int)
            self.declare_partials(of=self._var_names[name]['k'],
                                  wrt=self._var_names[name]['f'],
                                  rows=ar,
                                  cols=ar)

            r = np.arange(size * num_stages * num_seg, dtype=int)
            c = np.repeat(np.arange(num_seg, dtype=int), num_stages * size)
            self.declare_partials(of=self._var_names[name]['k'],
                                  wrt='h',
                                  rows=r,
                                  cols=c)
示例#6
0
    def setup(self):
        time_units = self.options['time_units']

        self.add_input('time', val=1.0, units=time_units)

        for control_name, options in iteritems(
                self.options['control_options']):
            shape = options['shape']
            units = options['units']
            rate_units = get_rate_units(units, time_units, deriv=1)
            rate2_units = get_rate_units(units, time_units, deriv=2)

            self.add_output('controls:{0}'.format(control_name),
                            shape=shape,
                            units=units)

            self.add_output('control_rates:{0}_rate'.format(control_name),
                            shape=shape,
                            units=rate_units)

            self.add_output('control_rates:{0}_rate2'.format(control_name),
                            shape=shape,
                            units=rate2_units)
示例#7
0
    def _setup_variables(self):
        num_nodes = self.num_nodes
        time_units = self.options['time_units']

        for name, options in iteritems(self._var_options):
            self._input_names[name] = name
            self._output_rate_names[name] = 'dYdt:{0}'.format(name)
            shape = options['shape']
            input_shape = (num_nodes,) + shape
            output_shape = (num_nodes,) + shape

            print(name, input_shape, output_shape)

            units = options['units']
            rate_units = get_rate_units(units, time_units)

            self._dynamic_names.append(name)

            self.add_input(self._input_names[name], val=np.ones(input_shape), units=units)

            self.add_output(self._output_rate_names[name], shape=output_shape, units=rate_units)

            size = np.prod(shape)
            self.rate_jacs[name] = np.zeros((num_nodes, size, num_nodes, size))
            for i in range(size):
                self.rate_jacs[name][:, i, :, i] = self.D
            self.rate_jacs[name] = self.rate_jacs[name].reshape((num_nodes * size,
                                                                 num_nodes * size),
                                                                order='C')
            self.rate_jac_rows[name], self.rate_jac_cols[name] = \
                np.where(self.rate_jacs[name] != 0)

            self.sizes[name] = size

            cs = np.tile(np.arange(num_nodes, dtype=int), reps=size)
            rs = np.concatenate([np.arange(0, num_nodes * size, size, dtype=int) + i
                                 for i in range(size)])

            self.declare_partials(of=self._output_rate_names[name],
                                  wrt='dt_dstau',
                                  rows=rs, cols=cs)

            self.declare_partials(of=self._output_rate_names[name],
                                  wrt=self._input_names[name],
                                  rows=self.rate_jac_rows[name], cols=self.rate_jac_cols[name])
示例#8
0
    def setup(self):
        state_options = self.options['state_options']
        time_units = self.options['time_units']

        for name, options in iteritems(state_options):
            self._input_names[name] = 'state_rates_in:{0}_rate'.format(name)
            self._output_names[name] = 'state_rates:{0}_rate'.format(name)
            shape = options['shape']
            units = options['units']

            rate_units = get_rate_units(units, time_units)

            self.add_input(self._input_names[name],
                           val=np.ones(shape),
                           units=rate_units)
            self.add_output(self._output_names[name],
                            shape=shape,
                            units=rate_units)
示例#9
0
    def setup(self):
        time_units = self.options['time_units']

        num_disc_nodes = self.options['grid_data'].subset_num_nodes[
            'state_disc']
        num_col_nodes = self.options['grid_data'].subset_num_nodes['col']

        state_options = self.options['state_options']

        transcription = self.options['transcription']

        self.add_input(name='dt_dstau',
                       shape=(num_col_nodes, ),
                       units=time_units,
                       desc='For each node, the duration of its '
                       'segment in the integration variable')

        self.xd_str = {}
        self.fd_str = {}
        self.xc_str = {}
        self.xdotc_str = {}

        for state_name, options in state_options.items():
            shape = options['shape']
            units = options['units']

            rate_units = get_rate_units(units, time_units)

            self.add_input(
                name='state_disc:{0}'.format(state_name),
                shape=(num_disc_nodes, ) + shape,
                desc='Values of state {0} at discretization nodes'.format(
                    state_name),
                units=units)

            if transcription == 'gauss-lobatto':
                self.add_input(name='staterate_disc:{0}'.format(state_name),
                               shape=(num_disc_nodes, ) + shape,
                               units=rate_units,
                               desc='EOM time derivative of state {0} at '
                               'discretization nodes'.format(state_name))

                self.add_output(name='state_col:{0}'.format(state_name),
                                shape=(num_col_nodes, ) + shape,
                                units=units,
                                desc='Interpolated values of state {0} at '
                                'collocation nodes'.format(state_name))

            self.add_output(
                name='staterate_col:{0}'.format(state_name),
                shape=(num_col_nodes, ) + shape,
                units=rate_units,
                desc='Interpolated rate of state {0} at collocation nodes'.
                format(state_name))

            self.xd_str[state_name] = 'state_disc:{0}'.format(state_name)
            self.fd_str[state_name] = 'staterate_disc:{0}'.format(state_name)
            self.xc_str[state_name] = 'state_col:{0}'.format(state_name)
            self.xdotc_str[state_name] = 'staterate_col:{0}'.format(state_name)

        if transcription == 'gauss-lobatto':
            Ai, Bi, Ad, Bd = self.options['grid_data'].phase_hermite_matrices(
                'state_disc', 'col')
        elif transcription == 'radau-ps':
            Ai, Ad = self.options['grid_data'].phase_lagrange_matrices(
                'state_disc', 'col')
            Bi = Bd = np.zeros(shape=(num_col_nodes, num_disc_nodes))
        else:
            raise ValueError('unhandled transcription type: '
                             '{0}'.format(self.options['transcription']))
        self.matrices = {'Ai': Ai, 'Bi': Bi, 'Ad': Ad, 'Bd': Bd}

        # Setup partials

        self.jacs = {'Ai': {}, 'Bi': {}, 'Ad': {}, 'Bd': {}}
        self.Bi_rows = {}
        self.Bi_cols = {}
        self.Ad_rows = {}
        self.Ad_cols = {}
        self.sizes = {}
        self.num_col_nodes = num_col_nodes
        self.num_disc_nodes = num_disc_nodes
        for name, options in iteritems(state_options):
            shape = options['shape']

            size = np.prod(shape)

            for key in self.jacs:
                jac = np.zeros((num_col_nodes, size, num_disc_nodes, size))
                for i in range(size):
                    jac[:, i, :, i] = self.matrices[key]
                jac = jac.reshape(
                    (num_col_nodes * size, num_disc_nodes * size), order='C')
                self.jacs[key][name] = jac

            self.sizes[name] = size

            #
            # Partial of xdotc wrt dt_dstau
            #

            # The partial of xdotc (state rate at collocation nodes) is a matrix of m bands
            # on and below the diagonal where m is the size of the variable.
            rs_dtdstau = np.zeros(num_col_nodes * size, dtype=int)
            cs_dtdstau = np.tile(np.arange(0, num_col_nodes, dtype=int),
                                 reps=size)
            r_band = np.arange(0, num_col_nodes, dtype=int) * size

            r0 = 0
            for i in range(size):
                rs_dtdstau[r0:r0 + num_col_nodes] = r_band + i
                r0 += num_col_nodes

            self.declare_partials(of=self.xdotc_str[name],
                                  wrt='dt_dstau',
                                  rows=rs_dtdstau,
                                  cols=cs_dtdstau)

            if transcription == 'gauss-lobatto':
                self.declare_partials(of=self.xc_str[name],
                                      wrt='dt_dstau',
                                      rows=rs_dtdstau,
                                      cols=cs_dtdstau)

                Ai_rows, Ai_cols = np.where(self.jacs['Ai'][name] != 0)
                self.declare_partials(of=self.xc_str[name],
                                      wrt=self.xd_str[name],
                                      rows=Ai_rows,
                                      cols=Ai_cols,
                                      val=self.jacs['Ai'][name][Ai_rows,
                                                                Ai_cols])

                self.Bi_rows[name], self.Bi_cols[name] = np.where(
                    self.jacs['Bi'][name] != 0)
                self.declare_partials(of=self.xc_str[name],
                                      wrt=self.fd_str[name],
                                      rows=self.Bi_rows[name],
                                      cols=self.Bi_cols[name])

                Bd_rows, Bd_cols = np.where(self.jacs['Bd'][name] != 0)
                self.declare_partials(of=self.xdotc_str[name],
                                      wrt=self.fd_str[name],
                                      rows=Bd_rows,
                                      cols=Bd_cols,
                                      val=self.jacs['Bd'][name][Bd_rows,
                                                                Bd_cols])

            self.Ad_rows[name], self.Ad_cols[name] = np.where(
                self.jacs['Ad'][name] != 0)
            self.declare_partials(of=self.xdotc_str[name],
                                  wrt=self.xd_str[name],
                                  rows=self.Ad_rows[name],
                                  cols=self.Ad_cols[name])
示例#10
0
文件: test_misc.py 项目: thearn/dymos
    def test_get_rate_units_invalid_deriv(self):

        with self.assertRaises(ValueError) as e:
            get_rate_units('m', 's', deriv=0)
            self.assertEqual(str(e.exception),
                             'deriv argument must be 1 or 2.')
示例#11
0
    def record_results(self,
                       phase_name,
                       filename,
                       ode_class,
                       ode_init_kwargs=None):
        """
        Record the outputs to the given filename.  This is done by instantiating a new
        problem with an IndepVarComp for the time, states, controls, and control rates, as
        well as an instance of the given ODE class (instantiated with the number of nodes equal
        to the number of times in the outputs).

        The system is populated with data from outputs, has a recorder attached, and is executed
        via problem.run_model.  This data can then be retrieved from the `system_cases` attribute
        of CaseReader.

        Parameters
        ----------
        phase_name : str
            The name of the phase whose simulation results are being recorded.
        filename : str
            The filename to which the recording should be saved.
        ode_class : openmdao.System
            A system class with the appropriate ODE metadata attached via the dymos declare_time,
            declare_state, and declare_parameter decorators.
        ode_init_kwargs : dict or None
            A dictionary of keyword arguments with which ode_class should be instantiated.
        """
        init_kwargs = {} if ode_init_kwargs is None else ode_init_kwargs

        p = Problem(model=Group())
        time = self.get_values('time')
        nn = len(time)
        ode_sys = ode_class(num_nodes=nn, **init_kwargs)
        ivc = p.model.add_subsystem('inputs',
                                    subsys=IndepVarComp(),
                                    promotes_outputs=['*'])
        p.model.add_subsystem('ode', subsys=ode_sys)

        # Connect times
        ivc.add_output('time',
                       val=np.zeros((nn, 1)),
                       units=self.time_options['units'])
        p.model.connect(
            'time',
            ['ode.{0}'.format(t) for t in self.time_options['targets']])

        # Connect states
        for name, options in iteritems(self.state_options):
            ivc.add_output('states:{0}'.format(name),
                           val=np.zeros((nn, ) + options['shape']),
                           units=options['units'])
            p.model.connect('states:{0}'.format(name),
                            ['ode.{0}'.format(t) for t in options['targets']])

        # Connect controls
        sys_param_options = ode_sys.ode_options._parameters
        for name, options in iteritems(self.control_options):
            units = options['units']
            ivc.add_output('controls:{0}'.format(name),
                           val=np.zeros((nn, ) + options['shape']),
                           units=units)
            p.model.connect('controls:{0}'.format(name), [
                'ode.{0}'.format(t) for t in sys_param_options[name]['targets']
            ],
                            src_indices=np.arange(nn, dtype=int))

            rate_units = get_rate_units(units,
                                        self.time_options['units'],
                                        deriv=1)
            ivc.add_output('control_rates:{0}_rate'.format(name),
                           val=np.zeros((nn, ) + options['shape']),
                           units=rate_units)
            if options['rate_param']:
                rate_targets = sys_param_options[
                    options['rate_param']]['targets']
                p.model.connect('control_rates:{0}_rate'.format(name),
                                ['ode.{0}'.format(t) for t in rate_targets],
                                src_indices=np.arange(nn, dtype=int))

            rate2_units = get_rate_units(units,
                                         self.time_options['units'],
                                         deriv=2)
            ivc.add_output('control_rates:{0}_rate2'.format(name),
                           val=np.zeros((nn, ) + options['shape']),
                           units=rate2_units)
            if options['rate2_param']:
                rate2_targets = sys_param_options[
                    options['rate2_param']]['targets']
                p.model.connect('control_rates:{0}_rate2'.format(name),
                                ['ode.{0}'.format(t) for t in rate2_targets],
                                src_indices=np.arange(nn, dtype=int))

        # Connect design parameters
        for name, options in iteritems(self.design_parameter_options):
            units = options['units']
            ivc.add_output('design_parameters:{0}'.format(name),
                           val=np.zeros((nn, ) + options['shape']),
                           units=units)
            p.model.connect('design_parameters:{0}'.format(name), [
                'ode.{0}'.format(t) for t in sys_param_options[name]['targets']
            ],
                            src_indices=np.arange(nn, dtype=int))

        # Connect input parameters
        for name, options in iteritems(self.input_parameter_options):
            units = options['units']
            ivc.add_output('input_parameters:{0}'.format(name),
                           val=np.zeros((nn, ) + options['shape']),
                           units=units)
            p.model.connect('input_parameters:{0}'.format(name), [
                'ode.{0}'.format(t) for t in sys_param_options[name]['targets']
            ],
                            src_indices=np.arange(nn, dtype=int))

        p.setup(check=False)

        p.model.add_recorder(SqliteRecorder(filename))
        p.model.recording_options['record_metadata'] = True
        p.model.recording_options['record_outputs'] = True

        # Assign times
        p['time'] = time

        # Assign states
        for name in self.state_options:
            p['states:{0}'.format(name)] = self.get_values(name)

        # Assign controls
        for name, options in iteritems(self.control_options):
            shape = p['controls:{0}'.format(name)].shape
            p['controls:{0}'.format(name)] = np.reshape(
                self.get_values(name), shape)

            p['control_rates:{0}_rate'.format(name)] = \
                np.reshape(self.get_values('{0}_rate'.format(name)), shape)

            p['control_rates:{0}_rate2'.format(name)] = \
                np.reshape(self.get_values('{0}_rate2'.format(name)), shape)

        # Assign design parameters
        for name, options in iteritems(self.design_parameter_options):
            shape = p['design_parameters:{0}'.format(name)].shape
            p['design_parameters:{0}'.format(name)] = np.reshape(
                self.get_values(name), shape)

        # Assign input parameters
        for name, options in iteritems(self.input_parameter_options):
            shape = p['input_parameters:{0}'.format(name)].shape
            p['input_parameters:{0}'.format(name)] = np.reshape(
                self.get_values(name), shape)

        # Populate outputs of ODE
        prom2abs_ode_outputs = p.model.ode._var_allprocs_prom2abs_list[
            'output']
        for prom_name, abs_name in iteritems(prom2abs_ode_outputs):
            if p[abs_name[0]].shape[0] == 1:
                p[abs_name[0]] = self.get_values(prom_name)[0]
            else:
                p[abs_name[0]] = np.reshape(self.get_values(prom_name),
                                            p[abs_name[0]].shape)

        # Run model to record file
        p.run_model()
示例#12
0
    def _setup_control_continuity(self):
        control_options = self.options['control_options']
        num_segend_nodes = self.options['grid_data'].subset_num_nodes[
            'segment_ends']
        num_segments = self.options['grid_data'].num_segments
        time_units = self.options['time_units']

        if num_segments <= 1:
            # Control value and rate continuity is enforced even with compressed transcription
            return

        self.add_input('t_duration',
                       units=time_units,
                       val=1.0,
                       desc='time duration of the phase')

        for control_name, options in iteritems(control_options):
            shape = options['shape']
            size = np.prod(shape)
            units = options['units']
            rate_units = get_rate_units(units, time_units, deriv=1)
            rate2_units = get_rate_units(units, time_units, deriv=2)

            # Define the sparsity pattern for rate and rate2 continuity
            rs_size1 = np.repeat(np.arange(num_segments - 1, dtype=int), 2)
            cs_size1 = np.arange(1, num_segend_nodes - 1, dtype=int)

            template = np.zeros((num_segments - 1, num_segend_nodes))
            template[rs_size1, cs_size1] = 1.0
            template = np.kron(template, np.eye(size))
            rs, cs = template.nonzero()

            vals = np.zeros(len(rs), dtype=float)
            vals[0::2] = -1.0
            vals[1::2] = 1.0
            self.rate_jac_templates[control_name] = vals

            #
            # Setup value continuity
            #
            self.name_maps[control_name] = {}

            self.name_maps[control_name]['value_names'] = \
                ('controls:{0}'.format(control_name),
                 'defect_controls:{0}'.format(control_name))

            self.name_maps[control_name]['rate_names'] = \
                ('control_rates:{0}_rate'.format(control_name),
                 'defect_control_rates:{0}_rate'.format(control_name))

            self.name_maps[control_name]['rate2_names'] = \
                ('control_rates:{0}_rate2'.format(control_name),
                 'defect_control_rates:{0}_rate2'.format(control_name))

            self.add_input(
                name='controls:{0}'.format(control_name),
                shape=(num_segend_nodes, ) + shape,
                desc='Values of control {0} at discretization nodes'.format(
                    control_name),
                units=units)

            self.add_output(
                name='defect_controls:{0}'.format(control_name),
                val=5 * np.ones((num_segments - 1, ) + shape),
                desc='Continuity constraint values for control {0}'.format(
                    control_name),
                units=units)

            self.declare_partials(
                'defect_controls:{0}'.format(control_name),
                'controls:{0}'.format(control_name),
                val=vals,
                rows=rs,
                cols=cs,
            )

            #
            # Setup first derivative continuity
            #

            self.add_input(name='control_rates:{0}_rate'.format(control_name),
                           shape=(num_segend_nodes, ) + shape,
                           desc='Values of control {0} derivative at '
                           'discretization nodes'.format(control_name),
                           units=rate_units)

            self.add_output(
                name='defect_control_rates:{0}_rate'.format(control_name),
                shape=(num_segments - 1, ) + shape,
                desc='Consistency constraint values for '
                'control {0} derivative'.format(control_name),
                units=rate_units)

            self.declare_partials(
                'defect_control_rates:{0}_rate'.format(control_name),
                'control_rates:{0}_rate'.format(control_name),
                rows=rs,
                cols=cs,
            )

            self.declare_partials(
                'defect_control_rates:{0}_rate'.format(control_name),
                't_duration',
                dependent=True,
            )

            #
            # Setup second derivative continuity
            #

            self.add_input(name='control_rates:{0}_rate2'.format(control_name),
                           shape=(num_segend_nodes, ) + shape,
                           desc='Values of control {0} second derivative '
                           'at discretization nodes'.format(control_name),
                           units=rate2_units)

            self.add_output(
                name='defect_control_rates:{0}_rate2'.format(control_name),
                shape=(num_segments - 1, ) + shape,
                desc='Consistency constraint values for control '
                '{0} second derivative'.format(control_name),
                units=rate2_units)

            self.declare_partials(
                'defect_control_rates:{0}_rate2'.format(control_name),
                'control_rates:{0}_rate2'.format(control_name),
                rows=rs,
                cols=cs,
            )

            self.declare_partials(
                'defect_control_rates:{0}_rate2'.format(control_name),
                't_duration',
                dependent=True)
示例#13
0
    def setup(self):
        gd = self.options['grid_data']
        num_col_nodes = gd.subset_num_nodes['col']
        time_units = self.options['time_units']
        state_options = self.options['state_options']

        self.add_input('dt_dstau', units=time_units, shape=(num_col_nodes, ))

        self.var_names = var_names = {}
        for state_name in state_options:
            var_names[state_name] = {
                'f_approx': 'f_approx:{0}'.format(state_name),
                'f_computed': 'f_computed:{0}'.format(state_name),
                'defect': 'defects:{0}'.format(state_name),
            }

        for state_name, options in iteritems(state_options):
            shape = options['shape']
            units = options['units']

            rate_units = get_rate_units(units, time_units)

            var_names = self.var_names[state_name]

            self.add_input(name=var_names['f_approx'],
                           shape=(num_col_nodes, ) + shape,
                           desc='Estimated derivative of state {0} '
                           'at the collocation nodes'.format(state_name),
                           units=rate_units)

            self.add_input(name=var_names['f_computed'],
                           shape=(num_col_nodes, ) + shape,
                           desc='Computed derivative of state {0} '
                           'at the collocation nodes'.format(state_name),
                           units=rate_units)

            self.add_output(
                name=var_names['defect'],
                shape=(num_col_nodes, ) + shape,
                desc='Interior defects of state {0}'.format(state_name),
                units=units)

            if 'defect_ref' in options and options['defect_ref'] is not None:
                def_scl = 1.0 / options['defect_ref']
            elif 'defect_scaler' in options:
                def_scl = options['defect_scaler']
            else:
                def_scl = 1.0

            self.add_constraint(name=var_names['defect'],
                                equals=0.0,
                                scaler=def_scl)

        # Setup partials
        num_col_nodes = self.options['grid_data'].subset_num_nodes['col']
        state_options = self.options['state_options']

        for state_name, options in state_options.items():
            shape = options['shape']
            size = np.prod(shape)

            r = np.arange(num_col_nodes * size)

            var_names = self.var_names[state_name]

            self.declare_partials(of=var_names['defect'],
                                  wrt=var_names['f_approx'],
                                  rows=r,
                                  cols=r)

            self.declare_partials(of=var_names['defect'],
                                  wrt=var_names['f_computed'],
                                  rows=r,
                                  cols=r)

            c = np.repeat(np.arange(num_col_nodes), size)
            self.declare_partials(of=var_names['defect'],
                                  wrt='dt_dstau',
                                  rows=r,
                                  cols=c)
示例#14
0
    def record_results(self, traj, exp_outs, filename):
        """
        Record the outputs to the given filename.  This is done by instantiating a new
        problem with an IndepVarComp for the time, states, controls, and control rates, as
        well as an instance of the given ODE class (instantiated with the number of nodes equal
        to the number of times in the outputs).

        The system is populated with data from outputs, has a recorder attached, and is executed
        via problem.run_model.  This data can then be retrieved from the `system_cases` attribute
        of CaseReader.

        Parameters
        ----------
        traj : Trajectory
            The Trajectory whose simulated results are to be recorded.
        exp_outs : dict of {str : PhaseSimulationResults}.
            A dictionary of {phase_name : PhaseSimulationResults} for each phase to be recorded
        filename : str
            The filename to which the recording should be saved.
        """
        # Make sure we have the same keys/phases in both the trajectory and exp_outs
        if set(traj._phases) != set(exp_outs):
            raise ValueError(
                'TrajectorySimulationResults trajectory._phases and '
                'exp_outs must contain the same keys.')

        p = Problem(model=Group())

        traj_group = p.model.add_subsystem('phases', ParallelGroup())

        phase_groups = {}

        for phase_name, phase in iteritems(traj._phases):
            ode_class = phase.options['ode_class']
            init_kwargs = phase.options['ode_init_kwargs']
            exp_out = exp_outs[phase_name]

            phase_group = traj_group.add_subsystem(phase_name, subsys=Group())
            phase_groups[phase_name] = phase_group

            time = exp_out.get_values('time')
            nn = len(time)
            ode_sys = ode_class(num_nodes=nn, **init_kwargs)
            ivc = phase_group.add_subsystem('inputs',
                                            subsys=IndepVarComp(),
                                            promotes_outputs=['*'])
            phase_group.add_subsystem('ode', subsys=ode_sys)

            # Connect times
            ivc.add_output('time',
                           val=np.zeros((nn, 1)),
                           units=phase.time_options['units'])
            phase_group.connect(
                'time',
                ['ode.{0}'.format(t) for t in phase.time_options['targets']])

            # Connect states
            for name, options in iteritems(phase.state_options):
                ivc.add_output('states:{0}'.format(name),
                               val=np.zeros((nn, ) + options['shape']),
                               units=options['units'])
                phase_group.connect(
                    'states:{0}'.format(name),
                    ['ode.{0}'.format(t) for t in options['targets']])

            # Connect controls
            sys_param_options = ode_sys.ode_options._parameters
            for name, options in iteritems(phase.control_options):
                units = options['units']
                ivc.add_output('controls:{0}'.format(name),
                               val=np.zeros((nn, ) + options['shape']),
                               units=units)
                phase_group.connect('controls:{0}'.format(name), [
                    'ode.{0}'.format(t)
                    for t in sys_param_options[name]['targets']
                ],
                                    src_indices=np.arange(nn, dtype=int))

                rate_units = get_rate_units(units,
                                            phase.time_options['units'],
                                            deriv=1)
                ivc.add_output('control_rates:{0}_rate'.format(name),
                               val=np.zeros((nn, ) + options['shape']),
                               units=rate_units)
                if options['rate_param']:
                    rate_targets = sys_param_options[
                        options['rate_param']]['targets']
                    phase_group.connect(
                        'control_rates:{0}_rate'.format(name),
                        ['ode.{0}'.format(t) for t in rate_targets],
                        src_indices=np.arange(nn, dtype=int))

                rate2_units = get_rate_units(units,
                                             phase.time_options['units'],
                                             deriv=2)
                ivc.add_output('control_rates:{0}_rate2'.format(name),
                               val=np.zeros((nn, ) + options['shape']),
                               units=rate2_units)
                if options['rate2_param']:
                    rate2_targets = sys_param_options[
                        options['rate2_param']]['targets']
                    phase_group.connect(
                        'control_rates:{0}_rate2'.format(name),
                        ['ode.{0}'.format(t) for t in rate2_targets],
                        src_indices=np.arange(nn, dtype=int))

            # Connect design parameters
            for name, options in iteritems(phase.design_parameter_options):
                units = options['units']
                ivc.add_output('design_parameters:{0}'.format(name),
                               val=np.zeros((nn, ) + options['shape']),
                               units=units)
                phase_group.connect('design_parameters:{0}'.format(name), [
                    'ode.{0}'.format(t)
                    for t in sys_param_options[name]['targets']
                ],
                                    src_indices=np.arange(nn, dtype=int))

            # Connect input parameters
            for name, options in iteritems(phase.input_parameter_options):
                units = options['units']
                ivc.add_output('input_parameters:{0}'.format(name),
                               val=np.zeros((nn, ) + options['shape']),
                               units=units)
                phase_group.connect('input_parameters:{0}'.format(name), [
                    'ode.{0}'.format(t) for t in sys_param_options[
                        options['target_param']]['targets']
                ],
                                    src_indices=np.arange(nn, dtype=int))

        p.setup(check=True)

        p.model.add_recorder(SqliteRecorder(filename))
        p.model.recording_options['record_metadata'] = True
        p.model.recording_options['record_outputs'] = True

        # Assign values

        for phase_name, phase in iteritems(traj._phases):
            exp_out = exp_outs[phase_name]

            # Assign times
            p['phases.{0}.time'.format(phase_name)] = exp_out.get_values(
                'time')

            # Assign states
            for name in phase.state_options:
                p['phases.{0}.states:{1}'.format(
                    phase_name, name)] = exp_out.get_values(name)

            # Assign controls
            for name, options in iteritems(phase.control_options):
                shape = p['phases.{0}.controls:{1}'.format(phase_name,
                                                           name)].shape

                p['phases.{0}.controls:{1}'.format(phase_name, name)] = \
                    np.reshape(exp_out.get_values(name), shape)

                p['phases.{0}.control_rates:{1}_rate'.format(phase_name, name)] = \
                    np.reshape(exp_out.get_values('{0}_rate'.format(name)), shape)

                p['phases.{0}.control_rates:{1}_rate2'.format(phase_name, name)] = \
                    np.reshape(exp_out.get_values('{0}_rate2'.format(name)), shape)

            # Assign design parameters
            for name, options in iteritems(phase.design_parameter_options):
                shape = p['phases.{0}.design_parameters:{1}'.format(
                    phase_name, name)].shape
                p['phases.{0}.design_parameters:{1}'.format(phase_name, name)] = \
                    np.reshape(exp_out.get_values(name), shape)

            # Assign input parameters
            for name, options in iteritems(phase.input_parameter_options):
                shape = p['phases.{0}.input_parameters:{1}'.format(
                    phase_name, name)].shape
                p['phases.{0}.input_parameters:{1}'.format(phase_name, name)] = \
                    np.reshape(exp_out.get_values(name), shape)

            # Populate outputs of ODE
            prom2abs_ode_outputs = \
                phase_groups[phase_name].ode._var_allprocs_prom2abs_list['output']
            for prom_name, abs_name in iteritems(prom2abs_ode_outputs):
                if p[abs_name[0]].shape[0] == 1:
                    p[abs_name[0]] = exp_out.get_values(prom_name)[0]
                else:
                    p[abs_name[0]] = np.reshape(exp_out.get_values(prom_name),
                                                p[abs_name[0]].shape)

        # Run model to record file
        p.run_model()
示例#15
0
    def _setup_controls(self):
        control_options = self.options['control_options']
        gd = self.options['grid_data']
        num_nodes = self.num_nodes
        num_control_input_nodes = self.options['grid_data'].subset_num_nodes[
            'control_input']
        time_units = self.options['time_units']

        for name, options in iteritems(control_options):
            self._input_names[name] = 'controls:{0}'.format(name)
            self._output_val_names[name] = 'control_values:{0}'.format(name)
            self._output_rate_names[name] = 'control_rates:{0}_rate'.format(
                name)
            self._output_rate2_names[name] = 'control_rates:{0}_rate2'.format(
                name)
            shape = options['shape']
            input_shape = (num_control_input_nodes, ) + shape
            output_shape = (num_nodes, ) + shape

            units = options['units']
            rate_units = get_rate_units(units, time_units)
            rate2_units = get_rate_units(units, time_units, deriv=2)

            self._dynamic_names.append(name)

            self.add_input(self._input_names[name],
                           val=np.ones(input_shape),
                           units=units)

            self.add_output(self._output_val_names[name],
                            shape=output_shape,
                            units=units)

            self.add_output(self._output_rate_names[name],
                            shape=output_shape,
                            units=rate_units)

            self.add_output(self._output_rate2_names[name],
                            shape=output_shape,
                            units=rate2_units)

            size = np.prod(shape)
            self.val_jacs[name] = np.zeros(
                (num_nodes, size, num_control_input_nodes, size))
            self.rate_jacs[name] = np.zeros(
                (num_nodes, size, num_control_input_nodes, size))
            self.rate2_jacs[name] = np.zeros(
                (num_nodes, size, num_control_input_nodes, size))
            for i in range(size):
                self.val_jacs[name][:, i, :, i] = self.L
                self.rate_jacs[name][:, i, :, i] = self.D
                self.rate2_jacs[name][:, i, :, i] = self.D2
            self.val_jacs[name] = self.val_jacs[name].reshape(
                (num_nodes * size, num_control_input_nodes * size), order='C')
            self.rate_jacs[name] = self.rate_jacs[name].reshape(
                (num_nodes * size, num_control_input_nodes * size), order='C')
            self.rate2_jacs[name] = self.rate2_jacs[name].reshape(
                (num_nodes * size, num_control_input_nodes * size), order='C')
            self.val_jac_rows[name], self.val_jac_cols[name] = \
                np.where(self.val_jacs[name] != 0)
            self.rate_jac_rows[name], self.rate_jac_cols[name] = \
                np.where(self.rate_jacs[name] != 0)
            self.rate2_jac_rows[name], self.rate2_jac_cols[name] = \
                np.where(self.rate2_jacs[name] != 0)

            self.sizes[name] = size

            rs, cs = self.val_jac_rows[name], self.val_jac_cols[name]
            self.declare_partials(of=self._output_val_names[name],
                                  wrt=self._input_names[name],
                                  rows=rs,
                                  cols=cs,
                                  val=self.val_jacs[name][rs, cs])

            cs = np.tile(np.arange(num_nodes, dtype=int), reps=size)
            rs = np.concatenate([
                np.arange(0, num_nodes * size, size, dtype=int) + i
                for i in range(size)
            ])

            self.declare_partials(of=self._output_rate_names[name],
                                  wrt='dt_dstau',
                                  rows=rs,
                                  cols=cs)

            self.declare_partials(of=self._output_rate_names[name],
                                  wrt=self._input_names[name],
                                  rows=self.rate_jac_rows[name],
                                  cols=self.rate_jac_cols[name])

            self.declare_partials(of=self._output_rate2_names[name],
                                  wrt='dt_dstau',
                                  rows=rs,
                                  cols=cs)

            self.declare_partials(of=self._output_rate2_names[name],
                                  wrt=self._input_names[name],
                                  rows=self.rate2_jac_rows[name],
                                  cols=self.rate2_jac_cols[name])