def test_luminance_in_timeseries_calc(df_perez_luminance, mock_array_timeseries_calculate): """ Test that the calculation of luminance -- first step in using the vf model with Perez -- is functional """ df_inputs_clearday = pd.read_csv(FILE_PATH) df_inputs_clearday = df_inputs_clearday.set_index('datetime', drop=True) df_inputs_clearday.index = (pd.DatetimeIndex( df_inputs_clearday.index).tz_localize('UTC').tz_convert( 'Etc/GMT+7').tz_localize(None)) # Break up inputs (timestamps, surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs_clearday) _, df_outputs = calculate_radiosities_serially_perez( (None, timestamps, solar_zenith, solar_azimuth, surface_tilt, surface_azimuth, dni, dhi)) col_order = df_outputs.columns tol = 1e-8 np.testing.assert_allclose(df_outputs.values, df_perez_luminance[col_order].values, atol=0, rtol=tol)
def test_serial_calculation(pvarray_parameters_serial_calc, df_inputs_serial_calculation): """ Make sure that the calculations using the Perez model stay consistent for all the modeled surfaces. Also testing that there is no unexpected NaN. """ # Break up inputs (timestamps, surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs_serial_calculation) # Run calculation in 1 process only df_registries, _ = calculate_radiosities_serially_perez( (pvarray_parameters_serial_calc, timestamps, solar_zenith, solar_azimuth, surface_tilt, surface_azimuth, dni, dhi)) # Format df_registries to get outputs df_outputs = get_average_pvrow_outputs(df_registries, include_shading=False) # Did the outputs remain consistent? test_results = values_are_consistent(df_outputs) for result in test_results: assert result['passed'], ("test failed for %s" % result['irradiance_term'])
def test_calculate_radiosities_parallel_perez(): """ Check that the parallel calculation using Perez diffuse model is able to run. The consistency is not tested here, because it is already tested for the serial calculation (which it relies on) """ # Inputs to the calculations filename = "file_test_multiprocessing_inputs.csv" subset_idx = 100 arguments = { 'n_pvrows': 2, 'pvrow_height': 3., 'pvrow_width': 1., 'array_azimuth': 270., 'array_tilt': -20., 'gcr': 0.3, 'solar_zenith': 20., 'solar_azimuth': 90., 'rho_ground': 0.2, 'rho_front_pvrow': 0.01, 'rho_back_pvrow': 0.03 } # Import inputs df_inputs_simulation = pd.read_csv(os.path.join(TEST_DATA, filename), index_col=0) df_inputs_simulation.index = pd.DatetimeIndex(df_inputs_simulation.index) # Reduce number of inputs df_inputs_simulation = df_inputs_simulation.iloc[:subset_idx, :] # Select number of processes n_processes = None # Break up inputs (timestamps, array_tilt, array_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs_simulation) # Run calculation results = calculate_radiosities_parallel_perez(arguments, timestamps, array_tilt, array_azimuth, solar_zenith, solar_azimuth, dni, dhi, n_processes=n_processes)
def test_back_surface_luminance(): """ The model didn't calculate cases when the sun would hit the back surface because the perez model would return 0 circumsolar (not calculated for back surface). Fix was implemented, and this should check for it. """ pvarray_parameters = { 'surface_azimuth': 90, 'surface_tilt': 0.0, 'gcr': 0.3, 'n_pvrows': 3, 'Pvrow_height': 1.5, 'pvrow_width': 1.0, 'rho_back_pvrow': 0.03, 'rho_front_pvrow': 0.01, 'rho_ground': 0.2, 'solar_azimuth': 90.0, 'solar_zenith': 20.0 } input_filename = 'file_test_back_surface_luminance.csv' df_inputs = pd.read_csv(os.path.join(TEST_DATA, input_filename), index_col=0) df_inputs.index = pd.DatetimeIndex(df_inputs.index).tz_localize( 'UTC').tz_convert('US/Arizona') # Break up inputs (timestamps, tracker_theta, surface_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs) args = (pvarray_parameters, timestamps, solar_zenith, solar_azimuth, tracker_theta, surface_azimuth, dni, dhi) df_registries, _ = calculate_radiosities_serially_perez(args) df_outputs = get_average_pvrow_outputs(df_registries) vf_ipoa_front = df_outputs.loc[:, IDX_SLICE[1, 'front', 'qinc']] vf_ipoa_back = df_outputs.loc[:, IDX_SLICE[1, 'back', 'qinc']] assert isinstance(vf_ipoa_front[0], float) assert isinstance(vf_ipoa_back[0], float)
def test_serial_circumsolar_shading_calculation(): """ Calculate and save results from front surface circumsolar shading on pvrows. Test that it functions with the given data. """ # Choose a PV array configuration and pass the arguments necessary for # the calculation to be triggered: # eg 'calculate_front_circ_horizon_shading' arguments = { 'array_azimuth': 90.0, 'array_tilt': 20.0, 'cut': [(1, 5, 'front')], 'gcr': 0.3, 'n_pvrows': 2, 'pvrow_height': 1.5, 'pvrow_width': 1., 'rho_ground': 0.2, 'rho_pvrow_back': 0.03, 'rho_pvrow_front': 0.01, 'solar_azimuth': 90.0, 'solar_zenith': 30.0, 'circumsolar_angle': 50., 'horizon_band_angle': 6.5, 'calculate_front_circ_horizon_shading': True, 'circumsolar_model': 'gaussian' } # Load inputs for the serial calculation test_file = os.path.join( TEST_DATA, 'file_test_serial_circumsolar_shading_calculation.csv') df_inputs = pd.read_csv(test_file, index_col=0) df_inputs.index = pd.DatetimeIndex(df_inputs.index) (timestamps, array_tilt, array_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs) # Run the calculation for functional testing df_registries, df_inputs_perez = ( calculate_radiosities_serially_perez((arguments, timestamps, array_tilt, array_azimuth, solar_zenith, solar_azimuth, dni, dhi)) )
def test_negativevf_and_flatcasenoon(): pvarray_parameters = { 'surface_azimuth': 90, 'tracker_theta': 0.0, 'gcr': 0.3, 'n_pvrows': 3, 'pvrow_height': 1.5, 'pvrow_width': 1.0, 'rho_back_pvrow': 0.03, 'rho_front_pvrow': 0.01, 'rho_ground': 0.2, 'solar_azimuth': 90.0, 'solar_zenith': 20.0 } input_filename = 'file_test_negativevf_and_flatcasenoon.csv' df_inputs = pd.read_csv(os.path.join(TEST_DATA, input_filename), index_col=0) df_inputs.index = pd.DatetimeIndex(df_inputs.index).tz_localize( 'UTC').tz_convert('US/Arizona') # Break up inputs (timestamps, tracker_theta, surface_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs) args = (pvarray_parameters, timestamps, solar_zenith, solar_azimuth, tracker_theta, surface_azimuth, dni, dhi) df_registries, _ = calculate_radiosities_serially_perez(args) df_outputs = get_average_pvrow_outputs(df_registries) vf_ipoa_front = df_outputs.loc[:, IDX_SLICE[1, 'front', 'qinc']] vf_ipoa_back = df_outputs.loc[:, IDX_SLICE[1, 'back', 'qinc']] # The model should calculate for all daytime points now since we fixed # the solar noon case (almost flat but not really), and we allowed # negative vf values early and late in the day expected_n_calculated_values = 13 assert np.sum(vf_ipoa_front.notnull()) == expected_n_calculated_values assert np.sum(vf_ipoa_back.notnull()) == expected_n_calculated_values
def test_perez_diffuse_luminance(df_perez_luminance): """ Test that the calculation of luminance -- first step in using the vf model with Perez -- is functional """ df_inputs = df_perez_luminance[[ 'surface_tilt', 'surface_azimuth', 'solar_zenith', 'solar_azimuth', 'dni', 'dhi' ]] (timestamps, surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs) df_outputs = perez_diffuse_luminance(timestamps, surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, dni, dhi) col_order = df_outputs.columns tol = 1e-8 np.testing.assert_allclose(df_outputs.values, df_perez_luminance[col_order].values, atol=0, rtol=tol)
def test_serial_calculation_with_skips( pvarray_parameters_serial_calc, df_inputs_serial_calculation_with_skips): """ Make sure that the calculations using the Perez model stay consistent for all the modeled surfaces. Also testing that there is no unexpected NaN. """ # Break up inputs (timestamps, surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs_serial_calculation_with_skips) # Run calculation in 1 process only df_registries, _ = calculate_radiosities_serially_perez( (pvarray_parameters_serial_calc, timestamps, solar_zenith, solar_azimuth, surface_tilt, surface_azimuth, dni, dhi)) list_nan_idx = df_registries.index[df_registries.set_index( 'timestamps').count(axis=1) == 0] # There should be one line with only nan values assert len(list_nan_idx) == 1
def test_perez_diffuse_luminance(df_perez_luminance): """ Test that the calculation of luminance -- first step in using the vf model with Perez -- is functional """ df_inputs_clearday = pd.read_csv(FILE_PATH) df_inputs_clearday = df_inputs_clearday.set_index('datetime', drop=True) df_inputs_clearday.index = (pd.DatetimeIndex( df_inputs_clearday.index).tz_localize('UTC').tz_convert( 'Etc/GMT+7').tz_localize(None)) # Break up inputs (timestamps, array_tilt, array_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs_clearday) df_outputs = perez_diffuse_luminance(timestamps, array_tilt, array_azimuth, solar_zenith, solar_azimuth, dni, dhi) col_order = df_outputs.columns tol = 1e-8 assert np.allclose(df_outputs.values, df_perez_luminance[col_order].values, atol=0, rtol=tol)
def test_array_calculate_timeseries(): """ Check that the timeseries results of the radiosity calculation using the isotropic diffuse sky approach stay consistent """ # Simple sky and array configuration df_inputs = pd.DataFrame( { 'solar_zenith': [80., 20., 70.4407256], 'solar_azimuth': [0., 180., 248.08690811], 'surface_tilt': [70., 40., 42.4337927], 'surface_azimuth': [180., 180., 270.], 'dni': [1e3, 1e3, 1000.], 'dhi': [1e2, 1e2, 100.] }, index=[0, 1, 2]) arguments = { 'n_pvrows': 3, 'pvrow_height': 1.5, 'pvrow_width': 1., 'gcr': 0.3, } # Break up inputs (timestamps, surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs) # Fill in the missing pieces luminance_isotropic = dhi luminance_circumsolar = np.zeros(len(timestamps)) poa_horizon = np.zeros(len(timestamps)) poa_circumsolar = np.zeros(len(timestamps)) # Run timeseries calculation df_registries = array_timeseries_calculate(arguments, timestamps, solar_zenith, solar_azimuth, surface_tilt, surface_azimuth, dni, luminance_isotropic, luminance_circumsolar, poa_horizon, poa_circumsolar) # Calculate surface averages for pvrows df_outputs = get_average_pvrow_outputs(df_registries, values=['q0', 'qinc'], include_shading=False) # Check that the outputs are as expected expected_outputs_array = np.array( [[31.60177482, 6.28906975, 3.58335581], [632.03549634, 125.78139505, 71.66711623], [2.27843869, 31.55401986, 28.05923971], [75.94795617, 1051.80066185, 935.30799022], [31.87339866, 6.3776871, 1.81431887], [637.46797317, 127.55374206, 36.28637745], [2.20476856, 31.21803306, 27.85790853], [73.49228524, 1040.60110204, 928.59695092], [46.7960208, 7.21518794, 2.16642175], [935.92041595, 144.30375888, 43.32843492], [2.29986192, 31.16722793, 27.77628919], [76.66206408, 1038.90759755, 925.87630648], [True, False, False]], dtype=object) tol = 1e-8 np.testing.assert_allclose(expected_outputs_array[:-1, :].astype(float), df_outputs.values.T, atol=tol, rtol=0, equal_nan=True)
def test_save_all_outputs_calculate_perez(): """ Make sure that the serial and parallel calculations are able to save all the requested data on discretized segments (instead of averaging them by default). Check the consistency of the results. """ # Load timeseries input data df_inputs_clearday = pd.read_csv(FILE_PATH) df_inputs_clearday = df_inputs_clearday.set_index('datetime', drop=True) df_inputs_clearday.index = (pd.DatetimeIndex( df_inputs_clearday.index).tz_localize('UTC').tz_convert( 'Etc/GMT+7').tz_localize(None)) idx_subset = 10 # PV array parameters for test arguments = { 'n_pvrows': 3, 'pvrow_height': 1.5, 'pvrow_width': 1., 'gcr': 0.4, 'rho_ground': 0.8, 'rho_back_pvrow': 0.03, 'rho_front_pvrow': 0.01, 'cut': [(1, 3, 'front')] } # Break up inputs (timestamps, surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs_clearday.iloc[:idx_subset]) args = (arguments, timestamps, solar_zenith, solar_azimuth, surface_tilt, surface_azimuth, dni, dhi) # Run the serial calculation df_registries_serial, _ = (calculate_radiosities_serially_perez(args)) df_registries_parallel, _ = (calculate_radiosities_parallel_perez(*args)) # Format the outputs df_outputs_segments_serial = get_pvrow_segment_outputs( df_registries_serial, values=['qinc'], include_shading=False) df_outputs_segments_parallel = get_pvrow_segment_outputs( df_registries_parallel, values=['qinc'], include_shading=False) # Load files with expected outputs expected_ipoa_dict_qinc = np.array( [[842.54617681, 842.5566707, 842.43690951], [839.30179691, 839.30652961, 839.30906023], [839.17118956, 839.17513098, 839.17725568], [842.24679271, 842.26194393, 842.15463231]]) # Perform the comparisons rtol = 1e-6 atol = 0 np.testing.assert_allclose(expected_ipoa_dict_qinc, df_outputs_segments_serial.values, atol=atol, rtol=rtol) np.testing.assert_allclose(expected_ipoa_dict_qinc, df_outputs_segments_parallel.values, atol=atol, rtol=rtol)
def test_save_all_outputs_calculate_perez(): """ Make sure that the serial and parallel calculations are able to save all the requested data on discretized segments (instead of averaging them by default). Check the consistency of the results. """ # Load timeseries input data df_inputs_clearday = pd.read_csv(FILE_PATH) df_inputs_clearday = df_inputs_clearday.set_index('datetime', drop=True) df_inputs_clearday.index = (pd.DatetimeIndex( df_inputs_clearday.index).tz_localize('UTC').tz_convert( 'Etc/GMT+7').tz_localize(None)) idx_subset = 10 # Adjustment in angles needed: need to keep azimuth constant and change # tilt angle only df_inputs_clearday.loc[(df_inputs_clearday.solar_azimuth <= 180.), 'array_azimuth'] = ( df_inputs_clearday.loc[:, 'array_azimuth'][-1]) df_inputs_clearday.loc[(df_inputs_clearday.solar_azimuth <= 180.), 'array_tilt'] *= (-1) # PV array parameters for test arguments = { 'n_pvrows': 3, 'pvrow_height': 1.5, 'pvrow_width': 1., 'gcr': 0.4, 'rho_ground': 0.8, 'rho_back_pvrow': 0.03, 'rho_front_pvrow': 0.01, 'cut': [(1, 3, 'front')] } # Break up inputs (timestamps, array_tilt, array_azimuth, solar_zenith, solar_azimuth, dni, dhi) = breakup_df_inputs(df_inputs_clearday.iloc[:idx_subset]) args = (arguments, timestamps, solar_zenith, solar_azimuth, array_tilt, array_azimuth, dni, dhi) # Run the serial calculation df_registries_serial, _ = (calculate_radiosities_serially_perez(args)) df_registries_parallel, _ = (calculate_radiosities_parallel_perez(*args)) # Format the outputs df_outputs_segments_serial = get_pvrow_segment_outputs( df_registries_serial, values=['qinc'], include_shading=False) df_outputs_segments_parallel = get_pvrow_segment_outputs( df_registries_parallel, values=['qinc'], include_shading=False) # Load files with expected outputs expected_ipoa_dict_qinc = np.array( [[842.43691838, 842.54795737, 842.52912932], [839.30539601, 839.30285394, 839.29810984], [839.17118976, 839.17513111, 839.17725576], [842.24681064, 842.26195526, 842.15463995]]) # Perform the comparisons rtol = 1e-7 atol = 0 assert np.allclose(expected_ipoa_dict_qinc, df_outputs_segments_serial.values, atol=atol, rtol=rtol) assert np.allclose(expected_ipoa_dict_qinc, df_outputs_segments_parallel.values, atol=atol, rtol=rtol)