• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

WISDEM / WEIS / 7302598135

22 Dec 2023 05:58PM UTC coverage: 76.293%. First build
7302598135

Pull #251

github

web-flow
Merge d77db5760 into 36b276939
Pull Request #251: Phase 2 Starting Point

116 of 149 new or added lines in 10 files covered. (77.85%)

12210 of 16004 relevant lines covered (76.29%)

0.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

47.45
/weis/glue_code/gc_PoseOptimization.py
1
from wisdem.glue_code.gc_PoseOptimization import PoseOptimization
1✔
2
import numpy as np
1✔
3

4
class PoseOptimizationWEIS(PoseOptimization):
1✔
5

6
    def __init__(self, wt_init, modeling_options, analysis_options):
1✔
7
        
8
        self.level_flags = np.array([modeling_options[level]['flag'] for level in ['Level1','Level2','Level3']])
1✔
9
        # if sum(self.level_flags) > 1:
10
            # raise Exception('Only one level in WEIS can be enabled at the same time')
11

12
        super(PoseOptimizationWEIS, self).__init__(wt_init, modeling_options, analysis_options)
1✔
13

14
        # Set solve component for some optimization constraints, and merit figures (RAFT or openfast)
15
        if modeling_options['Level3']['flag']:
1✔
16
            self.floating_solve_component = 'aeroelastic'
1✔
17
        elif modeling_options['Level1']['flag']:
1✔
18
            self.floating_solve_component = 'raft'
1✔
NEW
19
        else:
×
20
            self.floating_solve_component = 'floatingse'
1✔
21

22
        # aeroelastic won't compute floating period, execpt in special sims
23
        if modeling_options['Level1']['flag']:
1✔
24
            self.floating_period_solve_component = 'raft'
1✔
NEW
25
        else:
×
26
            self.floating_period_solve_component = 'floatingse'
1✔
27
        
28
        
29
    def get_number_design_variables(self):
1✔
30
        # Determine the number of design variables
31
        n_DV = super(PoseOptimizationWEIS, self).get_number_design_variables()
×
32

33
        n_add = 0
×
34
        if self.opt['design_variables']['control']['servo']['pitch_control']['omega']['flag']:
×
35
            n_add += 1
×
36
        if self.opt['design_variables']['control']['servo']['pitch_control']['zeta']['flag']:
×
37
            n_add += 1
×
38
        if self.opt['design_variables']['control']['servo']['pitch_control']['Kp_float']['flag']:
×
39
            n_add += 1
×
40
        if self.opt['design_variables']['control']['servo']['pitch_control']['ptfm_freq']['flag']:
×
41
            n_add += 1
×
42
        if self.opt['design_variables']['control']['servo']['torque_control']['omega']['flag']:
×
43
            n_add += 1
×
44
        if self.opt['design_variables']['control']['servo']['torque_control']['zeta']['flag']:
×
45
            n_add += 1
×
46
        if self.opt['design_variables']['control']['servo']['flap_control']['flp_kp_norm']['flag']:
×
47
            n_add += 1
×
48
        if self.opt['design_variables']['control']['servo']['flap_control']['flp_tau']['flag']:
×
49
            n_add += 1
×
50
        if self.opt['design_variables']['control']['flaps']['te_flap_end']['flag']:
×
51
            n_add += self.modeling['WISDEM']['RotorSE']['n_te_flaps']
×
52
        if self.opt['design_variables']['control']['flaps']['te_flap_ext']['flag']:
×
53
            n_add += self.modeling['WISDEM']['RotorSE']['n_te_flaps']
×
54
        if self.opt['design_variables']['control']['ps_percent']['flag']:
×
55
            n_add += 1
×
56
        
57
        if self.opt['driver']['optimization']['form'] == 'central':
×
58
            n_add *= 2
×
59

60
        # TMD DVs
61
        if self.opt['design_variables']['TMDs']['flag']:
×
62
            TMD_opt = self.opt['design_variables']['TMDs']
×
63

64
            # We only support one TMD for now
65
            for tmd_group in TMD_opt['groups']:
×
66
                if 'mass' in tmd_group:
×
67
                    n_add += 1
×
68
                if 'stiffness' in tmd_group:
×
69
                    n_add += 1
×
70
                if 'damping' in tmd_group:
×
71
                    n_add += 1
×
72

73

74

75
        
76

77
        return n_DV+n_add
×
78

79

80
    
81
    def set_objective(self, wt_opt):
1✔
82
        if self.opt['merit_figure'] == 'blade_tip_deflection':
1✔
83
            wt_opt.model.add_objective('tcons_post.tip_deflection_ratio')
×
84
            
85
        elif self.opt['merit_figure'] == 'DEL_RootMyb':   # for DAC optimization on root-flap-bending moments
1✔
86
            wt_opt.model.add_objective('aeroelastic.DEL_RootMyb', ref = 1.e3)
×
87
            
88
        elif self.opt['merit_figure'] == 'DEL_TwrBsMyt':   # for pitch controller optimization
1✔
89
            wt_opt.model.add_objective('aeroelastic.DEL_TwrBsMyt', ref=1.e4)
1✔
90
            
91
        elif self.opt['merit_figure'] == 'rotor_overspeed':
1✔
NEW
92
            if not any(self.level_flags):
×
NEW
93
                raise Exception('Please turn on the call to OpenFAST or RAFT if you are trying to optimize rotor overspeed constraints.')
×
NEW
94
            wt_opt.model.add_objective(f'{self.floating_solve_component}.rotor_overspeed')
×
95
        
96
        elif self.opt['merit_figure'] == 'Std_PtfmPitch':
1✔
97
            wt_opt.model.add_objective('aeroelastic.Std_PtfmPitch')
1✔
98
        
99
        elif self.opt['merit_figure'] == 'Max_PtfmPitch':
1✔
100
            wt_opt.model.add_objective('aeroelastic.Max_PtfmPitch')
×
101

102
        elif self.opt['merit_figure'] == 'Cp':
1✔
103
            wt_opt.model.add_objective('aeroelastic.Cp_out', ref=-1.)
×
104
        
105
        elif self.opt['merit_figure'] == 'weis_lcoe':
1✔
106
            wt_opt.model.add_objective('financese_post.lcoe')
×
107
        
108
        elif self.opt['merit_figure'] == 'OL2CL_pitch':
1✔
109
            wt_opt.model.add_objective('aeroelastic.OL2CL_pitch')
×
110
        
111
        else:
×
112
            super(PoseOptimizationWEIS, self).set_objective(wt_opt)
1✔
113
                
114
        return wt_opt
1✔
115

116
    
117
    def set_design_variables(self, wt_opt, wt_init):
1✔
118
        super(PoseOptimizationWEIS, self).set_design_variables(wt_opt, wt_init)
1✔
119

120
        # -- Control --
121
        control_opt = self.opt['design_variables']['control']
1✔
122
        if control_opt['servo']['pitch_control']['omega']['flag']:
1✔
123
            wt_opt.model.add_design_var('tune_rosco_ivc.omega_pc', lower=control_opt['servo']['pitch_control']['omega']['min'], 
1✔
124
                                                            upper=control_opt['servo']['pitch_control']['omega']['max'])
1✔
125
        if control_opt['servo']['pitch_control']['zeta']['flag']:                            
1✔
126
            wt_opt.model.add_design_var('tune_rosco_ivc.zeta_pc', lower=control_opt['servo']['pitch_control']['zeta']['min'], 
1✔
127
                                                           upper=control_opt['servo']['pitch_control']['zeta']['max'])
1✔
128
        if control_opt['servo']['torque_control']['omega']['flag']:
1✔
129
            wt_opt.model.add_design_var('tune_rosco_ivc.omega_vs', lower=control_opt['servo']['torque_control']['omega']['min'], 
×
130
                                                            upper=control_opt['servo']['torque_control']['omega']['max'])
×
131
        if control_opt['servo']['torque_control']['zeta']['flag']:                                                    
1✔
132
            wt_opt.model.add_design_var('tune_rosco_ivc.zeta_vs', lower=control_opt['servo']['torque_control']['zeta']['min'], 
×
NEW
133
                                                           upper=control_opt['servo']['torque_control']['zeta_max'])
×
134
        if control_opt['servo']['ipc_control']['Kp']['flag']:
1✔
135
            wt_opt.model.add_design_var('tune_rosco_ivc.IPC_Kp1p', lower=control_opt['servo']['ipc_control']['Kp']['min'],
×
136
                                                            upper=control_opt['servo']['ipc_control']['Kp']['max'],
×
137
                                                            ref=control_opt['servo']['ipc_control']['Kp']['ref'])
×
138
        if control_opt['servo']['ipc_control']['Ki']['flag']:
1✔
139
            wt_opt.model.add_design_var('tune_rosco_ivc.IPC_Ki1p', lower=control_opt['servo']['ipc_control']['Ki']['min'],
×
140
                                                            upper=control_opt['servo']['ipc_control']['Ki']['max'],
×
141
                                                            ref=control_opt['servo']['ipc_control']['Kp']['ref'])
×
142
        if control_opt['servo']['pitch_control']['stability_margin']['flag']:
1✔
143
            wt_opt.model.add_design_var('tune_rosco_ivc.stability_margin', lower=control_opt['servo']['pitch_control']['stability_margin']['min'],
×
144
                                                            upper=control_opt['servo']['pitch_control']['stability_margin']['max'])
×
145
        if control_opt['flaps']['te_flap_end']['flag']:
1✔
146
            wt_opt.model.add_design_var('dac_ivc.te_flap_end', lower=control_opt['flaps']['te_flap_end']['min'],
×
147
                                                            upper=control_opt['flaps']['te_flap_end']['max'])
×
148
        if control_opt['flaps']['te_flap_ext']['flag']:
1✔
149
            wt_opt.model.add_design_var('dac_ivc.te_flap_ext', lower=control_opt['flaps']['te_flap_ext']['min'],
×
150
                                                            upper=control_opt['flaps']['te_flap_ext']['max'])
×
151
        if 'flap_control' in control_opt['servo']:
1✔
152
            if control_opt['servo']['flap_control']['flp_kp_norm']['flag']:
1✔
153
                wt_opt.model.add_design_var('tune_rosco_ivc.flp_kp_norm', 
×
154
                                    lower=control_opt['servo']['flap_control']['flp_kp_norm']['min'], 
×
155
                                    upper=control_opt['servo']['flap_control']['flp_kp_norm']['max'])
×
156
            if control_opt['servo']['flap_control']['flp_tau']['flag']:
1✔
157
                wt_opt.model.add_design_var('tune_rosco_ivc.flp_tau', 
×
158
                                    lower=control_opt['servo']['flap_control']['flp_tau']['min'], 
×
159
                                    upper=control_opt['servo']['flap_control']['flp_tau']['max'])
×
160

161
        if control_opt['ps_percent']['flag']:
1✔
162
            wt_opt.model.add_design_var('tune_rosco_ivc.ps_percent', lower=control_opt['ps_percent']['lower_bound'],
×
163
                                                            upper=control_opt['ps_percent']['upper_bound'])
×
164

165
        if control_opt['servo']['pitch_control']['Kp_float']['flag']:
1✔
166
            wt_opt.model.add_design_var('tune_rosco_ivc.Kp_float', lower=control_opt['servo']['pitch_control']['Kp_float']['min'], 
1✔
167
                                                           upper=control_opt['servo']['pitch_control']['Kp_float']['max'])
1✔
168

169
        if control_opt['servo']['pitch_control']['ptfm_freq']['flag']:
1✔
170
            wt_opt.model.add_design_var('tune_rosco_ivc.ptfm_freq', lower=control_opt['servo']['pitch_control']['ptfm_freq']['min'], 
1✔
171
                                                           upper=control_opt['servo']['pitch_control']['ptfm_freq']['max'])
1✔
172

173
        if self.opt['design_variables']['TMDs']['flag']:
1✔
174
            TMD_opt = self.opt['design_variables']['TMDs']
1✔
175

176
            # We only support one TMD for now
177
            for i_group, tmd_group in enumerate(TMD_opt['groups']):
1✔
178
                if 'mass' in tmd_group:
1✔
179
                    wt_opt.model.add_design_var(
1✔
180
                        f'TMDs.TMD_IVCs.group_{i_group}_mass', 
1✔
181
                        lower=tmd_group['mass']['lower_bound'],
1✔
182
                        upper=tmd_group['mass']['upper_bound'],
1✔
183
                        )
184
                if 'stiffness' in tmd_group:
1✔
185
                    wt_opt.model.add_design_var(
186
                        f'TMDs.TMD_IVCs.group_{i_group}_stiffness', 
187
                        lower=tmd_group['stiffness']['lower_bound'],
188
                        upper=tmd_group['stiffness']['upper_bound']
189
                        )
190
                    if 'natural_frequency' in tmd_group:
×
191
                        raise Exception("natural_frequency and stiffness can not be design variables in the same group")
×
192
                if 'damping' in tmd_group:
1✔
193
                    wt_opt.model.add_design_var(
194
                        f'TMDs.TMD_IVCs.group_{i_group}_damping', 
195
                        lower=tmd_group['damping']['lower_bound'],
196
                        upper=tmd_group['damping']['upper_bound']
197
                        )
198
                    if 'damping_ratio' in tmd_group:
×
199
                        raise Exception("damping_ratio and damping can not be design variables in the same group")
×
200
                if 'natural_frequency' in tmd_group:
1✔
201
                    wt_opt.model.add_design_var(
1✔
202
                        f'TMDs.TMD_IVCs.group_{i_group}_natural_frequency', 
1✔
203
                        lower=tmd_group['natural_frequency']['lower_bound'],
1✔
204
                        upper=tmd_group['natural_frequency']['upper_bound']
1✔
205
                        )
206
                if 'damping_ratio' in tmd_group:
1✔
207
                    wt_opt.model.add_design_var(
1✔
208
                        f'TMDs.TMD_IVCs.group_{i_group}_damping_ratio', 
1✔
209
                        lower=tmd_group['damping_ratio']['lower_bound'],
1✔
210
                        upper=tmd_group['damping_ratio']['upper_bound']
1✔
211
                        )
212
        
213
        return wt_opt
1✔
214

215
    
216
    def set_constraints(self, wt_opt):
1✔
217
        super(PoseOptimizationWEIS, self).set_constraints(wt_opt)
1✔
218

219
        blade_opt = self.opt["design_variables"]["blade"]
1✔
220
        blade_constr = self.opt["constraints"]["blade"]
1✔
221
        if blade_constr['tip_deflection']['flag']:
1✔
222
            # Remove generic WISDEM one
223
            name = 'tcons.tip_deflection_ratio'
×
224
            if name in wt_opt.model._responses:
×
225
                wt_opt.model._responses.pop( name )
×
226
            if name in wt_opt.model._static_responses:
×
227
                wt_opt.model._static_responses.pop( name )
×
228
                
229
            if blade_opt['structure']['spar_cap_ss']['flag'] or blade_opt['structure']['spar_cap_ps']['flag']:
×
230
                wt_opt.model.add_constraint('tcons_post.tip_deflection_ratio', upper=1.0)
×
231
            else:
×
232
                print('WARNING: the tip deflection is set to be constrained, but spar caps thickness is not an active design variable. The constraint is not enforced.')
×
233

234
        if blade_constr["strains_spar_cap_ss"]["flag"]:
1✔
235
            # Remove generic WISDEM one
236
            name = 'rotorse.rs.constr.constr_max_strainU_spar'
×
237
            if name in wt_opt.model._responses:
×
238
                wt_opt.model._responses.pop( name )
×
239
            if name in wt_opt.model._static_responses:
×
240
                wt_opt.model._static_responses.pop( name )
×
241
            if blade_opt["structure"]["spar_cap_ss"]["flag"]:
×
242
                indices_strains_spar_cap_ss = range(blade_constr["strains_spar_cap_ss"]["index_start"], blade_constr["strains_spar_cap_ss"]["index_end"])
×
243
                wt_opt.model.add_constraint("rlds_post.constr.constr_max_strainU_spar", indices = indices_strains_spar_cap_ss, upper=1.0)
×
244

245
        if blade_constr["strains_spar_cap_ps"]["flag"]:
1✔
246
            if (
247
                blade_opt["structure"]["spar_cap_ps"]["flag"]
248
                or blade_opt["structure"]["spar_cap_ps"]["equal_to_suction"]
249
            ):
250
                # Remove generic WISDEM one
251
                name = 'rotorse.rs.constr.constr_max_strainL_spar'
252
                if name in wt_opt.model._responses:
253
                    wt_opt.model._responses.pop( name )
254
                if name in wt_opt.model._static_responses:
255
                    wt_opt.model._static_responses.pop( name )
256
                indices_strains_spar_cap_ps = range(blade_constr["strains_spar_cap_ps"]["index_start"], blade_constr["strains_spar_cap_ps"]["index_end"])
257
                wt_opt.model.add_constraint("rlds_post.constr.constr_max_strainL_spar", indices = indices_strains_spar_cap_ps, upper=1.0)
258

259
        ### CONTROL CONSTRAINTS
260
        control_constraints = self.opt['constraints']['control']
1✔
261
        
262
        # Flap control
263
        if control_constraints['flap_control']['flag']:
1✔
264
            if self.modeling['Level3']['flag'] != True:
265
                raise Exception('Please turn on the call to OpenFAST if you are trying to optimize trailing edge flaps.')
266
            wt_opt.model.add_constraint('sse_tune.tune_rosco.flptune_coeff1',
267
                lower = control_constraints['flap_control']['min'],
268
                upper = control_constraints['flap_control']['max'])
269
            wt_opt.model.add_constraint('sse_tune.tune_rosco.flptune_coeff2', 
×
270
                lower = control_constraints['flap_control']['min'],
×
271
                upper = control_constraints['flap_control']['max'])    
×
272
        
273
        # Rotor overspeed
274
        if control_constraints['rotor_overspeed']['flag']:
1✔
275
            if not any(self.level_flags):
1✔
276
                raise Exception('Please turn on the call to OpenFAST or RAFT if you are trying to optimize rotor overspeed constraints.')
×
277
            wt_opt.model.add_constraint(f'{self.floating_solve_component}.rotor_overspeed',
1✔
278
                lower = control_constraints['rotor_overspeed']['min'],
1✔
279
                upper = control_constraints['rotor_overspeed']['max'])
1✔
280
        
281
        # Add PI gains if overspeed is merit_figure or constraint
282
        if control_constraints['rotor_overspeed']['flag'] or self.opt['merit_figure'] == 'rotor_overspeed':
1✔
283
            wt_opt.model.add_constraint('sse_tune.tune_rosco.PC_Kp',
1✔
284
                upper = 0.0)
1✔
285
            wt_opt.model.add_constraint('sse_tune.tune_rosco.PC_Ki', 
1✔
286
                upper = 0.0)  
