Open and run in Colab (interactive) Edit on Gitlab

Cables

Try this yourself (requires google account)

TOPFARM can use the Electrical Network Design package EDWIN to optimize the carray cabels as well as the substation position at each iteration of the layout optimization

Install TOPFARM if needed

[1]:
# Install TopFarm if needed
import importlib
if not importlib.util.find_spec("topfarm"):
    !pip install git+https://gitlab.windenergy.dtu.dk/TOPFARM/TopFarm2.git
[2]:
# Install EDWIN if needed
import importlib
if not importlib.util.find_spec("ed_win"):
    !pip install git+https://gitlab.windenergy.dtu.dk/TOPFARM/edwin.git#egg=ed_win[interarray]
DEPRECATION: git+https://gitlab.windenergy.dtu.dk/TOPFARM/edwin.git#egg=ed_win[interarray] contains an egg fragment with a non-PEP 508 name pip 25.0 will enforce this behaviour change. A possible replacement is to use the req @ url syntax, and remove the egg fragment. Discussion can be found at https://github.com/pypa/pip/issues/11617
Collecting ed_win (from ed_win[interarray])
  Cloning https://gitlab.windenergy.dtu.dk/TOPFARM/edwin.git to /tmp/pip-install-ee88owzj/ed-win_0702d6b471604a7c8dbf4e1614236e84
  Running command git clone --filter=blob:none --quiet https://gitlab.windenergy.dtu.dk/TOPFARM/edwin.git /tmp/pip-install-ee88owzj/ed-win_0702d6b471604a7c8dbf4e1614236e84
  Resolved https://gitlab.windenergy.dtu.dk/TOPFARM/edwin.git to commit 517099b186a093556129aa75c968924861f9b9b1
  Running command git submodule update --init --recursive -q
  Preparing metadata (setup.py) ... - \ done
Requirement already satisfied: networkx in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from ed_win->ed_win[interarray]) (3.4.2)
Requirement already satisfied: matplotlib in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from ed_win->ed_win[interarray]) (3.10.3)
Requirement already satisfied: shapely in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from ed_win->ed_win[interarray]) (2.1.1)
Requirement already satisfied: numpy in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from ed_win->ed_win[interarray]) (2.2.6)
Requirement already satisfied: xarray in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from ed_win->ed_win[interarray]) (2025.4.0)
Requirement already satisfied: scipy in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from ed_win->ed_win[interarray]) (1.15.2)
Collecting windIO (from ed_win->ed_win[interarray])
  Downloading windio-1.1.1-py3-none-any.whl.metadata (14 kB)
Collecting openpyxl (from ed_win->ed_win[interarray])
  Downloading openpyxl-3.1.5-py2.py3-none-any.whl.metadata (2.5 kB)
Collecting pony (from ed_win->ed_win[interarray])
  Downloading pony-0.7.19-py3-none-any.whl.metadata (2.8 kB)
Requirement already satisfied: pyyaml in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from ed_win->ed_win[interarray]) (6.0.2)
Collecting utm (from ed_win->ed_win[interarray])
  Downloading utm-0.8.1-py3-none-any.whl.metadata (5.2 kB)
Collecting pyomo (from ed_win->ed_win[interarray])
  Downloading pyomo-6.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (8.2 kB)
Collecting loguru (from ed_win->ed_win[interarray])
  Downloading loguru-0.7.3-py3-none-any.whl.metadata (22 kB)
Collecting numba (from ed_win->ed_win[interarray])
  Downloading numba-0.61.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (2.8 kB)
Collecting ortools (from ed_win->ed_win[interarray])
  Downloading ortools-9.14.6206-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (3.3 kB)
Collecting svg.py (from ed_win->ed_win[interarray])
  Downloading svg_py-1.6.0-py3-none-any.whl.metadata (2.1 kB)
Requirement already satisfied: contourpy>=1.0.1 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from matplotlib->ed_win->ed_win[interarray]) (1.3.2)
Requirement already satisfied: cycler>=0.10 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from matplotlib->ed_win->ed_win[interarray]) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from matplotlib->ed_win->ed_win[interarray]) (4.58.0)
Requirement already satisfied: kiwisolver>=1.3.1 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from matplotlib->ed_win->ed_win[interarray]) (1.4.8)
Requirement already satisfied: packaging>=20.0 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from matplotlib->ed_win->ed_win[interarray]) (25.0)
Requirement already satisfied: pillow>=8 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from matplotlib->ed_win->ed_win[interarray]) (11.2.1)
Requirement already satisfied: pyparsing>=2.3.1 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from matplotlib->ed_win->ed_win[interarray]) (3.2.3)
Requirement already satisfied: python-dateutil>=2.7 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from matplotlib->ed_win->ed_win[interarray]) (2.9.0.post0)
Collecting llvmlite<0.45,>=0.44.0dev0 (from numba->ed_win->ed_win[interarray])
  Downloading llvmlite-0.44.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (5.0 kB)
Collecting et-xmlfile (from openpyxl->ed_win->ed_win[interarray])
  Downloading et_xmlfile-2.0.0-py3-none-any.whl.metadata (2.7 kB)
Collecting absl-py>=2.0.0 (from ortools->ed_win->ed_win[interarray])
  Downloading absl_py-2.3.0-py3-none-any.whl.metadata (2.4 kB)
Requirement already satisfied: pandas>=2.0.0 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from ortools->ed_win->ed_win[interarray]) (2.2.3)
Collecting protobuf<6.32,>=6.31.1 (from ortools->ed_win->ed_win[interarray])
  Downloading protobuf-6.31.1-cp39-abi3-manylinux2014_x86_64.whl.metadata (593 bytes)
Requirement already satisfied: typing-extensions>=4.12 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from ortools->ed_win->ed_win[interarray]) (4.13.2)
Collecting immutabledict>=3.0.0 (from ortools->ed_win->ed_win[interarray])
  Downloading immutabledict-4.2.1-py3-none-any.whl.metadata (3.5 kB)
Collecting ply (from pyomo->ed_win->ed_win[interarray])
  Downloading ply-3.11-py2.py3-none-any.whl.metadata (844 bytes)
Requirement already satisfied: jsonschema in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from windIO->ed_win->ed_win[interarray]) (4.24.0)
Collecting ruamel.yaml (from windIO->ed_win->ed_win[interarray])
  Downloading ruamel.yaml-0.18.14-py3-none-any.whl.metadata (24 kB)
Requirement already satisfied: netcdf4 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from windIO->ed_win->ed_win[interarray]) (1.7.2)
Requirement already satisfied: pytz>=2020.1 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from pandas>=2.0.0->ortools->ed_win->ed_win[interarray]) (2025.2)
Requirement already satisfied: tzdata>=2022.7 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from pandas>=2.0.0->ortools->ed_win->ed_win[interarray]) (2025.2)
Requirement already satisfied: six>=1.5 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from python-dateutil>=2.7->matplotlib->ed_win->ed_win[interarray]) (1.17.0)
Requirement already satisfied: attrs>=22.2.0 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from jsonschema->windIO->ed_win->ed_win[interarray]) (25.3.0)
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from jsonschema->windIO->ed_win->ed_win[interarray]) (2025.4.1)
Requirement already satisfied: referencing>=0.28.4 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from jsonschema->windIO->ed_win->ed_win[interarray]) (0.36.2)
Requirement already satisfied: rpds-py>=0.7.1 in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from jsonschema->windIO->ed_win->ed_win[interarray]) (0.25.1)
Requirement already satisfied: cftime in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from netcdf4->windIO->ed_win->ed_win[interarray]) (1.6.4)
Requirement already satisfied: certifi in /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages (from netcdf4->windIO->ed_win->ed_win[interarray]) (2025.4.26)
Collecting ruamel.yaml.clib>=0.2.7 (from ruamel.yaml->windIO->ed_win->ed_win[interarray])
  Downloading ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (2.7 kB)
Downloading loguru-0.7.3-py3-none-any.whl (61 kB)
Downloading numba-0.61.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (3.9 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 MB 26.0 MB/s eta 0:00:00
Downloading openpyxl-3.1.5-py2.py3-none-any.whl (250 kB)
Downloading ortools-9.14.6206-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (27.7 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 27.7/27.7 MB 69.5 MB/s eta 0:00:00
Downloading pony-0.7.19-py3-none-any.whl (317 kB)
Downloading pyomo-6.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.2 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.2/4.2 MB 41.9 MB/s eta 0:00:00
Downloading svg_py-1.6.0-py3-none-any.whl (13 kB)
Downloading utm-0.8.1-py3-none-any.whl (8.6 kB)
Downloading windio-1.1.1-py3-none-any.whl (1.1 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.1/1.1 MB 34.0 MB/s eta 0:00:00
Downloading absl_py-2.3.0-py3-none-any.whl (135 kB)
Downloading immutabledict-4.2.1-py3-none-any.whl (4.7 kB)
Downloading llvmlite-0.44.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (42.4 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 42.4/42.4 MB 53.9 MB/s eta 0:00:00
Downloading protobuf-6.31.1-cp39-abi3-manylinux2014_x86_64.whl (321 kB)
Downloading et_xmlfile-2.0.0-py3-none-any.whl (18 kB)
Downloading ply-3.11-py2.py3-none-any.whl (49 kB)
Downloading ruamel.yaml-0.18.14-py3-none-any.whl (118 kB)
Downloading ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (754 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 754.1/754.1 kB 19.8 MB/s eta 0:00:00
Building wheels for collected packages: ed_win
  Building wheel for ed_win (setup.py) ... - \ | done
  Created wheel for ed_win: filename=ed_win-1.1.0-py3-none-any.whl size=265780 sha256=5c4a9ee8efa2a3fe3ef922bbda19bbd99d3d35106c2c584aa19efb10f5586f69
  Stored in directory: /tmp/pip-ephem-wheel-cache-o4osxs7d/wheels/dc/ef/33/6de3c3355f68f41028161e9a2096c6bcbeb8afb140128b44de
Successfully built ed_win
Installing collected packages: pony, ply, utm, svg.py, ruamel.yaml.clib, pyomo, protobuf, loguru, llvmlite, immutabledict, et-xmlfile, absl-py, ruamel.yaml, openpyxl, numba, ortools, windIO, ed_win
Successfully installed absl-py-2.3.0 ed_win-1.1.0 et-xmlfile-2.0.0 immutabledict-4.2.1 llvmlite-0.44.0 loguru-0.7.3 numba-0.61.2 openpyxl-3.1.5 ortools-9.14.6206 ply-3.11 pony-0.7.19 protobuf-6.31.1 pyomo-6.9.2 ruamel.yaml-0.18.14 ruamel.yaml.clib-0.2.12 svg.py-1.6.0 utm-0.8.1 windIO-1.1.1
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.

Import

[3]:
import numpy as np
from scipy.interpolate import RegularGridInterpolator
import matplotlib.pyplot as plt

from topfarm.constraint_components.spacing import SpacingConstraint
from topfarm.constraint_components.boundary import XYBoundaryConstraint
from topfarm.easy_drivers import EasyScipyOptimizeDriver
from topfarm.cost_models.cost_model_wrappers import CostModelComponent
from topfarm._topfarm import TopFarmProblem, TopFarmGroup
from topfarm.cost_models.py_wake_wrapper import PyWakeAEPCostModelComponent
from topfarm.plotting import XYPlotComp
from topfarm.utils import plot_list_recorder
from topfarm.cost_models.economic_models.dtu_wind_cm_main import economic_evaluation

from py_wake.examples.data.iea37._iea37 import IEA37_WindTurbines
from py_wake import BastankhahGaussian
from py_wake.examples.data.hornsrev1 import Hornsrev1Site

from ed_win.wind_farm_network import WindFarmNetwork
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[3], line 19
     16 from py_wake import BastankhahGaussian
     17 from py_wake.examples.data.hornsrev1 import Hornsrev1Site
---> 19 from ed_win.wind_farm_network import WindFarmNetwork

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/ed_win/wind_farm_network.py:12
     10 import os
     11 import xarray as xr
---> 12 from windIO.utils.yml_utils import load_yaml, Loader
     13 from ed_win.drivers.drivers_api import InterArray
     14 from ed_win.drivers.interarray.interface import assign_cables

ModuleNotFoundError: No module named 'windIO.utils'

Site

[4]:
n_wt = 30
initial = np.asarray([np.random.random(30)*6000, np.random.random(30)*-10000]).T
x_init = initial[:,0]
y_init = initial[:,1]
boundary = np.array([(0, 0), (6000, 0), (6000, -10000), (0, -10000)])  # turbine boundaries
drivers = [EasyScipyOptimizeDriver(maxiter=10)]
windTurbines = IEA37_WindTurbines()
site = Hornsrev1Site()
wfm = BastankhahGaussian(site, windTurbines)

/builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/py_wake/deficit_models/gaussian.py:124: UserWarning: The BastankhahGaussian model is not representative of the setup used in the literature. For this, use py_wake.literature.gaussian_models.Bastankhah_PorteAgel_2014 instead
  DeprecatedModel.__init__(self, 'py_wake.literature.gaussian_models.Bastankhah_PorteAgel_2014')

Bathymetry

[5]:
sigma = 3000.0
mu = 0.0

x_peak_1 = 1000
y_peak_1 = -1000
x_peak_2 = 4000
y_peak_2 = -8000
x1, y1 = np.meshgrid(np.linspace(0 - x_peak_1, 6000- x_peak_1, 100), np.linspace(-10000 - y_peak_1, 0 - y_peak_1, 100))
d1 = np.sqrt(x1*x1 + y1*y1)
g1 = np.exp(-((d1 - mu)**2 / (2.0 * sigma**2)))
x2, y2 = np.meshgrid(np.linspace(0 - x_peak_2, 6000- x_peak_2, 100), np.linspace(-10000 - y_peak_2, 0 - y_peak_2, 100))
d2 = np.sqrt(x2*x2 + y2*y2)
g2 = np.exp(-((d2 - mu)**2 / (2.0 * sigma**2)))
g = 5 * g1 - 8 * g2 - 30

plt.imshow(g, extent=(-1000, 7000, -11000, 1000), origin='lower', cmap='viridis')
plt.colorbar()
plt.title('2D Gaussian Function')
plt.show()

x = np.linspace(-1000, 7000, 100)
y = np.linspace(-11000, 1000, 100)

f = RegularGridInterpolator((x, y), g)
../_images/notebooks_cables_11_0.png

Cables

[6]:
x_ss_init = x_init.mean()
y_ss_init = y_init.mean()
turbines_pos=np.asarray([x_init, y_init]).T
substations_pos = np.asarray([[x_ss_init], [y_ss_init]]).T

cables = np.array([[500, 3, 100], [800, 5, 150], [1000, 10, 250]])  # Here you set up cables [<cable cross section>, <number of turbines can be connected>, <price in € per meter>]

wfn = WindFarmNetwork(turbines_pos=turbines_pos, substations_pos=substations_pos, cables=cables)
G = wfn.optimize(turbines_pos)
cable_cost_ref = G.size(weight="cost")  # euro
cable_length_ref = G.size(weight="length")  # m
cost_per_length_ref = cable_cost_ref / cable_length_ref # euro / m

G.plot()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[6], line 8
      4 substations_pos = np.asarray([[x_ss_init], [y_ss_init]]).T
      6 cables = np.array([[500, 3, 100], [800, 5, 150], [1000, 10, 250]])  # Here you set up cables [<cable cross section>, <number of turbines can be connected>, <price in € per meter>]
----> 8 wfn = WindFarmNetwork(turbines_pos=turbines_pos, substations_pos=substations_pos, cables=cables)
      9 G = wfn.optimize(turbines_pos)
     10 cable_cost_ref = G.size(weight="cost")  # euro

NameError: name 'WindFarmNetwork' is not defined

Economy

[7]:
Drotor_vector = [windTurbines.diameter()] * n_wt
power_rated_vector = [float(windTurbines.power(20))*1e-6] * n_wt
hub_height_vector = [windTurbines.hub_height()] * n_wt

# add additional cost model inputs for shore distance, energy price, project lifetime, rated rotor speed and water depth
distance_from_shore = 30         # [km]
energy_price = 0.1               # [Euro/kWh] What we get per kWh
project_duration = 25            # [years]
rated_rpm_array = [12] * n_wt    # [rpm]
simres = wfm(x_init, y_init)
aep = simres.aep().values.sum()
CF = aep / (windTurbines.power(20)*1e-9 * 24*365*n_wt)

eco_eval = economic_evaluation(distance_from_shore, energy_price, project_duration)
npv_ref = eco_eval.calculate_npv(rated_rpm_array, Drotor_vector, power_rated_vector, hub_height_vector, 30, aep/n_wt * np.ones(n_wt)*10**6, cabling_cost=cable_cost_ref)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[7], line 15
     12 CF = aep / (windTurbines.power(20)*1e-9 * 24*365*n_wt)
     14 eco_eval = economic_evaluation(distance_from_shore, energy_price, project_duration)
---> 15 npv_ref = eco_eval.calculate_npv(rated_rpm_array, Drotor_vector, power_rated_vector, hub_height_vector, 30, aep/n_wt * np.ones(n_wt)*10**6, cabling_cost=cable_cost_ref)

NameError: name 'cable_cost_ref' is not defined

Python Functions

[8]:
# Water Depth
def water_depth_func(x, y, **kwargs):
    xnew, ynew = np.meshgrid(x, y)
    points = np.array([xnew.flatten(), ynew.flatten()]).T
    return - np.diag(f(points).reshape(n_wt, n_wt).T)

# Cables
def cable_func(x, y, x_substation, y_substation, **kwargs):
    G = wfn.optimize(turbines_pos= np.asarray([x, y]).T, substations_pos=np.asarray([[float(x_substation[0])], [float(y_substation[0])]]).T)
    return G.size(weight="cost"), {'cabling_length': G.size(weight="length")}

# Economy
def npv_func(AEP, water_depth, cabling_cost, **kwargs):
    eco_eval.calculate_npv(rated_rpm_array, Drotor_vector, power_rated_vector, hub_height_vector, water_depth, AEP/n_wt * np.ones(n_wt)*10**6, cabling_cost=cabling_cost)
    eco_eval.calculate_irr(rated_rpm_array, Drotor_vector, power_rated_vector, hub_height_vector, water_depth, AEP/n_wt * np.ones(n_wt)*10**6, cabling_cost=cabling_cost)
    CAPEX = eco_eval.project_costs_sums["CAPEX"]
    OPEX = eco_eval.project_costs_sums["OPEX"]
    return eco_eval.NPV, {'irr': eco_eval.IRR,
                          'OPEX': OPEX,
                          'CAPEX': CAPEX,}

Components

[9]:
# Water Depth
water_depth_component = CostModelComponent(input_keys=[('x', x_init),('y', y_init)],
                                          n_wt=n_wt,
                                          cost_function=water_depth_func,
                                          objective=False,
                                          output_keys=[('water_depth', np.zeros(n_wt))])

# Cables
cable_component = CostModelComponent(input_keys=[('x', x_init),('y', y_init), ('x_substation', x_ss_init), ('y_substation', y_ss_init)],
                                     n_wt=n_wt,
                                     cost_function=cable_func,
                                     objective=False,
                                     output_keys=[('cabling_cost', 0)],
                                     additional_output=[('cabling_length', 0)])

# Economy
npv_comp = CostModelComponent(input_keys=[('AEP', 0), ('water_depth', 30*np.ones(n_wt)), ('cabling_cost', 100000)],
                              n_wt=n_wt,
                              cost_function=npv_func,
                              objective=True,
                              maximize=True,
                              output_keys=[('npv', 0)],
                              additional_output=[('irr', 0),
                                                 ('CAPEX', 0),
                                                 ('OPEX', 0)])

# AEP
aep_comp = PyWakeAEPCostModelComponent(wfm, n_wt, objective=False)

Problem Assembly

[10]:
cost_comp = TopFarmGroup([PyWakeAEPCostModelComponent(wfm, n_wt, objective=False), water_depth_component, cable_component, npv_comp])


tf = TopFarmProblem(
    design_vars=dict(zip('xy', initial.T), x_substation=x_ss_init, y_substation=y_ss_init),
    cost_comp=cost_comp,
    constraints=[XYBoundaryConstraint(boundary),
                 SpacingConstraint(500)
                 ],
    driver=drivers[0],
    plot_comp=XYPlotComp()
)

INFO: checking out_of_order...
INFO:     out_of_order check complete (0.000515 sec).
INFO: checking system...
INFO:     system check complete (0.000019 sec).
INFO: checking solvers...
INFO:     solvers check complete (0.000134 sec).
INFO: checking dup_inputs...
INFO:     dup_inputs check complete (0.000034 sec).
INFO: checking missing_recorders...
INFO:     missing_recorders check complete (0.000004 sec).
INFO: checking unserializable_options...
INFO:     unserializable_options check complete (0.000172 sec).
INFO: checking comp_has_no_outputs...
INFO:     comp_has_no_outputs check complete (0.000039 sec).
INFO: checking auto_ivc_warnings...
INFO:     auto_ivc_warnings check complete (0.000002 sec).

Optimize

[11]:
cost, _, recorder = tf.optimize()

INFO: checking out_of_order...
INFO:     out_of_order check complete (0.000183 sec).
INFO: checking system...
INFO:     system check complete (0.000016 sec).
INFO: checking solvers...
INFO:     solvers check complete (0.000124 sec).
INFO: checking dup_inputs...
INFO:     dup_inputs check complete (0.000036 sec).
INFO: checking missing_recorders...
INFO:     missing_recorders check complete (0.000004 sec).
INFO: checking unserializable_options...
INFO:     unserializable_options check complete (0.000159 sec).
INFO: checking comp_has_no_outputs...
INFO:     comp_has_no_outputs check complete (0.000030 sec).
INFO: checking auto_ivc_warnings...
INFO:     auto_ivc_warnings check complete (0.000003 sec).
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/system.py:2876, in System._call_user_function(self, fname, protect_inputs, protect_outputs, protect_residuals)
   2875 try:
-> 2876     yield
   2877 except Exception:

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/explicitcomponent.py:279, in ExplicitComponent._compute_wrapper(self)
    278 else:
--> 279     self.compute(self._inputs, self._outputs)

File /builds/TOPFARM/TopFarm2/topfarm/cost_models/cost_model_wrappers.py:166, in CostModelComponent.compute(self, inputs, outputs)
    165 if self.additional_output:
--> 166     c, additional_output = self.cost_function(**{x: inputs[x] for x in self.all_input_keys})
    167     for k, v in additional_output.items():

Cell In[8], line 9, in cable_func(x, y, x_substation, y_substation, **kwargs)
      8 def cable_func(x, y, x_substation, y_substation, **kwargs):
----> 9     G = wfn.optimize(turbines_pos= np.asarray([x, y]).T, substations_pos=np.asarray([[float(x_substation[0])], [float(y_substation[0])]]).T)
     10     return G.size(weight="cost"), {'cabling_length': G.size(weight="length")}

NameError: name 'wfn' is not defined

During handling of the above exception, another exception occurred:

NameError                                 Traceback (most recent call last)
Cell In[11], line 1
----> 1 cost, _, recorder = tf.optimize()

File /builds/TOPFARM/TopFarm2/topfarm/_topfarm.py:500, in TopFarmProblem.optimize(self, state, disp, recorder_as_list)
    498 self.setup()
    499 t = time.time()
--> 500 self.run_driver()
    501 self.cleanup()
    502 if disp:

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/problem.py:732, in Problem.run_driver(self, case_prefix, reset_iter_counts)
    728     record_model_options(self, self._run_counter)
    730     model._clear_iprint()
--> 732     return driver._run()
    733 finally:
    734     self._recording_iter.prefix = old_prefix

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/driver.py:822, in Driver._run(self)
    820 else:
    821     with SaveOptResult(self):
--> 822         self.result.success = not self.run()
    824 return self.result

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/drivers/scipy_optimizer.py:268, in ScipyOptimizeDriver.run(self)
    266 with RecordingDebugging(self._get_name(), self.iter_count, self):
    267     with model._relevance.nonlinear_active('iter'):
--> 268         self._run_solve_nonlinear()
    269     self.iter_count += 1
    271 self._con_cache = self.get_constraint_values()

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/driver.py:178, in DriverResult.track_stats.<locals>._track_time.<locals>.wrapper(*args, **kwargs)
    175 @functools.wraps(func)
    176 def wrapper(*args, **kwargs):
    177     start_time = time.perf_counter()
--> 178     ret = func(*args, **kwargs)
    179     end_time = time.perf_counter()
    180     result = args[0].result

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/driver.py:1268, in Driver._run_solve_nonlinear(self)
   1266 @DriverResult.track_stats(kind='model')
   1267 def _run_solve_nonlinear(self):
-> 1268     return self._problem().model.run_solve_nonlinear()

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/system.py:5004, in System.run_solve_nonlinear(self)
   4998 """
   4999 Compute outputs.
   5000
   5001 This calls _solve_nonlinear, but with the model assumed to be in an unscaled state.
   5002 """
   5003 with self._scaled_context_all():
-> 5004     self._solve_nonlinear()

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/group.py:3644, in Group._solve_nonlinear(self)
   3642 with Recording(name + '._solve_nonlinear', self.iter_count, self):
   3643     with self._relevance.active(self._nonlinear_solver.use_relevance()):
-> 3644         self._nonlinear_solver._solve_with_cache_check()

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/solvers/nonlinear/nonlinear_runonce.py:26, in NonlinearRunOnce._solve_with_cache_check(self)
     25 def _solve_with_cache_check(self):
---> 26     self.solve()

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/solvers/nonlinear/nonlinear_runonce.py:45, in NonlinearRunOnce.solve(self)
     41             subsys._solve_nonlinear()
     43 # If this is not a parallel group, transfer for each subsystem just prior to running it.
     44 else:
---> 45     self._gs_iter()
     47 rec.abs = 0.0
     48 rec.rel = 0.0

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/solvers/solver.py:900, in NonlinearSolver._gs_iter(self)
    898 if subsys._is_local:
    899     try:
--> 900         subsys._solve_nonlinear()
    901     except AnalysisError as err:
    902         if 'reraise_child_analysiserror' not in self.options or \
    903                 self.options['reraise_child_analysiserror']:

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/group.py:3644, in Group._solve_nonlinear(self)
   3642 with Recording(name + '._solve_nonlinear', self.iter_count, self):
   3643     with self._relevance.active(self._nonlinear_solver.use_relevance()):
-> 3644         self._nonlinear_solver._solve_with_cache_check()

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/solvers/nonlinear/nonlinear_runonce.py:26, in NonlinearRunOnce._solve_with_cache_check(self)
     25 def _solve_with_cache_check(self):
---> 26     self.solve()

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/solvers/nonlinear/nonlinear_runonce.py:45, in NonlinearRunOnce.solve(self)
     41             subsys._solve_nonlinear()
     43 # If this is not a parallel group, transfer for each subsystem just prior to running it.
     44 else:
---> 45     self._gs_iter()
     47 rec.abs = 0.0
     48 rec.rel = 0.0

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/solvers/solver.py:900, in NonlinearSolver._gs_iter(self)
    898 if subsys._is_local:
    899     try:
--> 900         subsys._solve_nonlinear()
    901     except AnalysisError as err:
    902         if 'reraise_child_analysiserror' not in self.options or \
    903                 self.options['reraise_child_analysiserror']:

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/explicitcomponent.py:305, in ExplicitComponent._solve_nonlinear(self)
    303 self._residuals.set_val(0.0)
    304 with self._unscaled_context(outputs=[self._outputs]):
--> 305     self._compute_wrapper()

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/explicitcomponent.py:259, in ExplicitComponent._compute_wrapper(self)
    255 def _compute_wrapper(self):
    256     """
    257     Call compute based on the value of the "run_root_only" option.
    258     """
--> 259     with self._call_user_function('compute'):
    260         if self._run_root_only():
    261             if self.comm.rank == 0:

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/contextlib.py:158, in _GeneratorContextManager.__exit__(self, typ, value, traceback)
    156     value = typ()
    157 try:
--> 158     self.gen.throw(value)
    159 except StopIteration as exc:
    160     # Suppress StopIteration *unless* it's the same exception that
    161     # was passed to throw().  This prevents a StopIteration
    162     # raised inside the "with" statement from being suppressed.
    163     return exc is not value

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/system.py:2882, in System._call_user_function(self, fname, protect_inputs, protect_outputs, protect_residuals)
   2880         raise
   2881     else:
-> 2882         raise err_type(
   2883             f"{self.msginfo}: Error calling {fname}(), {err}").with_traceback(trace)
   2884 finally:
   2885     self._inputs.read_only = False

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/system.py:2876, in System._call_user_function(self, fname, protect_inputs, protect_outputs, protect_residuals)
   2873 self._residuals.read_only = protect_residuals
   2875 try:
-> 2876     yield
   2877 except Exception:
   2878     err_type, err, trace = sys.exc_info()

File /builds/TOPFARM/TopFarm2/.pixi/envs/default/lib/python3.12/site-packages/openmdao/core/explicitcomponent.py:279, in ExplicitComponent._compute_wrapper(self)
    276     self.compute(self._inputs, self._outputs,
    277                  self._discrete_inputs, self._discrete_outputs)
    278 else:
--> 279     self.compute(self._inputs, self._outputs)

File /builds/TOPFARM/TopFarm2/topfarm/cost_models/cost_model_wrappers.py:166, in CostModelComponent.compute(self, inputs, outputs)
    164 t = time.time()
    165 if self.additional_output:
--> 166     c, additional_output = self.cost_function(**{x: inputs[x] for x in self.all_input_keys})
    167     for k, v in additional_output.items():
    168         outputs[k] = v

Cell In[8], line 9, in cable_func(x, y, x_substation, y_substation, **kwargs)
      8 def cable_func(x, y, x_substation, y_substation, **kwargs):
----> 9     G = wfn.optimize(turbines_pos= np.asarray([x, y]).T, substations_pos=np.asarray([[float(x_substation[0])], [float(y_substation[0])]]).T)
     10     return G.size(weight="cost"), {'cabling_length': G.size(weight="length")}

NameError: 'cost_comp.comp_2' <class CostModelComponent>: Error calling compute(), name 'wfn' is not defined

Plot

[12]:
plot_list_recorder(recorder)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[12], line 1
----> 1 plot_list_recorder(recorder)

NameError: name 'recorder' is not defined
[13]:
x_opt = recorder['x'][-1]
y_opt = recorder['y'][-1]
x_sub_opt = recorder['x_substation'][-1]
y_sub_opt = recorder['y_substation'][-1]
G = wfn.optimize(np.asarray([x_opt, y_opt]).T,
                 substations_pos=np.asarray([[float(x_sub_opt)], [float(y_sub_opt)]]).T,
                 )
G.plot()

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[13], line 1
----> 1 x_opt = recorder['x'][-1]
      2 y_opt = recorder['y'][-1]
      3 x_sub_opt = recorder['x_substation'][-1]

NameError: name 'recorder' is not defined
[ ]: