def test_analytical_azimuth(): times = pd.DatetimeIndex(start="1/1/2015 0:00", end="12/31/2015 23:00", freq="H").tz_localize('Etc/GMT+8') lat, lon = 37.8, -122.25 lat_rad = np.deg2rad(lat) output = solarposition.spa_python(times, lat, lon, 100) solar_azimuth = np.deg2rad(output['azimuth']) # spa solar_zenith = np.deg2rad(output['zenith']) # spencer eot = solarposition.equation_of_time_spencer71(times.dayofyear) hour_angle = np.deg2rad(solarposition.hour_angle(times, lon, eot)) decl = solarposition.declination_spencer71(times.dayofyear) zenith = solarposition.solar_zenith_analytical(lat_rad, hour_angle, decl) azimuth_1 = solarposition.solar_azimuth_analytical(lat_rad, hour_angle, decl, zenith) # pvcdrom and cooper eot = solarposition.equation_of_time_pvcdrom(times.dayofyear) hour_angle = np.deg2rad(solarposition.hour_angle(times, lon, eot)) decl = solarposition.declination_cooper69(times.dayofyear) zenith = solarposition.solar_zenith_analytical(lat_rad, hour_angle, decl) azimuth_2 = solarposition.solar_azimuth_analytical(lat_rad, hour_angle, decl, zenith) idx = np.where(solar_zenith < np.pi/2) assert np.allclose(azimuth_1[idx], solar_azimuth.as_matrix()[idx], atol=0.01) assert np.allclose(azimuth_2[idx], solar_azimuth.as_matrix()[idx], atol=0.017)
def test_analytical_azimuth(): times = pd.DatetimeIndex(start="1/1/2015 0:00", end="12/31/2015 23:00", freq="H").tz_localize('Etc/GMT+8') lat, lon = 37.8, -122.25 lat_rad = np.deg2rad(lat) output = solarposition.spa_python(times, lat, lon, 100) solar_azimuth = np.deg2rad(output['azimuth']) # spa solar_zenith = np.deg2rad(output['zenith']) # spencer eot = solarposition.equation_of_time_spencer71(times.dayofyear) hour_angle = np.deg2rad(solarposition.hour_angle(times, lon, eot)) decl = solarposition.declination_spencer71(times.dayofyear) zenith = solarposition.solar_zenith_analytical(lat_rad, hour_angle, decl) azimuth_1 = solarposition.solar_azimuth_analytical(lat_rad, hour_angle, decl, zenith) # pvcdrom and cooper eot = solarposition.equation_of_time_pvcdrom(times.dayofyear) hour_angle = np.deg2rad(solarposition.hour_angle(times, lon, eot)) decl = solarposition.declination_cooper69(times.dayofyear) zenith = solarposition.solar_zenith_analytical(lat_rad, hour_angle, decl) azimuth_2 = solarposition.solar_azimuth_analytical(lat_rad, hour_angle, decl, zenith) idx = np.where(solar_zenith < np.pi/2) assert np.allclose(azimuth_1[idx], solar_azimuth.as_matrix()[idx], atol=0.01) assert np.allclose(azimuth_2[idx], solar_azimuth.as_matrix()[idx], atol=0.017) # test for NaN values at boundary conditions (PR #431) test_angles = np.radians(np.array( [[ 0., -180., -20.], [ 0., 0., -5.], [ 0., 0., 0.], [ 0., 0., 15.], [ 0., 180., 20.], [ 30., 0., -20.], [ 30., 0., -5.], [ 30., 0., 0.], [ 30., 180., 5.], [ 30., 0., 10.], [ -30., 0., -20.], [ -30., 0., -15.], [ -30., 0., 0.], [ -30., -180., 5.], [ -30., 180., 10.]])) zeniths = solarposition.solar_zenith_analytical(*test_angles.T) azimuths = solarposition.solar_azimuth_analytical(*test_angles.T, zenith=zeniths) assert not np.isnan(azimuths).any()
def test_analytical_azimuth(): times = pd.DatetimeIndex(start="1/1/2015 0:00", end="12/31/2015 23:00", freq="H").tz_localize('Etc/GMT+8') lat, lon = 37.8, -122.25 lat_rad = np.deg2rad(lat) output = solarposition.spa_python(times, lat, lon, 100) solar_azimuth = np.deg2rad(output['azimuth']) # spa solar_zenith = np.deg2rad(output['zenith']) # spencer eot = solarposition.equation_of_time_spencer71(times.dayofyear) hour_angle = np.deg2rad(solarposition.hour_angle(times, lon, eot)) decl = solarposition.declination_spencer71(times.dayofyear) zenith = solarposition.solar_zenith_analytical(lat_rad, hour_angle, decl) azimuth_1 = solarposition.solar_azimuth_analytical(lat_rad, hour_angle, decl, zenith) # pvcdrom and cooper eot = solarposition.equation_of_time_pvcdrom(times.dayofyear) hour_angle = np.deg2rad(solarposition.hour_angle(times, lon, eot)) decl = solarposition.declination_cooper69(times.dayofyear) zenith = solarposition.solar_zenith_analytical(lat_rad, hour_angle, decl) azimuth_2 = solarposition.solar_azimuth_analytical(lat_rad, hour_angle, decl, zenith) idx = np.where(solar_zenith < np.pi/2) assert np.allclose(azimuth_1[idx], solar_azimuth.values[idx], atol=0.01) assert np.allclose(azimuth_2[idx], solar_azimuth.values[idx], atol=0.017) # test for NaN values at boundary conditions (PR #431) test_angles = np.radians(np.array( [[ 0., -180., -20.], [ 0., 0., -5.], [ 0., 0., 0.], [ 0., 0., 15.], [ 0., 180., 20.], [ 30., 0., -20.], [ 30., 0., -5.], [ 30., 0., 0.], [ 30., 180., 5.], [ 30., 0., 10.], [ -30., 0., -20.], [ -30., 0., -15.], [ -30., 0., 0.], [ -30., -180., 5.], [ -30., 180., 10.]])) zeniths = solarposition.solar_zenith_analytical(*test_angles.T) azimuths = solarposition.solar_azimuth_analytical(*test_angles.T, zenith=zeniths) assert not np.isnan(azimuths).any()
def test_analytical_zenith(): times = pd.date_range(start="1/1/2015 0:00", end="12/31/2015 23:00", freq="H").tz_localize('Etc/GMT+8') lat, lon = 37.8, -122.25 lat_rad = np.deg2rad(lat) output = solarposition.spa_python(times, lat, lon, 100) solar_zenith = np.deg2rad(output['zenith']) # spa # spencer eot = solarposition.equation_of_time_spencer71(times.dayofyear) hour_angle = np.deg2rad(solarposition.hour_angle(times, lon, eot)) decl = solarposition.declination_spencer71(times.dayofyear) zenith_1 = solarposition.solar_zenith_analytical(lat_rad, hour_angle, decl) # pvcdrom and cooper eot = solarposition.equation_of_time_pvcdrom(times.dayofyear) hour_angle = np.deg2rad(solarposition.hour_angle(times, lon, eot)) decl = solarposition.declination_cooper69(times.dayofyear) zenith_2 = solarposition.solar_zenith_analytical(lat_rad, hour_angle, decl) assert np.allclose(zenith_1, solar_zenith, atol=0.015) assert np.allclose(zenith_2, solar_zenith, atol=0.025)
def test_hour_angle(): """ Test conversion from hours to hour angles in degrees given the following inputs from NREL SPA calculator at Golden, CO date,times,eot,sunrise,sunset 1/2/2015,7:21:55,-3.935172,-70.699400,70.512721 1/2/2015,16:47:43,-4.117227,-70.699400,70.512721 1/2/2015,12:04:45,-4.026295,-70.699400,70.512721 """ longitude = -105.1786 # degrees times = pd.DatetimeIndex([ '2015-01-02 07:21:55.2132', '2015-01-02 16:47:42.9828', '2015-01-02 12:04:44.6340' ]).tz_localize('Etc/GMT+7') eot = np.array([-3.935172, -4.117227, -4.026295]) hours = solarposition.hour_angle(times, longitude, eot) expected = (-70.682338, 70.72118825000001, 0.000801250) # FIXME: there are differences from expected NREL SPA calculator values # sunrise: 4 seconds, sunset: 48 seconds, transit: 0.2 seconds # but the differences may be due to other SPA input parameters assert np.allclose(hours, expected)
def test_bird(): """Test Bird/Hulstrom Clearsky Model""" times = pd.date_range(start='1/1/2015 0:00', end='12/31/2015 23:00', freq='H') tz = -7 # test timezone gmt_tz = pytz.timezone('Etc/GMT%+d' % -(tz)) times = times.tz_localize(gmt_tz) # set timezone # match test data from BIRD_08_16_2012.xls latitude = 40. longitude = -105. press_mB = 840. o3_cm = 0.3 h2o_cm = 1.5 aod_500nm = 0.1 aod_380nm = 0.15 b_a = 0.85 alb = 0.2 eot = solarposition.equation_of_time_spencer71(times.dayofyear) hour_angle = solarposition.hour_angle(times, longitude, eot) - 0.5 * 15. declination = solarposition.declination_spencer71(times.dayofyear) zenith = solarposition.solar_zenith_analytical( np.deg2rad(latitude), np.deg2rad(hour_angle), declination ) zenith = np.rad2deg(zenith) airmass = atmosphere.get_relative_airmass(zenith, model='kasten1966') etr = irradiance.get_extra_radiation(times) # test Bird with time series data field_names = ('dni', 'direct_horizontal', 'ghi', 'dhi') irrads = clearsky.bird( zenith, airmass, aod_380nm, aod_500nm, h2o_cm, o3_cm, press_mB * 100., etr, b_a, alb ) Eb, Ebh, Gh, Dh = (irrads[_] for _ in field_names) clearsky_path = os.path.dirname(os.path.abspath(__file__)) pvlib_path = os.path.dirname(clearsky_path) data_path = os.path.join(pvlib_path, 'data', 'BIRD_08_16_2012.csv') testdata = pd.read_csv(data_path, usecols=range(1, 26), header=1).dropna() testdata.index = times[1:48] assert np.allclose(testdata['DEC'], np.rad2deg(declination[1:48])) assert np.allclose(testdata['EQT'], eot[1:48], rtol=1e-4) assert np.allclose(testdata['Hour Angle'], hour_angle[1:48]) assert np.allclose(testdata['Zenith Ang'], zenith[1:48]) dawn = zenith < 88. dusk = testdata['Zenith Ang'] < 88. am = pd.Series(np.where(dawn, airmass, 0.), index=times).fillna(0.0) assert np.allclose( testdata['Air Mass'].where(dusk, 0.), am[1:48], rtol=1e-3 ) direct_beam = pd.Series(np.where(dawn, Eb, 0.), index=times).fillna(0.) assert np.allclose( testdata['Direct Beam'].where(dusk, 0.), direct_beam[1:48], rtol=1e-3 ) direct_horz = pd.Series(np.where(dawn, Ebh, 0.), index=times).fillna(0.) assert np.allclose( testdata['Direct Hz'].where(dusk, 0.), direct_horz[1:48], rtol=1e-3 ) global_horz = pd.Series(np.where(dawn, Gh, 0.), index=times).fillna(0.) assert np.allclose( testdata['Global Hz'].where(dusk, 0.), global_horz[1:48], rtol=1e-3 ) diffuse_horz = pd.Series(np.where(dawn, Dh, 0.), index=times).fillna(0.) assert np.allclose( testdata['Dif Hz'].where(dusk, 0.), diffuse_horz[1:48], rtol=1e-3 ) # test keyword parameters irrads2 = clearsky.bird( zenith, airmass, aod_380nm, aod_500nm, h2o_cm, dni_extra=etr ) Eb2, Ebh2, Gh2, Dh2 = (irrads2[_] for _ in field_names) clearsky_path = os.path.dirname(os.path.abspath(__file__)) pvlib_path = os.path.dirname(clearsky_path) data_path = os.path.join(pvlib_path, 'data', 'BIRD_08_16_2012_patm.csv') testdata2 = pd.read_csv(data_path, usecols=range(1, 26), header=1).dropna() testdata2.index = times[1:48] direct_beam2 = pd.Series(np.where(dawn, Eb2, 0.), index=times).fillna(0.) assert np.allclose( testdata2['Direct Beam'].where(dusk, 0.), direct_beam2[1:48], rtol=1e-3 ) direct_horz2 = pd.Series(np.where(dawn, Ebh2, 0.), index=times).fillna(0.) assert np.allclose( testdata2['Direct Hz'].where(dusk, 0.), direct_horz2[1:48], rtol=1e-3 ) global_horz2 = pd.Series(np.where(dawn, Gh2, 0.), index=times).fillna(0.) assert np.allclose( testdata2['Global Hz'].where(dusk, 0.), global_horz2[1:48], rtol=1e-3 ) diffuse_horz2 = pd.Series(np.where(dawn, Dh2, 0.), index=times).fillna(0.) assert np.allclose( testdata2['Dif Hz'].where(dusk, 0.), diffuse_horz2[1:48], rtol=1e-3 ) # test scalars just at noon # XXX: calculations start at 12am so noon is at index = 12 irrads3 = clearsky.bird( zenith[12], airmass[12], aod_380nm, aod_500nm, h2o_cm, dni_extra=etr[12] ) Eb3, Ebh3, Gh3, Dh3 = (irrads3[_] for _ in field_names) # XXX: testdata starts at 1am so noon is at index = 11 np.allclose( [Eb3, Ebh3, Gh3, Dh3], testdata2[['Direct Beam', 'Direct Hz', 'Global Hz', 'Dif Hz']].iloc[11], rtol=1e-3) return pd.DataFrame({'Eb': Eb, 'Ebh': Ebh, 'Gh': Gh, 'Dh': Dh}, index=times)
def test_bird(): """Test Bird/Hulstrom Clearsky Model""" times = pd.date_range(start='1/1/2015 0:00', end='12/31/2015 23:00', freq='H') tz = -7 # test timezone gmt_tz = pytz.timezone('Etc/GMT%+d' % -(tz)) times = times.tz_localize(gmt_tz) # set timezone # match test data from BIRD_08_16_2012.xls latitude = 40. longitude = -105. press_mB = 840. o3_cm = 0.3 h2o_cm = 1.5 aod_500nm = 0.1 aod_380nm = 0.15 b_a = 0.85 alb = 0.2 eot = solarposition.equation_of_time_spencer71(times.dayofyear) hour_angle = solarposition.hour_angle(times, longitude, eot) - 0.5 * 15. declination = solarposition.declination_spencer71(times.dayofyear) zenith = solarposition.solar_zenith_analytical( np.deg2rad(latitude), np.deg2rad(hour_angle), declination ) zenith = np.rad2deg(zenith) airmass = atmosphere.get_relative_airmass(zenith, model='kasten1966') etr = irradiance.get_extra_radiation(times) # test Bird with time series data field_names = ('dni', 'direct_horizontal', 'ghi', 'dhi') irrads = clearsky.bird( zenith, airmass, aod_380nm, aod_500nm, h2o_cm, o3_cm, press_mB * 100., etr, b_a, alb ) Eb, Ebh, Gh, Dh = (irrads[_] for _ in field_names) data_path = DATA_DIR / 'BIRD_08_16_2012.csv' testdata = pd.read_csv(data_path, usecols=range(1, 26), header=1).dropna() testdata.index = times[1:48] assert np.allclose(testdata['DEC'], np.rad2deg(declination[1:48])) assert np.allclose(testdata['EQT'], eot[1:48], rtol=1e-4) assert np.allclose(testdata['Hour Angle'], hour_angle[1:48]) assert np.allclose(testdata['Zenith Ang'], zenith[1:48]) dawn = zenith < 88. dusk = testdata['Zenith Ang'] < 88. am = pd.Series(np.where(dawn, airmass, 0.), index=times).fillna(0.0) assert np.allclose( testdata['Air Mass'].where(dusk, 0.), am[1:48], rtol=1e-3 ) direct_beam = pd.Series(np.where(dawn, Eb, 0.), index=times).fillna(0.) assert np.allclose( testdata['Direct Beam'].where(dusk, 0.), direct_beam[1:48], rtol=1e-3 ) direct_horz = pd.Series(np.where(dawn, Ebh, 0.), index=times).fillna(0.) assert np.allclose( testdata['Direct Hz'].where(dusk, 0.), direct_horz[1:48], rtol=1e-3 ) global_horz = pd.Series(np.where(dawn, Gh, 0.), index=times).fillna(0.) assert np.allclose( testdata['Global Hz'].where(dusk, 0.), global_horz[1:48], rtol=1e-3 ) diffuse_horz = pd.Series(np.where(dawn, Dh, 0.), index=times).fillna(0.) assert np.allclose( testdata['Dif Hz'].where(dusk, 0.), diffuse_horz[1:48], rtol=1e-3 ) # test keyword parameters irrads2 = clearsky.bird( zenith, airmass, aod_380nm, aod_500nm, h2o_cm, dni_extra=etr ) Eb2, Ebh2, Gh2, Dh2 = (irrads2[_] for _ in field_names) data_path = DATA_DIR / 'BIRD_08_16_2012_patm.csv' testdata2 = pd.read_csv(data_path, usecols=range(1, 26), header=1).dropna() testdata2.index = times[1:48] direct_beam2 = pd.Series(np.where(dawn, Eb2, 0.), index=times).fillna(0.) assert np.allclose( testdata2['Direct Beam'].where(dusk, 0.), direct_beam2[1:48], rtol=1e-3 ) direct_horz2 = pd.Series(np.where(dawn, Ebh2, 0.), index=times).fillna(0.) assert np.allclose( testdata2['Direct Hz'].where(dusk, 0.), direct_horz2[1:48], rtol=1e-3 ) global_horz2 = pd.Series(np.where(dawn, Gh2, 0.), index=times).fillna(0.) assert np.allclose( testdata2['Global Hz'].where(dusk, 0.), global_horz2[1:48], rtol=1e-3 ) diffuse_horz2 = pd.Series(np.where(dawn, Dh2, 0.), index=times).fillna(0.) assert np.allclose( testdata2['Dif Hz'].where(dusk, 0.), diffuse_horz2[1:48], rtol=1e-3 ) # test scalars just at noon # XXX: calculations start at 12am so noon is at index = 12 irrads3 = clearsky.bird( zenith[12], airmass[12], aod_380nm, aod_500nm, h2o_cm, dni_extra=etr[12] ) Eb3, Ebh3, Gh3, Dh3 = (irrads3[_] for _ in field_names) # XXX: testdata starts at 1am so noon is at index = 11 np.allclose( [Eb3, Ebh3, Gh3, Dh3], testdata2[['Direct Beam', 'Direct Hz', 'Global Hz', 'Dif Hz']].iloc[11], rtol=1e-3) return pd.DataFrame({'Eb': Eb, 'Ebh': Ebh, 'Gh': Gh, 'Dh': Dh}, index=times)
# note: .dll extension is not needed assy = clr.AddReference(str(src)) from clr import pv lat, lon = 37.81, -122.25 tz = -8.0 dates = ["19900101T12:30:00", "19900102T12:30:00", "19900103T12:30:00", "19900104T12:30:00"] print('Solar Position') sp = pv.SolarPosition(dates, lat, lon, tz) print('Day Angle, offset=1') da = sp.CalcSimpleDayAngleArray() eot = sp.EquationOfTimeSpencer71(da) print('Equation of time, Spencer (1971)') for doy in range(4): print(f'{doy+1:d} --> {eot[doy]:g}') doy = np.arange(4) + 1 eot_pvcdrom = equation_of_time_pvcdrom(doy) eot_test = equation_of_time_spencer71(doy) assert np.allclose([_ for _ in eot], eot_test) decl = declination_spencer71(doy) decl_cooper = declination_cooper69(doy) ts = pd.DatetimeIndex(dates, tz=f'Etc/GMT{int(tz):+d}') ha = hour_angle(ts, lon, eot_test) sp_test = get_solarposition(ts, latitude=lat, longitude=lon) ze = solar_zenith_analytical(37.81*np.pi/180.0, ha*np.pi/180.0, decl)*180/np.pi