1✔
287
        
288
        # Nacelle Accelleration magnitude
289
        if control_constraints['nacelle_acceleration']['flag']:
1✔
NEW
290
            if not any(self.level_flags):
×
NEW
291
                raise Exception('Please turn on the call to OpenFAST or RAFT if you are trying to optimize with nacelle_acceleration constraint.')
×
NEW
292
            wt_opt.model.add_constraint(f'{self.floating_solve_component}.max_nac_accel',
×
293
                    upper = control_constraints['nacelle_acceleration']['max'])
×
294
        
295
        # Max platform pitch
296
        if control_constraints['Max_PtfmPitch']['flag']:
1✔
297
            if not any(self.level_flags):
1✔
298
                raise Exception('Please turn on the call to OpenFAST or RAFT if you are trying to optimize Max_PtfmPitch constraints.')
×
299
            wt_opt.model.add_constraint(f'{self.floating_solve_component}.Max_PtfmPitch',
1✔
300
                upper = control_constraints['Max_PtfmPitch']['max'])
1✔
301
        
302
        # Platform pitch motion
303
        if control_constraints['Std_PtfmPitch']['flag']:
1✔
304
            if not any(self.level_flags):
×
305
                raise Exception('Please turn on the call to OpenFAST or RAFT if you are trying to optimize Std_PtfmPitch constraints.')
×
NEW
306
            wt_opt.model.add_constraint(f'{self.floating_solve_component}.Std_PtfmPitch',
×
307
                upper = control_constraints['Std_PtfmPitch']['max'])
×
308
        if control_constraints['Max_TwrBsMyt']['flag']:
1✔
309
            if self.modeling['Level3']['flag'] != True:
×
310
                raise Exception('Please turn on the call to OpenFAST if you are trying to optimize Max_TwrBsMyt constraints.')
×
311
            wt_opt.model.add_constraint('aeroelastic.max_TwrBsMyt_ratio', 
×
312
                upper = 1.0)
×
313
        if control_constraints['DEL_TwrBsMyt']['flag']:
1✔
314
            if self.modeling['Level3']['flag'] != True:
×
315
                raise Exception('Please turn on the call to OpenFAST if you are trying to optimize Max_TwrBsMyt constraints.')
×
316
            wt_opt.model.add_constraint('aeroelastic.DEL_TwrBsMyt_ratio', 
×
317
                upper = 1.0)
×
318
            
319
        # Blade pitch travel
320
        if control_constraints['avg_pitch_travel']['flag']:
1✔
321
            if self.modeling['Level3']['flag'] != True:
×
322
                raise Exception('Please turn on the call to OpenFAST if you are trying to optimize avg_pitch_travel constraints.')
×
323
            wt_opt.model.add_constraint('aeroelastic.avg_pitch_travel',
×
324
                upper = control_constraints['avg_pitch_travel']['max'])
×
325

326
        # Blade pitch duty cycle (number of direction changes)
327
        if control_constraints['pitch_duty_cycle']['flag']:
1✔
328
            if self.modeling['Level3']['flag'] != True:
×
329
                raise Exception('Please turn on the call to OpenFAST if you are trying to optimize pitch_duty_cycle constraints.')
×
330
            wt_opt.model.add_constraint('aeroelastic.pitch_duty_cycle',
×
331
                upper = control_constraints['pitch_duty_cycle']['max'])
×
332

333
        # OpenFAST failure
334
        if self.opt['constraints']['openfast_failed']['flag']:
1✔
335
            if self.modeling['Level3']['flag'] != True:
1✔
336
                raise Exception('Please turn on the call to OpenFAST if you are trying to optimize with openfast_failed constraint.')
×
337
            wt_opt.model.add_constraint('aeroelastic.openfast_failed',upper = 1.)
1✔
338

339
        # Max offset
340
        if self.opt['constraints']['floating']['Max_Offset']['flag']:
1✔
341
            if not any(self.level_flags):
×
342
                raise Exception('Please turn on the call to OpenFAST or RAFT if you are trying to optimize with openfast_failed constraint.')
×
343
            wt_opt.model.add_constraint(
344
                f'{self.floating_solve_component}.Max_Offset',
345
                upper = self.opt['constraints']['floating']['Max_Offset']['max']
346
                )
347
                
348
        # Tower constraints
349
        tower_opt = self.opt["design_variables"]["tower"]
1✔
350
        tower_constr = self.opt["constraints"]["tower"]
1✔
351
        if tower_constr["global_buckling"]["flag"] and self.modeling['Level3']['flag']:
1✔
352
            # Remove generic WISDEM one
353
            name = 'towerse.post.constr_global_buckling'
×
354
            if name in wt_opt.model._responses:
×
355
                wt_opt.model._responses.pop( name )
×
356
            if name in wt_opt.model._static_responses:
×
357
                wt_opt.model._static_responses.pop( name )
×
358
                
359
            wt_opt.model.add_constraint("towerse_post.constr_global_buckling", upper=1.0)
×
360
        
361
        if tower_constr["shell_buckling"]["flag"] and self.modeling['Level3']['flag']:
1✔
362
            # Remove generic WISDEM one
363
            name = 'towerse.post.constr_shell_buckling'
×
364
            if name in wt_opt.model._responses:
×
365
                wt_opt.model._responses.pop( name )
×
366
            if name in wt_opt.model._static_responses:
×
367
                wt_opt.model._static_responses.pop( name )
×
368
                
369
            wt_opt.model.add_constraint("towerse_post.constr_shell_buckling", upper=1.0)
×
370
        
371
        if tower_constr["stress"]["flag"] and self.modeling['Level3']['flag']:
1✔
372
            # Remove generic WISDEM one
373
            name = 'towerse.post.constr_stress'
×
374
            if name in wt_opt.model._responses:
×
375
                wt_opt.model._responses.pop( name )
×
376
            if name in wt_opt.model._static_responses:
×
377
                wt_opt.model._static_responses.pop( name )
×
378
                
379
            wt_opt.model.add_constraint("towerse_post.constr_stress", upper=1.0)
×
380

381
        # Damage constraints
382
        damage_constraints = self.opt['constraints']['damage']
1✔
383
        if damage_constraints['tower_base']['flag'] and (self.modeling['Level2']['flag'] or self.modeling['Level3']['flag']):
1✔
384
            if self.modeling['Level3']['flag'] != True:
1✔
385
                raise Exception('Please turn on the call to OpenFAST if you are trying to optimize with tower_base damage constraint.')
×
386

387
            tower_base_damage_max = damage_constraints['tower_base']['max']
1✔
388
            if damage_constraints['tower_base']['log']:
1✔
389
                tower_base_damage_max = np.log(tower_base_damage_max)
1✔
390

391
            wt_opt.model.add_constraint('aeroelastic.damage_tower_base',upper = tower_base_damage_max)
1✔
392

393
        return wt_opt
1✔
394

395

396
    def set_initial_weis(self, wt_opt):
1✔
397

398
        if self.modeling["flags"]["blade"]:
1✔
399
            blade_constr = self.opt["constraints"]["blade"]
1✔
400
            wt_opt["rlds_post.constr.max_strainU_spar"] = blade_constr["strains_spar_cap_ss"]["max"]
1✔
401
            wt_opt["rlds_post.constr.max_strainL_spar"] = blade_constr["strains_spar_cap_ps"]["max"]
1✔
402
            wt_opt["stall_check_of.stall_margin"] = blade_constr["stall"]["margin"] * 180.0 / np.pi
1✔
403
            wt_opt["tcons_post.max_allowable_td_ratio"] = blade_constr["tip_deflection"]["margin"]
1✔
404

405
        return wt_opt
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc