openfast icon indicating copy to clipboard operation
openfast copied to clipboard

Additional features for the new SeaState module and HydroDyn

Open luwang00 opened this issue 3 years ago • 2 comments

This Pull request is NOT ready for merging (requires the merging of HaymanConsulting:F/SeaState+ first)

This pull request also supercedes the HydroDyn / SeaState+ pull request from HaymanConsulting (items from that PR are now included here).

r-tests will not pass. Need to update input files based on input file changes. New features have passed preliminary verification: luwang00/feature-test (private repository).

Feature or improvement description

  • Added the Constrained NewWave feature to SeaState.

  • Added WaveMod=7 option to SeaState to enable incident waves based on user specified wave frequency components.

  • Implemented and reenabled all wave stretching options in HydroDyn: no wave stretching (WaveStMod = 0), vertical stretching (WaveStMod = 1), extrapolation stretching (WaveStMod = 2), and Wheeler stretching (WaveStMod = 3). Nodal load smoothing is formulated and implemented to ensure continuous and smooth variation of the wave loads as member nodes enter and exit water.

  • Added the MacCamy-Fuchs diffraction correction to HydroDyn for Morison-only members.

  • Minor updates and bug fixes such as making the wave-radiation convolutional integral in HydroDyn 2nd order accurate.

  • The registry system has been augmented to support Fortran pointers. This allows for sharing of pointers to large data arrays across OpenFAST modules.

  • The wave kinematics functionality of HydroDyn has been separated out into its own module: SeaState. This module is initialized by the glue-code and resulting data is passed via the glue-code to individual modules (i.e., HydroDyn).

  • Wave kinematics are now generated on a 3D grid, which is user-specified in the SeaState input file.

  • Strip-theory Hydrodynamic load calculations can now be performed at the displaced location of the substructure. Potential flow (wave excitation loads) can now be computed at the WAMIT body's displaced location.

Related issue, if one exists https://github.com/OpenFAST/openfast/pull/970#issue-1108403765 https://github.com/OpenFAST/openfast/issues/847 https://github.com/OpenFAST/openfast/issues/844 https://github.com/OpenFAST/openfast/issues/842

Impacted areas of the software HydroDyn => restructuring to split out new SeaState module HydroDyn => Wave stretching and the MacCamy-Fuchs diffraction correction. SeaState => Wave stretching, the MacCamy-Fuchs diffraction correction, WaveMod=7 option, and the Constrainted NewWave feature. FAST glue-code => support for new SeaState module FAST glude-code => Passing additional pointers and variables from SeaState to HydroDyn to support wave stretching. FAST Registry => Fortran Pointer support NOTE: This breaks restart functionality

Additional supporting information Draft documentation of the new features is included: docs/OtherSupporting/HydroDyn/HydroDyn_MacCamy-Fuchs.docx docs/OtherSupporting/HydroDyn/HydroDyn_WaveStretching_Plan.docx docs/OtherSupporting/SeaState/SeaState_Constrained_NewWave.docx docs/OtherSupporting/SeaState/SeaState_WaveMod7.docx

To do

  • [ ] merge #970 (with updated r-test)
  • [ ] update r-test results
  • [ ] add test cases for feature (from @luwang00 private repo)
  • [ ] Update input files for regression tests
  • [ ] Verify regression test results are similar (differences expected)
  • [ ] Update the hd_c_lib interface module
  • [ ] Update python interface (if needed)
  • [ ] add SeaState regression tests: Limited testing has been performed and looks good. Testing database is here: https://github.com/HaymanConsulting/seast-test

luwang00 avatar Feb 18 '22 16:02 luwang00

Hi all,

I'm getting the following error after compiling this PR,

"HydroDyn_Init:Morison_Init:Morison_CalcOutput:An initially fully submerged member cannot pierce the free surface. This has happend for Member ID 8".

I appreciate this is on going work and perhaps it's either simply not ready or I'm misusing it in some way.

I'm using the WaveStMod = 3 option.

I think the problem relates to defining whether or not a member is fully submerged and/or requires wave stretching.

In Morison.f90 (lines 3291-3293), we have : z1 = u%Mesh%Position(3, mem%NodeIndx(1)) - p%MSL2SWL z2 = u%Mesh%Position(3, mem%NodeIndx(N+1)) - p%MSL2SWL IF ( z2 > 0.0_SiKi .AND. z1 <= 0.0_SiKi .AND. p%WaveStMod > 0) THEN i.e. we enter the wave stretching loop if we have an element with a lower most point at a minimum on the MSL.

