Exemple #1
0
def run_opt(layout_number, wec_method_number, wake_model, opt_alg_number,
            max_wec, nsteps):
    OPENMDAO_REQUIRE_MPI = False
    run_number = layout_number
    model = wake_model
    # set model
    MODELS = ['FLORIS', 'BPA', 'JENSEN', 'LARSEN']
    print(MODELS[model])

    # select optimization approach/method
    opt_algs = ['snopt', 'ga', 'ps']
    opt_algorithm = opt_algs[opt_alg_number]

    # select wec method
    wec_methods = ['none', 'diam', 'angle', 'hybrid']
    wec_method = wec_methods[wec_method_number]

    # pop_size = 760

    # save and show options
    show_start = False
    show_end = False
    save_start = False
    save_end = False

    save_locations = True
    save_aep = True
    save_time = True
    rec_func_calls = True

    input_directory = "../../../input_files/"

    # set options for BPA
    print_ti = False
    sort_turbs = True

    # turbine_type = 'NREL5MW'            #can be 'V80' or 'NREL5MW'
    turbine_type = 'V80'  # can be 'V80' or 'NREL5MW'

    wake_model_version = 2016

    WECH = 0
    if wec_method == 'diam':
        output_directory = "../output_files/%s_wec_diam_max_wec_%i_nsteps_%.3f/" % (
            opt_algorithm, max_wec, nsteps)
        relax = True
        # expansion_factors = np.array([3, 2.75, 2.5, 2.25, 2.0, 1.75, 1.5, 1.25, 1.0, 1.0])
        expansion_factors = np.linspace(1.0, max_wec, nsteps)
        expansion_factors = np.append(np.flip(expansion_factors), 1.0)
        conv_tols = np.array([1E-2, 1E-2, 1E-2, 1E-2, 1E-2, 1E-2, 1E-3])
    elif wec_method == 'angle':
        output_directory = "../output_files/%s_wec_angle_max_wec_%i_nsteps_%.3f/" % (
            opt_algorithm, max_wec, nsteps)
        relax = True
        # expansion_factors = np.array([50, 40, 30, 20, 10, 0.0, 0.0])
        expansion_factors = np.linspace(0.0, max_wec, nsteps)
        expansion_factors = np.append(np.flip(expansion_factors), 0.0)
    elif wec_method == 'hybrid':
        expansion_factors = np.linspace(1.0, max_wec, nsteps)
        expansion_factors = np.append(np.flip(expansion_factors), 1.0)
        output_directory = "../output_files/%s_wec_hybrid_max_wec_%i_nsteps_%.3f/" % (
            opt_algorithm, max_wec, nsteps)
        relax = True
        WECH = 1
    elif wec_method == 'none':
        relax = False
        if opt_algorithm == "ps":
            expansion_factors = np.array([1.0])
            conv_tols = np.array([1E-3])
        else:
            expansion_factors = np.array([1.0, 1.0])
            conv_tols = np.array([1E-2, 1E-3])
        output_directory = "../output_files/%s/" % opt_algorithm
    else:
        raise ValueError('wec_method must be diam, angle, hybrid, or none')

    # create output directory if it does not exist yet
    import distutils.dir_util
    distutils.dir_util.mkpath(output_directory)

    differentiable = True

    # for expansion_factor in np.array([5., 4., 3., 2.75, 2.5, 2.25, 2.0, 1.75, 1.5, 1.25, 1.0]):
    # for expansion_factor in np.array([20., 15., 10., 5., 4., 3., 2.5, 1.25, 1.0]):
    # expansion_factors = np.array([20., 10., 5., 2.5, 1.25, 1.0])

    wake_combination_method = 1  # can be [0:Linear freestreem superposition,
    #  1:Linear upstream velocity superposition,
    #  2:Sum of squares freestream superposition,
    #  3:Sum of squares upstream velocity superposition]

    ti_calculation_method = 4  # can be [0:No added TI calculations,
    # 1:TI by Niayifar and Porte Agel altered by Annoni and Thomas,
    # 2:TI by Niayifar and Porte Agel 2016,
    # 3:TI by Niayifar and Porte Agel 2016 with added soft max function,
    # 4:TI by Niayifar and Porte Agel 2016 using area overlap ratio,
    # 5:TI by Niayifar and Porte Agel 2016 using area overlap ratio and SM function]

    if wec_method_number > 0:
        ti_opt_method = 0  # can be [0:No added TI calculations,
        # 1:TI by Niayifar and Porte Agel altered by Annoni and Thomas,
        # 2:TI by Niayifar and Porte Agel 2016,
        # 3:TI by Niayifar and Porte Agel 2016 with added soft max function,
        # 4:TI by Niayifar and Porte Agel 2016 using area overlap ratio,
        # 5:TI by Niayifar and Porte Agel 2016 using area overlap ratio and SM function]

    else:
        ti_opt_method = 0
    final_ti_opt_method = 5

    if opt_algorithm == 'ps':
        ti_opt_method = ti_calculation_method

    sm_smoothing = 700.

    if ti_calculation_method == 0:
        calc_k_star_calc = False
    else:
        calc_k_star_calc = True

    if ti_opt_method == 0:
        calc_k_star_opt = False
    else:
        calc_k_star_opt = True

    nRotorPoints = 1

    wind_rose_file = 'directional'  # can be one of: 'amalia', 'nantucket', 'directional'

    TI = 0.108
    k_calc = 0.3837 * TI + 0.003678
    # k_calc = 0.022
    # k_opt = 0.04

    shear_exp = 0.31

    # air_density = 1.1716  # kg/m^3
    air_density = 1.225  # kg/m^3 (from Jen)

    if turbine_type == 'V80':

        # define turbine size
        rotor_diameter = 80.  # (m)
        hub_height = 70.0

        z_ref = 80.0  # m
        z_0 = 0.0

        # load performance characteristics
        cut_in_speed = 4.  # m/s
        cut_out_speed = 25.  # m/s
        rated_wind_speed = 16.  # m/s
        rated_power = 2000.  # kW
        generator_efficiency = 0.944

        ct_curve_data = np.loadtxt(input_directory +
                                   'mfg_ct_vestas_v80_niayifar2016.txt',
                                   delimiter=",")
        ct_curve_wind_speed = ct_curve_data[:, 0]
        ct_curve_ct = ct_curve_data[:, 1]

        # air_density = 1.1716  # kg/m^3
        Ar = 0.25 * np.pi * rotor_diameter**2
        # cp_curve_wind_speed = ct_curve[:, 0]
        power_data = np.loadtxt(input_directory +
                                'niayifar_vestas_v80_power_curve_observed.txt',
                                delimiter=',')
        # cp_curve_cp = niayifar_power_model(cp_curve_wind_speed)/(0.5*air_density*cp_curve_wind_speed**3*Ar)
        cp_curve_cp = power_data[:, 1] * (1E6) / (0.5 * air_density *
                                                  power_data[:, 0]**3 * Ar)
        cp_curve_wind_speed = power_data[:, 0]
        cp_curve_spline = UnivariateSpline(cp_curve_wind_speed,
                                           cp_curve_cp,
                                           ext='const')
        cp_curve_spline.set_smoothing_factor(.0001)

    elif turbine_type == 'NREL5MW':

        # define turbine size
        rotor_diameter = 126.4  # (m)
        hub_height = 90.0

        z_ref = 80.0  # m
        z_0 = 0.0

        # load performance characteristics
        cut_in_speed = 3.  # m/s
        cut_out_speed = 25.  # m/s
        rated_wind_speed = 11.4  # m/s
        rated_power = 5000.  # kW
        generator_efficiency = 0.944

        filename = input_directory + "NREL5MWCPCT_dict.p"
        # filename = "../input_files/NREL5MWCPCT_smooth_dict.p"
        import pickle

        data = pickle.load(open(filename, "rb"), encoding='latin1')
        ct_curve = np.zeros([data['wind_speed'].size, 2])
        ct_curve_wind_speed = data['wind_speed']
        ct_curve_ct = data['CT']

        # cp_curve_cp = data['CP']
        # cp_curve_wind_speed = data['wind_speed']

        loc0 = np.where(data['wind_speed'] < 11.55)
        loc1 = np.where(data['wind_speed'] > 11.7)

        cp_curve_cp = np.hstack([data['CP'][loc0], data['CP'][loc1]])
        cp_curve_wind_speed = np.hstack(
            [data['wind_speed'][loc0], data['wind_speed'][loc1]])
        cp_curve_spline = UnivariateSpline(cp_curve_wind_speed,
                                           cp_curve_cp,
                                           ext='const')
        cp_curve_spline.set_smoothing_factor(.000001)
    else:
        raise ValueError("Turbine type is undefined.")

    # load starting locations
    layout_directory = input_directory

    # layout_data = np.loadtxt(layout_directory + "layouts/round_38turbs/nTurbs38_spacing5_layout_%i.txt" % layout_number)
    layout_data = np.loadtxt(
        layout_directory +
        "layouts/grid_16turbs/nTurbs16_spacing5_layout_%i.txt" % layout_number)
    # layout_data = np.loadtxt(layout_directory+"layouts/nTurbs9_spacing5_layout_%i.txt" % layout_number)

    turbineX = layout_data[:, 0] * rotor_diameter
    turbineY = layout_data[:, 1] * rotor_diameter

    turbineX_init = np.copy(turbineX)
    turbineY_init = np.copy(turbineY)

    nTurbines = turbineX.size

    boundary_x = np.array(
        [0.0, 5. * rotor_diameter * (np.sqrt(nTurbines) - 1) + rotor_diameter])
    boundary_y = np.array(
        [0.0, 5. * rotor_diameter * (np.sqrt(nTurbines) - 1) + rotor_diameter])

    if show_start:
        plot_square_farm(turbineX_init,
                         turbineY_init,
                         rotor_diameter,
                         boundary_x,
                         boundary_y,
                         boundary_x[1] - boundary_x[0],
                         show_start=show_start)

    # plot_round_farm(turbineX, turbineY, rotor_diameter, [boundary_center_x, boundary_center_y], boundary_radius,
    #                 show_start=show_start)
    # quit()
    # initialize input variable arrays
    nTurbs = nTurbines
    rotorDiameter = np.zeros(nTurbs)
    hubHeight = np.zeros(nTurbs)
    axialInduction = np.zeros(nTurbs)
    Ct = np.zeros(nTurbs)
    Cp = np.zeros(nTurbs)
    generatorEfficiency = np.zeros(nTurbs)
    yaw = np.zeros(nTurbs)
    minSpacing = 2.  # number of rotor diameters

    # define initial values
    for turbI in range(0, nTurbs):
        rotorDiameter[turbI] = rotor_diameter  # m
        hubHeight[turbI] = hub_height  # m
        axialInduction[turbI] = 1.0 / 3.0
        Ct[turbI] = 4.0 * axialInduction[turbI] * (1.0 - axialInduction[turbI])
        # print(Ct)
        Cp[turbI] = 4.0 * 1.0 / 3.0 * np.power((1 - 1.0 / 3.0), 2)
        generatorEfficiency[turbI] = generator_efficiency
        yaw[turbI] = 0.  # deg.

    # Define flow properties
    if wind_rose_file == 'nantucket':
        # windRose = np.loadtxt(input_directory + 'nantucket_windrose_ave_speeds.txt')
        windRose = np.loadtxt(input_directory +
                              'nantucket_wind_rose_for_LES.txt')
        windDirections = windRose[:, 0]
        windSpeeds = windRose[:, 1]
        windFrequencies = windRose[:, 2]
        size = np.size(windDirections)
    elif wind_rose_file == 'amalia':
        windRose = np.loadtxt(
            input_directory +
            'windrose_amalia_directionally_averaged_speeds.txt')
        windDirections = windRose[:, 0]
        windSpeeds = windRose[:, 1]
        windFrequencies = windRose[:, 2]
        size = np.size(windDirections)
    elif wind_rose_file == 'directional':
        windRose = np.loadtxt(input_directory + 'directional_windrose.txt')
        windDirections = windRose[:, 0]
        windSpeeds = windRose[:, 1]
        windFrequencies = windRose[:, 2]
        size = np.size(windDirections)
    elif wind_rose_file == '1d':
        windDirections = np.array([270.])
        windSpeeds = np.array([8.0])
        windFrequencies = np.array([1.0])
        size = np.size(windDirections)
    else:
        size = 20
        windDirections = np.linspace(0, 270, size)
        windFrequencies = np.ones(size) / size

    wake_model_options = {
        'nSamples': 0,
        'nRotorPoints': nRotorPoints,
        'use_ct_curve': True,
        'ct_curve_ct': ct_curve_ct,
        'ct_curve_wind_speed': ct_curve_wind_speed,
        'interp_type': 1,
        'use_rotor_components': False,
        'differentiable': differentiable,
        'verbose': False
    }

    nVertices = 0
    if MODELS[model] == 'BPA':
        # initialize problem
        prob = om.Problem(
            model=OptAEP(nTurbines=nTurbs,
                         nDirections=windDirections.size,
                         nVertices=nVertices,
                         minSpacing=minSpacing,
                         differentiable=differentiable,
                         use_rotor_components=False,
                         wake_model=gauss_wrapper,
                         params_IdepVar_func=add_gauss_params_IndepVarComps,
                         params_IdepVar_args={'nRotorPoints': nRotorPoints},
                         wake_model_options=wake_model_options,
                         cp_points=cp_curve_cp.size,
                         cp_curve_spline=cp_curve_spline,
                         record_function_calls=True,
                         runparallel=False))
    elif MODELS[model] == 'FLORIS':
        # initialize problem
        prob = om.Problem(
            model=OptAEP(nTurbines=nTurbs,
                         nDirections=windDirections.size,
                         nVertices=nVertices,
                         minSpacing=minSpacing,
                         differentiable=differentiable,
                         use_rotor_components=False,
                         wake_model=floris_wrapper,
                         params_IdepVar_func=add_floris_params_IndepVarComps,
                         params_IdepVar_args={},
                         record_function_calls=True))
    # elif MODELS[model] == 'JENSEN':
    #     initialize problem
    # prob = om.Problem(model=OptAEP(nTurbines=nTurbs, nDirections=windDirections.size, nVertices=nVertices,
    #                                       minSpacing=minSpacing, differentiable=False, use_rotor_components=False,
    #                                       wake_model=jensen_wrapper,
    #                                       params_IdepVar_func=add_jensen_params_IndepVarComps,
    #                                       params_IdepVar_args={},
    #                                               record_function_calls=True))
    else:
        ValueError(
            'The %s model is not currently available. Please select BPA or FLORIS'
            % (MODELS[model]))
    # prob.model.deriv_options['type'] = 'fd'
    # prob.model.deriv_options['form'] = 'central'
    # prob.model.deriv_options['step_size'] = 1.0e-8
    # prob.model.linear_solver = om.LinearBlockGS()
    # prob.model.linear_solver.options['iprint'] = 0
    # prob.model.linear_solver.options['maxiter'] = 5
    #
    # prob.model.nonlinear_solver = om.NonlinearBlockGS()
    # prob.model.nonlinear_solver.options['iprint'] = 0

    # prob.model.linear_solver = om.DirectSolver()

    prob.driver = om.pyOptSparseDriver()

    if opt_algorithm == 'snopt':
        # set up optimizer
        prob.driver.options['optimizer'] = 'SNOPT'
        # prob.driver.options['gradient method'] = 'snopt_fd'

        # set optimizer options
        prob.driver.opt_settings['Verify level'] = -1
        # set optimizer options
        prob.driver.opt_settings['Major optimality tolerance'] = np.float(1e-3)

        prob.driver.opt_settings[
            'Print file'] = output_directory + 'SNOPT_print_multistart_%iturbs_%sWindRose_%idirs_%sModel_RunID%i.out' % (
                nTurbs, wind_rose_file, size, MODELS[model], run_number)
        prob.driver.opt_settings[
            'Summary file'] = output_directory + 'SNOPT_summary_multistart_%iturbs_%sWindRose_%idirs_%sModel_RunID%i.out' % (
                nTurbs, wind_rose_file, size, MODELS[model], run_number)

        prob.model.add_constraint('sc',
                                  lower=np.zeros(
                                      int(((nTurbs - 1.) * nTurbs / 2.))),
                                  scaler=1E-2)  # ,
        # active_tol=(2. * rotor_diameter) ** 2)
        # prob.model.add_constraint('boundaryDistances', lower=(np.zeros(1 * turbineX.size)), scaler=1E-2)  # ,
        # active_tol=2. * rotor_diameter)

        prob.driver.options['dynamic_derivs_sparsity'] = True

    elif opt_algorithm == 'ga':

        prob.driver.options['optimizer'] = 'NSGA2'

        prob.driver.opt_settings['PrintOut'] = 1

        prob.driver.opt_settings['maxGen'] = 50000

        prob.driver.opt_settings['PopSize'] = 10 * nTurbines * 2

        # prob.driver.opt_settings['pMut_real'] = 0.001

        prob.driver.opt_settings['xinit'] = 1

        prob.driver.opt_settings['rtol'] = 1E-4

        prob.driver.opt_settings['atol'] = 1E-4

        prob.driver.opt_settings['min_tol_gens'] = 200

        prob.driver.opt_settings['file_number'] = run_number

        prob.model.add_constraint('sc',
                                  lower=np.zeros(
                                      int(((nTurbs - 1.) * nTurbs / 2.))),
                                  scaler=1E-2)
        # prob.model.add_constraint('boundaryDistances', lower=(np.zeros(1 * turbineX.size)), scaler=1E-2)

    elif opt_algorithm == 'ps':

        prob.driver.options['optimizer'] = 'ALPSO'

        prob.driver.opt_settings['fileout'] = 1

        prob.driver.opt_settings[
            'filename'] = output_directory + 'ALPSO_summary_multistart_%iturbs_%sWindRose_%idirs_%sModel_RunID%i.out' % (
                nTurbs, wind_rose_file, size, MODELS[model], run_number)

        prob.driver.opt_settings['maxOuterIter'] = 10000
        # prob.driver.opt_settings['stopIters'] = 10
        # prob.driver.opt_settings['minInnerIter'] = 100

        prob.driver.opt_settings['SwarmSize'] = 25

        prob.driver.opt_settings[
            'xinit'] = 1  # Initial Position Flag (0 - no position, 1 - position given)

        prob.driver.opt_settings[
            'Scaling'] = 1  # Design Variables Scaling Flag (0 - no scaling, 1 - scaling between [-1, 1])

        # prob.driver.opt_settings['rtol'] = 1E-3  # Relative Tolerance for Lagrange Multipliers
        #
        # prob.driver.opt_settings['atol'] = 1E-2  # Absolute Tolerance for Lagrange Function
        #
        prob.driver.opt_settings[
            'dtol'] = 0.01  # Relative Tolerance in Distance of All Particles to Terminate (GCPSO)
        #
        # prob.driver.opt_settings['itol'] = 1E-3  # Absolute Tolerance for Inequality constraints
        #
        # prob.driver.opt_settings['dynInnerIter'] = 1  # Dynamic Number of Inner Iterations Flag

        prob.model.add_constraint('sc',
                                  lower=np.zeros(
                                      int(((nTurbs - 1.) * nTurbs / 2.))),
                                  scaler=1E-2)
        # prob.model.add_constraint('boundaryDistances', lower=(np.zeros(1 * turbineX.size)), scaler=1E-2)

        # prob.driver.add_objective('obj', scaler=1E0)
    prob.model.add_objective('obj', scaler=1E-4)

    # select design variables
    prob.model.add_design_var(
        'turbineX',
        scaler=1E0,
        lower=np.ones(nTurbines) * (boundary_x[0] + rotor_diameter / 2.),
        upper=np.ones(nTurbines) * (boundary_x[1] - rotor_diameter / 2.))
    prob.model.add_design_var(
        'turbineY',
        scaler=1E0,
        lower=np.ones(nTurbines) * (boundary_y[0] + rotor_diameter / 2.),
        upper=np.ones(nTurbines) * (boundary_y[1] - rotor_diameter / 2.))

    # prob.driver.recording_options['include'] = ['obj']

    # prob.model.ln_solver.options['single_voi_relevance_reduction'] = True
    # prob.model.ln_solver.options['mode'] = 'rev'

    # if run_number == 0:
    #     # set up recorder
    #     recorder = SqliteRecorder(output_directory+'recorder_database_run%i' % run_number)
    #     recorder.options['record_params'] = True
    #     recorder.options['record_metadata'] = False
    #     recorder.options['record_unknowns'] = True
    #     recorder.options['record_derivs'] = False
    #     recorder.options['includes'] = ['turbineX', 'turbineY', 'AEP']
    #     prob.driver.add_recorder(recorder)

    driver_recorder = om.SqliteRecorder(output_directory +
                                        'recorded_data_driver_%s.sql' %
                                        (run_number))
    # model_recorder = om.SqliteRecorder(output_directory + 'recorded_data_model_%s.sql' %(run_number))
    prob.driver.add_recorder(driver_recorder)
    # prob.model.add_recorder(model_recorder)
    prob.driver.recording_options['record_constraints'] = False
    prob.driver.recording_options['record_derivatives'] = False
    prob.driver.recording_options['record_desvars'] = True
    prob.driver.recording_options['record_inputs'] = False
    prob.driver.recording_options['record_model_metadata'] = True
    prob.driver.recording_options['record_objectives'] = True
    prob.driver.recording_options['includes'] = ['AEP']
    prob.driver.recording_options['record_responses'] = False
    #
    # prob_recorder = om.SqliteRecorder(output_directory + 'recorded_data_prob_%s.sql' %(run_number))
    # prob.add_recorder(prob_recorder)
    # prob.recording_options['includes'] = []
    # prob.recording_options['record_objectives'] = True

    # prob.model.recording_options['record_constraints'] = False
    # prob.model.recording_options['record_derivatives'] = False
    # prob.model.recording_options['record_desvars'] = False
    # prob.model.recording_options['record_inputs'] = False
    # prob.model.recording_options['record_model_metadata'] = False
    # prob.model.recording_options['record_objectives'] = True
    # prob.model.recording_options['includes'] = ['AEP']
    # prob.model.recording_options['record_responses'] = False
    # prob.set_solver_print(0)
    # prob.record_iteration('all')
    # set up profiling
    # from plantenergy.GeneralWindFarmComponents import WindFarmAEP
    # methods = [
    #     ('*', (WindFarmAEP,))
    # ]
    #
    # iprofile.setup(methods=methods)

    print("almost time for setup")
    tic = time.time()
    print("entering setup at time = ", tic)
    prob.setup(check=True)
    toc = time.time()
    print("setup complete at time = ", toc)

    # print the results
    print(('Problem setup took %.03f sec.' % (toc - tic)))

    # assign initial values to design variables
    prob['turbineX'] = np.copy(turbineX)
    prob['turbineY'] = np.copy(turbineY)
    for direction_id in range(0, windDirections.size):
        prob['yaw%i' % direction_id] = yaw

    # assign values to constant inputs (not design variables)
    prob['rotorDiameter'] = rotorDiameter
    prob['hubHeight'] = hubHeight
    prob['axialInduction'] = axialInduction
    prob['generatorEfficiency'] = generatorEfficiency
    prob['windSpeeds'] = windSpeeds
    prob['air_density'] = air_density
    prob['windDirections'] = windDirections
    prob['windFrequencies'] = windFrequencies
    prob['Ct_in'] = Ct
    prob['Cp_in'] = Cp
    prob['cp_curve_cp'] = cp_curve_cp
    prob['cp_curve_wind_speed'] = cp_curve_wind_speed
    cutInSpeeds = np.ones(nTurbines) * cut_in_speed
    prob['cut_in_speed'] = cutInSpeeds
    ratedPowers = np.ones(nTurbines) * rated_power
    prob['rated_power'] = ratedPowers

    # assign values to turbine states
    prob['cut_in_speed'] = np.ones(nTurbines) * cut_in_speed
    prob['cut_out_speed'] = np.ones(nTurbines) * cut_out_speed
    prob['rated_power'] = np.ones(nTurbines) * rated_power
    prob['rated_wind_speed'] = np.ones(nTurbines) * rated_wind_speed
    prob['use_power_curve_definition'] = True

    # assign boundary values
    # prob['boundary_center'] = np.array([boundary_center_x, boundary_center_y])
    # prob['boundary_radius'] = boundary_radius

    if MODELS[model] == 'BPA':
        prob['model_params:wake_combination_method'] = np.copy(
            wake_combination_method)
        prob['model_params:ti_calculation_method'] = np.copy(
            ti_calculation_method)
        prob['model_params:wake_model_version'] = np.copy(wake_model_version)
        prob['model_params:wec_factor'] = 1.0
        prob['model_params:wec_spreading_angle'] = 0.0
        prob['model_params:calc_k_star'] = np.copy(calc_k_star_calc)
        prob['model_params:sort'] = np.copy(sort_turbs)
        prob['model_params:z_ref'] = np.copy(z_ref)
        prob['model_params:z_0'] = np.copy(z_0)
        prob['model_params:ky'] = np.copy(k_calc)
        prob['model_params:kz'] = np.copy(k_calc)
        prob['model_params:print_ti'] = np.copy(print_ti)
        prob['model_params:shear_exp'] = np.copy(shear_exp)
        prob['model_params:I'] = np.copy(TI)
        prob['model_params:sm_smoothing'] = np.copy(sm_smoothing)
        prob['model_params:WECH'] = WECH
        if nRotorPoints > 1:
            prob['model_params:RotorPointsY'], prob[
                'model_params:RotorPointsZ'] = sunflower_points(nRotorPoints)

    modelruns = 0
    prob.run_model(case_prefix='ModelRun%i' % modelruns)
    AEP_init_calc = np.copy(prob['AEP'])
    print(AEP_init_calc * 1E-6)

    if MODELS[model] == 'BPA':
        prob['model_params:ti_calculation_method'] = np.copy(ti_opt_method)
        prob['model_params:calc_k_star'] = np.copy(calc_k_star_opt)

    modelruns += 1
    prob.run_model(case_prefix='ModelRun%i' % modelruns)
    AEP_init_opt = np.copy(prob['AEP'])
    AEP_run_opt = np.copy(AEP_init_opt)
    print(AEP_init_opt * 1E-6)

    config.obj_func_calls_array[:] = 0.0
    config.sens_func_calls_array[:] = 0.0

    expansion_factor_last = 0.0
    driverruns = 0
    tict = time.time()
    if relax:
        for expansion_factor, i in zip(
                expansion_factors,
                np.arange(0, expansion_factors.size)):  # best so far
            # print("func calls: ", config.obj_func_calls_array, np.sum(config.obj_func_calls_array))
            # print("grad func calls: ", config.sens_func_calls_array, np.sum(config.sens_func_calls_array))
            # AEP_init_run_opt = prob['AEP']

            if expansion_factor_last == expansion_factor:
                ti_opt_method = np.copy(final_ti_opt_method)
                calc_k_star_opt = True

            print("starting run with exp. fac = ", expansion_factor)

            if opt_algorithm == 'snopt':

                # adjust convergence tolerance
                prob.driver.opt_settings['Major optimality tolerance'] = float(
                    conv_tols[i])
                prob.driver.opt_settings['Print file'] = output_directory + \
                                                         'SNOPT_print_multistart_%iturbs_%sWindRose_%idirs_%sModel_RunID%i_EF%.3f_TItype%i.out' % (
                                                             nTurbs, wind_rose_file, size, MODELS[model], run_number,
                                                             expansion_factor, ti_opt_method)

                prob.driver.opt_settings['Summary file'] = output_directory + \
                                                           'SNOPT_summary_multistart_%iturbs_%sWindRose_%idirs_%sModel_RunID%i_EF%.3f_TItype%i.out' % (
                                                               nTurbs, wind_rose_file, size, MODELS[model], run_number,
                                                               expansion_factor, ti_opt_method)
            elif opt_algorithm == 'ps':
                prob.driver.opt_settings[
                    'filename'] = output_directory + 'ALPSO_summary_multistart_%iturbs_%sWindRose_%idirs_%sModel_RunID%i.out' % (
                        nTurbs, wind_rose_file, size, MODELS[model],
                        run_number)

            turbineX = np.copy(prob['turbineX'])
            turbineY = np.copy(prob['turbineY'])
            prob['turbineX'] = np.copy(turbineX)
            prob['turbineY'] = np.copy(turbineY)

            if MODELS[model] == 'BPA':
                prob['model_params:ti_calculation_method'] = np.copy(
                    ti_opt_method)
                prob['model_params:calc_k_star'] = np.copy(calc_k_star_opt)
                if wec_method == 'diam':
                    prob['model_params:wec_factor'] = np.copy(expansion_factor)
                elif wec_method == "hybrid":
                    prob['model_params:wec_factor'] = np.copy(expansion_factor)
                elif wec_method == 'angle':
                    prob['model_params:wec_spreading_angle'] = np.copy(
                        expansion_factor)

            # run the problem
            print('start %s run' % (MODELS[model]))
            tic = time.time()
            # iprofile.start()
            config.obj_func_calls_array[prob.comm.rank] = 0.0
            config.sens_func_calls_array[prob.comm.rank] = 0.0
            prob.run_driver(case_prefix='DriverRun%i' % driverruns)
            driverruns += 1
            # quit()
            toc = time.time()
            obj_calls = np.copy(config.obj_func_calls_array[0])
            sens_calls = np.copy(config.sens_func_calls_array[0])
            # iprofile.stop()
            toc = time.time()
            # print(np.sum(config.obj_func_calls_array))
            # print(np.sum(config.sens_func_calls_array))
            print('end %s run' % (MODELS[model]))

            run_time = toc - tic
            # print(run_time, expansion_factor)

            AEP_run_opt = np.copy(prob['AEP'])
            # print("AEP improvement = ", AEP_run_opt / AEP_init_opt)

            if MODELS[model] == 'BPA':
                prob['model_params:wec_factor'] = 1.0
                prob['model_params:wec_spreading_angle'] = 0.0
                prob['model_params:ti_calculation_method'] = np.copy(
                    ti_calculation_method)
                prob['model_params:calc_k_star'] = np.copy(calc_k_star_calc)

            modelruns += 1
            prob.run_model(case_prefix='ModelRun%i' % modelruns)
            AEP_run_calc = np.copy(prob['AEP'])
            # print("compare: ", aep_run, prob['AEP'])
            print("AEP calc improvement = ", AEP_run_calc / AEP_init_calc)

            if prob.model.comm.rank == 0:
                # if save_aep:
                #     np.savetxt(output_directory + '%s_multistart_aep_results_%iturbs_%sWindRose_%idirs_%sModel_RunID%i_EF%.3f.txt' % (
                #         opt_algorithm, nTurbs, wind_rose_file, size, MODELS[model], run_number, expansion_factor),
                #                np.c_[AEP_init, prob['AEP']],
                #                header="Initial AEP, Final AEP")
                if save_locations:
                    np.savetxt(
                        output_directory +
                        '%s_multistart_locations_%iturbs_%sWindRose_%idirs_%s_run%i_EF%.3f_TItype%i.txt'
                        % (opt_algorithm, nTurbs, wind_rose_file, size,
                           MODELS[model], run_number, expansion_factor,
                           ti_opt_method),
                        np.c_[turbineX_init, turbineY_init, prob['turbineX'],
                              prob['turbineY']],
                        header=
                        "initial turbineX, initial turbineY, final turbineX, final turbineY"
                    )
                # if save_time:
                #     np.savetxt(output_directory + '%s_multistart_time_%iturbs_%sWindRose_%idirs_%s_run%i_EF%.3f.txt' % (
                #         opt_algorithm, nTurbs, wind_rose_file, size, MODELS[model], run_number, expansion_factor),
                #                np.c_[run_time],
                #                header="run time")
                if save_time and save_aep and rec_func_calls:
                    output_file = output_directory + '%s_multistart_rundata_%iturbs_%sWindRose_%idirs_%s_run%i.txt' \
                                  % (opt_algorithm, nTurbs, wind_rose_file, size, MODELS[model], run_number)
                    f = open(output_file, "a")

                    if i == 0:
                        header = "run number, exp fac, ti calc, ti opt, aep init calc (kW), aep init opt (kW), " \
                                 "aep run calc (kW), aep run opt (kW), run time (s), obj func calls, sens func calls"
                    else:
                        header = ''

                    np.savetxt(f,
                               np.c_[run_number, expansion_factor,
                                     ti_calculation_method, ti_opt_method,
                                     AEP_init_calc, AEP_init_opt, AEP_run_calc,
                                     AEP_run_opt, run_time, obj_calls,
                                     sens_calls],
                               header=header)
                    f.close()
            expansion_factor_last = expansion_factor
            #
            # cr = om.CaseReader(output_directory + 'recorded_data.sql')
            #
            # driver_cases = cr.list_cases('driver')
            # nits = len(driver_cases)
            # objectives = np.zeros(nits)
            # calls = np.zeros(nits)
            # for i in np.arange(0, nits):
            #     case = cr.get_case(driver_cases[i])
            #     print(case)
            #     objectives[i] = np.copy(case['obj'])
            #     calls[i] = i
            # plt.plot(objectives)
            # plt.scatter(calls, objectives)
            # plt.show()

    else:
        for expansion_factor, i in zip(
                expansion_factors,
                np.arange(0, expansion_factors.size)):  # best so far
            # print("func calls: ", config.obj_func_calls_array, np.sum(config.obj_func_calls_array))
            # print("grad func calls: ", config.sens_func_calls_array, np.sum(config.sens_func_calls_array))
            # AEP_init_run_opt = prob['AEP']

            if expansion_factor_last == expansion_factor:
                ti_opt_method = np.copy(final_ti_opt_method)
                calc_k_star_opt = True

            if opt_algorithm == 'snopt':
                prob.driver.opt_settings['Major optimality tolerance'] = float(
                    conv_tols[i])
                prob.driver.opt_settings['Print file'] = output_directory + \
                                                         'SNOPT_print_multistart_%iturbs_%sWindRose_%idirs_%sModel_RunID%i_TItype%i.out' % (
                                                             nTurbs, wind_rose_file, size, MODELS[model], run_number, ti_opt_method)

                prob.driver.opt_settings['Summary file'] = output_directory + \
                                                           'SNOPT_summary_multistart_%iturbs_%sWindRose_%idirs_%sModel_RunID%i_TItype%i.out' % (
                                                               nTurbs, wind_rose_file, size, MODELS[model], run_number, ti_opt_method)

            print("starting run with exp. fac = ", expansion_factor)
            # run the problem
            print('start %s run' % (MODELS[model]))
            # cProfile.run('prob.run_driver()')
            if MODELS[model] == 'BPA':
                # prob['model_params:wec_factor'] = 1.
                prob['model_params:ti_calculation_method'] = np.copy(
                    ti_opt_method)
                prob['model_params:calc_k_star'] = np.copy(calc_k_star_opt)
            tic = time.time()
            # cProfile.run('prob.run_driver()')
            config.obj_func_calls_array[prob.comm.rank] = 0.0
            config.sens_func_calls_array[prob.comm.rank] = 0.0
            prob.run_driver(case_prefix='DriverRun%i' % driverruns)
            driverruns += 1
            # quit()
            toc = time.time()
            obj_calls = np.copy(config.obj_func_calls_array[0])
            sens_calls = np.copy(config.sens_func_calls_array[0])

            run_time = toc - tic

            AEP_run_opt = np.copy(prob['AEP'])
            # print("AEP improvement = ", AEP_run_calc / AEP_init_calc)

            if MODELS[model] == 'BPA':
                prob['model_params:wec_factor'] = 1.0
                prob['model_params:wec_spreading_angle'] = 0.0
                prob['model_params:ti_calculation_method'] = np.copy(
                    ti_calculation_method)
                prob['model_params:calc_k_star'] = np.copy(calc_k_star_calc)

            modelruns += 1
            prob.run_model(case_prefix='ModelRun%i' % modelruns)
            AEP_run_calc = np.copy(prob['AEP'])

            if prob.model.comm.rank == 0:

                if save_locations:
                    np.savetxt(
                        output_directory +
                        '%s_multistart_locations_%iturbs_%sWindRose_%idirs_%s_run%i_TItype%i.txt'
                        % (opt_algorithm, nTurbs, wind_rose_file, size,
                           MODELS[model], run_number, ti_opt_method),
                        np.c_[turbineX_init, turbineY_init, prob['turbineX'],
                              prob['turbineY']],
                        header=
                        "initial turbineX, initial turbineY, final turbineX, final turbineY"
                    )

                if save_time and save_aep and rec_func_calls:
                    output_file = output_directory + '%s_multistart_rundata_%iturbs_%sWindRose_%idirs_%s_run%i_TItype%i.txt' \
                                  % (opt_algorithm, nTurbs, wind_rose_file, size, MODELS[model], run_number, ti_opt_method)
                    f = open(output_file, "a")

                    header = "run number, ti calc, ti opt, aep init calc (kW), aep init opt (kW), " \
                             "aep run calc (kW), aep run opt (kW), run time (s), obj func calls, sens func calls"

                    np.savetxt(f,
                               np.c_[run_number, ti_calculation_method,
                                     ti_opt_method, AEP_init_calc,
                                     AEP_init_opt, AEP_run_calc, AEP_run_opt,
                                     run_time, obj_calls, sens_calls],
                               header=header)
                    f.close()
            expansion_factor_last = expansion_factor

    turbineX_end = np.copy(prob['turbineX'])
    turbineY_end = np.copy(prob['turbineY'])

    toct = time.time()
    total_time = toct - tict

    if prob.model.comm.rank == 0:

        # print the results
        print(('Opt. calculation took %.03f sec.' % (toct - tict)))

        for direction_id in range(0, windDirections.size):
            print('yaw%i (deg) = ' % direction_id,
                  prob['yaw%i' % direction_id])

        print('turbine X positions in wind frame (m): %s' % prob['turbineX'])
        print('turbine Y positions in wind frame (m): %s' % prob['turbineY'])
        print('wind farm power in each direction (kW): %s' % prob['dirPowers'])
        print('Initial AEP (kWh): %s' % AEP_init_opt)
        print('Final AEP (kWh): %s' % AEP_run_calc)
        print('AEP improvement: %s' % (AEP_run_calc / AEP_init_calc))

    if show_end:
        plot_square_farm(turbineX_end,
                         turbineY_end,
                         rotor_diameter,
                         boundary_x,
                         boundary_y,
                         boundary_x[1] - boundary_x[0],
                         show_start=show_start)

    prob.cleanup()

    if MODELS[model] == 'BPA':
        prob['model_params:wec_factor'] = 1.0
        prob['model_params:wec_spreading_angle'] = 0.0
        prob['model_params:ti_calculation_method'] = 4
        prob['model_params:calc_k_star'] = True

    cr = om.CaseReader(output_directory +
                       'recorded_data_driver_%s.sql' % run_number)

    driver_cases = cr.list_cases('driver')
    nits = len(driver_cases)
    objectives = np.zeros(nits)
    AEPopt = np.zeros(nits)
    AEPcalc = np.zeros(nits)
    calls = np.zeros(nits)
    for i in np.arange(0, nits):
        case = cr.get_case(driver_cases[i])
        # print(case)
        AEPopt[i] = case['AEP']
        objectives[i] = case.get_objectives()['obj']

        prob['turbineX'] = np.copy(case['turbineX'])
        prob['turbineY'] = np.copy(case['turbineY'])
        if opt_algorithm == "snopt":
            prob.run_model(case_prefix='ProcessingRun')
            AEPcalc[i] = np.copy(prob['AEP'])
        else:
            AEPcalc[i] = case['AEP']

        calls[i] = i
