Skip to content

Commit

Permalink
Merge pull request NREL#31 from dzalkind/openfast_250
Browse files Browse the repository at this point in the history
Update to OpenFAST 2.5.0
  • Loading branch information
nikhar-abbas authored Feb 5, 2021
2 parents 65620c1 + 4a76068 commit 08c9ae7
Show file tree
Hide file tree
Showing 28 changed files with 398 additions and 233 deletions.
96 changes: 48 additions & 48 deletions Examples/DISCON.IN

Large diffs are not rendered by default.

Binary file modified Examples/NREL5MW_saved.p
Binary file not shown.
9 changes: 5 additions & 4 deletions Examples/example_01.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
from ROSCO_toolbox import turbine as ROSCO_turbine

# Load yaml file
parameter_filename = os.path.join(os.path.dirname(__file__),'NREL5MW_example.yaml')
this_dir = os.path.dirname(os.path.abspath(__file__))
parameter_filename = os.path.join(this_dir,'NREL5MW_example.yaml')
inps = yaml.safe_load(open(parameter_filename))
path_params = inps['path_params']
turbine_params = inps['turbine_params']
Expand All @@ -28,13 +29,13 @@

turbine.load_from_fast(
path_params['FAST_InputFile'],
os.path.join(os.path.dirname(__file__),path_params['FAST_directory']),
os.path.join(this_dir,path_params['FAST_directory']),
dev_branch=True,
rot_source='txt',txt_filename=os.path.join(os.path.dirname(__file__),path_params['rotor_performance_filename'])
rot_source='txt',txt_filename=os.path.join(this_dir,path_params['rotor_performance_filename'])
)

# Print some basic turbine info
print(turbine)

# Save the turbine model
turbine.save(os.path.join(os.path.dirname(__file__),'NREL5MW_saved.p'))
turbine.save(os.path.join(this_dir,'NREL5MW_saved.p'))
3 changes: 2 additions & 1 deletion Examples/example_02.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
turbine = ROSCO_turbine.Turbine

# Load quick from python pickle
turbine = turbine.load(os.path.join(os.path.dirname(__file__),'NREL5MW_saved.p'))
this_dir = os.path.dirname(os.path.abspath(__file__))
turbine = turbine.load(os.path.join(this_dir,'NREL5MW_saved.p'))

# plot rotor performance
print('Plotting Cp data')
Expand Down
7 changes: 4 additions & 3 deletions Examples/example_03.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
control_params = {}

# Load yaml file
parameter_filename = os.path.join(os.path.dirname(__file__),'NREL5MW_example.yaml')
this_dir = os.path.dirname(os.path.abspath(__file__))
parameter_filename = os.path.join(this_dir,'NREL5MW_example.yaml')
inps = yaml.safe_load(open(parameter_filename))
path_params = inps['path_params']
turbine_params = inps['turbine_params']
Expand All @@ -29,11 +30,11 @@
turbine = ROSCO_turbine.Turbine(turbine_params)
turbine.load_from_fast(
path_params['FAST_InputFile'],
os.path.join(os.path.dirname(__file__),path_params['FAST_directory']),
os.path.join(this_dir,path_params['FAST_directory']),
dev_branch=True,
rot_source='cc-blade',
txt_filename=None)

# Write rotor performance text file
txt_filename = os.path.join(os.path.dirname(__file__),'Cp_Ct_Cq.Ex03.txt')
txt_filename = os.path.join(this_dir,'Cp_Ct_Cq.Ex03.txt')
write_rotor_performance(turbine,txt_filename=txt_filename)
7 changes: 4 additions & 3 deletions Examples/example_04.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
from ROSCO_toolbox.utilities import write_DISCON

