OpenFAST: Linearization of NREL 5MW Onshore Turbine

Dear Mohamed,

What input perturbation have you applied to the linear model? Does the output from your linear model match that of the nonlinear model when no input perturbations to the linear model are specified, such that all states, state derivatives, and input perturbations are zero? This should be the case because the output perturbations from the linear model are then zero, and when the periodic OP is added the perturbation, the result should match the nonlinear model.

Best regards,

Dear Jason

Thank you for your explanation.
However, I found less deviation between the linearized model and the nonlinear model, although I set all perturbations to zeros. I add the periodic OPs that are retrieved from the linearization txt file (*.lin). The operating conditions of the nonlinear model are the same as the linearization point. Moreover, I made another simulation with accounting the periodicity of A, B, C, and D matrices, but, it gives me the same results.
The Blade RootMFlp1 VS Simulation time ( kN.m VS seconds).
The yellow line for the nonlinear model. The blue line for the linear model.

The connection diagram is shown below

Regards
M.Fekry

Dear Mohamed,

I still have not fully understood your Simulink model, but if the perturbations zero, then the linear and nonlinear model should agree if the OP from the linear model is derived from the conditions of the nonlinear model. Are you adding the periodic OP to perturbation (which are all zeros for now) when comparing the linear and nonlinear models, including inputs, states, and outputs?

Best regards,

Dear Dr. Jason

The connection diagram of the Simulink is shown below:


The A, B, C, D matrices are calculated by azimuth averaged in the non-rotating frame using MBC toolbox.
I added the operating states only as shown in the diagram above. All perturbations are zero. So, I can expect that the linear and nonlinear responses should be almost similar.
The tower fore-aft displacement and generator speed are agreed well in this case as shown below:
The generator speed rpm VS simulation time S.

The tower fore-aft displacement m VS simulation time S.

Continuing from above

However, The RootMFlp1, RootMFlp2, and RootMFlp3 have some deviation as shown below:
RootMFlp1 kN.m VS Time S


Also, I compared the corresponding states and I found them agreed well as shown below:
Blade flap-wise displacement m VS Time S

Blade flap-wise velocity m VS Time S

Are there any precautions should I take when dealing with C and D matrices?

Regards
M.Fekry

Dear Mohamed,

Are the perturbed outputs from the linear model (dy = Cdx + Ddu) all zero? From your Simulink model (Linear Model Diagram.jpg), it still looks like you are adding Xop to dx before multiplying it by C.

And where is the periodic OP of the blade flapwise outputs added to the perturbed outputs from the linear model, i.e., y = yop(Azimuth) + dy, after transformation of dy from the nonrotating to the rotating frame? Given that dy in your case should be zero (both rotating and nonrotating), the blade flapwise output from the linear model should just be the OP value, which should match the nonlinear model.

Best regards,

Dr. Jason
Thank you very much for your explanation
it works now.
RootMFlp1 kN.m VS Time S


Regards
M.Fekry

Dear Jonkman,
First, thank your help on topic “Obtaining sensitivity of aerodynamic power to rotor-collective blade pitch”, I have successfully gotten the data. My version is OPENFAST 2.4.
However, I have some questions.
First, what is the difference between AD RtAeroPwr and ED RotPwr. Maybe the GenEff 94.4 in ServoDyn? I compared them in linearization files. They are not the relation about GenEff.
Second, I looked at the sensitivity of them to rotor-collective blade pith. For ED RotPwr, it is -5.904E+03. For AD RtAeroPwr, it is -5.134E+07. Owing to their units, one is KW, the other is W, so I think the sensitivity of them should differ 10^3, but it is nearly 10^4 now. I am a litter puzzled.
Could you please help me?

Best regards!

Dear Dezheng.Zhu,

A similar question was asked and answered in the following forum topic: FAST_v8.15 OutList parameters - #2 by Jason.Jonkman.

If the generator or drivetrain DOFs are enabled in ElastoDyn, I would expect large differences in the derivatives calculated from a linearization analysis between RotPwr from ElastoDyn and RtAeroPwr from AeroDyn because the former is effected by rotor acceleration/deceleration while the later is not. If the generator and drivetrain DOFs are disabled in ElastoDyn, then I would expect quite good agreement between the two.

Best regards,

Dear @Jason.Jonkman,

