How to add additional wave gauges to OpenFAST output

Hello,

I am looking to add the additional output of more than 9 wave gauges. I have tried modifiying the source code of SeaState but when examining the outputs, I get an “Invalid” unit and all zeros for the values, however, it does output the “Wave10Elev” just all zeros.

I have made modifications in “SeaState_output” such as
INTEGER(IntKi), PARAMETER :: Wave9Elev = 9
INTEGER(IntKi), PARAMETER :: Wave10Elev = 10

INTEGER(IntKi), PARAMETER :: Wave9Elv1 = 19
INTEGER(IntKi), PARAMETER :: Wave10Elv1 = 20

INTEGER(IntKi), PARAMETER :: Wave9Elv2 = 29
INTEGER(IntKi), PARAMETER :: Wave10Elv2 = 30

INTEGER(IntKi), PARAMETER, PUBLIC :: MaxOutPts = 120

INTEGER, PARAMETER :: WaveElevi(10) = (/Wave1Elev,Wave2Elev,Wave3Elev,Wave4Elev,Wave5Elev,Wave6Elev,Wave7Elev,Wave8Elev,Wave9Elev,Wave10Elev/)
INTEGER, PARAMETER :: WaveElevi1(10) = (/Wave1Elv1,Wave2Elv1,Wave3Elv1,Wave4Elv1,Wave5Elv1,Wave6Elv1,Wave7Elv1,Wave8Elv1,Wave9Elv1,Wave10Elv1/)
INTEGER, PARAMETER :: WaveElevi2(10) = (/Wave1Elv2,Wave2Elv2,Wave3Elv2,Wave4Elv2,Wave5Elv2,Wave6Elv2,Wave7Elv2,Wave8Elv2,Wave9Elv2,Wave10Elv2/)

And modifying “ValidParamAry(120)”, “ParamIndxAry(120)”, “ParamUnitsAry(120)” to include the new variables.

I also modified the SeaState_Input to no longer yield an error if NWaveElev > 9

I would appreciate any help on this. I am assuming there is another location where I need to edit. I assumed it would loop through NWaveElev and calculate the wave elevations of all user-defined locations.

Thank you,
Jacob Fontaine

I also edited:

do I=p%NWaveElev+1,10
      InvalidOutput(WaveElevi(I)) = .true.
      InvalidOutput(WaveElevi1(I))= .true.
      InvalidOutput(WaveElevi2(I))= .true.
   end do

Hi Jacob,

It looks like you got most of the changes required. Could you double check whether SeaState is actually evaluating the wave elevation at the 10th probe location in SeaSt_CalcOutput in SeaState.f90? You can just add a print command in that subroutine to see if you are getting numbers for i=10.

Best,
Lu

Hi Lu,

Thank you for your reply.

I modified the SeaSt_CalcOutput

DO i = 1, p%NWaveElev
         positionXY = (/p%WaveElevxi(i),p%WaveElevyi(i)/)
         WaveElev1(i) = WaveField_GetNodeWaveElev1( p%WaveField, m%WaveField_m, Time, positionXY, ErrStat2, ErrMsg2 )
           CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName )
         WaveElev2(i) = WaveField_GetNodeWaveElev2( p%WaveField, m%WaveField_m, Time, positionXY, ErrStat2, ErrMsg2 )
           CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName )
         WaveElev(i)  = WaveElev1(i) + WaveElev2(i)
         ! Print out the 10th probe’s elevation:
         IF (i == 10) THEN
           WRITE(*,'(A,F8.3,A,1P,E12.4)') 'SeaSt_CalcOutput @ Time=', Time, &
             ': WaveElev(10)=', WaveElev(i)
         END IF
      END DO

In the terminal while running OpenFAST I get:

SeaSt_CalcOutput @ Time=   0.200: WaveElev(10)= -1.7404E+00
SeaSt_CalcOutput @ Time=   0.400: WaveElev(10)= -1.6999E+00
SeaSt_CalcOutput @ Time=   0.600: WaveElev(10)= -1.6600E+00
SeaSt_CalcOutput @ Time=   0.800: WaveElev(10)= -1.6339E+00
SeaSt_CalcOutput @ Time=   1.000: WaveElev(10)= -1.6334E+00
SeaSt_CalcOutput @ Time=   1.200: WaveElev(10)= -1.6678E+00
SeaSt_CalcOutput @ Time=   1.400: WaveElev(10)= -1.7436E+00
SeaSt_CalcOutput @ Time=   1.600: WaveElev(10)= -1.8641E+00

However, when examining the .out file, I get:

Wave10Elev
INVALID
 0.000E+00
 0.000E+00
 0.000E+00
 0.000E+00
 0.000E+00
 0.000E+00
 0.000E+00

So it is calculated what the wave elevation should be, but just having issues with saving to the .out file? Perhaps there is some small error in the edits I have made prior, so I will double check.

Cheers,
Jacob

Hi Jacob,

That’s a good sign. If I’m not mistaken, it’s only a few more steps from CalcOutput to the output file. If you could follow the data a bit, it should be relatively easy to find out where it got lost along the way.

It’s interesting that the channel is still labeled as INVALID. Maybe it’s worth double checking your modification to the following patch of code?

do I=p%NWaveElev+1,10
InvalidOutput(WaveElevi(I)) = .true.
InvalidOutput(WaveElevi1(I))= .true.
InvalidOutput(WaveElevi2(I))= .true.
end do

Good luck!

Best,
Lu

Hi Lu,

I figured it out, it was this comment that gave me the answer " CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(120) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically"

Before I had:

CHARACTER(OutStrLenM1), PARAMETER  :: ValidParamAry(120) =  (/  &   ! This lists the names of the allowed parameters, which must be sorted alphabetically
                               "FACC1XI   ","FACC1YI   ","FACC1ZI   ","FACC2XI   ","FACC2YI   ","FACC2ZI   ","FACC3XI   ", &
                               "FACC3YI   ","FACC3ZI   ","FACC4XI   ","FACC4YI   ","FACC4ZI   ","FACC5XI   ","FACC5YI   ", &
                               "FACC5ZI   ","FACC6XI   ","FACC6YI   ","FACC6ZI   ","FACC7XI   ","FACC7YI   ","FACC7ZI   ", &
                               "FACC8XI   ","FACC8YI   ","FACC8ZI   ","FACC9XI   ","FACC9YI   ","FACC9ZI   ","FACCMCF1XI", &
                               "FACCMCF1YI","FACCMCF1ZI","FACCMCF2XI","FACCMCF2YI","FACCMCF2ZI","FACCMCF3XI","FACCMCF3YI", &
                               "FACCMCF3ZI","FACCMCF4XI","FACCMCF4YI","FACCMCF4ZI","FACCMCF5XI","FACCMCF5YI","FACCMCF5ZI", &
                               "FACCMCF6XI","FACCMCF6YI","FACCMCF6ZI","FACCMCF7XI","FACCMCF7YI","FACCMCF7ZI","FACCMCF8XI", &
                               "FACCMCF8YI","FACCMCF8ZI","FACCMCF9XI","FACCMCF9YI","FACCMCF9ZI","FDYNP1    ","FDYNP2    ", &
                               "FDYNP3    ","FDYNP4    ","FDYNP5    ","FDYNP6    ","FDYNP7    ","FDYNP8    ","FDYNP9    ", &
                               "FVEL1XI   ","FVEL1YI   ","FVEL1ZI   ","FVEL2XI   ","FVEL2YI   ","FVEL2ZI   ","FVEL3XI   ", &
                               "FVEL3YI   ","FVEL3ZI   ","FVEL4XI   ","FVEL4YI   ","FVEL4ZI   ","FVEL5XI   ","FVEL5YI   ", &
                               "FVEL5ZI   ","FVEL6XI   ","FVEL6YI   ","FVEL6ZI   ","FVEL7XI   ","FVEL7YI   ","FVEL7ZI   ", &
                               "FVEL8XI   ","FVEL8YI   ","FVEL8ZI   ","FVEL9XI   ","FVEL9YI   ","FVEL9ZI   ","WAVE1ELEV ", &
                               "WAVE1ELV1 ","WAVE1ELV2 ","WAVE2ELEV ","WAVE2ELV1 ","WAVE2ELV2 ","WAVE3ELEV ","WAVE3ELV1 ", &
                               "WAVE3ELV2 ","WAVE4ELEV ","WAVE4ELV1 ","WAVE4ELV2 ","WAVE5ELEV ","WAVE5ELV1 ","WAVE5ELV2 ", &
                               "WAVE6ELEV ","WAVE6ELV1 ","WAVE6ELV2 ","WAVE7ELEV ","WAVE7ELV1 ","WAVE7ELV2 ","WAVE8ELEV ", &
                               "WAVE8ELV1 ","WAVE8ELV2 ","WAVE9ELEV ","WAVE9ELV1 ","WAVE9ELV2 ", "WAVE10ELEV","WAVE10ELV1","WAVE10ELV2"/)
