From 4f5584bc1edc5a16287ba6ad58524949516d0763 Mon Sep 17 00:00:00 2001 From: jannamartinek Date: Tue, 12 Sep 2023 18:20:58 -0600 Subject: [PATCH] Minor updates to falling particle receiver model --- ssc/cmod_csp_tower_particle.cpp | 26 +++-- tcs/csp_solver_falling_particle_receiver.cpp | 112 +++++++++++++------ tcs/csp_solver_falling_particle_receiver.h | 2 + 3 files changed, 95 insertions(+), 45 deletions(-) diff --git a/ssc/cmod_csp_tower_particle.cpp b/ssc/cmod_csp_tower_particle.cpp index 4afaf1a59..778bb393e 100644 --- a/ssc/cmod_csp_tower_particle.cpp +++ b/ssc/cmod_csp_tower_particle.cpp @@ -528,7 +528,7 @@ static var_info _cm_vtab_csp_tower_particle[] = { { SSC_OUTPUT, SSC_ARRAY, "defocus", "Field optical focus fraction", "", "", "", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_ARRAY, "sf_adjust_out", "Field availability adjustment factor", "", "", "", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_ARRAY, "rec_defocus", "Receiver component defocus", "", "", "", "sim_type=1", "", ""}, - { SSC_OUTPUT, SSC_ARRAY, "q_dot_rec_inc", "Receiver incident thermal power", "MWt", "", "", "sim_type=1", "", ""}, + { SSC_OUTPUT, SSC_ARRAY, "q_dot_rec_inc", "Receiver incident thermal power on particle curtain", "MWt", "", "", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_ARRAY, "eta_therm", "Receiver efficiency", "", "", "", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_ARRAY, "Q_thermal", "Receiver thermal power to HTF less particle transport loss", "MWt", "", "", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_ARRAY, "pparasi", "Field tracking power", "MWe", "", "", "sim_type=1", "", ""}, @@ -537,10 +537,10 @@ static var_info _cm_vtab_csp_tower_particle[] = { { SSC_OUTPUT, SSC_ARRAY, "q_startup", "Receiver startup thermal energy consumed", "MWt", "", "", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_ARRAY, "T_rec_in", "Receiver HTF inlet temperature", "C", "", "", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_ARRAY, "T_rec_out", "Receiver HTF outlet temperature", "C", "", "", "sim_type=1", "", ""}, - { SSC_OUTPUT, SSC_ARRAY, "q_transport_losses", "Receiver particle transport losses", "MWt", "", "", "sim_type=1", "", ""}, - { SSC_OUTPUT, SSC_ARRAY, "q_thermal_loss", "Receiver reflection, convection and emission losses", "MWt", "", "", "sim_type=1", "", ""}, - //{ SSC_OUTPUT, SSC_ARRAY, "q_dot_reflection_loss", "Receiver reflection losses", "MWt", "", "", "sim_type=1", "", ""}, - { SSC_OUTPUT, SSC_ARRAY, "P_tower_lift", "Receiver and tower particle lift power", "MWe", "", "", "sim_type=1", "", ""}, + { SSC_OUTPUT, SSC_ARRAY, "q_transport_loss", "Receiver particle transport losses", "MWt", "", "", "sim_type=1", "", ""}, + { SSC_OUTPUT, SSC_ARRAY, "q_thermal_loss", "Receiver convection and emission losses", "MWt", "", "", "sim_type=1", "", ""}, + { SSC_OUTPUT, SSC_ARRAY, "q_reflection_loss", "Receiver reflection losses", "MWt", "", "", "sim_type=1", "", ""}, + { SSC_OUTPUT, SSC_ARRAY, "P_tower_lift", "Receiver and tower particle lift power", "MWe", "", "", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_ARRAY, "clearsky", "Predicted clear-sky beam normal irradiance", "W/m2", "", "CR", "sim_type=1&rec_clearsky_fraction>0", "", "" }, @@ -654,8 +654,9 @@ static var_info _cm_vtab_csp_tower_particle[] = { { SSC_OUTPUT, SSC_NUMBER, "annual_W_cycle_gross", "Electrical source - power cycle gross output", "kWhe", "", "", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_NUMBER, "annual_W_cooling_tower", "Total of condenser operation parasitics", "kWhe", "", "PC", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_NUMBER, "annual_q_rec_inc", "Annual receiver incident thermal power", "MWt-hr", "", "Tower and Receiver", "sim_type=1", "", ""}, - { SSC_OUTPUT, SSC_NUMBER, "annual_q_rec_loss", "Annual receiver reflective, advective, and radiative losses", "MWt-hr", "", "Tower and Receiver", "sim_type=1", "", ""}, - { SSC_OUTPUT, SSC_NUMBER, "annual_eta_rec_th_incl_refl", "Annual receiver efficiency including reflective loss", "", "", "Tower and Receiver", "sim_type=1", "", ""}, + { SSC_OUTPUT, SSC_NUMBER, "annual_q_rec_reflection_loss", "Annual receiver reflection losses", "MWt-hr", "", "Tower and Receiver", "sim_type=1", "", ""}, + { SSC_OUTPUT, SSC_NUMBER, "annual_q_rec_thermal_loss", "Annual receiver advective and radiative losses", "MWt-hr", "", "Tower and Receiver", "sim_type=1", "", ""}, + { SSC_OUTPUT, SSC_NUMBER, "annual_eta_rec", "Annual receiver efficiency including reflective, advective, radiative loss", "", "", "Tower and Receiver", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_NUMBER, "conversion_factor", "Gross to net conversion factor", "%", "", "", "sim_type=1", "", ""}, { SSC_OUTPUT, SSC_NUMBER, "capacity_factor", "Capacity factor", "%", "", "", "sim_type=1", "", ""}, @@ -1184,9 +1185,9 @@ class cm_csp_tower_particle : public compute_module collector_receiver.mc_reported_outputs.assign(C_csp_mspt_collector_receiver::E_Q_DOT_STARTUP, allocate("q_startup", n_steps_fixed), n_steps_fixed); collector_receiver.mc_reported_outputs.assign(C_csp_mspt_collector_receiver::E_T_HTF_IN, allocate("T_rec_in", n_steps_fixed), n_steps_fixed); collector_receiver.mc_reported_outputs.assign(C_csp_mspt_collector_receiver::E_T_HTF_OUT, allocate("T_rec_out", n_steps_fixed), n_steps_fixed); - collector_receiver.mc_reported_outputs.assign(C_csp_mspt_collector_receiver::E_Q_DOT_PIPE_LOSS, allocate("q_transport_losses", n_steps_fixed), n_steps_fixed); + collector_receiver.mc_reported_outputs.assign(C_csp_mspt_collector_receiver::E_Q_DOT_PIPE_LOSS, allocate("q_transport_loss", n_steps_fixed), n_steps_fixed); collector_receiver.mc_reported_outputs.assign(C_csp_mspt_collector_receiver::E_Q_DOT_LOSS, allocate("q_thermal_loss", n_steps_fixed), n_steps_fixed); - //collector_receiver.mc_reported_outputs.assign(C_csp_mspt_collector_receiver::E_Q_DOT_REFL_LOSS, allocate("q_dot_reflection_loss", n_steps_fixed), n_steps_fixed); + collector_receiver.mc_reported_outputs.assign(C_csp_mspt_collector_receiver::E_Q_DOT_REFL_LOSS, allocate("q_reflection_loss", n_steps_fixed), n_steps_fixed); collector_receiver.mc_reported_outputs.assign(C_csp_mspt_collector_receiver::E_W_DOT_TRACKING, allocate("pparasi", n_steps_fixed), n_steps_fixed); collector_receiver.mc_reported_outputs.assign(C_csp_mspt_collector_receiver::E_W_DOT_PUMP, allocate("P_tower_lift", n_steps_fixed), n_steps_fixed); @@ -2158,10 +2159,11 @@ class cm_csp_tower_particle : public compute_module accumulate_annual_for_year("P_cycle", "annual_W_cycle_gross", 1000.0*sim_setup.m_report_step / 3600.0, steps_per_hour, 1, n_steps_fixed/steps_per_hour); //[kWe-hr] accumulate_annual_for_year("P_cooling_tower_tot", "annual_W_cooling_tower", 1000.0*sim_setup.m_report_step / 3600.0, steps_per_hour, 1, n_steps_fixed / steps_per_hour); //[kWe-hr] - accumulate_annual_for_year("q_dot_rec_inc", "annual_q_rec_inc", sim_setup.m_report_step / 3600.0, steps_per_hour, 1, n_steps_fixed / steps_per_hour); //[MWt-hr] - accumulate_annual_for_year("q_thermal_loss", "annual_q_rec_loss", sim_setup.m_report_step / 3600.0, steps_per_hour, 1, n_steps_fixed / steps_per_hour); + accumulate_annual_for_year("q_dot_rec_inc", "annual_q_rec_inc", sim_setup.m_report_step / 3600.0, steps_per_hour, 1, n_steps_fixed / steps_per_hour); //[MWt-hr] // Incident power on particle curtain not including reflection (note that this is different than the definition of "incident" in the MSPT model) + accumulate_annual_for_year("q_reflection_loss", "annual_q_rec_reflection_loss", sim_setup.m_report_step / 3600.0, steps_per_hour, 1, n_steps_fixed / steps_per_hour); + accumulate_annual_for_year("q_thermal_loss", "annual_q_rec_thermal_loss", sim_setup.m_report_step / 3600.0, steps_per_hour, 1, n_steps_fixed / steps_per_hour); - assign("annual_eta_rec_th_incl_refl", (ssc_number_t)(1.0 - as_number("annual_q_rec_loss") / as_number("annual_q_rec_inc"))); + assign("annual_eta_rec", (ssc_number_t)(1.0 - (as_number("annual_q_rec_thermal_loss") + as_number("annual_q_rec_reflection_loss"))/ as_number("annual_q_rec_inc"))); accumulate_annual_for_year("disp_objective", "disp_objective_ann", sim_setup.m_report_step / 3600.0 / as_double("disp_frequency"), steps_per_hour, 1, n_steps_fixed/steps_per_hour); diff --git a/tcs/csp_solver_falling_particle_receiver.cpp b/tcs/csp_solver_falling_particle_receiver.cpp index 9b3b98cd5..0158d3a5c 100644 --- a/tcs/csp_solver_falling_particle_receiver.cpp +++ b/tcs/csp_solver_falling_particle_receiver.cpp @@ -135,6 +135,7 @@ C_falling_particle_receiver::C_falling_particle_receiver(double h_tower /*m*/, m_curtain_area = std::numeric_limits::quiet_NaN(); m_curtain_elem_area = std::numeric_limits::quiet_NaN(); m_back_wall_elem_area = std::numeric_limits::quiet_NaN(); + m_vf_curtain_ap_avg = std::numeric_limits::quiet_NaN(); // State variables m_E_su_prev = std::numeric_limits::quiet_NaN(); @@ -198,8 +199,9 @@ void C_falling_particle_receiver::init() m_t_su_prev = m_rec_su_delay; //[hr] Startup time requirement double c_htf_des = field_htfProps.Cp((m_T_htf_hot_des + m_T_htf_cold_des) / 2.0) * 1000.0; //[J/kg-K] Specific heat at design conditions - m_m_dot_htf_des = m_q_rec_des / (c_htf_des * (m_T_htf_hot_des - m_T_htf_cold_des)); //[kg/s] - m_m_dot_htf_max = m_m_dot_htf_max_frac * m_m_dot_htf_des; //[kg/s] + m_m_dot_htf_des = m_q_rec_des / (c_htf_des * (m_T_htf_hot_des - m_T_htf_cold_des)); //[kg/s] + m_m_dot_htf_max = m_m_dot_htf_max_frac * m_m_dot_htf_des; //[kg/s] + m_q_dot_inc_min = m_q_rec_des * m_f_rec_min / m_eta_therm_des_est; //[W] Minimum receiver thermal power // If no startup requirements, then receiver is always ON // ... in the sense that the controller doesn't need to worry about startup @@ -285,8 +287,8 @@ void C_falling_particle_receiver::call(const C_csp_weatherreader::S_outputs& wea double m_dot_tot, T_particle_hot, T_particle_hot_rec, eta, T_htf_prop, cp_htf, W_lift; m_dot_tot = T_particle_hot = T_particle_hot_rec = eta = T_htf_prop = cp_htf = W_lift = std::numeric_limits::quiet_NaN(); - double Q_inc, Q_refl, Q_adv, Q_rad, Q_transport, Q_thermal, Q_inc_pre_defocus; - Q_inc = Q_refl = Q_adv = Q_rad = Q_transport = Q_thermal = Q_inc_pre_defocus = std::numeric_limits::quiet_NaN(); + double Q_inc, Q_refl, Q_adv, Q_rad, Q_cond, Q_transport, Q_thermal, Q_inc_pre_defocus; + Q_inc = Q_refl = Q_adv = Q_rad = Q_cond = Q_transport = Q_thermal = Q_inc_pre_defocus = std::numeric_limits::quiet_NaN(); // Set current timestep stored values to NaN so we know that code solved for them @@ -492,6 +494,7 @@ void C_falling_particle_receiver::call(const C_csp_weatherreader::S_outputs& wea Q_refl = soln.Q_refl; Q_adv = soln.Q_adv; Q_rad = soln.Q_rad; + Q_cond = soln.Q_cond; Q_transport = soln.Q_transport; Q_thermal = soln.Q_thermal; @@ -581,7 +584,6 @@ void C_falling_particle_receiver::call(const C_csp_weatherreader::S_outputs& wea // After convergence, determine whether the mass flow rate falls below the lower limit if (Q_inc < m_q_dot_inc_min) { - // GOTO 900 // Steady State always reports Q_thermal (even when much less than min) because model is letting receiver begin startup with this energy // Should be a way to communicate to controller that Q_thermal is less than q_min without losing this functionality if (m_mode != C_csp_collector_receiver::STEADY_STATE || m_mode_prev == C_csp_collector_receiver::ON || m_mode_prev == C_csp_collector_receiver::OFF_NO_SU_REQ) @@ -603,6 +605,7 @@ void C_falling_particle_receiver::call(const C_csp_weatherreader::S_outputs& wea Q_refl = 0.0; Q_adv = 0.0; Q_rad = 0.0; + Q_cond = 0.0; Q_transport = 0.0; Q_thermal = 0.0; W_lift = 0.0; @@ -621,7 +624,7 @@ void C_falling_particle_receiver::call(const C_csp_weatherreader::S_outputs& wea outputs.m_m_dot_salt_tot = m_dot_tot * 3600.0; //[kg/hr] convert from kg/s outputs.m_eta_therm = eta; //[-] Receiver efficiency (includes curtain reflection, radiation and convective losses) outputs.m_W_dot_pump = W_lift / 1.E6; //[MW] convert from W - outputs.m_q_conv_sum = Q_adv / 1.E6; //[MW] convert from W + outputs.m_q_conv_sum = (Q_adv+Q_cond) / 1.E6; //[MW] convert from W // TODO: Lumping reported advection loss and conduction loss for now, would be better to separate outputs.m_q_rad_sum = Q_rad / 1.E6; //[MW] convert from W outputs.m_q_dot_refl_loss = Q_refl / 1.E6; outputs.m_Q_thermal = Q_thermal / 1.E6; //[MW] convert from W @@ -912,6 +915,7 @@ void C_falling_particle_receiver::calculate_steady_state_soln(s_steady_state_sol cp = field_htfProps.Cp(T_particle_prop) * 1000.0; // Particle specific heat [J/kg-K] evaluated at average of current inlet temperature and design outlet temperature T_cold_in_rec = T_cold_in - m_Q_dot_transport_loss_cold / cp / soln.m_dot_tot; // Inlet temperature to receiver accounting from loss from cold particle transport + double rhow = 1.0 - m_cav_emis; bool rec_is_off = false; bool converged = false; @@ -922,6 +926,12 @@ void C_falling_particle_receiver::calculate_steady_state_soln(s_steady_state_sol Q_thermal = m_fixed_efficiency * Q_inc; // Thermal power to particles in receiver [W] Tp_out = T_cold_in_rec + Q_thermal / (soln.m_dot_tot * cp); converged = true; + + Q_refl = 0.0; + Q_rad = 0.0; + Q_cond = 0.0; + Q_adv = (1.0 - m_fixed_efficiency)*Q_inc; // Artificially assign all losses as advection losses. These are only reported through the compute module as "thermal" losses + } else if (m_model_type == 1 || m_model_type == 2) // Receiver efficiency correlations from Sandia (https://www.osti.gov/biblio/1890267, page 43) { @@ -959,12 +969,24 @@ void C_falling_particle_receiver::calculate_steady_state_soln(s_steady_state_sol Q_thermal = eta*Q_inc; Tp_out = T_cold_in_rec + Q_thermal / (soln.m_dot_tot * cp); converged = true; + + Q_refl = 0.0; + Q_rad = 0.0; + Q_cond = 0.0; + Q_adv = (1.0 - eta) * Q_inc; // Artificially assign all losses as advection losses. These are only reported through the compute module as combined "thermal" losses + } else if (m_model_type == 3) // Quasi-2D physics-based receiver model { + double vel_out, Tfilm, hadv, fwind, Rwall, tauc1, rhoc1; + double qnet_ap, qnet_wf, hwconv, qadv, qtot, dh, Tcond_prev, Tcond_next; + double Twf, Twfnew, Tpdiff, Twdiff, Twfdiff; + util::matrix_t Tp, Tw, Tpnew, Twnew; + Rwall = 1.0 / m_cav_hext + m_cav_twall / m_cav_kwall; // Cavity wall thermal resistance + //--- Solve mass and momentum equations for curtain velocity, thickness, void fraction util::matrix_t mdot_per_elem(m_n_x); // Mass flow (kg/s) per element for (int i = 0; i < m_n_x; i++) @@ -972,9 +994,9 @@ void C_falling_particle_receiver::calculate_steady_state_soln(s_steady_state_sol mdot_per_elem.at(i) = soln.m_dot_tot / m_n_x; // TODO: Update to allow for multiple mass flow control zones } solve_particle_flow(mdot_per_elem, soln.phip, soln.vel, soln.thc); + vel_out = calculate_mass_wtd_avg_exit(mdot_per_elem, soln.vel); // Mass-weighted average exit velocity //--- Calculate curtain optical properties from solution for curtain void fraction and thickness - double tauc1, rhoc1; soln.tauc.resize_fill(m_n_y, m_n_x, 0.0); soln.rhoc.resize_fill(m_n_y, m_n_x, 0.0); for (int j = 0; j < m_n_y; j++) @@ -988,15 +1010,13 @@ void C_falling_particle_receiver::calculate_steady_state_soln(s_steady_state_sol } //--- Initialize solutions for particle and wall temperatures - double Twf, Twfnew; - util::matrix_t Tp, Tw, Tpnew, Twnew; Tp.resize_fill(m_n_y, m_n_x, T_cold_in_rec); // Particle temperature [K] Tpnew.resize_fill(m_n_y, m_n_x, T_cold_in_rec); Tw.resize_fill(m_n_y, m_n_x, T_cold_in_rec); // Back wall temperature [K] Twnew.resize_fill(m_n_y, m_n_x, T_cold_in_rec); + //--- Set initial guess for particle and wall temperatures - double power_approx, Tout_approx, dT, qnet_approx, eta_est; if (soln_exists && init_from_existing) { Tp = soln.T_p; @@ -1005,23 +1025,50 @@ void C_falling_particle_receiver::calculate_steady_state_soln(s_steady_state_sol } else { - eta_est = 0.85; - if (soln_exists && soln.eta > 0.0) - eta_est = soln.eta; - util::matrix_t flux_sum_over_heights = sum_over_rows(soln.q_dot_inc, true); + double qabs_approx, qnet_approx, dh_approx, rhoc_avg, flux_avg, Ec_avg, vf_to_ap; + + if (m_hadv_model_type == 0) + { + hadv = m_hadv_user; + fwind = 1.0; + } + else if (m_hadv_model_type == 1) // Use Sandia's correlations for advective loss + { + Tfilm = 0.5 * (0.5 * (m_T_htf_hot_des + T_cold_in_rec) + T_amb); + calculate_advection_coeff_sandia(vel_out, Tfilm, v_wind, wdir, P_amb, hadv, fwind); + hadv = fmax(hadv, 0.0); + } + else // TODO: Need an error here... eventually expand to include a lookup table + { + hadv = 0.0; + fwind = 1.0; + } + + rhoc_avg = flux_avg = Ec_avg = 0.0; + vf_to_ap = m_rad_model_type == 1 ? m_vf_curtain_ap_avg : m_vf_rad_type_0; for (int i = 0; i < m_n_x; i++) { - power_approx = eta_est * flux_sum_over_heights.at(i) * m_curtain_elem_area; // Approximate power to particles [W] - Tout_approx = T_cold_in_rec + power_approx / cp / mdot_per_elem.at(i); // Approximate particle exit temperature [K] - dT = (Tout_approx - T_cold_in_rec) / (m_n_y - 1); - for (int j = 0; j < m_n_y; j++) + Tp.at(0, i) = T_cold_in_rec; + for (int j=0; j0 ? soln.Q_thermal / soln.Q_inc : 0.0; soln.eta_with_transport = soln.Q_inc > 0 ? (soln.Q_thermal - m_Q_dot_transport_loss_cold - m_Q_dot_transport_loss_hot) / soln.Q_inc : 0.0; @@ -1342,9 +1387,6 @@ void C_falling_particle_receiver::solve_for_mass_flow(s_steady_state_soln &soln) { qq++; - if (qq > 0 && soln.rec_is_off) // SS solution was unsuccessful or resulted in an infeasible exit temperature ->start next iteration from the default intial guess - init_from_existing = false; - //-- Solve model at current mass flow guess soln.m_dot_tot = m_dot_guess; calculate_steady_state_soln(soln, tol, init_from_existing, 50); // Solve steady state thermal model @@ -1354,7 +1396,8 @@ void C_falling_particle_receiver::solve_for_mass_flow(s_steady_state_soln &soln) eta_history.at(qq) = soln.eta_with_transport; converged_history.at(qq) = soln.converged; - if (qq > 0 && std::abs(soln.T_particle_hot - Tout_history.at(qq - 1)) < 50) + init_from_existing = false; + if (qq>0 && !soln.rec_is_off && std::abs(soln.T_particle_hot - Tout_history.at(qq - 1)) < 20) init_from_existing = true; @@ -1739,6 +1782,7 @@ void C_falling_particle_receiver::calculate_view_factors() double dyg, dxg; int ifw = nelem - 1; // Index of front wall + m_vf_curtain_ap_avg = 0.0; y0 = 0; for (j = 0; j < ny; j++) { @@ -1751,11 +1795,12 @@ void C_falling_particle_receiver::calculate_view_factors() i = 1 + j * nx + k; // Front curtain element index in flattened array m_vf.at(i, 0) = vf_parallel_rect(x0*dx, y0*dy, side_width, top_height, dxg, dyg, m_ap_width, m_ap_height, m_curtain_dist); // View factor from front curtain element to full aperture - m_vf.at(0, i) = m_vf.at(i, 0) * (dxg * dyg / m_ap_area); // View factor from aperture to front curtain element - m_vf.at(i, ifw) = 1.0 - m_vf.at(i, 0); // View factor from front curtain element to front wall. Each element can only see the aperture or the front wall + m_vf.at(0, i) = m_vf.at(i, 0) * (dxg * dyg / m_ap_area); // View factor from aperture to front curtain element + m_vf.at(i, ifw) = 1.0 - m_vf.at(i, 0); // View factor from front curtain element to front wall. Each element can only see the aperture or the front wall m_vf.at(ifw, i) = m_vf.at(i, ifw) * (dxg * dyg / m_cav_front_area); // View factor from front wall to front curtain element vf_ap_sum += m_vf.at(0, i); // Sum of view factors from aperture to front curtain - vf_fw_sum += m_vf.at(ifw, i); // Sum of view factors from front wall to front curtain + vf_fw_sum += m_vf.at(ifw, i); // Sum of view factors from front wall to front curtain + m_vf_curtain_ap_avg += m_vf.at(i, 0) / (nx * ny); // Average view factor from front curtain to aperture if (is_symmetric && nx > 1) { @@ -1769,6 +1814,7 @@ void C_falling_particle_receiver::calculate_view_factors() m_vf.at(ifw, isym) = m_vf.at(ifw, i); vf_ap_sum += m_vf.at(0, isym); vf_fw_sum += m_vf.at(ifw, isym); + m_vf_curtain_ap_avg += m_vf.at(isym, 0) / (nx * ny); } } x0 += m_nx_per_group.at(k); diff --git a/tcs/csp_solver_falling_particle_receiver.h b/tcs/csp_solver_falling_particle_receiver.h index 1a5df91e8..dcbbbd272 100644 --- a/tcs/csp_solver_falling_particle_receiver.h +++ b/tcs/csp_solver_falling_particle_receiver.h @@ -75,6 +75,7 @@ class C_falling_particle_receiver : public C_pt_receiver double Q_refl; // Total solar reflection loss (W) double Q_rad; // Total radiation loss (W) double Q_adv; // Total advection loss (W) + double Q_cond; // Total conduction loss (W) double Q_transport; // Total thermal loss from particle transport (W) double Q_thermal; // Total thermal power delivered to the particles (including losses from particle transport) (W) double eta; // Receiver efficiency (energy to particles / solar energy incident on curtain) @@ -196,6 +197,7 @@ class C_falling_particle_receiver : public C_pt_receiver util::matrix_t m_nx_per_group; // Number of width elements per radiation group util::matrix_t m_ny_per_group; // Number of height elements per radiation group util::matrix_t m_vf; // View factor matrix + double m_vf_curtain_ap_avg; // Average view factor between curtain and aperture // State variables