I am trying to linearize the onshore 5 MW reference wind turbine at a steady wind speed of 23 m/s. I have been facing some problems and I followed a debbuging process, that I will be explaining, and I would be glad if you could share your thoughts about it. The configuration I have been using can be found in this link:

First, I was receving this warning message:

"_NREL5MW_LINParametric/../5MW_Baseline/NRELOffshrBsline5MW_AeroDyn_blade.dat".
 AD_Init:Init_BEMTmodule:BEMT_Init:UA_Init:UA_SetParameters:UA_ValidateAFI:File
 "_NREL5MW_LINParametric/../5MW_Baseline/Airfoils/DU40_A17.dat":
The separation function f_st does  not reach 1; max(f_st)=0.56668. 
Check the calculation or provide f_st in the input file.

I have seen a similar issue here, and the proposed solutions are to either change the airfoil data or use a different UAMod. I got this message for all the speeds (3-25 m/s), but at the end the of the simulation I was seeing “OpenFAST terminated normally”. However, it was only when the OP was 23 m/s or higher (24 or 25 m/s) that I couldn’t apply the MBC3 to the lin files. I was getting this error message in MATLAB:

Unable to perform assignment because the size of the left side is 438-by-438 and 
the size of the right side is 314-by-438.

I checked the issue and realized that the A matrix was being truncated at the 314 state variable (AD x4 blade 1, node 18, -), where it row was full of NaN. I first solved this issue by setting UAEndRad = 0.85 instead of 1, but I was still getting the first warning message.

Then, I started checking the results with UA_Mod = 5 and got the following warning messages:

AD_Init:Init_BEMTmodule:BEMT_Init:UA_Init:UA_SetParameters:UA_ValidateAFI:File
“_NREL5MW_LINParametric/../5MW_Baseline/Airfoils/DU40_A17.dat”:UA cutout parameter should be at a value where the separation function is 0; separation function is 1.29902E-02.

UA_SetParameters:UA_ValidateAFI:File
“_NREL5MW_LINParametric/../5MW_Baseline/Airfoils/DU35_A17.dat”:UA cutout parameter should be at a value where the separation function is 0; separation function is 1.43151E-02.

UA_SetParameters:UA_ValidateAFI:File
“_NREL5MW_LINParametric/../5MW_Baseline/Airfoils/DU30_A17.dat”:UA cutout parameter should be at a value where the separation function is 0; separation function is 1.06945E-03.

This warnings made me change the parameter UAStartRad, to avoid having UA on those airfoils. After trying some values I finally set it to 0.45. With UAStartRad = 0.45 I am able to run the linearizations without any of those warning messages and then I can apply the MBC3 without any problems.

SUMMARY:

UA_Mod = 4
UAStartRad = 0
UAEndRad = 1

“The separation function f_st does not reach 1” warning message and I can’t apply MBC3 because the matrix A gets truncated.

UA_Mod = 4
UAStartRad = 0
UAEndRad = 0.85

“The separation function f_st does not reach 1” warning message still appearing, but I can apply MBC3.

UA_Mod = 5
UAStartRad = 0
UAEndRad = 1

Second warning messages appeared, and I can apply MBC3.

UA_Mod = 5
UAStartRad = 0.45
UAEndRad = 1

No warning messages, and I can apply MBC3.

UA_Mod = 4
UAStartRad = 0.45
UAEndRad = 1

No warning messages, and I can’t apply MBC3 because the matrix A gets truncated.

Best regards,
Ignacio López

Dear @Ignacio.Lopez,

Can you clarify when you are receiving warning messages–is it during the steady-state trim solution or during the linearization process?

I see that your model is quite sophisticated, with many DOFs enabled in ElastoDyn, as well as dynamic inflow and UA enabled in AeroDyn. Do you have issues in a simpler model without aerodynamic states, e.g., DBEMT_Mod = -1 and UAMod = 0?

Best regards,

Dear @Jason.Jonkman,

I’m receiving the warning messages during the steady-state trim solution. They appear just after the simulation begins and it happens when Linearize = True and False

