03: Simplified Floating

03: Simplified Floating#

In this example, we run Ard on a simplified floating platform problem.

We follow Example 02 closely, so descriptions are more sparse.

from pathlib import Path  # optional, for nice path specifications

import pprint as pp  # optional, for nice printing
import numpy as np  # numerics library
import matplotlib.pyplot as plt  # plotting capabilities

import windIO

import ard  # technically we only really need this
from ard.utils.io import load_yaml  # we grab a yaml loader here
from ard.api import set_up_ard_model  # the secret sauce
from ard.viz.layout import plot_layout  # a plotting tool!

import openmdao.api as om  # for N2 diagrams from the OpenMDAO backend

# import optiwindnet.plotting

%matplotlib inline
# load input
path_inputs = Path.cwd().absolute() / "inputs"
input_dict = load_yaml(path_inputs / "ard_system.yaml")

# set up system
prob = set_up_ard_model(input_dict=input_dict, root_data_path=path_inputs)
Running OpenMDAO util to clean the output directories...
	No OpenMDAO output directories found.
... done.

Created top-level OpenMDAO problem: top_level.
Adding top_level.
    Adding layout2aep.
        Adding layout to layout2aep.
        Adding aepFLORIS to layout2aep.
	Activating approximate totals on layout2aep
    Adding landuse.
    Adding collection.
    Adding mooring_design.
    Adding mooring_constraint.
    Adding spacing_constraint.
    Adding tcc.
    Adding orbit.
    Adding opex.
    Adding financese.
System top_level built.
System top_level set up.

Some new components are added to the Ard model here, comparing to Example 02:

  • mooring_design: designs the mooring system, here simply by doing straight-line mooring lines to the constant-valued seafloor

  • mooring_constraint: a module to compute a constraint function to make sure the moorings don't violate regulatory requirements on proximity

# visualize model
if False:
    om.n2(prob)
# run the model
prob.run_model()

# collapse the test result data
test_data = {
    "AEP_val": float(prob.get_val("AEP_farm", units="GW*h")[0]),
    "CapEx_val": float(prob.get_val("tcc.tcc", units="MUSD")[0]),
    "BOS_val": float(prob.get_val("orbit.total_capex", units="MUSD")[0]),
    "OpEx_val": float(prob.get_val("opex.opex", units="MUSD/yr")[0]),
    "LCOE_val": float(prob.get_val("financese.lcoe", units="USD/MW/h")[0]),
    "area_tight": float(prob.get_val("landuse.area_tight", units="km**2")[0]),
    "coll_length": float(prob.get_val("collection.total_length_cables", units="km")[0]),
    "mooring_spacing": float(
        np.min(prob.get_val("mooring_constraint.mooring_spacing", units="km"))
    ),
    "turbine_spacing": float(
        np.min(prob.get_val("spacing_constraint.turbine_spacing", units="km"))
    ),
}

print("\n\nRESULTS:\n")
pp.pprint(test_data)
print("\n\n")
UserWarning: /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/floris/core/flow_field.py:169
'where' used without 'out', expect unitialized memory in output. If this is intentional, use out=None.
ORBIT library intialized at '/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/library'


RESULTS:

{'AEP_val': 410.14878567258273,
 'BOS_val': 994.1921261768098,
 'CapEx_val': 118.75948972475001,
 'LCOE_val': 226.31146168189625,
 'OpEx_val': 9.350000000000001,
 'area_tight': 13.2496,
 'coll_length': 21.89865877023397,
 'mooring_spacing': 0.042875983926893214,
 'turbine_spacing': 0.91}
