Skip to content

Commit 43401ed

Browse files
authored
Merge pull request #3306 from hkross/bug/MHK_Inflow_Calls
MHK inflow calls
2 parents 005b790 + 7a3ff44 commit 43401ed

7 files changed

Lines changed: 73 additions & 37 deletions

File tree

docs/source/user/inflowwind/input.rst

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,26 +117,26 @@ be performed in a different order than if both angles are specified in the same
117117

118118
.. _inflow_superposition:
119119

120-
Superposition of Wave and Current Inflow
121-
========================================
122-
For MHK turbines, wave and current velocities and accelerations are superimposed (i.e., summed) such that all submerged components are exposed
120+
Superposition/Coupling of Wave and Current Inflow
121+
=================================================
122+
For MHK turbines, wave and current velocities and accelerations are superimposed (i.e., summed) or coupled (see :ref:`sea-waves`) such that all submerged components are exposed
123123
to the same inflow field. Both AeroDyn and HydroDyn can query SeaState for wave field information. SeaState then queries InflowWind for the current
124-
field, sums the velocities and accelerations, and returns the superimposed flow field information. This has several implications for modeling
124+
field, sums or couples the velocities and accelerations, and returns the flow field information. This has several implications for modeling
125125
MHK turbines, which are listed below. Note that dynamic pressure contributions from InflowWind are neglected.
126126

127127
When modeling a rotor or rotor/tower only (i.e., hydrodynamics modeled in AeroDyn only):
128128

129129
- SeaState must be used when defining a flow field with waves
130-
- Current definition in SeaState must always be set to 0
131-
- If SeaState is activated, InflowWind must also be activated, though the current can be set to 0
132130
- InflowWind must be used when defining a flow field with currents
131+
- Current definition in SeaState must always be set to 0
133132
- For combined wave and current flow fields, SeaState will query InflowWind
134133

135134
When modeling a rotor or rotor/tower and support structure (i.e., hydrodynamics modeled in AeroDyn and HydroDyn):
136135

137136
- SeaState must always be used, even when defining a flow field with no waves
138-
- Current definition in SeaState must always be set to 0
139-
- If SeaState is activated, InflowWind must also be activated, though the current can be set to 0
140137
- InflowWind must be used when defining a flow field with currents
138+
- Current definition in SeaState must always be set to 0
141139
- For current only cases, set the SeaState wave field to 0; current information will be passed through SeaState from InflowWind
142-
- For combined wave and current flow fields, SeaState will query InflowWind
140+
- For combined wave and current flow fields, SeaState will query InflowWind
141+
142+
Wave and current coupling is only possible when running the OpenFAST glue code or the AeroDyn driver. This feature is not supported by the HydroDyn or MoorDyn drivers.

docs/source/user/seastate/input_files.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ When setting up the wave grid, it is necessary to make sure the wave grid is lar
107107

108108
OpenFAST precomputes and saves the wave-field velocity, acceleration, dynamic pressure, and wave elevation at the start of the simulation. Generating and maintaining the wave grid can be memory intensive for long simulations. Users should set the wave grid to be no larger or finer than necessary to reduce memory use. Reducing **WaveTMax** or increasing **WaveDT** (see WAVES section below) also reduces memory use. For long crested waves (no directional spreading) aligned with the *X*-direction (or *Y*-direction), **NY** (or **NX**) can be reduced to the minimum allowed value of 2 to save memory.
109109

110+
.. _sea-waves:
111+
110112
Waves
111113
-----
112114

@@ -211,7 +213,8 @@ time-averaged current velocity at the still water level. For applicable **WindTy
211213
InflowWind, users should ensure that the flow-field grid from InflowWind reaches the still
212214
water level. **WvCrntMod** has no effect when **WaveMod** = 0 or 6, or when there is no
213215
current from either SeaState (**CurrMod** = 0) or InflowWind if simulating marine
214-
hydrokinetic turbines.
216+
hydrokinetic turbines. See :ref:`inflow_superposition`
217+
for additional context around wave-current coupling when simulating MHK turbines.
215218

216219
**WaveTMax** sets the length of the incident wave kinematics time
217220
series, but it also determines the frequency step used in the inverse

modules/aerodyn/src/AeroDyn.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,7 +1412,7 @@ subroutine Init_RotInflow( p, RotInflow, errStat, ErrMsg )
14121412
if (Failed()) return
14131413
RotInflow%Blade(k)%InflowVel = 0.0_ReKi
14141414

