Skip to content

Commit

Permalink
Merge branch 'develop' into marine-geothermal-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
mjprilliman committed Nov 17, 2023
2 parents 829bcaf + 047030c commit 77bd65f
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 18 deletions.
8 changes: 6 additions & 2 deletions shared/lib_battery_dispatch_automatic_fom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,12 @@ void dispatch_automatic_front_of_meter_t::setup_cost_forecast_vector()

ppa_prices.reserve(_forecast_hours * _steps_per_hour);
if (discharge_hours >= _forecast_hours * _steps_per_hour) {
// -1 for 0 indexed arrays, additional -1 to ensure there is always a charging price lower than the discharing price if the forecast hours is = to battery capacity in hourrs
discharge_hours = _forecast_hours * _steps_per_hour - 2;
// -1 for 0 indexed arrays, additional -1 to ensure there is always a charging price lower than the discharing price if the forecast hours is = to battery capacity in hours
// exception caused if look_ahead_hours <= 1 and _steps_per_hour =1 ). specifically, size_t extremely large if set to negative integer - see SAM issue 1547
if ((int)_forecast_hours * (int)_steps_per_hour - 2 < 0) // handles 1 hour look ahead but 0 hour look ahead still fails (should not be allowed)
discharge_hours = 0;
else
discharge_hours = _forecast_hours * _steps_per_hour - 2;
}
}

