Example #1
0
def do_multi_segment_calculation(Aseg_m2, C_eff_Jperm2K, Cp_fluid_JperkgK, DT,
                                 Mfl_kgpers, Mo_seg, Nseg, STORED, Tabs, TabsA,
                                 Tamb_C, Tfl, TflA, TflB, Tin_C, Tout_C,
                                 c1_pvt, c2, delts, q_gain_Seg, q_gain_Wperm2,
                                 q_rad_Wperm2):
    Tout_Seg_C = 0.0  # this value will be overwritten after first iteration
    for Iseg in range(1, Nseg + 1):
        # get temperatures of the previous time-step
        TflA[Iseg] = STORED[100 + Iseg]
        TabsA[Iseg] = STORED[300 + Iseg]
        if Iseg > 1:
            Tin_Seg = Tout_Seg_C
        else:
            Tin_Seg = Tin_C
        if Mfl_kgpers > 0 and Mo_seg == 1:  # same heat gain/ losses for all segments
            Tout_Seg_C = (
                (Mfl_kgpers * Cp_fluid_JperkgK *
                 (Tin_Seg + 273.15)) / Aseg_m2 - (C_eff_Jperm2K *
                                                  (Tin_Seg + 273.15)) /
                (2 * delts) + q_gain_Wperm2 +
                (C_eff_Jperm2K * (TflA[Iseg] + 273.15) / delts)) / (
                    Mfl_kgpers * Cp_fluid_JperkgK / Aseg_m2 + C_eff_Jperm2K /
                    (2 * delts))
            Tout_Seg_C = Tout_Seg_C - 273.15  # in [C]
            TflB[Iseg] = (Tin_Seg + Tout_Seg_C) / 2
        else:  # heat losses based on each segment's inlet and outlet temperatures.
            Tfl[1] = TflA[Iseg]
            Tabs[1] = TabsA[Iseg]
            q_gain_Wperm2 = calc_q_gain(Tfl, q_rad_Wperm2, DT, Tin_Seg,
                                        Aseg_m2, c1_pvt, c2, Mfl_kgpers, delts,
                                        Cp_fluid_JperkgK, C_eff_Jperm2K,
                                        Tamb_C)
            Tout_Seg_C = Tout_C
            if Mfl_kgpers > 0:
                TflB[Iseg] = (Tin_Seg + Tout_Seg_C) / 2
                Tout_Seg_C = TflA[Iseg] + (q_gain_Wperm2 *
                                           delts) / C_eff_Jperm2K
            else:
                TflB[Iseg] = Tout_Seg_C

            # the following lines do not perform meaningful operation, the iterations on DT are performed in calc_q_gain
            # these lines are kept here as a reference to the original model in FORTRAN
            # q_fluid_Wperm2 = (Tout_Seg_C - Tin_Seg) * Mfl_kgpers * Cp_fluid_JperkgK / Aseg_m2
            # q_mtherm_Wperm2 = (TflB[Iseg] - TflA[Iseg]) * C_eff_Jperm2K / delts
            # q_balance_error = q_gain_Wperm2 - q_fluid_Wperm2 - q_mtherm_Wperm2
            # # assert abs(q_balance_error) > 1, "q_balance_error in photovoltaic-thermal calculation"
        q_gain_Seg[Iseg] = q_gain_Wperm2  # in W/m2
    return Tout_Seg_C
Example #2
0
def calc_PVT_module(config, radiation_Wperm2, panel_properties_SC,
                    panel_properties_PV, Tamb_vector_C, IAM_b, tilt_angle_deg,
                    pipe_lengths, absorbed_radiation_PV_Wperm2, Tcell_PV_C,
                    module_area_per_group_m2):
    """
    This function calculates the heat & electricity production from PVT collectors. 
    The heat production calculation is adapted from calc_SC_module and then the updated cell temperature is used to 
    calculate PV electricity production.
    
    :param tilt_angle_deg: solar panel tilt angle [rad]
    :param IAM_b_vector: incident angle modifier for beam radiation [-]
    :param I_direct_vector: direct radiation [W/m2]
    :param I_diffuse_vector: diffuse radiation [W/m2]
    :param Tamb_vector_C: dry bulb temperature [C]
    :param IAM_d_vector: incident angle modifier for diffuse radiation [-]
    :param Leq: equivalent length of pipes per aperture area [m/m2 aperture)
    :param Le: equivalent length of collector pipes per aperture area [m/m2 aperture]
    :param absorbed_radiation_PV_Wperm2: absorbed solar radiation of PV module [Wh/m2]
    :param Tcell_PV_C: PV cell temperature [C]
    :param module_area_per_group_m2: PV module area [m2]
    :return:

    ..[J. Allan et al., 2015] J. Allan, Z. Dehouche, S. Stankovic, L. Mauricette. "Performance testing of thermal and
    photovoltaic thermal solar collectors." Energy Science & Engineering 2015; 3(4): 310-326
    """

    # read variables
    Tin_C = get_t_in_pvt(config)
    n0 = panel_properties_SC[
        'n0']  # zero loss efficiency at normal incidence [-]
    c1 = panel_properties_SC[
        'c1']  # collector heat loss coefficient at zero temperature difference and wind speed [W/m2K]
    c2 = panel_properties_SC[
        'c2']  # temperature difference dependency of the heat loss coefficient [W/m2K2]
    mB0_r = panel_properties_SC[
        'mB0_r']  # nominal flow rate per aperture area [kg/h/m2 aperture]
    mB_max_r = panel_properties_SC[
        'mB_max_r']  # maximum flow rate per aperture area
    mB_min_r = panel_properties_SC[
        'mB_min_r']  # minimum flow rate per aperture area
    C_eff_Jperm2K = panel_properties_SC[
        'C_eff']  # thermal capacitance of module [J/m2K]
    IAM_d = panel_properties_SC[
        'IAM_d']  # incident angle modifier for diffuse radiation [-]
    dP1 = panel_properties_SC['dP1']  # pressure drop [Pa/m2] at zero flow rate
    dP2 = panel_properties_SC[
        'dP2']  # pressure drop [Pa/m2] at nominal flow rate (mB0)
    dP3 = panel_properties_SC[
        'dP3']  # pressure drop [Pa/m2] at maximum flow rate (mB_max)
    dP4 = panel_properties_SC[
        'dP4']  # pressure drop [Pa/m2] at minimum flow rate (mB_min)
    Cp_fluid_JperkgK = panel_properties_SC['Cp_fluid']  # J/kgK
    aperature_area_ratio = panel_properties_SC[
        'aperture_area_ratio']  # aperature area ratio [-]
    area_pv_module = panel_properties_PV['module_length_m']**2
    Nseg = panel_properties_SC['Nseg']
    T_max_C = panel_properties_SC['t_max']
    eff_nom = panel_properties_PV['PV_n']
    Bref = panel_properties_PV['PV_Bref']
    misc_losses = panel_properties_PV['misc_losses']

    aperture_area_m2 = aperature_area_ratio * area_pv_module  # aperture area of each module [m2]
    msc_max_kgpers = mB_max_r * aperture_area_m2 / 3600  # maximum mass flow [kg/s]

    # Do the calculation of every time step for every possible flow condition
    # get states where highly performing values are obtained.
    specific_flows_kgpers = [
        np.zeros(HOURS_IN_YEAR),
        (np.zeros(HOURS_IN_YEAR) + mB0_r) * aperture_area_m2 / 3600,
        (np.zeros(HOURS_IN_YEAR) + mB_max_r) * aperture_area_m2 / 3600,
        (np.zeros(HOURS_IN_YEAR) + mB_min_r) * aperture_area_m2 / 3600,
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR)
    ]  # in kg/s
    specific_pressure_losses_Pa = [
        np.zeros(HOURS_IN_YEAR),
        (np.zeros(HOURS_IN_YEAR) + dP2) * aperture_area_m2,
        (np.zeros(HOURS_IN_YEAR) + dP3) * aperture_area_m2,
        (np.zeros(HOURS_IN_YEAR) + dP4) * aperture_area_m2,
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR)
    ]  # in Pa

    # generate empty lists to store results
    temperature_out = [
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR)
    ]
    temperature_in = [
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR)
    ]
    supply_out_kW = [
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR)
    ]
    supply_losses_kW = [
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR)
    ]
    auxiliary_electricity_kW = [
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR)
    ]
    temperature_mean = [
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR),
        np.zeros(HOURS_IN_YEAR)
    ]
    mcp_kWperK = np.zeros(HOURS_IN_YEAR)
    T_module_C = np.zeros(HOURS_IN_YEAR)

    # calculate absorbed radiation
    tilt_rad = radians(tilt_angle_deg)
    q_rad_vector = np.vectorize(calc_q_rad)(
        n0, IAM_b, IAM_d, radiation_Wperm2.I_direct,
        radiation_Wperm2.I_diffuse,
        tilt_rad)  # absorbed solar radiation in W/m2 is a mean of the group
    counter = 0
    Flag = False
    Flag2 = False
    for flow in range(6):
        Mo_seg = 1  # mode of segmented heat loss calculation. only one mode is implemented.
        TIME0 = 0
        DELT = 1  # timestep 1 hour
        delts = DELT * 3600  # convert time step in seconds
        Tfl = np.zeros(
            3
        )  # create vector to store value at previous [1] and present [2] time-steps
        DT = np.zeros(3)
        Tabs = np.zeros(3)
        STORED = np.zeros(600)
        TflA = np.zeros(600)
        TflB = np.zeros(600)
        TabsB = np.zeros(600)
        TabsA = np.zeros(600)
        q_gain_Seg = np.zeros(101)  # maximum Iseg = maximum Nseg + 1 = 101

        for time in range(HOURS_IN_YEAR):
            # c1_pvt = c1 - eff_nom * Bref * absorbed_radiation_PV_Wperm2[time] #todo: to delete
            c1_pvt = calc_cl_pvt(Bref, absorbed_radiation_PV_Wperm2, c1,
                                 eff_nom, time)
            Mfl_kgpers = calc_Mfl_kgpers(DELT, Nseg, STORED, TIME0, Tin_C,
                                         specific_flows_kgpers[flow], time,
                                         Cp_fluid_JperkgK, C_eff_Jperm2K,
                                         aperture_area_m2)

            # calculate average fluid temperature and average absorber temperature at the beginning of the time-step
            Tamb_C = Tamb_vector_C[time]
            q_rad_Wperm2 = q_rad_vector[time]
            Tout_C = calc_Tout_C(Cp_fluid_JperkgK, DT, Mfl_kgpers, Nseg,
                                 STORED, Tabs, Tamb_C, Tfl, Tin_C,
                                 aperture_area_m2, c1_pvt, q_rad_Wperm2)

            # calculate q_gain with the guess for DT[1]
            q_gain_Wperm2 = calc_q_gain(Tfl, q_rad_Wperm2, DT, Tin_C,
                                        aperture_area_m2, c1_pvt, c2,
                                        Mfl_kgpers, delts, Cp_fluid_JperkgK,
                                        C_eff_Jperm2K, Tamb_C)

            Aseg_m2 = aperture_area_m2 / Nseg  # aperture area per segment

            # multi-segment calculation to avoid temperature jump at times of flow rate changes
            Tout_Seg_C = do_multi_segment_calculation(
                Aseg_m2, C_eff_Jperm2K, Cp_fluid_JperkgK, DT, Mfl_kgpers,
                Mo_seg, Nseg, STORED, Tabs, TabsA, Tamb_C, Tfl, TflA, TflB,
                Tin_C, Tout_C, c1_pvt, c2, delts, q_gain_Seg, q_gain_Wperm2,
                q_rad_Wperm2)

            # resulting energy output
            q_out_kW = Mfl_kgpers * Cp_fluid_JperkgK * (Tout_Seg_C -
                                                        Tin_C) / 1000  # [kW]
            Tabs[2] = 0
            # storage of the mean temperature
            for Iseg in range(1, Nseg + 1):
                STORED[200 + Iseg] = TflB[Iseg]
                STORED[400 + Iseg] = TabsB[Iseg]
                Tabs[2] = Tabs[2] + TabsB[Iseg] / Nseg

            # outputs
            temperature_out[flow][time] = Tout_Seg_C
            temperature_in[flow][time] = Tin_C
            supply_out_kW[flow][time] = q_out_kW
            temperature_mean[flow][time] = (
                Tin_C + Tout_Seg_C) / 2  # Mean absorber temperature at present

            q_gain_Wperm2 = 0
            TavgB = 0
            TavgA = 0
            for Iseg in range(1, Nseg + 1):
                q_gain_Wperm2 = q_gain_Wperm2 + q_gain_Seg * Aseg_m2  # W
                TavgA = TavgA + TflA[Iseg] / Nseg
                TavgB = TavgB + TflB[Iseg] / Nseg

                # # OUT[9] = qgain/Area_a # in W/m2
                # q_mtherm_Wperm2 = (TavgB - TavgA) * C_eff_Jperm2K * aperture_area_m2 / delts
                # q_balance_error = q_gain_Wperm2 - q_mtherm_Wperm2 - q_out_kW

                # OUT[11] = q_mtherm
                # OUT[12] = q_balance_error
        if flow < 4:
            auxiliary_electricity_kW[flow] = vectorize_calc_Eaux_SC(
                specific_flows_kgpers[flow], specific_pressure_losses_Pa[flow],
                pipe_lengths, aperture_area_m2)  # in kW
        if flow == 3:
            q1 = supply_out_kW[0]
            q2 = supply_out_kW[1]
            q3 = supply_out_kW[2]
            q4 = supply_out_kW[3]
            E1 = auxiliary_electricity_kW[0]
            E2 = auxiliary_electricity_kW[1]
            E3 = auxiliary_electricity_kW[2]
            E4 = auxiliary_electricity_kW[3]
            specific_flows_kgpers[4], specific_pressure_losses_Pa[
                4] = calc_optimal_mass_flow(q1, q2, q3, q4, E1, E2, E3, E4, 0,
                                            mB0_r, mB_max_r, mB_min_r, 0, dP2,
                                            dP3, dP4, aperture_area_m2)
        if flow == 4:
            auxiliary_electricity_kW[flow] = vectorize_calc_Eaux_SC(
                specific_flows_kgpers[flow], specific_pressure_losses_Pa[flow],
                pipe_lengths, aperture_area_m2)  # in kW
            dp5 = specific_pressure_losses_Pa[flow]
            q5 = supply_out_kW[flow]
            m5 = specific_flows_kgpers[flow]
            # set points to zero when load is negative
            specific_flows_kgpers[5], specific_pressure_losses_Pa[
                5] = calc_optimal_mass_flow_2(m5, q5, dp5)

        if flow == 5:  # optimal mass flow
            supply_losses_kW[flow] = np.vectorize(calc_qloss_network)(
                specific_flows_kgpers[flow], pipe_lengths['l_ext_mperm2'],
                aperture_area_m2, temperature_mean[flow], Tamb_vector_C,
                msc_max_kgpers)
            supply_out_pre = supply_out_kW[flow].copy(
            ) + supply_losses_kW[flow].copy()
            auxiliary_electricity_kW[flow] = vectorize_calc_Eaux_SC(
                specific_flows_kgpers[flow], specific_pressure_losses_Pa[flow],
                pipe_lengths, aperture_area_m2)  # in kW
            supply_out_total_kW = supply_out_kW + 0.5 * auxiliary_electricity_kW[
                flow] - supply_losses_kW[flow]
            mcp_kWperK = specific_flows_kgpers[flow] * (Cp_fluid_JperkgK / 1000
                                                        )  # mcp in kW/c

    turn_off_the_water_circuit_if_total_energy_supply_is_zero(
        T_module_C, Tcell_PV_C, auxiliary_electricity_kW[flow], mcp_kWperK,
        supply_out_total_kW[5], temperature_in[5], temperature_out[5])

    el_output_PV_kW = np.vectorize(calc_PV_power)(absorbed_radiation_PV_Wperm2,
                                                  T_module_C, eff_nom,
                                                  module_area_per_group_m2,
                                                  Bref, misc_losses)

    # write results into a list
    result = [
        supply_losses_kW[5], supply_out_total_kW[5],
        auxiliary_electricity_kW[5], temperature_out[5], temperature_in[5],
        mcp_kWperK, el_output_PV_kW
    ]

    return result