1415-
if (p%MHK > 0) then
1415+
if (p%MHK /= MHK_None) then
14161416
call AllocAry( RotInflow%Blade(k)%InflowAcc, 3_IntKi, p%NumBlNds, 'RotInflow%Blade(k)%InflowAcc', ErrStat2, ErrMsg2 )
14171417
if (Failed()) return
14181418
RotInflow%Blade(k)%InflowAcc = 0.0_ReKi
@@ -1422,7 +1422,7 @@ subroutine Init_RotInflow( p, RotInflow, errStat, ErrMsg )
14221422
call AllocAry( RotInflow%Tower%InflowVel, 3_IntKi, p%NumTwrNds, 'RotInflow%Tower%InflowVel', ErrStat2, ErrMsg2 ) ! could be size zero
14231423
if (Failed()) return
14241424

1425-
if (p%MHK > 0) then
1425+
if (p%MHK /= MHK_None) then
14261426
call AllocAry( RotInflow%Tower%InflowAcc, 3_IntKi, p%NumTwrNds, 'RotInflow%Tower%InflowAcc', ErrStat2, ErrMsg2 ) ! could be size zero
14271427
if (Failed()) return
14281428
end if
@@ -2031,7 +2031,7 @@ subroutine AD_CalcWind_Rotor(t, u, FlowField, p, p_AD, m, RotInflow, StartNode,
20312031
if (.not. associated(FlowField)) return ! use the initial (or input) values for these inputs
20322032

20332033
! If rotor is MHK, add water depth to z coordinate
2034-
if (p%MHK > 0) then
2034+
if (p%MHK /= MHK_None) then
20352035
PosOffset = [0.0_ReKi, 0.0_ReKi, p%WtrDpth]
20362036
else
20372037
PosOffset = 0.0_ReKi
@@ -4541,7 +4541,7 @@ SUBROUTINE ValidateInputData( InitInp, InputFileData, NumBl, calcCrvAngle, ErrSt
45414541
! .............................
45424542
! check tower mesh data:
45434543
! .............................
4544-
if (InputFileData%TwrPotent /= TwrPotent_none .or. InputFileData%TwrShadow /= TwrShadow_none .or. InputFileData%TwrAero /= TwrAero_none .or. InitInp%MHK > 0) then
4544+
if (InputFileData%TwrPotent /= TwrPotent_none .or. InputFileData%TwrShadow /= TwrShadow_none .or. InputFileData%TwrAero /= TwrAero_none .or. InitInp%MHK /= MHK_None) then
45454545
do iR = 1,size(NumBl)
45464546
if (InputFileData%rotors(iR)%NumTwrNds <= 0) cycle !bjj: this could be removed since the loops here already take into account the number of tower nodes
45474547

modules/aerodyn/src/AeroDyn_Driver_Subs.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1411,7 +1411,7 @@ subroutine ValidateInputs(dvr, errStat, errMsg)
14111411

14121412
if (dvr%MHK /= MHK_None .and. dvr%MHK /= MHK_FixedBottom .and. dvr%MHK /= MHK_Floating) call SetErrStat(ErrID_Fatal, 'MHK switch must be 0, 1, or 2.', ErrStat, ErrMsg, RoutineName)
14131413

1414-
if (dvr%MHK /= MHK_None .and. dvr%SS_InitInp%CompSeaSt == 1 .and. dvr%IW_InitInp%CompInflow /= 1) call SetErrStat( ErrID_Fatal, 'InflowWind must be activated for MHK turbines when SeaState is used.', ErrStat, ErrMsg, RoutineName )
1414+
if (dvr%MHK /= MHK_None .and. dvr%SS_InitInp%CompSeaSt == 1 .and. dvr%IW_InitInp%CompInflow == 0 .and. dvr%IW_InitInp%HWindSpeed > 0) call SetErrStat( ErrID_Fatal, 'Steady Wind option in AeroDyn driver cannot be used for MHK turbines with SeaState.', ErrStat, ErrMsg, RoutineName )
14151415

14161416
if (dvr%MHK == MHK_None .and. dvr%SS_InitInp%CompSeaSt /= 0) call SetErrStat( ErrID_Fatal, 'SeaState cannot be used with wind turbines.', ErrStat, ErrMsg, RoutineName )
14171417

modules/seastate/src/SeaSt_WaveField.f90

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,16 @@ SUBROUTINE WaveField_GetNodeWaveKin( WaveField, WaveField_m, Time, pos, forceNod
168168
WaveElev = WaveField_GetNodeTotalWaveElev(WaveField, WaveField_m, Time, pos, ErrStat2, ErrMsg2, Elev1=WaveElev1, Elev2=WaveElev2)
169169
if (Failed()) return
170170

171+
! Check if point is below the seabed
172+
if (pos(3)<-WaveField%EffWtrDpth) then
173+
nodeInWater = 1_IntKi ! Prevent problems with HydroDyn logic
174+
FV(:) = 0.0_SiKi
175+
FA(:) = 0.0_SiKi
176+
FDynP = 0.0_SiKi
177+
FAMCF(:) = 0.0_SiKi
178+
return
179+
end if
180+
171181
IF (WaveField%WaveStMod == 0) THEN ! No wave stretching
172182

173183
IF ( pos(3) <= 0.0_ReKi) THEN ! Node is at or below the SWL
@@ -182,10 +192,10 @@ SUBROUTINE WaveField_GetNodeWaveKin( WaveField, WaveField_m, Time, pos, forceNod
182192
END IF
183193
ELSE ! Node is above the SWL
184194
nodeInWater = 0_IntKi
185-
FV(:) = 0.0
186-
FA(:) = 0.0
187-
FDynP = 0.0
188-
FAMCF(:) = 0.0
195+
FV(:) = 0.0_SiKi
196+
FA(:) = 0.0_SiKi
197+
FDynP = 0.0_SiKi
198+
FAMCF(:) = 0.0_SiKi
189199
END IF
190200

191201
ELSE ! Wave stretching enabled
@@ -251,10 +261,10 @@ SUBROUTINE WaveField_GetNodeWaveKin( WaveField, WaveField_m, Time, pos, forceNod
251261
ELSE ! Node is out of water - zero-out all wave dynamics
252262

253263
nodeInWater = 0_IntKi
254-
FV(:) = 0.0
255-
FA(:) = 0.0
256-
FDynP = 0.0
257-
FAMCF(:) = 0.0
264+
FV(:) = 0.0_SiKi
265+
FA(:) = 0.0_SiKi
266+
FDynP = 0.0_SiKi
267+
FAMCF(:) = 0.0_SiKi
258268

259269
END IF ! If node is in or out of water
260270

@@ -315,6 +325,13 @@ SUBROUTINE WaveField_GetDynP( WaveField, WaveField_m, Time, pos, forceNodeInWate
315325
! Wave elevation (Calls WaveField_Interp_Setup3D internally so WaveField_Interp_3D_vec can be used below)
316326
WaveElev = WaveField_GetNodeTotalWaveElev( WaveField, WaveField_m, Time, pos, ErrStat2, ErrMsg2 ); if (Failed()) return;
317327

328+
! Check if point is below the seabed
329+
if (pos(3)<-WaveField%EffWtrDpth) then
330+
nodeInWater = 1_IntKi ! Prevent problems with HydroDyn logic
331+
FDynP = 0.0_SiKi
332+
return
333+
end if
334+
318335
IF (WaveField%WaveStMod == 0) THEN ! No wave stretching
319336

320337
IF ( pos(3) <= 0.0_ReKi) THEN ! Node is at or below the SWL
@@ -324,7 +341,7 @@ SUBROUTINE WaveField_GetDynP( WaveField, WaveField_m, Time, pos, forceNodeInWate
324341
FDynP = GridInterp4D ( WaveField%WaveDynP, WaveField_m )
325342
ELSE ! Node is above the SWL
326343
nodeInWater = 0_IntKi
327-
FDynP = 0.0
344+
FDynP = 0.0_SiKi
328345
END IF
329346

330347
ELSE ! Wave stretching enabled
@@ -365,7 +382,7 @@ SUBROUTINE WaveField_GetDynP( WaveField, WaveField_m, Time, pos, forceNodeInWate
365382
ELSE ! Node is out of water - zero-out all wave dynamics
366383

367384
nodeInWater = 0_IntKi
368-
FDynP = 0.0
385+
FDynP = 0.0_SiKi
369386

370387
END IF ! If node is in or out of water
371388
END IF ! If wave stretching is on or off
@@ -407,6 +424,13 @@ SUBROUTINE WaveField_GetNodeWaveVel( WaveField, WaveField_m, Time, pos, forceNod
407424
! Wave elevation (Calls WaveField_Interp_Setup3D internally so WaveField_Interp_3D_vec can be used below)
408425
WaveElev = WaveField_GetNodeTotalWaveElev( WaveField, WaveField_m, Time, pos, ErrStat2, ErrMsg2 ); if (Failed()) return;
409426

427+
! Check if point is below the seabed
428+
if (pos(3)<-WaveField%EffWtrDpth) then
429+
nodeInWater = 1_IntKi ! Prevent problems with HydroDyn logic
430+
FV(:) = 0.0_SiKi
431+
return
432+
end if
433+
410434
IF (WaveField%WaveStMod == 0) THEN ! No wave stretching
411435

412436
IF ( pos(3) <= 0.0_ReKi) THEN ! Node is at or below the SWL
@@ -416,7 +440,7 @@ SUBROUTINE WaveField_GetNodeWaveVel( WaveField, WaveField_m, Time, pos, forceNod
416440
FV(:) = GridInterp4DVec( WaveField%WaveVel, WaveField_m )
417441
ELSE ! Node is above the SWL
418442
nodeInWater = 0_IntKi
419-
FV(:) = 0.0
443+
FV(:) = 0.0_SiKi
420444
END IF
421445

422446
ELSE ! Wave stretching enabled
@@ -463,7 +487,7 @@ SUBROUTINE WaveField_GetNodeWaveVel( WaveField, WaveField_m, Time, pos, forceNod
463487
ELSE ! Node is out of water - zero-out all wave dynamics
464488

465489
nodeInWater = 0_IntKi
466-
FV(:) = 0.0
490+
FV(:) = 0.0_SiKi
467491

468492
END IF ! If node is in or out of water
469493

@@ -520,7 +544,15 @@ SUBROUTINE WaveField_GetNodeWaveVelAcc( WaveField, WaveField_m, Time, pos, force
520544

521545
! Wave elevation
522546
WaveElev = WaveField_GetNodeTotalWaveElev( WaveField, WaveField_m, Time, pos, ErrStat2, ErrMsg2 ); if (Failed()) return;
523-
547+
548+
! Check if point is below the seabed
549+
if (pos(3)<-WaveField%EffWtrDpth) then
550+
nodeInWater = 1_IntKi ! Prevent problems with HydroDyn logic
551+
FV(:) = 0.0_SiKi
552+
FA(:) = 0.0_SiKi
553+
return
554+
end if
555+
524556
IF (WaveField%WaveStMod == 0) THEN ! No wave stretching
525557

526558
IF ( pos(3) <= 0.0_ReKi) THEN ! Node is at or below the SWL
@@ -531,8 +563,8 @@ SUBROUTINE WaveField_GetNodeWaveVelAcc( WaveField, WaveField_m, Time, pos, force
531563
FA(:) = GridInterp4DVec( WaveField%WaveAcc, WaveField_m )
532564
ELSE ! Node is above the SWL
533565
nodeInWater = 0_IntKi
534-
FV(:) = 0.0
535-
FA(:) = 0.0
566+
FV(:) = 0.0_SiKi
567+
FA(:) = 0.0_SiKi
536568
END IF
537569

538570
ELSE ! Wave stretching enabled
@@ -582,8 +614,8 @@ SUBROUTINE WaveField_GetNodeWaveVelAcc( WaveField, WaveField_m, Time, pos, force
582614
ELSE ! Node is out of water - zero-out all wave dynamics
583615

584616
nodeInWater = 0_IntKi
585-
FV(:) = 0.0
586-
FA(:) = 0.0
617+
FV(:) = 0.0_SiKi
618+
FA(:) = 0.0_SiKi
587619
END IF ! If node is in or out of water
588620

589621
END IF ! If wave stretching is on or off

modules/seastate/src/SeaState_Input.f90

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,11 @@ subroutine SeaStateInput_ProcessInitData( InitInp, p, InputFileData, ErrStat, Er
925925

926926

927927
! CurrMod - Current profile model switch
928+
if ( ( InputFileData%Current%CurrMod /= 0 ) .AND. ( InitInp%MHK /= MHK_None ) ) then
929+
call SetErrStat( ErrID_Fatal,'CurrMod must be set to 0 for an MHK turbine.',ErrStat,ErrMsg,RoutineName)
930+
return
931+
end if
932+
928933
if ( InitInp%hasCurrField ) then
929934
call SetErrStat( ErrID_Warn,'Expecting current field from InflowWind. Setting CurrMod to 0.',ErrStat,ErrMsg,RoutineName)
930935
InputFileData%Current%CurrMod = 0
@@ -940,10 +945,6 @@ subroutine SeaStateInput_ProcessInitData( InitInp, p, InputFileData, ErrStat, Er
940945
return
941946
end if
942947

943-
! if ( ( InputFileData%Current%CurrMod /= 0 ) .AND. ( InitInp%MHK /= MHK_None ) ) then
944-
! call SetErrStat( ErrID_Fatal,'CurrMod must be set to 0 for an MHK turbine.',ErrStat,ErrMsg,RoutineName)
945-
! return
946-
! end if
947948

948949

949950
if ( InputFileData%Current%CurrMod == 1 ) then ! .TRUE if we have standard current.

0 commit comments

Comments
 (0)