Expand Down
2 changes: 1 addition & 1 deletion ssc/cmod_battery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ var_info vtab_battery_inputs[] = {
{ SSC_INPUT, SSC_NUMBER, "batt_dispatch_auto_btm_can_discharge_to_grid", "Behind the meter battery can discharge to grid?", "0/1", "", "BatteryDispatch", "", "", "" },
{ SSC_INPUT, SSC_NUMBER, "batt_dispatch_charge_only_system_exceeds_load", "Battery can charge from system only when system output exceeds load", "0/1", "", "BatteryDispatch", "en_batt=1&en_standalone_batt=0&batt_meter_position=0", "", "" },
{ SSC_INPUT, SSC_NUMBER, "batt_dispatch_discharge_only_load_exceeds_system","Battery can discharge battery only when load exceeds system output", "0/1", "", "BatteryDispatch", "en_batt=1&en_standalone_batt=0&batt_meter_position=0", "", "" },
{ SSC_INPUT, SSC_NUMBER, "batt_look_ahead_hours", "Hours to look ahead in automated dispatch", "hours", "", "BatteryDispatch", "", "", "" },
{ SSC_INPUT, SSC_NUMBER, "batt_look_ahead_hours", "Hours to look ahead in automated dispatch", "hours", "", "BatteryDispatch", "", "MIN=1", "" },
{ SSC_INPUT, SSC_NUMBER, "batt_dispatch_update_frequency_hours", "Frequency to update the look-ahead dispatch", "hours", "", "BatteryDispatch", "", "", "" },

// PV smoothing specific inputs
Expand Down
2 changes: 1 addition & 1 deletion ssc/cmod_hcpv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ class cm_hcpv : public compute_module

adjustment_factors haf(this, "adjust");
if (!haf.setup())
throw exec_error("pvwattsv5", "failed to setup adjustment factors: " + haf.error());
throw exec_error("hcpv", "failed to setup adjustment factors: " + haf.error());



Expand Down
6 changes: 5 additions & 1 deletion ssc/cmod_windpower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ void cm_windpower::exec()
if (wpc.nTurbines > wpc.GetMaxTurbines())
throw exec_error("windpower", util::format("the wind model is only configured to handle up to %d turbines.", wpc.GetMaxTurbines()));

// create adjustment factors and losses
// create adjustment factors and losses - set them up initially here for the Weibull distribution method, rewrite them later with nrec for the time series method
adjustment_factors haf(this, "adjust");
if (!haf.setup())
throw exec_error("windpower", "failed to setup adjustment factors: " + haf.error());
Expand Down Expand Up @@ -502,6 +502,10 @@ void cm_windpower::exec()
if (steps_per_hour * 8760 != nstep && !contains_leap_day)
throw exec_error("windpower", util::format("invalid number of data records (%d): must be an integer multiple of 8760", (int)nstep));

// overwrite adjustment factors setup using the correct value for nrec, which we don't have until this part of the code
if (!haf.setup(nstep))
throw exec_error("windpower", "failed to setup adjustment factors: " + haf.error());

// allocate output data
ssc_number_t *farmpwr = allocate("gen", nstep);
ssc_number_t *wspd = allocate("wind_speed", nstep);
Expand Down
14 changes: 9 additions & 5 deletions ssc/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1093,13 +1093,17 @@ bool adjustment_factors::setup(int nsteps, int analysis_period) //nsteps is set
m_factors[nsteps * a + i] *= (1.0 - p[0]/100.0); //input as factors not percentage
}
}
else if (n == (size_t)(nsteps * analysis_period)) { //Hourly or subhourly
else if (n == (size_t)(nsteps * analysis_period)) { //Hourly or subhourly- must match weather file resolution
for (int a = 0; a < analysis_period; a++) {
for (int i = 0; i < nsteps; i++)
m_factors[nsteps * a + i] *= (1.0 - p[a*nsteps + i]/100.0); //convert from percentages to factors
}
}
else if (n % 12 == 0) { //Monthly
else if ((n % 8760 == 0) && n != (size_t)(nsteps * analysis_period)) // give a helpful error for timestep mismatch
{
m_error = util::format("Availability losses must be the same timestep as the weather file, if they are not daily/weekly/monthly.");
}
else if (n == (size_t)( 12 * analysis_period)) { //Monthly
for (int a = 0; a < analysis_period; a++) {
for (int i = 0; i < nsteps; i++) {
month = util::month_of(int(i / steps_per_hour))-1;
Expand All @@ -1108,7 +1112,7 @@ bool adjustment_factors::setup(int nsteps, int analysis_period) //nsteps is set

}
}
else if (n % 365 == 0) { //Daily
else if (n == (size_t)( 365 * analysis_period)) { //Daily
for (int a = 0; a < analysis_period; a++) {
for (int i = 0; i < nsteps; i++) {
day = util::day_of_year(int(i / steps_per_hour));
Expand All @@ -1117,7 +1121,7 @@ bool adjustment_factors::setup(int nsteps, int analysis_period) //nsteps is set

}
}
else if (n % 52 == 0) { //Weekly
else if (n == (size_t)( 52 * analysis_period)) { //Weekly
for (int a = 0; a < analysis_period; a++) {
for (int i = 0; i < nsteps; i++) {
week = util::week_of(int(i / steps_per_hour));
Expand All @@ -1133,7 +1137,7 @@ bool adjustment_factors::setup(int nsteps, int analysis_period) //nsteps is set
}
}
else {
m_error = util::format("Error with lifetime loss data inputs");
m_error = util::format("Error in length of lifetime availability losses.");
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions test/input_cases/pvsamv1_battery_common_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ void pvsamv1_battery_defaults(ssc_data_t& data) {
ssc_data_set_number(data, "dc_adjust_constant", 0.0);
ssc_data_set_number(data, "dc_adjust_en_periods", 1);
ssc_data_set_matrix(data, "dc_adjust_periods", p_dc_adjust_periods, 1, 3);
ssc_data_set_number(data, "dc_adjust_en_timeindex", 1);
ssc_data_set_number(data, "dc_adjust_en_timeindex", 0);
ssc_data_set_array(data, "dc_adjust_timeindex", p_dc_adjust_hourly, 8760);

ssc_data_set_number(data, "batt_chem", 1);
Expand Down Expand Up @@ -1167,7 +1167,7 @@ void commercial_multiarray_default(ssc_data_t& data) {
ssc_data_set_number(data, "dc_adjust_constant", 0.0);
ssc_data_set_number(data, "dc_adjust_en_periods", 1);
ssc_data_set_matrix(data, "dc_adjust_periods", p_dc_adjust_periods, 1, 3);
ssc_data_set_number(data, "dc_adjust_en_timeindex", 1);
ssc_data_set_number(data, "dc_adjust_en_timeindex", 0);
ssc_data_set_array(data, "dc_adjust_timeindex", p_dc_adjust_hourly, 8760);


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@
"batt_dispatch_pvs_timestep_multiplier": 3.0,
"batt_dispatch_pvs_wf_forecast_choice": 0.0,
"batt_dispatch_pvs_wf_timestep": 60.0,
"batt_dispatch_update_frequency_hours": 0.0,
"batt_dispatch_update_frequency_hours": 1.0,
"batt_dispatch_wf_forecast_choice": 0.0,
"batt_duration_choice": 0.0,
"batt_gridcharge_percent_1": 100.0,
Expand Down Expand Up @@ -706,7 +706,7 @@
50.0
]
],
"batt_look_ahead_hours": 0.0,
"batt_look_ahead_hours": 18.0,
"batt_loss_choice": 0.0,
"batt_losses": [
0.0
Expand Down
5 changes: 1 addition & 4 deletions test/ssc_test/cmod_pvsamv1_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,10 +422,7 @@ TEST_F(CMPvsamv1PowerIntegration_cmod_pvsamv1, LossAdjustmentNonLifetime) {
ssc_data_set_array(data, "adjust_timeindex", timeindex_subhourly, 17520);

pvsam_errors = run_module(data, "pvsamv1");
ssc_data_get_number(data, "annual_energy", &annual_energy);
EXPECT_NEAR(annual_energy, 8833.8, m_error_tolerance_hi);
ssc_data_get_number(data, "kwh_per_kw", &kwh_per_kw);
EXPECT_NEAR(kwh_per_kw, 1883, m_error_tolerance_hi) << "Energy yield"; // Same as 1 year because year 2 has 0 production
EXPECT_TRUE(pvsam_errors); //this should throw an error because we are not allowing losses at a more granular timestep than weather
}


Expand Down

0 comments on commit 77bd65f

Please sign in to comment.