Exemple #2
0
def set_up_prob():
    layout_number = 0
    wec_method_number = 0
    wake_model = 1
    opt_alg_number = 2
    max_wec = 3
    nsteps = 6
    record = False
    OPENMDAO_REQUIRE_MPI = False
    run_number = layout_number
    model = wake_model
    # set model
    MODELS = ['FLORIS', 'BPA', 'JENSEN', 'LARSEN']
    # print(MODELS[model])

    # select optimization approach/method
    opt_algs = ['snopt', 'ga', 'ps']
    opt_algorithm = opt_algs[opt_alg_number]

    # select wec method
    wec_methods = ['none', 'diam', 'angle', 'hybrid']
    wec_method = wec_methods[wec_method_number]

    # pop_size = 760

    # save and show options
    show_start = False
    show_end = False
    save_start = False
    save_end = False

    save_locations = True
    save_aep = True
    save_time = True
    rec_func_calls = True

    input_directory = "../../../input_files/"

    # set options for BPA
    print_ti = False
    sort_turbs = True

    # turbine_type = 'NREL5MW'            #can be 'V80' or 'NREL5MW'
    turbine_type = 'V80'  # can be 'V80' or 'NREL5MW'

    wake_model_version = 2016

    WECH = 0
    if wec_method == 'diam':
        output_directory = "../output_files/%s_wec_diam_max_wec_%i_nsteps_%.3f/" % (
            opt_algorithm, max_wec, nsteps)
        relax = True
        # expansion_factors = np.array([3, 2.75, 2.5, 2.25, 2.0, 1.75, 1.5, 1.25, 1.0, 1.0])

        expansion_factors = np.linspace(1.0, max_wec, nsteps)
        if opt_algorithm == 'ps':
            expansion_factors = np.append(np.flip(expansion_factors), 1.0)
        else:
            expansion_factors = np.append(np.flip(expansion_factors), 1.0)
        conv_tols = np.array([9E-3, 9E-3, 9E-3, 9E-3, 9E-3, 9E-3, 1E-3])
    elif wec_method == 'angle':
        output_directory = "../output_files/%s_wec_angle_max_wec_%i_nsteps_%.3f/" % (
            opt_algorithm, max_wec, nsteps)
        relax = True
        # expansion_factors = np.array([50, 40, 30, 20, 10, 0.0, 0.0])
        expansion_factors = np.linspace(0.0, max_wec, nsteps)
        expansion_factors = np.append(np.flip(expansion_factors), 0.0)
    elif wec_method == 'hybrid':
        expansion_factors = np.linspace(1.0, max_wec, nsteps)
        expansion_factors = np.append(np.flip(expansion_factors), 1.0)
        output_directory = "../output_files/%s_wec_hybrid_max_wec_%i_nsteps_%.3f/" % (
            opt_algorithm, max_wec, nsteps)
        relax = True
        WECH = 1
    elif wec_method == 'none':
        relax = False
        if opt_algorithm == 'ps':
            expansion_factors = np.array([1.0])
            conv_tols = np.array([1E-4])
        else:
            expansion_factors = np.array([1.0, 1.0])
            conv_tols = np.array([9E-3, 1E-3])
        output_directory = "../output_files/%s/" % opt_algorithm
    else:
        raise ValueError('wec_method must be diam, angle, hybrid, or none')

    # create output directory if it does not exist yet
    import distutils.dir_util
    distutils.dir_util.mkpath(output_directory)

    differentiable = True

    # for expansion_factor in np.array([5., 4., 3., 2.75, 2.5, 2.25, 2.0, 1.75, 1.5, 1.25, 1.0]):
    # for expansion_factor in np.array([20., 15., 10., 5., 4., 3., 2.5, 1.25, 1.0]):
    # expansion_factors = np.array([20., 10., 5., 2.5, 1.25, 1.0])

    wake_combination_method = 1  # can be [0:Linear freestreem superposition,
    #  1:Linear upstream velocity superposition,
    #  2:Sum of squares freestream superposition,
    #  3:Sum of squares upstream velocity superposition]

    ti_calculation_method = 4  # can be [0:No added TI calculations,
    # 1:TI by Niayifar and Porte Agel altered by Annoni and Thomas,
    # 2:TI by Niayifar and Porte Agel 2016,
    # 3:TI by Niayifar and Porte Agel 2016 with added soft max function,
    # 4:TI by Niayifar and Porte Agel 2016 using area overlap ratio,
    # 5:TI by Niayifar and Porte Agel 2016 using area overlap ratio and SM function]

    if wec_method_number > 0:
        ti_opt_method = 0  # can be [0:No added TI calculations,
        # 1:TI by Niayifar and Porte Agel altered by Annoni and Thomas,
        # 2:TI by Niayifar and Porte Agel 2016,
        # 3:TI by Niayifar and Porte Agel 2016 with added soft max function,
        # 4:TI by Niayifar and Porte Agel 2016 using area overlap ratio,
        # 5:TI by Niayifar and Porte Agel 2016 using area overlap ratio and SM function]

    else:
        ti_opt_method = 0
    final_ti_opt_method = 5

    if opt_algorithm == 'ps' and wec_method == 'none':
        ti_opt_method = ti_calculation_method

    sm_smoothing = 700.

    if ti_calculation_method == 0:
        calc_k_star_calc = False
    else:
        calc_k_star_calc = True

    if ti_opt_method == 0:
        calc_k_star_opt = False
    else:
        calc_k_star_opt = True

    nRotorPoints = 1

    wind_rose_file = 'nantucket'  # can be one of: 'amalia', 'nantucket', 'directional

    TI = 0.108
    k_calc = 0.3837 * TI + 0.003678
    # k_calc = 0.022
    # k_opt = 0.04

    shear_exp = 0.31

    # air_density = 1.1716  # kg/m^3
    air_density = 1.225  # kg/m^3 (from Jen)

    if turbine_type == 'V80':

        # define turbine size
        rotor_diameter = 80.  # (m)
        hub_height = 70.0

        z_ref = 80.0  # m
        z_0 = 0.0

        # load performance characteristics
        cut_in_speed = 4.  # m/s
        cut_out_speed = 25.  # m/s
        rated_wind_speed = 16.  # m/s
        rated_power = 2000.  # kW
        generator_efficiency = 0.944

        ct_curve_data = np.loadtxt(input_directory +
                                   'mfg_ct_vestas_v80_niayifar2016.txt',
                                   delimiter=",")
        ct_curve_wind_speed = ct_curve_data[:, 0]
        ct_curve_ct = ct_curve_data[:, 1]

        # air_density = 1.1716  # kg/m^3
        Ar = 0.25 * np.pi * rotor_diameter**2
        # cp_curve_wind_speed = ct_curve[:, 0]
        power_data = np.loadtxt(input_directory +
                                'niayifar_vestas_v80_power_curve_observed.txt',
                                delimiter=',')
        # cp_curve_cp = niayifar_power_model(cp_curve_wind_speed)/(0.5*air_density*cp_curve_wind_speed**3*Ar)
        cp_curve_cp = power_data[:, 1] * (1E6) / (0.5 * air_density *
                                                  power_data[:, 0]**3 * Ar)
        cp_curve_wind_speed = power_data[:, 0]
        cp_curve_spline = UnivariateSpline(cp_curve_wind_speed,
                                           cp_curve_cp,
                                           ext='const')
        cp_curve_spline.set_smoothing_factor(.0001)

    elif turbine_type == 'NREL5MW':

        # define turbine size
        rotor_diameter = 126.4  # (m)
        hub_height = 90.0

        z_ref = 80.0  # m
        z_0 = 0.0

        # load performance characteristics
        cut_in_speed = 3.  # m/s
        cut_out_speed = 25.  # m/s
        rated_wind_speed = 11.4  # m/s
        rated_power = 5000.  # kW
        generator_efficiency = 0.944

        filename = input_directory + "NREL5MWCPCT_dict.p"
        # filename = "../input_files/NREL5MWCPCT_smooth_dict.p"
        import pickle

        data = pickle.load(open(filename, "rb"), encoding='latin1')
        ct_curve = np.zeros([data['wind_speed'].size, 2])
        ct_curve_wind_speed = data['wind_speed']
        ct_curve_ct = data['CT']

        # cp_curve_cp = data['CP']
        # cp_curve_wind_speed = data['wind_speed']

        loc0 = np.where(data['wind_speed'] < 11.55)
        loc1 = np.where(data['wind_speed'] > 11.7)

        cp_curve_cp = np.hstack([data['CP'][loc0], data['CP'][loc1]])
        cp_curve_wind_speed = np.hstack(
            [data['wind_speed'][loc0], data['wind_speed'][loc1]])
        cp_curve_spline = UnivariateSpline(cp_curve_wind_speed,
                                           cp_curve_cp,
                                           ext='const')
        cp_curve_spline.set_smoothing_factor(.000001)
    else:
        raise ValueError("Turbine type is undefined.")

    # load starting locations
    layout_directory = input_directory

    layout_data = np.loadtxt(
        layout_directory +
        "layouts/round_38turbs/nTurbs38_spacing5_layout_%i.txt" %
        layout_number)
    # layout_data = np.loadtxt(layout_directory + "layouts/grid_16turbs/nTurbs16_spacing5_layout_%i.txt" % layout_number)
    # layout_data = np.loadtxt(layout_directory+"layouts/nTurbs9_spacing5_layout_%i.txt" % layout_number)

    turbineX = layout_data[:, 0] * rotor_diameter + rotor_diameter / 2.
    turbineY = layout_data[:, 1] * rotor_diameter + rotor_diameter / 2.

    turbineX_init = np.copy(turbineX)
    turbineY_init = np.copy(turbineY)

    nTurbines = turbineX.size

    # create boundary specifications
    boundary_radius = 0.5 * (rotor_diameter * 4000. / 126.4 - rotor_diameter
                             )  # 1936.8
    center = np.array([boundary_radius, boundary_radius]) + rotor_diameter / 2.
    start_min_spacing = 5.
    nVertices = 1
    boundary_center_x = center[0]
    boundary_center_y = center[1]
    xmax = np.max(turbineX)
    ymax = np.max(turbineY)
    xmin = np.min(turbineX)
    ymin = np.min(turbineY)

    # initialize input variable arrays
    nTurbs = nTurbines
    rotorDiameter = np.zeros(nTurbs)
    hubHeight = np.zeros(nTurbs)
    axialInduction = np.zeros(nTurbs)
    Ct = np.zeros(nTurbs)
    Cp = np.zeros(nTurbs)
    generatorEfficiency = np.zeros(nTurbs)
    yaw = np.zeros(nTurbs)
    minSpacing = 2.  # number of rotor diameters

    # define initial values
    for turbI in range(0, nTurbs):
        rotorDiameter[turbI] = rotor_diameter  # m
        hubHeight[turbI] = hub_height  # m
        axialInduction[turbI] = 1.0 / 3.0
        Ct[turbI] = 4.0 * axialInduction[turbI] * (1.0 - axialInduction[turbI])
        # print(Ct)
        Cp[turbI] = 4.0 * 1.0 / 3.0 * np.power((1 - 1.0 / 3.0), 2)
        generatorEfficiency[turbI] = generator_efficiency
        yaw[turbI] = 0.  # deg.

    # Define flow properties
    if wind_rose_file == 'nantucket':
        # windRose = np.loadtxt(input_directory + 'nantucket_windrose_ave_speeds.txt')
        windRose = np.loadtxt(input_directory +
                              'nantucket_wind_rose_for_LES.txt')
        windDirections = windRose[:, 0]
        windSpeeds = windRose[:, 1]
        windFrequencies = windRose[:, 2]
        size = np.size(windDirections)
    elif wind_rose_file == 'amalia':
        windRose = np.loadtxt(
            input_directory +
            'windrose_amalia_directionally_averaged_speeds.txt')
        windDirections = windRose[:, 0]
        windSpeeds = windRose[:, 1]
        windFrequencies = windRose[:, 2]
        size = np.size(windDirections)
    elif wind_rose_file == 'directional':
        windRose = np.loadtxt(input_directory + 'directional_windrose.txt')
        windDirections = windRose[:, 0]
        windSpeeds = windRose[:, 1]
        windFrequencies = windRose[:, 2]
        size = np.size(windDirections)
    elif wind_rose_file == '1d':
        windDirections = np.array([270.])
        windSpeeds = np.array([8.0])
        windFrequencies = np.array([1.0])
        size = np.size(windDirections)
    else:
        size = 20
        windDirections = np.linspace(0, 270, size)
        windFrequencies = np.ones(size) / size

    wake_model_options = {
        'nSamples': 0,
        'nRotorPoints': nRotorPoints,
        'use_ct_curve': True,
        'ct_curve_ct': ct_curve_ct,
        'ct_curve_wind_speed': ct_curve_wind_speed,
        'interp_type': 1,
        'use_rotor_components': False,
        'differentiable': differentiable,
        'verbose': False
    }

    if MODELS[model] == 'BPA':
        # initialize problem
        prob = om.Problem(
            model=OptAEP(nTurbines=nTurbs,
                         nDirections=windDirections.size,
                         nVertices=nVertices,
                         minSpacing=minSpacing,
                         differentiable=differentiable,
                         use_rotor_components=False,
                         wake_model=gauss_wrapper,
                         params_IdepVar_func=add_gauss_params_IndepVarComps,
                         params_IdepVar_args={'nRotorPoints': nRotorPoints},
                         wake_model_options=wake_model_options,
                         cp_points=cp_curve_cp.size,
                         cp_curve_spline=cp_curve_spline,
                         record_function_calls=True,
                         runparallel=False))
    elif MODELS[model] == 'FLORIS':
        # initialize problem
        prob = om.Problem(
            model=OptAEP(nTurbines=nTurbs,
                         nDirections=windDirections.size,
                         nVertices=nVertices,
                         minSpacing=minSpacing,
                         differentiable=differentiable,
                         use_rotor_components=False,
                         wake_model=floris_wrapper,
                         params_IdepVar_func=add_floris_params_IndepVarComps,
                         params_IdepVar_args={},
                         record_function_calls=True))

    else:
        ValueError(
            'The %s model is not currently available. Please select BPA or FLORIS'
            % (MODELS[model]))

    prob.driver = om.pyOptSparseDriver()

    if opt_algorithm == 'snopt':
        # set up optimizer
        prob.driver.options['optimizer'] = 'SNOPT'
        # prob.driver.options['gradient method'] = 'snopt_fd'

        # set optimizer options
        prob.driver.opt_settings['Verify level'] = -1
        # set optimizer options
        prob.driver.opt_settings['Major optimality tolerance'] = np.float(1e-3)

        prob.driver.opt_settings[
            'Print file'] = output_directory + 'SNOPT_print_multistart_%iturbs_%sWindRose_%idirs_%sModel_RunID%i.out' % (
                nTurbs, wind_rose_file, size, MODELS[model], run_number)
        prob.driver.opt_settings[
            'Summary file'] = output_directory + 'SNOPT_summary_multistart_%iturbs_%sWindRose_%idirs_%sModel_RunID%i.out' % (
                nTurbs, wind_rose_file, size, MODELS[model], run_number)

        prob.model.add_constraint('sc',
                                  lower=np.zeros(
                                      int(((nTurbs - 1.) * nTurbs / 2.))),
                                  scaler=1E-4)  # ,
        # active_tol=(2. * rotor_diameter) ** 2)
        prob.model.add_constraint('boundaryDistances',
                                  lower=(np.zeros(1 * turbineX.size)),
                                  scaler=1E-4)  # ,
        # active_tol=2. * rotor_diameter)

        prob.driver.options['dynamic_derivs_sparsity'] = True

    elif opt_algorithm == 'ga':

        prob.driver.options['optimizer'] = 'NSGA2'

        prob.driver.opt_settings['PrintOut'] = 1

        prob.driver.opt_settings['maxGen'] = 50000

        prob.driver.opt_settings['PopSize'] = 10 * nTurbines * 2

        # prob.driver.opt_settings['pMut_real'] = 0.001

        prob.driver.opt_settings['xinit'] = 1

        prob.driver.opt_settings['rtol'] = 1E-4

        prob.driver.opt_settings['atol'] = 1E-4

        prob.driver.opt_settings['min_tol_gens'] = 200

        prob.driver.opt_settings['file_number'] = run_number

        prob.model.add_constraint('sc',
                                  lower=np.zeros(
                                      int(((nTurbs - 1.) * nTurbs / 2.))),
                                  scaler=1E-4)
        prob.model.add_constraint('boundaryDistances',
                                  lower=(np.zeros(1 * turbineX.size)),
                                  scaler=1E-4)

    elif opt_algorithm == 'ps':
        prob.driver.options['optimizer'] = 'ALPSO'
        prob.driver.opt_settings[
            "SwarmSize"] = 30  # Number of Particles (Depends on Problem dimensions)
        # prob.driver.opt_settings["maxOuterIter"] = OuterIter # Maximum Number of Outer Loop Iterations (Major Iterations)
        # prob.driver.opt_settings["maxInnerIter"] = InnerIter  # Maximum Number of Inner Loop Iterations (Minor Iterations)
        # prob.driver.opt_settings["minInnerIter"] = InnerIter  # Minimum Number of Inner Loop Iterations (Dynamic Inner Iterations)
        # prob.driver.opt_settings["dynInnerIter"] = 0  # Dynamic Number of Inner Iterations Flag
        prob.driver.opt_settings[
            "stopCriteria"] = 0  # Stopping Criteria Flag (0 - maxIters, 1 - convergence)
        prob.driver.opt_settings[
            "stopIters"] = 5  # Consecutive Number of Iterations for which the Stopping Criteria must be Satisfied
        prob.driver.opt_settings[
            "etol"] = 1e-3  # Absolute Tolerance for Equality constraints
        prob.driver.opt_settings[
            "itol"] = 1e-3  # Absolute Tolerance for Inequality constraints
        # 'ltol':[float, 1e-2],            # Absolute Tolerance for Lagrange Multipliers
        prob.driver.opt_settings[
            "rtol"] = 1e-6  # Relative Tolerance for Lagrange Multipliers
        prob.driver.opt_settings[
            "atol"] = 1e-6  # Absolute Tolerance for Lagrange Function
        prob.driver.opt_settings[
            "dtol"] = 1e-1  # Relative Tolerance in Distance of All Particles to Terminate (GCPSO)
        prob.driver.opt_settings[
            "printOuterIters"] = 0  # Number of Iterations Before Print Outer Loop Information
        prob.driver.opt_settings[
            "printInnerIters"] = 0  # Number of Iterations Before Print Inner Loop Information
        prob.driver.opt_settings["rinit"] = 1.0  # Initial Penalty Factor
        prob.driver.opt_settings[
            "xinit"] = 1  # Initial Position Flag (0 - no position, 1 - position given)
        prob.driver.opt_settings[
            "vinit"] = 1.0  # Initial Velocity of Particles in Normalized [-1, 1] Design Space
        prob.driver.opt_settings[
            "vmax"] = 2.0  # Maximum Velocity of Particles in Normalized [-1, 1] Design Space
        prob.driver.opt_settings["c1"] = 2.0  # Cognitive Parameter
        prob.driver.opt_settings["c2"] = 1.0  # Social Parameter
        prob.driver.opt_settings["w1"] = 0.99  # Initial Inertia Weight
        prob.driver.opt_settings["w2"] = 0.55  # Final Inertia Weight
        prob.driver.opt_settings[
            "ns"] = 15  # Number of Consecutive Successes in Finding New Best Position of Best Particle Before Search Radius will be Increased (GCPSO)
        prob.driver.opt_settings[
            "nf"] = 5  # Number of Consecutive Failures in Finding New Best Position of Best Particle Before Search Radius will be Increased (GCPSO)
        prob.driver.opt_settings["dt"] = 1.0  # Time step
        prob.driver.opt_settings[
            "vcrazy"] = 1e-2  # Craziness Velocity (Added to Particle Velocity After Updating the Penalty Factors and Langangian Multipliers)
        prob.driver.opt_settings[
            "fileout"] = 1  # Flag to Turn On Output to filename
        # prob.driver.opt_settings["filename"] = "ALPSO.out" # We could probably remove fileout flag if filename or fileinstance is given
        prob.driver.opt_settings[
            "seed"] = 0.0  # Random Number Seed (0 - Auto-Seed based on time clock)
        prob.driver.opt_settings[
            "HoodSize"] = 5  # Number of Neighbours of Each Particle
        prob.driver.opt_settings[
            "HoodModel"] = "gbest"  # Neighbourhood Model (dl/slring - Double/Single Link Ring, wheel - Wheel, Spatial - based on spatial distance, sfrac - Spatial Fraction)
        prob.driver.opt_settings[
            "HoodSelf"] = 1  # Selfless Neighbourhood Model (0 - Include Particle i in NH i, 1 - Don't Include Particle i)
        prob.driver.opt_settings[
            "Scaling"] = 1  # Design Variables Scaling Flag (0 - no scaling, 1 - scaling between [-1, 1])
        # prob.driver.opt_settings["parallelType"] = 'EXT'  # Type of parallelization ('' or 'EXT')

        prob.model.add_constraint('sc',
                                  lower=np.zeros(
                                      int(((nTurbs - 1.) * nTurbs / 2.))),
                                  scaler=1E-7)
        prob.model.add_constraint('boundaryDistances',
                                  lower=(np.zeros(1 * turbineX.size)),
                                  scaler=1E-7)

        # prob.driver.add_objective('obj', scaler=1E0)
    prob.model.add_objective('obj', scaler=1E-9)

    # select design variables
    prob.model.add_design_var('turbineX',
                              scaler=1E-4,
                              lower=np.zeros(nTurbines),
                              upper=np.ones(nTurbines) * 2. * boundary_radius)
    prob.model.add_design_var('turbineY',
                              scaler=1E-4,
                              lower=np.zeros(nTurbines),
                              upper=np.ones(nTurbines) * 2. * boundary_radius)

    if record:
        driver_recorder = om.SqliteRecorder(output_directory +
                                            'recorded_data_driver_%s.sql' %
                                            (run_number))
        # model_recorder = om.SqliteRecorder(output_directory + 'recorded_data_model_%s.sql' %(run_number))
        prob.driver.add_recorder(driver_recorder)
        # prob.model.add_recorder(model_recorder)
        prob.driver.recording_options['record_constraints'] = False
        prob.driver.recording_options['record_derivatives'] = False
        prob.driver.recording_options['record_desvars'] = True
        prob.driver.recording_options['record_inputs'] = False
        prob.driver.recording_options['record_model_metadata'] = True
        prob.driver.recording_options['record_objectives'] = True
        prob.driver.recording_options['includes'] = ['AEP']
        prob.driver.recording_options['record_responses'] = False

    # print("almost time for setup")
    tic = time.time()
    # print("entering setup at time = ", tic)
    prob.setup(check=False)
    toc = time.time()
    # print("setup complete at time = ", toc)

    # print the results
    # print(('Problem setup took %.03f sec.' % (toc - tic)))

    # assign initial values to design variables
    prob['turbineX'] = np.copy(turbineX)
    prob['turbineY'] = np.copy(turbineY)
    for direction_id in range(0, windDirections.size):
        prob['yaw%i' % direction_id] = yaw

    # assign values to constant inputs (not design variables)
    prob['rotorDiameter'] = rotorDiameter
    prob['hubHeight'] = hubHeight
    prob['axialInduction'] = axialInduction
    prob['generatorEfficiency'] = generatorEfficiency
    prob['windSpeeds'] = windSpeeds
    prob['air_density'] = air_density
    prob['windDirections'] = windDirections
    prob['windFrequencies'] = windFrequencies
    prob['Ct_in'] = Ct
    prob['Cp_in'] = Cp
    prob['cp_curve_cp'] = cp_curve_cp
    prob['cp_curve_wind_speed'] = cp_curve_wind_speed
    cutInSpeeds = np.ones(nTurbines) * cut_in_speed
    prob['cut_in_speed'] = cutInSpeeds
    ratedPowers = np.ones(nTurbines) * rated_power
    prob['rated_power'] = ratedPowers

    # assign values to turbine states
    prob['cut_in_speed'] = np.ones(nTurbines) * cut_in_speed
    prob['cut_out_speed'] = np.ones(nTurbines) * cut_out_speed
    prob['rated_power'] = np.ones(nTurbines) * rated_power
    prob['rated_wind_speed'] = np.ones(nTurbines) * rated_wind_speed
    prob['use_power_curve_definition'] = True

    # assign boundary values
    prob['boundary_center'] = np.array([boundary_center_x, boundary_center_y])
    prob['boundary_radius'] = boundary_radius

    if MODELS[model] == 'BPA':
        prob['model_params:wake_combination_method'] = np.copy(
            wake_combination_method)
        prob['model_params:ti_calculation_method'] = np.copy(
            ti_calculation_method)
        prob['model_params:wake_model_version'] = np.copy(wake_model_version)
        prob['model_params:wec_factor'] = 1.0
        prob['model_params:wec_spreading_angle'] = 0.0
        prob['model_params:calc_k_star'] = np.copy(calc_k_star_calc)
        prob['model_params:sort'] = np.copy(sort_turbs)
        prob['model_params:z_ref'] = np.copy(z_ref)
        prob['model_params:z_0'] = np.copy(z_0)
        prob['model_params:ky'] = np.copy(k_calc)
        prob['model_params:kz'] = np.copy(k_calc)
        prob['model_params:print_ti'] = np.copy(print_ti)
        prob['model_params:shear_exp'] = np.copy(shear_exp)
        prob['model_params:I'] = np.copy(TI)
        prob['model_params:sm_smoothing'] = np.copy(sm_smoothing)
        prob['model_params:WECH'] = WECH
        if nRotorPoints > 1:
            prob['model_params:RotorPointsY'], prob[
                'model_params:RotorPointsZ'] = sunflower_points(nRotorPoints)

        # prob.run_model()
        # AEP_init_calc = np.copy(prob['AEP'])*1E3 # convert to Whr
        # print("initial AEP: ", AEP_init_calc)
    return prob
