Example #1
0
    def test(self):
        """
        A simple example to compute inertial forces on four projectiles at
            a number of analysis points (F_inertial = - m*a)
        """
        import numpy as np
        #from openmdao.api import Problem, Group, IndepVarComp
        from openconcept.utilities.math.multiply_divide_comp import ElementMultiplyDivideComp
        from openmdao.utils.assert_utils import assert_near_equal

        n = 5
        length = 4
        p = Problem(model=Group())

        ivc = IndepVarComp()
        #the vector represents forces at 3 analysis points (rows) in 2 dimensional plane (cols)
        ivc.add_output(name='mass', shape=(n, length), units='kg')
        ivc.add_output(name='acceleration',
                       shape=(n, length),
                       units='m / s**2')
        p.model.add_subsystem(name='ivc',
                              subsys=ivc,
                              promotes_outputs=['mass', 'acceleration'])

        #construct an multi/subtracter here. create a relationship through the add_equation method
        multi = ElementMultiplyDivideComp()
        multi.add_equation('inertial_force',
                           input_names=['mass', 'acceleration'],
                           vec_size=n,
                           length=length,
                           input_units=['kg', 'm / s**2'],
                           scaling_factor=-1)
        #note the scaling factors. we assume all forces are positive sign upstream

        p.model.add_subsystem(name='inertialforcecomp',
                              subsys=multi,
                              promotes_inputs=['*'])

        p.setup()

        #set thrust to exceed drag, weight to equal lift for this scenario
        p['mass'] = np.ones((n, length)) * 500
        p['acceleration'] = np.random.rand(n, length)

        p.run_model()

        # print(p.get_val('totalforcecomp.total_force', units='kN'))

        # Verify the results
        expected_i = -p['mass'] * p['acceleration'] / 1000
        assert_near_equal(
            p.get_val('inertialforcecomp.inertial_force', units='kN'),
            expected_i)
Example #2
0
    def setup(self):
        nn = self.options['num_nodes']

        # Scale the heat transfer by the number of pipes
        # Used ExecComp here because multiplying vector and scalar inputs
        self.add_subsystem('heat_divide',
                           ExecComp('q_div = q / n_pipes',
                                    q_div={
                                        'units': 'W',
                                        'shape': (nn, )
                                    },
                                    q={
                                        'units': 'W',
                                        'shape': (nn, )
                                    }),
                           promotes_inputs=['q', 'n_pipes'])

        # Maximum heat transfer and weight
        self.add_subsystem(
            'q_max_calc',
            QMaxHeatPipe(
                num_nodes=nn,
                theta=self.options['theta'],
                yield_stress=self.options['yield_stress'],
                rho_wall=self.options['rho_wall'],
                stress_safety_factor=self.options['stress_safety_factor']),
            # Assume temp in heat pipe is close to evaporator temp
            promotes_inputs=[
                'inner_diam', 'length', ('design_temp', 'T_design'),
                ('temp', 'T_evap')
            ])

        # Multiply max heat transfer and weight by number of pipes
        multiply = ElementMultiplyDivideComp()
        multiply.add_equation(output_name='weight',
                              input_names=['single_pipe_weight', 'n_pipes'],
                              input_units=['kg', None])
        self.add_subsystem('weight_multiplier',
                           multiply,
                           promotes_inputs=['n_pipes'],
                           promotes_outputs=['weight'])
        self.connect('q_max_calc.heat_pipe_weight',
                     'weight_multiplier.single_pipe_weight')
        # Used ExecComp here because multiplying vector and scalar inputs
        self.add_subsystem('q_max_multiplier',
                           ExecComp('q_max = single_pipe_q_max * n_pipes',
                                    q_max={
                                        'units': 'W',
                                        'shape': (nn, )
                                    },
                                    single_pipe_q_max={
                                        'units': 'W',
                                        'shape': (nn, )
                                    }),
                           promotes_inputs=['n_pipes'],
                           promotes_outputs=['q_max'])
        self.connect('q_max_calc.q_max', 'q_max_multiplier.single_pipe_q_max')

        # Thermal resistance at current operator condition
        self.add_subsystem(
            'ammonia_surrogate',
            AmmoniaProperties(num_nodes=nn),
            # Assume temp in heat pipe is close to evaporator temp
            promotes_inputs=[('temp', 'T_evap')])
        self.add_subsystem(
            'delta_T_calc',
            HeatPipeVaporTempDrop(num_nodes=nn),
            # Assume temp in heat pipe is close to evaporator temp
            promotes_inputs=[('temp', 'T_evap'), 'inner_diam', 'length'])
        self.add_subsystem('resistance',
                           HeatPipeThermalResistance(
                               num_nodes=nn,
                               length_evap=self.options['length_evap'],
                               length_cond=self.options['length_cond'],
                               wall_conduct=self.options['wall_conduct'],
                               wick_thickness=self.options['wick_thickness'],
                               wick_conduct=self.options['wick_conduct'],
                               vapor_resistance=True),
                           promotes_inputs=['inner_diam'])
        self.connect('ammonia_surrogate.rho_vapor', 'delta_T_calc.rho_vapor')
        self.connect('ammonia_surrogate.vapor_pressure',
                     'delta_T_calc.vapor_pressure')
        self.connect('delta_T_calc.delta_T', 'resistance.delta_T')
        self.connect('q_max_calc.wall_thickness', 'resistance.wall_thickness'
                     )  # use wall thickness from hoop stress calc

        # Compute condenser temperature
        self.add_subsystem('cond_temp_calc',
                           ExecComp('T_cond = T_evap - q*R',
                                    T_cond={
                                        'units': 'degC',
                                        'shape': (nn, )
                                    },
                                    T_evap={
                                        'units': 'degC',
                                        'shape': (nn, )
                                    },
                                    q={
                                        'units': 'W',
                                        'shape': (nn, )
                                    },
                                    R={
                                        'units': 'K/W',
                                        'shape': (nn, )
                                    }),
                           promotes_inputs=['T_evap'],
                           promotes_outputs=['T_cond'])
        self.connect('heat_divide.q_div',
                     ['delta_T_calc.q', 'resistance.q', 'cond_temp_calc.q'])
        self.connect('resistance.thermal_resistance', 'cond_temp_calc.R')

        # Warn the user if heat transfer exceeds maximum possible
        self.add_subsystem('q_max_warning',
                           QMaxWarning(num_nodes=nn,
                                       q_max_warn=self.options['q_max_warn']),
                           promotes_inputs=['q', 'q_max'])