Skip to content

Commit

Permalink
added particle receiver to solarpilot cmod
Browse files Browse the repository at this point in the history
  • Loading branch information
qualand committed Dec 11, 2023
1 parent 47f6114 commit 5363fed
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 278 deletions.
529 changes: 261 additions & 268 deletions ssc/cmod_csp_tower_particle.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion ssc/cmod_etes_electric_resistance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ class cm_etes_electric_resistance : public compute_module
pc->m_CT = as_integer("CT"); // cooling tech type: 1=evaporative, 2=air, 3=hybrid
if (pc->m_CT > 2) {
std::string err_msg = util::format("The specified power cycle cooling tech type, %d, does not exist"
" for the ETES electric resistance heating model. Choose from 1) evaporative or 2) air\n", pb_tech_type);
" for the ETES electric resistance heating model. Choose from 1) evaporative or 2) air\n", pc->m_CT);
log(err_msg, SSC_WARNING);
return;
}
Expand Down
31 changes: 24 additions & 7 deletions ssc/cmod_solarpilot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,26 @@ static var_info _cm_vtab_solarpilot[] = {
{ SSC_INPUT, SSC_STRING, "solar_resource_file", "Solar weather data file", "", "", "SolarPILOT", "?", "LOCAL_FILE", "" },

{ SSC_INPUT, SSC_NUMBER, "receiver_type", "0: external (default), 1; cavity", "", "", "SolarPILOT", "?=0", "", "" },
{ SSC_INPUT, SSC_NUMBER, "rec_height", "External receiver height", "m", "", "SolarPILOT", "receiver_type=0", "", "" },
{ SSC_INPUT, SSC_NUMBER, "rec_aspect", "External receiver aspect ratio (H/W)", "frac", "", "SolarPILOT", "receiver_type=0", "", "" },
{ SSC_INPUT, SSC_NUMBER, "rec_height", "External receiver height", "m", "", "SolarPILOT", "receiver_type=0|receiver_type=3", "", "" },
{ SSC_INPUT, SSC_NUMBER, "rec_aspect", "Receiver aspect ratio (H/W)", "frac", "", "SolarPILOT", "receiver_type=0", "", "" },
{ SSC_INPUT, SSC_NUMBER, "cav_rec_height", "Cavity receiver height", "m", "", "SolarPILOT", "receiver_type=1", "", "" },
{ SSC_INPUT, SSC_NUMBER, "cav_rec_width", "Cavity receiver width", "m", "", "SolarPILOT", "receiver_type=1", "", "" },
{ SSC_INPUT, SSC_NUMBER, "n_cav_rec_panels", "Cavity receiver number of panels", "", "", "SolarPILOT", "receiver_type=1", "", "" },
{ SSC_INPUT, SSC_NUMBER, "cav_rec_span", "Cavity receiver span angle", "deg", "", "SolarPILOT", "receiver_type=1", "", "" },

// Free-falling particle receiver
{ SSC_INPUT, SSC_NUMBER, "rec_width", "Aperture width - in", "m", "", "SolarPILOT", "receiver_type=3", "", ""},
{ SSC_INPUT, SSC_NUMBER, "norm_curtain_height", "Normalized particle curtain height", "", "", "SolarPILOT", "receiver_type=3", "", ""},
{ SSC_INPUT, SSC_NUMBER, "norm_curtain_width", "Normalized particle curtain width", "", "", "SolarPILOT", "receiver_type=3", "", ""},
{ SSC_INPUT, SSC_NUMBER, "max_curtain_depth", "Particle curtain entrance depth", "m", "", "SolarPILOT", "receiver_type=3", "", ""},
{ SSC_INPUT, SSC_MATRIX, "norm_heights_depths", "Normalized troughs heights and depths, pass [[0,0]] for no curtain troughs", "", "", "SolarPILOT", "receiver_type=3", "", ""},
{ SSC_INPUT, SSC_NUMBER, "curtain_type", "Flat=0;Curved=1", "", "", "SolarPILOT", "receiver_type=3", "", ""},
//{ SSC_INPUT, SSC_NUMBER, "curtain_radius", "Particle curtain radius", "m", "", "SolarPILOT", "receiver_type=3&curtain_type=1", "", ""},
{ SSC_INPUT, SSC_NUMBER, "is_snout", "Is SNOUT enabled?", "", "", "SolarPILOT", "receiver_type=3", "", ""},
{ SSC_INPUT, SSC_NUMBER, "snout_depth", "Distance from aperture window to SNOUT front plane", "m", "", "SolarPILOT", "receiver_type=3&is_snout=1", "", ""},
{ SSC_INPUT, SSC_NUMBER, "snout_horiz_angle", "SNOUT spanning angle defined in the aperture vertical mid-plane", "deg", "", "SolarPILOT", "receiver_type=3&is_snout=1", "", ""},
{ SSC_INPUT, SSC_NUMBER, "snout_vert_bot_angle", "SNOUT bottom surface angle from aperture normal", "deg", "", "SolarPILOT", "receiver_type=3&is_snout=1", "", ""},
{ SSC_INPUT, SSC_NUMBER, "snout_vert_top_angle", "SNOUT top surface angle from aperture normal", "deg", "", "SolarPILOT", "receiver_type=3&is_snout=1", "", ""},

{ SSC_INPUT, SSC_NUMBER, "helio_width", "Heliostat width", "m", "", "SolarPILOT", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "helio_height", "Heliostat height", "m", "", "SolarPILOT", "*", "", "" },
Expand Down Expand Up @@ -119,13 +132,13 @@ static var_info _cm_vtab_solarpilot[] = {
{ SSC_INPUT, SSC_NUMBER, "contingency_rate", "Contingency for cost overrun", "%", "", "SolarPILOT", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "sales_tax_rate", "Sales tax rate", "%", "", "SolarPILOT", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "sales_tax_frac", "Percent of cost to which sales tax applies", "%", "", "SolarPILOT", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "cost_sf_fixed", "Soalr field fixed cost", "$", "", "SolarPILOT", "*", "", "" },
{ SSC_INPUT, SSC_NUMBER, "cost_sf_fixed", "Solar field fixed cost", "$", "", "SolarPILOT", "*", "", "" },

{ SSC_INPUT, SSC_NUMBER, "is_optimize", "Do SolarPILOT optimization", "", "", "SolarPILOT", "?=0", "", "" },
{ SSC_INPUT, SSC_NUMBER, "flux_max", "Maximum allowable flux", "", "", "SolarPILOT", "?=1000", "", "" },
{ SSC_INPUT, SSC_NUMBER, "opt_init_step", "Optimization initial step size", "", "", "SolarPILOT", "?=0.05", "", "" },
{ SSC_INPUT, SSC_NUMBER, "opt_max_iter", "Max. number iteration steps", "", "", "SolarPILOT", "?=200", "", "" },
{ SSC_INPUT, SSC_NUMBER, "opt_conv_tol", "Optimization convergence tol", "", "", "SolarPILOT", "?=0.001", "", "" },
{ SSC_INPUT, SSC_NUMBER, "opt_conv_tol", "Optimization convergence tolerance", "", "", "SolarPILOT", "?=0.001", "", "" },
{ SSC_INPUT, SSC_NUMBER, "opt_algorithm", "Optimization algorithm", "", "", "SolarPILOT", "?=1", "", "" },
{ SSC_INPUT, SSC_NUMBER, "opt_flux_penalty", "Optimization flux overage penalty", "", "", "SolarPILOT", "*", "", "" },
{ SSC_INPUT, SSC_MATRIX, "helio_positions_in", "Heliostat position table", "", "", "SolarPILOT", "", "", "" },
Expand All @@ -143,6 +156,7 @@ static var_info _cm_vtab_solarpilot[] = {
{ SSC_OUTPUT, SSC_NUMBER, "rec_height_opt", "Optimized receiver height", "m", "", "SolarPILOT", "*", "", "" },
{ SSC_OUTPUT, SSC_NUMBER, "rec_aspect_opt", "Optimized receiver aspect ratio", "-", "", "SolarPILOT", "receiver_type=0", "", "" },
{ SSC_OUTPUT, SSC_NUMBER, "cav_rec_aper_width_opt", "Optimized cavity receiver aperture width", "-", "", "SolarPILOT", "receiver_type=1", "", "" },
{ SSC_OUTPUT, SSC_NUMBER, "rec_width_opt", "Optimized receiver width", "m", "", "SolarPILOT", "receiver_type=3", "", "" },
{ SSC_OUTPUT, SSC_NUMBER, "flux_max_observed", "Maximum observed flux at design", "kW/m2", "", "SolarPILOT", "check_max_flux=1", "", "" },

{ SSC_OUTPUT, SSC_NUMBER, "cost_rec_tot", "Total receiver cost", "$", "", "SolarPILOT", "*", "", "" },
Expand Down Expand Up @@ -181,12 +195,12 @@ class cm_solarpilot : public compute_module

// Post-process solarpilot outputs for receiver configs
// Set outputs unique to receiver configs
if (rec_type == 0) {
if (rec_type == 0) { // external

assign("rec_aspect_opt", (ssc_number_t)spi.recs.front().rec_aspect.Val());

}
else if (rec_type == 1) {
else if (rec_type == 1) { // cavity

double cav_rec_height_spout, cav_radius_spout, f_offset_spout;
cav_rec_height_spout = cav_radius_spout = f_offset_spout = std::numeric_limits<double>::quiet_NaN();
Expand All @@ -211,6 +225,9 @@ class cm_solarpilot : public compute_module

assign("cav_rec_aper_width_opt", (ssc_number_t)rec_width_calc);
}
else if (rec_type == 3) { // free-falling receiver
assign("rec_width_opt", (ssc_number_t)spi.recs.front().rec_width.val);
}

assign("h_tower_opt", (ssc_number_t)spi.sf.tht.val);
assign("rec_height_opt", (ssc_number_t)spi.recs.front().rec_height.val);
Expand Down Expand Up @@ -269,7 +286,7 @@ class cm_solarpilot : public compute_module
for( size_t i=0;i<nvals;i++ )
{
opteff[i * 3] = (ssc_number_t)(spi.fluxtab.azimuths[i] * 180. / pi - 180.); //Convention is usually S=0, E<0, W>0
opteff[i * 3 + 1] = (ssc_number_t)(spi.fluxtab.zeniths[i] * 180. / pi); //Provide zenith angle
opteff[i * 3 + 1] = (ssc_number_t)(spi.fluxtab.zeniths[i] * 180. / pi); //Provide zenith angle
opteff[i * 3 + 2] = (ssc_number_t)spi.fluxtab.efficiency[i];
}
}
Expand Down
2 changes: 1 addition & 1 deletion ssc/cmod_tcsmolten_salt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ class cm_tcsmolten_salt : public compute_module
assign("n_flux_x", 2); // n_flux_x represents *per panel* the number subsurfaces in x direction
}
else {
throw exec_error("tcsmolten_salt", "receiver_type must be 1 (external) or 0 (cavity)");
throw exec_error("tcsmolten_salt", "receiver_type must be 0 (external) or 1 (cavity)");
}

if ((field_model_type == 0 || field_model_type == 1) && sim_type == 1) // Auto-design. Generate a new system (is_optimize = true) or field layout
Expand Down
7 changes: 6 additions & 1 deletion ssc/csp_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ bool solarpilot_invoke::run(std::shared_ptr<weather_data_provider> wdata)
rf->rec_type.val = "Falling particle";
rf->rec_height.val = m_cmod->as_double("rec_height");
rf->rec_width.val = m_cmod->as_double("rec_width");
rf->absorptance.val = 1.0;

// Curtain dimensions
rf->norm_curtain_height.val = m_cmod->as_double("norm_curtain_height"); // [-]
Expand Down Expand Up @@ -519,7 +520,11 @@ bool solarpilot_invoke::run(std::shared_ptr<weather_data_provider> wdata)

int nflux_x = m_cmod->as_integer("n_flux_x");
int nflux_y = m_cmod->as_integer("n_flux_y");
if(! m_sapi->CalculateFluxMaps(fluxtab, nflux_x, nflux_y, true) )

if (nflux_x < 1 || nflux_y < 1)
throw exec_error("solarpilot", "flux map resolution must be a positive integer");

if(! m_sapi->CalculateFluxMaps(fluxtab, nflux_x, nflux_y, true) )
{
flux.aim_method.combo_select( aim_method_save );
return false; //simulation failed or was canceled.
Expand Down
3 changes: 3 additions & 0 deletions tcs/csp_solver_falling_particle_receiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ void C_falling_particle_receiver::init()
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
m_W_dot_pumping_tower_share = (m_m_dot_htf_des * m_h_tower * 9.8067 / m_eta_pump) / 1.e6; // [MWe]
m_W_dot_pumping_rec_share = (m_m_dot_htf_des * m_curtain_height * 9.8067 / m_eta_pump) / 1.e6; // [MWe]
m_W_dot_rec_pump_des_calc = m_W_dot_pumping_tower_share + m_W_dot_pumping_rec_share;


// If no startup requirements, then receiver is always ON
Expand Down

0 comments on commit 5363fed

Please sign in to comment.