.. _radiation_conversion: ############################# Radiation Conversion Modeling ############################# This page documents how SunPeek converts available radiation measurements into the tilted irradiance components used by collector arrays. The current implementation focuses on the practically important case where only one measured global irradiance sensor is available in the plane of a radiation sensor. In SunPeek this sensor is mapped to the array input slot ``in_global``. Terminology =========== SunPeek uses the following radiation quantities: .. list-table:: :header-rows: 1 :widths: 20 25 55 * - Symbol / slot - Name - Meaning * - ``in_global`` - measured global irradiance - Hemispherical irradiance measured in the plane of the mapped sensor. * - ``in_diffuse`` - measured diffuse irradiance - Diffuse irradiance measured in the plane of the mapped sensor. * - ``in_beam`` - measured beam irradiance - Beam irradiance measured in the plane of the mapped sensor. * - ``in_dni`` - measured direct normal irradiance - Direct irradiance measure normal to the sun beam. * - ``rd_gti`` - global tilted irradiance - Global irradiance in the plane of collector array (POA). * - ``rd_bti`` - beam tilted irradiance - Direct/beam component in the POA. * - ``rd_dti`` - diffuse tilted irradiance - Diffuse component in the POA. * - ``GHI`` - global horizontal irradiance - Global irradiance on the horizontal plane. * - ``DHI`` - diffuse horizontal irradiance - Diffuse irradiance on the horizontal plane. * - ``DNI`` - direct normal irradiance - Direct irradiance measure normal to the sun beam. * - ``AOI`` - angle of incidence - Angle between the sun beam and the surface normal. The measured ``in_global`` value is not automatically the same as ``rd_gti``. They are identical only if the radiation sensor plane and the collector array plane have the same tilt and azimuth. Input slots and supported strategy ================================== Array radiation conversion uses four standard input slots: .. code-block:: text in_global, in_beam, in_diffuse, in_dni The currently implemented radiation-model strategy handles the input pattern: .. code-block:: text 1000 = in_global only This means: - ``in_global`` is available - ``in_beam`` is not available - ``in_diffuse`` is not available - ``in_dni`` is not available For this case SunPeek uses reverse transposition to estimate horizontal irradiance components from the measured global irradiance in the sensor plane. Those horizontal components are then transposed into the collector array plane. DNI-only input, i.e. input pattern ``0001``, is not sufficient to calculate the full set of tilted components. DNI defines the direct normal beam component, but it does not define the diffuse irradiance contribution. Therefore SunPeek does not calculate ``rd_gti``, ``rd_bti`` and ``rd_dti`` from ``in_dni`` alone. Implemented model chain ======================= The implemented model chain is: .. code-block:: text measured global irradiance in sensor plane -> reverse transposition -> GHI, DNI, DHI -> forward transposition -> rd_gti, rd_bti, rd_dti in collector array plane In code this is implemented in: - :mod:`sunpeek.core_methods.virtuals.radiation` - :class:`sunpeek.core_methods.virtuals.calculations.TiltedIrradiances` The core model functions live in :mod:`sunpeek.core_methods.virtuals.radiation`: .. code-block:: python get_horizontal_from_poa_global(...) get_poa_from_horizontal(...) get_array_irradiance_from_measured_poa_global(...) The virtual sensor strategy in :class:`~sunpeek.core_methods.virtuals.calculations.StrategyTiltedIrradiance_reverse_transposition` only orchestrates sensor access, orientation handling, and conversion of the numeric model result back to unit-aware virtual sensor series. Step 1: reverse transposition ============================= The first step estimates horizontal irradiance components from the measured global plane-of-array irradiance: .. code-block:: text measured GTI_sensor -> GHI, DNI, DHI SunPeek uses :func:`pvlib.irradiance.gti_dirint` for this step. Required inputs are: - measured global irradiance in the sensor plane - sensor tilt and azimuth - solar zenith and azimuth - timestamp index - ground albedo (default=0.25 (pvlib default value)) The AOI for the radiation sensor plane is calculated with :func:`pvlib.irradiance.aoi`. The implementation uses the ``perez-driesse`` model option. The ``delta_kt_prime`` stability index is used only when the time index is regular and sufficiently short-spaced. For very short, irregular, or coarse time series, SunPeek disables it so virtual sensor calculations can still run on small data windows. Step 2: forward transposition ============================= The second step transposes the estimated horizontal components into the collector array plane: .. code-block:: text GHI, DNI, DHI -> POA global, POA direct, POA diffuse SunPeek uses :func:`pvlib.irradiance.get_total_irradiance` with the ``perez-driesse`` model for this step. The returned plane-of-array components are mapped to SunPeek virtual sensors: .. code-block:: text poa_global -> rd_gti poa_direct -> rd_bti poa_diffuse -> rd_dti Same-plane preservation ======================= If the radiation sensor plane and the collector array plane have the same orientation, SunPeek preserves the measured global irradiance: .. math:: rd\_gti = in\_global The beam component is still calculated from the modeled horizontal components. The diffuse component is then calculated by closure: .. math:: rd\_dti = rd\_gti - rd\_bti This keeps the modeled output consistent with the measured global irradiance in the collector plane. In this same-plane case, the following relationship is enforced: .. math:: rd\_gti = rd\_bti + rd\_dti If the sensor plane and collector plane differ, SunPeek uses the forward transposed ``poa_global`` and ``poa_diffuse`` values. Orientation metadata ==================== Reverse transposition requires orientation metadata for the measured ``in_global`` sensor: - ``tilt`` - ``azim`` For fixed-mounted arrays, the collector array orientation is taken from the array mounting configuration. Single-axis tracking arrays are not supported by the current reverse transposition strategy. For tracking arrays, the sensor plane and collector plane can change relative to each other over time, and additional model design is required. Validity limits =============== Reverse transposition from measured GTI is less reliable for high incidence angles. The pvlib documentation for :func:`pvlib.irradiance.gti_dirint` notes poor model performance for approximately: .. code-block:: text AOI > 80 deg AND POA irradiance > 200 W/m² The AOI limit is consistent with Marion's GTI-DIRINT validation discussion, where increased errors are reported for incidence angles in the 80--90 deg range. The exact 200 W/m² irradiance threshold is taken from the pvlib implementation documentation and should therefore be treated as a pvlib-recommended practical validity flag rather than a separately derived threshold from Marion (2015). SunPeek currently uses these limits in validation and diagnostic comparisons. Validation comparisons keep only timestamps with ``AOI <= 80 deg`` or ``POA irradiance <= 200 W/m²``. Equivalently, they exclude timestamps where both limits are exceeded at the same time. The core model does not yet mask or remove calculated values inside this documented poor-performance region. A future implementation may expose a helper or virtual sensor such as: .. code-block:: text rd_conversion_valid or a function equivalent to: .. code-block:: python valid = (aoi <= 80) | (poa_global <= 200) Validation approach =================== The implementation is validated with FHW operational demo data. The validation uses measured ``rd_gti`` as the only model input and keeps measured ``rd_bti``, ``rd_dti`` and ``rd_dni`` as independent references. For the yearly FHW validation, comparisons are filtered to timestamps with: .. code-block:: text reference AOI <= 80 deg OR reference GTI <= 200 W/m² The test suite checks: - successful calculation from ``in_global`` only; - explicit feedthrough behavior; - same-plane GTI preservation; - closure ``rd_gti = rd_bti + rd_dti``; - yearly agreement with measured BTI and DTI; - direct helper behavior in :mod:`sunpeek.core_methods.virtuals.radiation`. Measured DNI is available in the FHW data and can be used to validate the intermediate DNI estimated by reverse transposition. This is useful because DNI is an internal model result that strongly affects the calculated beam tilted irradiance. It should be treated as an additional model validation, not as an input for the ``in_global``-only strategy. Example validation plots ------------------------ The following figures show an example validation window from the FHW yearly demo data. The model uses only measured ``rd_gti`` as input. The measured ``rd_bti`` and ``rd_dti`` sensors are shown only as independent references. .. figure:: _static/radiation_conversion/radiation_validation_june.png :alt: Radiation conversion validation for a June time window :align: center :width: 100% Modeled and measured tilted radiation components for a selected June time window. The plot compares modeled BTI and DTI against the corresponding measured FHW reference sensors. .. figure:: _static/radiation_conversion/radiation_validation_june_errors.png :alt: Radiation conversion validation errors for a June time window :align: center :width: 100% Error time series for the same June validation window, calculated as modeled minus measured irradiance. Power Check validation ---------------------- The radiation conversion also changes the automatic Power Check strategy selection. Since BTI/DTI can be modeled from ``in_global``, the Power Check can be calculated using Formula 2 instead of Formula 1. This behavior is validated with the yearly FHW demo data. The test compares three Power Check runs: - Formula 2 with measured ``rd_bti`` and ``rd_dti``. This is used as the reference because it applies the same Power Check formula with independently measured radiation components. - Formula 1 with measured ``rd_gti``. This represents the previous fallback when only global tilted irradiance is available. - Formula 2 with modeled ``rd_bti`` and ``rd_dti`` from measured ``rd_gti``. This represents the new radiation-conversion workflow. The comparison is performed on common ISO Power Check intervals only, because Formula 1 and Formula 2 apply different irradiance restrictions and may therefore select different valid intervals. .. figure:: _static/radiation_conversion/power_check_radiation_formula_regression.png :alt: Radiation conversion impact on Power Check :align: center :width: 100% Power Check output of (left) Formula 1 using measured GTI and (right) Formula 2 using modeled BTI/DTI, compared to the reference case using Formula 2 with measured BTI/DTI. All three approaches have similar performance for the FHW demo data, though Formula 2 using modeled BTI/DTI has a smaller mean absolute error and a smaller absolute bias than Formula 1. For other locations, Formula 2 using modeled BTI/DTI may have a larger advantage over Formula 1 because it uses a time-resolved beam/diffuse split instead of the fixed global-radiation approximation used by Formula 1. Limitations =========== The current implementation has the following limitations: - only fixed-mounted arrays are supported for reverse transposition; - only the ``in_global``-only model strategy is implemented; - DNI-only input is not sufficient for full tilted irradiance conversion; - model quality depends on sensor orientation metadata; - high-AOI conditions can produce poor reverse-transposition results; - pvlib may emit convergence warnings for some timestamps; - AOI and irradiance validity limits are currently used in validation, but not applied as hard output masks. References ========== The implementation is based on pvlib's irradiance modeling functions: - :func:`pvlib.irradiance.gti_dirint` - :func:`pvlib.irradiance.get_total_irradiance` - :func:`pvlib.irradiance.aoi` Relevant literature: - Marion, B. (2015). *A model for deriving the direct normal and diffuse horizontal irradiance from the global tilted irradiance*. Solar Energy 122, 1037-1046. DOI: 10.1016/j.solener.2015.10.024. - Driesse, A., Jensen, A. R., and Perez, R. (2024). *A continuous form of the Perez diffuse sky model for forward and reverse transposition*. Solar Energy 267. DOI: 10.1016/j.solener.2023.112093.