Exemple #3
0
        prob['model_params:wake_combination_method'] = wake_combination_method
        prob['model_params:ti_calculation_method'] = ti_calculation_method
        prob['model_params:wake_model_version'] = wake_model_version
        prob['model_params:opt_exp_fac'] = 1.0
        prob['model_params:calc_k_star'] = calc_k_star_calc
        prob['model_params:sort'] = sort_turbs
        prob['model_params:z_ref'] = z_ref
        prob['model_params:z_0'] = z_0
        prob['model_params:ky'] = k_calc
        prob['model_params:kz'] = k_calc
        prob['model_params:print_ti'] = print_ti
        prob['model_params:shear_exp'] = shear_exp
        prob['model_params:I'] = TI
        prob['model_params:sm_smoothing'] = sm_smoothing
        if nRotorPoints > 1:
            prob['model_params:RotorPointsY'], prob['model_params:RotorPointsZ'] = sunflower_points(nRotorPoints)

    prob.run_once()
    AEP_init_calc = prob['AEP']
    mpi_print(prob, AEP_init_calc * 1E-6)

    if MODELS[model] is 'BPA':
        prob['model_params:ti_calculation_method'] = ti_opt_method
        prob['model_params:calc_k_star'] = calc_k_star_opt

    prob.run_once()
    AEP_init_opt = prob['AEP']
    AEP_run_opt = np.copy(AEP_init_opt)
    mpi_print(prob, AEP_init_opt * 1E-6)

    config.obj_func_calls_array[:] = 0.0
def setup_probs():

    nTurbines = 2
    nDirections = 1

    rotorDiameter = 126.4
    rotorArea = np.pi * rotorDiameter * rotorDiameter / 4.0
    axialInduction = 1.0 / 3.0
    # CP = 0.7737/0.944 * 4.0 * 1.0/3.0 * np.power((1 - 1.0/3.0), 2)
    CP = 4.0 * 1.0 / 3.0 * np.power((1 - 1.0 / 3.0), 2)
    # CP =0.768 * 4.0 * 1.0/3.0 * np.power((1 - 1.0/3.0), 2)
    CT = 4.0 * axialInduction * (1.0 - axialInduction)
    generator_efficiency = 0.944

    # Define turbine characteristics
    axialInduction = np.array([axialInduction, axialInduction])
    rotorDiameter = np.array([rotorDiameter, rotorDiameter])
    generatorEfficiency = np.array(
        [generator_efficiency, generator_efficiency])
    yaw = np.array([0., 0.])
    hubHeight = np.array([90.0, 90.0])
    # Define site measurements
    wind_direction = 270. - 0.523599 * 180. / np.pi
    wind_speed = 8.  # m/s
    air_density = 1.1716

    Ct = np.array([CT, CT])
    Cp = np.array([CP, CP])
    nRotorPoints = 4
    rotor_pnt_typ = 0
    location = 0.69

    filename = "./input_files/NREL5MWCPCT_dict.p"
    # filename = "../input_files/NREL5MWCPCT_smooth_dict.p"
    import cPickle as pickle

    data = pickle.load(open(filename, "rb"))
    ct_curve_wind_speed = data['wind_speed']
    ct_curve_ct = data['CT']

    gauss_model_options = {
        'nSamples': 0,
        'nRotorPoints': nRotorPoints,
        'use_ct_curve': True,
        'ct_curve_ct': ct_curve_ct,
        'ct_curve_wind_speed': ct_curve_wind_speed,
        'interp_type': 1,
        'use_rotor_components': False,
        'verbose': False
    }

    # gauss_prob = Problem(root=AEPGroup(nTurbines=nTurbines, nDirections=nDirections, use_rotor_components=False,
    #                            wake_model=gauss_wrapper, datasize=0, minSpacing=2.0,
    #                            params_IdepVar_func=add_gauss_params_IndepVarComps, wake_model_options=gauss_model_options,
    #                            params_IndepVar_args={'nRotorPoints': nRotorPoints}))

    gauss_prob = Problem(
        root=AEPGroup(nTurbines=nTurbines,
                      nDirections=nDirections,
                      use_rotor_components=False,
                      wake_model=gauss_wrapper,
                      datasize=0,
                      params_IdepVar_func=add_gauss_params_IndepVarComps,
                      wake_model_options=gauss_model_options,
                      params_IndepVar_args={'nRotorPoints': nRotorPoints}))

    floris_options = {
        'differentiable': True,
        'nSamples': 0,
        'use_rotor_components': False
    }

    floris_prob_orig = Problem(
        root=OptAEP(nTurbines=nTurbines,
                    nDirections=nDirections,
                    use_rotor_components=False,
                    wake_model=floris_wrapper,
                    wake_model_options=floris_options,
                    datasize=0,
                    params_IdepVar_func=add_floris_params_IndepVarComps,
                    params_IndepVar_args={}))

    floris_prob_tuned = Problem(
        root=OptAEP(nTurbines=nTurbines,
                    nDirections=nDirections,
                    use_rotor_components=False,
                    wake_model=floris_wrapper,
                    wake_model_options=floris_options,
                    datasize=0,
                    params_IdepVar_func=add_floris_params_IndepVarComps,
                    params_IndepVar_args={}))

    probs = [gauss_prob, floris_prob_orig, floris_prob_tuned]
    for prob in probs:
        prob.setup()
        if prob is floris_prob_orig or prob is floris_prob_tuned:
            prob['model_params:useWakeAngle'] = True

        turbineX = np.array([1118.1, 1881.9])
        turbineY = np.array([1279.5, 1720.5])
        # prob['gen_params:CTcorrected'] = False
        # prob['gen_params:CPcorrected'] = False
        prob['turbineX'] = turbineX
        prob['turbineY'] = turbineY
        prob['rotorDiameter'] = rotorDiameter
        prob['axialInduction'] = axialInduction
        prob['generatorEfficiency'] = generatorEfficiency
        prob['air_density'] = air_density
        prob['Cp_in'] = Cp
        prob['Ct_in'] = Ct
        prob['windSpeeds'] = np.array([wind_speed])
        prob['windDirections'] = np.array([wind_direction])
        prob['hubHeight'] = hubHeight

        if prob is gauss_prob:

            sort_turbs = True
            wake_combination_method = 1  # can be [0:Linear freestreem superposition,
            #  1:Linear upstream velocity superposition,
            #  2:Sum of squares freestream superposition,
            #  3:Sum of squares upstream velocity superposition]
            ti_calculation_method = 5  # can be [0:No added TI calculations,
            # 1:TI by Niayifar and Porte Agel altered by Annoni and Thomas,
            # 2:TI by Niayifar and Porte Agel 2016,
            # 3:TI by Niayifar and Porte Agel 2016 with added soft max function,
            # 4:TI by Niayifar and Porte Agel 2016 using area overlap ratio,
            # 5:TI by Niayifar and Porte Agel 2016 using area overlap ratio and SM function]
            calc_k_star = True
            z_ref = 90.0
            z_0 = 0.001
            k_calc = 0.065

            # tuned with 1 rotor point: error_turbine2:  380593.475508 ky:  0.0147484983033 kz:  0.0365360001244 I:  1.0 shear_exp:  0.0804912726779
            # tuned with 500 rotor points: error_turbine2:  505958.824163 ky:  0.010239469297 kz:  0.0187826477801 I:  0.5 shear_exp:  0.115698347406
            # tuned with 1000 rotor points: error_turbine2:  440240.45048 ky:  0.0132947699754 kz:  0.0267832386866 I:  0.149427342515 shear_exp:  0.107996557048
            # tuned with k_star and 1000 rotor points: error_turbine2:  759565.303289 ky:  0.065 kz:  0.065 I:  0.0765060707278 shear_exp:  0.104381464423
            # using NPA to calculate initial spreading, but then letting BPA adjust it with TI after that. 1000 rotor points
            # error_turbine2:  759565.279351 ky:  0.0330333796913 kz:  0.0330333796913 I:  0.0765060716478 shear_exp:  0.104381467026
            # using NPA to calculate initial spreading, but then letting BPA adjust it with TI after that. 16 rotor points
            # error_turbine2:  642639.730582 ky:  0.0307280539404 kz:  0.0307280539404 I:  0.0704979253074 shear_exp:  0.108435318499
            # tuning only shear_exp with 16 rotor points: error_turbine2:  779216.077341 ky:  0.0267 kz:  0.0267 I:  0.06 shear_exp:  0.161084449732
            I = .063  # + 0.04
            # I = .06
            ky = 0.3837 * I + 0.003678
            # ky = 0.022
            kz = 0.3837 * I + 0.003678
            # kz = 0.022
            # shear_exp = 0.161084449732
            shear_exp = 0.11

            prob[
                'model_params:wake_combination_method'] = wake_combination_method
            prob['model_params:ti_calculation_method'] = ti_calculation_method
            prob['model_params:calc_k_star'] = calc_k_star
            prob['model_params:sort'] = sort_turbs
            prob['model_params:z_ref'] = z_ref
            prob['model_params:z_0'] = z_0
            prob['model_params:ky'] = ky
            prob['model_params:kz'] = kz
            prob['model_params:I'] = I
            prob['model_params:shear_exp'] = shear_exp
            print "in gauss setup"
            if nRotorPoints > 1:
                if rotor_pnt_typ == 0:
                    points = circumference_points(nRotorPoints, location)
                elif rotor_pnt_typ == 1:
                    points = sunflower_points(nRotorPoints)
                print points
                prob['model_params:RotorPointsY'], prob[
                    'model_params:RotorPointsZ'] = points
                print "setting rotor points"

    return probs
    ax2.plot(blade3X * c1 + 0.,
             blade3Y * c1 + H,
             linewidth=1 * 1.5,
             color='C0',
             alpha=0.5)

    x_sample = np.array([0.69 * R, 0., -0.69 * R, 0.])
    y_sample = np.array([0., 0.69 * R, 0., -0.69 * R]) + H
    ax1.plot(x_sample, y_sample, 'o', color='C2', alpha=0.5, markersize=3)

    ax1.text(0.69 * R, H + 7., '(0.69,0)', horizontalalignment='center')
    ax1.text(0., H + 0.69 * R + 7., '(0,0.69)', horizontalalignment='center')
    ax1.text(-0.69 * R, H + 7., '(-0.69,0)', horizontalalignment='center')
    ax1.text(0., H - 0.69 * R + 7., '(0,-0.69)', horizontalalignment='center')

    x_sample, y_sample = sunflower_points(100)
    x_sample = x_sample * R
    y_sample = y_sample * R + H
    ax2.plot(x_sample, y_sample, 'o', color='C2', alpha=0.5, markersize=3)

    ax1.axis('equal')
    ax1.axis('off')

    ax2.axis('equal')
    ax2.axis('off')

    ax1.set_ylim(-15., H + R + 5)
    ax2.set_ylim(-15., H + R + 5)

    ax1.text(0., -10., 'optimize', horizontalalignment='center')
    ax2.text(0., -10., 'evaluate', horizontalalignment='center')
