def pvl_perez(SurfTilt, SurfAz, DHI, DNI, HExtra, SunZen, SunAz, AM, modelt='allsitescomposite1990'): ''' Determine diffuse irradiance from the sky on a tilted surface using one of the Perez models Perez models determine the diffuse irradiance from the sky (ground reflected irradiance is not included in this algorithm) on a tilted surface using the surface tilt angle, surface azimuth angle, diffuse horizontal irradiance, direct normal irradiance, extraterrestrial irradiance, sun zenith angle, sun azimuth angle, and relative (not pressure-corrected) airmass. Optionally a selector may be used to use any of Perez's model coefficient sets. Parameters ---------- SurfTilt : float or DataFrame Surface tilt angles in decimal degrees. SurfTilt must be >=0 and <=180. The tilt angle is defined as degrees from horizontal (e.g. surface facing up = 0, surface facing horizon = 90) SurfAz : float or DataFrame Surface azimuth angles in decimal degrees. SurfAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, South=180 East = 90, West = 270). DHI : float or DataFrame diffuse horizontal irradiance in W/m^2. DHI must be >=0. DNI : float or DataFrame direct normal irradiance in W/m^2. DNI must be >=0. HExtra : float or DataFrame extraterrestrial normal irradiance in W/m^2. HExtra must be >=0. SunZen : float or DataFrame apparent (refraction-corrected) zenith angles in decimal degrees. SunZen must be >=0 and <=180. SunAz : float or DataFrame Sun azimuth angles in decimal degrees. SunAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, East = 90, West = 270). AM : float or DataFrame relative (not pressure-corrected) airmass values. If AM is a DataFrame it must be of the same size as all other DataFrame inputs. AM must be >=0 (careful using the 1/sec(z) model of AM generation) Other Parameters ---------------- model : string (optional, default='allsitescomposite1990') a character string which selects the desired set of Perez coefficients. If model is not provided as an input, the default, '1990' will be used. All possible model selections are: * '1990' * 'allsitescomposite1990' (same as '1990') * 'allsitescomposite1988' * 'sandiacomposite1988' * 'usacomposite1988' * 'france1988' * 'phoenix1988' * 'elmonte1988' * 'osage1988' * 'albuquerque1988' * 'capecanaveral1988' * 'albany1988' Returns -------- SkyDiffuse : float or DataFrame the diffuse component of the solar radiation on an arbitrarily tilted surface defined by the Perez model as given in reference [3]. SkyDiffuse is the diffuse component ONLY and does not include the ground reflected irradiance or the irradiance due to the beam. References ---------- [1] Loutzenhiser P.G. et. al. "Empirical validation of models to compute solar irradiance on inclined surfaces for building energy simulation" 2007, Solar Energy vol. 81. pp. 254-267 [2] Perez, R., Seals, R., Ineichen, P., Stewart, R., Menicucci, D., 1987. A new simplified version of the Perez diffuse irradiance model for tilted surfaces. Solar Energy 39(3), 221-232. [3] Perez, R., Ineichen, P., Seals, R., Michalsky, J., Stewart, R., 1990. Modeling daylight availability and irradiance components from direct and global irradiance. Solar Energy 44 (5), 271-289. [4] Perez, R. et. al 1988. "The Development and Verification of the Perez Diffuse Radiation Model". SAND88-7030 See also -------- pvl_ephemeris pvl_extraradiation pvl_isotropicsky pvl_haydavies1980 pvl_reindl1990 pvl_klucher1979 pvl_kingdiffuse pvl_relativeairmass ''' Vars = locals() Expect = { 'SurfTilt': ('num', 'x>=0'), 'SurfAz': ('x>=-180'), 'DHI': ('x>=0'), 'DNI': ('x>=0'), 'HExtra': ('x>=0'), 'SunZen': ('x>=0'), 'SunAz': ('x>=-180'), 'AM': ('x>=0'), 'modelt': ('default', 'default=allsitescomposite1990') } var = pvl_tools.Parse(Vars, Expect) kappa = 1.041 #for SunZen in radians z = var.SunZen * np.pi / 180 # # convert to radians Dhfilter = var.DHI > 0 e = ((var.DHI[Dhfilter] + var.DNI[Dhfilter]) / var.DHI[Dhfilter] + kappa * z[Dhfilter]**3) / (1 + kappa * z[Dhfilter]**3).reindex_like( var.SunZen) ebin = pd.Series(np.zeros(var.DHI.shape[0]), index=e.index) # Select which bin e falls into ebin[(e < 1.065)] = 1 ebin[(e >= 1.065) & (e < 1.23)] = 2 ebin[(e >= 1.23) & (e < 1.5)] = 3 ebin[(e >= 1.5) & (e < 1.95)] = 4 ebin[(e >= 1.95) & (e < 2.8)] = 5 ebin[(e >= 2.8) & (e < 4.5)] = 6 ebin[(e >= 4.5) & (e < 6.2)] = 7 ebin[e >= 6.2] = 8 ebinfilter = ebin > 0 ebin = ebin - 1 #correct for 0 indexing ebin[ebinfilter == False] = np.NaN ebin = ebin.dropna().astype(int) # This is added because in cases where the sun is below the horizon # (var.SunZen > 90) but there is still diffuse horizontal light (var.DHI>0), it is # possible that the airmass (var.AM) could be NaN, which messes up later # calculations. Instead, if the sun is down, and there is still var.DHI, we set # the airmass to the airmass value on the horizon (approximately 37-38). #var.AM(var.SunZen >=90 & var.DHI >0) = 37; var.HExtra[var.HExtra == 0] = .00000001 #very hacky, fix this delt = var.DHI * var.AM / var.HExtra # # The various possible sets of Perez coefficients are contained # in a subfunction to clean up the code. F1c, F2c = GetPerezCoefficients(var.modelt) F1 = F1c[ebin, 0] + F1c[ebin, 1] * delt[ebinfilter] + F1c[ebin, 2] * z[ebinfilter] F1[F1 < 0] = 0 F1 = F1.astype(float) F2 = F2c[ebin, 0] + F2c[ebin, 1] * delt[ebinfilter] + F2c[ebin, 2] * z[ebinfilter] F2[F2 < 0] = 0 F2 = F2.astype(float) A = pvl_tools.cosd(var.SurfTilt) * pvl_tools.cosd( var.SunZen) + pvl_tools.sind(var.SurfTilt) * pvl_tools.sind( var.SunZen) * pvl_tools.cosd(var.SunAz - var.SurfAz) #removed +180 from azimuth modifier: Rob Andrews October 19th 2012 A[A < 0] = 0 B = pvl_tools.cosd(var.SunZen) B[B < pvl_tools.cosd(85)] = pvl_tools.cosd(85) #Calculate Diffuse POA from sky dome #SkyDiffuse = pd.Series(np.zeros(var.DHI.shape[0]),index=data.index) SkyDiffuse = var.DHI[ebinfilter] * ( 0.5 * (1 - F1[ebinfilter]) * (1 + pvl_tools.cosd(var.SurfTilt)) + F1[ebinfilter] * A[ebinfilter] / B[ebinfilter] + F2[ebinfilter] * pvl_tools.sind(var.SurfTilt)) SkyDiffuse[SkyDiffuse <= 0] = 0 return pd.DataFrame({'In_Plane_SkyDiffuse': SkyDiffuse})
def pvl_haydavies1980(SurfTilt, SurfAz, DHI, DNI, HExtra, SunZen, SunAz): ''' Determine diffuse irradiance from the sky on a tilted surface using Hay & Davies' 1980 model Hay and Davies' 1980 model determines the diffuse irradiance from the sky (ground reflected irradiance is not included in this algorithm) on a tilted surface using the surface tilt angle, surface azimuth angle, diffuse horizontal irradiance, direct normal irradiance, extraterrestrial irradiance, sun zenith angle, and sun azimuth angle. Parameters ---------- SurfTilt : float or DataFrame Surface tilt angles in decimal degrees. SurfTilt must be >=0 and <=180. The tilt angle is defined as degrees from horizontal (e.g. surface facing up = 0, surface facing horizon = 90) SurfAz : float or DataFrame Surface azimuth angles in decimal degrees. SurfAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, South=180 East = 90, West = 270). DHI : float or DataFrame diffuse horizontal irradiance in W/m^2. DHI must be >=0. DNI : float or DataFrame direct normal irradiance in W/m^2. DNI must be >=0. HExtra : float or DataFrame extraterrestrial normal irradiance in W/m^2. HExtra must be >=0. SunZen : float or DataFrame apparent (refraction-corrected) zenith angles in decimal degrees. SunZen must be >=0 and <=180. SunAz : float or DataFrame Sun azimuth angles in decimal degrees. SunAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, East = 90, West = 270). Returns -------- SkyDiffuse : float or DataFrame the diffuse component of the solar radiation on an arbitrarily tilted surface defined by the Perez model as given in reference [3]. SkyDiffuse is the diffuse component ONLY and does not include the ground reflected irradiance or the irradiance due to the beam. References ----------- [1] Loutzenhiser P.G. et. al. "Empirical validation of models to compute solar irradiance on inclined surfaces for building energy simulation" 2007, Solar Energy vol. 81. pp. 254-267 [2] Hay, J.E., Davies, J.A., 1980. Calculations of the solar radiation incident on an inclined surface. In: Hay, J.E., Won, T.K. (Eds.), Proc. of First Canadian Solar Radiation Data Workshop, 59. Ministry of Supply and Services, Canada. See Also -------- pvl_ephemeris pvl_extraradiation pvl_isotropicsky pvl_reindl1990 pvl_perez pvl_klucher1979 pvl_kingdiffuse pvl_spa ''' Vars = locals() Expect = { 'SurfTilt': ('num', 'x>=0'), 'SurfAz': ('x>=-180'), 'DHI': ('x>=0'), 'DNI': ('x>=0'), 'HExtra': ('x>=0'), 'SunZen': ('x>=0'), 'SunAz': ('x>=-180'), } var = pvl_tools.Parse(Vars, Expect) COSTT = pvl_tools.cosd(SurfTilt) * pvl_tools.cosd(SunZen) + pvl_tools.sind( SurfTilt) * pvl_tools.sind(SunZen) * pvl_tools.cosd(SunAz - SurfAz) RB = np.max(COSTT, 0) / np.max(pvl_tools.cosd(SunZen), 0.01745) AI = DNI / HExtra SkyDiffuse = DHI * ((AI * (RB) + (1 - AI) * (0.5) * ((1 + pvl_tools.cosd(SurfTilt))))) return SkyDiffuse
def pvl_physicaliam(K, L, n, theta): ''' Determine the incidence angle modifier using refractive index, glazing thickness, and extinction coefficient pvl_physicaliam calculates the incidence angle modifier as described in De Soto et al. "Improvement and validation of a model for photovoltaic array performance", section 3. The calculation is based upon a physical model of absorbtion and transmission through a cover. Required information includes, incident angle, cover extinction coefficient, cover thickness Note: The authors of this function believe that eqn. 14 in [1] is incorrect. This function uses the following equation in its place: theta_r = arcsin(1/n * sin(theta)) Parameters ---------- K : float The glazing extinction coefficient in units of 1/meters. Reference [1] indicates that a value of 4 is reasonable for "water white" glass. K must be a numeric scalar or vector with all values >=0. If K is a vector, it must be the same size as all other input vectors. L : float The glazing thickness in units of meters. Reference [1] indicates that 0.002 meters (2 mm) is reasonable for most glass-covered PV panels. L must be a numeric scalar or vector with all values >=0. If L is a vector, it must be the same size as all other input vectors. n : float The effective index of refraction (unitless). Reference [1] indicates that a value of 1.526 is acceptable for glass. n must be a numeric scalar or vector with all values >=0. If n is a vector, it must be the same size as all other input vectors. theta :float The angle of incidence between the module normal vector and the sun-beam vector in degrees. Theta must be a numeric scalar or vector. For any values of theta where abs(theta)>90, IAM is set to 0. For any values of theta where -90 < theta < 0, theta is set to abs(theta) and evaluated. A warning will be generated if any(theta<0 or theta>90). Returns ------- IAM : float The incident angle modifier as specified in eqns. 14-16 of [1]. IAM is a column vector with the same number of elements as the largest input vector. References ---------- [1] W. De Soto et al., "Improvement and validation of a model for photovoltaic array performance", Solar Energy, vol 80, pp. 78-88, 2006. [2] Duffie, John A. & Beckman, William A.. (2006). Solar Engineering of Thermal Processes, third edition. [Books24x7 version] Available from http://common.books24x7.com/toc.aspx?bookid=17160. See Also -------- pvl_getaoi pvl_ephemeris pvl_spa pvl_ashraeiam ''' Vars = locals() Expect = {'K': 'x >= 0', 'L': 'x >= 0', 'n': 'x >= 0', 'theta': 'num'} var = pvl_tools.Parse(Vars, Expect) if any((var.theta < 0) | (var.theta >= 90)): print( 'Input incident angles <0 or >=90 detected For input angles with absolute value greater than 90, the ' + 'modifier is set to 0. For input angles between -90 and 0, the ' + 'angle is changed to its absolute value and evaluated.') var.theta[(var.theta < 0) | (var.theta >= 90)] = abs((var.theta < 0) | (var.theta >= 90)) thetar_deg = pvl_tools.asind(1.0 / n * (pvl_tools.sind(theta))) tau = np.exp(-1.0 * (K * (L) / pvl_tools.cosd(thetar_deg))) * ((1 - 0.5 * ( (((pvl_tools.sind(thetar_deg - theta))**2) / ((pvl_tools.sind(thetar_deg + theta))**2) + ((pvl_tools.tand(thetar_deg - theta))**2) / ((pvl_tools.tand(thetar_deg + theta))**2))))) zeroang = 1e-06 thetar_deg0 = pvl_tools.asind(1.0 / n * (pvl_tools.sind(zeroang))) tau0 = np.exp(-1.0 * (K * (L) / pvl_tools.cosd(thetar_deg0))) * ( (1 - 0.5 * ((((pvl_tools.sind(thetar_deg0 - zeroang))**2) / ((pvl_tools.sind(thetar_deg0 + zeroang))**2) + ((pvl_tools.tand(thetar_deg0 - zeroang))**2) / ((pvl_tools.tand(thetar_deg0 + zeroang))**2))))) IAM = tau / tau0 IAM[theta == 0] = 1 IAM[abs(theta) > 90 | (IAM < 0)] = 0 return IAM
def pvl_klucher1979(SurfTilt, SurfAz, DHI, GHI, SunZen, SunAz): ''' Determine diffuse irradiance from the sky on a tilted surface using Klucher's 1979 model Klucher's 1979 model determines the diffuse irradiance from the sky (ground reflected irradiance is not included in this algorithm) on a tilted surface using the surface tilt angle, surface azimuth angle, diffuse horizontal irradiance, direct normal irradiance, global horizontal irradiance, extraterrestrial irradiance, sun zenith angle, and sun azimuth angle. Parameters ---------- SurfTilt : float or DataFrame Surface tilt angles in decimal degrees. SurfTilt must be >=0 and <=180. The tilt angle is defined as degrees from horizontal (e.g. surface facing up = 0, surface facing horizon = 90) SurfAz : float or DataFrame Surface azimuth angles in decimal degrees. SurfAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, South=180 East = 90, West = 270). DHI : float or DataFrame diffuse horizontal irradiance in W/m^2. DHI must be >=0. GHI : float or DataFrame Global irradiance in W/m^2. DNI must be >=0. SunZen : float or DataFrame apparent (refraction-corrected) zenith angles in decimal degrees. SunZen must be >=0 and <=180. SunAz : float or DataFrame Sun azimuth angles in decimal degrees. SunAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, East = 90, West = 270). Returns ------- SkyDiffuse : float or DataFrame the diffuse component of the solar radiation on an arbitrarily tilted surface defined by the Klucher model as given in Loutzenhiser et. al (2007) equation 4. SkyDiffuse is the diffuse component ONLY and does not include the ground reflected irradiance or the irradiance due to the beam. SkyDiffuse is a column vector vector with a number of elements equal to the input vector(s). References ---------- [1] Loutzenhiser P.G. et. al. "Empirical validation of models to compute solar irradiance on inclined surfaces for building energy simulation" 2007, Solar Energy vol. 81. pp. 254-267 [2] Klucher, T.M., 1979. Evaluation of models to predict insolation on tilted surfaces. Solar Energy 23 (2), 111-114. See also -------- pvl_ephemeris pvl_extraradiation pvl_isotropicsky pvl_haydavies1980 pvl_perez pvl_reindl1990 pvl_kingdiffuse ''' Vars = locals() Expect = { 'SurfTilt': ('num', 'x>=0'), 'SurfAz': ('x>=-180'), 'DHI': ('x>=0'), 'GHI': ('x>=0'), 'SunZen': ('x>=0'), 'SunAz': ('x>=-180') } var = pvl_tools.Parse(Vars, Expect) GHI[GHI < DHI] = DHI GHI[GHI < 1e-06] = 1e-06 COSTT = pvl_tools.cosd(SurfTilt) * pvl_tools.cosd(SunZen) + pvl_tools.sind( SurfTilt) * pvl_tools.sind(SunZen) * pvl_tools.cosd(SunAz - SurfAz) F = 1 - ((DHI / GHI)**2) SkyDiffuse = DHI * ((0.5 * ((1 + pvl_tools.cosd(SurfTilt))))) * ((1 + F * ( ((pvl_tools.sind(SurfTilt / 2))**3)))) * ((1 + F * (((COSTT)**2)) * (( (pvl_tools.sind(SunZen))**3)))) return SkyDiffuse
def pvl_klucher1979(SurfTilt,SurfAz,DHI,GHI,SunZen,SunAz): ''' Determine diffuse irradiance from the sky on a tilted surface using Klucher's 1979 model Klucher's 1979 model determines the diffuse irradiance from the sky (ground reflected irradiance is not included in this algorithm) on a tilted surface using the surface tilt angle, surface azimuth angle, diffuse horizontal irradiance, direct normal irradiance, global horizontal irradiance, extraterrestrial irradiance, sun zenith angle, and sun azimuth angle. Parameters ---------- SurfTilt : float or DataFrame Surface tilt angles in decimal degrees. SurfTilt must be >=0 and <=180. The tilt angle is defined as degrees from horizontal (e.g. surface facing up = 0, surface facing horizon = 90) SurfAz : float or DataFrame Surface azimuth angles in decimal degrees. SurfAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, South=180 East = 90, West = 270). DHI : float or DataFrame diffuse horizontal irradiance in W/m^2. DHI must be >=0. GHI : float or DataFrame Global irradiance in W/m^2. DNI must be >=0. SunZen : float or DataFrame apparent (refraction-corrected) zenith angles in decimal degrees. SunZen must be >=0 and <=180. SunAz : float or DataFrame Sun azimuth angles in decimal degrees. SunAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, East = 90, West = 270). Returns ------- SkyDiffuse : float or DataFrame the diffuse component of the solar radiation on an arbitrarily tilted surface defined by the Klucher model as given in Loutzenhiser et. al (2007) equation 4. SkyDiffuse is the diffuse component ONLY and does not include the ground reflected irradiance or the irradiance due to the beam. SkyDiffuse is a column vector vector with a number of elements equal to the input vector(s). References ---------- [1] Loutzenhiser P.G. et. al. "Empirical validation of models to compute solar irradiance on inclined surfaces for building energy simulation" 2007, Solar Energy vol. 81. pp. 254-267 [2] Klucher, T.M., 1979. Evaluation of models to predict insolation on tilted surfaces. Solar Energy 23 (2), 111-114. See also -------- pvl_ephemeris pvl_extraradiation pvl_isotropicsky pvl_haydavies1980 pvl_perez pvl_reindl1990 pvl_kingdiffuse ''' Vars=locals() Expect={'SurfTilt':('num','x>=0'), 'SurfAz':('x>=-180'), 'DHI':('x>=0'), 'GHI':('x>=0'), 'SunZen':('x>=0'), 'SunAz':('x>=-180') } var=pvl_tools.Parse(Vars,Expect) GHI[GHI < DHI]=DHI GHI[GHI < 1e-06]=1e-06 COSTT=pvl_tools.cosd(SurfTilt)*pvl_tools.cosd(SunZen) + pvl_tools.sind(SurfTilt)*pvl_tools.sind(SunZen)*pvl_tools.cosd(SunAz - SurfAz) F=1 - ((DHI / GHI) ** 2) SkyDiffuse=DHI*((0.5*((1 + pvl_tools.cosd(SurfTilt)))))*((1 + F*(((pvl_tools.sind(SurfTilt / 2)) ** 3))))*((1 + F*(((COSTT) ** 2))*(((pvl_tools.sind(SunZen)) ** 3)))) return SkyDiffuse
def pvl_perez(SurfTilt, SurfAz, DHI, DNI, HExtra, SunZen, SunAz, AM,modelt='allsitescomposite1990'): ''' Determine diffuse irradiance from the sky on a tilted surface using one of the Perez models Perez models determine the diffuse irradiance from the sky (ground reflected irradiance is not included in this algorithm) on a tilted surface using the surface tilt angle, surface azimuth angle, diffuse horizontal irradiance, direct normal irradiance, extraterrestrial irradiance, sun zenith angle, sun azimuth angle, and relative (not pressure-corrected) airmass. Optionally a selector may be used to use any of Perez's model coefficient sets. Parameters ---------- SurfTilt : float or DataFrame Surface tilt angles in decimal degrees. SurfTilt must be >=0 and <=180. The tilt angle is defined as degrees from horizontal (e.g. surface facing up = 0, surface facing horizon = 90) SurfAz : float or DataFrame Surface azimuth angles in decimal degrees. SurfAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, South=180 East = 90, West = 270). DHI : float or DataFrame diffuse horizontal irradiance in W/m^2. DHI must be >=0. DNI : float or DataFrame direct normal irradiance in W/m^2. DNI must be >=0. HExtra : float or DataFrame extraterrestrial normal irradiance in W/m^2. HExtra must be >=0. SunZen : float or DataFrame apparent (refraction-corrected) zenith angles in decimal degrees. SunZen must be >=0 and <=180. SunAz : float or DataFrame Sun azimuth angles in decimal degrees. SunAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, East = 90, West = 270). AM : float or DataFrame relative (not pressure-corrected) airmass values. If AM is a DataFrame it must be of the same size as all other DataFrame inputs. AM must be >=0 (careful using the 1/sec(z) model of AM generation) Other Parameters ---------------- model : string (optional, default='allsitescomposite1990') a character string which selects the desired set of Perez coefficients. If model is not provided as an input, the default, '1990' will be used. All possible model selections are: * '1990' * 'allsitescomposite1990' (same as '1990') * 'allsitescomposite1988' * 'sandiacomposite1988' * 'usacomposite1988' * 'france1988' * 'phoenix1988' * 'elmonte1988' * 'osage1988' * 'albuquerque1988' * 'capecanaveral1988' * 'albany1988' Returns -------- SkyDiffuse : float or DataFrame the diffuse component of the solar radiation on an arbitrarily tilted surface defined by the Perez model as given in reference [3]. SkyDiffuse is the diffuse component ONLY and does not include the ground reflected irradiance or the irradiance due to the beam. References ---------- [1] Loutzenhiser P.G. et. al. "Empirical validation of models to compute solar irradiance on inclined surfaces for building energy simulation" 2007, Solar Energy vol. 81. pp. 254-267 [2] Perez, R., Seals, R., Ineichen, P., Stewart, R., Menicucci, D., 1987. A new simplified version of the Perez diffuse irradiance model for tilted surfaces. Solar Energy 39(3), 221-232. [3] Perez, R., Ineichen, P., Seals, R., Michalsky, J., Stewart, R., 1990. Modeling daylight availability and irradiance components from direct and global irradiance. Solar Energy 44 (5), 271-289. [4] Perez, R. et. al 1988. "The Development and Verification of the Perez Diffuse Radiation Model". SAND88-7030 See also -------- pvl_ephemeris pvl_extraradiation pvl_isotropicsky pvl_haydavies1980 pvl_reindl1990 pvl_klucher1979 pvl_kingdiffuse pvl_relativeairmass ''' Vars=locals() Expect={'SurfTilt':('num','x>=0'), 'SurfAz':('x>=-180'), 'DHI':('x>=0'), 'DNI':('x>=0'), 'HExtra':('x>=0'), 'SunZen':('x>=0'), 'SunAz':('x>=-180'), 'AM':('x>=0'), 'modelt': ('default','default=allsitescomposite1990')} var=pvl_tools.Parse(Vars,Expect) kappa = 1.041 #for SunZen in radians z = var.SunZen*np.pi/180# # convert to radians Dhfilter = var.DHI > 0 e = ((var.DHI[Dhfilter] + var.DNI[Dhfilter])/var.DHI[Dhfilter]+kappa*z[Dhfilter]**3)/(1+kappa*z[Dhfilter]**3).reindex_like(var.SunZen) ebin = pd.Series(np.zeros(var.DHI.shape[0]),index=e.index) # Select which bin e falls into ebin[(e<1.065)]= 1 ebin[(e>=1.065) & (e<1.23)]= 2 ebin[(e>=1.23) & (e<1.5)]= 3 ebin[(e>=1.5) & (e<1.95)]= 4 ebin[(e>=1.95) & (e<2.8)]= 5 ebin[(e>=2.8) & (e<4.5)]= 6 ebin[(e>=4.5) & (e<6.2)]= 7 ebin[e>=6.2] = 8 ebinfilter=ebin>0 ebin=ebin-1 #correct for 0 indexing ebin[ebinfilter==False]=np.NaN ebin=ebin.dropna().astype(int) # This is added because in cases where the sun is below the horizon # (var.SunZen > 90) but there is still diffuse horizontal light (var.DHI>0), it is # possible that the airmass (var.AM) could be NaN, which messes up later # calculations. Instead, if the sun is down, and there is still var.DHI, we set # the airmass to the airmass value on the horizon (approximately 37-38). #var.AM(var.SunZen >=90 & var.DHI >0) = 37; var.HExtra[var.HExtra==0]=.00000001 #very hacky, fix this delt = var.DHI*var.AM/var.HExtra # # The various possible sets of Perez coefficients are contained # in a subfunction to clean up the code. F1c,F2c = GetPerezCoefficients(var.modelt) F1= F1c[ebin,0] + F1c[ebin,1]*delt[ebinfilter] + F1c[ebin,2]*z[ebinfilter] F1[F1<0]=0; F1=F1.astype(float) F2= F2c[ebin,0] + F2c[ebin,1]*delt[ebinfilter] + F2c[ebin,2]*z[ebinfilter] F2[F2<0]=0 F2=F2.astype(float) A = pvl_tools.cosd(var.SurfTilt)*pvl_tools.cosd(var.SunZen) + pvl_tools.sind(var.SurfTilt)*pvl_tools.sind(var.SunZen)*pvl_tools.cosd(var.SunAz-var.SurfAz); #removed +180 from azimuth modifier: Rob Andrews October 19th 2012 A[A < 0] = 0 B = pvl_tools.cosd(var.SunZen); B[B < pvl_tools.cosd(85)] = pvl_tools.cosd(85) #Calculate Diffuse POA from sky dome #SkyDiffuse = pd.Series(np.zeros(var.DHI.shape[0]),index=data.index) SkyDiffuse = var.DHI[ebinfilter]*( 0.5* (1-F1[ebinfilter])*(1+pvl_tools.cosd(var.SurfTilt))+F1[ebinfilter] * A[ebinfilter]/ B[ebinfilter] + F2[ebinfilter]* pvl_tools.sind(var.SurfTilt)) SkyDiffuse[SkyDiffuse <= 0]= 0 return pd.DataFrame({'In_Plane_SkyDiffuse':SkyDiffuse})
def pvl_reindl1990(SurfTilt, SurfAz, DHI, DNI, GHI, HExtra, SunZen, SunAz): ''' Determine diffuse irradiance from the sky on a tilted surface using Reindl's 1990 model Reindl's 1990 model determines the diffuse irradiance from the sky (ground reflected irradiance is not included in this algorithm) on a tilted surface using the surface tilt angle, surface azimuth angle, diffuse horizontal irradiance, direct normal irradiance, global horizontal irradiance, extraterrestrial irradiance, sun zenith angle, and sun azimuth angle. Parameters ---------- SurfTilt : DataFrame Surface tilt angles in decimal degrees. SurfTilt must be >=0 and <=180. The tilt angle is defined as degrees from horizontal (e.g. surface facing up = 0, surface facing horizon = 90) SurfAz : DataFrame Surface azimuth angles in decimal degrees. SurfAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, South=180 East = 90, West = 270). DHI : DataFrame diffuse horizontal irradiance in W/m^2. DHI must be >=0. DNI : DataFrame direct normal irradiance in W/m^2. DNI must be >=0. GHI: DataFrame Global irradiance in W/m^2. GHI must be >=0. HExtra : DataFrame extraterrestrial normal irradiance in W/m^2. HExtra must be >=0. SunZen : DataFrame apparent (refraction-corrected) zenith angles in decimal degrees. SunZen must be >=0 and <=180. SunAz : DataFrame Sun azimuth angles in decimal degrees. SunAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, East = 90, West = 270). Returns ------- SkyDiffuse : DataFrame the diffuse component of the solar radiation on an arbitrarily tilted surface defined by the Reindl model as given in Loutzenhiser et. al (2007) equation 8. SkyDiffuse is the diffuse component ONLY and does not include the ground reflected irradiance or the irradiance due to the beam. SkyDiffuse is a column vector vector with a number of elements equal to the input vector(s). Notes ----- The POAskydiffuse calculation is generated from the Loutzenhiser et al. (2007) paper, equation 8. Note that I have removed the beam and ground reflectance portion of the equation and this generates ONLY the diffuse radiation from the sky and circumsolar, so the form of the equation varies slightly from equation 8. References ---------- [1] Loutzenhiser P.G. et. al. "Empirical validation of models to compute solar irradiance on inclined surfaces for building energy simulation" 2007, Solar Energy vol. 81. pp. 254-267 [2] Reindl, D.T., Beckmann, W.A., Duffie, J.A., 1990a. Diffuse fraction correlations. Solar Energy 45(1), 1-7. [3] Reindl, D.T., Beckmann, W.A., Duffie, J.A., 1990b. Evaluation of hourly tilted surface radiation models. Solar Energy 45(1), 9-17. See Also --------- pvl_ephemeris pvl_extraradiation pvl_isotropicsky pvl_haydavies1980 pvl_perez pvl_klucher1979 pvl_kingdiffuse ''' Vars = locals() Expect = { 'SurfTilt': ('num', 'x>=0'), 'SurfAz': ('num', 'x>=-180'), 'DHI': ('num', 'x>=0'), 'DNI': ('num', 'x>=0'), 'GHI': ('num', 'x>=0'), 'HExtra': ('num', 'x>=0'), 'SunZen': ('num', 'x>=0'), 'SunAz': ('num', 'x>=-180'), } var = pvl_tools.Parse(Vars, Expect) small = 1e-06 COSTT = pvl_tools.cosd(SurfTilt) * pvl_tools.cosd(SunZen) + pvl_tools.sind( SurfTilt) * pvl_tools.sind(SunZen) * pvl_tools.cosd(SunAz - SurfAz) RB = np.max(COSTT, 0) / np.max(pvl_tools.cosd(SunZen), 0.01745) AI = DNI / HExtra GHI[GHI < small] = small HB = DNI * (pvl_tools.cosd(SunZen)) HB[HB < 0] = 0 GHI[GHI < 0] = 0 F = np.sqrt(HB / GHI) SCUBE = (pvl_tools.sind(SurfTilt * (0.5)))**3 SkyDiffuse = DHI * ((AI * (RB) + (1 - AI) * (0.5) * ((1 + pvl_tools.cosd(SurfTilt))) * ((1 + F * (SCUBE))))) return SkyDiffuse
def pvl_haydavies1980(SurfTilt,SurfAz,DHI,DNI,HExtra,SunZen,SunAz): ''' Determine diffuse irradiance from the sky on a tilted surface using Hay & Davies' 1980 model Hay and Davies' 1980 model determines the diffuse irradiance from the sky (ground reflected irradiance is not included in this algorithm) on a tilted surface using the surface tilt angle, surface azimuth angle, diffuse horizontal irradiance, direct normal irradiance, extraterrestrial irradiance, sun zenith angle, and sun azimuth angle. Parameters ---------- SurfTilt : float or DataFrame Surface tilt angles in decimal degrees. SurfTilt must be >=0 and <=180. The tilt angle is defined as degrees from horizontal (e.g. surface facing up = 0, surface facing horizon = 90) SurfAz : float or DataFrame Surface azimuth angles in decimal degrees. SurfAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, South=180 East = 90, West = 270). DHI : float or DataFrame diffuse horizontal irradiance in W/m^2. DHI must be >=0. DNI : float or DataFrame direct normal irradiance in W/m^2. DNI must be >=0. HExtra : float or DataFrame extraterrestrial normal irradiance in W/m^2. HExtra must be >=0. SunZen : float or DataFrame apparent (refraction-corrected) zenith angles in decimal degrees. SunZen must be >=0 and <=180. SunAz : float or DataFrame Sun azimuth angles in decimal degrees. SunAz must be >=0 and <=360. The Azimuth convention is defined as degrees east of north (e.g. North = 0, East = 90, West = 270). Returns -------- SkyDiffuse : float or DataFrame the diffuse component of the solar radiation on an arbitrarily tilted surface defined by the Perez model as given in reference [3]. SkyDiffuse is the diffuse component ONLY and does not include the ground reflected irradiance or the irradiance due to the beam. References ----------- [1] Loutzenhiser P.G. et. al. "Empirical validation of models to compute solar irradiance on inclined surfaces for building energy simulation" 2007, Solar Energy vol. 81. pp. 254-267 [2] Hay, J.E., Davies, J.A., 1980. Calculations of the solar radiation incident on an inclined surface. In: Hay, J.E., Won, T.K. (Eds.), Proc. of First Canadian Solar Radiation Data Workshop, 59. Ministry of Supply and Services, Canada. See Also -------- pvl_ephemeris pvl_extraradiation pvl_isotropicsky pvl_reindl1990 pvl_perez pvl_klucher1979 pvl_kingdiffuse pvl_spa ''' Vars=locals() Expect={'SurfTilt':('num','x>=0'), 'SurfAz':('x>=-180'), 'DHI':('x>=0'), 'DNI':('x>=0'), 'HExtra':('x>=0'), 'SunZen':('x>=0'), 'SunAz':('x>=-180'), } var=pvl_tools.Parse(Vars,Expect) COSTT=pvl_tools.cosd(SurfTilt)*pvl_tools.cosd(SunZen) + pvl_tools.sind(SurfTilt)*pvl_tools.sind(SunZen)*pvl_tools.cosd(SunAz - SurfAz) RB=np.max(COSTT,0) / np.max(pvl_tools.cosd(SunZen),0.01745) AI=DNI / HExtra SkyDiffuse=DHI*((AI*(RB) + (1 - AI)*(0.5)*((1 + pvl_tools.cosd(SurfTilt))))) return SkyDiffuse
def pvl_physicaliam(K,L,n,theta): ''' Determine the incidence angle modifier using refractive index, glazing thickness, and extinction coefficient pvl_physicaliam calculates the incidence angle modifier as described in De Soto et al. "Improvement and validation of a model for photovoltaic array performance", section 3. The calculation is based upon a physical model of absorbtion and transmission through a cover. Required information includes, incident angle, cover extinction coefficient, cover thickness Note: The authors of this function believe that eqn. 14 in [1] is incorrect. This function uses the following equation in its place: theta_r = arcsin(1/n * sin(theta)) Parameters ---------- K : float The glazing extinction coefficient in units of 1/meters. Reference [1] indicates that a value of 4 is reasonable for "water white" glass. K must be a numeric scalar or vector with all values >=0. If K is a vector, it must be the same size as all other input vectors. L : float The glazing thickness in units of meters. Reference [1] indicates that 0.002 meters (2 mm) is reasonable for most glass-covered PV panels. L must be a numeric scalar or vector with all values >=0. If L is a vector, it must be the same size as all other input vectors. n : float The effective index of refraction (unitless). Reference [1] indicates that a value of 1.526 is acceptable for glass. n must be a numeric scalar or vector with all values >=0. If n is a vector, it must be the same size as all other input vectors. theta :float The angle of incidence between the module normal vector and the sun-beam vector in degrees. Theta must be a numeric scalar or vector. For any values of theta where abs(theta)>90, IAM is set to 0. For any values of theta where -90 < theta < 0, theta is set to abs(theta) and evaluated. A warning will be generated if any(theta<0 or theta>90). Returns ------- IAM : float The incident angle modifier as specified in eqns. 14-16 of [1]. IAM is a column vector with the same number of elements as the largest input vector. References ---------- [1] W. De Soto et al., "Improvement and validation of a model for photovoltaic array performance", Solar Energy, vol 80, pp. 78-88, 2006. [2] Duffie, John A. & Beckman, William A.. (2006). Solar Engineering of Thermal Processes, third edition. [Books24x7 version] Available from http://common.books24x7.com/toc.aspx?bookid=17160. See Also -------- pvl_getaoi pvl_ephemeris pvl_spa pvl_ashraeiam ''' Vars=locals() Expect={'K':'x >= 0', 'L':'x >= 0', 'n':'x >= 0', 'theta':'num'} var=pvl_tools.Parse(Vars,Expect) if any((var.theta < 0) | (var.theta >= 90)): print('Input incident angles <0 or >=90 detected For input angles with absolute value greater than 90, the ' + 'modifier is set to 0. For input angles between -90 and 0, the ' + 'angle is changed to its absolute value and evaluated.') var.theta[(var.theta < 0) | (var.theta >= 90)]=abs((var.theta < 0) | (var.theta >= 90)) thetar_deg=pvl_tools.asind(1.0 / n*(pvl_tools.sind(theta))) tau=np.exp(- 1.0 * (K*(L) / pvl_tools.cosd(thetar_deg)))*((1 - 0.5*((((pvl_tools.sind(thetar_deg - theta)) ** 2) / ((pvl_tools.sind(thetar_deg + theta)) ** 2) + ((pvl_tools.tand(thetar_deg - theta)) ** 2) / ((pvl_tools.tand(thetar_deg + theta)) ** 2))))) zeroang=1e-06 thetar_deg0=pvl_tools.asind(1.0 / n*(pvl_tools.sind(zeroang))) tau0=np.exp(- 1.0 * (K*(L) / pvl_tools.cosd(thetar_deg0)))*((1 - 0.5*((((pvl_tools.sind(thetar_deg0 - zeroang)) ** 2) / ((pvl_tools.sind(thetar_deg0 + zeroang)) ** 2) + ((pvl_tools.tand(thetar_deg0 - zeroang)) ** 2) / ((pvl_tools.tand(thetar_deg0 + zeroang)) ** 2))))) IAM=tau / tau0 IAM[theta == 0]=1 IAM[abs(theta) > 90 | (IAM < 0)]=0 return IAM