Skip to content

Commit 4868069

Browse files
committed
Merge pull request #26 from wholmgren/disc
DISC fixes
2 parents e24d1c9 + e495c42 commit 4868069

File tree

2 files changed

+83
-60
lines changed

2 files changed

+83
-60
lines changed

pvlib/clearsky.py

Lines changed: 61 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -284,9 +284,10 @@ def _linearly_scale(inputmatrix, inputmin, inputmax, outputmin, outputmax):
284284

285285

286286

287-
def disc(GHI, SunZen, Time, pressure=101325):
287+
def disc(GHI, zenith, times, pressure=101325):
288288
'''
289-
Estimate Direct Normal Irradiance from Global Horizontal Irradiance using the DISC model
289+
Estimate Direct Normal Irradiance from Global Horizontal Irradiance
290+
using the DISC model.
290291
291292
The DISC algorithm converts global horizontal irradiance to direct
292293
normal irradiance through empirical relationships between the global
@@ -295,35 +296,27 @@ def disc(GHI, SunZen, Time, pressure=101325):
295296
Parameters
296297
----------
297298
298-
GHI : float or DataFrame
299-
global horizontal irradiance in W/m^2. GHI must be >=0.
299+
GHI : Series
300+
Global horizontal irradiance in W/m^2.
300301
301-
Z : float or DataFrame
302-
True (not refraction - corrected) zenith angles in decimal degrees.
303-
Z must be >=0 and <=180.
302+
zenith : Series
303+
True (not refraction - corrected) solar zenith
304+
angles in decimal degrees.
304305
305-
doy : float or DataFrame
306-
the day of the year. doy must be >= 1 and < 367.
306+
times : DatetimeIndex
307307
308-
Other Parameters
309-
----------------
310-
311-
pressure : float or DataFrame (optional, Default=101325)
312-
313-
site pressure in Pascal. Pressure may be measured
314-
or an average pressure may be calculated from site altitude. If
315-
pressure is omitted, standard pressure (101325 Pa) will be used, this
316-
is acceptable if the site is near sea level. If the site is not near
317-
sea:level, inclusion of a measured or average pressure is highly
318-
recommended.
308+
pressure : float or Series
309+
Site pressure in Pascal.
319310
320311
Returns
321312
-------
322-
DNI : float or DataFrame
323-
The modeled direct normal irradiance in W/m^2 provided by the
324-
Direct Insolation Simulation Code (DISC) model.
325-
Kt : float or DataFrame
326-
Ratio of global to extraterrestrial irradiance on a horizontal plane.
313+
DataFrame with the following keys:
314+
* ``DNI_gen_DISC``: The modeled direct normal irradiance
315+
in W/m^2 provided by the
316+
Direct Insolation Simulation Code (DISC) model.
317+
* ``Kt_gen_DISC``: Ratio of global to extraterrestrial
318+
irradiance on a horizontal plane.
319+
* ``AM``: Airmass
327320
328321
References
329322
----------
@@ -343,46 +336,54 @@ def disc(GHI, SunZen, Time, pressure=101325):
343336
ephemeris
344337
alt2pres
345338
dirint
346-
347339
'''
348340

349-
#create a temporary dataframe to house masked values, initially filled with NaN
350-
temp=pd.DataFrame(index=Time,columns=['A','B','C'])
351-
352-
353-
pressure=101325
354-
doy=Time.dayofyear
355-
DayAngle=2.0 * np.pi*((doy - 1)) / 365
356-
re=1.00011 + 0.034221*(np.cos(DayAngle)) + (0.00128)*(np.sin(DayAngle)) + 0.000719*(np.cos(2.0 * DayAngle)) + (7.7e-05)*(np.sin(2.0 * DayAngle))
357-
I0=re*(1370)
358-
I0h=I0*(np.cos(np.radians(SunZen)))
359-
Ztemp=SunZen
360-
Ztemp[SunZen > 87]=87
361-
AM=1.0 / (np.cos(np.radians(Ztemp)) + 0.15*(((93.885 - Ztemp) ** (- 1.253))))*(pressure) / 101325
362-
Kt=GHI / (I0h)
363-
Kt[Kt < 0]=0
364-
Kt[Kt > 2]=np.NaN
365-
temp.A[Kt > 0.6]=- 5.743 + 21.77*(Kt[Kt > 0.6]) - 27.49*(Kt[Kt > 0.6] ** 2) + 11.56*(Kt[Kt > 0.6] ** 3)
366-
temp.B[Kt > 0.6]=41.4 - 118.5*(Kt[Kt > 0.6]) + 66.05*(Kt[Kt > 0.6] ** 2) + 31.9*(Kt[Kt > 0.6] ** 3)
367-
temp.C[Kt > 0.6]=- 47.01 + 184.2*(Kt[Kt > 0.6]) - 222.0 * Kt[Kt > 0.6] ** 2 + 73.81*(Kt[Kt > 0.6] ** 3)
368-
temp.A[(Kt <= 0.6-1)]=0.512 - 1.56*(Kt[(Kt <= 0.6-1)]) + 2.286*(Kt[(Kt <= 0.6-1)] ** 2) - 2.222*(Kt[(Kt <= 0.6-1)] ** 3)
369-
temp.B[(Kt <= 0.6-1)]=0.37 + 0.962*(Kt[(Kt <= 0.6-1)])
370-
temp.C[(Kt <= 0.6-1)]=- 0.28 + 0.932*(Kt[(Kt <= 0.6-1)]) - 2.048*(Kt[(Kt <= 0.6-1)] ** 2)
341+
logger.debug('clearsky.disc')
342+
343+
temp = pd.DataFrame(index=times, columns=['A','B','C'])
344+
345+
doy = times.dayofyear
346+
347+
DayAngle = 2. * np.pi*(doy - 1) / 365
348+
349+
re = (1.00011 + 0.034221*np.cos(DayAngle) + 0.00128*np.sin(DayAngle)
350+
+ 0.000719*np.cos(2.*DayAngle) + 7.7e-05*np.sin(2.*DayAngle) )
351+
352+
I0 = re * 1370.
353+
I0h = I0 * np.cos(np.radians(zenith))
354+
355+
Ztemp = zenith.copy()
356+
Ztemp[zenith > 87] = np.NaN
357+
358+
AM = 1.0 / ( np.cos(np.radians(Ztemp)) + 0.15*( (93.885 - Ztemp)**(-1.253) ) ) * (pressure / 101325)
359+
360+
Kt = GHI / I0h
361+
Kt[Kt < 0] = 0
362+
Kt[Kt > 2] = np.NaN
363+
364+
temp.A[Kt > 0.6] = -5.743 + 21.77*(Kt[Kt > 0.6]) - 27.49*(Kt[Kt > 0.6] ** 2) + 11.56*(Kt[Kt > 0.6] ** 3)
365+
temp.B[Kt > 0.6] = 41.4 - 118.5*(Kt[Kt > 0.6]) + 66.05*(Kt[Kt > 0.6] ** 2) + 31.9*(Kt[Kt > 0.6] ** 3)
366+
temp.C[Kt > 0.6] = -47.01 + 184.2*(Kt[Kt > 0.6]) - 222.0 * Kt[Kt > 0.6] ** 2 + 73.81*(Kt[Kt > 0.6] ** 3)
367+
temp.A[Kt <= 0.6] = 0.512 - 1.56*(Kt[Kt <= 0.6]) + 2.286*(Kt[Kt <= 0.6] ** 2) - 2.222*(Kt[Kt <= 0.6] ** 3)
368+
temp.B[Kt <= 0.6] = 0.37 + 0.962*(Kt[Kt <= 0.6])
369+
temp.C[Kt <= 0.6] = -0.28 + 0.932*(Kt[Kt <= 0.6]) - 2.048*(Kt[Kt <= 0.6] ** 2)
370+
371371
#return to numeric after masking operations
372-
temp=temp.astype(float)
373-
delKn=temp.A + temp.B*((temp.C*(AM)).apply(np.exp))
374-
Knc=0.866 - 0.122*(AM) + 0.0121*(AM ** 2) - 0.000653*(AM ** 3) + 1.4e-05*(AM ** 4)
375-
Kn=Knc - delKn
376-
DNI=(Kn)*(I0)
372+
temp = temp.astype(float)
377373

378-
DNI[SunZen > 87]=np.NaN
379-
DNI[GHI < 1]=np.NaN
380-
DNI[DNI < 0]=np.NaN
374+
delKn = temp.A + temp.B * np.exp(temp.C*AM)
375+
376+
Knc = 0.866 - 0.122*(AM) + 0.0121*(AM ** 2) - 0.000653*(AM ** 3) + 1.4e-05*(AM ** 4)
377+
Kn = Knc - delKn
378+
379+
DNI = Kn * I0
381380

382-
DFOut=pd.DataFrame({'DNI_gen_DISC':DNI})
381+
DNI[zenith > 87] = np.NaN
382+
DNI[GHI < 1] = np.NaN
383+
DNI[DNI < 0] = np.NaN
383384

384-
DFOut['Kt_gen_DISC']=Kt
385-
DFOut['AM']=AM
386-
DFOut['Ztemp']=Ztemp
385+
DFOut = pd.DataFrame({'DNI_gen_DISC':DNI})
386+
DFOut['Kt_gen_DISC'] = Kt
387+
DFOut['AM'] = AM
387388

388389
return DFOut

pvlib/test/test_clearsky.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
from nose.tools import raises
1010

11+
from numpy.testing import assert_almost_equal
12+
1113
from pvlib.location import Location
1214
from pvlib import clearsky
1315
from pvlib import solarposition
@@ -54,3 +56,23 @@ def test_haurwitz():
5456
def test_haurwitz_keys():
5557
clearsky_data = clearsky.haurwitz(ephem_data['zenith'])
5658
assert 'GHI' in clearsky_data.columns
59+
60+
61+
# test DISC
62+
def test_disc_keys():
63+
clearsky_data = clearsky.ineichen(times, tus)
64+
disc_data = clearsky.disc(clearsky_data['GHI'], ephem_data['zenith'],
65+
ephem_data.index)
66+
assert 'DNI_gen_DISC' in disc_data.columns
67+
assert 'Kt_gen_DISC' in disc_data.columns
68+
assert 'AM' in disc_data.columns
69+
70+
def test_disc_value():
71+
times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700'])
72+
ghi = pd.Series([1038.62, 254.53], index=times)
73+
zenith = pd.Series([10.567, 72.469], index=times)
74+
pressure = 93193.
75+
disc_data = clearsky.disc(ghi, zenith, times, pressure=pressure)
76+
assert_almost_equal(disc_data['DNI_gen_DISC'].values,
77+
np.array([830.46, 676.09]), 1)
78+

0 commit comments

Comments
 (0)