INTEGER(IntKi), PARAMETER :: ParamIndxAry(120) =  (/ &                            ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:)
                                   FAcc1xi ,    FAcc1yi ,    FAcc1zi ,    FAcc2xi ,    FAcc2yi ,    FAcc2zi ,    FAcc3xi , &
                                   FAcc3yi ,    FAcc3zi ,    FAcc4xi ,    FAcc4yi ,    FAcc4zi ,    FAcc5xi ,    FAcc5yi , &
                                   FAcc5zi ,    FAcc6xi ,    FAcc6yi ,    FAcc6zi ,    FAcc7xi ,    FAcc7yi ,    FAcc7zi , &
                                   FAcc8xi ,    FAcc8yi ,    FAcc8zi ,    FAcc9xi ,    FAcc9yi ,    FAcc9zi , FAccMCF1xi , &
                                FAccMCF1yi , FAccMCF1zi , FAccMCF2xi , FAccMCF2yi , FAccMCF2zi , FAccMCF3xi , FAccMCF3yi , &
                                FAccMCF3zi , FAccMCF4xi , FAccMCF4yi , FAccMCF4zi , FAccMCF5xi , FAccMCF5yi , FAccMCF5zi , &
                                FAccMCF6xi , FAccMCF6yi , FAccMCF6zi , FAccMCF7xi , FAccMCF7yi , FAccMCF7zi , FAccMCF8xi , &
                                FAccMCF8yi , FAccMCF8zi , FAccMCF9xi , FAccMCF9yi , FAccMCF9zi ,     FDynP1 ,     FDynP2 , &
                                    FDynP3 ,     FDynP4 ,     FDynP5 ,     FDynP6 ,     FDynP7 ,     FDynP8 ,     FDynP9 , &
                                   FVel1xi ,    FVel1yi ,    FVel1zi ,    FVel2xi ,    FVel2yi ,    FVel2zi ,    FVel3xi , &
                                   FVel3yi ,    FVel3zi ,    FVel4xi ,    FVel4yi ,    FVel4zi ,    FVel5xi ,    FVel5yi , &
                                   FVel5zi ,    FVel6xi ,    FVel6yi ,    FVel6zi ,    FVel7xi ,    FVel7yi ,    FVel7zi , &
                                   FVel8xi ,    FVel8yi ,    FVel8zi ,    FVel9xi ,    FVel9yi ,    FVel9zi ,  Wave1Elev , &
                                 Wave1Elv1 ,  Wave1Elv2 ,  Wave2Elev ,  Wave2Elv1 ,  Wave2Elv2 ,  Wave3Elev ,  Wave3Elv1 , &
                                 Wave3Elv2 ,  Wave4Elev ,  Wave4Elv1 ,  Wave4Elv2 ,  Wave5Elev ,  Wave5Elv1 ,  Wave5Elv2 , &
                                 Wave6Elev ,  Wave6Elv1 ,  Wave6Elv2 ,  Wave7Elev ,  Wave7Elv1 ,  Wave7Elv2 ,  Wave8Elev , &
                                 Wave8Elv1 ,  Wave8Elv2 ,  Wave9Elev ,  Wave9Elv1 ,  Wave9Elv2,  Wave10Elev ,  Wave10Elv1 ,  Wave10Elv2 /)

But because it should be sorted alphabetically (alphanumerically?) this new 10th wave probe should actually come before the first wave probe, so these two variables should be:

   CHARACTER(OutStrLenM1), PARAMETER  :: ValidParamAry(120) =  (/  &   ! This lists the names of the allowed parameters, which must be sorted alphabetically
                               "FACC1XI   ","FACC1YI   ","FACC1ZI   ","FACC2XI   ","FACC2YI   ","FACC2ZI   ","FACC3XI   ", &
                               "FACC3YI   ","FACC3ZI   ","FACC4XI   ","FACC4YI   ","FACC4ZI   ","FACC5XI   ","FACC5YI   ", &
                               "FACC5ZI   ","FACC6XI   ","FACC6YI   ","FACC6ZI   ","FACC7XI   ","FACC7YI   ","FACC7ZI   ", &
                               "FACC8XI   ","FACC8YI   ","FACC8ZI   ","FACC9XI   ","FACC9YI   ","FACC9ZI   ","FACCMCF1XI", &
                               "FACCMCF1YI","FACCMCF1ZI","FACCMCF2XI","FACCMCF2YI","FACCMCF2ZI","FACCMCF3XI","FACCMCF3YI", &
                               "FACCMCF3ZI","FACCMCF4XI","FACCMCF4YI","FACCMCF4ZI","FACCMCF5XI","FACCMCF5YI","FACCMCF5ZI", &
                               "FACCMCF6XI","FACCMCF6YI","FACCMCF6ZI","FACCMCF7XI","FACCMCF7YI","FACCMCF7ZI","FACCMCF8XI", &
                               "FACCMCF8YI","FACCMCF8ZI","FACCMCF9XI","FACCMCF9YI","FACCMCF9ZI","FDYNP1    ","FDYNP2    ", &
                               "FDYNP3    ","FDYNP4    ","FDYNP5    ","FDYNP6    ","FDYNP7    ","FDYNP8    ","FDYNP9    ", &
                               "FVEL1XI   ","FVEL1YI   ","FVEL1ZI   ","FVEL2XI   ","FVEL2YI   ","FVEL2ZI   ","FVEL3XI   ", &
                               "FVEL3YI   ","FVEL3ZI   ","FVEL4XI   ","FVEL4YI   ","FVEL4ZI   ","FVEL5XI   ","FVEL5YI   ", &
                               "FVEL5ZI   ","FVEL6XI   ","FVEL6YI   ","FVEL6ZI   ","FVEL7XI   ","FVEL7YI   ","FVEL7ZI   ", &
                               "FVEL8XI   ","FVEL8YI   ","FVEL8ZI   ","FVEL9XI   ","FVEL9YI   ","FVEL9ZI   ","WAVE10ELEV","WAVE10ELV1","WAVE10ELV2","WAVE1ELEV ", &
                               "WAVE1ELV1 ","WAVE1ELV2 ","WAVE2ELEV ","WAVE2ELV1 ","WAVE2ELV2 ","WAVE3ELEV ","WAVE3ELV1 ", &
                               "WAVE3ELV2 ","WAVE4ELEV ","WAVE4ELV1 ","WAVE4ELV2 ","WAVE5ELEV ","WAVE5ELV1 ","WAVE5ELV2 ", &
                               "WAVE6ELEV ","WAVE6ELV1 ","WAVE6ELV2 ","WAVE7ELEV ","WAVE7ELV1 ","WAVE7ELV2 ","WAVE8ELEV ", &
                               "WAVE8ELV1 ","WAVE8ELV2 ","WAVE9ELEV ","WAVE9ELV1 ","WAVE9ELV2 "/)
   INTEGER(IntKi), PARAMETER :: ParamIndxAry(120) =  (/ &                            ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:)
                                   FAcc1xi ,    FAcc1yi ,    FAcc1zi ,    FAcc2xi ,    FAcc2yi ,    FAcc2zi ,    FAcc3xi , &
                                   FAcc3yi ,    FAcc3zi ,    FAcc4xi ,    FAcc4yi ,    FAcc4zi ,    FAcc5xi ,    FAcc5yi , &
                                   FAcc5zi ,    FAcc6xi ,    FAcc6yi ,    FAcc6zi ,    FAcc7xi ,    FAcc7yi ,    FAcc7zi , &
                                   FAcc8xi ,    FAcc8yi ,    FAcc8zi ,    FAcc9xi ,    FAcc9yi ,    FAcc9zi , FAccMCF1xi , &
                                FAccMCF1yi , FAccMCF1zi , FAccMCF2xi , FAccMCF2yi , FAccMCF2zi , FAccMCF3xi , FAccMCF3yi , &
                                FAccMCF3zi , FAccMCF4xi , FAccMCF4yi , FAccMCF4zi , FAccMCF5xi , FAccMCF5yi , FAccMCF5zi , &
                                FAccMCF6xi , FAccMCF6yi , FAccMCF6zi , FAccMCF7xi , FAccMCF7yi , FAccMCF7zi , FAccMCF8xi , &
                                FAccMCF8yi , FAccMCF8zi , FAccMCF9xi , FAccMCF9yi , FAccMCF9zi ,     FDynP1 ,     FDynP2 , &
                                    FDynP3 ,     FDynP4 ,     FDynP5 ,     FDynP6 ,     FDynP7 ,     FDynP8 ,     FDynP9 , &
                                   FVel1xi ,    FVel1yi ,    FVel1zi ,    FVel2xi ,    FVel2yi ,    FVel2zi ,    FVel3xi , &
                                   FVel3yi ,    FVel3zi ,    FVel4xi ,    FVel4yi ,    FVel4zi ,    FVel5xi ,    FVel5yi , &
                                   FVel5zi ,    FVel6xi ,    FVel6yi ,    FVel6zi ,    FVel7xi ,    FVel7yi ,    FVel7zi , &
                                   FVel8xi ,    FVel8yi ,    FVel8zi ,    FVel9xi ,    FVel9yi ,    FVel9zi ,  Wave10Elev ,  Wave10Elv1 ,  Wave10Elv2 , Wave1Elev , &
                                 Wave1Elv1 ,  Wave1Elv2 ,  Wave2Elev ,  Wave2Elv1 ,  Wave2Elv2 ,  Wave3Elev ,  Wave3Elv1 , &
                                 Wave3Elv2 ,  Wave4Elev ,  Wave4Elv1 ,  Wave4Elv2 ,  Wave5Elev ,  Wave5Elv1 ,  Wave5Elv2 , &
                                 Wave6Elev ,  Wave6Elv1 ,  Wave6Elv2 ,  Wave7Elev ,  Wave7Elv1 ,  Wave7Elv2 ,  Wave8Elev , &
                                 Wave8Elv1 ,  Wave8Elv2 ,  Wave9Elev ,  Wave9Elv1 ,  Wave9Elv2 /)

Hope this helps anyone else out in the future. Thanks for your help, Lu!

Best,
Jacob

Good catch. Glad to hear it’s working now.

I just want to mention that the Fortran code defining the output channels are usually automatically generated. This entails updating the definition of the output channels in this file from the OpenFAST repo:

and run the MATLAB script below to generate the Fortran code.

This is convenient for adding a large number of output channels.

That will definitely be helpful. Thanks!

-Jacob