OpenFAST

 Copyright (C) 2026 National Renewable Energy Laboratory
 Copyright (C) 2026 Envision Energy USA LTD

 This program is licensed under Apache License Version 2.0 and comes with ABSOLUTELY NO WARRANTY.
 See the "LICENSE" file distributed with this software for details.
 **************************************************************************************************

 OpenFAST-v4.2.0
 Compile Info:
  - Compiler: GCC version 14.3.0
  - Architecture: 64 bit
  - Precision: single
  - OpenMP: No
  - Date: Jan 28 2026
  - Time: 21:04:40
 Execution Info:
  - Date: 06/08/2026
  - Time: 10:29:00+0200

 OpenFAST input file heading:
     FAST                   Certification - Test #18: NREL 5.0 MW Baseline Wind Turbine (Onshore)

  Running ElastoDyn.
 Nodal outputs section of ElastoDyn input file not found or improperly formatted.
  Running InflowWind.
  Running AeroDyn.
    AeroDyn: projMod: 2
    Projection: Polar, BEM: polar (3D)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 1, blade 1)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 2, blade 1)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 3, blade 1)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 4, blade 1)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 1, blade 2)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 2, blade 2)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 3, blade 2)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 4, blade 2)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 1, blade 3)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 2, blade 3)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 3, blade 3)
 Warning: Turning off Unsteady Aerodynamics because polar has constant data. (node 4, blade 3)
  Running ServoDyn.

 FAST_InitializeAll:ED_Init:ED_ReadInput:ReadBladeInputs:ReadBladeFile:The ElastoDyn Blade file,
 ws23_test/../5MW_Baseline/NRELOffshrBsline5MW_Blade.dat, DISTRIBUTED BLADE PROPERTIES table
 contains the PitchAxis column.  This column is unused and will be removed in future releases
 FAST_InitializeAll:AD_Init:ReadInputFiles:Blade1:ReadBladeInputs:BlCrvAng will be calculated and
 overwrite the values specified in blade file
 "ws23_test/../5MW_Baseline/NRELOffshrBsline5MW_AeroDyn_blade.dat".
 ReadInputFiles:Blade2:ReadBladeInputs:BlCrvAng will be calculated and overwrite the values
 specified in blade file "ws23_test/../5MW_Baseline/NRELOffshrBsline5MW_AeroDyn_blade.dat".
 ReadInputFiles:Blade3:ReadBladeInputs:BlCrvAng will be calculated and overwrite the values
 specified in blade file "ws23_test/../5MW_Baseline/NRELOffshrBsline5MW_AeroDyn_blade.dat".
 AD_Init:Init_BEMTmodule:BEMT_Init:UA_Init:UA_SetParameters:UA_ValidateAFI:File
 "ws23_test/../5MW_Baseline/Airfoils/DU40_A17.dat":The separation function f_st does not reach 1;
 max(f_st)=0.56668. Check the calculation or provide f_st in the input file.


  Time: 0 of 600 seconds.
 Time: 15 of 600 seconds.  Estimated final completion at 10:32:07 (in 0.002 days).

With a simpler model without aerodynamic states (DBEMT_Mod = -1 and UAMod = 0) I don’t have any problems. I have also tried DBEMT_Mod = 3 and UAMod = 0, since DBEMT_Mod = 3 is the recommend practice according to the OpenFAST Documentation, and -1 is useful for simplified linearizations only. The moment I try to activate any unsteady aerodynamics (UAMod = 4 or 5) I get those warning messages. Reducing the number of DOFs doesn’t change anything.

Best regards,

Dear @Jason.Jonkman,

Since I need to continue with my work, is it acceptable/common practice to linearize the 5 MW wind turbine without UA (UA_Mod = 0)?

I have made a little research about the first warning:

"_NREL5MW_LINParametric/../5MW_Baseline/NRELOffshrBsline5MW_AeroDyn_blade.dat".
 AD_Init:Init_BEMTmodule:BEMT_Init:UA_Init:UA_SetParameters:UA_ValidateAFI:File
 "_NREL5MW_LINParametric/../5MW_Baseline/Airfoils/DU40_A17.dat":
The separation function f_st does  not reach 1; max(f_st)=0.56668.  
Check the calculation or provide f_st in the input file.

I’d like to share a couple of things:

  1. I have checked the DU40_A17 airfoil with the Polar.py script from the openfast_toolbox and the separation function does reach 1.
