def test_wind_icing_losses(i): """Test wind icing losses.""" pc = Gen.get_pc(REV2_POINTS, None, SAM_FILE, 'windpower', sites_per_worker=3, res_file=RES_FILE) pc.project_points.sam_configs[SAM_FILE]['en_icing_cutoff'] = 1 pc.project_points.sam_configs[SAM_FILE]['icing_cutoff_temp'] = \ ICING_BASELINE[i]['temp'] pc.project_points.sam_configs[SAM_FILE]['icing_cutoff_rh'] = \ ICING_BASELINE[i]['rh'] gen = Gen.reV_run('windpower', pc, SAM_FILE, RES_FILE, max_workers=1, sites_per_worker=3, fout=None) gen_outs = list(gen.out['cf_mean']) assert np.allclose(gen_outs, ICING_BASELINE[i]['output'], rtol=RTOL, atol=ATOL)
def test_bifacial(): """Test pvwattsv7 with bifacial panel with albedo.""" year = 2012 rev2_points = slice(0, 1) res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(year) sam_files = TESTDATADIR + '/SAM/i_pvwattsv7.json' # run reV 2.0 generation pp = ProjectPoints(rev2_points, sam_files, 'pvwattsv7', res_file=res_file) gen = Gen.reV_run(tech='pvwattsv7', points=rev2_points, sam_files=sam_files, res_file=res_file, max_workers=1, sites_per_worker=1, fout=None) sam_files = TESTDATADIR + '/SAM/i_pvwattsv7_bifacial.json' # run reV 2.0 generation pp = ProjectPoints(rev2_points, sam_files, 'pvwattsv7', res_file=res_file) gen_bi = Gen.reV_run(tech='pvwattsv7', points=rev2_points, sam_files=sam_files, res_file=res_file, max_workers=1, sites_per_worker=1, fout=None) assert all(gen_bi.out['cf_mean'] > gen.out['cf_mean']) assert np.isclose(gen.out['cf_mean'][0], 0.151, atol=0.005) assert np.isclose(gen_bi.out['cf_mean'][0], 0.162, atol=0.005)
def test_rev_run_gen_econ(points=slice(0, 10), year=2012, max_workers=1): """Test full reV2 gen->econ pipeline with windbos inputs and benchmark against baseline results.""" # get full file paths. sam_files = os.path.join(TESTDATADIR, 'SAM/i_singleowner_windbos.json') res_file = os.path.join(TESTDATADIR, 'wtk/ri_100_wtk_{}.h5'.format(year)) fn_gen = 'windbos_gen_{}.h5'.format(year) cf_file = os.path.join(OUT_DIR, fn_gen) # run reV 2.0 generation Gen.reV_run('windpower', points, sam_files, res_file, output_request=('cf_mean', 'cf_profile'), max_workers=max_workers, sites_per_worker=3, fout=fn_gen, dirout=OUT_DIR) econ_outs = ('lcoe_nom', 'lcoe_real', 'flip_actual_irr', 'project_return_aftertax_npv', 'total_installed_cost', 'turbine_cost', 'sales_tax_cost', 'bos_cost') e = Econ.reV_run(points=points, sam_files=sam_files, cf_file=cf_file, cf_year=year, site_data=None, output_request=econ_outs, max_workers=max_workers, sites_per_worker=3, fout=None) for k in econ_outs: msg = 'Failed for {}'.format(k) assert np.allclose(e.out[k], BASELINE[k], atol=ATOL, rtol=RTOL), msg if PURGE_OUT: for fn in os.listdir(OUT_DIR): os.remove(os.path.join(OUT_DIR, fn)) return e
def test_wind_gen_site_data(points=slice(0, 5), year=2012, max_workers=1): """Test site specific SAM input config via site_data arg""" sam_files = TESTDATADIR + '/SAM/wind_gen_standard_losses_0.json' res_file = TESTDATADIR + '/wtk/ri_100_wtk_{}.h5'.format(year) output_request = ('cf_mean', 'turb_generic_loss') baseline = Gen.reV_run('windpower', points, sam_files, res_file, max_workers=max_workers, sites_per_worker=3, fout=None, output_request=output_request) site_data = pd.DataFrame({ 'gid': np.arange(2), 'turb_generic_loss': np.zeros(2) }) test = Gen.reV_run('windpower', points, sam_files, res_file, max_workers=max_workers, sites_per_worker=3, fout=None, output_request=output_request, site_data=site_data) assert all(test.out['cf_mean'][0:2] > baseline.out['cf_mean'][0:2]) assert np.allclose(test.out['cf_mean'][2:], baseline.out['cf_mean'][2:]) assert np.allclose(test.out['turb_generic_loss'][0:2], np.zeros(2)) assert np.allclose(test.out['turb_generic_loss'][2:], 16.7 * np.ones(3))
def test_wind_low_temp_cutoff(i): """Test wind low temperature cutoff.""" pc = Gen.get_pc(REV2_POINTS, None, SAM_FILE, 'windpower', sites_per_worker=3, res_file=RES_FILE) pc.project_points.sam_configs[SAM_FILE]['en_low_temp_cutoff'] = 1 pc.project_points.sam_configs[SAM_FILE]['low_temp_cutoff'] = \ LOW_TEMP_BASELINE[i]['temp'] gen = Gen.reV_run('windpower', pc, SAM_FILE, RES_FILE, max_workers=1, sites_per_worker=3, fout=None) gen_outs = list(gen.out['cf_mean']) assert np.allclose(gen_outs, LOW_TEMP_BASELINE[i]['output'], rtol=RTOL, atol=ATOL)
def test_pvwatts_v5_v7(): """Test reV pvwatts generation for v5 vs. v7""" year = 2012 rev2_points = slice(0, 3) res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(year) sam_files = TESTDATADIR + '/SAM/naris_pv_1axis_inv13.json' # run reV 2.0 generation pp = ProjectPoints(rev2_points, sam_files, 'pvwattsv7', res_file=res_file) gen7 = Gen.reV_run(tech='pvwattsv7', points=rev2_points, sam_files=sam_files, res_file=res_file, max_workers=1, sites_per_worker=1, fout=None) pp = ProjectPoints(rev2_points, sam_files, 'pvwattsv5', res_file=res_file) gen5 = Gen.reV_run(tech='pvwattsv5', points=rev2_points, sam_files=sam_files, res_file=res_file, max_workers=1, sites_per_worker=1, fout=None) msg = 'PVwatts v5 and v7 did not match within test tolerance' assert np.allclose(gen7.out['cf_mean'], gen5.out['cf_mean'], atol=3), msg
def test_wind_gen_slice(f_rev1_out, rev2_points, year, max_workers): """Test reV 2.0 generation for PV and benchmark against reV 1.0 results.""" # get full file paths. rev1_outs = os.path.join(TESTDATADIR, 'ri_wind', 'scalar_outputs', f_rev1_out) sam_files = TESTDATADIR + '/SAM/wind_gen_standard_losses_0.json' res_file = TESTDATADIR + '/wtk/ri_100_wtk_{}.h5'.format(year) # run reV 2.0 generation pp = ProjectPoints(rev2_points, sam_files, 'windpower', res_file=res_file) gen = Gen.reV_run('windpower', rev2_points, sam_files, res_file, max_workers=max_workers, sites_per_worker=3, fout=None) gen_outs = list(gen.out['cf_mean']) # initialize the rev1 output hander with wind_results(rev1_outs) as wind: # get reV 1.0 results cf_mean_list = wind.get_cf_mean(pp.sites, year) # benchmark the results result = np.allclose(gen_outs, cf_mean_list, rtol=RTOL, atol=ATOL) msg = 'Wind cf_means results did not match reV 1.0 results!' assert result is True, msg
def test_time_index_step(): """Test reV time_index_step option to upscale resource""" # get full file paths. baseline = os.path.join(TESTDATADIR, 'gen_out', 'gen_profiles_hr_2017.h5') sam_files = os.path.join(TESTDATADIR, 'SAM', 'naris_pv_1axis_inv13_hr.json') res_file = os.path.join(TESTDATADIR, 'nsrdb', 'nsrdb_surfrad_2017.h5') # run reV 2.0 generation gen = Gen.reV_run(tech='pvwattsv5', points=slice(0, None), sam_files=sam_files, res_file=res_file, output_request=('cf_mean', 'cf_profile'), max_workers=1, sites_per_worker=100, fout=None) gen_outs = gen.out['cf_profile'].astype(np.int32) if not os.path.exists(baseline): with h5py.File(baseline, 'w') as f: f.create_dataset('cf_profile', data=gen_outs, dtype=gen_outs.dtype) else: with h5py.File(baseline, 'r') as f: baseline = f['cf_profile'][...].astype(np.int32) assert np.allclose(gen_outs, baseline)
def test_pass_through_lcoe_args(): """Test that the kwarg works to pass through LCOE input args from the SAM input to the reV output.""" year = 2012 rev2_points = slice(0, 3) res_file = os.path.join(TESTDATADIR, 'wtk/ri_100_wtk_{}.h5'.format(year)) sam_files = os.path.join(TESTDATADIR, 'SAM/i_windpower_lcoe.json') output_request = ('cf_mean', 'lcoe_fcr', 'capital_cost', 'fixed_charge_rate', 'variable_operating_cost', 'fixed_operating_cost') # run reV 2.0 generation gen = Gen.reV_run(tech='windpower', points=rev2_points, sam_files=sam_files, res_file=res_file, max_workers=1, sites_per_worker=1, fout=None, output_request=output_request) checks = [x in gen.out for x in Gen.LCOE_ARGS] assert all(checks) assert 'lcoe_fcr' in gen.out assert 'cf_mean' in gen.out
def test_gen_swh_leap_year(): """Test generation for solar water heating for a leap year (2012)""" points = slice(0, 1) sam_files = TESTDATADIR + '/SAM/swh_default.json' res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(2012) output_request = ('T_amb', 'T_cold', 'T_deliv', 'T_hot', 'draw', 'beam', 'diffuse', 'I_incident', 'I_transmitted', 'annual_Q_deliv', 'Q_deliv', 'cf_mean', 'solar_fraction') # run reV 2.0 generation gen = Gen.reV_run(tech='solarwaterheat', points=points, sam_files=sam_files, res_file=res_file, max_workers=1, output_request=output_request, sites_per_worker=1, fout=None, scale_outputs=True) # Some results will be different with PySAM 2 vs 1.2.1, in particular, # solar_fraction and cf_mean my_assert(gen.out['T_amb'], 204459, 0) my_assert(gen.out['T_cold'], 433511.47, 0) my_assert(gen.out['T_deliv'], 836763.3482, 0) my_assert(gen.out['T_hot'], 836961.2498, 0) my_assert(gen.out['draw'], 145999.90, 0) my_assert(gen.out['beam'], 3047259, 0) my_assert(gen.out['diffuse'], 1222013, 0) my_assert(gen.out['I_incident'], 3279731.523, -1) my_assert(gen.out['I_transmitted'], 2769482.776, -1) my_assert(gen.out['annual_Q_deliv'], 2697.09, 1) my_assert(gen.out['Q_deliv'], 5394.188339, 1) my_assert(gen.out['solar_fraction'], 0.6772, 4)
def test_gen_swh_non_leap_year(): """Test generation for solar water heating for non leap year (2013)""" points = slice(0, 1) sam_files = TESTDATADIR + '/SAM/swh_default.json' res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(2013) output_request = ('T_amb', 'T_cold', 'T_deliv', 'T_hot', 'draw', 'beam', 'diffuse', 'I_incident', 'I_transmitted', 'annual_Q_deliv', 'Q_deliv', 'cf_mean', 'solar_fraction', 'gen_profile') # run reV 2.0 generation gen = Gen.reV_run(tech='solarwaterheat', points=points, sam_files=sam_files, res_file=res_file, max_workers=1, output_request=output_request, sites_per_worker=1, fout=None, scale_outputs=True) # Some results will be different with PySAM 2 vs 1.2.1 my_assert(gen.out['T_amb'], 180621, 0) my_assert(gen.out['T_cold'], 410491.1066, 0) my_assert(gen.out['T_deliv'], 813060.4364, 0) my_assert(gen.out['T_hot'], 813419.981, 0) my_assert(gen.out['Q_deliv'], 5390.47749, 1) # Verify series are in correct order and have been rolled correctly if os.path.exists(BASELINE): with open(BASELINE, 'r') as f: profiles = json.load(f) for k in profiles.keys(): assert np.allclose(profiles[k], gen.out[k], rtol=0, atol=0.001) else: with open(BASELINE, 'w') as f: out = {k: v.tolist() for k, v in gen.out.items()} json.dump(out, f)
def test_pv_gen_csv2(f_rev1_out='project_outputs.h5', rev2_points=TESTDATADIR + '/project_points/ri.csv', res_file=TESTDATADIR + '/nsrdb/ri_100_nsrdb_2012.h5'): """Test project points csv input with list-based sam files.""" rev1_outs = os.path.join(TESTDATADIR, 'ri_pv', 'scalar_outputs', f_rev1_out) sam_files = [ TESTDATADIR + '/SAM/naris_pv_1axis_inv13.json', TESTDATADIR + '/SAM/naris_pv_1axis_inv13.json' ] sam_files = {'sam_param_{}'.format(i): k for i, k in enumerate(sam_files)} pp = ProjectPoints(rev2_points, sam_files, 'pvwattsv5') gen = Gen.reV_run(tech='pvwattsv5', points=rev2_points, sam_files=sam_files, res_file=res_file, fout=None) gen_outs = list(gen.out['cf_mean']) # initialize the rev1 output hander with pv_results(rev1_outs) as pv: # get reV 1.0 results cf_mean_list = pv.get_cf_mean(pp.sites, '2012') # benchmark the results result = np.allclose(gen_outs, cf_mean_list, rtol=RTOL, atol=ATOL) assert result is True
def test_gen_tph(): """Test generation for trough physical heat""" points = slice(0, 1) sam_files = TESTDATADIR + '/SAM/trough_default.json' res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(2012) # T_field_cold_in # sequence: Field timestep-averaged inlet temperature [C] # m_dot_field_delivered # sequence: Field total mass flow delivered [kg/s] # q_dot_htf_sf_out # sequence: Field thermal power leaving in HTF [MWt] output_request = ('T_field_cold_in', 'T_field_hot_out', 'm_dot_field_delivered', 'm_dot_field_recirc', 'q_dot_htf_sf_out', 'q_dot_to_heat_sink', 'q_dot_rec_inc', 'qinc_costh', 'dni_costh', 'beam', 'cf_mean', 'annual_gross_energy', 'annual_thermal_consumption', 'annual_energy') # run reV 2.0 generation gen = Gen.reV_run(tech='troughphysicalheat', points=points, sam_files=sam_files, res_file=res_file, max_workers=1, output_request=output_request, sites_per_worker=1, fout=None, scale_outputs=True) def my_assert(x, y, digits): if isinstance(x, np.ndarray): x = float(x.sum()) assert round(x, digits) == round(y, digits) # Some results may be different with PySAM 2 vs 1.2.1 my_assert(gen.out['annual_thermal_consumption'], 16361.0, 0) my_assert(gen.out['annual_gross_energy'], 14400000., -6)
def test_gen_downscaling(): """Test reV 2.0 generation with resource downscaled to 5 minutes.""" # get full file paths. baseline = os.path.join(TESTDATADIR, 'gen_out', 'gen_profiles_5min_2017.h5') sam_files = os.path.join(TESTDATADIR, 'SAM', 'naris_pv_1axis_inv13.json') res_file = os.path.join(TESTDATADIR, 'nsrdb', 'nsrdb_surfrad_2017.h5') # run reV 2.0 generation gen = Gen.reV_run(tech='pvwattsv5', points=slice(0, None), sam_files=sam_files, res_file=res_file, output_request=('cf_mean', 'cf_profile'), downscale='5min', max_workers=1, sites_per_worker=100, fout=None) gen_outs = gen.out['cf_profile'].astype(np.int32) if not os.path.exists(baseline): with h5py.File(baseline, 'w') as f: f.create_dataset('cf_profile', data=gen_outs, dtype=gen_outs.dtype) else: with h5py.File(baseline, 'r') as f: baseline = f['cf_profile'][...].astype(np.int32) x = mae_perc(gen_outs, baseline) msg = 'Mean absolute error is {}% from the baseline data'.format(x) assert x < 1, msg
def test_wind_gen_new_outputs(points=slice(0, 10), year=2012, max_workers=1): """Test reV 2.0 generation for wind with new outputs.""" # get full file paths. sam_files = TESTDATADIR + '/SAM/wind_gen_standard_losses_0.json' res_file = TESTDATADIR + '/wtk/ri_100_wtk_{}.h5'.format(year) output_request = ('cf_mean', 'cf_profile', 'monthly_energy') # run reV 2.0 generation gen = Gen.reV_run('windpower', points, sam_files, res_file, max_workers=max_workers, sites_per_worker=3, fout=None, output_request=output_request) assert gen.out['cf_mean'].shape == (10, ) assert gen.out['cf_profile'].shape == (8760, 10) assert gen.out['monthly_energy'].shape == (12, 10) assert gen._out['cf_mean'].dtype == np.uint16 assert gen._out['cf_profile'].dtype == np.uint16 assert gen._out['monthly_energy'].dtype == np.float32
def test_pv_gen_slice(f_rev1_out, rev2_points, year, max_workers): """Test reV 2.0 generation for PV and benchmark against reV 1.0 results.""" # get full file paths. rev1_outs = os.path.join(TESTDATADIR, 'ri_pv', 'scalar_outputs', f_rev1_out) sam_files = TESTDATADIR + '/SAM/naris_pv_1axis_inv13.json' res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(year) # run reV 2.0 generation pp = ProjectPoints(rev2_points, sam_files, 'pvwattsv5', res_file=res_file) gen = Gen.reV_run(tech='pvwattsv5', points=rev2_points, sam_files=sam_files, res_file=res_file, max_workers=max_workers, sites_per_worker=3, fout=None) gen_outs = list(gen.out['cf_mean']) # initialize the rev1 output hander with pv_results(rev1_outs) as pv: # get reV 1.0 results cf_mean_list = pv.get_cf_mean(pp.sites, year) # benchmark the results result = np.allclose(gen_outs, cf_mean_list, rtol=RTOL, atol=ATOL) assert result is True
def test_gen_linear(): """Test generation for linear Fresnel""" points = slice(0, 1) sam_files = TESTDATADIR + '/SAM/linear_default.json' res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(2012) # q_dot_to_heat_sink # sequence: Heat sink thermal power [MWt] # gen # sequence: System power generated [kW] # m_dot_field # sequence: Field total mass flow rate [kg/s] # q_dot_sf_out # sequence: Field thermal power leaving in steam [MWt] # W_dot_heat_sink_pump # sequence: Heat sink pumping power [MWe] # m_dot_loop # sequence: Receiver mass flow rate [kg/s] output_request = ('q_dot_to_heat_sink', 'gen', 'm_dot_field', 'q_dot_sf_out', 'W_dot_heat_sink_pump', 'm_dot_loop', 'q_dot_rec_inc', 'cf_mean', 'gen_profile', 'annual_field_energy', 'annual_thermal_consumption',) # run reV 2.0 generation gen = Gen.reV_run(tech='lineardirectsteam', points=points, sam_files=sam_files, res_file=res_file, max_workers=1, output_request=output_request, sites_per_worker=1, fout=None, scale_outputs=True) def my_assert(test, *truth, digits=0): if isinstance(test, np.ndarray): test = float(test.sum()) check = any(round(test, digits) == round(true, digits) for true in truth) assert check # Some results may be different with PySAM 2 vs 1.2.1 my_assert(gen.out['q_dot_to_heat_sink'], 10874.82934, digits=0) my_assert(gen.out['gen'], 10439836.56, digits=-2) my_assert(gen.out['m_dot_field'], 15146.1688, digits=1) my_assert(gen.out['q_dot_sf_out'], 10946.40988, digits=0) my_assert(gen.out['W_dot_heat_sink_pump'], 0.173017451, digits=6) my_assert(gen.out['annual_field_energy'], 5219916.0, 5219921.5, digits=0) my_assert(gen.out['annual_thermal_consumption'], 3178, digits=0) # Verify series are in correct order and have been rolled correctly if os.path.exists(BASELINE): with open(BASELINE, 'r') as f: profiles = json.load(f) for k in profiles.keys(): assert np.allclose(profiles[k], gen.out[k], rtol=RTOL, atol=ATOL) else: with open(BASELINE, 'w') as f: out = {k: v.tolist() for k, v in gen.out.items()} json.dump(out, f)
def test_pv_name_error(): """Test reV 2.0 generation for PV and benchmark against reV 1.0 results.""" year = 2012 rev2_points = slice(0, 3) sam_files = TESTDATADIR + '/SAM/naris_pv_1axis_inv13.json' res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(year) # run reV 2.0 generation with pytest.raises(KeyError) as record: pp = ProjectPoints(rev2_points, sam_files, 'pv', res_file=res_file) Gen.reV_run(tech='pv', points=rev2_points, sam_files=sam_files, res_file=res_file, max_workers=1, sites_per_worker=1, fout=None) assert 'Did not recognize' in record[0].message
def test_curtailment_res_mean(year): """Run Wind generation and ensure that the cf_profile is zero when curtailment is expected. Note that the probability of curtailment must be 1 for this to succeed. """ res_file = os.path.join(TESTDATADIR, 'wtk/ri_100_wtk_{}.h5'.format(year)) sam_files = os.path.join(TESTDATADIR, 'SAM/wind_gen_standard_losses_0.json') curtailment = os.path.join(TESTDATADIR, 'config/', 'curtailment.json') points = slice(0, 100) output_request = ('cf_mean', 'ws_mean') pc = Gen.get_pc(points, None, sam_files, 'windpower', sites_per_worker=50, res_file=res_file, curtailment=curtailment) resources = RevPySam.get_sam_res(res_file, pc.project_points, pc.project_points.tech, output_request) truth = resources['mean_windspeed'] # run reV 2.0 generation gen = Gen.reV_run('windpower', points, sam_files, res_file, fout=None, output_request=output_request, curtailment=curtailment, max_workers=1, sites_per_worker=50, scale_outputs=True) test = gen.out['ws_mean'] assert np.allclose(truth, test, rtol=0.001)
def test_random(year, site): """Run wind generation and ensure that no curtailment, 100% probability curtailment, and 50% probability curtailment result in expected decreases in the annual cf_mean. """ res_file = os.path.join(TESTDATADIR, 'wtk/ri_100_wtk_{}.h5'.format(year)) sam_files = os.path.join(TESTDATADIR, 'SAM/wind_gen_standard_losses_0.json') results = [] no_curtail = None curtailment = { "dawn_dusk": "nautical", "months": [4, 5, 6, 7], "precipitation": None, "probability": 1, "temperature": None, "wind_speed": 10.0 } prob_curtail = { "dawn_dusk": "nautical", "months": [4, 5, 6, 7], "precipitation": None, "probability": 0.5, "temperature": None, "wind_speed": 10.0 } for c in [no_curtail, curtailment, prob_curtail]: points = slice(site, site + 1) # run reV 2.0 generation and write to disk gen = Gen.reV_run('windpower', points, sam_files, res_file, fout=None, output_request=('cf_profile', ), curtailment=c, max_workers=1, sites_per_worker=50, scale_outputs=True) results.append(gen.out['cf_mean']) assert results[0] > results[1], 'Curtailment did not decrease cf_mean!' expected = (results[0] + results[1]) / 2 diff = expected - results[2] msg = ('Curtailment with 50% probability did not result in 50% less ' 'curtailment! No curtailment, curtailment, and 50% curtailment ' 'have the following cf_means: {}'.format(results)) assert diff <= 2, msg
def test_smart(year): """Gen PV CF profiles with write to disk and compare against rev1.""" res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(year) sam_files = TESTDATADIR + '/SAM/naris_pv_1axis_inv13.json' rev2_out_dir = os.path.join(TESTDATADIR, 'ri_pv_reV2') rev2_out = 'gen_ri_pv_smart_{}.h5'.format(year) points = slice(0, 10) # run reV 2.0 generation and write to disk Gen.reV_run(tech='pvwattsv5', points=points, sam_files=sam_files, res_file=res_file, fout=rev2_out, max_workers=2, sites_per_worker=50, dirout=rev2_out_dir, output_request=('cf_profile', )) # get reV 2.0 generation profiles from disk flist = os.listdir(rev2_out_dir) for fname in flist: if rev2_out.strip('.h5') in fname: with Outputs(os.path.join(rev2_out_dir, fname), 'r') as cf: rev2_profiles = cf['cf_profile'] break # get reV 1.0 generation profiles rev1_profiles = get_r1_profiles(year=year) rev1_profiles = rev1_profiles[:, points] result = np.allclose(rev1_profiles, rev2_profiles, rtol=RTOL, atol=ATOL) if result and PURGE_OUT: # remove output files if test passes. flist = os.listdir(rev2_out_dir) for fname in flist: os.remove(os.path.join(rev2_out_dir, fname)) assert result is True
def test_wind_generic_losses(loss): """Test varying wind turbine losses""" pc = Gen.get_pc(REV2_POINTS, None, SAM_FILE, 'windpower', sites_per_worker=3, res_file=RES_FILE) del pc.project_points.sam_configs[SAM_FILE]['wind_farm_losses_percent'] pc.project_points.sam_configs[SAM_FILE]['turb_generic_loss'] = loss gen = Gen.reV_run('windpower', pc, SAM_FILE, RES_FILE, max_workers=1, sites_per_worker=3, fout=None) gen_outs = list(gen.out['cf_mean']) assert np.allclose(gen_outs, LOSS_BASELINE[loss], rtol=RTOL, atol=ATOL)
def get_pc(points, points_range, sam_files, cf_file, sites_per_worker=None, append=False): """ Get a PointsControl instance. Parameters ---------- points : slice | list | str | reV.config.project_points.PointsControl Slice specifying project points, or string pointing to a project points csv, or a fully instantiated PointsControl object. points_range : list | None Optional two-entry list specifying the index range of the sites to analyze. To be taken from the reV.config.PointsControl.split_range property. sam_files : dict | str | list | SAMConfig SAM input configuration ID(s) and file path(s). Keys are the SAM config ID(s), top level value is the SAM path. Can also be a single config file str. If it's a list, it is mapped to the sorted list of unique configs requested by points csv. Can also be a pre loaded SAMConfig object. cf_file : str reV generation capacity factor output file with path. sites_per_worker : int Number of sites to run in series on a worker. None defaults to the resource file chunk size. append : bool Flag to append econ datasets to source cf_file. This has priority over the fout and dirout inputs. Returns ------- pc : reV.config.project_points.PointsControl PointsControl object instance. """ pc = Gen.get_pc(points, points_range, sam_files, 'econ', sites_per_worker=sites_per_worker, res_file=cf_file) if append: pc = Econ._econ_append_pc(pc.project_points, cf_file, sites_per_worker=sites_per_worker) return pc
def test_multi_file_nsrdb_2018(): """Test running reV gen from a multi-h5 directory with prefix and suffix""" points = slice(0, 10) max_workers = 1 sam_files = TESTDATADIR + '/SAM/naris_pv_1axis_inv13.json' res_file = TESTDATADIR + '/nsrdb/nsrdb_*{}.h5'.format(2018) # run reV 2.0 generation gen = Gen.reV_run(tech='pvwattsv5', points=points, sam_files=sam_files, res_file=res_file, max_workers=max_workers, sites_per_worker=3, fout=None) gen_outs = list(gen.out['cf_mean']) assert len(gen_outs) == 10 assert np.mean(gen_outs) > 0.14
def test_multi_file_5min_wtk(): """Test running reV gen from a multi-h5 directory with prefix and suffix""" points = slice(0, 10) max_workers = 1 sam_files = TESTDATADIR + '/SAM/wind_gen_standard_losses_0.json' res_file = TESTDATADIR + '/wtk/wtk_{}_*m.h5'.format(2010) # run reV 2.0 generation gen = Gen.reV_run(tech='windpower', points=points, sam_files=sam_files, res_file=res_file, max_workers=max_workers, sites_per_worker=3, fout=None) gen_outs = list(gen._out['cf_mean']) assert len(gen_outs) == 10 assert np.mean(gen_outs) > 0.55
def test_gen_csp(): """Test generation for CSP""" points = slice(0, 1) sam_files = TESTDATADIR + '/SAM/i_csp_tcsmolten_salt.json' res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(2012) # run reV 2.0 generation gen = Gen.reV_run(tech='tcsmoltensalt', points=points, sam_files=sam_files, res_file=res_file, max_workers=1, output_request=('cf_mean', 'cf_profile', 'gen_profile'), sites_per_worker=1, fout=None, scale_outputs=False) cf_mean = gen.out['cf_mean'] cf_profile = gen.out['cf_profile'] gen_profile = gen.out['gen_profile'] assert np.isclose(cf_mean, 0.2679, atol=0.001) assert np.isclose(cf_profile.max(), 0.001) assert gen_profile.max() > 1e5
def test_gen_input_mods(): """Test that the gen workers do not modify the top level input SAM config """ year = 2012 rev2_points = slice(0, 5) res_file = TESTDATADIR + '/nsrdb/ri_100_nsrdb_{}.h5'.format(year) sam_files = TESTDATADIR + '/SAM/i_pvwatts_fixed_lat_tilt.json' # run reV 2.0 generation pp = ProjectPoints(rev2_points, sam_files, 'pvwattsv7', res_file=res_file) gen = Gen.reV_run(tech='pvwattsv7', points=rev2_points, sam_files=sam_files, res_file=res_file, max_workers=1, sites_per_worker=1, fout=None) for i in range(5): inputs = gen.project_points[i][1] assert inputs['tilt'] == 'latitude'
def test_cf_curtailment(year, site): """Run Wind generation and ensure that the cf_profile is zero when curtailment is expected. Note that the probability of curtailment must be 1 for this to succeed. """ res_file = os.path.join(TESTDATADIR, 'wtk/ri_100_wtk_{}.h5'.format(year)) sam_files = os.path.join(TESTDATADIR, 'SAM/wind_gen_standard_losses_0.json') curtailment = os.path.join(TESTDATADIR, 'config/', 'curtailment.json') points = slice(site, site + 1) # run reV 2.0 generation gen = Gen.reV_run('windpower', points, sam_files, res_file, fout=None, output_request=('cf_profile', ), curtailment=curtailment, max_workers=1, sites_per_worker=50, scale_outputs=True) results, check_curtailment = test_res_curtailment(year, site=site) results['cf_profile'] = gen.out['cf_profile'].flatten() # was capacity factor NOT curtailed? check_cf = (gen.out['cf_profile'].flatten() != 0) # Were all thresholds met and windspeed NOT curtailed? check = check_curtailment & check_cf msg = ('All curtailment thresholds were met and cf_profile ' 'was not curtailed!') assert np.sum(check) == 0, msg return results
def test_sam_config_kw_replace(): """Test that the SAM config with old keys from pysam v1 gets updated on the fly and gets propogated to downstream splits.""" fpp = os.path.join(TESTDATADIR, 'project_points/pp_offshore.csv') sam_files = {'onshore': os.path.join( TESTDATADIR, 'SAM/wind_gen_standard_losses_0.json'), 'offshore': os.path.join( TESTDATADIR, 'SAM/wind_gen_standard_losses_1.json')} res_file = os.path.join(TESTDATADIR, 'wtk/ri_100_wtk_2012.h5') pp = ProjectPoints(fpp, sam_files, 'windpower') pc = PointsControl(pp, sites_per_split=100) gen = Gen(pc, res_file) config_on = gen.project_points.sam_configs['onshore'] config_of = gen.project_points.sam_configs['offshore'] assert 'turb_generic_loss' in config_on assert 'turb_generic_loss' in config_of pp_split = ProjectPoints.split(0, 10000, gen.project_points) config_on = pp_split.sam_configs['onshore'] config_of = pp_split.sam_configs['offshore'] assert 'turb_generic_loss' in config_on assert 'turb_generic_loss' in config_of pc_split = PointsControl.split(0, 10000, gen.project_points) config_on = pc_split.project_points.sam_configs['onshore'] config_of = pc_split.project_points.sam_configs['offshore'] assert 'turb_generic_loss' in config_on assert 'turb_generic_loss' in config_of for ipc in pc_split: if 'onshore' in ipc.project_points.sam_configs: config = ipc.project_points.sam_configs['onshore'] assert 'turb_generic_loss' in config if 'offshore' in ipc.project_points.sam_configs: config = ipc.project_points.sam_configs['offshore'] assert 'turb_generic_loss' in config
def test_windspeed_pass_through( rev2_points=slice(0, 10), year=2012, max_workers=1): """Test a windspeed output request so that resource array is passed through to output dict.""" sam_files = TESTDATADIR + '/SAM/wind_gen_standard_losses_0.json' res_file = TESTDATADIR + '/wtk/ri_100_wtk_{}.h5'.format(year) output_requests = ('cf_mean', 'windspeed') # run reV 2.0 generation gen = Gen.reV_run('windpower', rev2_points, sam_files, res_file, max_workers=max_workers, sites_per_worker=3, fout=None, output_request=output_requests) assert 'windspeed' in gen.out assert gen.out['windspeed'].shape == (8760, 10) assert gen._out['windspeed'].max() == 2597 assert gen._out['windspeed'].min() == 1