If you don't enter this loop, it seems you enter the else on line 3635 which in turn ends up invoking the following check, "p%WaveStMod>0 .AND. z1>m%WaveElev(mem%NodeIndx(i))": this is the check that is throwing my error.

Why doesn't the condition in line 3293 relate to instantaneous water level rather than the MSL2SWL? If this is as intended, why would we end up checking against some different water level (the instantaneous one) here ("p%WaveStMod>0 .AND. z1>m%WaveElev(mem%NodeIndx(i))")?

Best, Sam

Sam-Ramsahoye avatar Aug 23 '22 08:08 Sam-Ramsahoye

Hi all,

I'm getting the following error after compiling this PR,

"HydroDyn_Init:Morison_Init:Morison_CalcOutput:An initially fully submerged member cannot pierce the free surface. This has happend for Member ID 8".

I appreciate this is on going work and perhaps it's either simply not ready or I'm misusing it in some way.

I'm using the WaveStMod = 3 option.

I think the problem relates to defining whether or not a member is fully submerged and/or requires wave stretching.

In Morison.f90 (lines 3291-3293), we have : z1 = u%Mesh%Position(3, mem%NodeIndx(1)) - p%MSL2SWL z2 = u%Mesh%Position(3, mem%NodeIndx(N+1)) - p%MSL2SWL IF ( z2 > 0.0_SiKi .AND. z1 <= 0.0_SiKi .AND. p%WaveStMod > 0) THEN i.e. we enter the wave stretching loop if we have an element with a lower most point at a minimum on the MSL.

If you don't enter this loop, it seems you enter the else on line 3635 which in turn ends up invoking the following check, "p%WaveStMod>0 .AND. z1>m%WaveElev(mem%NodeIndx(i))": this is the check that is throwing my error.

Why doesn't the condition in line 3293 relate to instantaneous water level rather than the MSL2SWL? If this is as intended, why would we end up checking against some different water level (the instantaneous one) here ("p%WaveStMod>0 .AND. z1>m%WaveElev(mem%NodeIndx(i))")?

Best, Sam

Hi @Sam-Ramsahoye ,

Our current implementation of wave loads with wave stretching is different for surface-piercing members and fully submerged members. The undisplaced reference position of each member is used to determine whether it should be classed as surface-piercing or fully submerged. If one end node is above the still water level and one node is below at their undisplaced reference positions, the member is considered surface piercing. Otherwise, it is fully submerged. This is the IF condition on line 3293 you referenced.

This distinction between surface-piercing and fully submerged members is made because we need to carry out a special nodal load redistribution/smoothing procedure for the former. Without load smoothing, the local nodal hydrodynamic loads can be discontinuous as the nodes enter or emerge from water, which could potentially excite spurious high-frequency structural vibration in hydroelastic simulations. For surface-piercing members, the first branch of the IF condition on line 3293 with load smoothing is executed.

For fully submerged members, load smoothing is not required, so the second branch of the IF condition starting from line 3635 is executed. Note that if wave stretching is enabled, either branch of the IF condition on line 3293 uses the stretched wave field; the only difference is whether load smoothing is performed.

We currently require surface-piercing members to remain surface piercing and fully submerged members to remain fully submerged throughout the simulation (with reference to the instantaneous free surface). This restriction is imposed for two reasons. First, the load smoothing procedure does not guarantee continuous nodal loads as a surface-piercing member becomes fully submerged or vice versa. Second, the hydrodynamic model cannot correctly capture the water entry and exit loads. The second check on line 3649 you referenced enforces this restriction. It checks if all nodes of a member classed as fully submerged remain below the instantaneous free surface when wave stretching is enabled. A similar check that ensures a surface-piercing member don’t get fully submerged or move completely out of water also exists in the first branch of the IF condition on line 3293. See line 3418.

When wave stretching is off, there’s no need to distinguish between submerged and surface-piercing members, so the second branch of the IF condition on line 3293 is reused for convenience (with the unstretched wave field).

Based on the error message you provided, it looks like member 8 is classed as a fully submerged member (all nodes below the SWL at the undisplaced reference position), but part of it emerged from water during the time-domain simulation because of a large wave trough and/or structure heave motion, which is not allowed.

Best, Lu

luwang00 avatar Aug 26 '22 18:08 luwang00

@luwang00 Thanks very much again for your work developing the wave stretching functionality.

I know this is still WIP but I've noticed that buoyant loads aren't a function of the instantaneous water level.

I've put together a simple reproducer based on what I believe to be your latest iteration of the code (luwang00:dev). It's a monopile-like structure under loading from a regular wave and I simulate the loading over a single wave period: notice how the buoyancy load isn't a function of time.

image

