Dynamically imposing forces on a floating platform

Hello!

I am trying to run a simulation for a floating wind turbine. Now, I have the force applied to the platform as a list of parameters at each point in time, written in a file:

!Loading and Wave Elevation

!Dimension: 1 time column - 6 force columns

0.000 0.000 0.000 0.000 0.000 0.000 0.000

0.100 0.000 0.000 0.000 0.000 62830199416763.000 0.000

0.200 0.000 0.000 0.000 0.000 125650477216687.000 0.000

… (more time steps follow)

Is there a way to impose the forces dynamically, during the execution of the program, with live data taken from a sensor on the platform? In other words, can I increase the number of lines while OpenFAST is running, instead of loading them all in a pre-written file?

Dear @Tudor.Istrate,

The StC_DOF_MODE = 4 option of the Structural Control (StC) submodel of ServoDyn supports user-prescribed load (force, moment) time series at arbitrary locations in the blades, nacelle, tower, and substructure of an OpenFAST model. However, these loads must be pre-computed and fully prescribed at model initialization.

That said, the StC_DOF_MODE = 5 option allows your DISCON controller to specify the loads directly through the controller library, which you could compute based on feedback from other response signals. This option would require customization of your DISCON controller.

Best regards,

1 Like

Dear @Jason.Jonkman,

Thank you for your answer!

I tried with StC_DOF_MODE = 4, and everything works fine.
Now, I am trying to go with StC_DOF_MODE = 5, but I am unsure how to make the response real-time.

I managed to replicate the results from StC_DOF_MODE = 4 by modifying the required parameters for StC_DOF_MODE = 5 (like PrescribedForcesCoord). However, this is still just loading a pre-written file.

I also tried to change this part of the DISCON.IN file:

!------- External Controller Interface -----------------------------------------------------
“unused” ! DLL_FileName - Name/location of the dynamic library in the Bladed-DLL format
“unused” ! DLL_InFile - Name of input file sent to the DLL (-)
“DISCON” ! DLL_ProcName - Name of procedure in DLL to be called (-)

However, I still don’t know how to make it react to changes or how to write new lines in real time.

Am I getting anything wrong?

Best regards,
Tudor Istrate

Dear @Tudor.Istrate,

The StC_DOF_MODE = 5 option of StC requires that you customize your DISCON controller to specify the StC forces, which can be based on sensor feedback that is already sent to the DISCON controller. Are you already using a DISCON controller, such as ROSCO, the NREL 5-MW baseline controller, or your own controller? Have you tried to modify this controller to specify the StC forces?

Best regards,

Dear @Jason.Jonkman,

The controller I am using is ROSCO, which I compile using CMake.

Inside the controller, in the file ExtControl.f90, I believe that I have to modify this part of the initialization:

    ! Initialize strings for external controller
    aviFAIL     = 0
    avcMSG     = TRANSFER( C_NULL_CHAR,                            avcMSG     )
    avcOUTNAME = TRANSFER( TRIM(ExtRootName)//C_NULL_CHAR,   avcOUTNAME )
    accINFILE  = TRANSFER( TRIM(CntrPar%DLL_InFile)//C_NULL_CHAR, accINFILE  )

Also, I am not sure how to integrate the Extended Bladed Interface (4.14.2. Extended Bladed Interface — OpenFAST v4.1.1 documentation) with the ServoDyn (I am interested in Sensor inputs - Non LIDAR).

Am I on the right path?

Best regards,
Tudor Istrate

Dear @Tudor.Istrate,

Within the ROSCO source code, you shouldn’t need to change aviFAIL, avcMSG, avcOUTNAME, accINFILE, etc. Rather, using the Extended Bladed Interface only requires using (for inputs to the controller) or setting (for outputs from the controller) elements in the avrSWAP array that are part of the interface, e.g.,:

avrSWAP(2816) = StC_Force_X for group 1
avrSWAP(2836) = StC_Force_X for group 2

etc.

Best regards,

Dear @Jason.Jonkman,

Thank you very much! Based on your advice, this is what I did, based on the ROSCO controller code (for simplicity, I only focused on the Y direction):

In ROSCO_Types.f90, I added

REAL(ReKi) :: StC_Force_Y ! Structural control force in Y direction [N]

in the LocalVariables

In ReadSetParameters.f90, I added LocalVar%StC_Force_Y like this:

SUBROUTINE ReadAvrSWAP(avrSWAP, LocalVar, CntrPar, ErrVar)
    USE ROSCO_Types, ONLY : LocalVariables

    REAL(ReKi), INTENT(INOUT) :: avrSWAP(*)   ! The swap array, used to pass data to, and receive data from, the DLL controller.
    TYPE(LocalVariables), INTENT(INOUT) :: LocalVar
    TYPE(ControlParameters), INTENT(IN) :: CntrPar
    TYPE(ErrorVariables), INTENT(INOUT) :: ErrVar

    ! Allocate Variables:
    INTEGER(IntKi)                                  :: K         ! Index used for looping through blades.

    ! Load variables from calling program (See Appendix A of Bladed User's Guide):
    ! <Other variables>

    if (CntrPar%Ext_Interface > 0) THEN ! Use extended bladed interface

        ! <Other variables>
        LocalVar%StC_Force_Y        = avrSWAP(2817)

    ENDIF

In Controllers.f90, I added this in the StructuralControl subroutine:

    IF (CntrPar%StC_Mode == 1) THEN
        ! User defined control, step example
        **LocalVar%StC_Input(1) = LocalVar%StC_Force_Y**

Now, the libdiscon.dll is created and the simulation that worked before still works fine. However, I am not sure how to test if the controller works for Dynamically-imposed data. What am I supposed to change in the OpenFAST code to feed sensor data to the simulation?

Best regards,
Tudor Istrate

Hi,

You’ll need to enable the structural control in ServoDyn and a structural control input to OpenFAST. Here is a script that will generate and change the necessary inputs: ROSCO/Examples/23_structural_control.py at main · NREL/ROSCO · GitHub

You can see the ROSCO LocalVariables in the .dbg2 file by setting LoggingLevel to 2 and you can see the values of the avrSWAP sent to OpenFAST in a .dbg3 file by setting LoggingLevel to 3.

I hope this helps.

Best, Dan

1 Like