Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
xy_center : tuple of float
x and y coordinates of the PV row center point (invariant)
width : float
width of the PV rows [m]
rotation : np.ndarray
Timeseries rotation values of the PV row [deg]
Returns
-------
coords: :py:class:`~pvfactors.geometry.timeseries.TsLineCoords`
Timeseries coordinates of full PV row
"""
x_center, y_center = xy_center
radius = width / 2.
# Calculate coords
x1 = radius * cosd(rotation + 180.) + x_center
y1 = radius * sind(rotation + 180.) + y_center
x2 = radius * cosd(rotation) + x_center
y2 = radius * sind(rotation) + y_center
coords = TsLineCoords.from_array(np.array([[x1, y1], [x2, y2]]))
return coords
"""
kt_prime_gte_90 = _gti_dirint_gte_90_kt_prime(aoi, solar_zenith,
solar_azimuth, times,
kt_prime)
I0 = get_extra_radiation(times, 1370, 'spencer')
airmass = atmosphere.get_relative_airmass(solar_zenith, model='kasten1966')
airmass = atmosphere.get_absolute_airmass(airmass, pressure)
kt = kt_prime_gte_90 * _kt_kt_prime_factor(airmass)
disc_dni = np.maximum(_disc_kn(kt, airmass)[0] * I0, 0)
dni_gte_90 = _dirint_from_dni_ktprime(disc_dni, kt_prime, solar_zenith,
False, temp_dew)
dni_gte_90_proj = dni_gte_90 * tools.cosd(solar_zenith)
cos_surface_tilt = tools.cosd(surface_tilt)
# isotropic sky plus ground diffuse
dhi_gte_90 = (
(2 * poa_global - dni_gte_90_proj * albedo * (1 - cos_surface_tilt)) /
(1 + cos_surface_tilt + albedo * (1 - cos_surface_tilt)))
ghi_gte_90 = dni_gte_90_proj + dhi_gte_90
return ghi_gte_90, dni_gte_90, dhi_gte_90
df_inputs.solar_azimuth,
am,
return_components=True)
# Calculate Perez view factors:
a = aoi_projection(df_inputs.array_tilt, df_inputs.array_azimuth,
df_inputs.solar_zenith, df_inputs.solar_azimuth)
a = np.maximum(a, 0)
b = cosd(df_inputs.solar_zenith)
b = np.maximum(b, cosd(85))
vf_perez = pd.DataFrame(
np.array([
sind(df_inputs.array_tilt),
a / b,
(1. + cosd(df_inputs.array_tilt)) / 2.
]).T,
index=df_inputs.index,
columns=['vf_horizon', 'vf_circumsolar', 'vf_isotropic']
)
# Calculate diffuse luminance
luminance = pd.DataFrame(
np.array([
components['horizon'] / vf_perez['vf_horizon'],
components['circumsolar'] / vf_perez['vf_circumsolar'],
components['isotropic'] / vf_perez['vf_isotropic']
]).T,
index=df_inputs.index,
columns=['luminance_horizon', 'luminance_circumsolar',
'luminance_isotropic']
)
to the earth's surface [degrees].
solar_zenith : float
sun's zenith angle
solar_azimuth : float
sun's azimuth angle
"""
# Projection of 3d solar vector onto the cross section of the systems:
# which is the 2d plane we are considering: needed to calculate shadows
# Remember that the 2D plane is such that the direction of the torque
# tube vector goes out of (and normal to) the 2D plane, such that
# positive tilt angles will have the PV surfaces tilted to the LEFT
# and vice versa
solar_2d_vector = [
# a drawing really helps understand the following
- sind(solar_zenith) * cosd(surface_azimuth - solar_azimuth),
cosd(solar_zenith)]
# for a line of equation a*x + b*y + c = 0, we calculate intercept c
# and can derive x_0 such that crosses with line y = 0: x_0 = - c / a
list_x_shadows = []
list_shadow_line_pvarrays = []
# TODO: speed improvement can be made by translating the shadow
# boundaries and removing most of the for loop calculation
pvrow = None
for idx_pvrow, pvrow in enumerate(self.pvrows):
self.has_direct_shading = False
x1_shadow, x2_shadow = pvrow.get_shadow_bounds(solar_2d_vector)
list_x_shadows.append((x1_shadow, x2_shadow))
# Check if there is direct shading: if yes, the shadows will
# be grouped into one continuous shadow
if idx_pvrow == 1:
if list_x_shadows[0][1] > list_x_shadows[1][0]:
nans = np.array([np.nan, np.nan, np.nan])
F1c = np.vstack((F1c, nans))
F2c = np.vstack((F2c, nans))
F1 = (F1c[ebin, 0] + F1c[ebin, 1] * delta + F1c[ebin, 2] * z)
F1 = np.maximum(F1, 0)
F2 = (F2c[ebin, 0] + F2c[ebin, 1] * delta + F2c[ebin, 2] * z)
F2 = np.maximum(F2, 0)
A = aoi_projection(surface_tilt, surface_azimuth,
solar_zenith, solar_azimuth)
A = np.maximum(A, 0)
B = tools.cosd(solar_zenith)
B = np.maximum(B, tools.cosd(85))
# Calculate Diffuse POA from sky dome
term1 = 0.5 * (1 - F1) * (1 + tools.cosd(surface_tilt))
term2 = F1 * A / B
term3 = F2 * tools.sind(surface_tilt)
sky_diffuse = np.maximum(dhi * (term1 + term2 + term3), 0)
# we've preserved the input type until now, so don't ruin it!
if isinstance(sky_diffuse, pd.Series):
sky_diffuse[np.isnan(airmass)] = 0
else:
sky_diffuse = np.where(np.isnan(airmass), 0, sky_diffuse)
if return_components:
diffuse_components = OrderedDict()
"Results can be too high or negative.\n" +
"Help to improve this function on github:\n" +
"https://github.com/pvlib/pvlib-python \n")
if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns:
clearsky = self.location.get_clearsky(
self.weather.index, solar_position=self.solar_position)
self.weather.loc[:, 'dni'] = pvlib.irradiance.dni(
self.weather.loc[:, 'ghi'], self.weather.loc[:, 'dhi'],
self.solar_position.zenith,
clearsky_dni=clearsky['dni'],
clearsky_tolerance=1.1)
elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns:
warnings.warn(wrn_txt, UserWarning)
self.weather.loc[:, 'ghi'] = (
self.weather.dni * tools.cosd(self.solar_position.zenith) +
self.weather.dhi)
elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns:
warnings.warn(wrn_txt, UserWarning)
self.weather.loc[:, 'dhi'] = (
self.weather.ghi - self.weather.dni *
tools.cosd(self.solar_position.zenith))
return self
self.horizon['ground'] = np.zeros(n)
# PV row surfaces
front_is_illum = aoi_front_pvrow <= 90
# direct
self.direct['front_illum_pvrow'] = np.where(
front_is_illum, DNI * cosd(aoi_front_pvrow), 0.)
self.direct['front_shaded_pvrow'] = (
# Direct light through PV modules spacing
self.direct['front_illum_pvrow'] * self.module_spacing_ratio
# Direct light through PV modules, by transparency
+ self.direct['front_illum_pvrow']
* (1. - self.module_spacing_ratio)
* self.module_transparency)
self.direct['back_illum_pvrow'] = np.where(
~front_is_illum, DNI * cosd(aoi_back_pvrow), 0.)
self.direct['back_shaded_pvrow'] = (
# Direct light through PV modules spacing
self.direct['back_illum_pvrow'] * self.module_spacing_ratio
# Direct light through PV modules, by transparency
+ self.direct['back_illum_pvrow']
* (1. - self.module_spacing_ratio)
* self.module_transparency)
# circumsolar
self.circumsolar['front_illum_pvrow'] = np.where(
front_is_illum, poa_circumsolar_front, 0.)
self.circumsolar['front_shaded_pvrow'] = (
# Direct light through PV modules spacing
self.circumsolar['front_illum_pvrow'] * self.module_spacing_ratio
# Direct light through PV modules, by transparency
+ self.circumsolar['front_illum_pvrow']
* (1. - self.module_spacing_ratio)
Returns
-------
diffuse : numeric
The sky diffuse component of the solar radiation.
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] Hottel, H.C., Woertz, B.B., 1942. Evaluation of flat-plate solar
heat collector. Trans. ASME 64, 91.
'''
sky_diffuse = dhi * (1 + tools.cosd(surface_tilt)) * 0.5
return sky_diffuse
def _QCRad_ub(dni_extra, sza, lim):
cosd_sza = cosd(sza)
cosd_sza[cosd_sza < 0] = 0
return lim['mult'] * dni_extra * cosd_sza**lim['exp'] + lim['min']
Here we're using angles measured from the horizontal
Parameters
----------
aoi_1 : np.ndarray
Lower angles defining the infinite band
aoi_2 : np.ndarray
Higher angles defining the infinite band
Returns
-------
np.ndarray
View factors from infinitesimal surface to infinite strip
"""
return 0.5 * np.abs(cosd(aoi_1) - cosd(aoi_2))