WISDEM on Ubuntu and Windows 10: same serial calculation very different run times

Hello,

I have installed WISDEM on a Ubuntu 48-CPU workstation to run optimization in parallel.
To test it, I first launched the serial optimization that succeded on the WISDEM installed on my Windows-10 PC, that is, the aerostructural optimization in the WISDEM example nr 3.
The successful run on Windows took about 1 hour and 30 minutes to complete, the one on Ubuntu was still running after 10 hours…
Of course, the optimization input files are the same, and I followed the same procedure in the documentation for both WISDEM installations.

I installed WISDEM on Windows in May (10 May 2021) and on Ubuntu two weeks ago (1 October 2021). The Ubuntu version is 20.04.
After the installation on Ubuntu, I run the installation tests and one test failed (see screenshot in attachment): perhaps, this can be a hint on something wrong in my Ubuntu installation.

Thank you in advance for your time and help.

Hi Henny,

I am not sure why your Ubuntu WISDEM installation was taking so long. Was this with Anaconda or the native Ubuntu python packages? In my experience, the Windows simulations usually take longer because the open-source compilers aren’t great on Windows. Are you absolutely sure all of the input files were identical? Without some more detailed comparison regarding packages, compilers, problem setup, it will be almost impossible for me to be able to diagnose what the problem was. We could try to slowly go through that on the forum or maybe you are content to use your Windows installation?

Cheers,
Garrett

Hi Garret,

I tried few other tests of my Ubuntu installation of WISDEM, but let’go in order:

With Anaconda.

Yes. I re-run twice the same input files on Windows and on Ubuntu, and optimizations converged in ~1h30min on Windows, and kept running hours and hours on Ubuntu.

Now, my other tests were:

  • two basics optimization cases coded directly in openMDAO
  • the simple aerodynamic blade optimization in the WISDEM example nr. 3

Both openMDAO optimizations succeded on Ubuntu and were faster than when run on Windows. And also the simple aerodynamic blade optimization succeded on Ubuntu and gave the same results as on WIndows (it was a little slower, 5min50sec against 5min25sec on WIndows, but I do not see this as much of a problem).
My WISDEM version on Windows is 3.2.0 dev_0, but the one on Ubuntu is 3.3.0 dev_0: I am thinking to install WISDEM 3.2.0 in an other conda environment and re-run the test case in it… May it help?

Thank you for your constant help Garret.

Hi Henny,

Yes, you would have to be using the same version of WISDEM to make a fair comparison between the platforms. I would sync both to either the same Anaconda release or to the current develop-branch.

Just a forewarning, we might not be able to get to the bottom of the issue. This is the type of problem that is very difficult to diagnose.

Cheers,
Garrett

I installed the WISDEM version that I have on my Windows 10 PC (WISDEM=3.2.0, python=3.7.4, conda=4.8.1) on my Ubuntu workstation with the procedure detailed below.
conda list confirms that I have wisdem version 3.2.0 in the wisdem-320-env-bis conda environment.
But, when I run WISDEM test_all.py to check the installation, it soon stops with the error in the screenshot.
nlopt version 2.7.0 is installed.
What is wrong in my installation procedure?

Thank you for your time Garrett.

WISDEM 3.2.0 installation procedure (started from within the newly created folder ~/wisdem320/):

conda create -y --name wisdem-320-env-bis python==3.7.4 conda==4.8.1
conda activate wisdem-320-env-bis
conda install -y wisdem==3.2.0 git
conda remove --force wisdem
pip install simpy marmot-agents nlopt
conda install compilers
git clone https://github.com/WISDEM/WISDEM.git
cd WISDEM

at this point I changed the version number in the setup.py script of the cloned repository as below

