Skip to content

limit cos(aoi) in diffuse sky functions #535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 19, 2018
Merged

Conversation

wholmgren
Copy link
Member

@wholmgren wholmgren commented Aug 14, 2018

Fixes two issues related to projection of the solar angle:

  1. Dividing by near-0 cos(solar_zenith) when the sun is very close to the horizon.
  2. non-0 contributions of the beam irradiance to the reindl, haydavies, and klucher functions.

Implementation is up for debate. Seemed easier to make a pull request with a concrete proposal.

I considered calculating the cos_solar_zenith as:

cos_solar_zenith = aoi_projection(0, 0, solar_zenith, 0, projection_minimum=0.01745)

but I am worried this could lead to issues with small floating point arithmetic (worse, they could be platform and python/numpy version dependent).

other:

  • Add test values for solar zenith between 89 and 90 deg.
  • Rerun irradiance tutorial

@wholmgren wholmgren added this to the 0.6.0 milestone Aug 14, 2018
Minimum allowable value for the projection for the solar angle
into the plane of the array. For example, 0 is equivalent to a
90 degree limit, 0.01745 is equivalent to a 89 degree limit.
`None` applies no limit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your explanation makes me wonder whether the minimum would be better expressed in degrees.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I also wondered this. I only went with the projection because it's the quantity that is hardcoded in the matlab library.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After thinking through the response to your comment below, I am leaning towards keeping it as the dot product to avoid the complexity of handling angles > 90 degrees or less than 0.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having trouble seeing a use case which requires projection_minimum. The function's description says it calculates a dot product so that's what I'd expect it to do, and to not do more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it does less than a dot product since it assumes/requires the vectors are unit vectors. It's really just calculating the cosine of the angle of incidence. I think the name "projection" seems to suggest more, and may even be confusing to some.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will remove the projection_minimum kwargs and put the limits in the diffuse models where necessary. We can address the function name in a separate issue.


cos_solar_zenith = tools.cosd(solar_zenith)

if solar_zenith_projection_minimum is not None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think None should be possible here.

Copy link
Member Author

@wholmgren wholmgren Aug 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we could go with a default value of -1 and always apply the limit.


cos_solar_zenith = tools.cosd(solar_zenith)
cos_solar_zenith = np.maximum(tools.cosd(solar_zenith), 0.01745)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Rb this limit might be good, but for HB further below the limit should be zero (already enforced).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I'll fix this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it is more clear to leave the cos_tt and cos_solar_zenith calculations alone, and apply the filters to the value of Rb.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cwhanse I figured you'd be in favor of being consistent with the matlab approach. I like it because it addresses both #432 and #526.

Minimum allowable value for the projection for the solar angle
into the plane of the array. For example, 0 is equivalent to a
90 degree limit, 0.01745 is equivalent to a 89 degree limit.
`None` applies no limit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having trouble seeing a use case which requires projection_minimum. The function's description says it calculates a dot product so that's what I'd expect it to do, and to not do more.

into the plane of the array. `None` applies no limit.
solar_zenith_projection_minimum : numeric, default None
Minimum allowable value for the projection of the solar angle
on to a horizontal surface. `None` applies no limit.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm struggling to see how the xxx_minimum kwargs are more clear than handling the behind-the-plane or nearly co-planar cases directly, in the calculation of the ratios in the diffuse sky models.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair. I think this is a borderline case of "don't repeat yourself". I have no idea if people use these functions on their own.


cos_solar_zenith = tools.cosd(solar_zenith)

cos_solar_zenith = np.maximum(cos_solar_zenith,
solar_zenith_projection_minimum)

# ratio of titled and horizontal beam irradiance
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: tilted not titled

@wholmgren
Copy link
Member Author

@cwhanse is it easy enough for you to run the matlab equivalents of klucher, haydavies, reindl, king with the same inputs as our test suite?

@mikofski
Copy link
Member

@cwhanse is pvlib-matlab all functions, no classes? If so it should run in Octave, so then if there's a test suite, you could run it on a CI server like Travis. Just use sudo install octave in the build script

@cwhanse
Copy link
Member

cwhanse commented Aug 17, 2018

Yes, PVLib for Matlab is a collection of function. We currently have no test suite for PVLib for Matlab, which is a major deficiency.

@wholmgren
Copy link
Member Author

I'm working on some matlab/python tests here: https://github.com/wholmgren/MATLAB_PV_LIB/blob/skydifftest/tests/test_sky_diffuse.m I have little idea about what I'm doing with matlab testing, but it seems to get the job done for this pvlib python PR. @cwhanse if you're interested I can make a PR to the matlab repository, but I imagine you all might have a preferred way to do the testing.

@cwhanse
Copy link
Member

cwhanse commented Aug 18, 2018

Klucher:

The expected result for test_klucher_series is the same as produced by PVLib for MATLAB. However, PVLib for MATLAB does not filter out for cos(AOI) < 0, which is why the expected result is different from the calculated results. Bug in PVLib for MATLAB, in my opinion.

@cwhanse cwhanse closed this Aug 18, 2018
@cwhanse cwhanse reopened this Aug 18, 2018
@@ -836,8 +837,9 @@ def haydavies(surface_tilt, surface_azimuth, dhi, dni, dni_extra,
if projection_ratio is None:
cos_tt = aoi_projection(surface_tilt, surface_azimuth,
solar_zenith, solar_azimuth)
cos_tt = np.minimum(cos_tt, 0) # GH 526
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be np.maximum

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hay and Davies:

test_haydavies fails because of this error np.minimum. Otherwise I believe it should pass.

@@ -932,11 +934,13 @@ def reindl(surface_tilt, surface_azimuth, dhi, dni, ghi, dni_extra,

cos_tt = aoi_projection(surface_tilt, surface_azimuth,
solar_zenith, solar_azimuth)
cos_tt = np.minimum(cos_tt, 0) # GH 526
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

np.maximum here

@wholmgren
Copy link
Member Author

The test failures are unrelated. I believe this is ready to merge.

@cwhanse cwhanse merged commit 4f3b7e4 into pvlib:master Aug 19, 2018
@wholmgren wholmgren deleted the aoidiff branch August 19, 2018 17:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants