Skip to content

Commit 0d8ccb7

Browse files
committed
Adapting Example 3 for FAST.Farm so it can run on github action
1 parent d7fc711 commit 0d8ccb7

File tree

4 files changed

+106
-74
lines changed

4 files changed

+106
-74
lines changed

openfast_toolbox/fastfarm/examples/Ex1_FASTFarm_discretization.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,20 @@ def main(test=False):
4444
# -----------------------------------------------------------------------------
4545

4646
# ----------- Case absolute path
47-
path = os.path.join(scriptDir, '_ex1')
47+
path = os.path.join(scriptDir, '_ex1') # folder (preferably new) where all the simulation files will be written
4848

4949
# ----------- Execution parameters
5050

5151

5252
# -----------------------------------------------------------------------------
5353
# --------------------------- Farm parameters ---------------------------------
5454
# -----------------------------------------------------------------------------
55-
5655
# ----------- General turbine parameters
57-
cmax = 5 # Maximum blade chord (m)
58-
fmax = 10/6 # Maximum excitation frequency (Hz)
56+
cmax = 5 # Maximum blade chord (m), affects dr
57+
fmax = 10/6 # Maximum excitation frequency (Hz), affects dt_high
5958
Cmeander = 1.9 # Meandering constant (-)
6059
D = 240 # Rotor diameter (m)
6160
zhub = 150 # Hub height (m)
62-
6361
# ----------- Wind farm
6462
# The wts dictionary holds information of each wind turbine. The allowed entries
6563
# are: x, y, z, D, zhub, cmax, fmax, Cmeander, and phi_deg. The phi_deg is the
@@ -83,21 +81,18 @@ def main(test=False):
8381
# -----------------------------------------------------------------------------
8482
# ------------------- Inflow conditions and input files -----------------------
8583
# -----------------------------------------------------------------------------
86-
8784
# ----------- Additional variables
8885
tmax = 120 # Total simulation time
89-
nSeeds = 6 # Number of seeds
9086
zbot = 1 # Bottom of your domain
9187
mod_wake = 2 # Wake model. 1: Polar, 2: Curled, 3: Cartesian
92-
9388
# ----------- Inflow parameters
9489
inflowType = 'TS'
95-
96-
# ----------- Desired sweeps
97-
vhub = [8]
98-
shear = [0.1]
99-
TIvalue = [10]
100-
inflow_deg = [0]
90+
# ----------- Desired sweeps, fill array with multiple values if necessary
91+
nSeeds = 6 # Number of seeds
92+
vhub = [8] # Hub velocity [m/s]
93+
shear = [0.1] # Power law exponent [-]
94+
TIvalue = [10] # Turbulence intensity [%]
95+
inflow_deg = [0] # Wind direction [deg]
10196

10297
# ----------- Template files
10398

@@ -109,12 +104,12 @@ def main(test=False):
109104

110105
# ----------- Low- and high-res boxes parameters
111106
# High-res boxes settings
112-
dt_high = None # sampling frequency of high-res files
113-
ds_high = None # dx, dy, dz of high-res files
107+
dt_high = None # sampling time of high-res files [s]
108+
ds_high = None # dx, dy, dz of high-res files [m]
114109
extent_high = None # extent in y and x for each turbine, in D
115110
# Low-res boxes settings
116-
dt_low = None # sampling frequency of low-res files
117-
ds_low = None # dx, dy, dz of low-res files
111+
dt_low = None # sampling time of low-res files [s]
112+
ds_low = None # dx, dy, dz of low-res files [m]
118113
extent_low = None # extent in [xmin,xmax,ymin,ymax,zmax], in D
119114

120115

openfast_toolbox/fastfarm/examples/Ex2a_FASTFarm_TurbSim_driven.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ def main(test=False):
117117
TIvalue = [10] # Turbulence intensity [%]
118118
inflow_deg = [0] # Wind direction [deg]
119119