optimize = True  # set to False to skip optimization
if optimize:
    # run the optimization
    prob.run_driver()
    prob.cleanup()

    prob.check_totals(compact_print=True, show_only_incorrect=True)

    # collapse the test result data
    test_data = {
        "spacing_primary": float(prob.get_val("spacing_primary")[0]),
        "spacing_secondary": float(prob.get_val("spacing_secondary")[0]),
        "angle_orientation": float(prob.get_val("angle_orientation")[0]),
        "angle_skew": float(prob.get_val("angle_skew")[0]),
        "AEP_val": float(prob.get_val("AEP_farm", units="GW*h")[0]),
        "CapEx_val": float(prob.get_val("tcc.tcc", units="MUSD")[0]),
        "BOS_val": float(prob.get_val("orbit.total_capex", units="MUSD")[0]),
        "OpEx_val": float(prob.get_val("opex.opex", units="MUSD/yr")[0]),
        "LCOE_val": float(prob.get_val("financese.lcoe", units="USD/MW/h")[0]),
        "area_tight": float(prob.get_val("landuse.area_tight", units="km**2")[0]),
        "coll_length": float(
            prob.get_val("collection.total_length_cables", units="km")[0]
        ),
        "mooring_spacing": float(
            np.min(prob.get_val("mooring_constraint.mooring_spacing", units="km"))
        ),
        "turbine_spacing": float(
            np.min(prob.get_val("spacing_constraint.turbine_spacing", units="km"))
        ),
    }

    # clean up the recorder
    prob.cleanup()

    # print the results
    print("\n\nRESULTS (opt):\n")
    pp.pprint(test_data)
    print("\n\n")

    # plot convergence
    ## read cases
    cr = om.CaseReader(
        prob.get_outputs_dir() / input_dict["analysis_options"]["recorder"]["filepath"]
    )

    # Extract the driver cases
    cases = cr.get_cases("driver")

    # Initialize lists to store iteration data
    iterations = []
    objective_values = []

    # Loop through the cases and extract iteration number and objective value
    for i, case in enumerate(cases):
        iterations.append(i)
        obj_keys = input_dict["analysis_options"]["objectives"].keys()
        assert (len(obj_keys)) == 1
        objective_values.append(
            case.get_objectives()[next(iter(obj_keys))]  # get the unique entry
        )

    # Plot the convergence
    plt.figure(figsize=(8, 6))
    plt.plot(iterations, objective_values, marker="o", label="Objective (LCOE)")
    plt.xlabel("Iteration")
    plt.ylabel("Objective Value (Total Cable Length (m))")
    plt.title("Convergence Plot")
    plt.legend()
    plt.grid()
    plt.show()
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|0
--------------------------------------------------------------
Design Vars
{'angle_orientation': array([0.]),
 'angle_skew': array([0.]),
 'spacing_primary': array([7.]),
 'spacing_secondary': array([7.])}
UserWarning: /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/floris/core/flow_field.py:169
'where' used without 'out', expect unitialized memory in output. If this is intentional, use out=None.
Objectives
{'collection.total_length_cables': array([21898.65877023])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|1
--------------------------------------------------------------
Design Vars
{'angle_orientation': array([0.]),
 'angle_skew': array([0.]),
 'spacing_primary': array([7.]),
 'spacing_secondary': array([7.])}
UserWarning: /opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/floris/core/flow_field.py:169
'where' used without 'out', expect unitialized memory in output. If this is intentional, use out=None.
Objectives
{'collection.total_length_cables': array([21898.65877023])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|2
--------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.00169981]),
 'angle_skew': array([-0.00247939]),
 'spacing_primary': array([6.97727015]),
 'spacing_secondary': array([6.98376224])}
Objectives
{'collection.total_length_cables': array([21836.22659655])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|3
--------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.01182038]),
 'angle_skew': array([-0.00488319]),
 'spacing_primary': array([6.86364301]),
 'spacing_secondary': array([6.90258908])}
Objectives
{'collection.total_length_cables': array([21524.14814719])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|4
--------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.0354046]),
 'angle_skew': array([-0.14220988]),
 'spacing_primary': array([6.55392293]),
 'spacing_secondary': array([6.67001219])}
