Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RAFT DOE to create Surrogate Model (updated) #303

Draft
wants to merge 32 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5172594
Level 1 DOE in MPI parallel
yonghoonlee May 17, 2024
d4d2ac9
working with WISDEM3.13
yonghoonlee May 31, 2024
bda599f
latin hypercube example working (previously broken)
yonghoonlee Jun 4, 2024
8e52fc7
DOE results saving to smt file
yonghoonlee Jun 6, 2024
ec60001
parallel reading of sql data
yonghoonlee Jun 17, 2024
2a5ebde
Processing and storing data of DVs and other variables in parallel
yonghoonlee Jun 18, 2024
2bff26c
Added DVs to more comprehensively cover the DOE capability
yonghoonlee Jun 18, 2024
e67ad82
Training sm after doe run
yonghoonlee Jul 3, 2024
2f3b552
Customized KRG implemented for value and variance prediction
yonghoonlee Jul 3, 2024
b555b12
gathering after parallel sm training
yonghoonlee Jul 3, 2024
4c24668
Surrogate model writing implemented
yonghoonlee Jul 8, 2024
4602fbb
Saving DOE data in pkl and csv with recorder filename
yonghoonlee Jul 10, 2024
99c4a6d
Serial run list bug fixed
yonghoonlee Jul 12, 2024
60a62ec
Reduced DVs and samples to make SM stable
yonghoonlee Jul 19, 2024
71739f0
Readme reflects DOE to create SM
yonghoonlee Jul 19, 2024
504f186
Explanation revised for SM training
yonghoonlee Jul 19, 2024
57ea9f7
train_surrogate_model flag implemented to not interrupting existing c…
yonghoonlee Jul 20, 2024
7704b63
slurm script removed
yonghoonlee Jul 20, 2024
98141ad
Surrogate model validation implemented
yonghoonlee Jul 23, 2024
870bfcb
predict constant response without surrogate model
yonghoonlee Jul 23, 2024
6ddea75
Treat constant if correlation is too low
Jul 23, 2024
98bc05d
output var name fixed
Jul 23, 2024
c6ee585
Skipping logics for DOE and SMT are now individually working / Remove…
yonghoonlee Aug 7, 2024
b436d23
Added additional comment
yonghoonlee Aug 7, 2024
7aeda14
Comments added for classes and methods related to DOE-based surrogate…
yonghoonlee Aug 7, 2024
5dbb6d3
Comments added to improve logic readability
yonghoonlee Aug 7, 2024
6c0c3ca
Bug fix: sql filename suffix to be sql instead of sql_0 if MPI with 1…
yonghoonlee Aug 7, 2024
1564536
surrogate model training logic modified
yonghoonlee Nov 21, 2024
bf6dac3
Using MPI functionality from OpenMDAO instead of WISDEM's
yonghoonlee Nov 22, 2024
5b2c0b7
modeling option filename simplified
yonghoonlee Nov 26, 2024
b27a8b0
Sparse Gaussian Process inducing points specified
yonghoonlee Nov 26, 2024
db1ba50
Base force and torque excluded in DOE
yonghoonlee Nov 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ nosetests.xml
*.log
*.sql
*.sqlite
*.err
*.smt

# OS generated files #
######################
Expand Down
21 changes: 21 additions & 0 deletions examples/15_RAFT_Studies/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,25 @@ To optimize the UMaine semi using raft, run
Two options are provided in this example: `../06_IEA-15-240-RWT/IEA-15-240-RWT_VolturnUS-S.yaml` (original) and `raft_opt_out.yaml`, the optimized output.


# RAFT Surrogate Model Training with Design of Experiment
To create the surrogate model with RAFT simulations, run
```
python weis_driver_level1_doe.py
```
If parallel execution is possible (e.g., HPC) use slurm script to run with MPI across large number of cpus/nodes
```
sbatch weis_driver_level1_doe.sh
```
or MPI directly for cpus in a local computer
```
mpirun -np 4 python weis_driver_level1_doe.py
```

In `analysis_options_level1_doe.yaml`, the design variables (control and plant), driver (optimization:flag: False, design_of_experiments:flag: True), and recorder (flag: True, includes: ['*']) can be set up. Variables marked as design_variables (flag: True) are used as inputs, while all other variables are used as outputs of the surrogate model. Not all parameters are supported at this moment. Seven control parameters, diameters of floating platform members, joint locations, rotor diameter are currently implemented.

Once design of experiment is completed, a surrogate model for each output variable will be trained (in parallel if MPI is used), and recorder file_name.smt (log_opt.smt in the tutorial case) will be created.

At this moment, surrogate model training is not stable with large number of samples.

Further design coupling studies and/or surrogate-based optimization studies can be done in separate script files to be developed.