120-
121120
# ----------- Template files
122121
# --- Option 1
123122
templateFSTF = os.path.join(scriptDir, '../../../data/IEA15MW/FF.fstf')
@@ -152,7 +151,7 @@ def main(test=False):
152151
# SLURM scripts
153152
slurm_TS_high = os.path.join(scriptDir, './SampleFiles/runAllHighBox.sh')
154153
slurm_TS_low = os.path.join(scriptDir, './SampleFiles/runAllLowBox.sh')
155-
# slurm_FF_single = './SampleFiles/runFASTFarm_cond0_case0_seed0.sh'
154+
slurm_FF_single = './SampleFiles/runFASTFarm_cond0_case0_seed0.sh'
156155

157156

158157
# -----------------------------------------------------------------------------
@@ -196,8 +195,8 @@ def main(test=False):
196195
refTurb_rot=refTurb_rot, verbose=0)
197196

198197
# ----------- Perform auxiliary steps in preparing the case
199-
ffcase.setTemplateFilename(templateFiles=templateFiles, templateFSTF=templateFSTF)
200-
#ffcase.setTemplateFilename(templatePath, templateFiles)
198+
ffcase.setTemplateFilename(templateFiles=templateFiles, templateFSTF=templateFSTF) # Option 1
199+
#ffcase.setTemplateFilename(templatePath, templateFiles) # Option 2
201200
ffcase.getDomainParameters()
202201
ffcase.copyTurbineFilesForEachCase()
203202
ffcase.plot() # add showTurbNumber=True to help with potential debugging
@@ -243,7 +242,7 @@ def main(test=False):
243242

244243
# ----------- Prepare script for submission
245244
ffcase.FF_batch_prepare() # Write batch files with all commands to be run
246-
#ffcase.FF_slurm_prepare(slurm_FF_single)
245+
#ffcase.FF_slurm_prepare(slurm_FF_single) # Alternative, prepare a slurm batch file
247246

248247
# We can do simple modifications:
249248
modifyProperty(ffcase.FFFiles[0], 'NX_Low', 100) # Making the domain longer for visualization purposes
@@ -253,7 +252,7 @@ def main(test=False):
253252

254253
# ----------- Submit the FAST.Farm script (can be done from the command line)
255254
ffcase.FF_batch_run(showOutputs=True, showCommand=True, nBuffer=10, shell_cmd='bash')
256-
#ffcase.FF_slurm_submit(p='debug', t='1:00:00')
255+
#ffcase.FF_slurm_submit(p='debug', t='1:00:00') # Alternative, submit a slurm batch file
257256
return ffcase
258257

259258

openfast_toolbox/fastfarm/examples/Ex2b_FASTFarm_LES_driven.py