driver.txt HydroDyn.txt SeaState.txt

Sam-Ramsahoye avatar Feb 15 '23 14:02 Sam-Ramsahoye

@luwang00 Thanks very much again for your work developing the wave stretching functionality.

I know this is still WIP but I've noticed that buoyant loads aren't a function of the instantaneous water level.

I've put together a simple reproducer based on what I believe to be your latest iteration of the code (luwang00:dev). It's a monopile-like structure under loading from a regular wave and I simulate the loading over a single wave period: notice how the buoyancy load isn't a function of time.

image

driver.txt HydroDyn.txt SeaState.txt

Hi @Sam-Ramsahoye,

Thanks for trying out the new features. The constant HydroFzi you are seeing is as intended.

When WaveStMod != 0, the hydrostatic pressure $p_{hst}=-\rho g (z-z_{swl})$ is integrated over the instantaneous wetted surface of the member. Note that the hydrostatic pressure field itself is constant in time; only the surface over which it is integrated potentially changes with body motion and/or wave elevation.

You can see this effect by zeroing out your transverse hydrodynamic coefficients, in which case you are left with a small net time-varying side force from the hydrostatic loading due to the time-varying wave slope.

With the fixed monopile-like structure, only the bottom end plate contributes to the vertical force. Since the hydrostatic pressure on the end plate is constant and the structure is not moving, your HydroFzi is also constant. To obtain the dynamic vertical load from the wave dynamic pressure on the end plate, you need to set AxCp to a nonzero value, typically 1, under joint coefficients.

Also, I noticed that you have AMMod=0. Just be aware that this will force the evaluation of added-mass force to ignore wave stretching.

Best, Lu

luwang00 avatar Feb 15 '23 17:02 luwang00

@luwang00 Thanks very much for your reply, I'm still a little confused.

I was basically expecting to see the vertical load be more of less equal to the weight of the displaced volume of water as the members aren't filled i.e. they are cavities. Perhaps it's an issue with how I've configured the primary input file. The vertical z load is basically equal to the still water buoyancy load.

I think I might misunderstand the definition of joints and joint coefficients in HydroDyn.

The case I prepared for you is a small canonical example after I noticed a large discrepancy in HydroFzi comparing this update to HydroDyn against DNV's Sesam (Wajac) over a period of time in an irregular seastate where there's a constrained wave.

Thanks for your tip re AMMod==0!

Cheers, Sam

Sam-Ramsahoye avatar Feb 15 '23 17:02 Sam-Ramsahoye

@Sam-Ramsahoye

OpenFAST does not compute the buoyancy load using displaced volume. Instead, the hydrostatic load (a more accurate term than buoyancy in this case) is obtained by integrating the constant hydrostatic pressure field over the wetted surface. Any load from dynamic time-varying pressure induced by waves and/or body motion should all be accounted for through the hydrodynamic coefficients.

We believe this approach gives a more physical local load distribution from the hydrostatic pressure field in hydroelastic simulations. It also avoids double counting the effects of waves through both the hydrodynamic coefficients and displacement-based buoyancy (which OpenFAST does not use).

For the problem you brought up, my suggestion is still to use appropriate axial coefficients to capture the dynamic loads from the waves.

Finally, I understand the example case you provided is just to demonstrate the discrepancy you observed, but we'd like to point out that for an actual monopile, the lower end joint of the monopile should be below the seabed, in which case no hydrostatic load will be applied to the bottom end plate. This gives the correct behavior.

Best, Lu

luwang00 avatar Feb 16 '23 16:02 luwang00

@luwang00 Ah I see, thanks very much for the clarification.

Do you have an example input file for the WaveMod=7 option? I'd really like to try it out.

Thanks, Sam

Sam-Ramsahoye avatar Mar 09 '23 16:03 Sam-Ramsahoye

@Sam-Ramsahoye I've attached below an example wave-component input file for WaveMod=7. To run it with SeaState, set the following in the WAVES section of the SeaState input file:

  1. WaveMod = 7
  2. WaveTMax = 1000
  3. WvKinFile = example.txt
  4. WaveStMod can be set as needed.
  5. All other entries under WAVES are ignored when WaveMod=7.

example.txt

luwang00 avatar Mar 10 '23 18:03 luwang00

@luwang00 Thanks very much!

Sam-Ramsahoye avatar Mar 13 '23 12:03 Sam-Ramsahoye

So the regression tests require too much memory for GitHub actions. Since these currently work on standalone systems, we will merge now and do a quick follow-up PR to reduce the memory requirements for all these cases.

andrew-platt avatar May 31 '23 21:05 andrew-platt