def test_wave_class_1(self):
     # Test with normal partitioning
     file = 'tests/test_data//test_metdata_normal.txt'
     met_data = windbins.get_met_data(file)
     waves = windbins.Wave(met_data)
     met_partitions = waves.partition(num_divisions=3)
     compare_partitions = {
         'Significant Wave Height': [1.58, 1.8, 1.77],
         'Wave Direction': [98.0, 107.0, 116.0],
         'Wave Period': [13.79, 13.79, 13.79]
     }
     compare_partitions = pd.DataFrame(data=compare_partitions)
     assert compare_partitions.equals(met_partitions)
    def test_wave_class_4(self):
        # Test with custom partitioning, 1 wave climate consisting of only nans
        file = 'tests/test_data//test_metdata_normal.txt'
        met_data = windbins.get_met_data(file)
        waves = windbins.Wave(met_data)

        @mock.patch('fowt_force_gen.windbins.input', create=True)
        def dummy_inputs(mocked_inputs):
            mocked_inputs.side_effect = ['y', '1', '9 10 11']
            met_partitions = waves.partition(custom_partitioning=True)
            compare_partitions = {
                'Significant Wave Height': [np.nan],
                'Wave Direction': [np.nan],
                'Wave Period': [np.nan]
            }
            compare_partitions = pd.DataFrame(data=compare_partitions)
            assert compare_partitions.equals(met_partitions)

        dummy_inputs()
    def test_wave_class_3(self):
        # Test with custom partitioning, 2 overlapping wave climates
        file = 'tests/test_data//test_metdata_normal.txt'
        met_data = windbins.get_met_data(file)
        waves = windbins.Wave(met_data)

        @mock.patch('fowt_force_gen.windbins.input', create=True)
        def dummy_inputs(mocked_inputs):
            mocked_inputs.side_effect = ['y', '2', '1 3 5 7 9', '1 2 3 5 7']
            met_partitions = waves.partition(custom_partitioning=True)
            compare_partitions = {
                'Significant Wave Height': [1.723, 1.694],
                'Wave Direction': [98.75, 98.6],
                'Wave Period': [15.368, 15.256]
            }
            compare_partitions = pd.DataFrame(data=compare_partitions)
            assert compare_partitions.equals(met_partitions)

        dummy_inputs()
    def test_wave_class_2(self, monkeypatch):
        # Test with custom partitioning, 2 disparate wave climates
        file = 'tests/test_data//test_metdata_normal.txt'
        met_data = windbins.get_met_data(file)
        waves = windbins.Wave(met_data)

        @mock.patch('fowt_force_gen.windbins.input', create=True)
        def dummy_inputs(mocked_inputs):
            mocked_inputs.side_effect = ['y', '2', '0 1 2 3 4', '5 6 7 8']
            met_partitions = waves.partition(custom_partitioning=True)
            compare_partitions = {
                'Significant Wave Height': [1.684, 1.740],
                'Wave Direction': [107.4, 110.5],
                'Wave Period': [13.816, 15.59]
            }
            compare_partitions = pd.DataFrame(data=compare_partitions)
            assert compare_partitions.equals(met_partitions)

        dummy_inputs()
Example #5
0
def main():

    # Step 1: The user enters in geographic location of buoy location off the coast of North America
    parser = argparse.ArgumentParser(
        description=
        'Identifies nearest NOAA stationary buoy to input coordinates')
    parser.add_argument(
        '-lat',
        '--latitude',
        type=str,
        required=True,
        help=
        'String input of latitude. Use decimals degrees and either N/S or +/- to notate direction.'
    )
    parser.add_argument(
        '-lon',
        '--longitude',
        type=str,
        required=True,
        help=
        'String input of longitude. Use decimal degrees and either E/W or +/- to notate direction.'
    )
    parser.add_argument(
        '-pf',
        '--platform',
        type=str,
        required=True,
        help='Platform type. Either OC3 or OC4 (i.e. Hywind or DeepCwind)')
    parser.add_argument(
        '-fr',
        '--fileroot',
        type=str,
        required=True,
        help='Root of filenames that all output files will start with.')
    args = parser.parse_args()

    # Step 1.5: Define template OpenFAST files to be used later in custom file creation (Step 5)
    #           note: this ignores MoorDyn, which is created independently in Step 4
    template_file_dir = 'template_files'
    turbsim_file_dir = 'turbsim_files'
    dat_file_dir = 'fast_input_files'
    output_file_dir = 'output_files'
    mat_file_dir = 'force_gen'

    if not os.path.exists('force_gen'):
        os.makedirs('force_gen')
    if not os.path.exists('turbsim_files'):
        os.makedirs('turbsim_files')
    if not os.path.exists('output_files'):
        os.makedirs('output_files')

    if args.platform.lower() == 'oc3':
        template_hd_file = template_file_dir + '/OC3Hywind_HydroDyn_template.dat'
        template_fst_file = template_file_dir + '/OC3Hywind_OpenFAST_template.fst'
    elif args.platform.lower() == 'oc4':
        template_hd_file = template_file_dir + '/OC4Semi_HydroDyn_template.dat'
        template_fst_file = template_file_dir + '/OC4Semi_OpenFAST_template.fst'
    else:
        raise ValueError(
            "Platform type not recognized. Please specify either 'OC3' or 'OC4'"
        )

    template_inp_file = template_file_dir + '/IECKAI_template.inp'
    template_ifw_file = template_file_dir + '/InflowWind_template.dat'

    # Step 2: The nearest NOAA buoy is identified, and meteorological from the buoy is scraped and saved in text files
    buoy_num = buoy.geo_match(args.latitude, args.longitude)
    water_depth = buoy.get_water_depth(buoy_num)
    buoy.data_scraper(buoy_num)

    # Step 3: Read the text files and partition critical parameters into bins. If wind or current data does
    #         not exist, specify as such so it isn't accounted for in OpenFAST file creation. Prompt user for input
    #         to determine how to split wave climates, as separate HydroDyn files are created for each climate later.
    met_file = parse.get_most_recent_file_containing(
        'met_data_' + str(buoy_num), '.txt')
    met_data = windbins.get_met_data(met_file)
    os.remove(met_file)

    try:
        wind_file = parse.get_most_recent_file_containing(
            'wind_data_' + str(buoy_num), '.txt')
        wind_data = windbins.get_wind_data(wind_file)
        wind = windbins.Wind(wind_data)
        os.remove(wind_file)
    except:
        wind = windbins.Wind(met_data)
        pass

    try:
        curr_file = parse.get_most_recent_file_containing(
            'curr_data_' + str(buoy_num), '.txt')
        curr_data, curr_depth = windbins.get_current_data(curr_file)
        curr_speed = curr_data['Current Speed']
        curr_dir = curr_data['Current Direction']
        no_curr_file = False
        os.remove(curr_file)
    except:
        no_curr_file = True
        pass

    bin_probabilities = wind.get_bin_probabilities()

    waves = windbins.Wave(met_data)
    wave_climates = waves.partition(custom_partitioning=True)

    # Step 4: Tune the floating wind platform mooring system for the depth and platform used at the site, and generate
    #         the resulting MoorDyn input file
    moortune.tune(water_depth, args.platform,
                  dat_file_dir + '/' + args.fileroot + '_MoorDyn.dat')

    # Step 5: Generate the other needed OpenFAST input files for each permutation, and run OpenFAST
    #         Create INP files and run TurbSim
    filegen.inp_bulk_filegen(template_inp_file,
                             turbsim_file_dir + '/' + args.fileroot,
                             bin_probabilities.index.values)
    inp_files = parse.get_filenames('.inp', file_directory=turbsim_file_dir)
    run_fast.run_turbsim(inp_files)

    #         Create InflowWind files from TurbSim BTS files and wind direction data
    filegen.inflowwind_bulk_filegen(
        template_ifw_file, dat_file_dir + '/' + args.fileroot + '_InflowWind',
        turbsim_file_dir, bin_probabilities.columns)

    #          Create HydroDyn DAT files from custom wave climates
    if no_curr_file:
        filegen.hydrodyn_bulk_filegen(
            template_hd_file, dat_file_dir + '/' + args.fileroot + '_HydroDyn',
            water_depth, wave_climates)
    else:
        filegen.hydrodyn_bulk_filegen(
            template_hd_file,
            dat_file_dir + '/' + args.fileroot + '_HydroDyn',
            water_depth,
            wave_climates,
            current_climate=[curr_depth, curr_speed, curr_dir])

    #       Create OpenFAST FST files from previous custom files
    filegen.fst_bulk_filegen(
        template_fst_file, args.fileroot,
        dat_file_dir + '/' + args.fileroot + '_MoorDyn.dat', dat_file_dir,
        dat_file_dir)

    #       Run OpenFAST for all created FST files and move output files to specified directories
    fst_files = parse.get_filenames('.fst')
    run_fast.run_fast(fst_files)
    os.remove(fst_files)

    outb_files = parse.get_filenames('.outb')
    parse.move_files(outb_files, output_file_dir)

    md_out_files = parse.get_filenames('.out')
    parse.move_files(md_out_files, output_file_dir)

    # Do post-processing for all tests
    all_output_roots = [
        filenames.replace('.outb', '') for filenames in outb_files
    ]

    for test in all_output_roots:
        # Step 6: Parse the OpenFAST outputs into mooring/anchor tension and platform surge/sway into numpy arrays
        #         containing the relevant statistical occurrences
        ptfm_surge, ptfm_sway, anchor_tension, line1_tension, line2_tension, line3_tension = \
            parse.output_parse(output_file_dir+'/'+test)

        surge_stats = parse.make_distributions(ptfm_surge,
                                               calculate_stdev=False)
        sway_stats = parse.make_distributions(ptfm_sway, calculate_stdev=False)
        anchor_stats = parse.make_distributions(anchor_tension)
        line1_stats = parse.make_distributions(line1_tension)
        line2_stats = parse.make_distributions(line2_tension)
        line3_stats = parse.make_distributions(line3_tension)

        # Step 7: Create MAT files matching the format of the external reliability code
        reliability_results_filename = mat_file_dir + '/' + 'ReliabilityResults_' + test + '.mat'
        surge_results_filename = mat_file_dir + '/' + 'Surge_' + test + '.mat'
        filegen.create_mat_files(reliability_results_filename,
                                 surge_results_filename, line1_stats,
                                 line2_stats, line3_stats, anchor_stats[0, :],
                                 anchor_stats[1, :], anchor_stats[2, :],
                                 surge_stats, sway_stats)
Example #6
0
def main():

    # Step 1: The user enters in geographic location of buoy location off the coast of North America
    parser = argparse.ArgumentParser(
        description=
        'Identifies nearest NOAA stationary buoy to input coordinates')
    parser.add_argument(
        '-lat',
        '--latitude',
        type=str,
        required=True,
        help=
        'String input of latitude. Use decimals degrees and either N/S or +/- to notate direction.'
    )
    parser.add_argument(
        '-lon',
        '--longitude',
        type=str,
        required=True,
        help=
        'String input of longitude. Use decimal degrees and either E/W or +/- to notate direction.'
    )
    parser.add_argument(
        '-pf',
        '--platform',
        type=str,
        required=True,
        help='Platform type. Either OC3 or OC4 (i.e. Hywind or DeepCwind)')
    parser.add_argument(
        '-fr',
        '--fileroot',
        type=str,
        required=True,
        help='Root of filenames that all output files will start with.')
    parser.add_argument(
        '-ex',
        '--example',
        type=int,
        help=
        'Example MoorDyn files to use (optional). Overwrites fileroot if used.'
    )
    args = parser.parse_args()

    # Step 1.5: Define template OpenFAST files to be used later in custom file creation (Step 5)
    #           note: this ignores MoorDyn, which is created independently in Step 4
    if args.example:
        fileroot = 'example' + str(args.example)
        ex_file_dir = 'example_files'
    else:
        fileroot = args.fileroot
    template_file_dir = 'template_files'
    turbsim_file_dir = 'turbsim_files'
    dat_file_dir = 'fast_input_files'

    if not os.path.exists('force_gen'):
        os.makedirs('force_gen')
    if not os.path.exists('turbsim_files'):
        os.makedirs('turbsim_files')

    if args.platform.lower() == 'oc3':
        template_hd_file = template_file_dir + '/OC3Hywind_HydroDyn_template.dat'
        template_fst_file = template_file_dir + '/OC3Hywind_OpenFAST_template.fst'
    elif args.platform.lower() == 'oc4':
        template_hd_file = template_file_dir + '/OC4Semi_HydroDyn_template.dat'
        template_fst_file = template_file_dir + '/OC4Semi_OpenFAST_template.fst'
    else:
        raise ValueError(
            "Platform type not recognized. Please specify either 'OC3' or 'OC4'"
        )

    template_inp_file = template_file_dir + '/IECKAI_template.inp'
    template_ifw_file = template_file_dir + '/InflowWind_template.dat'

    # Step 2: The nearest NOAA buoy is identified, and meteorological from the buoy is scraped and saved in text files
    buoy_num = buoy.geo_match(args.latitude, args.longitude)
    water_depth = buoy.get_water_depth(buoy_num)
    buoy.data_scraper(buoy_num)

    # Step 3: Read the text files and partition critical parameters into bins. If wind or current data does
    #         not exist, specify as such so it isn't accounted for in OpenFAST file creation. Prompt user for input
    #         to determine how to split wave climates, as separate HydroDyn files are created for each climate later.
    met_file = parse.get_most_recent_file_containing(
        'met_data_' + str(buoy_num), '.txt')
    met_data = windbins.get_met_data(met_file)
    os.remove(met_file)

    try:
        wind_file = parse.get_most_recent_file_containing(
            'wind_data_' + str(buoy_num), '.txt')
        wind_data = windbins.get_wind_data(wind_file)
        wind = windbins.Wind(wind_data)
        os.remove(wind_file)
    except:
        wind = windbins.Wind(met_data)
        pass

    try:
        curr_file = parse.get_most_recent_file_containing(
            'curr_data_' + str(buoy_num), '.txt')
        curr_data, curr_depth = windbins.get_current_data(curr_file)
        curr_speed = curr_data['Current Speed']
        curr_dir = curr_data['Current Direction']
        no_curr_file = False
        os.remove(curr_file)
    except:
        no_curr_file = True
        pass

    bin_probabilities = wind.get_bin_probabilities()
    waves = windbins.Wave(met_data)
    wave_climates = waves.partition(custom_partitioning=True)

    # Step 4: Tune the floating wind platform mooring system for the depth and platform used at the site, and generate
    #         the resulting MoorDyn input file
    if not args.example:
        moortune.tune(water_depth, args.platform,
                      dat_file_dir + '/' + fileroot + '_MoorDyn.dat')

    # Step 5: Generate the other needed OpenFAST input files for each permutation, and run OpenFAST
    #         Create INP files
    filegen.inp_bulk_filegen(template_inp_file,
                             turbsim_file_dir + '/' + fileroot,
                             bin_probabilities.index.values)
    inp_files = parse.get_filenames('.inp', file_directory=turbsim_file_dir)
    #         Run TurbSim and create InflowWind files from BTS files and wind direction data
    if args.example:
        filegen.inflowwind_bulk_filegen(template_ifw_file,
                                        dat_file_dir + '/' + fileroot +
                                        '_InflowWind',
                                        turbsim_file_dir,
                                        bin_probabilities.columns,
                                        no_turbsim=True)
    else:
        run_fast.run_turbsim(inp_files)
        filegen.inflowwind_bulk_filegen(
            template_ifw_file, dat_file_dir + '/' + fileroot + '_InflowWind',
            turbsim_file_dir, bin_probabilities.columns)

    #          Create HydroDyn DAT files from custom wave climates
    if no_curr_file:
        filegen.hydrodyn_bulk_filegen(
            template_hd_file, dat_file_dir + '/' + fileroot + '_HydroDyn',
            water_depth, wave_climates)
    else:
        filegen.hydrodyn_bulk_filegen(
            template_hd_file,
            dat_file_dir + '/' + fileroot + '_HydroDyn',
            water_depth,
            wave_climates,
            current_climate=[curr_depth, curr_speed, curr_dir])

    #       Create OpenFAST FST files from previous custom files

    if args.example:
        filegen.fst_bulk_filegen(template_fst_file, 'force_gen/' + fileroot,
                                 ex_file_dir + '/' + fileroot + '_MoorDyn.dat',
                                 dat_file_dir, dat_file_dir)
    else:
        filegen.fst_bulk_filegen(
            template_fst_file, 'force_gen/' + fileroot,
            dat_file_dir + '/' + fileroot + '_MoorDyn.dat', dat_file_dir,
            dat_file_dir)
    bin_probabilities.to_csv(fileroot + '_bin_probabilities.csv')