Alpha (deg) | f_st value
    -180.00 |         0.00000
    -175.00 |         0.00000
    -170.00 |         0.00000
    -160.00 |         0.00000
    -155.00 |         0.00000
    -150.00 |         0.00000
    -145.00 |         0.00000
    -140.00 |         0.00000
    -135.00 |         0.00000
    -130.00 |         0.00000
    -125.00 |         0.00000
    -120.00 |         0.00000
    -115.00 |         0.00000
    -110.00 |         0.00000
    -105.00 |         0.00000
    -100.00 |         0.00000
     -95.00 |         0.00000
     -90.00 |         0.00000
     -85.00 |         0.00000
     -80.00 |         0.00000
     -75.00 |         0.00000
     -70.00 |         0.00000
     -65.00 |         0.00000
     -60.00 |         0.00000
     -55.00 |         0.00000
     -50.00 |         0.00000
     -45.00 |         0.00000
     -40.00 |         0.00000
     -35.00 |         0.00000
     -30.00 |         0.00567
     -25.00 |         0.02153
     -24.00 |         0.02613
     -23.00 |         0.03136
     -22.00 |         0.03696
     -21.00 |         0.04364
     -20.00 |         0.05083
     -19.00 |         0.05854
     -18.00 |         0.06577
     -17.00 |         0.07273
     -16.00 |         0.07858
     -15.00 |         0.08353
     -14.00 |         0.08720
     -13.00 |         0.08996
     -12.00 |         0.09048
     -11.00 |         0.08897
     -10.00 |         0.08461
      -8.00 |         0.06342
      -6.00 |         0.03483
      -5.50 |         0.03010
      -5.00 |         0.03171
      -4.50 |         0.09058
      -4.00 |         0.22258
      -3.50 |         0.04765
      -3.00 |         0.04765
      -2.50 |         0.00245
      -2.00 |         0.19593
      -1.50 |         0.48028
      -1.00 |         0.03907
      -0.50 |         0.00066
       0.00 |         0.08165
       0.50 |         0.23703
       1.00 |         0.39765
       1.50 |         0.53284
       2.00 |         0.64278
       2.50 |         0.72181
       3.00 |         0.77822
       3.50 |         0.82424
       4.00 |         0.86429
       4.50 |         0.90184
       5.00 |         0.93281
       5.50 |         0.95612
       6.00 |         0.97697
       6.50 |         0.98994
       7.00 |         0.99614
       7.50 |         1.00000
       8.00 |         0.99849
       8.50 |         0.99071
       9.00 |         0.97748
       9.50 |         0.96679
      10.00 |         0.94155
      10.50 |         0.91431
      11.00 |         0.88024
      11.50 |         0.84759
      12.00 |         0.81740
      12.50 |         0.78605
      13.00 |         0.75481
      13.50 |         0.73194
      14.50 |         0.68965
      15.00 |         0.67281
      15.50 |         0.64805
      16.00 |         0.62568
      16.50 |         0.60384
      17.00 |         0.58168
      17.50 |         0.56314
      18.00 |         0.54714
      19.00 |         0.51205
      19.50 |         0.49591
      20.50 |         0.46545
      21.00 |         0.44920
      22.00 |         0.41679
      23.00 |         0.38590
      24.00 |         0.35642
      25.00 |         0.32825
      26.00 |         0.30180
      28.00 |         0.25386
      30.00 |         0.21299
      32.00 |         0.17920
      35.00 |         0.13770
      40.00 |         0.07859
      45.00 |         0.03430
      50.00 |         0.00756
      55.00 |         0.00019
      60.00 |         0.00000
      65.00 |         0.00000
      70.00 |         0.00000
      75.00 |         0.00000
      80.00 |         0.00000
      85.00 |         0.00000
      90.00 |         0.00000
      95.00 |         0.00000
     100.00 |         0.00000
     105.00 |         0.00000
     110.00 |         0.00000
     115.00 |         0.00000
     120.00 |         0.00000
     125.00 |         0.00000
     130.00 |         0.00000
     135.00 |         0.00000
     140.00 |         0.00000
     145.00 |         0.00000
     150.00 |         0.00000
     155.00 |         0.00000
     160.00 |         0.00000
     170.00 |         0.00000
     175.00 |         0.00000
     180.00 |         0.00000
  1. The aforementioned Python script is throwing this warning:
    [WARN] More than 20% error between estimated slope (0.1078) and the slope around alpha0 (0.0400). The window for the slope search ([-10.0 17.0]) is likely wrong.

  2. I have also checked the following scripts: DU21_A17, DU25_A17, DU30_A17 and DU35_A17. With any of them I get that warning.

  3. After plotting some data of the DU40_A17 airfoil I have come up with a possible reason: there is to much noise near the alpha0 region, and that’s why the script is having trouble to estimate the slope. What do you think?

Best regards,