136 changes: 136 additions & 0 deletions examples/15_RAFT_Studies/analysis_options_level1_doe.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
general:
folder_output: outputs/level1_doe
fname_output: refturb_output

design_variables:
control:
ps_percent: #Peak shaving #defalt: 0.85
flag: False
lower_bound: 0.75
upper_bound: 1.0
servo:
pitch_control:
omega: #rad/s #default: 0.2
flag: True
min: 0.1
max: 0.7
zeta: #rad/s #default: 1.0
flag: True
min: 0.7
max: 1.5
Kp_float: #s #default: -10.0
flag: True
min: -20.0 #-100.0
max: 0.0
ptfm_freq: #rad/s default: 0.2
flag: True
min: 0.1 #0.00001
max: 1.5
torque_control:
omega: #rad/s #default: 0.12
flag: False
min: 0.1
max: 0.7
zeta: #rad/s #default: 0.85
flag: False
min: 0.7
max: 1.5
floating:
members:
flag: False
groups:
- names: [main_column] # Platform sizing: diameter (Center Column)
diameter:
lower_bound: 6.0 #default: 10
upper_bound: 14.0
constant: True
- names: [column1, column2, column3] # Platform sizing: diameter (Side Columns)
diameter:
lower_bound: 10.5 #11.0 #10.7 #8.5 # default: 12.5
upper_bound: 14.5 #14.5 #16.5
constant: True
- names: [Y_pontoon_upper1, Y_pontoon_upper2, Y_pontoon_upper3] # Platform sizing: Pantoon upper diameter
diameter:
lower_bound: 0.71 # default: 0.91
upper_bound: 1.11
constant: True
- names: [Y_pontoon_lower1, Y_pontoon_lower2, Y_pontoon_lower3] # Platform sizing: Pantoon lower diameter
diameter:
lower_bound: 6.6148 #7.6148 # default: 9.6148
upper_bound: 13.6148 #11.6148
constant: True
joints:
flag: False
z_coordinate:
- names: [main_keel, col1_keel, col2_keel, col3_keel] #Platform sizing: form -20 (keel) to 15 (freeboard)
lower_bound: -24.0 #default -20
upper_bound: -16.0
- names: [main_freeboard, col1_freeboard, col2_freeboard, col3_freeboard] #Platform sizing: form -20 (keel) to 15 (freeboard)
lower_bound: 7.0 #default 15
upper_bound: 21.0
r_coordinate:
- names: [col1_keel, col1_freeboard, col2_keel, col2_freeboard, col3_keel, col3_freeboard] #Platform sizing: Spacing
lower_bound: 41.57 #51.57 #48.57 #63.57 #42.57 # default: 51.57
upper_bound: 61.57 #72.57 #63.57 #60.0
rotor_diameter:
flag: True
minimum: 235.0 #242.23775645
maximum: 250.0
tower: # does not work for design coupling analysis
outer_diameter:
flag: False
lower_bound: 6.0 # 6.5[m]
upper_bound: 7.0
section_height:
flag: False
lower_bound: 13.0 # 5.0[m] I think in default it has 10 sections: 10 *15=150==hub height
upper_bound: 18.0

constraints:
control:
Max_PtfmPitch:
flag: True
max: 6.757845 #6.74303 #deg
Std_PtfmPitch:
flag: True
max: 2.0 #deg
nacelle_acceleration:
flag: True
max: 3.2667 # m/s^2
tower:
height_constraint:
flag: False
lower_bound: 0.1
upper_bound: 5.0
frequency_1:
flag: True
lower_bound: 0.35
upper_bound: 0.51
slope:
flag: False

merit_figure: platform_mass # Merit figure of the optimization problem. The options are 'AEP' - 'LCOE' - 'Cp' - 'blade_mass' - 'blade_tip_deflection'

driver:
optimization:
flag: False # Flag to enable optimization
solver: COBYLA #LN_COBYLA # Optimization solver. Other options are 'SLSQP' - 'CONMIN'
tol: 1.e-3 # Optimality tolerance
max_iter: 300 # Maximum number of iterations (SLSQP)
design_of_experiments:
flag: True # Flag to enable design of experiments
run_parallel: True # Flag to run using parallel processing
seed: 2
generator: LatinHypercube #Uniform #LatinHypercube #FullFact # Type of input generator. (Uniform)
num_samples: 50 # number of samples for (Uniform only)
levels: 1
skip_doe_if_results_exist: True
skip_smt_if_results_exist: True
train_surrogate_model: True

recorder:
flag: True # Flag to activate OpenMDAO recorder
file_name: log_opt.sql # Name of OpenMDAO recorder
includes: ['*'] #['*raft*','*floating*','*platform*']