# Top-level setup
setup(
    name="WISDEM",
    version="3.2.0", # "3.3.0"
    description="Wind-Plant Integrated System Design & Engineering Model",
    .
    .
    .

and finally run

python setup.py develop

Hi Henny,

Looks like some of the dependencies may have gotten out of step with one another. Perhaps try: ‘conda update --all’ to be sure you have the latest version of everything.

Cheers,
Garrett

Regarding version 3.2.0, I run

and got the updates, but then, a series of errors about modules not installed started appearing in sequence, as I tried to launch an optimization. To solve these errors I installed numpy, openmdao, sortedcontainers in the wisdem environment, and then the next error asked for the yaml module, which, however, conda refused to install because it is already installed …

Regarding version 3.3.0, then, I managed to run successfully the aerostructural optimization example that shipped with the installation (not the one I run on Windows). I succeded both the serial and the parallel calculations.
Then I reduced the optimality tolerance from 1e-5 to 1e-3 and increased the maximum number of iterations to 20: the parallel (10 cores) calculation succeded even faster, ~5min instead of ~31min.
The analysis options for this optimization have the number of control points for chord, twist, sparcaps thicness, and trailing-edge thickness set to 4. I increased this number to 10, adjusted index_end to 9, and run with tol=1e-3, and max_iter=20, but the parallel (10 cores) optimization failed because of "iteration limit reached " . Setting max_iter to 100 did not help neither: again failure because of "iteration limit reached " , after 5h40min of calculation.
Are there some more settings to adjust to have the aerostructural optimization working also with more control points?
At this point, since version 3.3.0 is at least operative on my PC, I prefer to focus on this problem rather than the one of version 3.2.0.

Hi Henny,

At this point, can you copy here your full analysis_options.yaml file that you are using?

Hi Garret,
here it is my analysis_options.yaml:

general:
    folder_output: outputs_aerostruct_tol0001_allCtrlPnts10_allCnstrnt_iter100_5
    fname_output: blade_out

design_variables:
    rotor_diameter:
        flag: True # False @ 3 Sept 2021 
        minimum: 190
        maximum: 240
    blade:
        aero_shape:
            twist:
                flag: True             # Flag to optimize the twist; True if 'inverse'=False and viceversa
                inverse: False         # Flag to determine twist from the user-defined desired margin to stall (defined in constraints) False
                n_opt: 10               # Number of control points along blade span; default=4
                max_decrease: 0.08722222222222221 # Maximum decrease for the twist in [rad] at the n_opt locations
                max_increase: 0.08722222222222221 # Maximum increase for the twist in [rad] at the n_opt locations
                index_start: 2         # Lock the first two DVs from blade root
                index_end: 10           # All DVs close to blade tip are active
            chord:
                flag: True             # Flag to optimize the chord
                n_opt: 10               # Number of control points along blade span; default=4
                max_decrease: 0.3      # Minimum multiplicative gain on existing chord at the n_opt locations
                max_increase: 3.       # Maximum multiplicative gain on existing chord at the n_opt locations
                index_start: 2         # Lock the first two DVs from blade root
                index_end: 9           # The last DV at blade tip is locked; 
                                        # It is recommended to lock the last point close to blade tip, setting index_end to n_opt minus 1
        structure:
            spar_cap_ss:
                flag: True             # Flag to optimize the spar cap thickness on the suction side
                n_opt: 10               # Number of control points along blade span; default=4
                max_decrease: 0.7      # Maximum nondimensional decrease at the n_opt locations
                max_increase: 1.3      # Maximum nondimensional increase at the n_opt locations
                index_start: 1         # Lock the first DV from blade root
                index_end: 9           # The last DV at blade tip is locked
                                        # It is recommended to lock the last point close to blade tip, setting index_end to n_opt minus 1
            spar_cap_ps:
                flag: True             # Flag to optimize the spar cap thickness on the pressure side
                equal_to_suction: True # Flag to impose the spar cap thickness on pressure and suction sides equal
                n_opt: 10               # Number of control points along blade span; default=4
                max_decrease: 0.7      # Maximum nondimensional decrease at the n_opt locations
                max_increase: 1.3      # Maximum nondimensional increase at the n_opt locations
                index_start: 1         # Lock the first DV from blade root
                index_end: 9           # The last DV at blade tip is locked
            te_ss:
                flag: True             # Flag to optimize the spar cap thickness on the pressure side
                n_opt: 10               # Number of control points along blade span; default=4
                max_decrease: 0.7      # Maximum nondimensional decrease at the n_opt locations
                max_increase: 1.3      # Maximum nondimensional increase at the n_opt locations
                index_start: 1         # Lock the first DV from blade root
                index_end: 9           # The last DV at blade tip is locked
            
            te_ps:
                flag: True             # Flag to optimize the spar cap thickness on the pressure side
                n_opt: 10               # Number of control points along blade span; default=4
                max_decrease: 0.7      # Maximum nondimensional decrease at the n_opt locations
                max_increase: 1.3      # Maximum nondimensional increase at the n_opt locations
                index_start: 1         # Lock the first DV from blade root
                index_end: 9           # The last DV at blade tip is locked    

merit_figure: LCOE

constraints:
    blade:
        strains_spar_cap_ss:
            flag: True         # Flag to impose constraints on maximum strains (absolute value) in the spar cap on the blade suction side
            max:    3500.e-6   # Value of maximum strains [-]
            index_start: 1     # Do not enforce constraint at the first station from blade root of the n_opt from spar_cap_ss
            index_end: 9       # Do not enforce constraint at the last station at blade tip of the n_opt from spar_cap_ss
        strains_spar_cap_ps:
            flag: True        # Flag to impose constraints on maximum strains (absolute value) in the spar cap on the blade pressure side
            max:    3500.e-6   # Value of maximum strains [-]
            index_start: 1     # Do not enforce constraint at the first station from blade root of the n_opt from spar_cap_ps
            index_end: 9       # Do not enforce constraint at the last station at blade tip of the n_opt from spar_cap_ps
        strains_te_ss:
            flag: True        # Flag to impose constraints on maximum strains (absolute value) in the spar cap on the blade pressure side
            max:    3500.e-6   # Value of maximum strains [-]
            index_start: 1     # Do not enforce constraint at the first station from blade root of the n_opt from spar_cap_ps
            index_end: 9       # Do not enforce constraint at the last station at blade tip of the n_opt from spar_cap_ps   
        strains_te_ps:
            flag: True        # Flag to impose constraints on maximum strains (absolute value) in the spar cap on the blade pressure side
            max:    3500.e-6   # Value of maximum strains [-]
            index_start: 1     # Do not enforce constraint at the first station from blade root of the n_opt from spar_cap_ps
            index_end: 9       # Do not enforce constraint at the last station at blade tip of the n_opt from spar_cap_ps     
        tip_deflection:
            flag: True         # True
            margin: 1.4175
        stall:
            flag: True    # Constraint on minimum stall margin
            margin: 0.087 # Value of minimum stall margin in [rad]   default=0.05233 range=[0.0:0.5]

driver:
    optimization:
        flag: True         # Flag to enable optimization
        tol: 1.e-3          # Optimality tolerance
        # max_major_iter: 10  # Maximum number of major design iterations (SNOPT)
        # max_minor_iter: 100 # Maximum number of minor design iterations (SNOPT)
        max_iter: 100         # Maximum number of iterations (SLSQP);
        solver: SLSQP       # Optimization solver. Other options are 'SLSQP' - 'CONMIN'
        step_size: 1.e-3    # Step size for finite differencing
        form: forward       # Finite differencing mode, either forward or central
    # check_partials:         # 1 Sept 2021
        # flag: True
recorder:
    flag: False             # Flag to activate OpenMDAO recorder
    file_name: log_opt.sql # Name of OpenMDAO recorder

thank you for your help.

Hello Henny,

I have two suggestions for you:

  1. Turn on the openmdao recorder at the end of your analysis option yaml. That will create log file in your output folder. Next, create a .py script in your run directory with these lines.

import openmdao.api as om from wisdem.glue_code.gc_RunTools import PlotRecorder import wisdem.inputs as sch import os mydir = os.path.dirname(os.path.realpath(__file__)) # get path to this file fname_analysis_options = mydir + os.sep + "analysis_options.yaml" analysis_options = sch.load_analysis_yaml(fname_analysis_options) wt_opt = om.Problem(model=PlotRecorder(opt_options=analysis_options)) wt_opt.setup(derivatives=False) wt_opt.run_model()

When you run this file from your wisdem environment, in the output folder a series of convergence plots will appear, showing you the design variables, constraints, and figure of merit against across the iterations. This will likely show why the optimizer is not stopping.

  1. Try simplifying your optimization problem, running the aerodynamic only test first and then the structural only test. Do those tests converge? Slowly move up in complexity of your problem

I hope this helps.
Best regards,
Pietro

I apologize for the late reply (the workstation has been unavailable for some weeks).

The aerodynamic-only test fails as I increase twist and chord control points from 4 to 10 because of Iteration limit reached, even if I set max_iter to 100 (tol=1E-3).
The structural-only test, instead, succeeds for 20 and 30 control points for spar caps and trailing edge thicknesses with max_iter set to 100 (tol=1E-3).
Looking at the convergence trends (two of them, representative of all the trends, in attachment), the ones of the succeeded optimization proceed smoothly towards the final values, while those of the failed optimization after initial large changes stay almost flat with some peaks.
I noted also that, despite my max_iter settings, the number of iterations reported in the plot of the failed optimization is much larger than 100, while 25 is the number of iterations that the successful optimization needed for convergence, as per CLI output.
What can I change in the settings of the aerodynamic-only optimization to have convergence?
This is the analysis_options_aero.yaml file:

general:
    folder_output: outputs_aero_計算番号2
    fname_output: blade_out

design_variables:
    blade:
        aero_shape:
            twist:
                flag: True  # Flag to optimize the twist
                inverse: False # Flag to determine twist from the user-defined desired margin to stall (defined in constraints)
                n_opt: 10     # Number of control points along blade span
                max_decrease: 0.08722222222222221 # Maximum decrease for the twist in [rad] at the n_opt locations
                max_increase: 0.08722222222222221 # Maximum increase for the twist in [rad] at the n_opt locations
                index_start: 2 # Lock the first two DVs from blade root
                index_end: 10 # All DVs close to blade tip are active
            chord:
                flag: True  # Flag to optimize the chord
                n_opt: 10     # Number of control points along blade span; 元の数値= 4
                max_decrease: 0.3 # Minimum multiplicative gain on existing chord at the n_opt locations
                max_increase: 3. # Maximum multiplicative gain on existing chord at the n_opt locations
                index_start: 0 # Start by optimizing chord at blade root
                index_end: 9 # Lock chord at blade tip

merit_figure: AEP

constraints:
    blade:
        stall:
            flag: True     # Constraint on minimum stall margin
            margin: 0.087 # Value of minimum stall margin in [rad]
        chord:
            flag: True # Constraint max chord to its default value (4.75 m)
        root_circle_diameter:
            flag: True # Constraint for the minimum blade root circle diameter
            max_ratio: 1.2 # The recommended value can be up to 20% larger than the actual

driver:
    optimization:
        flag: True         # Flag to enable optimization
        tol: 1.e-3          # Optimality tolerance
        # max_major_iter: 10  # Maximum number of major design iterations (SNOPT)
        # max_minor_iter: 100 # Maximum number of minor design iterations (SNOPT)
        max_iter: 20         # Maximum number of iterations (SLSQP)
        solver: SLSQP       # Optimization solver. Other options are 'SLSQP' - 'CONMIN'
        step_size: 1.e-3    # Step size for finite differencing
        form: forward       # Finite differencing mode, either forward or central

recorder:
    flag: True #False              # Flag to activate OpenMDAO recorder
    file_name: log_opt.sql  # Name of OpenMDAO recorder

Thank for the help, Pietro.

Best,
Henny
succeeded_structOpt_maxStrailLte.png
failed_aeroOpt_max_chord_constr.png

Dear Henny,
my apologies for the slow reply.
I believe that the aerodynamic optimization is not able to satisfy one (or more) constraint among the ones that you’ve set active

constraints: blade: stall: flag: True # Constraint on minimum stall margin margin: 0.087 # Value of minimum stall margin in [rad] chord: flag: True # Constraint max chord to its default value (4.75 m) root_circle_diameter: flag: True # Constraint for the minimum blade root circle diameter max_ratio: 1.2 # The recommended value can be up to 20% larger than the actual

Could you please try turning the constraints off and rerun? Once you identify what cannot be satisfied, we can focus on why that is.
Thank you!
Pietro

Dear Pietro,
I run three aerodynamic optimizations each with just one of the three constraints, and these are the results:

  • blade constraint = stall–> code crash
  • blade constraint = chord → optimization successful
  • blade constraint = root_circle_diameter → optimization failure

this is the last line of the message of the code crash:

The whole (very long) error message is in attachment as .txt file.
And this is the message for the optimization failure:

All the optimizations have tol=1e-3, max_iter=20, and n_opt=10 for twist and chord.

Thank you for your time and help,
Henny

If the message is “Iteration limit reached” with “Optimization FAILED” it means it did not reach the tolerance in the allowed number of iterations. You would need to relax the tolerance or extend the number of iterations. With your settings, I would suggest more than 20 iterations.

I didn’t see an attachment for the Frame3DD error. Usually that means needing to narrow your design variable bounds.

Good luck!

increasing the number of iterations to 100:

  • the optimization with only blade root_circle_diameter constrained succeeds
  • the optimization with blade root_circle_diameter and chord constrained succeeds

reducing the twist and chord values of max_decrease, max_increase to 2/3 of their previous values prevents the crash of the optimization with only blade stall constrained, but it still fails after 20 or 100 iterations. So the problem seems to be in the stall constrain set along with ten control points for the twist and chord design variables.