Energy Calculation
Introduction
The results of an energy calculation in WindFarmer: Analyst scripting are captured in a “Scenario”. The energy calculation will return scenarios which are snapshots of the workbook setup taken at that specific point in time and the corresponding results of the calculation. For the time being, these Scenarios only live within a script’s lifetime so it is up to you to extract the information you need from the Scenario in your script. The UI available scenario is called the Workbook which is live and modifiable. This snapshot is returned by the energy calculation as a Scenario object. Within this scenario the scripter will find the inputs to the energy calculation in a read-only status. E.g., the turbines and wind farms named with the ReadOnly prefix. Within one scenario, several types of energy calculations are run. Each different run is called a variant. Each variant corresponds to a different group of Energy model settings applied to the same layout. Currently the following variants are available:
- “Gross” variant: signifying a run with no wakes applied
- “Full” variant: signifying a run with wakes and all active settings in the workbook. . With the addition of the efficiencies calculation when active the following energy calculation runs are also available in the scenario. Note that the above are still valid but in this case the “Gross” variant will not include LWF effects. The following table describes the variants and the included effects:
Variant | Wake Model | Hysteresis Model | LWF Model | Neighbours | WSM |
---|---|---|---|---|---|
Gross | |||||
InternalWakesOn | x | ||||
HysteresisAdjustmentOn | x | x | |||
LargeWindFarmCorrectionOn | x | x | x | ||
NeighbourWakesOn | x | x | x | x | |
CurtailmentOn | x | x | x | x | x |
Full | x | x | x | x | x |
Having chosen which variant the scripter wants to get the results from, it is necessary to provide from which read-only turbine or from which location. There are results that are specific to a turbine instance, e.g. yield or flow case turbine power and others that are specific to a location, e.g. wind speed, turbulence intensity, terrain slope. Generally, flow related results are accessed by location while turbine specific results are accessed by the read-only turbine instance. A limitation at present is that flow results on a scenario are only available at a location where a turbine is placed.
Flow case results are accessed by specifying the direction (DirectionBearing
object) and wind speed (Speed
object) of the flow case, then the binning type which specifies if the quantity is binned by the wind speeds at the reference mast (FlowCaseBinningType.ReferenceLocationBinning
) or at the turbine (FlowCaseBinningType.LocalBinning
).
Note that the results façade will return objects with the appropriate type, e.g. Speed
, TurbulenceIntensity
or FlowCaseProbability
. The objects can be used directly in mathematical operation as if they were doubles, i.e. a function that accepts doubles will accept a TurbulenceIntensity
. This means you can exploit the Math library to manipulate results.
See below for some examples:
Run the Energy Calculation
// Energy calculation settings are found in Workbook.ModelSettings.EnergySettings
Workbook.ModelSettings.EnergySettings.WakeModelType = WakeModelType.EddyViscosity;
Workbook.ModelSettings.EnergySettings.NumberOfDirectionSectors = 180;
Workbook.ModelSettings.EnergySettings.UseAssociationMethod = true;
// Execute an energy calculation which will return a scenario
Scenario scenario = Toolbox.CalculateEnergy();
How to obtain a list of valid wind farms and turbines
/// <summary>
/// An example of how to obtain a list of valid wind farms and turbines in scripting.
/// </summary>
/// <param name="scenario">A scenerio</param>
public void How_to_obtain_a_list_of_valid_wind_farms_and_turbines(Scenario scenario)
{
// Wind farms or turbine that were excluded from the calculation
// are not valid objects in the results
// Obtain a list valid wind farms
var validReadOnlyWindFarms =
scenario.WindFarms.Where(farm => farm.ExcludeFromCalculation == false);
// Obtain a list of all valid turbines by selecting all
// turbines in the valid wind farms list
var validReadOnlyTurbines =
validReadOnlyWindFarms.SelectMany(farm => farm.Turbines);
}
How to obtain a scenario from a workbook
/// <summary>
/// An example of how to access current energy results stored
/// in the workbook (for the currently loaded scenario).
/// </summary>
public void Obtain_scenario_from_current_workbook()
{
Scenario scenario = Workbook.CurrentScenario;
//Access current energy results ...
}
Traverse a list of valid turbines and extract the average ambient conditions
/// <summary>
/// An example of how to traverse a list of valid turbines
/// and extract average ambient conditions
/// </summary>
/// <param name="scenario">A scenerio</param>
/// <param name="validReadOnlyTurbines">The turbines to traverse.</param>
public void Traverse_list_of_valid_turbines_and_extract_average_ambient_conditions(
Scenario scenario,
IEnumerable<ReadOnlyTurbine> validReadOnlyTurbines)
{
// Traverse list of ReadOnlyTurbines
foreach (ReadOnlyTurbine turbine in validReadOnlyTurbines)
{
Speed meanFreeWindSpeed =
scenario.MeanWindSpeeds
.GetVariantResult("Gross")
.GetValueForLocation(turbine.Location);
Yield grossYield =
scenario.TurbineTotalYields
.GetVariantResult("Gross")
.GetValueForTurbine(turbine);
}
// Alternative method: use list of Turbines in scenario
foreach (ReadOnlyTurbine turbine in scenario.Turbines)
{
// If excluded then loop jumps current iteration
if (turbine.ExcludeFromCalculation)
continue;
Speed meanFreeWindSpeed =
scenario.MeanWindSpeeds
.GetVariantResult("Gross")
.GetValueForLocation(turbine.Location);
Yield grossYield =
scenario.TurbineTotalYields
.GetVariantResult("Gross")
.GetValueForTurbine(turbine);
}
}
Traverse a list of valid turbines and extract the average waked conditions
/// <summary>
/// An example of how to traverse a list of valid turbines and extract average waked conditions
/// </summary>
/// <param name="scenario">A scenerio</param>
/// <param name="validReadOnlyTurbines">The turbines to traverse.</param>
public void Traverse_the_same_list_of_valid_turbines_for_the_averaged_waked_conditions(
Scenario scenario,
IEnumerable<ReadOnlyTurbine> validReadOnlyTurbines)
{
foreach (ReadOnlyTurbine turbine in validReadOnlyTurbines)
{
// Obtain the mean waked wind speed at the turbine
Speed meanWindSpeed =
scenario.MeanWindSpeeds
.GetVariantResult("Full")
.GetValueForLocation(turbine.Location);
// Net yield of the turbine
Yield netYield =
scenario.TurbineTotalYields
.GetVariantResult("Full")
.GetValueForTurbine(turbine);
// Mean incident turbulence intensity at the turbine
TurbulenceIntensity incidentTI =
scenario.MeanTurbulenceIntensities
.GetVariantResult("Full")
.GetValueForLocation(turbine.Location);
// Obtain the air density at the turbine
AirDensity airDensity =
scenario.AirDensities
.GetVariantResult("Full")
.GetValueForLocation(turbine.HubHeightLocation);
}
}
Perform mathematical operations with scripting objects
/// <summary>
/// An example of how to perform mathematical operations with scripting objects.
/// </summary>
/// <param name="scenario">A scenerio</param>
/// <param name="turbine">A turbine</param>
public void Perform_mathematical_operations_with_scripting_objects(
Scenario scenario,
ReadOnlyTurbine turbine)
{
Speed meanFreeWindSpeed =
scenario.MeanWindSpeeds
.GetVariantResult("Gross")
.GetValueForLocation(turbine.Location);
AirDensity airDensity =
scenario.AirDensities
.GetVariantResult("Full")
.GetValueForLocation(turbine.HubHeightLocation);
double rotorArea = Math.PI * Math.Pow(turbine.TurbineType.RotorDiameter * 0.5, 2);
double power = 0.5 * airDensity * rotorArea * Math.Pow(meanFreeWindSpeed, 3);
Toolbox.Log(string.Format(
"The available power at turbine {0} is {1} W/m2",
turbine.Name,
power));
}
Access flow and performance matrix data by flow case
/// <summary>
/// An example of how to get flow and performance matrix data by flow case.
/// </summary>
/// <param name="scenario">A scenario</param>
/// <param name="turbine">A turbine</param>
public void Access_flow_and_performance_matrix_data_by_flow_case(
Scenario scenario,
ReadOnlyTurbine turbine)
{
Speed speed = new Speed(10);
DirectionBearing direction = new DirectionBearing(250);
// Access the probability distribution over mast wind speed for the above flow case.
// Corresponds to channel #9 in WF Classic.
FlowCaseProbability probability =
scenario.FlowCaseProbabilities
.GetVariantResult("Full")
.GetValueForLocation(turbine.HubHeightLocation)
.GetResultForDirectionAndSpeed(
direction,
speed,
FlowCaseBinningType.ReferenceLocationBinning);
// Local probability distribution, corresponding to channel #16 in WF Classic.
FlowCaseProbability localProbability =
scenario.FlowCaseProbabilities
.GetVariantResult("Full")
.GetValueForLocation(turbine.HubHeightLocation)
.GetResultForDirectionAndSpeed(
direction,
speed,
FlowCaseBinningType.LocalBinning);
// Turbine electrical power in kW. Channel #2.
Power powerOutput =
scenario.FlowCaseTurbinePowers
.GetVariantResult("Full")
.GetValueForTurbine(turbine)
.GetResultForDirectionAndSpeed(direction, speed);
// Terrain slope
TerrainSlope slope =
scenario.TerrainSlopes
.GetVariantResult("Full")
.GetValueForLocation(turbine.Location)
.GetResult(direction);
}
Run energy and access the results using the efficiencies calculation
Workbook.ModelSettings.EnergySettings.CalculateEfficiencies = true;
Scenario scenario = Toolbox.CalculateEnergy();
ReadOnlyTurbine turbine = scenario.Turbines.First(); // First turbine in the list
Yield grossYield =
scenario.TurbineTotalYields
.GetVariantResult("Gross")
.GetValueForTurbine(turbine);
Yield standardWakeYield =
scenario.TurbineTotalYields
.GetVariantResult("InternalWakesOn")
.GetValueForTurbine(turbine);
Yield hysteresisYield =
scenario.TurbineTotalYields
.GetVariantResult("HysteresisAdjustmentOn")
.GetValueForTurbine(turbine);
Yield lwfYield =
scenario.TurbineTotalYields
.GetVariantResult("LargeWindFarmCorrectionOn")
.GetValueForTurbine(turbine);
Yield externalWakeYield =
scenario.TurbineTotalYields
.GetVariantResult("NeighbourWakesOn")
.GetValueForTurbine(turbine);
Yield curtailmentYield =
scenario.TurbineTotalYields
.GetVariantResult("CurtailmentOn")
.GetValueForTurbine(turbine);
// Calculate efficiencies from each run
double standardWakeEfficiency = standardWakeYield / grossYield;
double hysteresisEfficiency = hysteresisYield / standardWakeYield;
double lwfEfficiency = lwfYield / hysteresisYield;
double externalWakeEfficiency = externalWakeYield / lwfYield;
double curtailmentEfficiency = curtailmentYield / externalWakeYield;
double modelledWakeEfficiency =
standardWakeEfficiency * lwfEfficiency * externalWakeEfficiency;
Calculate the Ideal Yield
The Ideal Yield for a turbine is a theoretical energy yield that would be generated if the turbine were placed at its initiation mast. The ideal yield is an optionally calculated variant and available only for the new energy calculation.
The script below will run the energy calculation and then output in the log the result of the ideal yield, and the result of the gross yield (where the turbine is actually placed)
Workbook.ModelSettings.EnergySettings.CalculationToUse = EnergyCalculationToUseType.New;
Workbook.ModelSettings.EnergySettings.CalculateIdealYield = true;
Toolbox.CalculateEnergy();
Scenario results = Workbook.CurrentScenario;
foreach (var windfarm in results.WindFarms.Where(w => w.IsNeighbour == false && w.ExcludeFromCalculation == false))
{
foreach (var turbine in windfarm.Turbines.Where(t => t.ExcludeFromCalculation == false))
{
double idealYield = results.TurbineTotalYields.GetVariantResult("Ideal").GetValueForTurbine(turbine).Value / 1000.0;
double grossYield = results.TurbineTotalYields.GetVariantResult("Gross").GetValueForTurbine(turbine).Value / 1000.0;
Toolbox.Log(string.Format("turbine {0} \n ideal yield = \t{1}\n gross yield = \t{2}\n", turbine.Name, idealYield, grossYield));
}
}