119 changes: 119 additions & 0 deletions examples/15_RAFT_Studies/modeling_options_level1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
General:
verbosity: False # When set to True, the code prints to screen many infos
openfast_configuration:
use_exe: True
allow_fails: True
fail_value: 9999

WISDEM:
RotorSE:
flag: True
spar_cap_ss: Spar_Cap_SS
spar_cap_ps: Spar_Cap_PS
te_ss: TE_reinforcement_SS
te_ps: TE_reinforcement_PS
TowerSE:
flag: True
DriveSE:
flag: True
FloatingSE:
flag: True
# BOS:
# flag: True

Level3: # Options for WEIS fidelity level 3 = nonlinear time domain
flag: False
simulation:
DT: 0.01
CompElast: 1
CompInflow: 1
CompAero: 2
CompServo: 1
CompHydro: 1
CompSub: 0
CompMooring: 3
CompIce: 0
OutFileFmt: 3
linearization:
Linearize: False
ElastoDyn:
FlapDOF1: True
FlapDOF2: True
EdgeDOF: True
TeetDOF: False
DrTrDOF: False
GenDOF: True
YawDOF: False
TwFADOF1 : True
TwFADOF2 : True
TwSSDOF1 : True
TwSSDOF2 : True
PtfmSgDOF: True
PtfmSwDOF: True
PtfmHvDOF: True
PtfmRDOF : True
PtfmPDOF : True
PtfmYDOF : True
HydroDyn:
WvLowCOff: 0.15708
WvHiCOff: 3.2
WaveSeed1: 123456789
AddBQuad1: [9.23e5, 0.0, 0.0, 0.0, -8.92e6, 0.0]
AddBQuad2: [0.0, 9.23e5, 0.0, 8.92e6, 0.0, 0.0]
AddBQuad3: [0.0, 0.0, 2.3e6, 0.0, 0.0, 0.0]
AddBQuad4: [0.0, 8.92e6, 0.0, 1.68e10, 0.0, 0.0]
AddBQuad5: [-8.92e6, 0.0, 0.0, 0.0, 1.68e10, 0.0]
AddBQuad6: [0.0, 0.0, 0.0, 0.0, 0.0, 4.8e10]
PotMod: 1
# WaveMod: 0

Level1:
flag: True
potential_model_override: 0
trim_ballast: 2
heave_tol: 1
save_designs: True

ROSCO:
flag: True
SD_Mode: 0
PS_Mode: 1
ps_percent: 0.85
F_LPFType: 2
F_NotchType: 2
Fl_Mode: 2
tuning_yaml: ../01_aeroelasticse/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-UMaineSemi/IEA15MW-UMaineSemi.yaml
zeta_pc: [1]
omega_pc: [0.2]
U_pc: [12]
zeta_vs: 0.85 # Torque controller desired damping ratio [-]
omega_vs: 0.12
twr_freq: 3.2
ptfm_freq: 0.2
Kp_float: -10

DLC_driver:
metocean_conditions:
wind_speed: [4., 6., 8., 10., 12., 14., 16., 18., 20., 22., 24.]
wave_height_NSS: [0.83, 0.88, 0.94, 1.03, 1.16, 1.34, 1.57, 1.86, 2.22, 2.62, 3.07]
wave_period_NSS: [6.9, 6.96, 7.02, 7.12, 7.25, 7.43, 7.66, 7.94, 8.27, 8.63, 9.01]
wave_height_SSS: [6.3, 8, 8, 8.1, 8.5, 8.5, 9.8, 9.8, 9.8, 9.8, 9.9]
wave_period_SSS: [11.5, 12.7, 12.7, 12.8, 13.1, 13.1, 14.1, 14.1, 14.1, 14.1, 14.1]
wave_height1: 6.98
wave_period1: 11.7
wave_height50: 10.68
wave_period50: 14.2
DLCs:
- DLC: "1.1"
n_seeds: 1
# - DLC: "1.3"
# n_seeds: 6
- DLC: "1.4"
- DLC: "1.5"
- DLC: "1.6"
n_seeds: 1
- DLC: "6.1"
n_seeds: 1
# - DLC: "6.3"
# n_seeds: 6

25 changes: 25 additions & 0 deletions examples/15_RAFT_Studies/weis_driver_level1_doe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os
import time
import sys

from weis.glue_code.runWEIS import run_weis
from openmdao.utils.mpi import MPI

run_dir = os.path.dirname( os.path.realpath(__file__) ) + os.sep
fname_wt_input = os.path.join(run_dir,"..","06_IEA-15-240-RWT", "IEA-15-240-RWT_VolturnUS-S.yaml")
fname_modeling_options = run_dir + "modeling_options_level1.yaml"
fname_analysis_options = run_dir + "analysis_options_level1_doe.yaml"
overridden_values = {}

