@@ -281,7 +281,8 @@ def get_total_irradiance(surface_tilt, surface_azimuth,
281281 dni , ghi , dhi , dni_extra = None , airmass = None ,
282282 albedo = 0.25 , surface_type = None ,
283283 model = 'isotropic' ,
284- model_perez = 'allsitescomposite1990' ):
284+ model_perez = 'allsitescomposite1990' ,
285+ diffuse_components = False ):
285286 r"""
286287 Determine total in-plane irradiance and its beam, sky diffuse and ground
287288 reflected components, using the specified sky diffuse irradiance model.
@@ -332,10 +333,15 @@ def get_total_irradiance(surface_tilt, surface_azimuth,
332333 ``'perez-driesse'``.
333334 model_perez : str, default 'allsitescomposite1990'
334335 Used only if ``model='perez'``. See :py:func:`~pvlib.irradiance.perez`.
336+ diffuse_components : bool, default False
337+ If `True`, returns values for the different diffuse irradiance
338+ components available from the selected model
339+ (e.g., isotropic, circumsolar, horizon brightening).
340+ If `False`, only the total diffuse irradiance is returned.
335341
336342 Returns
337343 -------
338- total_irrad : OrderedDict or DataFrame
344+ total_irrad : Dict or DataFrame
339345 Contains keys/columns ``'poa_global', 'poa_direct', 'poa_diffuse',
340346 'poa_sky_diffuse', 'poa_ground_diffuse'``. [Wm⁻²]
341347
@@ -353,7 +359,7 @@ def get_total_irradiance(surface_tilt, surface_azimuth,
353359 poa_sky_diffuse = get_sky_diffuse (
354360 surface_tilt , surface_azimuth , solar_zenith , solar_azimuth ,
355361 dni , ghi , dhi , dni_extra = dni_extra , airmass = airmass , model = model ,
356- model_perez = model_perez )
362+ model_perez = model_perez , return_components = diffuse_components )
357363
358364 poa_ground_diffuse = get_ground_diffuse (surface_tilt , ghi , albedo ,
359365 surface_type )
@@ -366,7 +372,8 @@ def get_sky_diffuse(surface_tilt, surface_azimuth,
366372 solar_zenith , solar_azimuth ,
367373 dni , ghi , dhi , dni_extra = None , airmass = None ,
368374 model = 'isotropic' ,
369- model_perez = 'allsitescomposite1990' ):
375+ model_perez = 'allsitescomposite1990' ,
376+ return_components = False ):
370377 r"""
371378 Determine in-plane sky diffuse irradiance component
372379 using the specified sky diffuse irradiance model.
@@ -408,11 +415,20 @@ def get_sky_diffuse(surface_tilt, surface_azimuth,
408415 ``'perez-driesse'``.
409416 model_perez : str, default 'allsitescomposite1990'
410417 Used only if ``model='perez'``. See :py:func:`~pvlib.irradiance.perez`.
418+ return_components : bool, default False
419+ If `True`, returns values for the different diffuse irradiance
420+ components available from the selected model
421+ (e.g., isotropic, circumsolar, horizon brightening).
422+ If `False`, only the total diffuse irradiance is returned.
411423
412424 Returns
413425 -------
414- poa_sky_diffuse : numeric
415- Sky diffuse irradiance in the plane of array. [Wm⁻²]
426+ numeric, Dict, or DataFrame
427+ Return type controlled by ``return_components`` argument.
428+ If `False`, total sky diffuse irradiance in the plane of array
429+ is returned (numeric). [Wm⁻²]
430+ If `True`, the different diffuse components are returned
431+ (Dict or DataFrame). [Wm⁻²]
416432
417433 Raises
418434 ------
@@ -443,28 +459,32 @@ def get_sky_diffuse(surface_tilt, surface_azimuth,
443459 raise ValueError (f'dni_extra is required for model { model } ' )
444460
445461 if model == 'isotropic' :
446- sky = isotropic (surface_tilt , dhi )
462+ sky = isotropic (surface_tilt , dhi , return_components = return_components )
447463 elif model == 'klucher' :
448464 sky = klucher (surface_tilt , surface_azimuth , dhi , ghi ,
449- solar_zenith , solar_azimuth )
465+ solar_zenith , solar_azimuth ,
466+ return_components = return_components )
450467 elif model == 'haydavies' :
451468 sky = haydavies (surface_tilt , surface_azimuth , dhi , dni , dni_extra ,
452- solar_zenith , solar_azimuth )
469+ solar_zenith , solar_azimuth ,
470+ return_components = return_components )
453471 elif model == 'reindl' :
454472 sky = reindl (surface_tilt , surface_azimuth , dhi , dni , ghi , dni_extra ,
455- solar_zenith , solar_azimuth )
473+ solar_zenith , solar_azimuth ,
474+ return_components = return_components )
456475 elif model == 'king' :
457476 sky = king (surface_tilt , dhi , ghi , solar_zenith )
458477 elif model == 'perez' :
459478 if airmass is None :
460479 airmass = atmosphere .get_relative_airmass (solar_zenith )
461480 sky = perez (surface_tilt , surface_azimuth , dhi , dni , dni_extra ,
462481 solar_zenith , solar_azimuth , airmass ,
463- model = model_perez )
482+ model = model_perez , return_components = return_components )
464483 elif model == 'perez-driesse' :
465484 # perez_driesse will calculate its own airmass if needed
466485 sky = perez_driesse (surface_tilt , surface_azimuth , dhi , dni , dni_extra ,
467- solar_zenith , solar_azimuth , airmass )
486+ solar_zenith , solar_azimuth , airmass ,
487+ return_components = return_components )
468488 else :
469489 raise ValueError (f'invalid model selection { model } ' )
470490
@@ -488,7 +508,7 @@ def poa_components(aoi, dni, poa_sky_diffuse, poa_ground_diffuse):
488508 Direct normal irradiance, as measured from a TMY file or
489509 calculated with a clearsky model. See :term:`dni`. [Wm⁻²]
490510
491- poa_sky_diffuse : numeric
511+ poa_sky_diffuse : numeric, Dict or DataFrame
492512 Diffuse irradiance in the plane of the modules, as
493513 calculated by a diffuse irradiance translation function. [Wm⁻²]
494514
@@ -499,7 +519,7 @@ def poa_components(aoi, dni, poa_sky_diffuse, poa_ground_diffuse):
499519
500520 Returns
501521 -------
502- irrads : OrderedDict or DataFrame
522+ irrads : Dict or DataFrame
503523 Contains the following keys:
504524
505525 * ``poa_global`` : Total in-plane irradiance. [Wm⁻²]
@@ -508,22 +528,38 @@ def poa_components(aoi, dni, poa_sky_diffuse, poa_ground_diffuse):
508528 * ``poa_sky_diffuse`` : In-plane diffuse irradiance from sky. [Wm⁻²]
509529 * ``poa_ground_diffuse`` : In-plane diffuse irradiance from ground.
510530 [Wm⁻²]
531+
532+ If ``poa_sky_diffuse`` is a Dict or DataFrame, ``irrads`` will
533+ contain additional keys for each of the diffuse components returned by
534+ the selected diffuse irradiance model.
511535
512536 Notes
513537 ------
514538 Negative beam irradiation due to AOI > 90° or AOI < 0° is set to zero.
515539 '''
516540
541+ if isinstance (poa_sky_diffuse , dict ):
542+ sky_components = poa_sky_diffuse .copy ()
543+ total_poa_sky_diffuse = sky_components .pop ('poa_sky_diffuse' )
544+ elif isinstance (poa_sky_diffuse , pd .DataFrame ):
545+ sky_components = poa_sky_diffuse .to_dict (orient = 'series' )
546+ total_poa_sky_diffuse = sky_components .pop ('poa_sky_diffuse' )
547+ else :
548+ sky_components = {}
549+ total_poa_sky_diffuse = poa_sky_diffuse
550+
517551 poa_direct = np .maximum (dni * np .cos (np .radians (aoi )), 0 )
518- poa_diffuse = poa_sky_diffuse + poa_ground_diffuse
552+ poa_diffuse = total_poa_sky_diffuse + poa_ground_diffuse
519553 poa_global = poa_direct + poa_diffuse
520554
521- irrads = OrderedDict ()
522- irrads ['poa_global' ] = poa_global
523- irrads ['poa_direct' ] = poa_direct
524- irrads ['poa_diffuse' ] = poa_diffuse
525- irrads ['poa_sky_diffuse' ] = poa_sky_diffuse
526- irrads ['poa_ground_diffuse' ] = poa_ground_diffuse
555+ irrads = {
556+ 'poa_global' : poa_global ,
557+ 'poa_direct' : poa_direct ,
558+ 'poa_diffuse' : poa_diffuse ,
559+ 'poa_sky_diffuse' : total_poa_sky_diffuse ,
560+ 'poa_ground_diffuse' : poa_ground_diffuse ,
561+ ** sky_components
562+ }
527563
528564 if isinstance (poa_direct , pd .Series ):
529565 irrads = pd .DataFrame (irrads )
0 commit comments