ERBS

This function decomposes Global Horizontal Irradiance (GHI) into Direct Normal Irradiance (DNI) and Diffuse Horizontal Irradiance (DHI) using the Erbs empirical model.

The model estimates the diffuse fraction from GHI and computing the ratio of GHI to extraterrestrial irradiance. The result is returned as a 2D array where each row contains the computed DNI, DHI, and the clearness index (Kt).

Excel Usage

=ERBS(ghi, solar_zenith, times, min_cos_zenith, max_zenith)
  • ghi (list[list], required): Global horizontal irradiance (W/m^2).
  • solar_zenith (list[list], required): True (not refraction-corrected) solar zenith angles (degrees).
  • times (list[list], required): Timestamps in ISO8601 format.
  • min_cos_zenith (float, optional, default: 0.065): Minimum value of cos(zenith) when calculating clearness index.
  • max_zenith (float, optional, default: 87): Maximum value of zenith to allow in DNI calculation (degrees).

Returns (list[list]): 2D list containing [[dni, dhi, kt]], or an error string.

Example 1: Perform Erbs decomposition

Inputs:

ghi solar_zenith times
800 40 2024-06-21T12:00:00Z
500 60 2024-06-21T16:00:00Z

Excel formula:

=ERBS({800;500}, {40;60}, {"2024-06-21T12:00:00Z";"2024-06-21T16:00:00Z"})

Expected output:

Result
872.408 131.696 0.790283
822.17 88.9148 0.75674
Example 2: Erbs decomposition for a morning ramp

Inputs:

ghi solar_zenith times
250 75 2024-04-10T07:00:00Z
500 55 2024-04-10T09:00:00Z
720 35 2024-04-10T11:00:00Z

Excel formula:

=ERBS({250;500;720}, {75;55;35}, {"2024-04-10T07:00:00Z";"2024-04-10T09:00:00Z";"2024-04-10T11:00:00Z"})

Expected output:

Result
744.997 57.1806 0.710242
565.004 175.927 0.640975
579.196 245.55 0.646295
Example 3: Erbs decomposition with custom minimum cosine

Inputs:

ghi solar_zenith times min_cos_zenith
300 70 2024-08-01T08:00:00Z 0.08
620 45 2024-08-01T10:00:00Z
450 62 2024-08-01T14:00:00Z

Excel formula:

=ERBS({300;620;450}, {70;45;62}, {"2024-08-01T08:00:00Z";"2024-08-01T10:00:00Z";"2024-08-01T14:00:00Z"}, 0.08)

Expected output:

Result
604.64 93.2011 0.661743
603.997 192.91 0.661495
755.897 95.128 0.723141
Example 4: Erbs decomposition with stricter zenith cutoff

Inputs:

ghi solar_zenith times max_zenith
180 82 2024-02-20T07:30:00Z 80
340 74 2024-02-20T08:30:00Z
520 68 2024-02-20T09:30:00Z

Excel formula:

=ERBS({180;340;520}, {82;74;68}, {"2024-02-20T07:30:00Z";"2024-02-20T08:30:00Z";"2024-02-20T09:30:00Z"}, 80)

Expected output:

Result
0 180 0.92514
1029.98 56.1 0.88233
1159.08 85.8 0.992929

Python Code

Show Code
import pandas as pd
import numpy as np
from pvlib.irradiance import erbs as result_func

def erbs(ghi, solar_zenith, times, min_cos_zenith=0.065, max_zenith=87):
    """
    Estimate DNI and DHI from GHI and solar zenith using the Erbs model.

    See: https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.irradiance.erbs.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        ghi (list[list]): Global horizontal irradiance (W/m^2).
        solar_zenith (list[list]): True (not refraction-corrected) solar zenith angles (degrees).
        times (list[list]): Timestamps in ISO8601 format.
        min_cos_zenith (float, optional): Minimum value of cos(zenith) when calculating clearness index. Default is 0.065.
        max_zenith (float, optional): Maximum value of zenith to allow in DNI calculation (degrees). Default is 87.

    Returns:
        list[list]: 2D list containing [[dni, dhi, kt]], or an error string.
    """
    try:
        def flatten_num(data):
            if not isinstance(data, list): return [float(data)]
            flat = []
            for row in data:
                row = row if isinstance(row, list) else [row]
                for val in row:
                    if val == "": flat.append(float('nan'))
                    else: flat.append(float(val))
            return flat

        def flatten_str(data):
            if not isinstance(data, list): return [str(data)]
            return [str(val) for row in data for val in (row if isinstance(row, list) else [row]) if val != ""]

        ghi_list = flatten_num(ghi)
        zen_list = flatten_num(solar_zenith)
        time_list = flatten_str(times)

        n = len(ghi_list)
        if n == 0 or len(zen_list) != n or len(time_list) != n:
            return "Error: All input arrays must have the same non-zero length"

        idx = pd.DatetimeIndex(time_list)

        min_cz = float(min_cos_zenith) if min_cos_zenith is not None else 0.065
        max_z = float(max_zenith) if max_zenith is not None else 87.0

        res = result_func(np.array(ghi_list), np.array(zen_list), idx, min_cos_zenith=min_cz, max_zenith=max_z)

        output = []
        # Res returns an OrderedDict with 'dni', 'dhi', 'kt'
        dnia = res['dni']
        dhia = res['dhi']
        kta = res['kt']

        for i in range(n):
            d = float(dnia[i])
            dh = float(dhia[i])
            k = float(kta[i])
            output.append([d if not pd.isna(d) else "", dh if not pd.isna(dh) else "", k if not pd.isna(k) else ""])

        return output
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

Global horizontal irradiance (W/m^2).
True (not refraction-corrected) solar zenith angles (degrees).
Timestamps in ISO8601 format.
Minimum value of cos(zenith) when calculating clearness index.
Maximum value of zenith to allow in DNI calculation (degrees).