Skip to content

Commit

Permalink
added optional coefficient of thrust curve input to cmod_windpower fo…
Browse files Browse the repository at this point in the history
…r the park wake model. placeholder for functionality of using the input needs to be updated.
  • Loading branch information
janinefreeman committed Mar 28, 2024
1 parent fc8c310 commit a0958b1
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 4 deletions.
7 changes: 7 additions & 0 deletions shared/lib_windwakemodel.cpp
Expand Up @@ -214,6 +214,13 @@ double parkWakeModel::delta_V_Park(double Uo, double Ui, double distCrosswind, d
// bound the coeff of thrust
double Ct = max_of(min_of(0.999, dThrustCoeff), minThrustCoeff);

// overwrite the coefficient of thrust if it has been specified by the user
// if it has not been specified by the user, the thrust curve vector is {0.}
if (ctCurve.size() != 1)
{
// do something here
}

double k = wakeDecayConstant;

double dRadiusOfWake = dRadiusUpstream + (k * distDownwind); // radius of circle formed by wake from upwind rotor
Expand Down
6 changes: 5 additions & 1 deletion shared/lib_windwakemodel.h
Expand Up @@ -153,12 +153,16 @@ class parkWakeModel : public wakeModelBase{
double rotorDiameter;
double wakeDecayConstant = 0.07,
minThrustCoeff = 0.02;
std::vector<double> ctCurve; //vector that stores the optional coefficient of thrust curve input
double delta_V_Park(double dVelFreeStream, double dVelUpwind, double dDistCrossWind, double dDistDownWind, double dRadiusUpstream, double dRadiusDownstream, double dThrustCoeff);
double circle_overlap(double dist_center_to_center, double rad1, double rad2);

public:
parkWakeModel(){ nTurbines = 0; }
parkWakeModel(size_t numberOfTurbinesInFarm, windTurbine* wt, double wdc) { nTurbines = numberOfTurbinesInFarm; wTurbine = wt; setWakeDecayConstant(wdc); }
parkWakeModel(size_t numberOfTurbinesInFarm, windTurbine* wt, double wdc, std::vector<double> ctc)
{
nTurbines = numberOfTurbinesInFarm; wTurbine = wt; setWakeDecayConstant(wdc); ctCurve = ctc;
}
virtual ~parkWakeModel() {};
std::string getModelName() override { return "Park"; }
void setRotorDiameter(double d){ rotorDiameter = d; }
Expand Down
22 changes: 20 additions & 2 deletions ssc/cmod_windpower.cpp
Expand Up @@ -72,7 +72,9 @@ static var_info _cm_vtab_windpower[] = {
{ SSC_INPUT , SSC_NUMBER , "icing_cutoff_temp" , "Icing Cutoff Temperature" , "C" ,"" , "Losses" , "en_icing_cutoff=1" , "" , "" } ,
{ SSC_INPUT , SSC_NUMBER , "icing_cutoff_rh" , "Icing Cutoff Relative Humidity" , "%" ,"'rh' required in wind_resource_data" , "Losses" , "en_icing_cutoff=1" , "MIN=0" , "" } ,

// optional SDK only wake loss inputs
{ SSC_INPUT , SSC_NUMBER , "wake_loss_multiplier" , "Multiplier for the calculated wake loss" , "" ,">1 increases loss, <1 decreases loss", "Farm" , "" , "MIN=0" , "" } ,
{ SSC_INOUT , SSC_ARRAY , "wind_turbine_ct_curve" , "Park model coeff of thrust curve vs WS" , "" ,"uses same wind speeds as power curve", "Turbine" , "" , "LENGTH_EQUAL=wind_turbine_powercurve_windspeeds" , "GROUP=WTPCD" } ,

{ SSC_INPUT , SSC_NUMBER , "wake_int_loss" , "Constant Wake Model, internal wake loss" , "%" ,"" , "Losses" , "wind_farm_wake_model=3" , "MIN=0,MAX=100" , "" } ,
{ SSC_INPUT , SSC_NUMBER , "wake_ext_loss" , "External Wake loss" , "%" ,"" , "Losses" , "?=0" , "MIN=0,MAX=100" , "" } ,
Expand Down Expand Up @@ -291,7 +293,7 @@ void cm_windpower::exec()
wt.rotorDiameter = as_double("wind_turbine_rotor_diameter");
ssc_number_t *pc_w = as_array("wind_turbine_powercurve_windspeeds", &wt.powerCurveArrayLength);
if (wt.powerCurveArrayLength == 1)
throw exec_error("windpower", util::format("The wind turbine power curves has insufficient data. Consider changing the turbine design parameters"));
throw exec_error("windpower", util::format("The wind turbine power curve has insufficient data. Consider changing the turbine design parameters"));
ssc_number_t *pc_p = as_array("wind_turbine_powercurve_powerout", NULL);
std::vector<double> windSpeeds(wt.powerCurveArrayLength), powerOutput(wt.powerCurveArrayLength);
for (size_t i = 0; i < wt.powerCurveArrayLength; i++){
Expand Down Expand Up @@ -404,10 +406,26 @@ void cm_windpower::exec()
wakeModel = std::make_shared<simpleWakeModel>(simpleWakeModel(wpc.nTurbines, &wt));
else if (wakeModelChoice == PARK)
{
// get optional thrust curve
std::vector<double> ct_curve = { 0. }; //initialize this to length 1: a power curve length of 1 throws an exec error above & the length of ct curve is tied to the power curve, so this is a safe null value
if (is_assigned("wind_turbine_ct_curve"))
{
size_t *ctCurveLength = 0;
ssc_number_t *ctc = as_array("wind_turbine_ct_curve", ctCurveLength);
if (*ctCurveLength != wt.powerCurveArrayLength)
throw exec_error("windpower", "Thrust curve must have same number of values as the power curve");
ct_curve.resize(*ctCurveLength);
for (size_t i = 0; i < *ctCurveLength; i++)
ct_curve[i] = ctc[i];
}

// get optional wake decay constant
double wdc = 0.07; //this is the default value
if (is_assigned("park_wake_decay_constant"))
wdc = as_double("park_wake_decay_constant");
wakeModel = std::make_shared<parkWakeModel>(parkWakeModel(wpc.nTurbines, &wt, wdc));

// create the wake model
wakeModel = std::make_shared<parkWakeModel>(parkWakeModel(wpc.nTurbines, &wt, wdc, ct_curve));
}
else if (wakeModelChoice == EDDYVISCOSITY)
{
Expand Down
2 changes: 1 addition & 1 deletion test/shared_test/lib_windwakemodel_test.h
Expand Up @@ -154,7 +154,7 @@ class parkWakeModelTest : public ::testing::Test{
windSpeed.resize(numberTurbines);
turbIntensity.resize(numberTurbines, 0.1);
createDefaultTurbine(&wt);
pm = parkWakeModel(numberTurbines, &wt, 0.07);
pm = parkWakeModel(numberTurbines, &wt, 0.07, { 0. }); //use default values for the last two inputs
for (int i = 0; i < numberTurbines; i++){
windSpeed[i] = 10.;
}
Expand Down

0 comments on commit a0958b1

Please sign in to comment.