Skip to content

Artefact in Ineichen clearsky model for sun close to horizon #435

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

Closed
kdebrab opened this issue Feb 23, 2018 · 15 comments
Closed

Artefact in Ineichen clearsky model for sun close to horizon #435

kdebrab opened this issue Feb 23, 2018 · 15 comments
Milestone

Comments

@kdebrab
Copy link
Contributor

kdebrab commented Feb 23, 2018

Consider following example:

import pandas as pd
import pvlib
times = pd.date_range('2018-02-16', '2018-02-17', freq='min')
location = pvlib.location.Location(latitude=60., longitude=0.)
for model in ['ineichen', 'haurwitz', 'simplified_solis']:
    location.get_clearsky(times, model=model)['ghi'].plot(label=model, legend=True)

which results in following figure:
pvlib_clearsky

The (default) 'ineichen' clearsky model seems erratic at sunrise and sunset. The effect is especially visible for high latitudes during Winter when the sun slowly approaches the horizon.

Upon closer look in the code, I found the following comment:

# This equation is found in Solar Energy 73, pg 311. Full ref: Perez
# et. al., Vol. 73, pp. 307-317 (2002). It is slightly different
# than the equation given in Solar Energy 73, pg 156. We used the
# equation from pg 311 because of the existence of known typos in
# the pg 156 publication (notably the fh2-(TL-1) should be fh2 *
# (TL-1)).

which refers to the formula:
ghi = (np.exp(-cg2*airmass_absolute*(fh1 + fh2*(tl - 1))) *
np.exp(0.01*airmass_absolute**1.8))
# use fmax to map airmass nans to 0s. multiply and divide by tl to
# reinsert tl nans
ghi = cg1 * dni_extra * cos_zenith * tl / tl * np.fmax(ghi, 0)

However, apart from the typo mentioned, there is another important difference between both formula of Solar Energy 73, and that's the np.exp(0.01*airmass_absolute**1.8) factor, which is only present in the formula of pg 311, but not in the formula of pg 156!

It seems like the artefact is exactly a result of that np.exp(0.01*airmass_absolute**1.8) factor. This factor slowly increases from 1.01 at solar zenith to 1.95 at a zenith angle of 85°, but then shoots to 1000 when the sun reaches the horizon.

So, maybe there was an error also in the formula of Solar Energy 73, pg 311, and that factor wasn't supposed to be there?

Nevertheless, in reference [3] (Reno et al., 2012), this model was found to excel for US sites with the same formula as used by pvlib. The US sites were all below the 49th parallel. I wonder whether this model is still recommendable for higher latitudes?

@kdebrab
Copy link
Contributor Author

kdebrab commented Feb 23, 2018

There is actually another version of the paper of Ineichen, which doesn't contain the typo nor the factor causing the artefact: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.535.4248&rep=rep1&type=pdf.

@adriesse
Copy link
Member

Hi Karel! I saw this effect too but simply didn't have the time to investigate and report--so thank you for this! One hypothesis I had was that this might have worked ok for hourly averages.

@kdebrab
Copy link
Contributor Author

kdebrab commented Feb 23, 2018

Hi Anton, The effect indeed mostly disappears in hourly averages.

Unless you go even further north. Then the whole curve gets really biased. See e.g. the result for 70° latitude:
pvlib_clearsky_70

@wholmgren
Copy link
Member

Thanks for the detailed report. This artifact and the discrepancies among the papers and code is part of what motivated me to add the simplified solis model to the library.

@cwhanse
Copy link
Member

cwhanse commented Feb 23, 2018

And is an example of the original motivation for PVLib. We intended the open source libraries to expose and hopefully resolve this kind of ambiguity in models. @kdebrab do you see a resolution among the various papers? When I can find time I'll pull the Solar Energy papers and see what we can determine on our end. One of us should write Pierre and see if he can enlighten us.

@mikofski
Copy link
Member

Hi @kdebrab thanks for catching this. How does Ineichen compare to haurwitz and solis when the mystery factor np.exp(0.01*airmass_absolute**1.8) is removed? And how do they compare to Bird?

@adriesse
Copy link
Member

Pierre will retire in May, so don't wait too long to ask!

@mikofski
Copy link
Member

Gasp!

@adriesse
Copy link
Member

adriesse commented Apr 17, 2018

I checked with Pierre Ineichen, and he explained that Richard Perez added the exponential term in the later paper based on further analysis of measurements at 10 continental US sites. I guess no one checked the effect on locations outside this geographic area.

I would suggest that function be modified to accept a flag to indicate whether the Perez enhancement is to be used or not, with a default value of False.

@wholmgren
Copy link
Member

Thanks for checking. I support your proposed solution. I'm not going to get to it anytime soon, though, and would welcome a pull request.

@cwhanse
Copy link
Member

cwhanse commented Apr 17, 2018

I concur with @adriesse proposal. I would add a comment to the function signature warning that the Perez enhancement may produce biased results at high latitude, and link the False/True condition for the flag to the appropriate reference.

@martinherrerias
Copy link

One way to remove the artifacts while introducing less bias is to clip the airmass_absolute values to the point where the exponential correction becomes problematic. Something like:

airmass_critical = (cg2*(fh1+fh2*(tl-1))/0.018).^1.25
airmass_clipped = np.fmin(airmass_absolute, airmass_critical)
ghi = (np.exp(-cg2*airmass_clipped*(fh1 + fh2*(tl - 1)) + 0.01*airmass_clipped**1.8))
...
ghi = cg1 * dni_extra * cos_zenith * tl / tl * np.fmax(ghi, 0)

airmass_critical is a minimum for the combined exponential terms, which shoot up afterwards. Loosely:
airmass_critical = argmin(f(x)), for f = exp(-cg2*x*(fh1 + fh2*(tl - 1)) + 0.01*x^1.8))

This threshold starts at AM = 2.6 (for turbidity = 1 and altitude = 0), equivalent to ~22.5° solar elevation, and goes up to O(10) for higher turbidities and altitudes. For most cases, it corresponds to solar elevation angles below the 4° cutting threshold of the CIE 1994 quality control guidelines that Ineichen & Perez seem to have used, i.e. they probably didn't see beyond it.

Clipping at the minimum makes the adjustment smooth (C1), and leaves the results of the model untouched for most operating conditions.

clearsky_ineichen

@cwhanse
Copy link
Member

cwhanse commented Sep 22, 2020

@martinherrerias your proposal makes a lot of sense to me, now that I better understand the the role that correction plays. Rather than continuing in this old issue, would you like to open a new issue? If you are also inclined a pull request is welcome.

@adriesse
Copy link
Member

I would suggest controlling this new feature by the same flag or a new one. It should be possible to run the model as published.

This reminds me of some discussions about using models outside of the range of inputs for which they were developed and/or validated.

@mikofski
Copy link
Member

Are there any references for this new feature? @martinherrerias any plans to present or publish this idea? I think that would be useful. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants