Skip to content

Commit

Permalink
Merge branch 'patch' into iph_heat_sink
Browse files Browse the repository at this point in the history
  • Loading branch information
tyneises committed Jan 8, 2025
2 parents 57df699 + 20e6a0b commit cb9fc58
Show file tree
Hide file tree
Showing 28 changed files with 352 additions and 186 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ SSC is licensed with BSD-3-Clause terms, found [here](https://github.com/NREL/SA

# Citing this package

System Advisor Model Version 2023.12.17 (2023). SSC source code. National Renewable Energy Laboratory. Golden, CO. Accessed November 28, 2023. https://github.com/NREL/ssc
System Advisor Model Version 2024.12.12 (2024). SSC source code. National Renewable Energy Laboratory. Golden, CO. Accessed December 13, 2024. https://github.com/NREL/ssc
6 changes: 6 additions & 0 deletions shared/lib_battery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,12 @@ double battery_t::V_nominal() { return voltage->battery_voltage_nominal(); }

double battery_t::SOC() { return capacity->SOC(); }

double battery_t::SOC_max() { return capacity->SOC_max(); }

double battery_t::SOC_min() { return capacity->SOC_min(); }

double battery_t::nominal_energy() { return params->nominal_energy; }

double battery_t::I() { return capacity->I(); }

double battery_t::calculate_loss(double power, size_t lifetimeIndex) {
Expand Down
6 changes: 6 additions & 0 deletions shared/lib_battery.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,12 @@ class battery_t {

double SOC();

double SOC_max();

double SOC_min();

double nominal_energy();

double V(); // the actual battery voltage

double V_nominal(); // the nominal battery voltage
Expand Down
6 changes: 3 additions & 3 deletions shared/lib_battery_dispatch_automatic_btm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ void dispatch_automatic_behind_the_meter_t::costToCycle()
{
if (curr_year < m_battReplacementCostPerKWH.size()) {
double capacityPercentDamagePerCycle = _Battery->estimateCycleDamage();
m_cycleCost = 0.01 * capacityPercentDamagePerCycle * m_battReplacementCostPerKWH[curr_year] * _Battery->get_params().nominal_energy;
m_cycleCost = 0.01 * capacityPercentDamagePerCycle * m_battReplacementCostPerKWH[curr_year] * _Battery->nominal_energy();
}
else {
// Should only apply to BattWatts. BattWatts doesn't have retal rate dispatch, so this is fine.
Expand All @@ -915,13 +915,13 @@ void dispatch_automatic_behind_the_meter_t::costToCycle()
}
else if (m_battCycleCostChoice == dispatch_t::INPUT_CYCLE_COST)
{
m_cycleCost = cycle_costs_by_year[curr_year] * _Battery->get_params().nominal_energy;
m_cycleCost = cycle_costs_by_year[curr_year] * _Battery->nominal_energy();
}
}

double dispatch_automatic_behind_the_meter_t::cost_to_cycle_per_kwh()
{
return m_cycleCost / _Battery->get_params().nominal_energy;
return m_cycleCost / _Battery->nominal_energy();
}

double dispatch_automatic_behind_the_meter_t::omCost()
Expand Down
4 changes: 2 additions & 2 deletions shared/lib_battery_dispatch_pvsmoothing_fom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ void dispatch_pvsmoothing_front_of_meter_t::update_dispatch(size_t year, size_t
ssc_number_t battery_energy = _Battery->energy_nominal();
ssc_number_t batt_half_round_trip_eff = sqrt(m_etaDischarge * m_etaPVCharge);
ssc_number_t battery_power = m_batteryPower->getMaxACChargePower();
ssc_number_t soc_min = _Battery->get_params().capacity->minimum_SOC * 0.01;
ssc_number_t soc_max = _Battery->get_params().capacity->maximum_SOC * 0.01;
ssc_number_t soc_min = _Battery->SOC_min() * 0.01;
ssc_number_t soc_max = _Battery->SOC_max() * 0.01;
// scale by nameplate per ERPI code
battery_energy = m_batt_dispatch_pvs_nameplate_ac > 0 ? battery_energy / m_batt_dispatch_pvs_nameplate_ac : battery_energy;
battery_power = m_batt_dispatch_pvs_nameplate_ac > 0 ? battery_power / m_batt_dispatch_pvs_nameplate_ac : battery_power;
Expand Down
2 changes: 1 addition & 1 deletion ssc/cmod_etes_electric_resistance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ class cm_etes_electric_resistance : public compute_module
// User-Defined Cycle Parameters
pc->m_W_dot_cooling_des = as_double("ud_f_W_dot_cool_des") / 100.0 * as_double("P_ref"); //[MWe]
pc->m_m_dot_water_des = as_double("ud_m_dot_water_cool_des"); //[kg/s]
pc->m_is_udpc_sco2_regr = as_boolean("ud_is_sco2_regr"); //[-]
pc->m_is_udpc_sco2_regr = as_integer("ud_is_sco2_regr"); //[-]

// User-Defined Cycle Off-Design Tables
pc->mc_combined_ind = as_matrix("ud_ind_od");
Expand Down
75 changes: 38 additions & 37 deletions ssc/cmod_fresnel_physical.cpp

Large diffs are not rendered by default.

82 changes: 46 additions & 36 deletions ssc/cmod_fresnel_physical_iph.cpp

Large diffs are not rendered by default.

63 changes: 35 additions & 28 deletions ssc/cmod_hybrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,6 @@ class cm_hybrid : public compute_module

ssc_module_exec_with_error(module, input, compute_module);

ssc_number_t system_capacity = compute_module_inputs->table.lookup("system_capacity")->num;
hybridSystemCapacity += system_capacity;
hybridTotalInstalledCost += compute_module_inputs->table.lookup("total_installed_cost")->num;

ssc_data_t compute_module_outputs = ssc_data_create();

int pidx = 0;
Expand All @@ -174,6 +170,13 @@ class cm_hybrid : public compute_module
if (compute_module_inputs->table.lookup("system_use_lifetime_output"))
system_use_lifetime_output = compute_module_inputs->table.lookup("system_use_lifetime_output")->num;

ssc_number_t system_capacity = compute_module_inputs->table.lookup("system_capacity")->num;
if ((compute_module == "pvsamv1") || (compute_module == "pvwattsv8")) {
ssc_data_get_number(compute_module_outputs, "system_capacity_ac", &system_capacity);
}
hybridSystemCapacity += system_capacity;
hybridTotalInstalledCost += compute_module_inputs->table.lookup("total_installed_cost")->num;

// get minimum timestep from gen vector
ssc_number_t* curGen = ssc_data_get_array(compute_module_outputs, "gen", &len);
currentTimeStepsPerHour = len / 8760;
Expand Down Expand Up @@ -287,26 +290,6 @@ class cm_hybrid : public compute_module
}
}

// monthly energy generated
size_t step_per_hour = maximumTimeStepsPerHour;
ssc_number_t* pGenMonthly = ((var_table*)outputs)->allocate("monthly_energy", 12);
size_t c = 0;
for (int m = 0; m < 12; m++) // each month
{
pGenMonthly[m] = 0;
for (size_t d = 0; d < util::nday[m]; d++) // for each day in each month
for (int h = 0; h < 24; h++) // for each hour in each day
for (size_t j = 0; j < step_per_hour; j++)
pGenMonthly[m] += pGen[c++];
}

ssc_number_t pGenAnnual = 0;
for (size_t i = 0; i < genLength; i++)
pGenAnnual += pGen[i];
((var_table*)outputs)->assign("annual_energy", var_data(pGenAnnual));



if (fuelcells.size() > 0) { // run single fuel cell if present

percent = 100.0f * ((float)(generators.size() + fuelcells.size()) / (float)(generators.size() + fuelcells.size() + batteries.size() + financials.size()));
Expand Down Expand Up @@ -564,8 +547,35 @@ class cm_hybrid : public compute_module
if (batteries.size() > 0) {
use_batt_output = true;
pBattGen = ((var_table*)outputs)->lookup(batteries[0])->table.as_array("gen", &battGenLen);
if (battGenLen == genLength) {
for (size_t g = 0; g < genLength; g++) {
// Batt's gen is an inout that includes other system components
pGen[g] = pBattGen[g];
}
}
else {
throw exec_error("hybrid", util::format("Battery gen length incorrect, battery timeseries contains %d entries, generators contain %d", battGenLen, genLength));
}
}

// monthly energy generated
size_t step_per_hour = maximumTimeStepsPerHour;
ssc_number_t* pGenMonthly = ((var_table*)outputs)->allocate("monthly_energy", 12);
size_t c = 0;
for (int m = 0; m < 12; m++) // each month
{
pGenMonthly[m] = 0;
for (size_t d = 0; d < util::nday[m]; d++) // for each day in each month
for (int h = 0; h < 24; h++) // for each hour in each day
for (size_t j = 0; j < step_per_hour; j++)
pGenMonthly[m] += pGen[c++];
}

ssc_number_t pGenAnnual = 0;
for (size_t i = 0; i < genLength; i++)
pGenAnnual += pGen[i];
((var_table*)outputs)->assign("annual_energy", var_data(pGenAnnual));

ssc_number_t* pHybridOMSum = ((var_table*)outputs)->allocate("cf_hybrid_om_sum", analysisPeriod + 1); // add to top level "output" - assumes analysis period the same for all generators

for (int i = 0; i <= analysisPeriod; i++)
Expand Down Expand Up @@ -636,10 +646,7 @@ class cm_hybrid : public compute_module
var_data* compute_module_inputs = input_table->table.lookup(hybridVarTable);
var_table& input = compute_module_inputs->table;

// if (use_batt_output)
// ssc_data_set_array(static_cast<ssc_data_t>(&input), "gen", pBattGen, (int)battGenLen);
// else
ssc_data_set_array(static_cast<ssc_data_t>(&input), "gen", pGen, (int)genLength);
ssc_data_set_array(static_cast<ssc_data_t>(&input), "gen", pGen, (int)genLength);

if (batteries.size() > 0)
ssc_data_set_number(static_cast<ssc_data_t>(&input), "is_hybrid", 1); // for updating battery outputs to annual length in update_battery_outputs in common_financial.cpp
Expand Down
58 changes: 29 additions & 29 deletions ssc/cmod_mhk_costs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,58 +167,58 @@ class cm_mhk_costs : public compute_module
//Most CapEx costs depend on technology
if (technology == TIDAL)
{ // device = RM1
structural_assembly = 284245.0 * system_capacity_MW + 785137.0;
power_takeoff = 1527017.0 * system_capacity_MW + 505548.0;
mooring_found_substruc = 437091.0 * system_capacity_MW + 433518.0;
structural_assembly = 417185.0 * system_capacity_MW + 1068446.0;
power_takeoff = 1821066.0 * system_capacity_MW + 602898.0;
mooring_found_substruc = 443055.0 * system_capacity_MW + 384877.0;
//BOS costs SAM Cost Model v8.xlsx
development = 3197591.76 * pow(system_capacity_MW, 0.49);
eng_and_mgmt = 850744.0 * pow(system_capacity_MW, 0.565);
development = 189783 * system_capacity_MW + 8935599;
eng_and_mgmt = 78127 * system_capacity_MW + 2325517;
}
else // wave
{
if (device_type == RM3)
{
structural_assembly = 6854912.0 * system_capacity_MW + 2629191.0;
power_takeoff = 2081129.0 * pow(system_capacity_MW, 0.91);
mooring_found_substruc = 1836365.0 * system_capacity_MW + 29672.0;
structural_assembly = 8174919.0 * system_capacity_MW + 3135478.0;
power_takeoff = 2481879.0 * pow(system_capacity_MW, 0.91);
mooring_found_substruc = 2189982.0 * system_capacity_MW + 35386.0;
//BOS costs SAM Cost Model v8.xlsx
development = 3197591.76 * pow(system_capacity_MW, 0.49);
eng_and_mgmt = 850744.0 * pow(system_capacity_MW, 0.5649);
development = 189783 * system_capacity_MW + 8935599;
eng_and_mgmt = 78127 * system_capacity_MW + 2325517;
}

else if (device_type == RM5)
{
structural_assembly = 6848402.0 * system_capacity_MW + 3315338.0;
power_takeoff = 1600927.0 * pow(system_capacity_MW, 0.91);
mooring_found_substruc = 2158462.0 * system_capacity_MW + 1048932.0;
structural_assembly = 8167155.0 * system_capacity_MW + 3953752.0;
power_takeoff = 1909207.0 * pow(system_capacity_MW, 0.91);
mooring_found_substruc = 2574104.0 * system_capacity_MW + 1250918.0;
//BOS costs SAM Cost Model v8.xlsx
development = 3197591.76 * pow(system_capacity_MW, 0.49);
eng_and_mgmt = 850744.0 * pow(system_capacity_MW, 0.5649);
development = 189783 * system_capacity_MW + 8935599;
eng_and_mgmt = 78127 * system_capacity_MW + 2325517;
}

else if (device_type == RM6)
{
structural_assembly = 13320092.0 * system_capacity_MW + 6681164.0;
power_takeoff = 3796551.0 * pow(system_capacity_MW, 0.78);
mooring_found_substruc = 2030816.0 * system_capacity_MW + 478400.0;
structural_assembly = 15885057.0 * system_capacity_MW + 7967714.0;
power_takeoff = 4527629.0 * pow(system_capacity_MW, 0.78);
mooring_found_substruc = 2421878.0 * system_capacity_MW + 570523.0;
//BOS costs SAM Cost Model v8.xlsx
development = 3197591.76 * pow(system_capacity_MW, 0.49);
eng_and_mgmt = 850744.0 * pow(system_capacity_MW, 0.565);
development = 189783 * system_capacity_MW + 8935599;
eng_and_mgmt = 78127 * system_capacity_MW + 2325517;
}

else //generic model applies to everything else
{
structural_assembly = 6854912.0 * system_capacity_MW + 2629191.0;
power_takeoff = 1179579.0 * system_capacity_MW + 2495107.0;
mooring_found_substruc = 1178598.0 * system_capacity_MW + 1602348.0;
structural_assembly = 7708042.0 * system_capacity_MW + 7092078;
power_takeoff = 1550104.0 * system_capacity_MW + 5331628.0;
mooring_found_substruc = 1619167.0 * system_capacity_MW;
//BOS costs SAM Cost Model v8.xlsx
development = 3197591.0 * pow(system_capacity_MW, 0.49);
eng_and_mgmt = 850744.0 * pow(system_capacity_MW, 0.565);
development = 189783 * system_capacity_MW + 8935599;
eng_and_mgmt = 78127 * system_capacity_MW + 2325517;
}
}

// REmaining BOS costs that are not CapEx dependent and not technology dependent
assembly_and_install = 2805302.0 * pow(system_capacity_MW, 0.66);
assembly_and_install = 2564748 * pow(system_capacity_MW, 0.67);
other_infrastructure = 0;

//electrical infrastructure costs
Expand Down Expand Up @@ -338,11 +338,11 @@ class cm_mhk_costs : public compute_module
+ array_cable_system + export_cable_system + onshore_substation + offshore_substation + other_elec_infra;

// Calculate the CapEx dependent BOS costs
plant_commissioning = 0.016 * capex;
site_access_port_staging = 0.011 * capex;
plant_commissioning = 56103 * system_capacity_MW;
site_access_port_staging = 75462 * system_capacity_MW;

// Calculate the CapEx-dependent financial costs
project_contingency = 0.05 * capex;
project_contingency = 0.08 * capex;
insurance_during_construction = 0.01 * capex;
reserve_accounts = 0.03 * capex;

Expand Down
5 changes: 2 additions & 3 deletions ssc/cmod_mhk_tidal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ class cm_mhk_tidal : public compute_module
//Read and store tidal resource and power curve:
util::matrix_t<double> tidal_resource_matrix = as_matrix("tidal_resource");
util::matrix_t<double> tidal_power_curve = as_matrix("tidal_power_curve");
int tidal_resource_model_choice = as_integer("tidal_resource_model_choice");
//Check to ensure size of _power_vect == _speed_vect :
if ( tidal_power_curve.nrows() != tidal_resource_matrix.nrows() )
if ( tidal_resource_model_choice == 0 && tidal_power_curve.nrows() != tidal_resource_matrix.nrows() )
throw exec_error("mhk_tidal", "Size of Power Curve is not equal to Tidal Resource");

//Store the number of rows- this will have to change if resource and power curve can have different stream speeds
Expand Down Expand Up @@ -155,7 +155,6 @@ class cm_mhk_tidal : public compute_module
+ as_double("loss_downtime")
+ as_double("loss_additional");

int tidal_resource_model_choice = as_integer("tidal_resource_model_choice");
double tidal_resource_start_velocity = 0;
double tidal_power_start_velocity = 0;
double tidal_resource_end_velocity = 0;
Expand Down
7 changes: 5 additions & 2 deletions ssc/cmod_mspt_iph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ class cm_mspt_iph : public compute_module
// ***********************************************

int hs_type = as_integer("hs_type");
C_csp_power_cycle* c_heat_sink_pointer;
C_csp_power_cycle* c_heat_sink_pointer = nullptr;
C_pc_heat_sink c_heat_sink;
C_pc_heat_sink_physical c_heat_sink_phys;

Expand Down Expand Up @@ -1296,7 +1296,10 @@ class cm_mspt_iph : public compute_module
{
throw exec_error("mspt_iph", "hs_type must be 0-1");
}

if (c_heat_sink_pointer == nullptr)
{
throw exec_error("mspt_iph", "Heat sink pointer not assigned");
}

//// *********************************************************
//// *********************************************************
Expand Down
3 changes: 3 additions & 0 deletions ssc/cmod_pvsamv1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,8 @@ static var_info _cm_vtab_pvsamv1[] = {
//miscellaneous outputs
{ SSC_OUTPUT, SSC_NUMBER, "ts_shift_hours", "Sun position time offset", "hours", "", "Miscellaneous", "", "", "" },
{ SSC_OUTPUT, SSC_NUMBER, "nameplate_dc_rating", "System nameplate DC rating", "kW", "", "Miscellaneous", "*", "", "" },
{ SSC_OUTPUT, SSC_NUMBER, "system_capacity_ac", "System nameplate AC rating", "kWac", "", "Miscellaneous", "", "", "" },



// test outputs
Expand Down Expand Up @@ -3594,6 +3596,7 @@ void cm_pvsamv1::exec()
kWhACperkWAC = annual_energy / nameplate_ac_kW;
}
assign("capacity_factor_ac", var_data((ssc_number_t)(kWhACperkWAC / 87.6)));
assign("system_capacity_ac", var_data((ssc_number_t)nameplate_ac_kW));

if (is_assigned("load"))
{
Expand Down
2 changes: 2 additions & 0 deletions ssc/cmod_pvwattsv8.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ static var_info _cm_vtab_pvwattsv8[] = {

{ SSC_OUTPUT, SSC_NUMBER, "ts_shift_hours", "Time offset for interpreting time series outputs", "hours","", "Miscellaneous", "*", "", "" },
{ SSC_OUTPUT, SSC_NUMBER, "percent_complete", "Estimated percent of total completed simulation", "%", "", "Miscellaneous", "", "", "" },
{ SSC_OUTPUT, SSC_NUMBER, "system_capacity_ac", "System nameplate AC rating", "kWac", "", "Miscellaneous", "", "", "" },

var_info_invalid };

Expand Down Expand Up @@ -1442,6 +1443,7 @@ class cm_pvwattsv8 : public compute_module

// for battery model, specify a number of inverters
assign("inverter_efficiency", var_data((ssc_number_t)(as_double("inv_eff"))));
assign("system_capacity_ac", var_data((ssc_number_t)pv.ac_nameplate / 1000.0));

if (en_snowloss && snowmodel.badValues > 0)
log(util::format("The snow model has detected %d bad snow depth values (less than 0 or greater than 610 cm). These values have been set to zero.", snowmodel.badValues), SSC_WARNING);
Expand Down
Loading

0 comments on commit cb9fc58

Please sign in to comment.