def setup_probs():

    nTurbines = 2
    nDirections = 1

    rotorDiameter = 126.4
    rotorArea = np.pi*rotorDiameter*rotorDiameter/4.0
    axialInduction = 1.0/3.0
    # CP = 0.7737/0.944 * 4.0 * 1.0/3.0 * np.power((1 - 1.0/3.0), 2)
    CP = 4.0 * 1.0/3.0 * np.power((1 - 1.0/3.0), 2)
    # CP =0.768 * 4.0 * 1.0/3.0 * np.power((1 - 1.0/3.0), 2)
    CT = 4.0*axialInduction*(1.0-axialInduction)
    generator_efficiency = 0.944

    # Define turbine characteristics
    axialInduction = np.array([axialInduction, axialInduction])
    rotorDiameter = np.array([rotorDiameter, rotorDiameter])
    generatorEfficiency = np.array([generator_efficiency, generator_efficiency])
    yaw = np.array([0., 0.])
    hubHeight = np.array([90.0, 90.0])
    # Define site measurements
    wind_direction = 270.-0.523599*180./np.pi
    wind_speed = 8.    # m/s
    air_density = 1.1716

    Ct = np.array([CT, CT])
    Cp = np.array([CP, CP])
    nRotorPoints = 4
    rotor_pnt_typ = 0
    location = 0.69

    filename = "./input_files/NREL5MWCPCT_dict.p"
    # filename = "../input_files/NREL5MWCPCT_smooth_dict.p"
    import cPickle as pickle

    data = pickle.load(open(filename, "rb"))
    ct_curve_wind_speed = data['wind_speed']
    ct_curve_ct= data['CT']

    gauss_model_options = {'nSamples': 0,
                          'nRotorPoints': nRotorPoints,
                          'use_ct_curve': True,
                          'ct_curve_ct': ct_curve_ct,
                          'ct_curve_wind_speed': ct_curve_wind_speed,
                          'interp_type': 1,
                          'use_rotor_components': False,
                          'verbose': False}

    # gauss_prob = Problem(root=AEPGroup(nTurbines=nTurbines, nDirections=nDirections, use_rotor_components=False,
    #                            wake_model=gauss_wrapper, datasize=0, minSpacing=2.0,
    #                            params_IdepVar_func=add_gauss_params_IndepVarComps, wake_model_options=gauss_model_options,
    #                            params_IndepVar_args={'nRotorPoints': nRotorPoints}))

    gauss_prob = Problem(root=AEPGroup(nTurbines=nTurbines, nDirections=nDirections, use_rotor_components=False,
                                       wake_model=gauss_wrapper, datasize=0,
                                       params_IdepVar_func=add_gauss_params_IndepVarComps,
                                       wake_model_options=gauss_model_options,
                                       params_IndepVar_args={'nRotorPoints': nRotorPoints}))


    floris_options = {'differentiable': True, 'nSamples': 0, 'use_rotor_components': False}

    floris_prob_orig = Problem(root=OptAEP(nTurbines=nTurbines, nDirections=nDirections, use_rotor_components=False,
                               wake_model=floris_wrapper, wake_model_options=floris_options, datasize=0,
                               params_IdepVar_func=add_floris_params_IndepVarComps,
                               params_IndepVar_args={}))

    floris_prob_tuned = Problem(root=OptAEP(nTurbines=nTurbines, nDirections=nDirections, use_rotor_components=False,
                               wake_model=floris_wrapper, wake_model_options=floris_options, datasize=0,
                               params_IdepVar_func=add_floris_params_IndepVarComps,
                               params_IndepVar_args={}))

    probs = [gauss_prob, floris_prob_orig, floris_prob_tuned]
    for prob in probs:
        prob.setup()
        if prob is floris_prob_orig or prob is floris_prob_tuned:
            prob['model_params:useWakeAngle'] = True

        turbineX = np.array([1118.1, 1881.9])
        turbineY = np.array([1279.5, 1720.5])
        # prob['gen_params:CTcorrected'] = False
        # prob['gen_params:CPcorrected'] = False
        prob['turbineX'] = turbineX
        prob['turbineY'] = turbineY
        prob['rotorDiameter'] = rotorDiameter
        prob['axialInduction'] = axialInduction
        prob['generatorEfficiency'] = generatorEfficiency
        prob['air_density'] = air_density
        prob['Cp_in'] = Cp
        prob['Ct_in'] = Ct
        prob['windSpeeds'] = np.array([wind_speed])
        prob['windDirections'] = np.array([wind_direction])
        prob['hubHeight'] = hubHeight

        if prob is gauss_prob:

            sort_turbs = True
            wake_combination_method = 1  # can be [0:Linear freestreem superposition,
            #  1:Linear upstream velocity superposition,
            #  2:Sum of squares freestream superposition,
            #  3:Sum of squares upstream velocity superposition]
            ti_calculation_method = 5  # can be [0:No added TI calculations,
                                                # 1:TI by Niayifar and Porte Agel altered by Annoni and Thomas,
                                                # 2:TI by Niayifar and Porte Agel 2016,
                                                # 3:TI by Niayifar and Porte Agel 2016 with added soft max function,
                                                # 4:TI by Niayifar and Porte Agel 2016 using area overlap ratio,
                                                # 5:TI by Niayifar and Porte Agel 2016 using area overlap ratio and SM function]
            calc_k_star = True
            z_ref = 90.0
            z_0 = 0.001
            k_calc = 0.065

            # tuned with 1 rotor point: error_turbine2:  380593.475508 ky:  0.0147484983033 kz:  0.0365360001244 I:  1.0 shear_exp:  0.0804912726779
            # tuned with 500 rotor points: error_turbine2:  505958.824163 ky:  0.010239469297 kz:  0.0187826477801 I:  0.5 shear_exp:  0.115698347406
            # tuned with 1000 rotor points: error_turbine2:  440240.45048 ky:  0.0132947699754 kz:  0.0267832386866 I:  0.149427342515 shear_exp:  0.107996557048
            # tuned with k_star and 1000 rotor points: error_turbine2:  759565.303289 ky:  0.065 kz:  0.065 I:  0.0765060707278 shear_exp:  0.104381464423
            # using NPA to calculate initial spreading, but then letting BPA adjust it with TI after that. 1000 rotor points
            # error_turbine2:  759565.279351 ky:  0.0330333796913 kz:  0.0330333796913 I:  0.0765060716478 shear_exp:  0.104381467026
            # using NPA to calculate initial spreading, but then letting BPA adjust it with TI after that. 16 rotor points
            # error_turbine2:  642639.730582 ky:  0.0307280539404 kz:  0.0307280539404 I:  0.0704979253074 shear_exp:  0.108435318499
            # tuning only shear_exp with 16 rotor points: error_turbine2:  779216.077341 ky:  0.0267 kz:  0.0267 I:  0.06 shear_exp:  0.161084449732
            I = .063 # + 0.04
            # I = .06
            ky = 0.3837*I + 0.003678
            # ky = 0.022
            kz = 0.3837*I + 0.003678
            # kz = 0.022
            # shear_exp = 0.161084449732
            shear_exp = 0.11

            prob['model_params:wake_combination_method'] = wake_combination_method
            prob['model_params:ti_calculation_method'] = ti_calculation_method
            prob['model_params:calc_k_star'] = calc_k_star
            prob['model_params:sort'] = sort_turbs
            prob['model_params:z_ref'] = z_ref
            prob['model_params:z_0'] = z_0
            prob['model_params:ky'] = ky
            prob['model_params:kz'] = kz
            prob['model_params:I'] = I
            prob['model_params:shear_exp'] = shear_exp
            print "in gauss setup"
            if nRotorPoints > 1:
                if rotor_pnt_typ == 0:
                    points = circumference_points(nRotorPoints, location)
                elif rotor_pnt_typ == 1:
                    points = sunflower_points(nRotorPoints)
                print points
                prob['model_params:RotorPointsY'], prob['model_params:RotorPointsZ'] = points
                print "setting rotor points"

    return probs
    # location = 0.625 #0.5*1.25
    location = (0.7353288267358161 + 0.6398349246319044) / 2.
    location = 0.69
    print(location)
    rotor_pnt_typ = 1  # can be [0: circumference points,
    #         1: sunflower points
    #         2: horizontal line at hub height

    fig, ax = plt.subplots()
    if nRotorPoints > 1:
        if rotor_pnt_typ == 0:
            x, y = circumference_points(nRotorPoints, location=location)

            # ax.set_xlim([-70, 70])
        elif rotor_pnt_typ == 1:
            x, y = sunflower_points(nRotorPoints)
            # ax.plot(x, y)
        elif rotor_pnt_typ == 2:
            x, y = line_points(nRotorPoints)
        else:
            [x, y] = [0.0, 0.0]
        print(x, y)
        # x, y = sunflower_points(nRotorPoints)

        x *= 0.5 * rotor_diameter
        y *= 0.5 * rotor_diameter
        ax.scatter(x, y)

    else:
        [x, y] = np.array([0.0, 0.0])
        plt.scatter(x, y)
