Exemplo n.º 1
0
comp.add_output('precone', val=0., units='deg')
# comp.add_output('omega', val=236, shape=NUM_NODES, units='rad/s')
comp.add_output('hub_diameter', val=30, units='cm')
comp.add_output('prop_diameter', val=150, units='cm')
comp.add_output('pitch', val=0, shape=NUM_NODES, units='rad')
comp.add_output('chord_dv', val=10, shape=NUM_CP, units='cm')
comp.add_output('theta_dv', val=np.linspace(65., 25., NUM_CP)*np.pi/180., 
                shape=NUM_CP, units='rad')

comp.add_output('omega_max', val=500, units='rad/s')
comp.add_output('omega_min', val=200, units='rad/s')
comp.add_output('tsr2', val=200)

p.model.add_subsystem('ivc', comp, promotes=['*'])

comp = GeometryGroup(num_nodes=NUM_NODES, num_cp=NUM_CP,
                     num_radial=NUM_RADIAL)
p.model.add_subsystem('geom', comp,
                      promotes_inputs=['chord_dv', 'theta_dv', 'pitch'],
                      promotes_outputs=['radii', 'dradii', 'chord', 'theta']
                      )

p.model.connect('hub_diameter', 'geom.hub_diameter', src_indices=[0]*NUM_NODES)
p.model.connect('prop_diameter', 'geom.prop_diameter', src_indices=[0]*NUM_NODES)


comp = ccb.CCBladeGroup(num_nodes=NUM_NODES, num_radial=NUM_RADIAL,
                        airfoil_interp=ccblade_interp,
                        turbine=False)

p.model.add_subsystem('omega_calc', Omega(num_nodes=NUM_NODES), 
                      promotes_inputs=['prop_diameter', 'omega_min', 'omega_max', 'tsr2', 'v'],
Exemplo n.º 2
0
def main():
    interp = ViternaAirfoil().create_akima('mh117',
                                           Re_scaling=False,
                                           extend_alpha=True)

    def ccblade_interp(alpha, Re, Mach):
        shape = alpha.shape
        x = np.concatenate(
            [alpha.flatten()[:, np.newaxis],
             Re.flatten()[:, np.newaxis]],
            axis=-1)
        y = interp(x)
        y.shape = shape + (2, )
        return y[..., 0], y[..., 1]

    num_nodes = 1
    num_blades = 3
    num_radial = 15
    num_cp = 6
    chord = 10.
    theta = np.linspace(65., 25., num_cp) * np.pi / 180.
    pitch = 0.
    prop_data = {
        'num_radial': num_radial,
        'num_cp': num_cp,
        'pitch': pitch,
        'chord': chord,
        'theta': theta,
        'spline_type': 'akima',
        'B': num_blades,
        'interp': interp
    }

    hub_diameter = 30.  # cm
    prop_diameter = 150.  # cm
    c0 = np.sqrt(1.4 * 287.058 * 300.)  # meters/second
    rho0 = 1.4 * 98600. / (c0 * c0)  # kg/m^3
    omega = 236.

    prob = Problem()

    comp = IndepVarComp()
    comp.add_discrete_input('B', val=num_blades)
    comp.add_output('rho', val=rho0, shape=num_nodes, units='kg/m**3')
    comp.add_output('mu', val=1., shape=num_nodes, units='N/m**2*s')
    comp.add_output('asound', val=c0, shape=num_nodes, units='m/s')
    comp.add_output('v', val=77.2, shape=num_nodes, units='m/s')
    comp.add_output('alpha', val=0., shape=num_nodes, units='rad')
    comp.add_output('incidence', val=0., shape=num_nodes, units='rad')
    comp.add_output('precone', val=0., units='deg')
    comp.add_output('omega', val=omega, shape=num_nodes, units='rad/s')
    comp.add_output('hub_diameter',
                    val=hub_diameter,
                    shape=num_nodes,
                    units='cm')
    comp.add_output('prop_diameter',
                    val=prop_diameter,
                    shape=num_nodes,
                    units='cm')
    comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad')
    comp.add_output('chord_dv', val=chord, shape=num_cp, units='cm')
    comp.add_output('theta_dv', val=theta, shape=num_cp, units='rad')
    prob.model.add_subsystem('inputs_comp', comp, promotes=['*'])

    prob.model.add_subsystem('bemt_group',
                             BEMTGroup(num_nodes=num_nodes,
                                       prop_data=prop_data),
                             promotes_inputs=[
                                 'rho', 'mu', 'v', 'alpha', 'incidence',
                                 'omega', 'hub_diameter', 'prop_diameter',
                                 'pitch', 'chord_dv', 'theta_dv'
                             ],
                             promotes_outputs=[
                                 ('normal_load_dist', 'openbemt_normal_load'),
                                 ('circum_load_dist', 'openbemt_circum_load')
                             ])

    comp = GeometryGroup(num_nodes=num_nodes,
                         num_cp=num_cp,
                         num_radial=num_radial)
    prob.model.add_subsystem(
        'geometry_group',
        comp,
        promotes_inputs=[
            'hub_diameter', 'prop_diameter', 'chord_dv', 'theta_dv', 'pitch'
        ],
        promotes_outputs=['radii', 'dradii', 'chord', 'theta'])

    comp = SimpleInflow(num_nodes=num_nodes, num_radial=num_radial)
    prob.model.add_subsystem(
        'inflow_comp',
        comp,
        promotes_inputs=['v', 'omega', 'radii', 'precone'],
        promotes_outputs=['Vx', 'Vy'])

    comp = CCBladeGroup(num_nodes=num_nodes,
                        num_radial=num_radial,
                        airfoil_interp=ccblade_interp,
                        turbine=False,
                        phi_residual_solve_nonlinear='bracketing')
    prob.model.add_subsystem('ccblade_group',
                             comp,
                             promotes_inputs=[
                                 'B', 'radii', 'dradii', 'chord', 'theta',
                                 'rho', 'mu', 'asound', 'Vx', 'Vy', 'v',
                                 'precone', 'omega', 'hub_diameter',
                                 'prop_diameter'
                             ],
                             promotes_outputs=[('Np', 'ccblade_normal_load'),
                                               ('Tp', 'ccblade_circum_load')])

    prob.setup()
    prob.final_setup()
    prob.run_model()

    make_plots(prob)
Exemplo n.º 3
0
def main():

    num_nodes = 1
    num_blades = 3
    num_radial = 15
    num_cp = 6
    af_filename = 'mh117.dat'
    chord = np.tile(10., (num_nodes, num_cp))
    theta = np.tile(np.linspace(65., 25., num_cp)*np.pi/180., (num_nodes, 1))
    pitch = 0.

    hub_diameter = 30.  # cm
    prop_diameter = 150.  # cm
    c0 = np.sqrt(1.4*287.058*300.)  # meters/second
    rho0 = 1.4*98600./(c0*c0)  # kg/m^3
    omega = 236.

    prob = Problem()

    v = np.linspace(1., 1.5, num_nodes)*77.2
    comp = IndepVarComp()
    comp.add_output('rho', val=rho0, shape=num_nodes, units='kg/m**3')
    comp.add_output('mu', val=1., shape=num_nodes, units='N/m**2*s')
    comp.add_output('asound', val=c0, shape=num_nodes, units='m/s')
    comp.add_output('v', val=v, shape=num_nodes, units='m/s')
    comp.add_output('alpha', val=0., shape=num_nodes, units='rad')
    comp.add_output('incidence', val=0., shape=num_nodes, units='rad')
    comp.add_output('precone', val=0., shape=num_nodes, units='deg')
    comp.add_output('omega', val=omega, shape=num_nodes, units='rad/s')
    comp.add_output('hub_diameter', val=hub_diameter, shape=num_nodes, units='cm')
    comp.add_output('prop_diameter', val=prop_diameter, shape=num_nodes, units='cm')
    comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad')
    comp.add_output('chord_dv', val=chord, shape=(num_nodes, num_cp), units='cm')
    comp.add_output('theta_dv', val=theta, shape=(num_nodes, num_cp), units='rad')
    prob.model.add_subsystem('indep_var_comp', comp, promotes=['*'])

    comp = GeometryGroup(num_nodes=num_nodes, num_cp=num_cp,
                         num_radial=num_radial)
    prob.model.add_subsystem(
        'geometry_group', comp,
        promotes_inputs=['hub_diameter', 'prop_diameter', 'chord_dv',
                         'theta_dv', 'pitch'],
        promotes_outputs=['radii', 'dradii', 'chord', 'theta'])

    comp = SimpleInflow(num_nodes=num_nodes, num_radial=num_radial)
    prob.model.add_subsystem(
        'inflow_comp', comp,
        promotes_inputs=['v', 'omega', 'radii', 'precone'],
        promotes_outputs=['Vx', 'Vy'])

    comp = CCBladeGroup(num_nodes=num_nodes, num_radial=num_radial,
                        num_blades=num_blades, af_filename=af_filename,
                        turbine=False)
    prob.model.add_subsystem(
        'ccblade_group', comp,
        promotes_inputs=['radii', 'dradii', 'chord', 'theta', 'rho', 'mu',
                         'asound', 'v', 'precone', 'omega', 'Vx', 'Vy',
                         'precone', 'hub_diameter', 'prop_diameter'],
        promotes_outputs=['thrust', 'torque', 'efficiency'])

    # prob.model.add_design_var('chord_dv', lower=1., upper=20.,
    #                           scaler=5e-2)
    # prob.model.add_design_var('theta_dv',
    #                           lower=20.*np.pi/180., upper=90*np.pi/180.)

    # prob.model.add_objective('efficiency', scaler=-1.,)
    # prob.model.add_constraint('thrust', equals=700., scaler=1e-3,
    #                           indices=np.arange(num_nodes))
    # prob.driver = pyOptSparseDriver()
    # prob.driver.options['optimizer'] = 'SNOPT'

    prob.setup()
    prob.final_setup()
    st = time.time()
    # prob.run_driver()
    prob.run_model()
    elapsed_time = time.time() - st

    make_plots(prob)

    return elapsed_time
Exemplo n.º 4
0
def main():

    num_nodes = 1
    num_blades = 10
    num_radial = 15
    num_cp = 6

    af_filename = 'airfoils/mh117.dat'
    chord = 20.
    theta = 5.0*np.pi/180.0
    pitch = 0.

    # Numbers taken from the Aviary group's study of the RVLT tiltwing
    # turboelectric concept vehicle.
    n_props = 4
    hub_diameter = 30.  # cm
    prop_diameter = 15*30.48  # 15 ft in cm
    c0 = np.sqrt(1.4*287.058*300.)  # meters/second
    rho0 = 1.4*98600./(c0*c0)  # kg/m^3
    omega = 236.  # rad/s

    # Find the thrust per rotor from the vehicle's mass.
    m_full = 6367  # kg
    g = 9.81  # m/s**2
    thrust_vtol = m_full*g/n_props

    prob = Problem()

    comp = IndepVarComp()
    comp.add_output('rho', val=rho0, shape=num_nodes, units='kg/m**3')
    comp.add_output('mu', val=1., shape=num_nodes, units='N/m**2*s')
    comp.add_output('asound', val=c0, shape=num_nodes, units='m/s')
    comp.add_output('v', val=2., shape=num_nodes, units='m/s')
    comp.add_output('alpha', val=0., shape=num_nodes, units='rad')
    comp.add_output('incidence', val=0., shape=num_nodes, units='rad')
    comp.add_output('precone', val=0., units='deg')
    comp.add_output('hub_diameter', val=hub_diameter, shape=num_nodes, units='cm')
    comp.add_output('prop_diameter', val=prop_diameter, shape=num_nodes, units='cm')
    comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad')
    comp.add_output('chord_dv', val=chord, shape=num_cp, units='cm')
    comp.add_output('theta_dv', val=theta, shape=num_cp, units='rad')
    comp.add_output('thrust_vtol', val=thrust_vtol, shape=num_nodes, units='N')
    prob.model.add_subsystem('indep_var_comp', comp, promotes=['*'])

    comp = GeometryGroup(num_nodes=num_nodes, num_cp=num_cp,
                         num_radial=num_radial)
    prob.model.add_subsystem(
        'geometry_group', comp,
        promotes_inputs=['hub_diameter', 'prop_diameter', 'chord_dv',
                         'theta_dv', 'pitch'],
        promotes_outputs=['radii', 'dradii', 'chord', 'theta'])

    balance_group = Group()

    comp = CCBladeGroup(num_nodes=num_nodes, num_radial=num_radial,
                        num_blades=num_blades, af_filename=af_filename,
                        turbine=False)
    balance_group.add_subsystem(
        'ccblade_group', comp,
        promotes_inputs=['radii', 'dradii', 'chord', 'theta', 'rho', 'mu',
                         'asound', 'v', 'precone', 'omega', 'hub_diameter',
                         'prop_diameter'],
        promotes_outputs=['thrust', 'torque', 'efficiency'])

    comp = BalanceComp()
    comp.add_balance(
        name='omega',
        eq_units='N', lhs_name='thrust', rhs_name='thrust_vtol',
        val=omega, units='rad/s',
        lower=0.)
    balance_group.add_subsystem('thrust_balance_comp', comp, promotes=['*'])

    balance_group.linear_solver = DirectSolver(assemble_jac=True)
    # balance_group.nonlinear_solver = NewtonSolver(maxiter=20, iprint=2)
    # balance_group.nonlinear_solver.options['solve_subsystems'] = True
    # balance_group.nonlinear_solver.options['atol'] = 1e-9

    prob.model.add_subsystem('thrust_balance_group', balance_group,
                             promotes=['*'])

    prob.model.nonlinear_solver = NewtonSolver(maxiter=20, iprint=2)
    prob.model.nonlinear_solver.options['solve_subsystems'] = True
    prob.model.nonlinear_solver.options['atol'] = 1e-9
    prob.model.nonlinear_solver.linesearch = BoundsEnforceLS()
    prob.model.nonlinear_solver.linesearch.options['iprint'] = 2
    prob.setup()
    prob.final_setup()

    # Calculate the induced axial velocity at the rotor for hover, used for
    # non-diminsionalation.
    rho = prob.get_val('rho', units='kg/m**3')[0]
    hub_diameter = prob.get_val('hub_diameter', units='m')[0]
    prop_diameter = prob.get_val('prop_diameter', units='m')[0]
    thrust_vtol = prob.get_val('thrust_vtol', units='N')[0]
    A_rotor = 0.25*np.pi*(prop_diameter**2 - hub_diameter**2)
    v_h = np.sqrt(thrust_vtol/(2*rho*A_rotor))

    # Climb:
    climb_velocity_nondim = np.linspace(0.1, 2., 10)
    induced_velocity_nondim = np.zeros_like(climb_velocity_nondim)
    for vc, vi in np.nditer(
            [climb_velocity_nondim, induced_velocity_nondim],
            op_flags=[['readonly'], ['writeonly']]):

        # Run the model with the requested climb velocity.
        prob.set_val('v', vc*v_h, units='m/s')
        print(f"v = {prob.get_val('v', units='m/s')}")
        prob.run_model()

        # Calculate the area-weighted average induced velocity at the rotor.
        # Need the area of each blade section.
        radii = prob.get_val('radii',
                             units='m')
        dradii = prob.get_val('dradii',
                              units='m')
        dArea = 2*np.pi*radii*dradii

        # Get the induced velocity at the rotor plane for each blade section.
        Vx = prob.get_val('ccblade_group.Vx', units='m/s')
        a = prob.get_val('ccblade_group.ccblade_comp.a')

        # Get the area-weighted average of the induced velocity.
        vi[...] = np.sum(a*Vx*dArea/A_rotor)/v_h

    # Induced velocity from plain old momentum theory (for climb).
    induced_velocity_mt = (
        -0.5*climb_velocity_nondim + np.sqrt((0.5*climb_velocity_nondim)**2 + 1.))

    fig, ax = plt.subplots()
    ax.plot(climb_velocity_nondim, -induced_velocity_nondim,
            label='CCBlade.jl (climb)')
    ax.plot(climb_velocity_nondim, induced_velocity_mt,
            label='Momentum Theory (climb)')

    # Descent:
    climb_velocity_nondim = np.linspace(-4., -2.5, 10)
    induced_velocity_nondim = np.zeros_like(climb_velocity_nondim)
    for vc, vi in np.nditer(
            [climb_velocity_nondim, induced_velocity_nondim],
            op_flags=[['readonly'], ['writeonly']]):

        # Run the model with the requested climb velocity.
        prob.set_val('v', vc*v_h, units='m/s')
        print(f"vc = {vc}, v = {prob.get_val('v', units='m/s')}")
        prob.run_model()

        # Calculate the area-weighted average induced velocity at the rotor.
        # Need the area of each blade section.
        radii = prob.get_val('radii',
                             units='m')
        dradii = prob.get_val('dradii',
                              units='m')
        dArea = 2*np.pi*radii*dradii

        # Get the induced velocity at the rotor plane for each blade section.
        Vx = prob.get_val('ccblade_group.Vx', units='m/s')
        a = prob.get_val('ccblade_group.ccblade_comp.a')

        # Get the area-weighted average of the induced velocity.
        vi[...] = np.sum(a*Vx*dArea/A_rotor)/v_h

    # Induced velocity from plain old momentum theory (for descent).
    induced_velocity_mt = (
        -0.5*climb_velocity_nondim - np.sqrt((0.5*climb_velocity_nondim)**2 - 1.))

    # Plot the induced velocity for descent.
    ax.plot(climb_velocity_nondim, -induced_velocity_nondim,
            label='CCBlade.jl (descent)')
    ax.plot(climb_velocity_nondim, induced_velocity_mt,
            label='Momentum Theory (descent)')

    # # Empirical region:
    # climb_velocity_nondim = np.linspace(-1.9, -1.5, 5)
    # induced_velocity_nondim = np.zeros_like(climb_velocity_nondim)
    # for vc, vi in np.nditer(
    #         [climb_velocity_nondim, induced_velocity_nondim],
    #         op_flags=[['readonly'], ['writeonly']]):

    #     # Run the model with the requested climb velocity.
    #     prob.set_val('v', vc*v_h, units='m/s')
    #     print(f"vc = {vc}, v = {prob.get_val('v', units='m/s')}")
    #     prob.run_model()

    #     # Calculate the area-weighted average induced velocity at the rotor.
    #     # Need the area of each blade section.
    #     radii = prob.get_val('radii',
    #                          units='m')
    #     dradii = prob.get_val('dradii',
    #                           units='m')
    #     dArea = 2*np.pi*radii*dradii

    #     # Get the induced velocity at the rotor plane for each blade section.
    #     Vx = prob.get_val('ccblade_group.Vx', units='m/s')
    #     a = prob.get_val('ccblade_group.ccblade_comp.a')

    #     # Get the area-weighted average of the induced velocity.
    #     vi[...] = np.sum(a*Vx*dArea/A_rotor)/v_h

    # # Plot the induced velocity for the empirical region.
    # ax.plot(climb_velocity_nondim, -induced_velocity_nondim,
    #         label='CCBlade.jl (empirical region)')

    ax.set_xlabel('Vc/vh')
    ax.set_ylabel('Vi/vh')
    ax.legend()
    fig.savefig('induced_velocity.png')
Exemplo n.º 5
0
def main():
    interp = ViternaAirfoil().create_akima(
        'mh117', Re_scaling=False, extend_alpha=True)

    num_nodes = 1
    num_blades = 3
    num_radial = 15
    num_cp = 6
    af_filename = 'airfoils/mh117.dat'
    chord = 10.
    theta = np.linspace(65., 25., num_cp)*np.pi/180.
    pitch = 0.
    prop_data = {
        'num_radial': num_radial,
        'num_cp': num_cp,
        'pitch': pitch,
        'chord': chord,
        'theta': theta,
        'spline_type': 'akima',
        'B': num_blades,
        'interp': interp}

    hub_diameter = 30.  # cm
    prop_diameter = 150.  # cm
    c0 = np.sqrt(1.4*287.058*300.)  # meters/second
    rho0 = 1.4*98600./(c0*c0)  # kg/m^3
    omega = 236.

    prob = Problem()

    comp = IndepVarComp()
    comp.add_output('rho', val=rho0, shape=num_nodes, units='kg/m**3')
    comp.add_output('mu', val=1., shape=num_nodes, units='N/m**2*s')
    comp.add_output('asound', val=c0, shape=num_nodes, units='m/s')
    comp.add_output('v', val=77.2, shape=num_nodes, units='m/s')
    comp.add_output('alpha', val=0., shape=num_nodes, units='rad')
    comp.add_output('incidence', val=0., shape=num_nodes, units='rad')
    comp.add_output('precone', val=0., units='deg')
    comp.add_output('omega', val=omega, shape=num_nodes, units='rad/s')
    comp.add_output('hub_diameter', val=hub_diameter, shape=num_nodes, units='cm')
    comp.add_output('prop_diameter', val=prop_diameter, shape=num_nodes, units='cm')
    comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad')
    comp.add_output('chord_dv', val=chord, shape=num_cp, units='cm')
    comp.add_output('theta_dv', val=theta, shape=num_cp, units='rad')
    prob.model.add_subsystem('inputs_comp', comp, promotes=['*'])

    prob.model.add_subsystem(
        'bemt_group', BEMTGroup(num_nodes=num_nodes, prop_data=prop_data),
        promotes_inputs=['rho', 'mu', 'v', 'alpha', 'incidence', 'omega',
                         'hub_diameter', 'prop_diameter', 'pitch', 'chord_dv',
                         'theta_dv'],
        promotes_outputs=[('normal_load_dist', 'openbemt_normal_load'),
                          ('circum_load_dist', 'openbemt_circum_load')])

    comp = GeometryGroup(num_nodes=num_nodes, num_cp=num_cp,
                         num_radial=num_radial)
    prob.model.add_subsystem(
        'geometry_group', comp,
        promotes_inputs=['hub_diameter', 'prop_diameter', 'chord_dv',
                         'theta_dv', 'pitch'],
        promotes_outputs=['radii', 'dradii', 'chord', 'theta'])

    comp = CCBladeGroup(num_nodes=num_nodes, num_radial=num_radial,
                        num_blades=num_blades, af_filename=af_filename,
                        turbine=False)
    prob.model.add_subsystem(
        'ccblade_group', comp,
        promotes_inputs=['radii', 'dradii', 'chord', 'theta', 'rho', 'mu',
                         'asound', 'v', 'precone', 'omega', 'hub_diameter',
                         'prop_diameter'],
        promotes_outputs=[('Np', 'ccblade_normal_load'),
                          ('Tp', 'ccblade_circum_load')])

    prob.setup()
    prob.final_setup()
    prob.run_model()

    make_plots(prob)
Exemplo n.º 6
0
def main():
    interp = ViternaAirfoil().create_akima('mh117',
                                           Re_scaling=False,
                                           extend_alpha=True)

    def ccblade_interp(alpha, Re, Mach):
        shape = alpha.shape
        x = np.concatenate(
            [alpha.flatten()[:, np.newaxis],
             Re.flatten()[:, np.newaxis]],
            axis=-1)
        y = interp(x)
        y.shape = shape + (2, )
        return y[..., 0], y[..., 1]

    num_nodes = 1
    num_blades = 3
    num_radial = 15
    num_cp = 6
    chord = 10.
    theta = np.linspace(65., 25., num_cp) * np.pi / 180.
    pitch = 0.

    hub_diameter = 30.  # cm
    prop_diameter = 150.  # cm
    c0 = np.sqrt(1.4 * 287.058 * 300.)  # meters/second
    rho0 = 1.4 * 98600. / (c0 * c0)  # kg/m^3
    omega = 236.

    prob = Problem()

    comp = IndepVarComp()
    comp.add_discrete_input('B', val=num_blades)
    comp.add_output('rho', val=rho0, shape=num_nodes, units='kg/m**3')
    comp.add_output('mu', val=1., shape=num_nodes, units='N/m**2*s')
    comp.add_output('asound', val=c0, shape=num_nodes, units='m/s')
    comp.add_output('v', val=77.2, shape=num_nodes, units='m/s')
    comp.add_output('alpha', val=0., shape=num_nodes, units='rad')
    comp.add_output('incidence', val=0., shape=num_nodes, units='rad')
    comp.add_output('precone', val=0., units='deg')
    comp.add_output('omega', val=omega, shape=num_nodes, units='rad/s')
    comp.add_output('hub_diameter',
                    val=hub_diameter,
                    shape=num_nodes,
                    units='cm')
    comp.add_output('prop_diameter',
                    val=prop_diameter,
                    shape=num_nodes,
                    units='cm')
    comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad')
    comp.add_output('chord_dv', val=chord, shape=num_cp, units='cm')
    comp.add_output('theta_dv', val=theta, shape=num_cp, units='rad')
    prob.model.add_subsystem('inputs_comp', comp, promotes=['*'])

    comp = GeometryGroup(num_nodes=num_nodes,
                         num_cp=num_cp,
                         num_radial=num_radial)
    prob.model.add_subsystem(
        'geometry_group',
        comp,
        promotes_inputs=[
            'hub_diameter', 'prop_diameter', 'chord_dv', 'theta_dv', 'pitch'
        ],
        promotes_outputs=['radii', 'dradii', 'chord', 'theta'])

    comp = CCBladeGroup(num_nodes=num_nodes,
                        num_radial=num_radial,
                        airfoil_interp=ccblade_interp,
                        turbine=False,
                        phi_residual_solve_nonlinear=False)
    prob.model.add_subsystem('ccblade_group',
                             comp,
                             promotes_inputs=[
                                 'B', 'radii', 'dradii', 'chord', 'theta',
                                 'rho', 'mu', 'asound', 'v', 'precone',
                                 'omega', 'hub_diameter', 'prop_diameter'
                             ],
                             promotes_outputs=[('Np', 'ccblade_normal_load'),
                                               ('Tp', 'ccblade_circum_load')])

    prob.setup()
    prob.final_setup()

    eps = 1e-2
    num_phi = 45
    phi = np.linspace(-0.5 * np.pi + eps, 0.0 - eps, num_phi)
    phi = np.tile(phi[:, np.newaxis, np.newaxis], (1, num_nodes, num_radial))
    phi_residual = np.zeros_like(phi)

    for i in range(num_phi):
        p = phi[i, :, :]

        prob.set_val('ccblade_group.ccblade_comp.phi', p, units='rad')
        prob.run_model()
        prob.model.run_apply_nonlinear()
        inputs, outputs, residuals = prob.model.get_nonlinear_vectors()
        phi_residual[i, :, :] = residuals['ccblade_group.ccblade_comp.phi']

    make_individual_plots(prob, phi, phi_residual, 'phi_residual-r{:02d}.png')
Exemplo n.º 7
0
def main():
    interp = ViternaAirfoil().create_akima(
        'mh117', Re_scaling=False, extend_alpha=True)

    def ccblade_interp(alpha, Re, Mach):
        shape = alpha.shape
        x = np.concatenate(
            [
                alpha.flatten()[:, np.newaxis],
                Re.flatten()[:, np.newaxis]
            ], axis=-1)
        y = interp(x)
        y.shape = shape + (2,)
        return y[..., 0], y[..., 1]

    num_nodes = 1
    num_blades = 3
    num_radial = 15
    num_cp = 6
    chord = 10.
    theta = np.linspace(65., 25., num_cp)*np.pi/180.
    pitch = 0.

    hub_diameter = 30.  # cm
    prop_diameter = 150.  # cm
    c0 = np.sqrt(1.4*287.058*300.)  # meters/second
    rho0 = 1.4*98600./(c0*c0)  # kg/m^3
    omega = 236.

    prob = Problem()

    comp = IndepVarComp()
    comp.add_discrete_input('B', val=num_blades)
    comp.add_output('rho', val=rho0, shape=num_nodes, units='kg/m**3')
    comp.add_output('mu', val=1., shape=num_nodes, units='N/m**2*s')
    comp.add_output('asound', val=c0, shape=num_nodes, units='m/s')
    comp.add_output('v', val=77.2, shape=num_nodes, units='m/s')
    comp.add_output('alpha', val=0., shape=num_nodes, units='rad')
    comp.add_output('incidence', val=0., shape=num_nodes, units='rad')
    comp.add_output('precone', val=0., units='deg')
    comp.add_output('omega', val=omega, shape=num_nodes, units='rad/s')
    comp.add_output('hub_diameter', val=hub_diameter, shape=num_nodes, units='cm')
    comp.add_output('prop_diameter', val=prop_diameter, shape=num_nodes, units='cm')
    comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad')
    comp.add_output('chord_dv', val=chord, shape=num_cp, units='cm')
    comp.add_output('theta_dv', val=theta, shape=num_cp, units='rad')
    prob.model.add_subsystem('indep_var_comp', comp, promotes=['*'])

    comp = GeometryGroup(num_nodes=num_nodes, num_cp=num_cp,
                         num_radial=num_radial)
    prob.model.add_subsystem(
        'geometry_group', comp,
        promotes_inputs=['hub_diameter', 'prop_diameter', 'chord_dv',
                         'theta_dv', 'pitch'],
        promotes_outputs=['radii', 'dradii', 'chord', 'theta'])

    comp = SimpleInflow(num_nodes=num_nodes, num_radial=num_radial)
    prob.model.add_subsystem(
        'inflow_comp', comp,
        promotes_inputs=['v', 'omega', 'radii', 'precone'],
        promotes_outputs=['Vx', 'Vy'])

    comp = CCBladeGroup(num_nodes=num_nodes, num_radial=num_radial,
                        num_blades=num_blades,
                        airfoil_interp=ccblade_interp, turbine=False,
                        phi_residual_solve_nonlinear='bracketing')
    prob.model.add_subsystem(
        'ccblade_group', comp,
        promotes_inputs=['radii', 'dradii', 'chord', 'theta', 'rho',
                         'mu', 'asound', 'v', 'omega', 'Vx', 'Vy', 'precone',
                         'hub_diameter', 'prop_diameter'],
        promotes_outputs=['thrust', 'torque', 'efficiency'])

    prob.model.add_design_var('chord_dv', lower=1., upper=20.,
                              scaler=5e-2)
    prob.model.add_design_var('theta_dv',
                              lower=20.*np.pi/180., upper=90*np.pi/180.)

    prob.model.add_objective('efficiency', scaler=-1.,)
    prob.model.add_constraint('thrust', equals=700., scaler=1e-3,
                              indices=np.arange(num_nodes))
    prob.driver = pyOptSparseDriver()
    prob.driver.options['optimizer'] = 'SNOPT'

    prob.setup()
    prob.final_setup()
    st = time.time()
    prob.run_driver()
    elapsed_time = time.time() - st

    make_plots(prob)

    return elapsed_time
Exemplo n.º 8
0
    def test_openbemt_optimization(self):

        interp = ViternaAirfoil().create_akima('mh117',
                                               Re_scaling=False,
                                               extend_alpha=True)

        def ccblade_interp(alpha, Re, Mach):
            shape = alpha.shape
            x = np.concatenate(
                [alpha.flatten()[:, np.newaxis],
                 Re.flatten()[:, np.newaxis]],
                axis=-1)
            y = interp(x)
            y.shape = shape + (2, )
            return y[..., 0], y[..., 1]

        num_nodes = 1
        num_blades = 3
        num_radial = 15
        num_cp = 6
        chord = 10.
        theta = np.linspace(65., 25., num_cp) * np.pi / 180.
        pitch = 0.
        prop_data = {
            'num_radial': num_radial,
            'num_cp': num_cp,
            'pitch': pitch,
            'chord': chord,
            'theta': theta,
            'spline_type': 'akima',
            'B': num_blades,
            'interp': interp
        }

        hub_diameter = 30.  # cm
        prop_diameter = 150.  # cm
        c0 = np.sqrt(1.4 * 287.058 * 300.)  # meters/second
        rho0 = 1.4 * 98600. / (c0 * c0)  # kg/m^3
        omega = 236.

        prob_ccblade = om.Problem()
        prob_openbemt = om.Problem()

        comp = om.IndepVarComp()
        comp.add_output('rho', val=rho0, shape=num_nodes, units='kg/m**3')
        comp.add_output('mu', val=1., shape=num_nodes, units='N/m**2*s')
        comp.add_output('asound', val=c0, shape=num_nodes, units='m/s')
        comp.add_output('v', val=77.2, shape=num_nodes, units='m/s')
        comp.add_output('alpha', val=0., shape=num_nodes, units='rad')
        comp.add_output('incidence', val=0., shape=num_nodes, units='rad')
        comp.add_output('precone', val=0., units='deg')
        comp.add_output('omega', val=omega, shape=num_nodes, units='rad/s')
        comp.add_output('hub_diameter', val=hub_diameter, units='cm')
        comp.add_output('prop_diameter', val=prop_diameter, units='cm')
        comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad')
        comp.add_output('chord_dv', val=chord, shape=num_cp, units='cm')
        comp.add_output('theta_dv', val=theta, shape=num_cp, units='rad')
        prob_ccblade.model.add_subsystem('indep_var_comp',
                                         comp,
                                         promotes=['*'])
        prob_openbemt.model.add_subsystem('indep_var_comp',
                                          comp,
                                          promotes=['*'])

        comp = GeometryGroup(num_nodes=num_nodes,
                             num_cp=num_cp,
                             num_radial=num_radial)
        prob_ccblade.model.add_subsystem(
            'geometry_group',
            comp,
            promotes_inputs=[
                'hub_diameter', 'prop_diameter', 'chord_dv', 'theta_dv',
                'pitch'
            ],
            promotes_outputs=['radii', 'dradii', 'chord', 'theta'])

        comp = SimpleInflow(num_nodes=num_nodes, num_radial=num_radial)
        prob_ccblade.model.add_subsystem(
            'inflow_comp',
            comp,
            promotes_inputs=['v', 'omega', 'radii', 'precone'],
            promotes_outputs=['Vx', 'Vy'])

        comp = CCBladeGroup(num_nodes=num_nodes,
                            num_radial=num_radial,
                            num_blades=num_blades,
                            airfoil_interp=ccblade_interp,
                            turbine=False)
        prob_ccblade.model.add_subsystem(
            'ccblade_group',
            comp,
            promotes_inputs=[
                'radii', 'dradii', 'chord', 'theta', 'rho', 'mu', 'asound',
                'v', 'omega', 'Vx', 'Vy', 'precone', 'hub_diameter',
                'prop_diameter'
            ],
            promotes_outputs=['thrust', 'torque', 'efficiency'])

        prob_ccblade.model.add_design_var('chord_dv',
                                          lower=1.,
                                          upper=20.,
                                          scaler=5e-2)
        prob_ccblade.model.add_design_var('theta_dv',
                                          lower=20. * np.pi / 180.,
                                          upper=90 * np.pi / 180.)

        prob_ccblade.model.add_objective(
            'efficiency',
            scaler=-1.,
        )
        prob_ccblade.model.add_constraint('thrust',
                                          equals=700.,
                                          scaler=1e-3,
                                          indices=np.arange(num_nodes))
        prob_ccblade.driver = om.pyOptSparseDriver()
        prob_ccblade.driver.options['optimizer'] = 'SNOPT'

        prob_ccblade.setup()
        prob_ccblade.final_setup()
        prob_ccblade.run_driver()

        ccblade_normal_load = prob_ccblade.get_val('ccblade_group.Np',
                                                   units='N/m') * num_blades
        ccblade_circum_load = prob_ccblade.get_val('ccblade_group.Tp',
                                                   units='N/m') * num_blades

        prob_openbemt.model.add_subsystem(
            'bemt_group',
            BEMTGroup(num_nodes=num_nodes, prop_data=prop_data),
            promotes_inputs=[
                'rho', 'mu', 'v', 'alpha', 'incidence', 'omega',
                'hub_diameter', 'prop_diameter', 'pitch', 'chord_dv',
                'theta_dv'
            ],
            promotes_outputs=[('normal_load_dist', 'openbemt_normal_load'),
                              ('circum_load_dist', 'openbemt_circum_load'),
                              'dradii', 'thrust', 'efficiency'])

        prob_openbemt.model.add_design_var('chord_dv',
                                           lower=1.,
                                           upper=20.,
                                           scaler=5e-2)
        prob_openbemt.model.add_design_var('theta_dv',
                                           lower=20. * np.pi / 180.,
                                           upper=90 * np.pi / 180.)

        prob_openbemt.model.add_objective(
            'efficiency',
            scaler=-1.,
        )
        prob_openbemt.model.add_constraint('thrust',
                                           equals=700.,
                                           scaler=1e-3,
                                           indices=np.arange(num_nodes))
        prob_openbemt.driver = om.pyOptSparseDriver()
        prob_openbemt.driver.options['optimizer'] = 'SNOPT'

        prob_openbemt.setup()
        prob_openbemt.final_setup()
        prob_openbemt.model.bemt_group.phi_group.nonlinear_solver.options[
            'iprint'] = 0
        prob_openbemt.run_driver()

        openbemt_normal_load = prob_openbemt.get_val('openbemt_normal_load',
                                                     units='N')
        openbemt_circum_load = prob_openbemt.get_val('openbemt_circum_load',
                                                     units='N')
        dradii = prob_openbemt.get_val('dradii', units='m')
        openbemt_normal_load /= dradii
        openbemt_circum_load /= dradii

        assert_rel_error(self, ccblade_normal_load, openbemt_normal_load, 1e-2)
        assert_rel_error(self, ccblade_circum_load, openbemt_circum_load, 1e-2)