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
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