diff --git a/docs/sphinx/whatsnew/v1.5.2.rst b/docs/sphinx/whatsnew/v1.5.2.rst index 0bf7281..ce9df6f 100644 --- a/docs/sphinx/whatsnew/v1.5.2.rst +++ b/docs/sphinx/whatsnew/v1.5.2.rst @@ -16,9 +16,11 @@ Fixes output moving forward, the pvlib dependency is updated from ``pvlib>=0.7.0,<0.9.0`` to ``pvlib>=0.9.0,<0.10.0``. This will likely change the results of irradiance simulations. According to the - [pvlib release notes](https://pvlib-python.readthedocs.io/en/v0.9.0/whatsnew.html#bug-fixes), + `pvlib release notes `_, the differences are "expected to be small and primarily occur at low irradiance conditions". (:ghpull:`121`) +* Fixed a bug that affected some irradiance simulations when `surface_tilt` is exactly zero. + See `GH #125 `_ for details. (:ghpull:`128`) Contributors diff --git a/pvfactors/geometry/base.py b/pvfactors/geometry/base.py index a390bab..4cc7d1d 100644 --- a/pvfactors/geometry/base.py +++ b/pvfactors/geometry/base.py @@ -122,7 +122,7 @@ def _get_rotation_from_tilt_azimuth(surface_azimuth, axis_azimuth, tilt): # Calculate rotation of PV row (signed tilt angle) is_pointing_right = ((surface_azimuth - axis_azimuth) % 360.) > 180. rotation = np.where(is_pointing_right, tilt, -tilt) - + rotation[tilt == 0] = -0.0 # GH 125 return rotation diff --git a/pvfactors/tests/test_engine.py b/pvfactors/tests/test_engine.py index e537534..7560471 100644 --- a/pvfactors/tests/test_engine.py +++ b/pvfactors/tests/test_engine.py @@ -562,6 +562,47 @@ def test_check_direct_shading_continuity(): np.testing.assert_allclose(out, expected_out) +def test_check_tilt_zero_discontinuity(): + """ + Before version 1.5.2, surface_tilt=0 with certain combinations of + surface_azimuth and axis_azimuth showed anomolous behavior where + the irradiance at zero tilt was significantly different from the + irradiance at very small but nonzero tilts. Additionally, the + calculated VF matrix could have values outside [0, 1]. See GH #125 + """ + # expected value calculated for surface_tilt=0.001, so should + # not be significantly different from result for surface_tilt=0 + rear_qinc_expected = 76.10 + + timestamps = np.array([dt.datetime(2019, 6, 1, 10)]) + solar_azimuth = np.array([135]) + solar_zenith = np.array([45]) + dni = np.array([200]) + dhi = np.array([400]) + albedo = np.array([0.2]) + surface_tilt = np.array([0.0]) + + # the discontinuity did not occur for all combinations of + # (surface_azimuth, axis_azimuth), so test all four "primary" pairs: + for surface_azimuth in [90, 270]: + surface_azimuth = np.array([surface_azimuth]) + for axis_azimuth in [0, 180]: + params = dict(n_pvrows=3, axis_azimuth=axis_azimuth, + pvrow_height=2, pvrow_width=1, gcr=0.4) + + pvarray = OrderedPVArray.init_from_dict(params) + eng = PVEngine(pvarray) + eng.fit(timestamps, dni, dhi, solar_zenith, solar_azimuth, + surface_tilt, surface_azimuth, albedo) + + # Run simulation and get output + eng.run_full_mode() + out = pvarray.ts_pvrows[1].back.get_param_weighted('qinc') + assert np.all(pvarray.ts_vf_matrix >= 0) + assert np.all(pvarray.ts_vf_matrix <= 1) + assert rear_qinc_expected == pytest.approx(out[0], abs=1e-2) + + def test_create_engine_with_rho_init(params, pvmodule_canadian): """Check that can create PV engine with rho initialization from faoi functions"""