Lines changed: 86 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@
77
https://openfast.readthedocs.io/en/dev/source/user/fast.farm/ModelGuidance.html
88
99
"""
10-
10+
import os
1111
from openfast_toolbox.fastfarm.FASTFarmCaseCreation import FFCaseCreation
1212
from openfast_toolbox.fastfarm.AMRWindSimulation import AMRWindSimulation
1313

14-
def main():
14+
15+
scriptDir = os.path.dirname(__file__)
16+
17+
def main(test=False):
1518

1619
# -----------------------------------------------------------------------------
1720
# USER INPUT: Modify these
@@ -22,26 +25,25 @@ def main():
2225
# -----------------------------------------------------------------------------
2326

2427
# ----------- Case absolute path
25-
path = '/complete/path/of/your/case'
28+
path = os.path.join(scriptDir, '_ex3') # folder (preferably new) where all the simulation files will be written
2629

2730
# ----------- Execution parameters
2831
# If you are sure the correct binary is first on your $PATH and associated
2932
# libraries on $LD_LIBRARY_PATH, you can set the variable below to None or
3033
# remove it from the `FFCaseCreation` call
31-
ffbin = '/full/path/to/your/binary/.../bin/FAST.Farm'
34+
ffbin = os.path.join(scriptDir, './SampleFiles/dummy_fastfarm.exe.txt') # relative or absolute path of FAST.Farm executable
3235

36+
libdiscon = os.path.join(scriptDir, './SampleFiles/dummy_discon.dll.dummy') # relative or absolute path to discon shared library
3337

3438
# -----------------------------------------------------------------------------
3539
# --------------------------- Farm parameters ---------------------------------
3640
# -----------------------------------------------------------------------------
37-
3841
# ----------- General turbine parameters
39-
cmax = 5 # Maximum blade chord (m)
40-
fmax = 10/6 # Maximum excitation frequency (Hz)
42+
cmax = 5 # Maximum blade chord (m), affects dr
43+
fmax = 10/6 # Maximum excitation frequency (Hz), affects dt_high
4144
Cmeander = 1.9 # Meandering constant (-)
4245
D = 240 # Rotor diameter (m)
4346
zhub = 150 # Hub height (m)
44-
4547
# ----------- Wind farm
4648
# The wts dictionary holds information of each wind turbine. The allowed entries
4749
# are: x, y, z, D, zhub, cmax, fmax, Cmeander, and phi_deg. The phi_deg is the
@@ -65,12 +67,10 @@ def main():
6567
# -----------------------------------------------------------------------------
6668
# ------------------- Inflow conditions and input files -----------------------
6769
# -----------------------------------------------------------------------------
68-
6970
# ----------- Additional variables
7071
tmax = 60 # Total simulation time
7172
zbot = 1 # Bottom of your domain
7273
mod_wake = 2 # Wake model. 1: Polar, 2: Curled, 3: Cartesian
73-
7474
# ----------- Inflow parameters
7575
inflowType = 'LES'
7676
inflowPath = '/full/path/to/LES/case/.../LESboxes'
@@ -81,36 +81,40 @@ def main():
8181
# executions with multiple different LES solutions, you can give inflowPath
8282
# as a n-sized array (related to the different LES), and give the variables
8383
# below as n-sized arrays as well.
84-
vhub = [8]
85-
shear = [1]
86-
TIvalue = [1]
87-
inflow_deg = [0]
84+
vhub = [8] # Hub velocity [m/s]
85+
shear = [0.1] # Power law exponent [-]
86+
TIvalue = [10] # Turbulence intensity [%]
87+
inflow_deg = [0] # Wind direction [deg]
8888

8989
# ----------- Template files
90-
templatePath = '/full/path/where/template/files/are'
91-
# Files should be in templatePath. Put None on any input that is not applicable.
92-
templateFiles = {
93-
"EDfilename" : 'ElastoDyn.T',
94-
'SEDfilename' : None, # 'SimplifiedElastoDyn.T',
95-
'HDfilename' : None, # 'HydroDyn.dat', # ending with .T for per-turbine HD, .dat for holisitc
96-
'MDfilename' : None, # 'MoorDyn.T', # ending with .T for per-turbine MD, .dat for holistic
97-
'SSfilename' : None, # 'SeaState.dat',
98-
'SrvDfilename' : 'ServoDyn.T',
99-
'ADfilename' : 'AeroDyn.dat',
100-
'ADskfilename' : None,
101-
'SubDfilename' : 'SubDyn.dat',
102-
'IWfilename' : 'InflowWind.dat',
103-
'BDfilename' : None,
104-
'EDbladefilename' : 'ElastoDyn_Blade.dat',
105-
'EDtowerfilename' : 'ElastoDyn_Tower.dat',
106-
'ADbladefilename' : 'AeroDyn_Blade.dat',
107-
'turbfilename' : 'Model.T',
108-
'libdisconfilepath' : '/full/path/to/controller/libdiscon.so',
109-
'controllerInputfilename' : 'DISCON.IN',
110-
'coeffTablefilename' : None,
111-
'hydroDatapath' : None, # '/full/path/to/hydroData',
112-
'FFfilename' : 'Model_FFarm.fstf',
113-
}
90+
# --- Option 1
91+
templateFSTF = os.path.join(scriptDir, '../../../data/IEA15MW/FF.fstf')
92+
templateFiles = {'libdisconfilepath' : libdiscon}
93+
# --- Option 2
94+
#templatePath = '/full/path/where/template/files/are'
95+
## Files should be in templatePath. Put None on any input that is not applicable.
96+
#templateFiles = {
97+
# "EDfilename" : 'ElastoDyn.T',
98+
# 'SEDfilename' : None, # 'SimplifiedElastoDyn.T',
99+
# 'HDfilename' : None, # 'HydroDyn.dat', # ending with .T for per-turbine HD, .dat for holisitc
100+
# 'MDfilename' : None, # 'MoorDyn.T', # ending with .T for per-turbine MD, .dat for holistic
101+
# 'SSfilename' : None, # 'SeaState.dat',
102+
# 'SrvDfilename' : 'ServoDyn.T',
103+
# 'ADfilename' : 'AeroDyn.dat',
104+
# 'ADskfilename' : None,
105+
# 'SubDfilename' : 'SubDyn.dat',
106+
# 'IWfilename' : 'InflowWind.dat',
107+
# 'BDfilename' : None,
108+
# 'EDbladefilename' : 'ElastoDyn_Blade.dat',
109+
# 'EDtowerfilename' : 'ElastoDyn_Tower.dat',
110+
# 'ADbladefilename' : 'AeroDyn_Blade.dat',
111+
# 'turbfilename' : 'Model.T',
112+
# 'libdisconfilepath' : '/full/path/to/controller/libdiscon.so',
113+
# 'controllerInputfilename' : 'DISCON.IN',
114+
# 'coeffTablefilename' : None,
115+
# 'hydroDatapath' : None, # '/full/path/to/hydroData',
116+
# 'FFfilename' : 'Model_FFarm.fstf',
117+
#}
114118
# SLURM scripts
115119
slurm_FF_single = './SampleFiles/runFASTFarm_cond0_case0_seed0.sh'
116120

@@ -152,7 +156,7 @@ def main():
152156
level_lr=level_lr, level_hr=level_hr, verbose=0)
153157

154158
# -----------Save AMR-Wind sampling input
155-
amr.write_sampling_params(os.path.join(path,'FF_boxes.i'), overwrite=True)
159+
amr.write_sampling_params(os.path.join(path,'FF_boxes.i'), overwrite=True, terrain=False)
156160

157161

158162
# -----------------------------------------------------------------------------
@@ -166,12 +170,12 @@ def main():
166170

167171
# ----------- Low- and high-res boxes parameters
168172
# High-res boxes settings
169-
dt_high = amr.dt_high_les # sampling frequency of high-res files
170-
ds_high = amr.ds_high_les # dx, dy, dz of high-res files
171-
extent_high = amr.extent_high # extent in y and x for each turbine, in D.
173+
dt_high = amr.dt_high_les # sampling time of high-res files [s]
174+
ds_high = amr.ds_high_les # dx, dy, dz of high-res files [m]
175+
extent_high = amr.extent_high # extent in y and x for each turbine, in D
172176
# Low-res boxes settings
173-
dt_low = amr.dt_low_les # sampling frequency of low-res files
174-
ds_low = amr.ds_low_les # dx, dy, dz of low-res files
177+
dt_low = amr.dt_low_les # sampling time of low-res files [s]
178+
ds_low = amr.ds_low_les # dx, dy, dz of low-res files [m]
175179
extent_low = amr.extent_low # extent in [xmin,xmax,ymin,ymax,zmax], in D
176180

177181

@@ -193,27 +197,60 @@ def main():
193197
refTurb_rot=refTurb_rot, verbose=0)
194198

195199
# ----------- Perform auxiliary steps in preparing the case
196-
ffcase.setTemplateFilename(templatePath, templateFiles)
200+
ffcase.setTemplateFilename(templateFiles=templateFiles, templateFSTF=templateFSTF) # Option 1
201+
#ffcase.setTemplateFilename(templatePath, templateFiles) # Option 2
197202
ffcase.getDomainParameters()
198203
ffcase.copyTurbineFilesForEachCase()
199204

200205

201206
# -----------------------------------------------------------------------------
202207
# ------------------ Finish FAST.Farm setup and execution ---------------------
203208
# -----------------------------------------------------------------------------
209+
if test:
210+
return amr, ffcase
204211
# ----------- FAST.Farm setup
205-
ffcase.FF_setup()
212+
ffcase.FF_setup() # Write FAST.Farm input files
206213
# Update wake model constants (adjust as needed for your turbine model)
207214
ffcase.set_wake_model_params(k_VortexDecay=0, k_vCurl=2.8)
208215

209216
# ----------- Prepare script for submission
210-
ffcase.FF_slurm_prepare(slurm_FF_single)
217+
ffcase.FF_batch_prepare() # Write batch files with all commands to be run
218+
#ffcase.FF_slurm_prepare(slurm_FF_single) # Alternative, prepare a slurm batch file
211219

212220
# ----------- Submit the FAST.Farm script (can be done from the command line)
213-
ffcase.FF_slurm_submit(p='debug', t='1:00:00')
214-
221+
ffcase.FF_batch_run(showOutputs=True, showCommand=True, nBuffer=10, shell_cmd='bash')
222+
#ffcase.FF_slurm_submit(p='debug', t='1:00:00') # Alternative, submit a slurm batch file
223+
return amr, ffcase
215224

216225

217226
if __name__ == '__main__':
227+
amr, ffcase = main(test=True)
218228
# This example cannot be fully run.
229+
#print(amr)
230+
#print(ffcase)
219231
pass
232+
if __name__ == '__test__':
233+
amr, ffcase = main(test=True)
234+
# This example cannot be fully run.
235+
import numpy as np
236+
import shutil
237+
np.testing.assert_equal(amr.ds_low_les, 20.0)
238+
np.testing.assert_equal(amr.dt_low_les, 0.9)
239+
np.testing.assert_array_equal(amr.extent_low, [1.5, 2.5, 1.5, 1.5, 2] )
240+
np.testing.assert_equal(amr.ds_high_les, 5.0)
241+
np.testing.assert_equal(amr.dt_high_les, 0.3)
242+
np.testing.assert_equal(ffcase.ds_low, 20.0)
243+
np.testing.assert_equal(ffcase.dt_low, 0.9)
244+
np.testing.assert_equal(ffcase.ds_high, 5.0)
245+
np.testing.assert_equal(ffcase.dt_high, 0.3)
246+
np.testing.assert_(os.path.exists(ffcase.path), f"path does not exist {ffcase.path}")
247+
for cond, _ in enumerate(ffcase.condDirList):
248+
np.testing.assert_(os.path.exists(ffcase.getCondPath(cond)), f"cond path {cond} does not exist ")
249+
for case in range(ffcase.nCases):
250+
np.testing.assert_(os.path.exists(ffcase.getCasePath(cond, case)), f"case path {cond} {case} does not exist ")
251+
if os.path.exists(ffcase.path):
252+
try:
253+
shutil.rmtree(ffcase.path)
254+
except OSError as e:
255+
print('Fail to remove FAST.Farm ex2 folder' )
256+
pass

openfast_toolbox/fastfarm/tests/test_run_Examples.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ def test_run_examples(self):
1818
exclude_list=[]
1919
# Add tests to class
2020
MyDir=os.path.dirname(__file__)
21-
files = glob.glob(os.path.join(MyDir,'../examples/[A-Za-z][_-a-zA-Z0-9]*.py'))
21+
#files = glob.glob(os.path.join(MyDir,'../examples/[A-Za-z][_-a-zA-Z0-9]*.py'))
22+
files = glob.glob(os.path.join(MyDir,'../examples/[a-zA-Z]*.py'))
2223
import matplotlib.pyplot as plt
2324
print('\n--------------------------------------------------------------')
2425
for f in files:

0 commit comments

Comments
 (0)