def calc_PVT_module(config, radiation_Wperm2, panel_properties_SC,
                    panel_properties_PV, Tamb_vector_C, IAM_b, tilt_angle_deg,
                    pipe_lengths, absorbed_radiation_PV_Wperm2, Tcell_PV_C,
                    module_area_per_group_m2):
    """
    This function calculates the heat & electricity production from PVT collectors. 
    The heat production calculation is adapted from calc_SC_module and then the updated cell temperature is used to 
    calculate PV electricity production.
    
    :param tilt_angle_deg: solar panel tilt angle [rad]
    :param IAM_b_vector: incident angle modifier for beam radiation [-]
    :param I_direct_vector: direct radiation [W/m2]
    :param I_diffuse_vector: diffuse radiation [W/m2]
    :param Tamb_vector_C: dry bulb temperature [C]
    :param IAM_d_vector: incident angle modifier for diffuse radiation [-]
    :param Leq: equivalent length of pipes per aperture area [m/m2 aperture)
    :param Le: equivalent length of collector pipes per aperture area [m/m2 aperture]
    :param absorbed_radiation_PV_Wperm2: absorbed solar radiation of PV module [Wh/m2]
    :param Tcell_PV_C: PV cell temperature [C]
    :param module_area_per_group_m2: PV module area [m2]
    :return:

    ..[J. Allan et al., 2015] J. Allan, Z. Dehouche, S. Stankovic, L. Mauricette. "Performance testing of thermal and
    photovoltaic thermal solar collectors." Energy Science & Engineering 2015; 3(4): 310-326
    """

    # read variables
    Tin_C = get_t_in_pvt(config)
    n0 = panel_properties_SC[
        'n0']  # zero loss efficiency at normal incidence [-]
    c1 = panel_properties_SC[
        'c1']  # collector heat loss coefficient at zero temperature difference and wind speed [W/m2K]
    c2 = panel_properties_SC[
        'c2']  # temperature difference dependency of the heat loss coefficient [W/m2K2]
    mB0_r = panel_properties_SC[
        'mB0_r']  # nominal flow rate per aperture area [kg/h/m2 aperture]
    mB_max_r = panel_properties_SC[
        'mB_max_r']  # maximum flow rate per aperture area
    mB_min_r = panel_properties_SC[
        'mB_min_r']  # minimum flow rate per aperture area
    C_eff_Jperm2K = panel_properties_SC[
        'C_eff']  # thermal capacitance of module [J/m2K]
    IAM_d = panel_properties_SC[
        'IAM_d']  # incident angle modifier for diffuse radiation [-]
    dP1 = panel_properties_SC['dP1']  # pressure drop [Pa/m2] at zero flow rate
    dP2 = panel_properties_SC[
        'dP2']  # pressure drop [Pa/m2] at nominal flow rate (mB0)
    dP3 = panel_properties_SC[
        'dP3']  # pressure drop [Pa/m2] at maximum flow rate (mB_max)
    dP4 = panel_properties_SC[
        'dP4']  # pressure drop [Pa/m2] at minimum flow rate (mB_min)
    Cp_fluid_JperkgK = panel_properties_SC['Cp_fluid']  # J/kgK
    aperature_area_ratio = panel_properties_SC[
        'aperture_area_ratio']  # aperature area ratio [-]
    area_pv_module = panel_properties_PV['module_length_m']**2
    Nseg = panel_properties_SC['Nseg']
    T_max_C = panel_properties_SC['t_max']
    eff_nom = panel_properties_PV['PV_n']
    Bref = panel_properties_PV['PV_Bref']
    misc_losses = panel_properties_PV['misc_losses']

    aperture_area_m2 = aperature_area_ratio * area_pv_module  # aperture area of each module [m2]
    msc_max_kgpers = mB_max_r * aperture_area_m2 / 3600  # maximum mass flow [kg/s]

    # Do the calculation of every time step for every possible flow condition
    # get states where highly performing values are obtained.
    specific_flows_kgpers = [
        np.zeros(8760), (np.zeros(8760) + mB0_r) * aperture_area_m2 / 3600,
        (np.zeros(8760) + mB_max_r) * aperture_area_m2 / 3600,
        (np.zeros(8760) + mB_min_r) * aperture_area_m2 / 3600,
        np.zeros(8760),
        np.zeros(8760)
    ]  # in kg/s
    specific_pressure_losses_Pa = [
        np.zeros(8760), (np.zeros(8760) + dP2) * aperture_area_m2,
        (np.zeros(8760) + dP3) * aperture_area_m2,
        (np.zeros(8760) + dP4) * aperture_area_m2,
        np.zeros(8760),
        np.zeros(8760)
    ]  # in Pa

    # generate empty lists to store results
    temperature_out = [
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760)
    ]
    temperature_in = [
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760)
    ]
    supply_out_kW = [
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760)
    ]
    supply_losses_kW = [
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760)
    ]
    auxiliary_electricity_kW = [
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760)
    ]
    temperature_mean = [
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760),
        np.zeros(8760)
    ]
    mcp_kWperK = np.zeros(8760)
    T_module_C = np.zeros(8760)

    # calculate absorbed radiation
    tilt_rad = radians(tilt_angle_deg)
    q_rad_vector = np.vectorize(calc_q_rad)(
        n0, IAM_b, IAM_d, radiation_Wperm2.I_direct,
        radiation_Wperm2.I_diffuse,
        tilt_rad)  # absorbed solar radiation in W/m2 is a mean of the group
    counter = 0
    Flag = False
    Flag2 = False
    for flow in range(6):
        Mo_seg = 1  # mode of segmented heat loss calculation. only one mode is implemented.
        TIME0 = 0
        DELT = 1  # timestep 1 hour
        delts = DELT * 3600  # convert time step in seconds
        Tfl = np.zeros(
            [3, 1]
        )  # create vector to store value at previous [1] and present [2] time-steps
        DT = np.zeros([3, 1])
        Tabs = np.zeros([3, 1])
        STORED = np.zeros([600, 1])
        TflA = np.zeros([600, 1])
        TflB = np.zeros([600, 1])
        TabsB = np.zeros([600, 1])
        TabsA = np.zeros([600, 1])
        q_gain_Seg = np.zeros([101,
                               1])  # maximum Iseg = maximum Nseg + 1 = 101

        for time in range(8760):
            #c1_pvt = c1 - eff_nom * Bref * absorbed_radiation_PV_Wperm2[time] #todo: to delete
            c1_pvt = max(0, c1 -
                         eff_nom * Bref * absorbed_radiation_PV_Wperm2[time]
                         )  # _[J. Allan et al., 2015] eq.(18)
            Mfl_kgpers = specific_flows_kgpers[flow][time]
            if time < TIME0 + DELT / 2:
                for Iseg in range(101, 501):  # 400 points with the data
                    STORED[Iseg] = Tin_C
            else:
                for Iseg in range(1, Nseg):  # 400 points with the data
                    STORED[100 + Iseg] = STORED[200 + Iseg]
                    STORED[300 + Iseg] = STORED[400 + Iseg]

            # calculate stability criteria
            if Mfl_kgpers > 0:
                stability_criteria = Mfl_kgpers * Cp_fluid_JperkgK * Nseg * (
                    DELT * 3600) / (C_eff_Jperm2K * aperture_area_m2)
                if stability_criteria <= 0.5:
                    print('ERROR: stability criteria' +
                          str(stability_criteria) +
                          'is not reached. aperture_area: ' +
                          str(aperture_area_m2) + 'mass flow: ' +
                          str(Mfl_kgpers))

            # calculate average fluid temperature and average absorber temperature at the beginning of the time-step
            Tamb_C = Tamb_vector_C[time]
            q_rad_Wperm2 = q_rad_vector[time]
            Tfl[1] = 0  # mean fluid temperature
            Tabs[1] = 0  # mean absorber temperature
            for Iseg in range(1, Nseg + 1):
                Tfl[1] = Tfl[1] + STORED[100 +
                                         Iseg] / Nseg  # mean fluid temperature
                Tabs[1] = Tabs[1] + STORED[
                    300 + Iseg] / Nseg  # mean absorber temperature

            # first guess for Delta T
            if Mfl_kgpers > 0:
                Tout = Tin_C + (q_rad_Wperm2 - (
                    (c1_pvt) + 0.5) * (Tin_C - Tamb_C)) / (
                        Mfl_kgpers * Cp_fluid_JperkgK / aperture_area_m2)
                Tfl[2] = (Tin_C + Tout
                          ) / 2  # mean fluid temperature at present time-step
            else:
                # if c1_pvt < 0:
                #     print('c1_pvt: ', c1_pvt)
                Tout = Tamb_C + q_rad_Wperm2 / (c1_pvt + 0.5)
                Tfl[2] = Tout  # fluid temperature same as output
                # if Tout > T_max_C:
                #     print('Tout: ',Tout, 'c1_pvt: ', c1_pvt, 'q_rad', q_rad_Wperm2)

            DT[1] = Tfl[
                2] - Tamb_C  # difference between mean absorber temperature and the ambient temperature

            # calculate q_gain with the guess for DT[1]
            q_gain_Wperm2 = calc_q_gain(Tfl, Tabs, q_rad_Wperm2, DT, Tin_C,
                                        Tout, aperture_area_m2, c1_pvt, c2,
                                        Mfl_kgpers, delts, Cp_fluid_JperkgK,
                                        C_eff_Jperm2K, Tamb_C)

            Aseg_m2 = aperture_area_m2 / Nseg  # aperture area per segment
            for Iseg in range(1, Nseg + 1):
                # get temperatures of the previous time-step
                TflA[Iseg] = STORED[100 + Iseg]
                TabsA[Iseg] = STORED[300 + Iseg]
                if Iseg > 1:
                    TinSeg = ToutSeg
                else:
                    TinSeg = Tin_C
                if Mfl_kgpers > 0 and Mo_seg == 1:  # same heat gain/ losses for all segments
                    ToutSeg = ((Mfl_kgpers * Cp_fluid_JperkgK *
                                (TinSeg + 273.15)) / Aseg_m2 -
                               (C_eff_Jperm2K * (TinSeg + 273.15)) /
                               (2 * delts) + q_gain_Wperm2 +
                               (C_eff_Jperm2K *
                                (TflA[Iseg] + 273.15) / delts)) / (
                                    Mfl_kgpers * Cp_fluid_JperkgK / Aseg_m2 +
                                    C_eff_Jperm2K / (2 * delts))
                    ToutSeg = ToutSeg - 273.15  # in [C]
                    TflB[Iseg] = (TinSeg + ToutSeg) / 2
                else:  # heat losses based on each segment's inlet and outlet temperatures.
                    Tfl[1] = TflA[Iseg]
                    Tabs[1] = TabsA[Iseg]
                    q_gain_Wperm2 = calc_q_gain(Tfl, Tabs, q_rad_Wperm2, DT,
                                                TinSeg, Tout, Aseg_m2, c1_pvt,
                                                c2, Mfl_kgpers, delts,
                                                Cp_fluid_JperkgK,
                                                C_eff_Jperm2K, Tamb_C)
                    ToutSeg = Tout
                    if Mfl_kgpers > 0:
                        TflB[Iseg] = (TinSeg + ToutSeg) / 2
                        ToutSeg = TflA[Iseg] + (q_gain_Wperm2 *
                                                delts) / C_eff_Jperm2K
                    else:
                        TflB[Iseg] = ToutSeg

                    # TflB[Iseg] = ToutSeg
                    q_fluid_Wperm2 = (
                        ToutSeg -
                        TinSeg) * Mfl_kgpers * Cp_fluid_JperkgK / Aseg_m2
                    q_mtherm_Wperm2 = (TflB[Iseg] -
                                       TflA[Iseg]) * C_eff_Jperm2K / delts
                    q_balance_error = q_gain_Wperm2 - q_fluid_Wperm2 - q_mtherm_Wperm2
                    if abs(q_balance_error) > 1:
                        time = time  # re-enter the iteration when energy balance not satisfied
                q_gain_Seg[Iseg] = q_gain_Wperm2  # in W/m2

            # resulting energy output
            q_out_kW = Mfl_kgpers * Cp_fluid_JperkgK * (ToutSeg -
                                                        Tin_C) / 1000  # [kW]
            Tabs[2] = 0
            # storage of the mean temperature
            for Iseg in range(1, Nseg + 1):
                STORED[200 + Iseg] = TflB[Iseg]
                STORED[400 + Iseg] = TabsB[Iseg]
                Tabs[2] = Tabs[2] + TabsB[Iseg] / Nseg

            # outputs
            temperature_out[flow][time] = ToutSeg
            temperature_in[flow][time] = Tin_C
            supply_out_kW[flow][time] = q_out_kW
            temperature_mean[flow][time] = (
                Tin_C + ToutSeg) / 2  # Mean absorber temperature at present

            q_gain_Wperm2 = 0
            TavgB = 0
            TavgA = 0
            for Iseg in range(1, Nseg + 1):
                q_gain_Wperm2 = q_gain_Wperm2 + q_gain_Seg * Aseg_m2  # W
                TavgA = TavgA + TflA[Iseg] / Nseg
                TavgB = TavgB + TflB[Iseg] / Nseg

                # # OUT[9] = qgain/Area_a # in W/m2
                # q_mtherm_Wperm2 = (TavgB - TavgA) * C_eff_Jperm2K * aperture_area_m2 / delts
                # q_balance_error = q_gain_Wperm2 - q_mtherm_Wperm2 - q_out_kW

                # OUT[11] = q_mtherm
                # OUT[12] = q_balance_error
        if flow < 4:
            auxiliary_electricity_kW[flow] = np.vectorize(calc_Eaux_SC)(
                specific_flows_kgpers[flow], specific_pressure_losses_Pa[flow],
                pipe_lengths, aperture_area_m2)  # in kW
        if flow == 3:
            q1 = supply_out_kW[0]
            q2 = supply_out_kW[1]
            q3 = supply_out_kW[2]
            q4 = supply_out_kW[3]
            E1 = auxiliary_electricity_kW[0]
            E2 = auxiliary_electricity_kW[1]
            E3 = auxiliary_electricity_kW[2]
            E4 = auxiliary_electricity_kW[3]
            specific_flows_kgpers[4], specific_pressure_losses_Pa[
                4] = calc_optimal_mass_flow(q1, q2, q3, q4, E1, E2, E3, E4, 0,
                                            mB0_r, mB_max_r, mB_min_r, 0, dP2,
                                            dP3, dP4, aperture_area_m2)
        if flow == 4:
            auxiliary_electricity_kW[flow] = np.vectorize(calc_Eaux_SC)(
                specific_flows_kgpers[flow], specific_pressure_losses_Pa[flow],
                pipe_lengths, aperture_area_m2)  # in kW
            dp5 = specific_pressure_losses_Pa[flow]
            q5 = supply_out_kW[flow]
            m5 = specific_flows_kgpers[flow]
            # set points to zero when load is negative
            specific_flows_kgpers[5], specific_pressure_losses_Pa[
                5] = calc_optimal_mass_flow_2(m5, q5, dp5)

        if flow == 5:  # optimal mass flow
            supply_losses_kW[flow] = np.vectorize(calc_qloss_network)(
                specific_flows_kgpers[flow], pipe_lengths['l_ext_mperm2'],
                aperture_area_m2, temperature_mean[flow], Tamb_vector_C,
                msc_max_kgpers)
            supply_out_pre = supply_out_kW[flow].copy(
            ) + supply_losses_kW[flow].copy()
            auxiliary_electricity_kW[flow] = np.vectorize(calc_Eaux_SC)(
                specific_flows_kgpers[flow], specific_pressure_losses_Pa[flow],
                pipe_lengths, aperture_area_m2)  # in kW
            supply_out_total_kW = supply_out_kW + 0.5 * auxiliary_electricity_kW[
                flow] - supply_losses_kW[flow]
            mcp_kWperK = specific_flows_kgpers[flow] * (Cp_fluid_JperkgK / 1000
                                                        )  # mcp in kW/c

    for x in range(8760):
        # turn off the water circuit if total energy supply is zero
        if supply_out_total_kW[5][x] <= 0:
            supply_out_total_kW[5][x] = 0
            mcp_kWperK[x] = 0
            auxiliary_electricity_kW[5][x] = 0
            temperature_out[5][x] = 0
            temperature_in[5][x] = 0
        # update pv cell temperature with temperatures of the water circuit
        T_module_mean_C = (temperature_out[5][x] + temperature_in[5][x]) / 2
        T_module_C[
            x] = T_module_mean_C if T_module_mean_C > 0 else Tcell_PV_C[x]

    el_output_PV_kW = np.vectorize(calc_PV_power)(absorbed_radiation_PV_Wperm2,
                                                  T_module_C, eff_nom,
                                                  module_area_per_group_m2,
                                                  Bref, misc_losses)

    # write results into a list
    result = [
        supply_losses_kW[5], supply_out_total_kW[5],
        auxiliary_electricity_kW[5], temperature_out[5], temperature_in[5],
        mcp_kWperK, el_output_PV_kW
    ]

    return result