Beispiel #1
0
    def compute_partials(self, inputs, partials):
        rho = inputs['rho']
        v = inputs['v']
        alpha = inputs['alpha']
        c_0 = 1.0672181
        c_1 = -.19213774e-1
        c_2 = .21286289e-3
        c_3 = -.10117249e-5

        if np.any(v < 0):
            raise om.AnalysisError('Negative velocity magnitude encountered')

        sqrt_rho = np.sqrt(rho)

        q_r = 17700 * sqrt_rho * (.0001 * v)**3.07
        q_a = c_0 + c_1 * alpha + c_2 * alpha**2 + c_3 * alpha**3

        dqr_drho = 0.5 * q_r / rho
        dqr_dv = 17700 * sqrt_rho * 0.0001 * 3.07 * (0.0001 * v)**2.07

        dqa_dalpha = c_1 + 2 * c_2 * alpha + 3 * c_3 * alpha**2

        partials['q', 'rho'] = dqr_drho * q_a
        partials['q', 'v'] = dqr_dv * q_a
        partials['q', 'alpha'] = dqa_dalpha * q_r
Beispiel #2
0
    def solve_nonlinear(self, inputs, outputs):

        try:
            if self.options['mode'] == "MN":
                outputs['Vsonic'], outputs['V'], outputs['area'] = self._compute_outputs_MN(inputs)
            else:
                outputs['MN'], outputs['Vsonic'], outputs['V'] = self._compute_outputs_area(inputs)
        except FloatingPointError:
            raise om.AnalysisError('Bad values flow states in {}: Ts={}'.format(self.pathname, inputs['Ts']))
Beispiel #3
0
    def compute(self, inputs, outputs):
        """
        This will error if x is more than 2.
        """
        x = inputs['x']

        if x > 2.0:
            raise om.AnalysisError('Try again.')

        outputs['y'] = x * x + 2.0
Beispiel #4
0
    def _solve_nonlinear_brent(self, inputs, outputs, discrete_inputs,
                               discrete_outputs):
        SOLVE_TOL = 1e-10
        DEBUG_PRINT = self.options['debug_print']

        # Find brackets for the phi residual
        bracket_found, phi_1, phi_2 = self._first_bracket(
            inputs, outputs, self._residuals, discrete_inputs,
            discrete_outputs)
        if not np.all(bracket_found):
            raise om.AnalysisError("CCBlade bracketing failed")

        # Create a wrapper function compatible with the brentv function.
        def f(x):
            outputs['phi'][:, :] = x
            self.apply_nonlinear(inputs, outputs, self._residuals,
                                 discrete_inputs, discrete_outputs)
            return np.copy(self._residuals['phi'])

        # Find the root.
        phi, steps_taken, success = brentv(f,
                                           phi_1,
                                           phi_2,
                                           tolerance=SOLVE_TOL)

        # Fix up the other outputs.
        out_names = ('Np', 'Tp', 'a', 'ap', 'u', 'v', 'W', 'cl', 'cd', 'F')
        for name in out_names:
            if np.all(np.logical_not(np.isnan(self._residuals[name]))):
                outputs[name] += self._residuals[name]

        # Fix up the other residuals.
        self.apply_nonlinear(inputs, outputs, self._residuals, discrete_inputs,
                             discrete_outputs)

        if DEBUG_PRINT:
            res_norm = np.linalg.norm(self._residuals['phi'])
            print(
                f"CCBlade brentv steps taken: {steps_taken}, residual norm = {res_norm}"
            )

        if not success:
            raise om.AnalysisError("CCBlade _solve_nonlinear_brent failed")
def run_and_raise_macro(book, macro, stage):
    logger.info(f"Running macro {macro} at {stage} stage...")
    result = run_wrapped_macro(book, macro)
    logger.info(
        f"Finished running macro {macro} at {stage} stage with result: {result}"
    )

    if not result.success:
        raise om.AnalysisError(
            f'Excel macro "{macro}" executed in "{stage}" stage failed: {result.error}'
        )
Beispiel #6
0
    def compute(self, inputs, outputs):
        """f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3
        Optimal solution (minimum): x = 6.6667; y = -7.3333
        """
        x = inputs['x']
        y = inputs['y']

        if x < 1.75:
            raise om.AnalysisError('Try Again.')

        outputs['f_xy'] = (x - 3.0)**2 + x * y + (y + 4.0)**2 - 3.0