# Load yaml file
parameter_filename = os.path.join(os.path.dirname(__file__),'NREL5MW_example.yaml')
this_dir = os.path.dirname(os.path.abspath(__file__))
parameter_filename = os.path.join(this_dir,'NREL5MW_example.yaml')
inps = yaml.safe_load(open(parameter_filename))
path_params = inps['path_params']
turbine_params = inps['turbine_params']
Expand All @@ -33,9 +34,9 @@
# Load turbine data from OpenFAST and rotor performance text file
turbine.load_from_fast(
path_params['FAST_InputFile'],
os.path.join(os.path.dirname(__file__),path_params['FAST_directory']),
os.path.join(this_dir,path_params['FAST_directory']),
dev_branch=True,
rot_source='txt',txt_filename=os.path.join(os.path.dirname(__file__),path_params['rotor_performance_filename'])
rot_source='txt',txt_filename=os.path.join(this_dir,path_params['rotor_performance_filename'])
)

# Tune controller
Expand Down
2 changes: 1 addition & 1 deletion Examples/example_05.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from ROSCO_toolbox import control_interface as ROSCO_ci

# Specify controller dynamic library path and name
this_dir = os.path.dirname(__file__)
this_dir = os.path.dirname(os.path.abspath(__file__))
lib_name = os.path.join(this_dir,'../ROSCO/build/libdiscon.dylib')
param_filename = os.path.join(this_dir,'DISCON.IN')

Expand Down
12 changes: 8 additions & 4 deletions Examples/example_06.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
from ROSCO_toolbox.utilities import write_DISCON, run_openfast
from ROSCO_toolbox import sim as ROSCO_sim

this_dir = os.path.dirname(__file__)
this_dir = os.path.dirname(os.path.abspath(__file__))

# Load yaml file
parameter_filename = os.path.join(this_dir,'NREL5MW_example.yaml')
parameter_filename = os.path.join(os.path.dirname(this_dir), 'Tune_Cases', 'IEA15MW.yaml')
inps = yaml.safe_load(open(parameter_filename))
path_params = inps['path_params']
turbine_params = inps['turbine_params']
Expand All @@ -33,7 +33,10 @@
controller = ROSCO_controller.Controller(controller_params)

# Load turbine data from OpenFAST and rotor performance text file
turbine.load_from_fast(path_params['FAST_InputFile'],path_params['FAST_directory'],dev_branch=True,rot_source='txt',txt_filename=path_params['rotor_performance_filename'])
turbine.load_from_fast(path_params['FAST_InputFile'], \
os.path.join(this_dir,path_params['FAST_directory']), \
dev_branch=True,rot_source='txt',\
txt_filename=os.path.join(this_dir,path_params['FAST_directory'],path_params['rotor_performance_filename']))

# Tune controller
controller.tune_controller(turbine)
Expand All @@ -44,7 +47,8 @@

# Run OpenFAST
# --- May need to change fastcall if you use a non-standard command to call openfast
run_openfast(path_params['FAST_directory'], fastcall='openfast_sdev', fastfile=path_params['FAST_InputFile'], chdir=True)
fastcall = 'openfast'
run_openfast(path_params['FAST_directory'], fastcall=fastcall, fastfile=path_params['FAST_InputFile'], chdir=True)



Expand Down
2 changes: 1 addition & 1 deletion Examples/example_08.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from ROSCO_toolbox.ofTools.fast_io import output_processing
import os

this_dir = os.path.dirname(__file__)
this_dir = os.path.dirname(os.path.abspath(__file__))

# Define openfast output filenames
filenames = ["../Test_Cases/NREL-5MW/NREL-5MW.outb"]
Expand Down
4 changes: 2 additions & 2 deletions Examples/example_09.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
from ROSCO_toolbox.utilities import run_openfast
import os

this_dir = os.path.dirname(__file__)
this_dir = os.path.dirname(os.path.abspath(__file__))

# Define openfast output filenames
wind_directory = os.path.join(this_dir,'../Test_Cases/Wind/')
turbsim_infile = '90m_12mps_twr.inp'

run_openfast(wind_directory, fastcall='turbsim_sdev', fastfile=turbsim_infile, chdir=False)
run_openfast(wind_directory, fastcall='turbsim', fastfile=turbsim_infile, chdir=False)

6 changes: 3 additions & 3 deletions Examples/example_10.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
from ROSCO_toolbox import turbine as ROSCO_turbine
from ROSCO_toolbox import controller as ROSCO_controller

rt_dir = os.path.dirname(os.path.dirname(__file__))
this_dir = os.path.dirname(os.path.abspath(__file__))

# Load yaml file
parameter_filename = os.path.join(rt_dir,'Tune_Cases/BAR.yaml')
parameter_filename = os.path.join(os.path.dirname(this_dir),'Tune_Cases/BAR.yaml')
inps = yaml.safe_load(open(parameter_filename))
path_params = inps['path_params']
turbine_params = inps['turbine_params']
Expand All @@ -34,7 +34,7 @@
turbine = ROSCO_turbine.Turbine(turbine_params)
# turbine.load_from_fast(path_params['FAST_InputFile'],path_params['FAST_directory'],dev_branch=True,rot_source='txt',txt_filename=path_params['rotor_performance_filename'])
turbine.load_from_fast(path_params['FAST_InputFile'], \
os.path.join(rt_dir,path_params['FAST_directory']),dev_branch=True)
os.path.join(this_dir,path_params['FAST_directory']),dev_branch=True)

# Tune controller
controller = ROSCO_controller.Controller(controller_params)
Expand Down
10 changes: 4 additions & 6 deletions ROSCO_testing/run_Testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,14 @@ def run_testing(turbine2test, testtype, rosco_binaries=[], discon_files=[], **kw
if __name__ == "__main__":

# WEIS directory, for running openfast, etc.
# weis_dir = os.environ.get('weis_dir') # works if we do `export weis_dir=$(pwd)` in WEIS directory in terminal
weis_dir = '/Users/dzalkind/Tools/WEIS-3'
this_dir = os.path.dirname(__file__)

# Setup ROSCO testing parameters
rt_kwargs = {}
rt_kwargs['runDir'] = os.path.join(this_dir,'results/') # directory for FAST simulations
rt_kwargs['namebase'] = 'lite_test' # Base name for FAST files
rt_kwargs['FAST_exe'] = os.path.join(weis_dir,'local','bin','openfast') # OpenFAST executable path
rt_kwargs['Turbsim_exe']= os.path.join(weis_dir,'local','bin','turbsim') # Turbsim executable path
rt_kwargs['FAST_exe'] = 'openfast' # OpenFAST executable path
rt_kwargs['Turbsim_exe']= 'turbsim' # Turbsim executable path
rt_kwargs['FAST_ver'] = 'OpenFAST' # FAST version
rt_kwargs['dev_branch'] = True # dev branch of Openfast?
rt_kwargs['debug_level']= 2 # debug level. 0 - no outputs, 1 - minimal outputs, 2 - all outputs
Expand All @@ -99,11 +97,11 @@ def run_testing(turbine2test, testtype, rosco_binaries=[], discon_files=[], **kw
rt_kwargs['outfile_fmt'] = 2 # 1 = .txt, 2 = binary, 3 = both

# ---- Define test type ----
turbine2test = 'IEA-15MW' # IEA-15MW or NREL-5MW
turbine2test = 'NREL-5MW' # IEA-15MW or NREL-5MW
testtype = 'lite' # lite, heavy, binary-comp, discon-comp

# Only fill one of these if comparing controllers
rosco_binaries = [glob.glob(os.path.join(this_dir,'../ROSCO/build/libdiscon*'))[0]] # Differently named libdiscons to compare
rosco_binaries = [glob.glob(os.path.join(this_dir,'../ROSCO/build/libdiscon.*'))[0]] # Differently named libdiscons to compare
discon_files = [] # Differently named DISCON.IN files to compare


Expand Down
11 changes: 6 additions & 5 deletions ROSCO_toolbox/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ def tune_controller(self, turbine):
TSR_rated = rated_rotor_speed*R/turbine.v_rated # TSR at rated

# separate wind speeds by operation regions
v_below_rated = np.arange(turbine.v_min,turbine.v_rated,0.5) # below rated
v_above_rated = np.arange(turbine.v_rated,turbine.v_max,0.5) # above rated
v_below_rated = np.linspace(turbine.v_min,turbine.v_rated, num=30) # below rated
v_above_rated = np.linspace(turbine.v_rated,turbine.v_max, num=30) # above rated
v = np.concatenate((v_below_rated, v_above_rated))

# separate TSRs by operations regions
Expand Down Expand Up @@ -242,12 +242,12 @@ def tune_controller(self, turbine):

# separate and define below and above rated parameters
A_vs = A[0:len(v_below_rated)] # below rated
A_pc = A[len(v_below_rated):len(v)] # above rated
A_pc = A[-len(v_above_rated)+1:] # above rated
B_tau = B_tau * np.ones(len(v))

# -- Find gain schedule --
self.pc_gain_schedule = ControllerTypes()
self.pc_gain_schedule.second_order_PI(self.zeta_pc, self.omega_pc,A_pc,B_beta[len(v_below_rated):len(v)],linearize=True,v=v_above_rated)
self.pc_gain_schedule.second_order_PI(self.zeta_pc, self.omega_pc,A_pc,B_beta[-len(v_above_rated)+1:],linearize=True,v=v_above_rated[1:])
self.vs_gain_schedule = ControllerTypes()
self.vs_gain_schedule.second_order_PI(self.zeta_vs, self.omega_vs,A_vs,B_tau[0:len(v_below_rated)],linearize=False,v=v_below_rated)

Expand Down Expand Up @@ -303,7 +303,8 @@ def tune_controller(self, turbine):
# --- Floating feedback term ---
if self.Fl_Mode == 1: # Floating feedback
Kp_float = (dtau_dv/dtau_dbeta) * turbine.TowerHt * Ng
self.Kp_float = Kp_float[len(v_below_rated)]
f_kp = interpolate.interp1d(v,Kp_float)
self.Kp_float = f_kp(turbine.v_rated * (1.05)) # get Kp at v_rated + 0.5 m/s
# Turn on the notch filter if floating
self.F_NotchType = 2

Expand Down
5 changes: 5 additions & 0 deletions ROSCO_toolbox/ofTools/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# OpenFAST Tools
A set of OpenFAST tools is provided to ease the use of the ROSCO toolbox in conjuction with [OpenFAST](https://github.com/openfast/openfast).

OpenFAST can be installed using conda-forge using
```
conda install -c conda-forge openfast
```

Note that most of these scripts are copy and pasted from [weis's aeroleasticse](https://github.com/WISDEM/WEIS/tree/master/weis/aeroelasticse)

### case_gen
Expand Down
51 changes: 32 additions & 19 deletions ROSCO_toolbox/ofTools/case_gen/CaseGen_IEC.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,10 @@ def execute(self, case_inputs={}):
IEC_WindType = 'NTM'
alpha = 0.2
iecwind = pyIECWind_turb()
TMax = 630.
if self.TMax == 0:
TMax = 720.
else:
TMax = self.TMax

elif dlc in [1.3, 6.1, 6.3]:
if self.Turbine_Class == 'I':
Expand All @@ -93,19 +96,28 @@ def execute(self, case_inputs={}):
IEC_WindType = '%uETM'%x
alpha = 0.11
iecwind = pyIECWind_turb()
TMax = 630.
if self.TMax == 0:
TMax = 720.
else:
TMax = self.TMax

elif dlc == 1.4:
IEC_WindType = 'ECD'
alpha = 0.2
iecwind = pyIECWind_extreme()
TMax = 90.
if self.TMax == 0:
TMax = 120.
else:
TMax = self.TMax

elif dlc == 1.5:
IEC_WindType = 'EWS'
alpha = 0.2
iecwind = pyIECWind_extreme()
TMax = 90.
if self.TMax == 0:
TMax = 120.
else:
TMax = self.TMax

# Windfile generation setup
if self.TMax == 0.:
Expand Down Expand Up @@ -144,24 +156,24 @@ def execute(self, case_inputs={}):
case_inputs_i[("ServoDyn","TPitManS1")] = {'vals':[self.TStart], 'group':0}
case_inputs_i[("ServoDyn","TPitManS2")] = {'vals':[self.TStart], 'group':0}
case_inputs_i[("ServoDyn","TPitManS3")] = {'vals':[self.TStart], 'group':0}
case_inputs_i[("ServoDyn","PitManRat1")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","PitManRat2")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","PitManRat3")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF1")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF2")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF3")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(1)")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(2)")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(3)")] = {'vals':[self.PC_MaxRat], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(1)")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(2)")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(3)")] = {'vals':[90.], 'group':0}
case_inputs_i[("ServoDyn","GenTiStp")] = {'vals':["True"], 'group':0}
case_inputs_i[("ServoDyn","TimGenOf")] = {'vals':[self.TStart], 'group':0}
else:
case_inputs_i[("ServoDyn","TPitManS1")] = {'vals':[9999.9], 'group':0}
case_inputs_i[("ServoDyn","TPitManS2")] = {'vals':[9999.9], 'group':0}
case_inputs_i[("ServoDyn","TPitManS3")] = {'vals':[9999.9], 'group':0}
case_inputs_i[("ServoDyn","PitManRat1")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat2")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat3")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF1")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF2")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF3")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(1)")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(2)")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","PitManRat(3)")] = {'vals':[2.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(1)")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(2)")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","BlPitchF(3)")] = {'vals':[0.], 'group':0}
case_inputs_i[("ServoDyn","GenTiStp")] = {'vals':["True"], 'group':0}
case_inputs_i[("ServoDyn","TimGenOf")] = {'vals':[9999.9], 'group':0}

Expand Down Expand Up @@ -192,7 +204,6 @@ def execute(self, case_inputs={}):
case_inputs_i[("ServoDyn","PCMode")] = {'vals':[5], 'group':0}
case_inputs_i[("AeroDyn15","AFAeroMod")]= {'vals':[2], 'group':0}
case_inputs_i[("ElastoDyn","GenDOF")] = {'vals':["True"], 'group':0}
case_inputs_i[("ElastoDyn","YawDOF")] = {'vals':["True"], 'group':0}


# Matrix combining N dlc variables that affect wind file generation
Expand Down Expand Up @@ -283,7 +294,9 @@ def execute(self, case_inputs={}):
if ("Fst","TMax") not in case_inputs_i:
case_inputs_i[("Fst","TMax")] = {'vals':[TMax], 'group':0}
case_inputs_i[("InflowWind","WindType")] = {'vals':WindFile_type_out, 'group':1}
case_inputs_i[("InflowWind","Filename")] = {'vals':WindFile_out, 'group':1}
case_inputs_i[("InflowWind","Filename_Uni")] = {'vals':WindFile_out, 'group':1}
case_inputs_i[("InflowWind","FileName_BTS")] = {'vals':WindFile_out, 'group':1}
case_inputs_i[("InflowWind","RefLength")] = {'vals':[self.D], 'group':0}

if len(self.dlc_inputs['Yaw'][i]) > 0:
case_inputs_i[("ElastoDyn","NacYaw")] = {'vals':self.dlc_inputs['Yaw'][i], 'group':2}
Expand All @@ -298,7 +311,7 @@ def execute(self, case_inputs={}):
# make unique wave seeds
if self.uniqueWaveSeeds:
seed_base = int(float(dlc) * 10000) # set wave seed based on dlc so no repeats
num_in_dlc = len(case_inputs_i[("InflowWind","Filename")]['vals']) # sims in each DLC
num_in_dlc = len(case_inputs_i[("InflowWind","FileName_BTS")]['vals']) # sims in each DLC
wave_seeds = (seed_base + np.arange(0,num_in_dlc)).tolist()

case_inputs_i[("HydroDyn","WaveSeed1")] = {'vals':wave_seeds, 'group':1}
Expand Down
Loading

0 comments on commit 08c9ae7

Please sign in to comment.