def run_opt(layout_number, wec_method_number, wake_model, opt_alg_number,
            max_wec, nsteps, xs, ys):
    OPENMDAO_REQUIRE_MPI = False
    run_number = layout_number
    model = wake_model
    # set model
    MODELS = ['FLORIS', 'BPA', 'JENSEN', 'LARSEN']
    print(MODELS[model])

    # select optimization approach/method
    opt_algs = ['snopt', 'ga', 'ps']
    opt_algorithm = opt_algs[opt_alg_number]

    # select wec method
    wec_methods = ['none', 'diam', 'angle', 'hybrid']
    wec_method = wec_methods[wec_method_number]

    # pop_size = 760

    # save and show options
    show_start = False
    show_end = False
    save_start = True
    save_end = True

    save_locations = True
    save_aep = True
    save_time = True
    rec_func_calls = True

    input_directory = "../project-code/input_files/"

    # set options for BPA
    print_ti = False
    sort_turbs = True

    # turbine_type = 'NREL5MW'            #can be 'V80' or 'NREL5MW'
    turbine_type = 'V80'  # can be 'V80' or 'NREL5MW'

    wake_model_version = 2016

    WECH = 0
    if wec_method == 'diam':
        output_directory = "../output_files/%s_wec_diam_max_wec_%i_nsteps_%.3f/" % (
            opt_algorithm, max_wec, nsteps)
        relax = True
        # expansion_factors = np.array([3, 2.75, 2.5, 2.25, 2.0, 1.75, 1.5, 1.25, 1.0, 1.0])
        expansion_factors = np.linspace(1.0, max_wec, nsteps)
        expansion_factors = np.append(np.flip(expansion_factors), 1.0)
    elif wec_method == 'angle':
        output_directory = "../output_files/%s_wec_angle_max_wec_%i_nsteps_%.3f/" % (
            opt_algorithm, max_wec, nsteps)
        relax = True
        # expansion_factors = np.array([50, 40, 30, 20, 10, 0.0, 0.0])
        expansion_factors = np.linspace(0.0, max_wec, nsteps)
        expansion_factors = np.append(np.flip(expansion_factors), 0.0)
    elif wec_method == 'hybrid':
        expansion_factors = np.linspace(1.0, max_wec, nsteps)
        expansion_factors = np.append(np.flip(expansion_factors), 1.0)
        output_directory = "../output_files/%s_wec_hybrid_max_wec_%i_nsteps_%.3f/" % (
            opt_algorithm, max_wec, nsteps)
        relax = True
        WECH = 1
    elif wec_method == 'none':
        relax = False
        expansion_factors = np.array([1.0, 1.0])
        output_directory = "../output_files/%s/" % opt_algorithm
    else:
        raise ValueError('wec_method must be diam, angle, hybrid, or none')

    # create output directory if it does not exist yet
    import distutils.dir_util
    distutils.dir_util.mkpath(output_directory)

    differentiable = True

    # for expansion_factor in np.array([5., 4., 3., 2.75, 2.5, 2.25, 2.0, 1.75, 1.5, 1.25, 1.0]):
    # for expansion_factor in np.array([20., 15., 10., 5., 4., 3., 2.5, 1.25, 1.0]):
    # expansion_factors = np.array([20., 10., 5., 2.5, 1.25, 1.0])

    wake_combination_method = 1  # can be [0:Linear freestreem superposition,
    #  1:Linear upstream velocity superposition,
    #  2:Sum of squares freestream superposition,
    #  3:Sum of squares upstream velocity superposition]

    ti_calculation_method = 4  # can be [0:No added TI calculations,
    # 1:TI by Niayifar and Porte Agel altered by Annoni and Thomas,
    # 2:TI by Niayifar and Porte Agel 2016,
    # 3:TI by Niayifar and Porte Agel 2016 with added soft max function,
    # 4:TI by Niayifar and Porte Agel 2016 using area overlap ratio,
    # 5:TI by Niayifar and Porte Agel 2016 using area overlap ratio and SM function]

    if wec_method_number > 0:
        ti_opt_method = 0  # can be [0:No added TI calculations,
        # 1:TI by Niayifar and Porte Agel altered by Annoni and Thomas,
        # 2:TI by Niayifar and Porte Agel 2016,
        # 3:TI by Niayifar and Porte Agel 2016 with added soft max function,
        # 4:TI by Niayifar and Porte Agel 2016 using area overlap ratio,
        # 5:TI by Niayifar and Porte Agel 2016 using area overlap ratio and SM function]

    else:
        ti_opt_method = 0
    final_ti_opt_method = 5

    if opt_algorithm == 'ps':
        ti_opt_method = ti_calculation_method

    sm_smoothing = 700.

    if ti_calculation_method == 0:
        calc_k_star_calc = False
    else:
        calc_k_star_calc = True

    if ti_opt_method == 0:
        calc_k_star_opt = False
    else:
        calc_k_star_opt = True

    nRotorPoints = 1

    wind_rose_file = 'nantucket'  # can be one of: 'amalia', 'nantucket', 'directional

    TI = 0.108
    k_calc = 0.3837 * TI + 0.003678
    # k_calc = 0.022
    # k_opt = 0.04

    shear_exp = 0.31

    # air_density = 1.1716  # kg/m^3
    air_density = 1.225  # kg/m^3 (from Jen)

    if turbine_type == 'V80':

        # define turbine size
        rotor_diameter = 80.  # (m)
        hub_height = 70.0

        z_ref = 80.0  # m
        z_0 = 0.0

        # load performance characteristics
        cut_in_speed = 4.  # m/s
        cut_out_speed = 25.  # m/s
        rated_wind_speed = 16.  # m/s
        rated_power = 2000.  # kW
        generator_efficiency = 0.944

        ct_curve_data = np.loadtxt(input_directory +
                                   'mfg_ct_vestas_v80_niayifar2016.txt',
                                   delimiter=",")
        ct_curve_wind_speed = ct_curve_data[:, 0]
        ct_curve_ct = ct_curve_data[:, 1]

        # air_density = 1.1716  # kg/m^3
        Ar = 0.25 * np.pi * rotor_diameter**2
        # cp_curve_wind_speed = ct_curve[:, 0]
        power_data = np.loadtxt(input_directory +
                                'niayifar_vestas_v80_power_curve_observed.txt',
                                delimiter=',')
        # cp_curve_cp = niayifar_power_model(cp_curve_wind_speed)/(0.5*air_density*cp_curve_wind_speed**3*Ar)
        cp_curve_cp = power_data[:, 1] * (1E6) / (0.5 * air_density *
                                                  power_data[:, 0]**3 * Ar)
        cp_curve_wind_speed = power_data[:, 0]
        cp_curve_spline = UnivariateSpline(cp_curve_wind_speed,
                                           cp_curve_cp,
                                           ext='const')
        cp_curve_spline.set_smoothing_factor(.0001)

    elif turbine_type == 'NREL5MW':

        # define turbine size
        rotor_diameter = 126.4  # (m)
        hub_height = 90.0

        z_ref = 80.0  # m
        z_0 = 0.0

        # load performance characteristics
        cut_in_speed = 3.  # m/s
        cut_out_speed = 25.  # m/s
        rated_wind_speed = 11.4  # m/s
        rated_power = 5000.  # kW
        generator_efficiency = 0.944

        filename = input_directory + "NREL5MWCPCT_dict.p"
        # filename = "../input_files/NREL5MWCPCT_smooth_dict.p"
        import pickle

        data = pickle.load(open(filename, "rb"), encoding='latin1')
        ct_curve = np.zeros([data['wind_speed'].size, 2])
        ct_curve_wind_speed = data['wind_speed']
        ct_curve_ct = data['CT']

        # cp_curve_cp = data['CP']
        # cp_curve_wind_speed = data['wind_speed']

        loc0 = np.where(data['wind_speed'] < 11.55)
        loc1 = np.where(data['wind_speed'] > 11.7)

        cp_curve_cp = np.hstack([data['CP'][loc0], data['CP'][loc1]])
        cp_curve_wind_speed = np.hstack(
            [data['wind_speed'][loc0], data['wind_speed'][loc1]])
        cp_curve_spline = UnivariateSpline(cp_curve_wind_speed,
                                           cp_curve_cp,
                                           ext='const')
        cp_curve_spline.set_smoothing_factor(.000001)
    else:
        raise ValueError("Turbine type is undefined.")

    # load starting locations
    layout_directory = input_directory

    layout_data = np.loadtxt(
        layout_directory +
        "layouts/round_38turbs/nTurbs38_spacing5_layout_%i.txt" %
        layout_number)
    # layout_data = np.loadtxt(layout_directory + "layouts/grid_16turbs/nTurbs16_spacing5_layout_%i.txt" % layout_number)
    # layout_data = np.loadtxt(layout_directory+"layouts/nTurbs9_spacing5_layout_%i.txt" % layout_number)

    turbineX = layout_data[:, 0] * rotor_diameter + rotor_diameter / 2.
    turbineY = layout_data[:, 1] * rotor_diameter + rotor_diameter / 2.

    turbineX_init = np.copy(turbineX)
    turbineY_init = np.copy(turbineY)

    nTurbines = turbineX.size

    # create boundary specifications
    boundary_radius = 0.5 * (rotor_diameter * 4000. / 126.4 - rotor_diameter
                             )  # 1936.8
    center = np.array([boundary_radius, boundary_radius]) + rotor_diameter / 2.
    start_min_spacing = 5.
    nVertices = 1
    boundary_center_x = center[0]
    boundary_center_y = center[1]
    xmax = np.max(turbineX)
    ymax = np.max(turbineY)
    xmin = np.min(turbineX)
    ymin = np.min(turbineY)
    boundary_radius_plot = boundary_radius + 0.5 * rotor_diameter

    plot_round_farm(turbineX,
                    turbineY,
                    rotor_diameter, [boundary_center_x, boundary_center_y],
                    boundary_radius,
                    show_start=show_start,
                    save_start=save_start,
                    save_file="farm_layout.pdf")
    # quit()
    # initialize input variable arrays
    nTurbs = nTurbines
    rotorDiameter = np.zeros(nTurbs)
    hubHeight = np.zeros(nTurbs)
    axialInduction = np.zeros(nTurbs)
    Ct = np.zeros(nTurbs)
    Cp = np.zeros(nTurbs)
    generatorEfficiency = np.zeros(nTurbs)
    yaw = np.zeros(nTurbs)
    minSpacing = 2.  # number of rotor diameters

    # define initial values
    for turbI in range(0, nTurbs):
        rotorDiameter[turbI] = rotor_diameter  # m
        hubHeight[turbI] = hub_height  # m
        axialInduction[turbI] = 1.0 / 3.0
        Ct[turbI] = 4.0 * axialInduction[turbI] * (1.0 - axialInduction[turbI])
        # print(Ct)
        Cp[turbI] = 4.0 * 1.0 / 3.0 * np.power((1 - 1.0 / 3.0), 2)
        generatorEfficiency[turbI] = generator_efficiency
        yaw[turbI] = 0.  # deg.

    # Define flow properties
    if wind_rose_file is 'nantucket':
        # windRose = np.loadtxt(input_directory + 'nantucket_windrose_ave_speeds.txt')
        windRose = np.loadtxt(input_directory +
                              'nantucket_wind_rose_for_LES.txt')
        windDirections = windRose[:, 0]
        windSpeeds = windRose[:, 1]
        windFrequencies = windRose[:, 2]
        size = np.size(windDirections)
    elif wind_rose_file is 'amalia':
        windRose = np.loadtxt(
            input_directory +
            'windrose_amalia_directionally_averaged_speeds.txt')
        windDirections = windRose[:, 0]
        windSpeeds = windRose[:, 1]
        windFrequencies = windRose[:, 2]
        size = np.size(windDirections)
    elif wind_rose_file is 'directional':
        windRose = np.loadtxt(input_directory + 'directional_windrose.txt')
        windDirections = windRose[:, 0]
        windSpeeds = windRose[:, 1]
        windFrequencies = windRose[:, 2]
        size = np.size(windDirections)
    elif wind_rose_file is '1d':
        windDirections = np.array([270.])
        windSpeeds = np.array([8.0])
        windFrequencies = np.array([1.0])
        size = np.size(windDirections)
    else:
        size = 20
        windDirections = np.linspace(0, 270, size)
        windFrequencies = np.ones(size) / size

    wake_model_options = {
        'nSamples': 0,
        'nRotorPoints': nRotorPoints,
        'use_ct_curve': True,
        'ct_curve_ct': ct_curve_ct,
        'ct_curve_wind_speed': ct_curve_wind_speed,
        'interp_type': 1,
        'use_rotor_components': False,
        'differentiable': differentiable,
        'verbose': False
    }

    if MODELS[model] == 'BPA':
        # initialize problem
        prob = om.Problem(
            model=OptAEP(nTurbines=nTurbs,
                         nDirections=windDirections.size,
                         nVertices=nVertices,
                         minSpacing=minSpacing,
                         differentiable=differentiable,
                         use_rotor_components=False,
                         wake_model=gauss_wrapper,
                         params_IdepVar_func=add_gauss_params_IndepVarComps,
                         params_IdepVar_args={'nRotorPoints': nRotorPoints},
                         wake_model_options=wake_model_options,
                         cp_points=cp_curve_cp.size,
                         cp_curve_spline=cp_curve_spline,
                         record_function_calls=True,
                         runparallel=False))
    elif MODELS[model] == 'FLORIS':
        # initialize problem
        prob = om.Problem(
            model=OptAEP(nTurbines=nTurbs,
                         nDirections=windDirections.size,
                         nVertices=nVertices,
                         minSpacing=minSpacing,
                         differentiable=differentiable,
                         use_rotor_components=False,
                         wake_model=floris_wrapper,
                         params_IdepVar_func=add_floris_params_IndepVarComps,
                         params_IdepVar_args={},
                         record_function_calls=True))
    # elif MODELS[model] == 'JENSEN':
    #     initialize problem
    # prob = om.Problem(model=OptAEP(nTurbines=nTurbs, nDirections=windDirections.size, nVertices=nVertices,
    #                                       minSpacing=minSpacing, differentiable=False, use_rotor_components=False,
    #                                       wake_model=jensen_wrapper,
    #                                       params_IdepVar_func=add_jensen_params_IndepVarComps,
    #                                       params_IdepVar_args={},
    #                                               record_function_calls=True))
    else:
        ValueError(
            'The %s model is not currently available. Please select BPA or FLORIS'
            % (MODELS[model]))

    print("almost time for setup")
    tic = time.time()
    print("entering setup at time = ", tic)
    prob.setup(check=False)
    toc = time.time()
    print("setup complete at time = ", toc)

    # print the results
    print(('Problem setup took %.03f sec.' % (toc - tic)))

    # assign initial values to design variables
    prob['turbineX'] = np.copy(turbineX)
    prob['turbineY'] = np.copy(turbineY)
    for direction_id in range(0, windDirections.size):
        prob['yaw%i' % direction_id] = yaw

    # assign values to constant inputs (not design variables)
    prob['rotorDiameter'] = rotorDiameter
    prob['hubHeight'] = hubHeight
    prob['axialInduction'] = axialInduction
    prob['generatorEfficiency'] = generatorEfficiency
    prob['windSpeeds'] = windSpeeds
    prob['air_density'] = air_density
    prob['windDirections'] = windDirections
    prob['windFrequencies'] = windFrequencies
    prob['Ct_in'] = Ct
    prob['Cp_in'] = Cp
    prob['cp_curve_cp'] = cp_curve_cp
    prob['cp_curve_wind_speed'] = cp_curve_wind_speed
    cutInSpeeds = np.ones(nTurbines) * cut_in_speed
    prob['cut_in_speed'] = cutInSpeeds
    ratedPowers = np.ones(nTurbines) * rated_power
    prob['rated_power'] = ratedPowers

    # assign values to turbine states
    prob['cut_in_speed'] = np.ones(nTurbines) * cut_in_speed
    prob['cut_out_speed'] = np.ones(nTurbines) * cut_out_speed
    prob['rated_power'] = np.ones(nTurbines) * rated_power
    prob['rated_wind_speed'] = np.ones(nTurbines) * rated_wind_speed
    prob['use_power_curve_definition'] = True

    # assign boundary values
    prob['boundary_center'] = np.array([boundary_center_x, boundary_center_y])
    prob['boundary_radius'] = boundary_radius

    if MODELS[model] is 'BPA':
        prob['model_params:wake_combination_method'] = np.copy(
            wake_combination_method)
        prob['model_params:ti_calculation_method'] = np.copy(ti_opt_method)
        prob['model_params:wake_model_version'] = np.copy(wake_model_version)
        prob['model_params:wec_factor'] = 1.0
        prob['model_params:wec_spreading_angle'] = 0.0
        prob['model_params:calc_k_star'] = np.copy(calc_k_star_calc)
        prob['model_params:sort'] = np.copy(sort_turbs)
        prob['model_params:z_ref'] = np.copy(z_ref)
        prob['model_params:z_0'] = np.copy(z_0)
        prob['model_params:ky'] = np.copy(k_calc)
        prob['model_params:kz'] = np.copy(k_calc)
        prob['model_params:print_ti'] = np.copy(print_ti)
        prob['model_params:shear_exp'] = np.copy(shear_exp)
        prob['model_params:I'] = np.copy(TI)
        prob['model_params:sm_smoothing'] = np.copy(sm_smoothing)
        prob['model_params:WECH'] = WECH
        if nRotorPoints > 1:
            prob['model_params:RotorPointsY'], prob[
                'model_params:RotorPointsZ'] = sunflower_points(nRotorPoints)

    xx, yy = np.meshgrid(xs, ys)
    vel_out = np.zeros((xs.size, ys.size))
    for i in np.arange(0, xs.size):
        prob['turbineX'][0] = np.copy(xs[i])
        print(i)
        for j in np.arange(0, ys.size):
            if np.sqrt((ys[j] - boundary_center_y)**2 +
                       (xs[i] - boundary_center_x)**2) > boundary_radius:
                vel_out[i, j] = np.nan
                continue
            prob['turbineY'][0] = np.copy(ys[j])
            prob.run_model()
            vel_out[i, j] = np.copy(prob['AEP'])
            # print(i*j+j)

    fig = plt.figure()

    ax = plt.axes(projection='3d')

    # Hide grid lines
    ax.grid(False)
    plt.axis("off")

    # Hide axes ticks
    ax.set_xticks([])
    ax.set_yticks([])
    ax.set_zticks([])
    # make the panes transparent
    ax.xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
    ax.yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
    ax.zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
    # make the grid lines transparent
    ax.xaxis._axinfo["grid"]['color'] = (1, 1, 1, 0)
    ax.yaxis._axinfo["grid"]['color'] = (1, 1, 1, 0)
    ax.zaxis._axinfo["grid"]['color'] = (1, 1, 1, 0)
    print(np.max(vel_out))
    ax.plot_surface(xx,
                    yy,
                    vel_out,
                    vmin=np.nanmin(vel_out) - 10,
                    vmax=np.nanmax(vel_out) + 10,
                    cmap="hot",
                    rstride=1,
                    cstride=1,
                    linewidth=0,
                    antialiased=False)
    # ax.set_zlim(0, nTurbines*2E3)
    plt.savefig('multimodal.pdf', transparent=True)

    plt.show()

    return 0
    def setUp(self):
        try:
            from plantenergy.gauss import gauss_wrapper, add_gauss_params_IndepVarComps
            self.working_import = True
        except:
            self.working_import = False

        # define turbine locations in global reference frame
        # this is the 5 deg rotated from free stream wind farm from Gebraad 2014 CFD study
        # wind to 30 deg from east, farm rotated to 35 deg from east
        turbineX = np.array([1164.7, 947.2,  1682.4, 1464.9, 1982.6, 2200.1])
        turbineY = np.array([1024.7, 1335.3, 1387.2, 1697.8, 2060.3, 1749.7])

        hubHeight = np.zeros_like(turbineX)+90.
        # import matplotlib.pyplot as plt
        # plt.plot(turbineX, turbineY, 'o')
        # print np.arctan((turbineY[5]-turbineY[0])/(turbineX[5]-turbineX[0]))*180./np.pi
        # print 0.523599*180./np.pi
        # plt.show()
        # quit()
        # plt.plot(turbineX, turbineY, 'o')
        # plt.plot(np.array([0.0, ]))
        # plt.show()

        # initialize input variable arrays
        nTurbines = turbineX.size
        rotorDiameter = np.zeros(nTurbines)
        axialInduction = np.zeros(nTurbines)
        Ct = np.zeros(nTurbines)
        Cp = np.zeros(nTurbines)
        generatorEfficiency = np.zeros(nTurbines)
        yaw = np.zeros(nTurbines)

        # define initial values
        for turbI in range(0, nTurbines):
            rotorDiameter[turbI] = 126.4            # m
            axialInduction[turbI] = 1.0/3.0
            Ct[turbI] = 4.0*axialInduction[turbI]*(1.0-axialInduction[turbI])
            Cp[turbI] = 0.7737/0.944 * 4.0 * 1.0/3.0 * np.power((1 - 1.0/3.0), 2)
            generatorEfficiency[turbI] = 1.#0.944
            yaw[turbI] = 0.     # deg.

        # Define flow properties
        nDirections = 1
        wind_speed = 8.0                                # m/s
        air_density = 1.1716                            # kg/m^3
        wind_direction = 270.-0.523599*180./np.pi       # deg (N = 0 deg., using direction FROM, as in met-mast data)
        wind_frequency = 1.                             # probability of wind in this direction at this speed

        # set up problem
        nRotorPoints = 100

        # define turbine size
        rotor_diameter = 126.4  # (m)
        hub_height = 90.0

        z_ref = 80.0  # m
        z_0 = 0.0

        # load performance characteristics
        cut_in_speed = 3.  # m/s
        rated_power = 5000.  # kW
        generator_efficiency = 0.944
        input_directory = "./input_files/"
        filename = input_directory + "NREL5MWCPCT_dict.p"
        # filename = "../input_files/NREL5MWCPCT_smooth_dict.p"
        import cPickle as pickle

        data = pickle.load(open(filename, "rb"))
        ct_curve = np.zeros([data['wind_speed'].size, 2])
        ct_curve_wind_speed = data['wind_speed']
        ct_curve_ct = data['CT']

        # cp_curve_cp = data['CP']
        # cp_curve_wind_speed = data['wind_speed']

        loc0 = np.where(data['wind_speed'] < 11.55)
        loc1 = np.where(data['wind_speed'] > 11.7)

        cp_curve_cp = np.hstack([data['CP'][loc0], data['CP'][loc1]])
        cp_curve_wind_speed = np.hstack([data['wind_speed'][loc0], data['wind_speed'][loc1]])
        cp_curve_spline = UnivariateSpline(cp_curve_wind_speed, cp_curve_cp, ext='const')
        cp_curve_spline.set_smoothing_factor(.000001)

        wake_model_options = {'nSamples': 0,
                              'nRotorPoints': nRotorPoints,
                              'use_ct_curve': True,
                              'ct_curve_ct': ct_curve_ct,
                              'ct_curve_wind_speed': ct_curve_wind_speed,
                              'interp_type': 1,
                              'use_rotor_components': False,
                              'differentiable': True,
                              'verbose': False}

        prob = Problem(root=AEPGroup(nTurbines=nTurbines, nDirections=nDirections, wake_model=gauss_wrapper,
                                     wake_model_options=wake_model_options, datasize=0, use_rotor_components=False,
                                     params_IdepVar_func=add_gauss_params_IndepVarComps, differentiable=True,
                                     params_IndepVar_args={'nRotorPoints': nRotorPoints}))

        # initialize problem
        prob.setup(check=True)

        if nRotorPoints > 1:
            from plantenergy.utilities import sunflower_points
            prob['model_params:RotorPointsY'], prob['model_params:RotorPointsZ'] = sunflower_points(nRotorPoints)

        # assign values to turbine states
        prob['turbineX'] = turbineX
        prob['turbineY'] = turbineY
        prob['hubHeight'] = hubHeight
        prob['yaw0'] = yaw

        # assign values to constant inputs (not design variables)
        prob['rotorDiameter'] = rotorDiameter
        prob['axialInduction'] = axialInduction
        prob['generatorEfficiency'] = generatorEfficiency
        prob['windSpeeds'] = np.array([wind_speed])
        prob['model_params:I'] = 0.06
        prob['model_params:z_ref'] = 90.
        prob['model_params:z_0'] = 0.001
        prob['model_params:wake_model_version'] = 2016.
        prob['air_density'] = air_density
        prob['windDirections'] = np.array([wind_direction])
        prob['windFrequencies'] = np.array([wind_frequency])
        prob['cp_curve_cp'] = cp_curve_cp
        prob['cp_curve_wind_speed'] = cp_curve_wind_speed
        cutInSpeeds = np.ones(nTurbines) * cut_in_speed
        prob['cut_in_speed'] = cutInSpeeds
        ratedPowers = np.ones(nTurbines) * rated_power
        prob['rated_power'] = ratedPowers

        prob['model_params:wake_combination_method'] = 1
        prob['model_params:ti_calculation_method'] = 4
        prob['model_params:wake_model_version'] = 2016
        prob['model_params:wec_factor'] = 1.0
        prob['model_params:calc_k_star'] = True
        prob['model_params:sort'] = True
        prob['model_params:z_ref'] = z_ref
        prob['model_params:z_0'] = z_0
        prob['model_params:ky'] = 0.022
        prob['model_params:kz'] = 0.022
        prob['model_params:print_ti'] = False
        prob['model_params:shear_exp'] = 0.15
        prob['model_params:I'] = 0.06
        prob['model_params:sm_smoothing'] = 700
        if nRotorPoints > 1:
            prob['model_params:RotorPointsY'], prob['model_params:RotorPointsZ'] = sunflower_points(nRotorPoints)

        prob['model_params:wec_spreading_angle'] = 0.0

        prob['Ct_in'] = Ct
        prob['Cp_in'] = Cp

        # run the problem
        prob.run()

        self.prob = prob
