Skip to content

Commit bc66bc2

Browse files
SSC: Add builtin snow depth array, support varying periods for this array. (#1335)
* minimum working example of using snow depth with user input. Not robust: only works with hourly simulation * allow snow_array default to be of length 1 for testing (repeat 8760 times) * first pass at editing tests to reflect new variables * Use boolean operators correctly * add new snow variables to tranche of pv tests * add new defaults to pvyield common data * add snow related vars to more tests- these tests have presaved json inputs, so the snow variables might be out of place. consider if this is the ideal way to add these test * JSON-based tests: put new vars in test data, and remove them from test harness * If snow data and weather file have different periods that are divisible, up/downsample snow data to match weather file. Else error * add tests of snow data, including shorter than/longer than weather file data * Fix bug that led to OOB when running a lifetime (vs one year) simulation with user entered snow depth data. Need to cycle back to beginning of the snow depth data for each year --------- Co-authored-by: Paul Gilman <[email protected]>
1 parent b69cd29 commit bc66bc2

11 files changed

+149
-7
lines changed

shared/lib_pv_io_manager.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,41 @@ Irradiance_IO::Irradiance_IO(compute_module* cm, std::string cmName)
206206
throw exec_error(cmName, "Albedos must be greater than zero and less than one in the monthly uniform albedo matrix.");
207207
}
208208
}
209+
// read in the user entered snow data
210+
211+
std::vector<double> orig_snow_array = cm->as_vector_double("snow_array");
212+
// align the user entered snow data with the weather file data
213+
std::vector<double> aligned_snow_array;
214+
aligned_snow_array.reserve(numberOfWeatherFileRecords);
215+
if (orig_snow_array.size() == 1) {
216+
aligned_snow_array.resize(numberOfWeatherFileRecords);
217+
std::fill(aligned_snow_array.begin(), aligned_snow_array.end(), orig_snow_array[0]);
218+
}
219+
else if (orig_snow_array.size() < numberOfWeatherFileRecords) {
220+
if (numberOfWeatherFileRecords % orig_snow_array.size() != 0) {
221+
throw exec_error(cmName, "Snow depth array and weather file must have divisible periods.");
222+
}
223+
size_t mult = numberOfWeatherFileRecords / orig_snow_array.size();
224+
for (double depth : orig_snow_array) {
225+
for (size_t j = 0; j < mult; j++) {
226+
aligned_snow_array.push_back(depth);
227+
}
228+
}
229+
}
230+
else if (orig_snow_array.size() == numberOfWeatherFileRecords) {
231+
aligned_snow_array = orig_snow_array;
232+
}
233+
else {
234+
if (orig_snow_array.size() % numberOfWeatherFileRecords != 0) {
235+
throw exec_error(cmName, "Snow depth array and weather file must have divisible periods.");
236+
}
237+
size_t mult = orig_snow_array.size() / numberOfWeatherFileRecords;
238+
for (size_t i = 0; i < orig_snow_array.size(); i += mult) {
239+
aligned_snow_array.push_back(orig_snow_array[i]);
240+
}
241+
}
242+
userSpecifiedSnowDepth = aligned_snow_array;
243+
209244

210245
checkWeatherFile(cm, cmName);
211246
}
@@ -307,7 +342,7 @@ void Irradiance_IO::AllocateOutputs(compute_module* cm)
307342
else {
308343
p_weatherFileAlbedo = cm->allocate("alb", numberOfWeatherFileRecords);
309344
}
310-
p_weatherFileSnowDepth = cm->allocate("snowdepth", numberOfWeatherFileRecords);
345+
p_snowDepth = cm->allocate("snowdepth", numberOfWeatherFileRecords);
311346

312347
// If using input POA, must have POA for every subarray or assume POA applies to each subarray
313348
for (size_t subarray = 0; subarray != numberOfSubarrays; subarray++) {
@@ -725,6 +760,7 @@ PVSystem_IO::PVSystem_IO(compute_module* cm, std::string cmName, Simulation_IO*
725760
enableDCLifetimeLosses = cm->as_boolean("en_dc_lifetime_losses");
726761
enableACLifetimeLosses = cm->as_boolean("en_ac_lifetime_losses");
727762
enableSnowModel = cm->as_boolean("en_snow_model");
763+
useWeatherFileSnow = cm->as_boolean("use_snow_weather_file");
728764

729765
// The shared inverter of the PV array and a tightly-coupled DC connected battery
730766
std::unique_ptr<SharedInverter> tmpSharedInverter(new SharedInverter(Inverter->inverterType, numberOfInverters, &Inverter->sandiaInverter, &Inverter->partloadInverter, &Inverter->ondInverter, numberOfInvertersClipping));

shared/lib_pv_io_manager.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ struct Irradiance_IO
234234
flag useSpatialAlbedos; /// Specify whether to use spatial albedos
235235
std::vector<double> userSpecifiedMonthlyAlbedo; /// User can provide monthly uniform ground albedo values (0-1)
236236
util::matrix_t<double> userSpecifiedMonthlySpatialAlbedos; /// User can provide monthly spatial ground albedo values (0-1), [month, location]
237+
std::vector<double> userSpecifiedSnowDepth; /// User can provide hourly snow depth data (cm)
237238

238239
// Irradiance data Outputs (p_ is just a convention to organize all pointer outputs)
239240
ssc_number_t * p_weatherFileGHI; /// The Global Horizonal Irradiance from the weather file [W/m2]
@@ -245,7 +246,7 @@ struct Irradiance_IO
245246
ssc_number_t * p_weatherFileAmbientTemp; /// The ambient temperature from the weather file [C]
246247
ssc_number_t * p_weatherFileAlbedo; /// The ground albedo from the weather file
247248
ssc_number_t* p_weatherFileAlbedoSpatial; /// The ground albedo from the weather file and spatial matrix input
248-
ssc_number_t * p_weatherFileSnowDepth; /// The snow depth from the weather file
249+
ssc_number_t * p_snowDepth; /// The snow depth from the weather file or user input array
249250
ssc_number_t * p_IrradianceCalculated[3]; /// The calculated components of the irradiance [W/m2]
250251
ssc_number_t * p_sunZenithAngle; /// The calculate sun zenith angle [degrees]
251252
ssc_number_t * p_sunAltitudeAngle; /// The calculated sun altitude angle [degrees]
@@ -297,6 +298,7 @@ struct PVSystem_IO
297298
flag enableDCLifetimeLosses;
298299
flag enableACLifetimeLosses;
299300
flag enableSnowModel;
301+
flag useWeatherFileSnow;
300302

301303
int stringsInParallel;
302304
double ratedACOutput; ///< AC Power rating for whole system (all inverters)

ssc/cmod_pvsamv1.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ static var_info _cm_vtab_pvsamv1[] = {
6464
// misc inputs
6565
{SSC_INPUT, SSC_NUMBER, "en_snow_model", "Toggle snow loss estimation", "0/1", "", "Losses", "?=0", "BOOLEAN", "" },
6666
{ SSC_INPUT, SSC_NUMBER, "snow_slide_coefficient", "Snow Slide Coefficient", "", "", "Losses", "?=1.97", "", "" },
67-
67+
{SSC_INPUT, SSC_ARRAY, "snow_array", "Hourly snow depth ", "cm", "", "Losses", "?", "", ""},
68+
{SSC_INPUT, SSC_NUMBER, "use_snow_weather_file", "Use the snow depth from the weather file", "0/1", "0=user-specified,1=weatherfile", "Losses", "*", "", ""},
6869
{SSC_INPUT, SSC_NUMBER, "system_capacity", "DC Nameplate capacity", "kWdc", "", "System Design", "*", "", "" },
6970
{SSC_INPUT, SSC_NUMBER, "use_wf_albedo", "Use albedo in weather file if provided", "0/1", "0=user-specified,1=weatherfile", "Solar Resource", "?=1", "BOOLEAN", "" },
7071
{SSC_INPUT, SSC_NUMBER, "use_spatial_albedos", "Use spatial albedo values", "0/1", "0=no,1=yes", "Solar Resource", "?=0", "BOOLEAN", "" },
@@ -620,7 +621,7 @@ static var_info _cm_vtab_pvsamv1[] = {
620621
{ SSC_OUTPUT, SSC_ARRAY, "tdry", "Weather file ambient temperature", "C", "", "Time Series", "*", "", "" },
621622
{ SSC_OUTPUT, SSC_ARRAY, "alb", "Albedo", "", "", "Time Series", "", "", "" },
622623
{ SSC_OUTPUT, SSC_MATRIX, "alb_spatial", "Albedo spatial", "", "", "Time Series", "", "", "" },
623-
{ SSC_OUTPUT, SSC_ARRAY, "snowdepth", "Weather file snow depth", "cm", "", "Time Series", "", "", "" },
624+
{ SSC_OUTPUT, SSC_ARRAY, "snowdepth", "Snow depth", "cm", "", "Time Series", "", "", "" },
624625

625626
// calculated sun position data
626627
{ SSC_OUTPUT, SSC_ARRAY, "sol_zen", "Sun zenith angle", "degrees", "", "Time Series", "*", "", "" },
@@ -2445,9 +2446,20 @@ void cm_pvsamv1::exec()
24452446
if (PVSystem->enableSnowModel)
24462447
{
24472448
float smLoss = 0.0f;
2448-
2449+
float snowDep = 0.0f;
2450+
// Now we have the option to either use weather file snow data or user input snow data
2451+
if (PVSystem->useWeatherFileSnow)
2452+
{
2453+
// Use weather file snow data
2454+
snowDep = (float)wf.snow;
2455+
}
2456+
else
2457+
{
2458+
// Use user input snow data
2459+
snowDep = Irradiance->userSpecifiedSnowDepth[idx % nrec];
2460+
}
24492461
if (!Subarrays[nn]->snowModel.getLoss((float)(Subarrays[nn]->poa.poaBeamFront + Subarrays[nn]->poa.poaDiffuseFront + Subarrays[nn]->poa.poaGroundFront + ipoa_rear_after_losses[nn]),
2450-
(float)Subarrays[nn]->poa.surfaceTiltDegrees, (float)wf.wspd, (float)wf.tdry, (float)wf.snow, sunup, 1.0f / step_per_hour, smLoss))
2462+
(float)Subarrays[nn]->poa.surfaceTiltDegrees, (float)wf.wspd, (float)wf.tdry, snowDep, sunup, 1.0f / step_per_hour, smLoss))
24512463
{
24522464
if (!Subarrays[nn]->snowModel.good)
24532465
throw exec_error("pvsamv1", Subarrays[nn]->snowModel.msg);
@@ -2544,7 +2556,14 @@ void cm_pvsamv1::exec()
25442556
{
25452557
Irradiance->p_weatherFileWindSpeed[idx] = (ssc_number_t)wf.wspd;
25462558
Irradiance->p_weatherFileAmbientTemp[idx] = (ssc_number_t)wf.tdry;
2547-
Irradiance->p_weatherFileSnowDepth[idx] = (ssc_number_t)wf.snow;
2559+
double snoDep;
2560+
if (PVSystem->useWeatherFileSnow) {
2561+
snoDep = (ssc_number_t)wf.snow;
2562+
}
2563+
else {
2564+
snoDep = Irradiance->userSpecifiedSnowDepth[idx % nrec];
2565+
}
2566+
Irradiance->p_snowDepth[idx] = snoDep;
25482567
Irradiance->p_sunZenithAngle[idx] = (ssc_number_t)solzen;
25492568
Irradiance->p_sunAltitudeAngle[idx] = (ssc_number_t)solalt;
25502569
Irradiance->p_sunAzimuthAngle[idx] = (ssc_number_t)solazi;

test/input_cases/general_data/pvsmoothing_Phoenix_Validation_alloptions.json

Lines changed: 2 additions & 0 deletions
Large diffs are not rendered by default.

test/input_cases/pvsamv1_common_data.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ void pvsamv_nofinancial_default(ssc_data_t& data)
6868
ssc_data_set_number(data, "transformer_no_load_loss", 0);
6969
ssc_data_set_number(data, "transformer_load_loss", 0);
7070
ssc_data_set_number(data, "en_snow_model", 0);
71+
ssc_data_set_number(data, "use_snow_weather_file", 1);
72+
ssc_number_t snow_array[1] = { 0 };
73+
ssc_data_set_array(data, "snow_array", snow_array, 1);
7174
ssc_data_set_number(data, "system_capacity", 4.6928696632385254);
7275
ssc_data_set_number(data, "use_wf_albedo", 0);
7376
ssc_number_t p_albedo[12] = { 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224 };
@@ -568,6 +571,9 @@ void pvsamv1_with_residential_default(ssc_data_t& data)
568571
ssc_data_set_number(data, "use_wf_albedo", 0);
569572
ssc_number_t p_albedo[12] = { 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224 };
570573
ssc_data_set_array(data, "albedo", p_albedo, 12);
574+
ssc_data_set_number(data, "use_snow_weather_file", 1);
575+
ssc_number_t snow_array[1] = { 0 };
576+
ssc_data_set_array(data, "snow_array", snow_array, 1);
571577
ssc_data_set_number(data, "irrad_mode", 0);
572578
ssc_data_set_number(data, "sky_model", 2);
573579
ssc_data_set_number(data, "inverter_count", 1);

test/input_cases/pvyield_common_data.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ void pvyield_no_financial_meteo(ssc_data_t& data)
5858
ssc_data_set_number(data, "transformer_no_load_loss", 0);
5959
ssc_data_set_number(data, "transformer_load_loss", 0);
6060
ssc_data_set_number(data, "en_snow_model", 0);
61+
ssc_data_set_number(data, "use_snow_weather_file", 1);
62+
ssc_number_t snow_array[1] = { 0 };
63+
ssc_data_set_array(data, "snow_array", snow_array, 1);
6164
ssc_data_set_number(data, "system_capacity", 4182.357);
6265
ssc_data_set_number(data, "use_wf_albedo", 0);
6366
ssc_number_t p_albedo[12] = { 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224 };
@@ -506,6 +509,9 @@ void pvyield_bifacial_case(ssc_data_t& data)
506509
ssc_data_set_number(data, "transformer_no_load_loss", 0);
507510
ssc_data_set_number(data, "transformer_load_loss", 0);
508511
ssc_data_set_number(data, "en_snow_model", 0);
512+
ssc_data_set_number(data, "use_snow_weather_file", 1);
513+
ssc_number_t snow_array[1] = { 0 };
514+
ssc_data_set_array(data, "snow_array", snow_array, 1);
509515
ssc_data_set_number(data, "system_capacity", 206200);
510516
ssc_data_set_number(data, "use_wf_albedo", 1);
511517
ssc_number_t p_albedo[12] = { 0.005, 0.005, 0.004, 0.006, 0.015, 0.042, 0.083, 0.003, 0.066, 0.049, 0.013, 0.007 };
@@ -942,6 +948,9 @@ void pvyield_user_support_80603_meteo(ssc_data_t& data)
942948
ssc_data_set_number(data, "transformer_no_load_loss", 0);
943949
ssc_data_set_number(data, "transformer_load_loss", 0);
944950
ssc_data_set_number(data, "en_snow_model", 0);
951+
ssc_data_set_number(data, "use_snow_weather_file", 1);
952+
ssc_number_t snow_array[1] = { 0 };
953+
ssc_data_set_array(data, "snow_array", snow_array, 1);
945954
ssc_data_set_number(data, "system_capacity", 4182.357);
946955
ssc_data_set_number(data, "use_wf_albedo", 0);
947956
ssc_number_t p_albedo[12] = { 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224 };
@@ -1380,6 +1389,9 @@ void pvyield_user_support_80603_AZ(ssc_data_t& data)
13801389
ssc_data_set_number(data, "transformer_no_load_loss", 0);
13811390
ssc_data_set_number(data, "transformer_load_loss", 0);
13821391
ssc_data_set_number(data, "en_snow_model", 0);
1392+
ssc_data_set_number(data, "use_snow_weather_file", 1);
1393+
ssc_number_t snow_array[1] = { 0 };
1394+
ssc_data_set_array(data, "snow_array", snow_array, 1);
13831395
ssc_data_set_number(data, "system_capacity", 4182.357);
13841396
ssc_data_set_number(data, "use_wf_albedo", 0);
13851397
ssc_number_t p_albedo[12] = { 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224 };

test/input_json/PV_Batt_MP.json

Lines changed: 2 additions & 0 deletions
Large diffs are not rendered by default.

test/input_json/solesca/test_fixed_tilt_racking.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
"transformer_no_load_loss": 0.0,
3939
"transformer_load_loss": 0.0,
4040
"en_snow_model": 0.0,
41+
"use_snow_weather_file": 1,
42+
"snow_array": [0],
4143
"use_wf_albedo": 1.0,
4244
"use_spatial_albedos": 0.0,
4345
"albedo": [

test/input_json/solesca/test_flush_mount_racking.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
"transformer_no_load_loss": 0.5,
3939
"transformer_load_loss": 0.8,
4040
"en_snow_model": 0.0,
41+
"use_snow_weather_file": 1,
42+
"snow_array": [0],
4143
"use_wf_albedo": 0.0,
4244
"use_spatial_albedos": 0.0,
4345
"albedo": [

test/shared_test/lib_battery_dispatch_pvsmoothing_fom_test.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ TEST_F(PVSmoothing_lib_battery_dispatch, PV_Phoenix_all_on) {
5858
nfc1 = sprintf(file_path, "%s/test/input_cases/general_data/phoenix_az_33.450495_-111.983688_psmv3_60_tmy_1mInterpolated.csv", SSCDIR);
5959
ssc_data_set_string(dat, "solar_resource_file", file_path);
6060

61+
62+
6163
// Run with fixed output
6264
int errors = run_module(dat, "pvsamv1");
6365
// minimize memory usage for Travis

0 commit comments

Comments
 (0)