from matplotlib import rcParams
# update the default colours for plots
from cycler import cycler
rcParams['axes.prop_cycle'] = cycler(color=[
'#009fda', #cyan
'#0f204b', #dark blue
'#36842d', #land green
'#e98300', #orange
'#fecb00', #yellow
'#6e5091', #violet
'#c4262e', #red
])
#Setup required Python libraries and import the Bladed API
import sys # This provides Python system tools
import os # This provides operating system (os) tools
import clr # This allows us to import .Net assemblies, required for the following import statement
import math
import ctypes
import platform
import string
import pandas as pd
from random import *
%matplotlib inline
# Project and Batch API
sys.path.append(r'C:\DNV GL\Bladed 4.11')
clr.AddReference('GH.Bladed.Api.Facades')
from GH.Bladed.Api.Facades.EntryPoint import Bladed
clr.AddReference("GH.Bladed.DataModel") # This loads the datamodel so enum values can be accessed
from GH.Bladed.DataModel import Facades as GH_Bladed_DataModel_Facades
Bladed.Reset() #clear any pre-existing data e.g. from failed runs of this script
Bladed.ProjectApi.Settings.OverwriteOutputs = True
# Results API
sys.path.append(r"C:\DNV GL\Bladed Results API 1.0\Library\PythonUtils")
import ReferenceBladedResultsApi
from ResultsApi.EntryPoint import ResultsApi
from ResultsApiUtils import DotNetArrayToNumpy
# Results API Usage examples
sys.path.append(r"C:\DNV GL\Bladed Results API 1.0\Usage Examples\Python")
import RetrieveBStats
import RetrieveULoads
import RetrieveDELs
print("Libraries loaded successfully")
Libraries loaded successfully
ROOT_DIR = r"C:\Bladed\WorkflowDemo" #where runs will be saved
Bladed.BatchApi.StartFramework() #start the batch
batch_directory = os.path.join(ROOT_DIR, "batch") #specify full path to batch folder
Bladed.BatchApi.SetDirectory(batch_directory) #set the directory for jobs to be queued to
print("Batch launched Successfully")
Batch launched Successfully
#Specify the run we will use as a template and load it
PROJECT_FILE_PATH = r"C:\DNV GL\Bladed 4.11\demo_a.prj" #specify the project template
prj = Bladed.ProjectApi.GetProject(PROJECT_FILE_PATH) #load the project template
print("Project template loaded successfully")
Project template loaded successfully
rated_speed_folder = ROOT_DIR + '\\V_rated'
# Set simulation settings
prj.Simulation.SimulationType = GH_Bladed_DataModel_Facades.SimulationTypeEnumFacade.PowerProduction
prj.Simulation.SimulationSetup.SimulationEndTime = prj.Simulation.SimulationSetup.OutputStartTime + 30.0
# Set common wind settings
prj.Environment.Wind.TimeVaryingWind.ModelType = GH_Bladed_DataModel_Facades.WindModelEnumFacade.ConstantWind
prj.Environment.Wind.TimeVaryingWind.ConstantWind.ReferToHub = True
prj.Environment.Wind.TimeVaryingWind.ConstantWind.Direction = 0.
prj.Environment.Wind.TimeVaryingWind.ConstantWind.Inclination = math.radians(8.)
prj.Environment.Wind.WindShear.VerticalWindShearType = GH_Bladed_DataModel_Facades.VerticalWindShearEnumFacade.Exponential
prj.Environment.Wind.WindShear.ExponentialVerticalShear.WindShearExponent = 0.2
# It is already known that rated speed is between 11 and 12m/s
speed_list = list(range(3,21)) + [x/10. for x in range(111,120)]
for v_val in speed_list:
prj.Environment.Wind.TimeVaryingWind.ConstantWind.Speed = v_val
calc_folder = os.path.join(rated_speed_folder, "{:04.1f}".format(v_val))
Bladed.ProjectApi.QueueJob(prj, calc_folder, 'powprod')
print('Queued job in folder: ' + calc_folder)
print('Jobs queued successfully')
Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\03.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\04.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\05.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\06.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\07.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\08.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\09.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\10.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\11.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\12.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\13.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\14.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\15.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\16.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\17.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\18.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\19.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\20.0 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\11.1 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\11.2 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\11.3 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\11.4 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\11.5 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\11.6 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\11.7 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\11.8 Queued job in folder: C:\Bladed\WorkflowDemo\V_rated\11.9 Jobs queued successfully
Bladed.BatchApi.SetJobList("Rated_Speed_Calculation") # set batch list
# Add the queued jobs to the batch
Bladed.ProjectApi.AddQueuedJobsToBatch()
print('Jobs added to batch')
# Run the jobs
Bladed.BatchApi.RunBlocking()
print('Batch run complete')
Jobs added to batch Batch run complete
api_var_requests = [ResultsApi.RequestVariable('Electrical power', 'Summary information'),
ResultsApi.RequestVariable('Stationary hub Fx', 'Hub loads: fixed frame GL coordinates')]
bstats_df = RetrieveBStats.retrieve_bstats(rated_speed_folder, api_var_requests)
# Need to cut the wind speed number out of the folder path
bstats_df.index = [float(x[1:5]) for x in bstats_df.index]
mean_values = bstats_df.iloc[:, bstats_df.columns.get_level_values(1)=='Mean']
power_curve = mean_values.iloc[:,0]
ax1 = power_curve.plot(color='#009fda', legend=True, figsize=(15,6))
ax1.legend(loc='upper left')
thrust_curve = mean_values.iloc[:,1]
ax2 = ax1.twinx()
ax2.spines['right'].set_position(('axes', 1.0))
thrust_curve.plot(ax=ax2, color='#36842d', legend=True)
ax2.legend(loc='lower right')
print(mean_values)
Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\20.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\17.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\16.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\13.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\11.9\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\11.6\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\11.1\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\10.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\07.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\04.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\18.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\14.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\11.7\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\11.4\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\11.3\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\09.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\08.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\03.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\19.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\15.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\12.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\11.8\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\11.5\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\11.2\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\11.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\06.0\powprod Retrieving stats from run: C:\Bladed\WorkflowDemo\V_rated\05.0\powprod var Electrical power Stationary hub Fx stat Mean Mean unit kW kN 3.0 0.000926 58.495035 4.0 47.054549 75.517078 5.0 133.218060 92.780379 6.0 246.395850 120.497960 7.0 401.883980 156.743970 8.0 610.648810 198.535440 9.0 879.963310 245.901790 10.0 1231.083900 276.471830 11.0 1631.718100 304.987500 11.1 1673.256000 307.536370 11.2 1714.491800 310.109870 11.3 1755.736400 312.616630 11.4 1796.899600 315.079350 11.5 1838.021200 317.503550 11.6 1879.119200 319.886380 11.7 1920.161000 322.222380 11.8 1961.184300 324.518920 11.9 1999.994700 323.812550 12.0 1999.954600 307.584050 13.0 2000.041300 251.805100 14.0 2000.053500 224.876860 15.0 2000.058800 206.436380 16.0 2000.062000 192.451900 17.0 2000.062200 181.267410 18.0 2000.072800 172.056970 19.0 2000.071600 164.330540 20.0 2000.077500 157.747890
# Read rated speed from above
rated = 11.9
cut_in = prj.Turbine.RotorNacelleAssembly.Rotor.CutInSpeed
cut_out = prj.Turbine.RotorNacelleAssembly.Rotor.CutOutSpeed
speed_steps = [cut_in, rated, cut_out] # Make a list of the speeds
print(speed_steps)
[4.0, 11.9, 25.0]
dlc_path = ROOT_DIR + '\\dlc4p1'
# Set simulations settings
prj.Simulation.SimulationType = GH_Bladed_DataModel_Facades.SimulationTypeEnumFacade.NormalStop
prj.Simulation.SimulationSetup.OutputStartTime = 30 # allow time for simulation to stabilise
prj.Simulation.SimulationSetup.SimulationEndTime = 130 # 100s simualtion
prj.Simulation.SimulationSetup.TimeToBeginStop = 40 # begin stop 10s after output starts to write
print("Common run timings set")
# Set common wind settings
prj.Environment.Wind.TimeVaryingWind.ModelType = GH_Bladed_DataModel_Facades.WindModelEnumFacade.ConstantWind
prj.Environment.Wind.TimeVaryingWind.ConstantWind.ReferToHub = True # we are specifying hub height velocity
prj.Environment.Wind.TimeVaryingWind.ConstantWind.Inclination = math.radians(8.0) # wind inclination (convert to radians)
print("Common wind conditions set")
direction_steps = [-8, 0, 8] # Standard values
for wind_speed_index, wind_speed in enumerate(speed_steps):
for direction_index, direction in enumerate(direction_steps):
prj.Environment.Wind.TimeVaryingWind.ConstantWind.Speed = wind_speed # set wind speed
prj.Environment.Wind.TimeVaryingWind.ConstantWind.Direction = math.radians(direction) # wind direction
case_label = string.ascii_lowercase[wind_speed_index] + string.ascii_lowercase[direction_index] # set name of case
output_path = os.path.join(dlc_path,case_label) # set path to save case to
Bladed.ProjectApi.QueueJob(prj, output_path, "nstop") # queue the job for this wind speed/direction to memory
print("Case at {} m/s, {} deg, queued for path: {}".format(wind_speed,direction, output_path))
print("Jobs queued for adding to batch")
Common run timings set Common wind conditions set Case at 4.0 m/s, -8 deg, queued for path: C:\Bladed\WorkflowDemo\dlc4p1\aa Case at 4.0 m/s, 0 deg, queued for path: C:\Bladed\WorkflowDemo\dlc4p1\ab Case at 4.0 m/s, 8 deg, queued for path: C:\Bladed\WorkflowDemo\dlc4p1\ac Case at 11.9 m/s, -8 deg, queued for path: C:\Bladed\WorkflowDemo\dlc4p1\ba Case at 11.9 m/s, 0 deg, queued for path: C:\Bladed\WorkflowDemo\dlc4p1\bb Case at 11.9 m/s, 8 deg, queued for path: C:\Bladed\WorkflowDemo\dlc4p1\bc Case at 25.0 m/s, -8 deg, queued for path: C:\Bladed\WorkflowDemo\dlc4p1\ca Case at 25.0 m/s, 0 deg, queued for path: C:\Bladed\WorkflowDemo\dlc4p1\cb Case at 25.0 m/s, 8 deg, queued for path: C:\Bladed\WorkflowDemo\dlc4p1\cc Jobs queued for adding to batch
Bladed.BatchApi.SetJobList("dlc4.1") # set batch list
Bladed.ProjectApi.AddQueuedJobsToBatch()
print("All jobs successfully added to batch")
# Run the jobs
Bladed.BatchApi.RunBlocking()
print('Batch run complete')
All jobs successfully added to batch Batch run complete
run_folder = dlc_path
# Retrieve BStats
api_var_requests = [ResultsApi.RequestVariable('Stationary hub My', 'Hub loads: fixed frame GL coordinates')]
bstats_df = RetrieveBStats.retrieve_bstats(run_folder, api_var_requests)
maxes = bstats_df.iloc[:, bstats_df.columns.get_level_values(1) == 'Max']
ax_stats = maxes.plot(kind='bar')
ax_stats.grid()
# Retrieve time series
runs = ResultsApi.GetRuns(run_folder)
series_df = pd.DataFrame() # Empty dataframe to be filled later
numpyXValues_max = []
for run in runs:
# Note that you could use run.CompletionState to determine if the run was completed successfully
series = run.GetSeries('Stationary hub My', 'Hub loads: fixed frame GL coordinates')
numpyXValues = DotNetArrayToNumpy(series.GetXValues())
# Normal stop calculations are variable length, so need to store the x-values for longest time history
if len(numpyXValues) > len(numpyXValues_max):
numpyXValues_max = numpyXValues
numpyYValues = DotNetArrayToNumpy(series.GetYValues())
# Store y-values in a dataframe with the run location (minus the root directory)
numpyYValues_df = pd.DataFrame(numpyYValues,
columns=[run.DirectoryPath.replace(ROOT_DIR,'')])
# Concatenate the y-values with those already in the dataframe
series_df = pd.concat([series_df, numpyYValues_df], axis=1)
# Plot time series
series_df.index = numpyXValues
ax = series_df.plot(figsize=(15,6))
# Only interesting data up to 30s
ax.set_xlim(0,30)
ax.legend(loc='upper right')
ax.grid()
Retrieving stats from run: C:\Bladed\WorkflowDemo\dlc4p1\cc\nstop Retrieving stats from run: C:\Bladed\WorkflowDemo\dlc4p1\bc\nstop Retrieving stats from run: C:\Bladed\WorkflowDemo\dlc4p1\ba\nstop Retrieving stats from run: C:\Bladed\WorkflowDemo\dlc4p1\ab\nstop Retrieving stats from run: C:\Bladed\WorkflowDemo\dlc4p1\ca\nstop Retrieving stats from run: C:\Bladed\WorkflowDemo\dlc4p1\bb\nstop Retrieving stats from run: C:\Bladed\WorkflowDemo\dlc4p1\aa\nstop Retrieving stats from run: C:\Bladed\WorkflowDemo\dlc4p1\cb\nstop Retrieving stats from run: C:\Bladed\WorkflowDemo\dlc4p1\ac\nstop
# Get a group of results to use for uloads (Results API)
groupName = "Hub loads: fixed frame GL coordinates"
stat_hub_load_group = runs[0].GetGroupByName(groupName)
for DependentVariable in stat_hub_load_group.DependentVariables:
print(DependentVariable.Name)
Stationary hub Mx Stationary hub My Stationary hub Mz Stationary hub Myz Stationary hub Fx Stationary hub Fy Stationary hub Fz Stationary hub Fyz
# Retrieve a template uloads calculation
uload_file = r'C:\Bladed\WorkflowDemo\uloads.prj'
uload_prj = Bladed.ProjectApi.GetProject(uload_file)
uload_path = ROOT_DIR + '\\uloads'
print('ULoads template loaded')
ULoads template loaded
# Set defaults for uloads calculation
MAXMIN = uload_prj.LegacyModel.MAXMIN
MAXMIN.iUseGroups = 1 # Load case groups
MAXMIN.iSubGroupsOn = 0 # Not using sub groups for this demo
MAXMIN.iReportSafetyFac = 1
MAXMIN.iHistType = 1 # Absolute maximum
# Set up variables
MAXMINVars = uload_prj.LegacyModel.MAXMINVars
# Clear out the existing definitions, there's a blank definition at index 0 that's not used in the calc
for x in reversed(list(range(1, MAXMINVars.Count))):
MAXMINVars.RemoveAt(x)
# Loop through variables
for var in stat_hub_load_group.DependentVariables:
MAXMINVars.Add(MAXMINVars[0].Clone())
var_counter = MAXMINVars.Count - 1
MAXMINVars[var_counter].sDescription = var.Name # For 2D outputs (e.g. tower stations), this would include the location
MAXMINVars[var_counter].sVariab = var.Name
MAXMINVars[var_counter].sAttribf = '%{}'.format(stat_hub_load_group.FileExtensionNumericComponent)
MAXMINVars[var_counter].iDefaultSF = -1
MAXMINVars[var_counter].fSafetyFactor = 0
MAXMINVars[var_counter].iNDimens = 2 # 3 for 2D data (e.g. tower stations)
MAXMINVars[var_counter].iDimFlag = -1 # station location (float or string)
MAXMIN.iNVars = MAXMINVars.Count - 1
# Setup the load case groups and safety factors
LoadCaseGroup_dict = {'dlc4.1': 1.35}
MAXMINGroups = uload_prj.LegacyModel.MAXMINGroups
# Clear out the existing definitions, there's a blank definition at index 0 that's not used in the calc
for x in reversed(list(range(1, MAXMINGroups.Count))):
MAXMINGroups.RemoveAt(x)
# Loop through the groups and safety factors
for k, v in LoadCaseGroup_dict.items():
MAXMINGroups.Add(MAXMINGroups[0].Clone())
group_counter = MAXMINGroups.Count - 1
MAXMINGroups[group_counter].sName = k
MAXMINGroups[group_counter].fSafetyFactor = v
MAXMIN.iNumGroups = MAXMINGroups.Count - 1
# Subgroups not used in this example, various commented out lines demonstrate the possible usage
# for x in reversed(list(range(1, MAXMIN.iSubGroupType.Count))):
# MAXMIN.iSubGroupType.RemoveAt(x)
# Setup the load cases
MAXMINCases = uload_prj.LegacyModel.MAXMINCases
# Clear out the existing definitions, there's a blank definition at index 0 that's not used in the calc
for x in reversed(list(range(1, MAXMINCases.Count))):
MAXMINCases.RemoveAt(x)
for run in runs:
# if SubGroupType == 'Mean':
# MAXMIN.iSubGroupType.Add(1)
# elif SubGroupType == 'Half':
# MAXMIN.iSubGroupType.Add(2)
MAXMINCases.Add(MAXMINCases[0].Clone())
case_counter = MAXMINCases.Count - 1
MAXMINCases[case_counter].sDirectory = run.DirectoryPath
MAXMINCases[case_counter].sRunName = run.RunName
MAXMINCases[case_counter].sCase = run.DirectoryPath.replace(ROOT_DIR,'')
MAXMINCases[case_counter].sGroup = 'dlc4.1' # Load case group
# MAXMINCases[case_counter].iSubGroup = MAXMIN.iSubGroupType.Count - 1
MAXMIN.iNCases = MAXMINCases.Count - 1
# MAXMIN.iNumSubGroup = MAXMIN.iSubGroupType.Count - 1
Bladed.ProjectApi.QueueJob(uload_prj, uload_path, "uloads")
print('uloads calculation queued')
uloads calculation queued
Bladed.BatchApi.SetJobList('Ultimate load Postprocessing')
Bladed.ProjectApi.AddQueuedJobsToBatch()
print('ULoads calculation added to batch')
# Run the jobs
Bladed.BatchApi.RunBlocking()
print('Batch run complete')
ULoads calculation added to batch Batch run complete
uload_df_out, uloads_maxmin_df_out = RetrieveULoads.retrieve_uloads(uload_path + "\\uloads.$TE")
uload_df_out
Retrieving uload table data for C:\Bladed\WorkflowDemo\uloads\uloads Retrieved uload table data Created uload table dataframe Created uload extreme values dataframe
variable | LoadCaseID | Stationary hub Mx | Stationary hub My | Stationary hub Mz | Stationary hub Myz | Stationary hub Fx | Stationary hub Fy | Stationary hub Fz | Stationary hub Fyz | SafetyFactor | |
---|---|---|---|---|---|---|---|---|---|---|---|
unit | - | kNm | kNm | kNm | kNm | kN | kN | kN | kN | - | |
variable | max/min | ||||||||||
Stationary hub Mx | MAX | \dlc4p1\cb | 1607.2700 | 928.277000 | -436.458000 | 1025.760000 | 191.68100 | -10.517300 | -439.018 | 439.144 | 1.35 |
MIN | \dlc4p1\ab | -790.5670 | -16.797100 | -5.494510 | 17.672900 | 26.01630 | -7.338620 | -446.458 | 446.519 | 1.35 | |
Stationary hub My | MAX | \dlc4p1\cc | 1554.6300 | 1955.900000 | -141.161000 | 1960.990000 | 167.51700 | -32.672600 | -435.024 | 436.250 | 1.35 |
MIN | \dlc4p1\ca | 195.7730 | -1117.170000 | -721.223000 | 1329.750000 | -17.05200 | 9.291140 | -408.769 | 408.874 | 1.35 | |
Stationary hub Mz | MAX | \dlc4p1\ba | 1551.2100 | 515.475000 | 756.822000 | 915.692000 | 440.25600 | 9.508210 | -452.323 | 452.423 | 1.35 |
MIN | \dlc4p1\cb | 454.2740 | 487.008000 | -1569.240000 | 1643.080000 | -13.07210 | -11.872900 | -411.378 | 411.550 | 1.35 | |
Stationary hub Myz | MAX | \dlc4p1\cc | 1554.3300 | 1953.900000 | -174.708000 | 1961.690000 | 167.34300 | -32.960100 | -436.609 | 437.852 | 1.35 |
MIN | \dlc4p1\ac | -14.2621 | 0.861956 | 0.416762 | 0.957422 | 2.65917 | -1.127520 | -446.631 | 446.632 | 1.35 | |
Stationary hub Fx | MAX | \dlc4p1\bb | 1563.6000 | 186.752000 | 405.492000 | 446.431000 | 445.95600 | -4.461950 | -452.939 | 452.961 | 1.35 |
MIN | \dlc4p1\ba | 335.4750 | -188.316000 | -452.649000 | 490.259000 | -94.63520 | 0.517862 | -435.500 | 435.500 | 1.35 | |
Stationary hub Fy | MAX | \dlc4p1\ca | -19.2095 | -201.783000 | -69.173300 | 213.311000 | 27.24250 | 44.929500 | -423.063 | 425.442 | 1.35 |
MIN | \dlc4p1\cc | 314.4400 | 1061.710000 | 4.945450 | 1061.720000 | -20.99550 | -44.441000 | -416.551 | 418.915 | 1.35 | |
Stationary hub Fz | MAX | \dlc4p1\cb | 311.5620 | -81.745000 | -972.476000 | 975.906000 | -2.05378 | -4.820350 | -380.946 | 380.977 | 1.35 |
MIN | \dlc4p1\bc | 261.2860 | -280.269000 | 461.353000 | 539.812000 | -38.20310 | 1.126680 | -464.549 | 464.551 | 1.35 | |
Stationary hub Fyz | MAX | \dlc4p1\bc | 261.2860 | -280.269000 | 461.353000 | 539.812000 | -38.20310 | 1.126680 | -464.549 | 464.551 | 1.35 |
MIN | \dlc4p1\cb | 311.5620 | -81.745000 | -972.476000 | 975.906000 | -2.05378 | -4.820350 | -380.946 | 380.977 | 1.35 |
# Load Kaimal template
wind_file_template = r'C:\Bladed\WorkflowDemo\kaimal_wind_file.prj'
wind_file_prj = Bladed.ProjectApi.GetProject(wind_file_template)
wind_files_folder = ROOT_DIR + '\\wind_files'
for wind_speed in range(4,21,2):
wind_file_prj.PreProcessing.TurbulenceGeneration.MeanSpeed = wind_speed
wind_folder = wind_files_folder + '\\' + str(int(wind_speed))
for seed in range(1,3): # Just make 2 seeds for simplicity, normally 6+ with direction variation
random_seed_number = randint(1,1000)
wind_file_prj.PreProcessing.TurbulenceGeneration.TurbulenceSeed = random_seed_number
wind_file = wind_folder + '\\turb_{}'.format(seed)
wind_file_prj.PreProcessing.TurbulenceGeneration.OutputFileName = wind_file
Bladed.ProjectApi.QueueJob(wind_file_prj, wind_folder, "turb_" + str(seed))
# Note that the wind files would normally be an appropriate length for the simulations that will be run (e.g. 600s)
print('Wind file generation calculations queued')
Wind file generation calculations queued
Bladed.BatchApi.SetJobList('wind_files')
Bladed.ProjectApi.AddQueuedJobsToBatch()
print('wind file calculations added to batch')
# Run the jobs
Bladed.BatchApi.RunBlocking()
print('Batch run complete')
wind file calculations added to batch Batch run complete
dlc1p2_path = ROOT_DIR + '\\dlc1p2'
prj.Simulation.SimulationType = GH_Bladed_DataModel_Facades.SimulationTypeEnumFacade.PowerProduction
# Short simulations for demo, normally 600s
prj.Simulation.SimulationSetup.SimulationEndTime = prj.Simulation.SimulationSetup.OutputStartTime + 60.0
# Set common wind settings
prj.Environment.Wind.TimeVaryingWind.ModelType = GH_Bladed_DataModel_Facades.WindModelEnumFacade.TurbulentWind
prj.Environment.Wind.TimeVaryingWind.TurbulentWind.ReferToHub = True
prj.Environment.Wind.TimeVaryingWind.TurbulentWind.Direction = 0.
prj.Environment.Wind.TimeVaryingWind.TurbulentWind.Inclination = math.radians(8.)
prj.Environment.Wind.WindShear.VerticalWindShearType = GH_Bladed_DataModel_Facades.VerticalWindShearEnumFacade.Exponential
prj.Environment.Wind.WindShear.ExponentialVerticalShear.WindShearExponent = 0.2
for wind_speed_index, wind_speed in enumerate(range(4,21,2)):
prj.Environment.Wind.TimeVaryingWind.TurbulentWind.MeanSpeed = wind_speed
for seed in range(1,3): # Just make 2 seeds for simplicity, normally 6+ with direction variation
wind_file = wind_files_folder + '\\{}\\turb_{}.wnd'.format(int(wind_speed), seed)
prj.Environment.Wind.TimeVaryingWind.TurbulentWind.WindFile = wind_file
# Normally the turbulence intensity would be set to different values for each wind speed
case_label = string.ascii_lowercase[wind_speed_index] + str(seed) # set name of case
output_path = os.path.join(dlc1p2_path, case_label) # set path to save case to
Bladed.ProjectApi.QueueJob(prj, output_path, "powprod") # queue the job for this wind speed/direction to memory
print("Case at {} m/s, seed {}, queued for path: {}".format(wind_speed,seed, output_path))
print('Jobs queued')
Case at 4 m/s, seed 1, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\a1 Case at 4 m/s, seed 2, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\a2 Case at 6 m/s, seed 1, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\b1 Case at 6 m/s, seed 2, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\b2 Case at 8 m/s, seed 1, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\c1 Case at 8 m/s, seed 2, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\c2 Case at 10 m/s, seed 1, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\d1 Case at 10 m/s, seed 2, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\d2 Case at 12 m/s, seed 1, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\e1 Case at 12 m/s, seed 2, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\e2 Case at 14 m/s, seed 1, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\f1 Case at 14 m/s, seed 2, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\f2 Case at 16 m/s, seed 1, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\g1 Case at 16 m/s, seed 2, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\g2 Case at 18 m/s, seed 1, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\h1 Case at 18 m/s, seed 2, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\h2 Case at 20 m/s, seed 1, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\i1 Case at 20 m/s, seed 2, queued for path: C:\Bladed\WorkflowDemo\dlc1p2\i2 Jobs queued
Bladed.BatchApi.SetJobList('dlc1.2')
Bladed.ProjectApi.AddQueuedJobsToBatch()
print('dlc1.2 calculations added to batch')
# Run the jobs
Bladed.BatchApi.RunBlocking()
print('Batch run complete')
dlc1.2 calculations added to batch Batch run complete
runs = ResultsApi.GetRuns(dlc1p2_path)
# Get a group of results to use for rainflow (Results API)
groupName = "Hub loads: fixed frame GL coordinates"
stat_hub_load_group = runs[0].GetGroupByName(groupName)
for DependentVariable in stat_hub_load_group.DependentVariables:
print(DependentVariable.Name)
Stationary hub Mx Stationary hub My Stationary hub Mz Stationary hub Myz Stationary hub Fx Stationary hub Fy Stationary hub Fz Stationary hub Fyz
# Retrieve a template rainflow calculation
rainflow_file = r'C:\Bladed\WorkflowDemo\rainflow.prj'
rainflow_prj = Bladed.ProjectApi.GetProject(rainflow_file)
rainflow_path = ROOT_DIR + '\\rainflow'
print('Rainflow template loaded')
Rainflow template loaded
# Set runs
MultiRuns = rainflow_prj.LegacyModel.MultiRuns
# Clear out the existing definitions, there's a blank definition at index 0 that's not used in the calc
for x in reversed(list(range(1, MultiRuns.Count))):
MultiRuns.RemoveAt(x)
for run in runs:
MultiRuns.Add(MultiRuns[0].Clone())
case_counter = MultiRuns.Count - 1
MultiRuns[case_counter].sDirectory = run.DirectoryPath
MultiRuns[case_counter].sRunName = run.RunName
MultiRuns[case_counter].sConfig = 'H' # Hours
# Just equally weight them for simplicity for demo,
# normally the time at different wind speeds would be assigned according to a distribution (e.g. Weibull)
MultiRuns[case_counter].fOccFreq = 8766. / 18. * 60. * 60. # Seconds per year
MultiVars = rainflow_prj.LegacyModel.MultiVars
# Clear out the existing definitions, there's a blank definition at index 0 that's not used in the calc
for x in reversed(list(range(1, MultiVars.Count))):
MultiVars.RemoveAt(x)
# Loop through variables
for var in stat_hub_load_group.DependentVariables:
if not any(x in var.Name for x in ['xy', 'yz']): # Resultant loads not relevant for fatigue
MultiVars.Add(MultiVars[0].Clone())
var_counter = MultiVars.Count - 1
MultiVars[var_counter].sDescription = var.Name # For 2D outputs (e.g. tower stations), this would include the location
MultiVars[var_counter].sVariab = var.Name
MultiVars[var_counter].sAttribf = '%{}'.format(stat_hub_load_group.FileExtensionNumericComponent)
MultiVars[var_counter].iNDimens = 2 # 3 for 2D data (e.g. tower stations)
MultiVars[var_counter].iDimFlag = -1 # station location (float or string)
MultiVars[var_counter].iNBins = 128
Bladed.ProjectApi.QueueJob(rainflow_prj, rainflow_path, "rainflow")
print('rainflow calculation queued')
rainflow calculation queued
Bladed.BatchApi.SetJobList('Rainflow post processing')
Bladed.ProjectApi.AddQueuedJobsToBatch()
print('rainflow calculations added to batch')
# Run the jobs
Bladed.BatchApi.RunBlocking()
print('Batch run complete')
rainflow calculations added to batch Batch run complete
# Retrieve DELs
del_distribution_df_out, totals_df_out, number_of_cycles_out = RetrieveDELs.retrieve_dels(rainflow_path + "\\rainflow.$TE")
# Plot histogram
row_to_plot = del_distribution_df_out.iloc[[0]]
del_histo_fig = row_to_plot.transpose().plot(kind='bar', figsize=(15, 7)).get_figure()
del_histo_fig.axes[0].set_xlabel("Loadcase")
del_histo_fig.axes[0].set_ylabel("Lifetime weighted equivalent loads {}\n {}, inverse SN slope={} [{}]"
.format(number_of_cycles_out,
row_to_plot.index.values[0][0],
row_to_plot.index.values[0][2],
row_to_plot.index.values[0][1]))
del_histo_fig.tight_layout()
# DELs total table
totals_df_out
Retrieving rainflow data for C:\Bladed\WorkflowDemo\rainflow\rainflow Number of cycles: 1.00E+07 cycles Common Path: 'C:\Bladed\WorkflowDemo\dlc1p2\' DEL histogram data stored in dataframe Total DEL data stored in dataframe
variable | Stationary hub Mx | Stationary hub My | Stationary hub Mz | Stationary hub Fx | Stationary hub Fy | Stationary hub Fz |
---|---|---|---|---|---|---|
unit | kNm | kNm | kNm | kN | kN | kN |
Inverse SN Slope | ||||||
3.0 | 454.200134 | 3504.003418 | 3529.211670 | 218.658188 | 95.149284 | 141.424393 |
4.0 | 403.304443 | 2899.914795 | 2907.915283 | 187.389771 | 77.687775 | 109.956551 |
5.0 | 401.785736 | 2695.407471 | 2682.520996 | 177.488495 | 71.904671 | 98.668388 |
6.0 | 412.064636 | 2630.648682 | 2594.739746 | 174.825577 | 70.079750 | 94.641830 |
7.0 | 424.062653 | 2623.054199 | 2564.957031 | 175.050583 | 69.834518 | 93.751907 |
8.0 | 435.237671 | 2639.950195 | 2562.231201 | 176.473557 | 70.256668 | 94.261665 |
9.0 | 445.123230 | 2667.057617 | 2572.761963 | 178.361359 | 70.954834 | 95.358841 |
10.0 | 453.787537 | 2697.828857 | 2589.777832 | 180.380707 | 71.749916 | 96.657372 |
11.0 | 461.408386 | 2729.197998 | 2609.723633 | 182.379333 | 72.557297 | 97.977470 |
12.0 | 468.160278 | 2759.735107 | 2630.654297 | 184.290512 | 73.337105 | 99.239449 |