Beispiel #7
0
def Thrust(u0, power, A, T, rho, kappa):
    """
    This computes the thrust and induced velocity at the propeller disk.
    This uses formulas from propeller momentum theory.

    Parameters
    ----------
    u0 : float
        Freestream speed normal to the propeller disk
    power : float
        Power supplied to the propeller disk
    A : float
        Propeller disk area
    T : float
        Thrust guess
    rho : float
        Air density
    kappa: float
        Correction factor for non-uniform inflow and tip effects

    Returns
    -------
    thrust : float
        Thrust
    v_i : float
        Induced velocity at the propeller disk
    """

    T_old = T + 10.
    thrust = T

    # iteration loop to solve for the thrust as a function of power
    while np.any(np.abs(T_old - thrust) > 1e-10):
        T_old = thrust

        # ### FPI (Fixed point iteration)
        # T_new = power / (u0 + kappa * (-u0/2 + 0.5 * (u0**2 + 2 * thrust / rho / A)**0.5))
        # thrust = thrust + (T_new - thrust) * 0.5

        # # Newton-Raphson
        with np.errstate(all='raise'):
            try:
                root_term = (u0**2 + 2 * thrust / rho / A)**0.5
                R = power - thrust * (u0 + kappa * (-u0 / 2 + 0.5 * root_term))
                R_prime = -u0 - kappa * (-u0 / 2 + 0.5 * root_term +
                                         0.5 * thrust / rho / A / root_term)
                thrust = T_old - R / R_prime
            except:
                raise om.AnalysisError('invalid calc in thrust')

    # the induced velocity (i.e., velocity added at the disk) is
    v_i = (-u0 / 2 + (u0**2 / 4. + thrust / 2 / rho / A)**0.5)

    return thrust, v_i
 def compute(self,
             inputs,
             outputs,
             discrete_inputs=None,
             discrete_outputs=None):
     try:
         self.open_and_run(inputs, outputs, discrete_inputs or {},
                           discrete_outputs or {})
     except Exception as exc:
         if self.timeout_state.reached:
             raise om.AnalysisError("Timeout reached!")
         else:
             raise exc
Beispiel #9
0
    def apply_nonlinear(self, inputs, outputs, residuals):
        """
        Don't solve; just calculate the residual.
        """

        x = inputs['x']
        y = outputs['y']
        z = outputs['z']

        residuals['y'] = y - x - 2.0 * z
        residuals['z'] = x * z + z - 4.0

        self.counter += 1
        if self.counter > 5 and self.counter < 11:
            raise om.AnalysisError('catch me')
Beispiel #10
0
    def compute(self, inputs, outputs):
        rho = inputs['rho']
        v = inputs['v']
        alpha = inputs['alpha']
        c_0 = 1.0672181
        c_1 = -0.19213774e-1
        c_2 = 0.21286289e-3
        c_3 = -0.10117249e-5

        if np.any(v < 0):
            raise om.AnalysisError('Negative velocity magnitude encountered')

        q_r = 17700.0 * np.sqrt(rho) * (0.0001 * v)**3.07
        q_a = c_0 + c_1 * alpha + c_2 * alpha**2 + c_3 * alpha**3

        outputs['q'] = q_r * q_a
Beispiel #11
0
    def compute(self, inputs, outputs):

        n_stages = self.options['n_stages']
        i_row = self.options['i_row']

        if i_row % 2 == 0:  # even rows are stators
            T_gas = inputs['Tt_primary'] + self.options['T_safety']
            dh = 0
        else:  # rotor
            T_gas = .92 * inputs['Tt_primary'] + self.options['T_safety']
            dh = inputs['turb_pwr'] / n_stages  # only rotors do work

        if i_row == 0:
            profile_factor = .3
        else:
            profile_factor = .13

        W_primary = inputs['W_primary']
        if T_gas < self.options['T_metal']:
            outputs['W_cool'] = W_cool = 0
            phi_prime = 0
        else:
            phi = (T_gas - self.options['T_metal']) / (T_gas -
                                                       inputs['Tt_cool'])
            phi_prime = (phi + profile_factor) / (profile_factor + 1.)

            # print(self.pathname, W_primary, inputs['Tt_primary'], inputs['Tt_cool'], phi_prime)

            try:
                outputs['W_cool'] = W_cool = .022 * inputs['x_factor'] * (
                    4. / 3.) * W_primary * (phi_prime / (1 - phi_prime))**1.25
            except FloatingPointError:
                raise om.AnalysisError('bad flow values in {}; W: {}'.format(
                    self.pathname, W_primary))

        outputs['ht_out'] = (W_primary * inputs['ht_primary'] +
                             W_cool * inputs['ht_cool']) / (
                                 W_primary + W_cool) - dh / W_primary

        Pt_out = inputs['Pt_out']
        Pt_in = inputs['Pt_in']
        outputs['Pt_stage'] = Pt_out + (Pt_in - Pt_out) * self.i_stage
Beispiel #12
0
 def solve_linear(self, d_outputs, d_residuals, mode):
     super(BadComp, self).solve_linear(d_outputs, d_residuals, mode)
     raise om.AnalysisError("It's just a scratch.")
Beispiel #13
0
 def guess_nonlinear(self, inputs, outputs, resids):
     raise om.AnalysisError("It's just a scratch.")
Beispiel #14
0
 def solve_nonlinear(self, inputs, outputs):
     super(BadComp, self).solve_nonlinear(inputs, outputs)
     raise om.AnalysisError("It's just a scratch.")
Beispiel #15
0
 def compute_jacvec_product(self, inputs, d_inputs, d_outputs,
                            mode):
     super().compute_jacvec_product(inputs, d_inputs, d_outputs,
                                    mode)
     raise om.AnalysisError("It's just a scratch.")
Beispiel #16
0
    def _solve_nonlinear_bracketing(self, inputs, outputs, discrete_inputs,
                                    discrete_outputs):

        SOLVE_TOL = 1e-10
        DEBUG_PRINT = self.options['debug_print']
        residuals = self._residuals

        self.apply_nonlinear(inputs, outputs, residuals, discrete_inputs,
                             discrete_outputs)

        bracket_found, phi_1, phi_2 = self._first_bracket(
            inputs, outputs, residuals, discrete_inputs, discrete_outputs)
        if not np.all(bracket_found):
            raise om.AnalysisError("CCBlade bracketing failed")

        # Initialize the residuals.
        res_1 = np.zeros_like(phi_1)
        outputs['phi'][:, :] = phi_1
        self.apply_nonlinear(inputs, outputs, residuals, discrete_inputs,
                             discrete_outputs)
        res_1[:, :] = residuals['phi']

        res_2 = np.zeros_like(phi_1)
        outputs['phi'][:, :] = phi_2
        self.apply_nonlinear(inputs, outputs, residuals, discrete_inputs,
                             discrete_outputs)
        res_2[:, :] = residuals['phi']

        # now initialize the phi_1 and phi_2 vectors so they represent the correct brackets
        mask = res_1 > 0.
        phi_1[mask], phi_2[mask] = phi_2[mask], phi_1[mask]
        res_1[mask], res_2[mask] = res_2[mask], res_1[mask]

        steps_taken = 0
        success = np.all(np.abs(phi_1 - phi_2) < SOLVE_TOL)
        while steps_taken < 50 and not success:
            outputs['phi'][:] = 0.5 * (phi_1 + phi_2)
            self.apply_nonlinear(inputs, outputs, residuals, discrete_inputs,
                                 discrete_outputs)
            new_res = residuals['phi']

            mask_1 = new_res < 0
            mask_2 = new_res > 0

            phi_1[mask_1] = outputs['phi'][mask_1]
            res_1[mask_1] = new_res[mask_1]

            phi_2[mask_2] = outputs['phi'][mask_2]
            res_2[mask_2] = new_res[mask_2]

            steps_taken += 1
            success = np.all(np.abs(phi_1 - phi_2) < SOLVE_TOL)

            # only need to do this to get into the ballpark
            if DEBUG_PRINT:
                res_norm = np.linalg.norm(new_res)
                print(f"{steps_taken} solve_nonlinear res_norm: {res_norm}")

        # Fix up the other outputs.
        out_names = ('Np', 'Tp', 'a', 'ap', 'u', 'v', 'W', 'cl', 'cd', 'F')
        for name in out_names:
            if np.all(np.logical_not(np.isnan(residuals[name]))):
                outputs[name] += residuals[name]

        # Fix up the other residuals.
        self.apply_nonlinear(inputs, outputs, residuals, discrete_inputs,
                             discrete_outputs)
        if not success:
            raise om.AnalysisError(
                "CCBlade _solve_nonlinear_bracketing failed")
