def test_pvengine_float_inputs_perez_transparency_spacing_fast(params): """Test that module transparency and spacing are having the expected effect to calculated PV back side irradiance""" # Irradiance inputs timestamps = dt.datetime(2019, 6, 11, 11) DNI = 1000. DHI = 100. # --- with 0 transparency and spacing # Create models irr_params = {'module_transparency': 0., 'module_spacing_ratio': 0.} irradiance_model = HybridPerezOrdered(**irr_params) pvarray = OrderedPVArray.init_from_dict(params) eng = PVEngine(pvarray, irradiance_model=irradiance_model) # Fit engine eng.fit(timestamps, DNI, DHI, params['solar_zenith'], params['solar_azimuth'], params['surface_tilt'], params['surface_azimuth'], params['rho_ground']) # Run timestep def fn_report(pvarray): return (pvarray.ts_pvrows[1] .back.get_param_weighted('qinc')) no_spacing_transparency_back_qinc = \ eng.run_fast_mode(fn_build_report=fn_report, pvrow_index=1) # --- with non-0 transparency and spacing # Create models irr_params = {'module_transparency': 0.1, 'module_spacing_ratio': 0.1} irradiance_model = HybridPerezOrdered(**irr_params) pvarray = OrderedPVArray.init_from_dict(params) eng = PVEngine(pvarray, irradiance_model=irradiance_model) # Fit engine eng.fit(timestamps, DNI, DHI, params['solar_zenith'], params['solar_azimuth'], params['surface_tilt'], params['surface_azimuth'], params['rho_ground']) # Run timestep w_spacing_transparency_back_qinc = \ eng.run_fast_mode(fn_build_report=fn_report, pvrow_index=1) # Checks expected_back_qinc = 134.7143531 # higher than when params are 0 np.testing.assert_almost_equal( w_spacing_transparency_back_qinc, expected_back_qinc) assert no_spacing_transparency_back_qinc < w_spacing_transparency_back_qinc
def test_run_fast_mode_back_shading(params): """Test that PV engine works for timeseries fast mode and float inputs, and when there's large direct shading on the back surface. Value is very close to loop-style fast mode""" params.update({ 'gcr': 0.6, 'surface_azimuth': 270, 'surface_tilt': 120, 'solar_zenith': 70. }) # Prepare some engine inputs irradiance_model = HybridPerezOrdered() pvarray = OrderedPVArray.init_from_dict( params, param_names=irradiance_model.params) fast_mode_pvrow_index = 1 fast_mode_segment_index = 0 # Create engine object eng = PVEngine(pvarray, irradiance_model=irradiance_model, fast_mode_pvrow_index=fast_mode_pvrow_index, fast_mode_segment_index=fast_mode_segment_index) # Irradiance inputs timestamps = dt.datetime(2019, 6, 11, 11) DNI = 1000. DHI = 100. # Expected values expected_qinc = 683.537153 # Fit engine eng.fit(timestamps, DNI, DHI, params['solar_zenith'], params['solar_azimuth'], params['surface_tilt'], params['surface_azimuth'], params['rho_ground']) def fn_report(pvarray): return (pvarray.ts_pvrows[1].back.get_param_weighted('qinc')) # By providing segment index qinc = eng.run_fast_mode(fn_build_report=fn_report) # Check results np.testing.assert_allclose(qinc, expected_qinc) # Without providing segment index eng.fast_mode_segment_index = None qinc = eng.run_fast_mode(fn_build_report=fn_report) # Check results np.testing.assert_allclose(qinc, expected_qinc)
def test_run_fast_mode_segments(params): """Test that PV engine works for timeseries fast mode and float inputs. Value is very close to loop-like fast mode""" # Discretize middle PV row's back side params.update({'cut': {1: {'back': 5}}}) # Prepare some engine inputs irradiance_model = HybridPerezOrdered() pvarray = OrderedPVArray.init_from_dict( params, param_names=irradiance_model.params) fast_mode_pvrow_index = 1 fast_mode_segment_index = 2 # Create engine object eng = PVEngine(pvarray, irradiance_model=irradiance_model, fast_mode_pvrow_index=fast_mode_pvrow_index, fast_mode_segment_index=fast_mode_segment_index) # Irradiance inputs timestamps = dt.datetime(2019, 6, 11, 11) DNI = 1000. DHI = 100. # Fit engine eng.fit(timestamps, DNI, DHI, params['solar_zenith'], params['solar_azimuth'], params['surface_tilt'], params['surface_azimuth'], params['rho_ground']) # Checks np.testing.assert_almost_equal(eng.irradiance.direct['front_illum_pvrow'], DNI) # Define report function to grab irradiance from PV row segment def fn_report(pvarray): return (pvarray.ts_pvrows[1].back.list_segments[2].get_param_weighted( 'qinc')) # Expected value for middle segment qinc_expected = 116.572594 # Run fast mode for specific segment qinc_segment = eng.run_fast_mode(fn_build_report=fn_report) # Check results np.testing.assert_allclose(qinc_segment, qinc_expected) # Without providing segment index: the value should be the same as above eng.fast_mode_segment_index = None qinc_segment = eng.run_fast_mode(fn_build_report=fn_report) # Check results np.testing.assert_allclose(qinc_segment, qinc_expected)
def test_run_fast_and_full_modes_sequentially(params, fn_report_example): """Make sure that can run fast and full modes one after the other without making the engine crash""" # Irradiance inputs timestamps = dt.datetime(2019, 6, 11, 11) DNI = 1000. DHI = 100. # Prepare some engine inputs pvarray = OrderedPVArray.init_from_dict(params) fast_mode_pvrow_index = 1 fast_mode_segment_index = 0 # Create engine object eng = PVEngine(pvarray, fast_mode_pvrow_index=fast_mode_pvrow_index, fast_mode_segment_index=fast_mode_segment_index) # Fit engine eng.fit(timestamps, DNI, DHI, params['solar_zenith'], params['solar_azimuth'], params['surface_tilt'], params['surface_azimuth'], params['rho_ground']) # Run fast mode def fn_report(pvarray): return (pvarray.ts_pvrows[1].back.get_param_weighted('qinc')) qinc_fast = eng.run_fast_mode(fn_build_report=fn_report) # Run full mode report = eng.run_full_mode(fn_build_report=fn_report_example) np.testing.assert_allclose(qinc_fast, 119.095285) np.testing.assert_allclose(report['qinc_back'], 116.49050349491)
def test_fast_mode_8760(params, df_inputs_clearsky_8760): """Test fast mode with 1 PV row to make sure that is consistent after the vectorization update: should get exact same values """ # Get MET data df_inputs = df_inputs_clearsky_8760 timestamps = df_inputs.index dni = df_inputs.dni.values dhi = df_inputs.dhi.values solar_zenith = df_inputs.solar_zenith.values solar_azimuth = df_inputs.solar_azimuth.values surface_tilt = df_inputs.surface_tilt.values surface_azimuth = df_inputs.surface_azimuth.values # Run simulation for only 1 PV row params.update({'n_pvrows': 1}) # Run engine pvarray = OrderedPVArray.init_from_dict(params) eng = PVEngine(pvarray) eng.fit(timestamps, dni, dhi, solar_zenith, solar_azimuth, surface_tilt, surface_azimuth, params['rho_ground']) qinc = eng.run_fast_mode( fn_build_report=lambda pvarray: (pvarray.ts_pvrows[0].back.get_param_weighted('qinc')), pvrow_index=0) # Check than annual energy on back is consistent np.testing.assert_allclose(np.nansum(qinc) / 1e3, 342.848005)
def test_run_fast_mode_isotropic(params): """Test that PV engine works for timeseries fast mode and float inputs, and using the isotropic irradiance model""" # Prepare some engine inputs irradiance_model = IsotropicOrdered() pvarray = OrderedPVArray.init_from_dict( params, param_names=irradiance_model.params) fast_mode_pvrow_index = 1 fast_mode_segment_index = 0 # Create engine object eng = PVEngine(pvarray, irradiance_model=irradiance_model, fast_mode_pvrow_index=fast_mode_pvrow_index, fast_mode_segment_index=fast_mode_segment_index) # Irradiance inputs timestamps = dt.datetime(2019, 6, 11, 11) DNI = 1000. DHI = 100. # Fit engine eng.fit(timestamps, DNI, DHI, params['solar_zenith'], params['solar_azimuth'], params['surface_tilt'], params['surface_azimuth'], params['rho_ground']) # Checks np.testing.assert_almost_equal(eng.irradiance.direct['front_illum_pvrow'], DNI) # Expected value qinc_expected = 122.73453 # Run fast mode qinc = eng.run_fast_mode( fn_build_report=lambda pvarray: (pvarray.ts_pvrows[1] .back.get_param_weighted('qinc'))) # Check results np.testing.assert_allclose(qinc, qinc_expected) # Without providing segment index eng.fast_mode_segment_index = None qinc = eng.run_fast_mode( fn_build_report=lambda pvarray: (pvarray.ts_pvrows[1] .back.get_param_weighted('qinc'))) # Check results np.testing.assert_allclose(qinc, qinc_expected)
def test_run_fast_mode_compare_to_loop_like(params): """Test that PV engine works for timeseries fast mode and float inputs. Check the left pv row back side (no obstruction, since rotation < 0) This should be exactly the same calculated value as in loop-like fast mode because ground is not infinite for back of left pv row""" # Prepare some engine inputs irradiance_model = HybridPerezOrdered() pvarray = OrderedPVArray.init_from_dict( params, param_names=irradiance_model.params) fast_mode_pvrow_index = 1 # Irradiance inputs timestamps = dt.datetime(2019, 6, 11, 11) DNI = 1000. DHI = 100. # Create engine object eng = PVEngine(pvarray, irradiance_model=irradiance_model, fast_mode_pvrow_index=fast_mode_pvrow_index) # Fit engine eng.fit(timestamps, DNI, DHI, params['solar_zenith'], params['solar_azimuth'], params['surface_tilt'], params['surface_azimuth'], params['rho_ground']) # Run baseline calculation pvrow_idx = 0 time_idx = 0 pvarray_loop = _fast_mode_with_loop(eng.pvarray, eng.irradiance, eng.vf_calculator, pvrow_idx, time_idx) # Expected should be: 138.10421248631152 qinc_expected = pvarray_loop.pvrows[0].back.get_param_weighted('qinc') # Run timeseries calculation qinc = eng.run_fast_mode( fn_build_report=lambda pvarray: (pvarray.ts_pvrows[0].back.get_param_weighted('qinc')), pvrow_index=0) # Check results: value taken from loop-like fast mode np.testing.assert_allclose(qinc, qinc_expected)
def pvfactors_engine_run(data, pvarray_parameters, parallel=0, mode='full'): """My wrapper function to launch the pvfactors engine in parallel. It is mostly for Windows use. In Linux you can directly call run_parallel_engine. It uses MyReportBuilder to generate the output. Args: data (pandas DataFrame): The data to fit the model. pvarray_parameters (dict): The pvfactors dict describing the simulation. parallel (int, optional): Number of threads to launch. Defaults to 0 (just calls PVEngine.run_all_timesteps) mode (str): full or fast depending on the type of back irraadiances. See pvfactors doc. Returns: pandas DataFrame: The results of the simulation, as desired in MyReportBuilder. """ n, row = _get_cut(pvarray_parameters['cut']) rb = Report(n, row) if parallel > 1: report = run_parallel_engine(rb, pvarray_parameters, data.index, data.dni, data.dhi, data.zenith, data.azimuth, data.surface_tilt, data.surface_azimuth, data.albedo, n_processes=parallel) else: pvarray = OrderedPVArray.init_from_dict(pvarray_parameters) engine = PVEngine(pvarray) engine.fit(data.index, data.dni, data.dhi, data.zenith, data.azimuth, data.surface_tilt, data.surface_azimuth, data.albedo, data.ghi) if mode == 'full': report = engine.run_full_mode(rb.build) else: report = engine.run_fast_mode(rb.build, pvrow_index=0, segment_index=0) df_report = pd.DataFrame(report, index=data.index).fillna(0) return df_report