Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion shared/lib_pv_io_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,41 @@ Irradiance_IO::Irradiance_IO(compute_module* cm, std::string cmName)
throw exec_error(cmName, "Albedos must be greater than zero and less than one in the monthly uniform albedo matrix.");
}
}
// read in the user entered snow data

std::vector<double> orig_snow_array = cm->as_vector_double("snow_array");
// align the user entered snow data with the weather file data
std::vector<double> aligned_snow_array;
aligned_snow_array.reserve(numberOfWeatherFileRecords);
if (orig_snow_array.size() == 1) {
aligned_snow_array.resize(numberOfWeatherFileRecords);
std::fill(aligned_snow_array.begin(), aligned_snow_array.end(), orig_snow_array[0]);
}
else if (orig_snow_array.size() < numberOfWeatherFileRecords) {
if (numberOfWeatherFileRecords % orig_snow_array.size() != 0) {
throw exec_error(cmName, "Snow depth array and weather file must have divisible periods.");
}
size_t mult = numberOfWeatherFileRecords / orig_snow_array.size();
for (double depth : orig_snow_array) {
for (size_t j = 0; j < mult; j++) {
aligned_snow_array.push_back(depth);
}
}
}
else if (orig_snow_array.size() == numberOfWeatherFileRecords) {
aligned_snow_array = orig_snow_array;
}
else {
if (orig_snow_array.size() % numberOfWeatherFileRecords != 0) {
throw exec_error(cmName, "Snow depth array and weather file must have divisible periods.");
}
size_t mult = orig_snow_array.size() / numberOfWeatherFileRecords;
for (size_t i = 0; i < orig_snow_array.size(); i += mult) {
aligned_snow_array.push_back(orig_snow_array[i]);
}
}
userSpecifiedSnowDepth = aligned_snow_array;


checkWeatherFile(cm, cmName);
}
Expand Down Expand Up @@ -307,7 +342,7 @@ void Irradiance_IO::AllocateOutputs(compute_module* cm)
else {
p_weatherFileAlbedo = cm->allocate("alb", numberOfWeatherFileRecords);
}
p_weatherFileSnowDepth = cm->allocate("snowdepth", numberOfWeatherFileRecords);
p_snowDepth = cm->allocate("snowdepth", numberOfWeatherFileRecords);

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

// The shared inverter of the PV array and a tightly-coupled DC connected battery
std::unique_ptr<SharedInverter> tmpSharedInverter(new SharedInverter(Inverter->inverterType, numberOfInverters, &Inverter->sandiaInverter, &Inverter->partloadInverter, &Inverter->ondInverter, numberOfInvertersClipping));
Expand Down
4 changes: 3 additions & 1 deletion shared/lib_pv_io_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ struct Irradiance_IO
flag useSpatialAlbedos; /// Specify whether to use spatial albedos
std::vector<double> userSpecifiedMonthlyAlbedo; /// User can provide monthly uniform ground albedo values (0-1)
util::matrix_t<double> userSpecifiedMonthlySpatialAlbedos; /// User can provide monthly spatial ground albedo values (0-1), [month, location]
std::vector<double> userSpecifiedSnowDepth; /// User can provide hourly snow depth data (cm)

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

int stringsInParallel;
double ratedACOutput; ///< AC Power rating for whole system (all inverters)
Expand Down
29 changes: 24 additions & 5 deletions ssc/cmod_pvsamv1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ static var_info _cm_vtab_pvsamv1[] = {
// misc inputs
{SSC_INPUT, SSC_NUMBER, "en_snow_model", "Toggle snow loss estimation", "0/1", "", "Losses", "?=0", "BOOLEAN", "" },
{ SSC_INPUT, SSC_NUMBER, "snow_slide_coefficient", "Snow Slide Coefficient", "", "", "Losses", "?=1.97", "", "" },

{SSC_INPUT, SSC_ARRAY, "snow_array", "Hourly snow depth ", "cm", "", "Losses", "?", "", ""},
{SSC_INPUT, SSC_NUMBER, "use_snow_weather_file", "Use the snow depth from the weather file", "0/1", "0=user-specified,1=weatherfile", "Losses", "*", "", ""},
{SSC_INPUT, SSC_NUMBER, "system_capacity", "DC Nameplate capacity", "kWdc", "", "System Design", "*", "", "" },
{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", "" },
{SSC_INPUT, SSC_NUMBER, "use_spatial_albedos", "Use spatial albedo values", "0/1", "0=no,1=yes", "Solar Resource", "?=0", "BOOLEAN", "" },
Expand Down Expand Up @@ -620,7 +621,7 @@ static var_info _cm_vtab_pvsamv1[] = {
{ SSC_OUTPUT, SSC_ARRAY, "tdry", "Weather file ambient temperature", "C", "", "Time Series", "*", "", "" },
{ SSC_OUTPUT, SSC_ARRAY, "alb", "Albedo", "", "", "Time Series", "", "", "" },
{ SSC_OUTPUT, SSC_MATRIX, "alb_spatial", "Albedo spatial", "", "", "Time Series", "", "", "" },
{ SSC_OUTPUT, SSC_ARRAY, "snowdepth", "Weather file snow depth", "cm", "", "Time Series", "", "", "" },
{ SSC_OUTPUT, SSC_ARRAY, "snowdepth", "Snow depth", "cm", "", "Time Series", "", "", "" },

// calculated sun position data
{ SSC_OUTPUT, SSC_ARRAY, "sol_zen", "Sun zenith angle", "degrees", "", "Time Series", "*", "", "" },
Expand Down Expand Up @@ -2445,9 +2446,20 @@ void cm_pvsamv1::exec()
if (PVSystem->enableSnowModel)
{
float smLoss = 0.0f;

float snowDep = 0.0f;
// Now we have the option to either use weather file snow data or user input snow data
if (PVSystem->useWeatherFileSnow)
{
// Use weather file snow data
snowDep = (float)wf.snow;
}
else
{
// Use user input snow data
snowDep = Irradiance->userSpecifiedSnowDepth[idx % nrec];
}
if (!Subarrays[nn]->snowModel.getLoss((float)(Subarrays[nn]->poa.poaBeamFront + Subarrays[nn]->poa.poaDiffuseFront + Subarrays[nn]->poa.poaGroundFront + ipoa_rear_after_losses[nn]),
(float)Subarrays[nn]->poa.surfaceTiltDegrees, (float)wf.wspd, (float)wf.tdry, (float)wf.snow, sunup, 1.0f / step_per_hour, smLoss))
(float)Subarrays[nn]->poa.surfaceTiltDegrees, (float)wf.wspd, (float)wf.tdry, snowDep, sunup, 1.0f / step_per_hour, smLoss))
{
if (!Subarrays[nn]->snowModel.good)
throw exec_error("pvsamv1", Subarrays[nn]->snowModel.msg);
Expand Down Expand Up @@ -2544,7 +2556,14 @@ void cm_pvsamv1::exec()
{
Irradiance->p_weatherFileWindSpeed[idx] = (ssc_number_t)wf.wspd;
Irradiance->p_weatherFileAmbientTemp[idx] = (ssc_number_t)wf.tdry;
Irradiance->p_weatherFileSnowDepth[idx] = (ssc_number_t)wf.snow;
double snoDep;
if (PVSystem->useWeatherFileSnow) {
snoDep = (ssc_number_t)wf.snow;
}
else {
snoDep = Irradiance->userSpecifiedSnowDepth[idx % nrec];
}
Irradiance->p_snowDepth[idx] = snoDep;
Irradiance->p_sunZenithAngle[idx] = (ssc_number_t)solzen;
Irradiance->p_sunAltitudeAngle[idx] = (ssc_number_t)solalt;
Irradiance->p_sunAzimuthAngle[idx] = (ssc_number_t)solazi;
Expand Down

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions test/input_cases/pvsamv1_common_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ void pvsamv_nofinancial_default(ssc_data_t& data)
ssc_data_set_number(data, "transformer_no_load_loss", 0);
ssc_data_set_number(data, "transformer_load_loss", 0);
ssc_data_set_number(data, "en_snow_model", 0);
ssc_data_set_number(data, "use_snow_weather_file", 1);
ssc_number_t snow_array[1] = { 0 };
ssc_data_set_array(data, "snow_array", snow_array, 1);
ssc_data_set_number(data, "system_capacity", 4.6928696632385254);
ssc_data_set_number(data, "use_wf_albedo", 0);
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 };
Expand Down Expand Up @@ -568,6 +571,9 @@ void pvsamv1_with_residential_default(ssc_data_t& data)
ssc_data_set_number(data, "use_wf_albedo", 0);
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 };
ssc_data_set_array(data, "albedo", p_albedo, 12);
ssc_data_set_number(data, "use_snow_weather_file", 1);
ssc_number_t snow_array[1] = { 0 };
ssc_data_set_array(data, "snow_array", snow_array, 1);
ssc_data_set_number(data, "irrad_mode", 0);
ssc_data_set_number(data, "sky_model", 2);
ssc_data_set_number(data, "inverter_count", 1);
Expand Down
12 changes: 12 additions & 0 deletions test/input_cases/pvyield_common_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ void pvyield_no_financial_meteo(ssc_data_t& data)
ssc_data_set_number(data, "transformer_no_load_loss", 0);
ssc_data_set_number(data, "transformer_load_loss", 0);
ssc_data_set_number(data, "en_snow_model", 0);
ssc_data_set_number(data, "use_snow_weather_file", 1);
ssc_number_t snow_array[1] = { 0 };
ssc_data_set_array(data, "snow_array", snow_array, 1);
ssc_data_set_number(data, "system_capacity", 4182.357);
ssc_data_set_number(data, "use_wf_albedo", 0);
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 };
Expand Down Expand Up @@ -506,6 +509,9 @@ void pvyield_bifacial_case(ssc_data_t& data)
ssc_data_set_number(data, "transformer_no_load_loss", 0);
ssc_data_set_number(data, "transformer_load_loss", 0);
ssc_data_set_number(data, "en_snow_model", 0);
ssc_data_set_number(data, "use_snow_weather_file", 1);
ssc_number_t snow_array[1] = { 0 };
ssc_data_set_array(data, "snow_array", snow_array, 1);
ssc_data_set_number(data, "system_capacity", 206200);
ssc_data_set_number(data, "use_wf_albedo", 1);
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 };
Expand Down Expand Up @@ -942,6 +948,9 @@ void pvyield_user_support_80603_meteo(ssc_data_t& data)
ssc_data_set_number(data, "transformer_no_load_loss", 0);
ssc_data_set_number(data, "transformer_load_loss", 0);
ssc_data_set_number(data, "en_snow_model", 0);
ssc_data_set_number(data, "use_snow_weather_file", 1);
ssc_number_t snow_array[1] = { 0 };
ssc_data_set_array(data, "snow_array", snow_array, 1);
ssc_data_set_number(data, "system_capacity", 4182.357);
ssc_data_set_number(data, "use_wf_albedo", 0);
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 };
Expand Down Expand Up @@ -1380,6 +1389,9 @@ void pvyield_user_support_80603_AZ(ssc_data_t& data)
ssc_data_set_number(data, "transformer_no_load_loss", 0);
ssc_data_set_number(data, "transformer_load_loss", 0);
ssc_data_set_number(data, "en_snow_model", 0);
ssc_data_set_number(data, "use_snow_weather_file", 1);
ssc_number_t snow_array[1] = { 0 };
ssc_data_set_array(data, "snow_array", snow_array, 1);
ssc_data_set_number(data, "system_capacity", 4182.357);
ssc_data_set_number(data, "use_wf_albedo", 0);
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 };
Expand Down
2 changes: 2 additions & 0 deletions test/input_json/PV_Batt_MP.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions test/input_json/solesca/test_fixed_tilt_racking.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
"transformer_no_load_loss": 0.0,
"transformer_load_loss": 0.0,
"en_snow_model": 0.0,
"use_snow_weather_file": 1,
"snow_array": [0],
"use_wf_albedo": 1.0,
"use_spatial_albedos": 0.0,
"albedo": [
Expand Down
2 changes: 2 additions & 0 deletions test/input_json/solesca/test_flush_mount_racking.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
"transformer_no_load_loss": 0.5,
"transformer_load_loss": 0.8,
"en_snow_model": 0.0,
"use_snow_weather_file": 1,
"snow_array": [0],
"use_wf_albedo": 0.0,
"use_spatial_albedos": 0.0,
"albedo": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ TEST_F(PVSmoothing_lib_battery_dispatch, PV_Phoenix_all_on) {
nfc1 = sprintf(file_path, "%s/test/input_cases/general_data/phoenix_az_33.450495_-111.983688_psmv3_60_tmy_1mInterpolated.csv", SSCDIR);
ssc_data_set_string(dat, "solar_resource_file", file_path);



// Run with fixed output
int errors = run_module(dat, "pvsamv1");
// minimize memory usage for Travis
Expand Down
57 changes: 57 additions & 0 deletions test/ssc_test/cmod_pvsamv1_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1044,6 +1044,63 @@ TEST_F(CMPvsamv1PowerIntegration_cmod_pvsamv1, SnowModel)

}


/// Test PVSAMv1 with Snow Model enabled and set to 1-axis Tracking
TEST_F(CMPvsamv1PowerIntegration_cmod_pvsamv1, UserArraySnowModel)
{


std::map<std::string, double> pairs;

pairs["en_snow_model"] = 1;
pairs["subarray1_track_mode"] = 1;

// initial sim to get output snow data;
int pvsam_errors = modify_ssc_data_and_run_module(data, "pvsamv1", pairs);
EXPECT_FALSE(pvsam_errors);
ssc_number_t annual_energy;
ssc_data_get_number(data, "annual_energy", &annual_energy);
EXPECT_NEAR(annual_energy, 11395, m_error_tolerance_hi) << "Annual energy.";

// pull the wf snow data and put it into an array
int l = 8760;
ssc_number_t* snowdepth = ssc_data_get_array(data, "snowdepth", &l);
ssc_data_set_array(data, "snow_array", snowdepth, 8760);
// Use the snow data from the snow depth array
pairs["use_snow_weather_file"] = 0;
pvsam_errors = modify_ssc_data_and_run_module(data, "pvsamv1", pairs);
EXPECT_FALSE(pvsam_errors);
ssc_data_get_number(data, "annual_energy", &annual_energy);
EXPECT_NEAR(annual_energy, 11395, m_error_tolerance_hi) << "Annual energy.";

// Check handling of upsampled data
std::vector<ssc_number_t> upsampled;
upsampled.reserve(8760 * 2);
for (size_t i = 0; i < 8760; i++) {
upsampled.push_back(snowdepth[i]);
upsampled.push_back(snowdepth[i]);
}
ssc_data_set_array(data, "snow_array", upsampled.data(), 8760*2);
pvsam_errors = modify_ssc_data_and_run_module(data, "pvsamv1", pairs);
EXPECT_FALSE(pvsam_errors);
ssc_data_get_number(data, "annual_energy", &annual_energy);
EXPECT_NEAR(annual_energy, 11395, m_error_tolerance_hi) << "Annual energy.";

// Check handling of downsampled data
std::vector<ssc_number_t> downsampled;
downsampled.reserve(8760 / 2);
for (size_t i = 0; i < 8760/2; i++) {
downsampled.push_back(snowdepth[2*i]);
}
ssc_data_set_array(data, "snow_array", downsampled.data(), 8760 / 2);
pvsam_errors = modify_ssc_data_and_run_module(data, "pvsamv1", pairs);
EXPECT_FALSE(pvsam_errors);
ssc_data_get_number(data, "annual_energy", &annual_energy);
EXPECT_NEAR(annual_energy, 11377, m_error_tolerance_hi) << "Annual energy.";


}

TEST_F(CMPvsamv1PowerIntegration_cmod_pvsamv1, SubhourlyClippingCorrectionModel)
{
std::map<std::string, double> pairs;
Expand Down
Loading