Beispiel #17
0
    def compute(self, inputs, outputs):
        """
        Compute component outputs.

        Parameters
        ----------
        inputs : `Vector`
            `Vector` containing inputs.
        outputs : `Vector`
            `Vector` containing outputs.
        """
        idx = self.options['index']
        gd = self.options['grid_data']
        iface_prob = self.options['ode_integration_interface'].prob

        # Create the vector of initial state values
        self.initial_state_vec[:] = 0.0
        pos = 0
        for name, options in self.options['state_options'].items():
            size = np.prod(options['shape'])
            self.initial_state_vec[pos:pos + size] = \
                np.ravel(inputs['initial_states:{0}'.format(name)])
            pos += size

        # Setup the control interpolants
        if self.options['control_options']:
            t0_seg = inputs['time'][0]
            tf_seg = inputs['time'][-1]
            for name, options in self.options['control_options'].items():
                ctrl_vals = inputs['controls:{0}'.format(name)]
                self.options['ode_integration_interface'].setup_interpolant(
                    name, x0=t0_seg, xf=tf_seg, f_j=ctrl_vals)

        # Setup the polynomial control interpolants
        if self.options['polynomial_control_options']:
            t0_phase = inputs['t_initial']
            tf_phase = inputs['t_initial'] + inputs['t_duration']
            for name, options in self.options[
                    'polynomial_control_options'].items():
                ctrl_vals = inputs['polynomial_controls:{0}'.format(name)]
                self.options['ode_integration_interface'].setup_interpolant(
                    name, x0=t0_phase, xf=tf_phase, f_j=ctrl_vals)

        # Set the values of t_initial and t_duration
        iface_prob.set_val('t_initial',
                           val=inputs['t_initial'],
                           units=self.options['time_options']['units'])

        iface_prob.set_val('t_duration',
                           val=inputs['t_duration'],
                           units=self.options['time_options']['units'])

        # Set the values of the phase parameters
        if self.options['parameter_options']:
            for param_name, options in self.options['parameter_options'].items(
            ):
                val = inputs['parameters:{0}'.format(param_name)]
                iface_prob.set_val('parameters:{0}'.format(param_name),
                                   val=val,
                                   units=options['units'])

        # Setup the evaluation times.
        if self.options['output_nodes_per_seg'] is None:
            # Output nodes given as subset, convert segment tau of nodes to time
            i1, i2 = gd.subset_segment_indices['all'][idx, :]
            indices = gd.subset_node_indices['all'][i1:i2]
            nodes_eval = gd.node_stau[
                indices]  # evaluation nodes in segment tau space
            t_initial = inputs['time'][0]
            t_duration = inputs['time'][-1] - t_initial
            t_eval = t_initial + 0.5 * (nodes_eval + 1) * t_duration
        else:
            # Output nodes given as number, linspace them across the segment
            t_eval = np.linspace(inputs['time'][0], inputs['time'][-1],
                                 self.options['output_nodes_per_seg'])

        # Perform the integration using solve_ivp
        sim_options = {
            key: val
            for key, val in self.options['simulate_options'].items()
        }

        sol = solve_ivp(fun=self.options['ode_integration_interface'],
                        t_span=(inputs['time'][0], inputs['time'][-1]),
                        y0=self.initial_state_vec,
                        t_eval=t_eval,
                        **sim_options)

        if not sol.success:
            raise om.AnalysisError(
                f'solve_ivp failed: {sol.message} Dynamics changing '
                f'too dramatically')

        # Extract the solution
        pos = 0
        for name, options in self.options['state_options'].items():
            size = np.prod(options['shape'])
            outputs['states:{0}'.format(name)] = sol.y[pos:pos + size, :].T
            pos += size
Beispiel #18
0
 def apply_linear(self, inputs, outputs, d_inputs, d_outputs,
                  d_residuals, mode):
     super(BadComp, self).apply_linear(inputs, outputs, d_inputs,
                                       d_outputs, d_residuals, mode)
     raise om.AnalysisError("It's just a scratch.")
Beispiel #19
0
 def linearize(self, inputs, outputs, partials):
     super(BadComp, self).linearize(inputs, outputs, partials)
     raise om.AnalysisError("It's just a scratch.")
Beispiel #20
0
 def compute(self, inputs, outputs):
     super().compute(inputs, outputs)
     raise om.AnalysisError("It's just a scratch.")
Beispiel #21
0
 def compute_partials(self, inputs, partials):
     super().compute_partials(inputs, partials)
     raise om.AnalysisError("It's just a scratch.")
