ROSCO-MATLAB Implementation

This forum if for discussing controls. Questions about how to implement controls in FAST are more appropriate to the CAE Tools forum.

Moderator: Bonnie.Jonkman

Bartosz.Stachowicz
Posts: 48
Joined: Wed Jul 29, 2020 4:37 am
Organization: Politechnika Gdanska
Location: Gdansk

Re: ROSCO-MATLAB Implementation

Postby Bartosz.Stachowicz » Thu Apr 22, 2021 1:22 pm

Dear Nikhar Abbas,

In the paper you shared in this thread replying to KumaraRaja.Eedara you are mentioning the minimum rotor speed constraint. How is it estimated/derived for the 15MW NREL turbine?

BS

Nikhar.Abbas
Posts: 31
Joined: Wed Apr 29, 2020 7:11 pm
Organization: National Renewable Energy Lab
Location: Boulder, CO

Re: ROSCO-MATLAB Implementation

Postby Nikhar.Abbas » Fri Apr 23, 2021 10:29 am

Hi Bartosz,

The minimum rotor speed is simply from the definition of the IEA 15MW wind turbine here:
https://www.nrel.gov/docs/fy20osti/75698.pdf

Nikhar

Shubham.Baisthakur
Posts: 13
Joined: Thu Jan 07, 2021 11:40 pm
Organization: Trinity College Dublin
Location: Ireland

Re: ROSCO-MATLAB Implementation

Postby Shubham.Baisthakur » Tue Apr 27, 2021 3:56 pm

Hello Nikhar,
What is the main purpose of the DISCON.dll and DISCON.f90 file? Are these files only used to communicate with the openFAST? Also, what is the significance of the avrSWAP variable, which is repeatedly used in the ROSCO source code?

While implementing ROSCO in MATLAB, is it possible to bypass these files? Since I have an indigenously developed wind turbine model, I won't have to interface the controller with openFAST.

Thanks,
Shubham

Nikhar.Abbas
Posts: 31
Joined: Wed Apr 29, 2020 7:11 pm
Organization: National Renewable Energy Lab
Location: Boulder, CO

Re: ROSCO-MATLAB Implementation

Postby Nikhar.Abbas » Wed Apr 28, 2021 9:46 am

Hi Shubham,
DISCON.dll is the compiled binary file that OpenFAST (or any other simulator) calls to run ROSCO. DISCON.f90 is the "top-level" script in ROSCO that contains the primary DISCON routine. This routine calls all of the internal submodules, functions, etc., that make ROSCO run as it does. Finally, the avrSWAP is an array that is passed between ROSCO and the calling wind turbine simulator (e.g. OpenFAST) containing all of the controller's inputs/outputs. The structure of the avrSWAP is "bladed-style" - meaning that each entry in the array is consistent with DNV-GL Bladed's array structure (e.g., avrSWAP(2) contains the time variable, always).

For your purposes, I don't think any of these are particularly necessary. You might want to to draw from the structure of DISCON.f90 to understand the order of calls that happens in ROSCO, though.

Cheers,
Nikhar

Shubham.Baisthakur
Posts: 13
Joined: Thu Jan 07, 2021 11:40 pm
Organization: Trinity College Dublin
Location: Ireland

Re: ROSCO-MATLAB Implementation

Postby Shubham.Baisthakur » Wed Apr 28, 2021 10:26 am

Hello Nikhar,
Thanks for the reply. Although, there's one more issue.
A part of the ComputeVariablesSetPoint subroutine reads

Code: Select all

        ! ----- Torque controller reference errors -----
        ! Define VS reference generator speed [rad/s]
        IF ((CntrPar%VS_ControlMode == 2) .OR. (CntrPar%VS_ControlMode == 3)) THEN
            VS_RefSpd = (CntrPar%VS_TSRopt * LocalVar%We_Vw_F / CntrPar%WE_BladeRadius) * CntrPar%WE_GearboxRatio
            VS_RefSpd = saturate(VS_RefSpd,CntrPar%VS_MinOMSpd, CntrPar%VS_RefSpd)
        ELSE
            VS_RefSpd = CntrPar%VS_RefSpd
        ENDIF

However, as per the DISCON.IN file, VS_ControlMode can never have a value equal to 3.

Code: Select all

1                   ! VS_ControlMode   - Generator torque control mode in above rated conditions {0: constant torque, 1: constant power, 2: TSR tracking PI control}


Is this a bug or serves some other purpose?

Thanks,
Shubham

Nikhar.Abbas
Posts: 31
Joined: Wed Apr 29, 2020 7:11 pm
Organization: National Renewable Energy Lab
Location: Boulder, CO

Re: ROSCO-MATLAB Implementation

Postby Nikhar.Abbas » Wed Apr 28, 2021 10:39 am

Hi Shubham,

It looks like the descriptors in that DISCON.IN file are out of date - sorry about that. `VS_ControlMode = 3` corresponds to TSR tracking control below rated, and constant power above rated.

The most recent descriptions can be found here:
https://rosco-toolbox.readthedocs.io/en ... on-in-file

The details of this are discussed in the WES pre-print about ROSCO here:
https://wes.copernicus.org/preprints/wes-2021-19/

Cheers,
Nikhar

Shubham.Baisthakur
Posts: 13
Joined: Thu Jan 07, 2021 11:40 pm
Organization: Trinity College Dublin
Location: Ireland

Re: ROSCO-MATLAB Implementation

Postby Shubham.Baisthakur » Wed Apr 28, 2021 10:43 am

Hello Nikhar,
Thanks for the prompt reply. I really appreciate all the help.

Cheers,
Shubham

Shubham.Baisthakur
Posts: 13
Joined: Thu Jan 07, 2021 11:40 pm
Organization: Trinity College Dublin
Location: Ireland

Re: ROSCO-MATLAB Implementation

Postby Shubham.Baisthakur » Sat May 01, 2021 5:29 am

Hello Nikhar,
I have attached the code for the PIController function.

Code: Select all

    REAL FUNCTION PIController(error, kp, ki, minValue, maxValue, DT, I0, reset, inst)
    ! PI controller, with output saturation

        IMPLICIT NONE
        ! Allocate Inputs
        REAL(8), INTENT(IN)         :: error
        REAL(8), INTENT(IN)         :: kp
        REAL(8), INTENT(IN)         :: ki
        REAL(8), INTENT(IN)         :: minValue
        REAL(8), INTENT(IN)         :: maxValue
        REAL(8), INTENT(IN)         :: DT
        INTEGER(4), INTENT(INOUT)   :: inst
        REAL(8), INTENT(IN)         :: I0
        LOGICAL, INTENT(IN)         :: reset     
        ! Allocate local variables
        INTEGER(4)                      :: i                                            ! Counter for making arrays
        REAL(8)                         :: PTerm                                        ! Proportional term
        REAL(8), DIMENSION(99), SAVE    :: ITerm = (/ (real(9999.9), i = 1,99) /)       ! Integral term, current.
        REAL(8), DIMENSION(99), SAVE    :: ITermLast = (/ (real(9999.9), i = 1,99) /)   ! Integral term, the last time this controller was called. Supports 99 separate instances.
        INTEGER(4), DIMENSION(99), SAVE :: FirstCall = (/ (1, i=1,99) /)                ! First call of this function?
       
        ! Initialize persistent variables/arrays, and set initial condition for integrator term
        IF ((FirstCall(inst) == 1) .OR. reset) THEN
            ITerm(inst) = I0
            ITermLast(inst) = I0
           
            FirstCall(inst) = 0
            PIController = I0
        ELSE
            PTerm = kp*error
            ITerm(inst) = ITerm(inst) + DT*ki*error
            ITerm(inst) = saturate(ITerm(inst), minValue, maxValue)
            PIController = saturate(PTerm + ITerm(inst), minValue, maxValue)
       
            ITermLast(inst) = ITerm(inst)
        END IF
        inst = inst + 1
       
    END FUNCTION PIController


As per my understanding, as all the values of the FirstCall array are initialized as 1, the control will never transfer to the second part of the loop (the else part). Is this right, or I am missing some point?

Thanks,
Shubham

Nikhar.Abbas
Posts: 31
Joined: Wed Apr 29, 2020 7:11 pm
Organization: National Renewable Energy Lab
Location: Boulder, CO

Re: ROSCO-MATLAB Implementation

Postby Nikhar.Abbas » Mon May 03, 2021 2:52 pm

Hi Shubham,

FirstCall(inst) is set to zero in the first part of the for loop. Because of this, all subsequent calls of the function will go to the second part of the loop unless reset=True.

Nikhar

Shubham.Baisthakur
Posts: 13
Joined: Thu Jan 07, 2021 11:40 pm
Organization: Trinity College Dublin
Location: Ireland

Re: ROSCO-MATLAB Implementation

Postby Shubham.Baisthakur » Mon May 03, 2021 3:45 pm

Hello Nikhar,
Correct me if I am wrong. Here inst is used to access the value of a particular cell of the FirstCall array. Since towards the end of the subroutine, the inst variable is modified as inst = inst+1, so on every to call to the subroutine the inst value will be different. So effectively, everytime we will be checking a different location of the FirstCall array with 1.

Thanks,
Shubham

Nikhar.Abbas
Posts: 31
Joined: Wed Apr 29, 2020 7:11 pm
Organization: National Renewable Energy Lab
Location: Boulder, CO

Re: ROSCO-MATLAB Implementation

Postby Nikhar.Abbas » Tue May 04, 2021 9:54 am

Hi Shubham,
Each time the controller is called, the SetParameters subroutine is subsequently called. This happens here:
https://github.com/NREL/ROSCO/blob/e53f ... ON.F90#L64

Then, in the SetParameters subroutine, the filter and controller instances are re-set to 1:
https://github.com/NREL/ROSCO/blob/e53f ... s.f90#L512

So, basically, each time the DISCON routine is called, the instance variable is reset to one. This effectively "counts" the order at which the filters, pi-controllers, etc. are called. So, in the PIController function, the `FirstCall` gets filled as many times as the PIController function is called, with each entry corresponding to the order in which it is called. Hopefully this makes sense, it is a little confusing.

This behavior exists because of the way the memory needs to be stored for FORTRAN implementation (and could probably be done in a cleaner way). For your MATLAB implementation, though, I don't think you should do this, as function calls and full routines do not allocate memory in MATLAB in the way that FORTRAN does.

Cheers,
Nikhar

Shubham.Baisthakur
Posts: 13
Joined: Thu Jan 07, 2021 11:40 pm
Organization: Trinity College Dublin
Location: Ireland

Re: ROSCO-MATLAB Implementation

Postby Shubham.Baisthakur » Mon May 31, 2021 7:41 am

Hi Nikhar,
How to generate the performance file (Cp_Ct_Cq.txt) for the NREL 5MW turbine with the Monopile foundation? Can you please share the standard file, if you have already generated it?

Thanks,
Shubham

Nikhar.Abbas
Posts: 31
Joined: Wed Apr 29, 2020 7:11 pm
Organization: National Renewable Energy Lab
Location: Boulder, CO

Re: ROSCO-MATLAB Implementation

Postby Nikhar.Abbas » Tue Jun 01, 2021 10:39 am

Hi Shubham,
The Cp_Ct_Cq.txt file can be generated using CCBlade, as is shown in example_03.py in the ROSCO toolbox:
https://github.com/NREL/ROSCO_toolbox/b ... mple_03.py

For the NREL5MW rotor, the file can be found in the ROSCO toolbox here:
https://github.com/NREL/ROSCO_toolbox/b ... REL5MW.txt

It is no different for the NREL 5MW turbine on the Monopile foundation, as the rotor does not change between the two turbines.

Cheers,
Nikhar

Shubham.Baisthakur
Posts: 13
Joined: Thu Jan 07, 2021 11:40 pm
Organization: Trinity College Dublin
Location: Ireland

Re: ROSCO-MATLAB Implementation

Postby Shubham.Baisthakur » Tue Jun 01, 2021 1:59 pm

Thanks for the information, Nikhar. This is exactly what I was looking for.


Return to “Controls”

Who is online

Users browsing this forum: No registered users and 1 guest