Skip to content

Commit

Permalink
add check for power curve existence in thrust curve set function and …
Browse files Browse the repository at this point in the history
…update wake loss output names per Paul suggestions
  • Loading branch information
janinefreeman committed Apr 4, 2024
1 parent b67c957 commit a3393f5
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 24 deletions.
5 changes: 5 additions & 0 deletions shared/lib_windwakemodel.cpp
Expand Up @@ -51,6 +51,11 @@ bool windTurbine::setPowerCurve(std::vector<double> windSpeeds, std::vector<doub

bool windTurbine::setCtCurve(std::vector<double> thrustCoeffCurve)
{
if (powerCurveWS.empty())
{
errDetails = "Power curve must be set before thrust curve.";
return 0;
}
if (thrustCoeffCurve.size() != powerCurveWS.size())
{
errDetails = "Coefficient of thrust curve must have the same number of values as the power curve wind speeds";
Expand Down
24 changes: 12 additions & 12 deletions ssc/cmod_windpower.cpp
Expand Up @@ -114,8 +114,8 @@ static var_info _cm_vtab_windpower[] = {
{ SSC_OUTPUT , SSC_NUMBER , "year" , "Year" , "" ,"" , "Location" , "wind_resource_model_choice=0" , "" , "" } ,

// timeseries outputs
{ SSC_OUTPUT , SSC_ARRAY , "timeseries_wake_loss_kW" , "Wake loss at each timestep in kW" , "kW" ,"" , "Time Series" , "" , "" , "" } ,
{ SSC_OUTPUT , SSC_ARRAY , "timeseries_wake_loss_percent" , "Wake loss at each timestep percent" , "%" ,"" , "Time Series" , "" , "" , "" } ,
{ SSC_OUTPUT , SSC_ARRAY , "wake_loss_internal_kW" , "Internal wake loss in kW" , "kW" ,"" , "Time Series" , "" , "" , "" } ,
{ SSC_OUTPUT , SSC_ARRAY , "wake_loss_internal_percent" , "Internal wake loss percent" , "%" ,"" , "Time Series" , "" , "" , "" } ,

// monthly and annual outputs
{ SSC_OUTPUT , SSC_ARRAY , "monthly_energy" , "Monthly Energy Gross" , "kWh" ,"" , "Monthly" , "*" , "LENGTH=12" , "" } ,
Expand All @@ -131,9 +131,9 @@ static var_info _cm_vtab_windpower[] = {
{ SSC_OUTPUT , SSC_NUMBER , "env_losses" , "Environmental losses" , "%" ,"" , "Annual" ,"" , "" , "" } ,
{ SSC_OUTPUT , SSC_NUMBER , "ops_losses" , "Operational losses" , "%" ,"" , "Annual" ,"" , "" , "" } ,
{ SSC_OUTPUT , SSC_NUMBER , "turb_losses" , "Turbine losses" , "%" ,"" , "Annual" ,"" , "" , "" } ,
{ SSC_OUTPUT , SSC_NUMBER , "annual_internal_wake_loss_percent" , "Annual internal wake loss percentage" , "%" ,"" , "Annual" ,"" , "" , "" } ,
{ SSC_OUTPUT , SSC_NUMBER , "annual_internal_wake_loss_kWh" , "Annual internal wake loss" , "kWh" ,"" , "Annual" ,"" , "" , "" } ,
{ SSC_OUTPUT , SSC_NUMBER , "annual_total_wake_loss_percent" , "Annual total wake loss percentage" , "%" ,"" , "Annual" ,"" , "" , "" } ,
{ SSC_OUTPUT , SSC_NUMBER , "annual_wake_loss_internal_percent" , "Annual internal wake loss percentage" , "%" ,"" , "Annual" ,"" , "" , "" } ,
{ SSC_OUTPUT , SSC_NUMBER , "annual_wake_loss_internal_kWh" , "Annual internal wake loss" , "kWh" ,"" , "Annual" ,"" , "" , "" } ,
{ SSC_OUTPUT , SSC_NUMBER , "annual_wake_loss_total_percent" , "Annual total wake loss percentage" , "%" ,"" , "Annual" ,"" , "" , "" } ,
{ SSC_OUTPUT , SSC_NUMBER , "cutoff_losses" , "Low temp and Icing Cutoff losses" , "%" ,"" , "Annual" ,"" , "" , "" } ,
var_info_invalid };

Expand Down Expand Up @@ -266,7 +266,7 @@ void calculate_losses(compute_module *cm, double annual_wake_int_loss_percent) {
cm->assign("env_losses", env_loss_percent * 100.);
cm->assign("ops_losses", ops_loss_percent * 100.);
cm->assign("turb_losses", turb_loss_percent * 100.);
cm->assign("annual_total_wake_loss_percent", total_wake_loss_percent * 100.);
cm->assign("annual_wake_loss_total_percent", total_wake_loss_percent * 100.);
}

double get_fixed_losses(compute_module* cm){
Expand Down Expand Up @@ -459,9 +459,9 @@ void cm_windpower::exec()
double newWakeLoss = wakeLossBeforeMultiplier * wakeLossMultiplier;
farmPower = farmPowerGross - newWakeLoss;
}
assign("annual_internal_wake_loss_kWh", var_data((ssc_number_t)(farmPowerGross - farmPower)));
assign("annual_wake_loss_internal_kWh", var_data((ssc_number_t)(farmPowerGross - farmPower)));
annual_wake_int_loss_percent = (1. - farmPower / farmPowerGross) * 100.;
assign("annual_internal_wake_loss_percent", var_data((ssc_number_t)annual_wake_int_loss_percent));
assign("annual_wake_loss_internal_percent", var_data((ssc_number_t)annual_wake_int_loss_percent));
}

int nstep = 8760;
Expand Down Expand Up @@ -557,8 +557,8 @@ void cm_windpower::exec()

// allocate output data
ssc_number_t *farmpwr = allocate("gen", nstep);
ssc_number_t* wakeLosskW = allocate("timeseries_wake_loss_kW", nstep);
ssc_number_t* wakeLossPercent = allocate("timeseries_wake_loss_percent", nstep);
ssc_number_t* wakeLosskW = allocate("wake_loss_internal_kW", nstep);
ssc_number_t* wakeLossPercent = allocate("wake_loss_internal_percent", nstep);
ssc_number_t *wspd = allocate("wind_speed", nstep);
ssc_number_t *wdir = allocate("wind_direction", nstep);
ssc_number_t *air_temp = allocate("temp", nstep);
Expand Down Expand Up @@ -717,9 +717,9 @@ void cm_windpower::exec()

// if internal wake loss is calculated during simulation rather than provided, assign these outputs
if (wakeModelChoice != CONSTANTVALUE){
assign("annual_internal_wake_loss_kWh", var_data((ssc_number_t)(annual_gross - annual_after_wake_loss)));
assign("annual_wake_loss_internal_kWh", var_data((ssc_number_t)(annual_gross - annual_after_wake_loss)));
annual_wake_int_loss_percent = (1. - annual_after_wake_loss/annual_gross) * 100.;
assign("annual_internal_wake_loss_percent", var_data((ssc_number_t)annual_wake_int_loss_percent));
assign("annual_wake_loss_internal_percent", var_data((ssc_number_t)annual_wake_int_loss_percent));
}

calculate_p50p90(this);
Expand Down
24 changes: 12 additions & 12 deletions test/ssc_test/cmod_windpower_test.cpp
Expand Up @@ -85,7 +85,7 @@ TEST_F(CMWindPowerIntegration, WakeModelsUsingFile_cmod_windpower) {
EXPECT_NEAR(monthly_energy, 2.8218e6, e) << "Simple: December";

ssc_number_t wake_loss;
ssc_data_get_number(data, "annual_internal_wake_loss_percent", &wake_loss);
ssc_data_get_number(data, "annual_wake_loss_internal_percent", &wake_loss);
EXPECT_NEAR(wake_loss, 1.546, 1e-3) << "Simple: Wake loss";


Expand All @@ -102,7 +102,7 @@ TEST_F(CMWindPowerIntegration, WakeModelsUsingFile_cmod_windpower) {
monthly_energy = ssc_data_get_array(data, "monthly_energy", nullptr)[11];
EXPECT_NEAR(monthly_energy, 2.7472e6, e) << "Wasp: Dec";

ssc_data_get_number(data, "annual_internal_wake_loss_percent", &wake_loss);
ssc_data_get_number(data, "annual_wake_loss_internal_percent", &wake_loss);
EXPECT_NEAR(wake_loss, 4.148, 1e-3) << "Wasp: Wake loss";

// Eddy Viscosity Model
Expand All @@ -118,7 +118,7 @@ TEST_F(CMWindPowerIntegration, WakeModelsUsingFile_cmod_windpower) {
monthly_energy = ssc_data_get_array(data, "monthly_energy", nullptr)[11];
EXPECT_NEAR(monthly_energy, 2.6398e6, e) << "Eddy: Dec";

ssc_data_get_number(data, "annual_internal_wake_loss_percent", &wake_loss);
ssc_data_get_number(data, "annual_wake_loss_internal_percent", &wake_loss);
EXPECT_NEAR(wake_loss, 7.895, 1e-3) << "Eddy: Wake loss";

// Constant Loss Model
Expand All @@ -132,7 +132,7 @@ TEST_F(CMWindPowerIntegration, WakeModelsUsingFile_cmod_windpower) {
ssc_data_get_number(data, "annual_gross_energy", &gross);
EXPECT_NEAR(annual_energy, gross * 0.95, e) << "Constant";

ssc_data_get_number(data, "annual_total_wake_loss_percent", &wake_loss); //this wake model option doesn't report internal wake loss as an output
ssc_data_get_number(data, "annual_wake_loss_total_percent", &wake_loss); //this wake model option doesn't report internal wake loss as an output
EXPECT_NEAR(wake_loss, 5, 1e-3) << "Constant: Wake loss";
}

Expand All @@ -144,32 +144,32 @@ TEST_F(CMWindPowerIntegration, WakeLossMultiplier_cmod_windpower)
//Simple Wake Model
ssc_data_set_number(data, "wake_loss_multiplier", 1.0);
compute();
ssc_data_get_number(data, "annual_internal_wake_loss_percent", &withoutMultiplier);
ssc_data_get_number(data, "annual_wake_loss_internal_percent", &withoutMultiplier);
ssc_data_set_number(data, "wake_loss_multiplier", multiplier);
compute();
ssc_data_get_number(data, "annual_internal_wake_loss_percent", &withMultiplier);
ssc_data_get_number(data, "annual_wake_loss_internal_percent", &withMultiplier);
if (withoutMultiplier != 0.)
EXPECT_NEAR((withMultiplier / withoutMultiplier), multiplier, 0.01) << "Simple Wake Model Multiplier";

//WASP model (Park)
ssc_data_set_number(data, "wind_farm_wake_model", 1);
ssc_data_set_number(data, "wake_loss_multiplier", 1.0);
compute();
ssc_data_get_number(data, "annual_internal_wake_loss_percent", &withoutMultiplier);
ssc_data_get_number(data, "annual_wake_loss_internal_percent", &withoutMultiplier);
ssc_data_set_number(data, "wake_loss_multiplier", multiplier);
compute();
ssc_data_get_number(data, "annual_internal_wake_loss_percent", &withMultiplier);
ssc_data_get_number(data, "annual_wake_loss_internal_percent", &withMultiplier);
if (withoutMultiplier != 0.)
EXPECT_NEAR((withMultiplier / withoutMultiplier), multiplier, 0.01) << "WASP Wake Model Multiplier";

//Eddy Viscosity model
ssc_data_set_number(data, "wind_farm_wake_model", 2);
ssc_data_set_number(data, "wake_loss_multiplier", 1.0);
compute();
ssc_data_get_number(data, "annual_internal_wake_loss_percent", &withoutMultiplier);
ssc_data_get_number(data, "annual_wake_loss_internal_percent", &withoutMultiplier);
ssc_data_set_number(data, "wake_loss_multiplier", multiplier);
compute();
ssc_data_get_number(data, "annual_internal_wake_loss_percent", &withMultiplier);
ssc_data_get_number(data, "annual_wake_loss_internal_percent", &withMultiplier);
if (withoutMultiplier != 0.)
EXPECT_NEAR((withMultiplier / withoutMultiplier), multiplier, 0.01) << "EV Wake Model Multiplier";

Expand All @@ -178,10 +178,10 @@ TEST_F(CMWindPowerIntegration, WakeLossMultiplier_cmod_windpower)
ssc_data_set_number(data, "wake_int_loss", 5);
ssc_data_set_number(data, "wake_loss_multiplier", 1.0);
compute();
ssc_data_get_number(data, "annual_total_wake_loss_percent", &withoutMultiplier);
ssc_data_get_number(data, "annual_wake_loss_total_percent", &withoutMultiplier);
ssc_data_set_number(data, "wake_loss_multiplier", multiplier);
compute();
ssc_data_get_number(data, "annual_total_wake_loss_percent", &withMultiplier);
ssc_data_get_number(data, "annual_wake_loss_total_percent", &withMultiplier);
if (withoutMultiplier != 0.)
EXPECT_NEAR((withMultiplier / withoutMultiplier), multiplier, 0.01) << "Constant Loss Wake Model Multiplier";

Expand Down

0 comments on commit a3393f5

Please sign in to comment.