Beispiel #22
0
    def linearize(self, inputs, outputs, J):

        mode = self.options['mode']

        gamma = inputs['gamma']
        Ts = inputs['Ts']
        R = inputs['R']
        rho = inputs['rho']
        W = inputs['W']
        ht = inputs['ht']
        gamma = inputs['gamma']

        if mode == "MN":
            MN_squared_q2 = inputs['MN']**2/2.
        else:
            MN_squared_q2 = outputs['MN']**2/2.

        RT_q_MW = R*Ts
        ht_calc = inputs['hs'] + MN_squared_q2 * gamma * RT_q_MW

        J['Ps', 'ht'] = -ht_calc/ht**2
        J['Ps', 'hs'] = 1/ht

        # Derivatives of outputs
        part = .5*(gamma*R*Ts)**-.5
        J['Vsonic', 'gamma'] = dVs_dgamma = part*R*Ts
        J['Vsonic', 'R'] = part*gamma*Ts
        J['Vsonic', 'Ts'] = part*gamma*R
        J['Vsonic', 'Vsonic'] = -1.
        # J['V', 'V'] = -1.

        if mode=="MN":
            MN = inputs['MN']

            Vsonic, V, area = self._compute_outputs_MN(inputs)

            J['area', 'area'] = -1.

            J['Ps', 'MN'] = MN*gamma*RT_q_MW/ht
            J['Ps', 'R'] = Ts*MN_squared_q2*gamma/ht
            J['Ps', 'gamma'] = RT_q_MW*MN_squared_q2/ht
            J['Ps', 'Ts'] = MN_squared_q2*gamma*R/ht

            if MN >= 1e-16:
                J['area', 'W'] = 1.0/(rho*Vsonic*MN)
                J['area', 'rho'] = -W/(Vsonic*MN*rho**2)

                part = -W/(rho*Vsonic**2*MN) * 0.5*(R*gamma*Ts)**-.5
                J['area', 'gamma'] = part*R*Ts
                J['area', 'R'] = part*gamma*Ts
                J['area', 'Ts'] = part*gamma*R
                J['area', 'MN'] = -W/rho/Vsonic/MN**2

                J['V', 'MN'] = Vsonic
                J['V', 'Ts'] = MN * J['Vsonic', 'Ts']
                J['V', 'R'] = MN * J['Vsonic', 'R']
                J['V', 'gamma'] = MN * J['Vsonic', 'gamma']

        else:
            MN, Vsonic, V = self._compute_outputs_area(inputs)
            area = inputs['area']

            J['MN', 'MN'] = -1

            dresid_dMN = (MN*gamma*RT_q_MW)

            try:
                dMN_dA = -(W/rho/Vsonic/area**2)
            except FloatingPointError:
                raise om.AnalysisError('{} Bad value in static calc: rho={}, Vsonic={}, area={}'.format(self.pathname, rho, Vsonic, area))

            J['Ps', 'area'] = dMN_dA*dresid_dMN/ht
            J['V', 'area'] = dMN_dA*Vsonic
            J['MN', 'area'] = dMN_dA

            dMN_dVs = -W/(rho*area*Vsonic**2)
            dVs_dTs = 0.5*gamma*R/Vsonic
            J['Ps', 'Ts'] = gamma*(MN*dMN_dVs*dVs_dTs*RT_q_MW + MN_squared_q2*R)/ht
            J['V', 'Ts'] = -(dMN_dVs*dVs_dTs*Vsonic + MN*dVs_dTs)
            J['MN', 'Ts'] = dMN_dVs*dVs_dTs

            dVs_dR = 0.5*gamma*Ts/Vsonic
            J['Ps', 'R'] = -gamma*(MN*RT_q_MW*dMN_dVs*dVs_dR + MN_squared_q2*Ts)/ht
            J['V', 'R'] = dMN_dVs*dVs_dR*Vsonic + dVs_dR*MN  # works out to exactly 0
            J['MN', 'R'] = dMN_dVs*dVs_dR

            dMN_dW = (1/rho/Vsonic/area)
            J['Ps', 'W'] = dMN_dW*dresid_dMN/ht
            J['V', 'W'] = dMN_dW*Vsonic
            J['MN', 'W'] = dMN_dW

            dMN_dgamma = dMN_dVs*dVs_dgamma
            J['MN', 'gamma'] = dMN_dgamma
            J['Ps', 'gamma'] = RT_q_MW/ht*(MN_squared_q2 + gamma*MN*dMN_dgamma)
            J['V', 'gamma'] = dMN_dgamma*Vsonic + dVs_dgamma*MN

            dMN_drho = -W/(area*Vsonic*rho**2)
            J['Ps', 'rho'] = MN*gamma*R*Ts*dMN_drho/ht
            J['V', 'rho'] = dMN_drho*Vsonic
            J['MN', 'rho'] = dMN_drho
    def compute(self,
                inputs,
                outputs,
                discrete_inputs=None,
                discrete_outputs=None):
        idx = self.options['index']
        gd = self.options['grid_data']
        iface_prob = self.options['ode_integration_interface'].prob

        # Create the vector of initial state values
        self.initial_state_vec[:] = 0.0
        pos = 0
        for name, options in self.options['state_options'].items():
            size = np.prod(options['shape'])
            self.initial_state_vec[pos:pos + size] = \
                np.ravel(inputs['initial_states:{0}'.format(name)])
            pos += size

        # Setup the control interpolants
        if self.options['control_options']:
            t0_seg = inputs['time'][0]
            tf_seg = inputs['time'][-1]
            for name, options in self.options['control_options'].items():
                ctrl_vals = inputs['controls:{0}'.format(name)]
                self.options['ode_integration_interface'].control_interpolants[
                    name].setup(x0=t0_seg, xf=tf_seg, f_j=ctrl_vals)

        # Setup the polynomial control interpolants
        if self.options['polynomial_control_options']:
            t0_phase = inputs['t_initial']
            tf_phase = inputs['t_initial'] + inputs['t_duration']
            for name, options in self.options[
                    'polynomial_control_options'].items():
                ctrl_vals = inputs['polynomial_controls:{0}'.format(name)]
                self.options[
                    'ode_integration_interface'].polynomial_control_interpolants[
                        name].setup(x0=t0_phase, xf=tf_phase, f_j=ctrl_vals)

        # Set the values of t_initial and t_duration
        iface_prob.set_val('t_initial',
                           value=inputs['t_initial'],
                           units=self.options['time_options']['units'])

        iface_prob.set_val('t_duration',
                           value=inputs['t_duration'],
                           units=self.options['time_options']['units'])

        # Set the values of the phase design parameters
        if self.options['design_parameter_options']:
            for param_name, options in self.options[
                    'design_parameter_options'].items():
                val = inputs['design_parameters:{0}'.format(param_name)]
                iface_prob.set_val('design_parameters:{0}'.format(param_name),
                                   value=val,
                                   units=options['units'])

        # Set the values of the phase input parameters
        if self.options['input_parameter_options']:
            for param_name, options in self.options[
                    'input_parameter_options'].items():
                iface_prob.set_val(
                    'input_parameters:{0}'.format(param_name),
                    value=inputs['input_parameters:{0}'.format(param_name)],
                    units=options['units'])

        # Setup the evaluation times.
        if self.options['output_nodes_per_seg'] is None:
            # Output nodes given as subset, convert segment tau of nodes to time
            i1, i2 = gd.subset_segment_indices['all'][idx, :]
            indices = gd.subset_node_indices['all'][i1:i2]
            nodes_eval = gd.node_stau[
                indices]  # evaluation nodes in segment tau space
            t_initial = inputs['time'][0]
            t_duration = inputs['time'][-1] - t_initial
            t_eval = t_initial + 0.5 * (nodes_eval + 1) * t_duration
        else:
            # Output nodes given as number, linspace them across the segment
            t_eval = np.linspace(inputs['time'][0], inputs['time'][-1],
                                 self.options['output_nodes_per_seg'])

        # Perform the integration using solve_ivp
        sol = solve_ivp(fun=self.options['ode_integration_interface'],
                        t_span=(inputs['time'][0], inputs['time'][-1]),
                        y0=self.initial_state_vec,
                        method=self.options['method'],
                        atol=self.options['atol'],
                        rtol=self.options['rtol'],
                        t_eval=t_eval)

        if not sol.success:
            raise om.AnalysisError('solve_ivp failed', sol.message)

        # Extract the solution
        pos = 0
        for name, options in self.options['state_options'].items():
            size = np.prod(options['shape'])
            outputs['states:{0}'.format(name)] = sol.y[pos:pos + size, :].T
            pos += size
Beispiel #24
0
 def apply_nonlinear(self, inputs, outputs, residuals):
     super(BadComp, self).apply_nonlinear(inputs, outputs,
                                          residuals)
     raise om.AnalysisError("It's just a scratch.")