Exemple #10
0
    def setUp(self):
        from plantenergy.utilities import sunflower_points
        self.tolerance = 1E-1
        self.wake_combination_method = 1
        self.wake_model_version = 2016
        self.rotor_diameter = 80.
        self.hub_height = 70.
        self.ct = 0.6
        self.alpha = 2.32
        self.beta = 0.154
        self.expratemultiplier = 1.0
        self.wec_factor = 1.0
        self.wind_speed = 8.0
        self.z_ref = self.hub_height
        self.z_0 = 0.0002
        self.shear_exp = 0.15
        self.yaw = 0.0
        self.wtVelocity = np.array([self.wind_speed])
        self.TI = 0.077
        self.ky = 0.3837*self.TI + 0.003678  # np.array([0.3837*TIturbs[0] + 0.003678])
        self.kz = 0.3837*self.TI + 0.003678 # np.array([0.3837*TIturbs[0] + 0.003678])
        rotorpoints = sunflower_points(100)
        self.RotorPointsY = rotorpoints[0] #np.array([0, .5, 1.0, 0., 0.0, -.5, -1.0, 0., 0.])
        self.RotorPointsZ = rotorpoints[1] #np.array([0, 0., 0., .5, 1.0, 0., 0.0, -0.5, -1.])
        # self.RotorPointsY = np.array([0])
        # self.RotorPointsZ = np.array([0])
        self.RotorPointsY = np.array([0, .5, 1.0, 0., 0.0, -.5, -1.0, 0., 0.])
        self.RotorPointsZ = np.array([0, 0., 0., .5, 1.0, 0., 0.0, -0.5, -1.])
        self.TI_calculation_method = 4
        self.calc_k_star = True
        self.print_ti = False
        self.interp_type = 1
        self.sm_smoothing = 700.

        loc_data = np.loadtxt('input_files/horns_rev_locations.txt', delimiter=',')
        turbineXw = loc_data[:, 0] * self.rotor_diameter
        turbineYw = loc_data[:, 1] * self.rotor_diameter
        turbineZ = np.ones_like(turbineXw) * self.hub_height
        sorted_x_idx = np.argsort(turbineXw, kind='heapsort')
        rotorDiameter = np.ones_like(turbineXw) * self.rotor_diameter
        Ct = np.ones_like(turbineXw) * self.ct
        yaw = np.ones_like(turbineXw) * self.yaw
        TI_turbs = np.ones_like(turbineXw) * self.TI

        use_ct_curve = True
        # ct_data = np.loadtxt('input_files/predicted_ct_vestas_v80_niayifar2016.txt', delimiter=',')
        ct_data = np.loadtxt('input_files/mfg_ct_vestas_v80_niayifar2016.txt', delimiter=',')
        ct_curve_wind_speed = ct_data[:, 0]
        ct_curve_ct = ct_data[:, 1]

        CalculateFlowField=False

        wtVelocity, _ = porteagel_analyze(turbineXw, sorted_x_idx, turbineYw, turbineZ,
                                       rotorDiameter, Ct, self.wind_speed,
                                       yaw, self.ky, self.kz, self.alpha, self.beta, TI_turbs, self.RotorPointsY,
                                       self.RotorPointsZ, np.array([0]), np.array([0]), np.array([0]),
                                       self.z_ref, self.z_0, self.shear_exp, self.wake_combination_method,
                                       self.TI_calculation_method, self.calc_k_star, self.wec_factor, self.print_ti,
                                       self.wake_model_version, self.interp_type, use_ct_curve,
                                       ct_curve_wind_speed, ct_curve_ct, self.sm_smoothing,
                                       self.expratemultiplier, CalculateFlowField)

        free_stream_power = power_func_v80(self.wind_speed)
        wtPower = power_func_v80(wtVelocity)

        self.norm_pow_ave_by_row = np.zeros(10)
        for i in np.arange(0, self.norm_pow_ave_by_row.size):
            pow_ave_row = np.average([wtPower[40 + i], wtPower[50 + i], wtPower[60 + i]])
            self.norm_pow_ave_by_row[i] = pow_ave_row / free_stream_power