Objectives
{'collection.total_length_cables': array([20658.61893805])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|5
--------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.03527828]),
 'angle_skew': array([-0.14589906]),
 'spacing_primary': array([6.55384971]),
 'spacing_secondary': array([6.64457632])}
Objectives
{'collection.total_length_cables': array([20625.4411911])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|6
--------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02091876]),
 'angle_skew': array([-0.16122459]),
 'spacing_primary': array([6.55386143]),
 'spacing_secondary': array([6.55383148])}
Objectives
{'collection.total_length_cables': array([20507.59301867])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|7
--------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02126326]),
 'angle_skew': array([-0.16133396]),
 'spacing_primary': array([6.55384647]),
 'spacing_secondary': array([6.55382035])}
Objectives
{'collection.total_length_cables': array([20507.5506663])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|8
--------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02808669]),
 'angle_skew': array([-0.16292084]),
 'spacing_primary': array([6.55385166]),
 'spacing_secondary': array([6.55382316])}
Objectives
{'collection.total_length_cables': array([20507.55075989])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|9
--------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02453102]),
 'angle_skew': array([-0.16209392]),
 'spacing_primary': array([6.55384896]),
 'spacing_secondary': array([6.55382169])}
Objectives
{'collection.total_length_cables': array([20507.55071005])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|10
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02282978]),
 'angle_skew': array([-0.16169828]),
 'spacing_primary': array([6.55384766]),
 'spacing_secondary': array([6.55382099])}
Objectives
{'collection.total_length_cables': array([20507.55068703])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|11
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02201459]),
 'angle_skew': array([-0.16150869]),
 'spacing_primary': array([6.55384704]),
 'spacing_secondary': array([6.55382066])}
Objectives
{'collection.total_length_cables': array([20507.55067619])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|12
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02162369]),
 'angle_skew': array([-0.16141779]),
 'spacing_primary': array([6.55384674]),
 'spacing_secondary': array([6.5538205])}
Objectives
{'collection.total_length_cables': array([20507.55067103])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|13
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02143619]),
 'angle_skew': array([-0.16137418]),
 'spacing_primary': array([6.5538466]),
 'spacing_secondary': array([6.55382042])}
Objectives
{'collection.total_length_cables': array([20507.55066857])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|14
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02134623]),
 'angle_skew': array([-0.16135326]),
 'spacing_primary': array([6.55384653]),
 'spacing_secondary': array([6.55382038])}
Objectives
{'collection.total_length_cables': array([20507.55066739])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|15
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02130307]),
 'angle_skew': array([-0.16134322]),
 'spacing_primary': array([6.5538465]),
 'spacing_secondary': array([6.55382036])}
Objectives
{'collection.total_length_cables': array([20507.55066682])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|16
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02128236]),
 'angle_skew': array([-0.1613384]),
 'spacing_primary': array([6.55384649]),
 'spacing_secondary': array([6.55382036])}
Objectives
{'collection.total_length_cables': array([20507.55066655])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|17
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02127243]),
 'angle_skew': array([-0.16133609]),
 'spacing_primary': array([6.55384648]),
 'spacing_secondary': array([6.55382035])}
Objectives
{'collection.total_length_cables': array([20507.55066642])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|18
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-0.02126766]),
 'angle_skew': array([-0.16133498]),
 'spacing_primary': array([6.55384647]),
 'spacing_secondary': array([6.55382035])}
Objectives
{'collection.total_length_cables': array([20507.55066636])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|19
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-1.06737782]),
 'angle_skew': array([-0.39506431]),
 'spacing_primary': array([6.55430466]),
 'spacing_secondary': array([6.5538596])}
Objectives
{'collection.total_length_cables': array([20506.5507933])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|20
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-2.37852401]),
 'angle_skew': array([-0.68803555]),
 'spacing_primary': array([6.5549008]),
 'spacing_secondary': array([6.55412396])}
Objectives
{'collection.total_length_cables': array([20505.88566688])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|21
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-29.60593667]),
 'angle_skew': array([-6.77139009]),
 'spacing_primary': array([6.56118421]),
 'spacing_secondary': array([6.5616759])}
Objectives
{'collection.total_length_cables': array([20555.06390447])}
Driver debug print for iter coord: rank0:ScipyOptimize_SLSQP|22
---------------------------------------------------------------
Design Vars
{'angle_orientation': array([-5.63851371]),
 'angle_skew': array([-1.41640712]),
 'spacing_primary': array([6.55565312]),
 'spacing_secondary': array([6.55502817])}
Objectives
{'collection.total_length_cables': array([20504.53666797])}
Iteration limit reached    (Exit mode 9)
            Current function value: 1.0252268333985624
            Iterations: 10
            Function evaluations: 22
            Gradient evaluations: 11
Optimization FAILED.
Iteration limit reached
-----------------------------------
-----------------
Total Derivatives
-----------------

+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+
| 'of' variable                      | 'wrt' variable    | calc val @ max viol | fd val @ max viol | (calc-fd) - (a + r*fd) | error desc        |
+====================================+===================+=====================+===================+========================+===================+
| AEP_farm                           | angle_orientation |       -2.496802e+17 |     -3.143930e+11 |           2.496799e+17 |  2.496799e+17>TOL |
+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+
| AEP_farm                           | angle_skew        |        1.610595e+17 |     -2.042171e+11 |           1.610597e+17 |  1.610597e+17>TOL |
+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+
| AEP_farm                           | spacing_primary   |        1.855168e+09 |     -2.321905e+11 |           2.340455e+11 |  2.340455e+11>TOL |
+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+
| AEP_farm                           | spacing_secondary |        5.405708e+09 |      2.908631e+11 |           2.854571e+11 |  2.854571e+11>TOL |
+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+
| collection.total_length_cables     | angle_orientation |        9.063113e-01 |      1.338211e+00 |           4.318984e-01 |  4.318984e-01>TOL |
+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+
| collection.total_length_cables     | angle_skew        |       -1.911863e+00 |     -1.941769e+00 |           2.990369e-02 |  2.990369e-02>TOL |
+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+
| spacing_constraint.turbine_spacing | angle_orientation |       -2.285185e-04 |      0.000000e+00 |           2.285185e-04 |  2.285185e-04>TOL |
+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+
| spacing_constraint.turbine_spacing | angle_skew        |        1.865928e-04 |      0.000000e+00 |           1.865928e-04 |  1.865928e-04>TOL |
+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+
| spacing_constraint.turbine_spacing | spacing_primary   |       -8.951173e-16 |      4.656613e-10 |           4.656617e-10 |  4.656617e-10>TOL |
+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+
| spacing_constraint.turbine_spacing | spacing_secondary |        1.376855e-14 |     -4.656613e-10 |           4.656746e-10 |  4.656746e-10>TOL |
+------------------------------------+-------------------+---------------------+-------------------+------------------------+-------------------+


RESULTS (opt):

{'AEP_val': 440.5479229177636,
 'BOS_val': 993.5788953738085,
 'CapEx_val': 118.75948972475001,
 'LCOE_val': 210.59088933602834,
 'OpEx_val': 9.350000000000001,
 'angle_orientation': -5.638513705269998,
 'angle_skew': -1.4164071157514626,
 'area_tight': 11.619761537753096,
 'coll_length': 20.504536667971248,
 'mooring_spacing': 0.0635583900012834,
 'spacing_primary': 6.55565312253702,
 'spacing_secondary': 6.5550281704696225,
 'turbine_spacing': 0.8522349059298125}
../../_images/28ee8dbe5516d7d8c1d68a7f9a4eb1fb3f2b059d7de941eb0afbd049aa1b7476.png
plot_layout(prob, input_dict=input_dict, show_image=True, include_cable_routing=True)
../../_images/d24be4d123c6e3176c2611992b16096fb48259a80f32b825b57aba664adc4cd2.png
<Axes: >