tt = time.time()
wt_opt, modeling_options, opt_options = run_weis(fname_wt_input, fname_modeling_options, fname_analysis_options, overridden_values)

if MPI:
rank = MPI.COMM_WORLD.Get_rank()
else:
rank = 0
if rank == 0:
print('Run time: %f'%(time.time()-tt))
sys.stdout.flush()

print('rank = {:}, exiting'.format(rank))
45 changes: 43 additions & 2 deletions weis/glue_code/runWEIS.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from weis.control.tmd import assign_TMD_values
from weis.aeroelasticse.FileTools import save_yaml
from wisdem.inputs.validation import simple_types
from weis.surrogate.WTsurrogate import WindTurbineDOE2SM

fd_methods = ['SLSQP','SNOPT', 'LD_MMA']
evolutionary_methods = ['DE', 'NSGA2']
Expand Down Expand Up @@ -114,6 +115,7 @@ def run_weis(fname_wt_input, fname_modeling_options, fname_opt_options, geometry
else:
color_i = 0
rank = 0
max_cores = 1

# make the folder_output relative to the input, if it's a relative path
analysis_input_dir = os.path.dirname(opt_options['fname_input_analysis'])
Expand Down Expand Up @@ -211,13 +213,42 @@ def run_weis(fname_wt_input, fname_modeling_options, fname_opt_options, geometry
checks = wt_opt.check_partials(compact_print=True)

sys.stdout.flush()

yonghoonlee marked this conversation as resolved.
Show resolved Hide resolved
# DOE and SMT skip logics
SKIP_DRIVER = False
SKIP_SMT = False
sm_filename = os.path.join(folder_output, os.path.splitext(opt_options['recorder']['file_name'])[0] + '.smt')
sql_filename = os.path.join(folder_output, opt_options['recorder']['file_name'])
if MPI and max_cores>1:
sql_filename += '_{:}'.format(rank)
if opt_options['opt_flag'] and opt_options['driver']['design_of_experiments']['flag']: # if DOE enabled
# Skip DOE Driver if SQL file exists
if opt_options['driver']['design_of_experiments']['skip_doe_if_results_exist']: # if DOE skip flag set
if MPI:
doe_file_exist = MPI.COMM_WORLD.gather(os.path.isfile(sql_filename), root=0)
doe_file_exist = MPI.COMM_WORLD.bcast(doe_file_exist, root=0)
else:
doe_file_exist = [os.path.isfile(sql_filename)]
# If sql files exist for all MPI ranks, and no additional sql file exists outside of MPI size, set skip flag
if all(doe_file_exist) and not os.path.isfile(os.path.join(folder_output, opt_options['recorder']['file_name']) + '_{:}'.format(max_cores)):
SKIP_DRIVER = True
if (not MPI) or (MPI and rank == 0):
print('File {:} exists. Skipping the design of experiments.'.format(sql_filename))
# Skip SM Training if SMT file exists
if opt_options['driver']['design_of_experiments']['skip_smt_if_results_exist']: # if SMT skip flag set
if os.path.isfile(sm_filename):
SKIP_SMT = True
if (not MPI) or (MPI and rank == 0):
print('File {:} exists. Skipping the design of experiments.'.format(sm_filename))

# Run openmdao problem
if opt_options['opt_flag']:
wt_opt.run_driver()
if not SKIP_DRIVER:
wt_opt.run_driver()
else:
wt_opt.run_model()

if (not MPI) or (MPI and rank == 0):
if ((not MPI) or (MPI and rank == 0)) and (not SKIP_DRIVER):
# Save data coming from openmdao to an output yaml file
froot_out = os.path.join(folder_output, opt_options['general']['fname_output'])
# Remove the fst_vt key from the dictionary and write out the modeling options
Expand Down Expand Up @@ -255,6 +286,16 @@ def run_weis(fname_wt_input, fname_modeling_options, fname_opt_options, geometry
if MPI and color_i < 1000000:
MPI.COMM_WORLD.Barrier()

# If design_of_experiment, recorder flag, train_surrogate_model are all True,
yonghoonlee marked this conversation as resolved.
Show resolved Hide resolved
# collect sql files and create smt object
if opt_options['opt_flag'] and (not SKIP_SMT):
if opt_options['driver']['design_of_experiments']['flag'] and opt_options['recorder']['flag']:
if opt_options['driver']['design_of_experiments']['train_surrogate_model']:
WTSM = WindTurbineDOE2SM()
WTSM.read_doe(sql_filename, modeling_options, opt_options) # Parallel reading if MPI
WTSM.train_sm() # Parallel training if MPI
WTSM.write_sm(sm_filename) # Saving will be done in rank=0

if rank == 0:
return wt_opt, modeling_options, opt_options
else:
Expand Down
Loading
Loading