Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
f8730d9
Improved OM driver interface, take II (#123)
cfrontin Aug 22, 2025
15cc417
WindIO conversion (#120)
cfrontin Aug 27, 2025
a00fd14
Merge branch 'develop' into offshore-development
cfrontin Aug 28, 2025
e77d174
some changes
cfrontin Aug 28, 2025
6b32547
update the offshore example to run
cfrontin Aug 28, 2025
46e3d53
tests passing
cfrontin Aug 28, 2025
c9f5a6f
add data
cfrontin Aug 28, 2025
5c281e0
incidental cleanup and some renaming
cfrontin Sep 2, 2025
c08d920
update to examples
cfrontin Sep 2, 2025
1ba5e3d
fix the floris issue
cfrontin Sep 2, 2025
3d73b85
Merge branch 'hotfix/floris_zeroed_prob' into offshore-development
cfrontin Sep 2, 2025
efd1191
actual fix
cfrontin Sep 3, 2025
09d3dc8
black config
cfrontin Sep 3, 2025
fc34bec
Merge branch 'hotfix/floris_zeroed_prob' into offshore-development
cfrontin Sep 3, 2025
0a04f27
Clarify thrust data unpacking process w/ git reference
cfrontin Sep 3, 2025
4d44de5
streamline based on copilot suggestion
cfrontin Sep 3, 2025
9c36b59
fix failing floris test
cfrontin Sep 3, 2025
7ea4722
Merge branch 'hotfix/floris_zeroed_prob' into offshore-development
cfrontin Sep 3, 2025
2f68d1c
Change optiwindnet version constraint to exact match
cfrontin Sep 3, 2025
0f7d8aa
Merge branch 'hotfix/floris_zeroed_prob' into offshore-development
cfrontin Sep 3, 2025
fc37bd2
adjust boundary to be in standard metric meters rather than km
cfrontin Sep 3, 2025
a41db3b
Hotfix/floris zeroed prob (#127)
cfrontin Sep 3, 2025
50cd8b4
updates
cfrontin Sep 3, 2025
f0ba753
Merge branch 'develop' into offshore-development
cfrontin Sep 3, 2025
264bac1
update example
cfrontin Sep 3, 2025
726c8bf
fix system tests for boundary adjustment
cfrontin Sep 3, 2025
1ac4536
Refactor boundary distance and validation assertions
cfrontin Sep 4, 2025
518e9ed
fix example 03, and add modified ard system
cfrontin Sep 4, 2025
d114658
Merge branch 'offshore-development' of github.com:cfrontin/Ard into o…
cfrontin Sep 4, 2025
52e6fa2
black reformat
cfrontin Sep 4, 2025
be1e4b9
Merge branch 'WISDEM:offshore-development' into offshore-development
cfrontin Sep 4, 2025
586e3ea
update offshore problem
cfrontin Sep 8, 2025
f9c4dfc
Merge branch 'offshore-development' of github.com:cfrontin/Ard into o…
cfrontin Sep 8, 2025
ddd7cbc
WIP: adding flowers
bayc Sep 9, 2025
29f191b
Merge branch 'develop' into feature/flowers
cfrontin Sep 9, 2025
03cd371
working python interface when connected to cfrontin/flowers@4a798599e…
cfrontin Sep 9, 2025
4ba408b
add example
cfrontin Sep 9, 2025
70d1728
black reformat and gradients turned on for flowers
cfrontin Sep 9, 2025
d8f0b92
Merge branch 'feature/flowers' into offshore-development
cfrontin Sep 9, 2025
096dbbf
add flowers to system file in example
cfrontin Sep 9, 2025
3978fdb
use windIO parser
cfrontin Sep 9, 2025
46f9518
Merge branch 'feature/flowers' into offshore-development
cfrontin Sep 9, 2025
fa2e922
flowers enabled optimization problem turned on in offshore example
cfrontin Sep 10, 2025
5c4f8c9
brought an adjustment in
cfrontin Sep 10, 2025
0bfedd0
Merge branch 'feature/flowers' into offshore-development
cfrontin Sep 10, 2025
735f16c
cherrypick some improvements for beta out of offshore-development
cfrontin Sep 11, 2025
9fa8446
black update
cfrontin Sep 11, 2025
fe8c976
Merge branch 'develop' into feature/flowers
cfrontin Sep 11, 2025
24d5f62
Merge branch 'offshore-development' into develop
cfrontin Sep 11, 2025
98cc4d1
black reformat
cfrontin Sep 11, 2025
cfee272
Merge branch 'develop' into offshore-development
cfrontin Sep 11, 2025
a7e9d98
black reformat
cfrontin Sep 11, 2025
f18787a
Merge branch 'develop' into feature/flowers
cfrontin Sep 11, 2025
e272004
Merge branch 'develop' into offshore-development
cfrontin Sep 11, 2025
f5c0df6
Cherry-pick key general improvements from offshore-development for be…
cfrontin Sep 12, 2025
a6e2074
Docs overhaul (#133)
cfrontin Sep 15, 2025
142495a
Merge branch 'develop' into offshore-development
cfrontin Sep 15, 2025
4223f1a
oops missed one
cfrontin Sep 15, 2025
199210d
Merge branch 'develop' into feature/flowers
cfrontin Sep 15, 2025
97c03a3
fix: make optiwindnet wrapper compatible with optiwindnet v0.0.6 (#135)
mdealencar Sep 15, 2025
58855f6
remove funky merge stuff
cfrontin Sep 17, 2025
7efcbdc
Merge branch 'develop' into offshore-development
cfrontin Sep 17, 2025
f16effe
make sure wrg is deleted
cfrontin Sep 17, 2025
f7fa11d
Fix badge link in README.md
cfrontin Sep 17, 2025
1f6f728
working on offshore problem updates
cfrontin Sep 19, 2025
1fddaa1
switched collection and orbit to pass terse_links w/ zero deriv
cfrontin Sep 23, 2025
5d8c1c7
update flowers stuff
cfrontin Sep 23, 2025
121a6f0
fix to floris reference height
cfrontin Sep 23, 2025
1b125b4
Merge remote-tracking branch 'upstream/develop' into develop
cfrontin Sep 23, 2025
59a1633
Merge branch 'develop' into feature/flowers
cfrontin Sep 23, 2025
3e318af
add test script
cfrontin Sep 23, 2025
8443e60
update after floris ref height and density fix
cfrontin Sep 23, 2025
4867e5f
Merge branch 'develop' into feature/flowers
cfrontin Sep 23, 2025
96a19ff
add resampling
cfrontin Sep 23, 2025
696e22c
remove extraneous wrg file
cfrontin Sep 23, 2025
d6064a1
Merge branch 'feature/flowers' into offshore-development
cfrontin Sep 23, 2025
ca400bb
black reformat
cfrontin Sep 23, 2025
c8c7f93
Merge branch 'develop' into feature/flowers
cfrontin Sep 23, 2025
fde45a7
equilibriate wind rose resampling
cfrontin Sep 23, 2025
bf825c7
update to resampler
cfrontin Sep 23, 2025
e0d0966
Merge branch 'feature/flowers' into offshore-development
cfrontin Sep 23, 2025
5954e68
fix lookup for resample
cfrontin Sep 23, 2025
713bb41
Merge branch 'feature/flowers' into offshore-development
cfrontin Sep 23, 2025
88d9815
add a little more
cfrontin Sep 23, 2025
2be6c26
Merge branch 'feature/flowers' into offshore-development
cfrontin Sep 23, 2025
3a7760b
updates for milestone claim
cfrontin Sep 30, 2025
6ee8702
black reformat
cfrontin Sep 30, 2025
77d9620
black reformat and add notebook
cfrontin Sep 30, 2025
3bd4483
black reformat
cfrontin Sep 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/workflows/python-tests-consolidated.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,83 @@ jobs:
cwd=str(path_script.parent),
env=env,
)

find-examples_nb:
name: Find all example notebooks
needs: [test-unit, test-system]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Find example python notebooks
id: find_notebooks
run: |
echo "scripts<<EOF"
find examples -mindepth 2 -maxdepth 2 -name "*.ipynb" | jq -R -s -c 'split("\n")[:-1]'
echo "EOF"
echo "scripts<<EOF" >> $GITHUB_OUTPUT
find examples -mindepth 2 -maxdepth 2 -name "*.ipynb" | jq -R -s -c 'split("\n")[:-1]' >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
outputs:
scripts: ${{ steps.find_notebooks.outputs.scripts }}

test-examples_nb:
name: Run all example notebooks
needs: find-examples_nb
strategy:
fail-fast: false
matrix:
python-version: [3.12] # ["3.10", "3.11", "3.12", "3.13"]
os: [macos-latest, ubuntu-latest, windows-latest]
include:
- os: ubuntu-latest
path: ~/.cache/pip
- os: macos-latest
path: ~/Library/Caches/pip
- os: windows-latest
path: ~\AppData\Local\pip\Cache
script: ${{fromJson( needs.find-examples_nb.outputs.scripts )}}
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Get cache dependencies
id: cache
uses: actions/cache@v4
with:
path: ${{ matrix.path }}
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
restore-keys:
${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- name: Install Ard
run: |
pip install .[dev]
- name: Run examples
shell: python
run: |
import os
import pathlib
import subprocess

env = os.environ.copy()
env["MPLBACKEND"] = "Agg" # Non-interactive backend

path_script = pathlib.Path("${{ matrix.script }}").absolute()
print(f"RUNNING {path_script}")
subprocess.run(
["jupyter", "nbconvert", "--execute", "--to", "notebook", str(path_script.name)],
check=True,
cwd=str(path_script.parent),
env=env,
)
94 changes: 54 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
[![CI/CD test suite](https://github.com/WISDEM/Ard/actions/workflows/python-tests-consolidated.yaml/badge.svg?branch=develop)](https://github.com/WISDEM/Ard/actions/workflows/python-tests-consolidated.yaml)

# Ard

**Dig into wind farm design.**
[![CI/CD test suite](https://github.com/WISDEM/Ard/actions/workflows/python-tests-consolidated.yaml/badge.svg?branch=develop)](https://github.com/WISDEM/Ard/actions/workflows/python-tests-consolidated.yaml/badge.svg?branch=develop)

![Ard logo](assets/logomaker/logo.png)

**Dig in to wind farm design.**

<!-- The (aspirationally) foolproof tool for preparing wind farm layouts. -->

[An ard is a type of simple and lightweight plow](https://en.wikipedia.org/wiki/Ard_\(plough\)), used through the single-digit centuries to prepare a farm for planting.
The intent of `Ard` is to be a modular, full-stack multi-disciplinary optimization tool for wind farms.

The problem with wind farms is that they are complicated, multi-disciplinary objects.
They are aerodynamic machines, with complicated control systems, power electronic devices, social and political objects, and the core value (and cost) of complicated financial instruments.
Moreover, the design of *one* of these aspects affects all the rest!
Wind farms are complicated, multi-disciplinary systems.
They are aerodynamic machines (composed of complicated control systems, power electronic devices, etc.), social and political objects, generators of electrical power and consumers of electrical demand, and the core value generator (and cost) of complicated financial instruments.
Moreover, the design of any *one* of these aspects affects all the rest!

`Ard` seeks to make plant-level design choices that can incorporate these different aspects _and their interactions_ to make wind energy projects more successful.
`Ard` is a platform for wind farm layout optimization that seeks to enable plant-level design choices that can incorporate these different aspects _and their interactions_ to make wind energy projects more successful.
In brief, we are designing `Ard` to be: principled, modular, extensible, and effective, to allow resource-specific wind farm layout optimization with realistic, well-posed constraints, holistic and complex objectives, and natural incorporation of multiple fidelities and disciplines.

## Documentation
Ard documentation is available at [https://wisdem.github.io/Ard/]()
Expand Down Expand Up @@ -45,7 +50,6 @@ For a basic and static installation, type:
```shell
pip install .
```

For development (and really for everyone during pre-release), we recommend a full development installation:
```shell
pip install -e .[dev,docs]
Expand All @@ -60,59 +64,69 @@ mamba install wisdem -y
pip install -e .[dev,docs]
```

To test the installation, from the `Ard` folder run unit and regression tests:
## Testing instructions

The installation can be tested comprehensively using `pytest` from the top-level directory.
The developers also provide some convenience scripts for testing new installations; from the `Ard` folder run unit and regression tests:
```shell
source test/run_local_test_unit.sh
source test/run_local_test_system.sh
```
These enable the generation of HTML-based coverage reports by default and can be used to track "coverage", or the percentage of software lines of code that are run by the testing systems.
`Ard`'s git repository includes requirements for both the `main` and `develop` branches to have 80% coverage on unit testing and 50% testing in system testing, which are, respectively, tests of individual parts of `Ard` and "systems" composed of multiple parts.
Failures are not tolerated in code that is merged onto these branches and code found therein *should* never cause a testing failure if it has been found there.
If the process of installation and testing fails, please open a new issue [here](https://github.com/WISDEM/Ard/issues).

For user information, in pre-release, we are using some co-developed changes to the `FLORIS` library.

If the installation fails, please open a new issue [here](https://github.com/WISDEM/Ard/issues).
## Design philosophy

## OptiWindNet
The design of `Ard` was inspired by two use cases in particular:
1) systems energy researchers who are focusing on one specific subdiscipline (e.g. layout strategies, social impacts, or aerodynamic modeling) but want to be able to easily keep track of how a change in one discipline impacts the entire value chain down to production, cost, value, and/or societal outcomes of energy or even optimize with respect to these, and
2) private industry researchers who run business cases and may want to drop in proprietary analysis modules for specific disciplines while preserving some of the open-source modules of `Ard`.

We currently have experimental support for [Mauricio Souza de Alencar's OptiWindNet package for collection system cable path-planning optimization](https://gitlab.windenergy.dtu.dk/TOPFARM/OptiWindNet).
`Ard` is being developed as a modular tool to enable these types of research queries.
The goals during the development of `Ard` are to be:
1) principled:
- robustly documented
- adhering to [best-practices for code development](https://doi.org/10.2172/2479115)
2) modular and extensible:
- choose the analysis components you want
- skip the ones you don't
- build yourself the ones we don't have
3) effective
- robustly tested and testable at both unit and system levels
These principles guide us to implement, using [`OpenMDAO`](https://openmdao.org) as a backbone, a multi-disciplinary design, analysis, and optimization (MDAO) model of the wind farm layout problem, a toolset to accomplish the capability goals of `Ard`, to:
1) allow optimization of wind farm layouts for specific wind resource profiles
2) enable the incorporation of realistic but well-posed constraints
3) target holistic and complex system-level optimization objectives like LCOE and beyond-LCOE metrics
4) naturally incorporate analyses across fidelities to efficiently integrate advanced simulation

## Current capabilities

For the alpha pre-release of `Ard`, we have concentrated on optimization of wind plants, starting from a structured layout and optimizing it to minimize the levelized cost of energy, or LCOE.
This capability is demonstrated for a land-based (LB) wind farm in `examples/LCOE_LB_stack` and tested in an abridged form in `test/system/LCOE_stack/test_LCOE_LB_stack.py`.
In this example, the wind farm layout is parametrized with two angles, named orientation and skewed, and turbine distancing for rows and columns.
In the alpha pre-release stage, the constituent subcomponents of these problems are known to work and fully tested; any capabilities not touched in the layout-to-LCOE stack should be treated as experimental.
For the beta pre-release of `Ard`, we concentrate on optimization problems for wind plants, starting from structured layouts to minimize LCOE.
This capability is demonstrated for a land-based (LB) wind farm in `examples/01_onshore` and tested in an abridged form in `test/system/ard/api/test_LCOE_LB_stack.py`.
In this example, the wind farm layout is parametrized with two angles, named orientation and skew, and turbine distancing for rows and columns.
Additionally, we have offshore examples adjacent to the onshore example in the `examples` subdirectory.
In the beta pre-release stage, the constituent subcomponents of these problems are known to work and have full testing coverage.

These cases start from a four parameter farm layout, compute landuse area, make FLORIS AEP estimates, compute turbine capital costs, balance-of-station (BOS), and operational costs using WISDEM components, and finally give summary estimates of plant finance figures.
These cases start from a four parameter farm layout, compute land use area, make FLORIS estimates of annual energy production (AEP), compute turbine capital costs, balance-of-station (BOS), and operational costs elements of NREL's turbine systems engineering tool [WISDEM](https://github.com/wisdem/wisdem), and finally give summary estimates of plant finance figures.
The components that achieve this can be assembled to either run a single top-down analysis run, or run an optimization.

A second example is in progress to reoptimize the layout of two offshore wind farms, one fixed bottom (OFB) and one floating (OFL).
Both wind farms are made of the [22 MW reference wind turbine](https://github.com/IEAWindSystems/IEA-22-280-RWT).
In this example, BOS costs are estimated using the tool [ORBIT](https://github.com/WISDEM/ORBIT).
# Contributing to `Ard`

## Roadmap to future capabilities

The future development of `Ard` is centered around two user cases:
1) systems energy researchers who are focusing on one specific subdiscipline (e.g. layout strategies, social impacts, or aerodynamic modeling) but want to be able to easily keep track of how it impacts the entire value chain down to production, cost, and/or value of energy or even optimize with respect to it, and
2) private industry researchers who are interested in how public-sector research results change when proprietary analysis tools are dropped in and coupled the other tools in a systems-level simulation.

`Ard` is being developed as a modular tool to enable these types of research queries.
This starts from our research goals, which are that `Ard` should be:
1) principled: fully documented, and adhering to best-practices for code development
2) modular and extensible: choose the parts you want, skip the ones you don't, build yourself the ones we don't have
3) effective: fully tested and testable at the unit and system level, and built with a derivative-forward approach

This, then, allows us to attempt to accomplish the technical goals of `Ard`, to:
1) allow optimization of wind farm layouts for specific wind resource profiles
2) target wholistic and complex system-level optimization objectives like LCOE and beyond-LCOE metrics
3) naturally incorporate multi-fidelity analyses to efficiently integrate physics-resolving simulation
We have striven towards best-practices documentation and testing for `Ard`.
Contribution is welcome, and we are happy [to field pull requests from github](https://github.com/WISDEM/Ard/pulls).
For acceptance, PRs must:
- be formatted using [`black`](https://github.com/psf/black)
- not fail any unit tests or system tests
- achieve coverage criteria for unit & system testing
- be documented enough for continued maintenance by core `Ard` developers

## Building Documentation

To build the documentation locally run the following from the top `Ard/` directory.

To build the documentation locally, run the following from the top-level `Ard/` directory:
```shell
jupyter-book build docs/
```

You can then open `Ard/docs/_build/html/index.html` to view the docs.

---
Expand Down
5 changes: 3 additions & 2 deletions ard/api/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ def set_up_ard_model(input_dict: Union[str, dict], root_data_path: str = None):
analysis_options=input_dict["analysis_options"],
)

prob.setup()

return prob


Expand Down Expand Up @@ -203,6 +205,7 @@ def set_up_system_recursive(
if "driver" in analysis_options:
Driver = getattr(om, analysis_options["driver"]["name"])

# handle DOE drivers with special treatment
if Driver == om.DOEDriver:
generator = None
if "generator" in analysis_options["driver"]:
Expand Down Expand Up @@ -278,6 +281,4 @@ def set_up_system_recursive(
units="m",
)

prob.setup()

return prob
60 changes: 45 additions & 15 deletions ard/collection/optiwindnet_wrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from optiwindnet.mesh import make_planar_embedding
from optiwindnet.interarraylib import L_from_site
from optiwindnet.heuristics import EW_presolver
from optiwindnet.MILP import solver_factory, ModelOptions
from optiwindnet.MILP import OWNWarmupFailed, solver_factory, ModelOptions

from . import templates

Expand Down Expand Up @@ -69,6 +69,9 @@ class OptiwindnetCollection(templates.CollectionTemplate):
-------
total_length_cables : float
the total length of cables used in the collection system network
terse_links : np.ndarray
a 1D numpy int array encoding the electrical connections of the collection
system (tree topology), with length `N_turbines`

Discrete Outputs
-------
Expand All @@ -81,14 +84,12 @@ class OptiwindnetCollection(templates.CollectionTemplate):
length `N_turbines`
max_load_cables : int
the maximum cable capacity required by the collection system
terse_links : np.ndarray
a 1D numpy int array encoding the electrical connections of the collection
system (tree topology), with length `N_turbines`
"""

def initialize(self):
"""Initialization of OM component."""
super().initialize()
self.S_previous: nx.Graph | None = None

def setup(self):
"""Setup of OM component."""
Expand All @@ -102,6 +103,13 @@ def setup_partials(self):
["x_turbines", "y_turbines", "x_substations", "y_substations"],
method="exact",
)
self.declare_partials(
["terse_links"],
["x_turbines", "y_turbines", "x_substations", "y_substations"],
method="exact",
val=0.0,
dependent=False,
)

def compute(
self,
Expand All @@ -126,20 +134,42 @@ def compute(
# create planar embedding and set of available links
P, A = make_planar_embedding(L)

# presolve
S_warm = EW_presolver(A, capacity=max_turbines_per_string)
solver = solver_factory(solver_name)

model_options = self.modeling_options["collection"]["model_options"]
# start from previous solution if available, else from heuristic if it fits
if self.S_previous is not None:
S_warm = self.S_previous
elif (
model_options.get("topology") == "branched"
and model_options.get("feeder_limit") == "unlimited"
and model_options.get("feeder_route") == "segmented"
):
S_warm = EW_presolver(A, capacity=max_turbines_per_string)
else:
S_warm = None

try:
solver.set_problem(
P,
A,
max_turbines_per_string,
ModelOptions(**model_options),
warmstart=S_warm,
)
except OWNWarmupFailed:
# the previous solution is no longer feasible
solver.set_problem(
P,
A,
max_turbines_per_string,
ModelOptions(**model_options),
)

# do the branch-and-bound MILP search
solver = solver_factory(solver_name)
solver.set_problem(
P,
A,
max_turbines_per_string,
ModelOptions(**self.modeling_options["collection"]["model_options"]),
warmstart=S_warm,
)
info = solver.solve(**self.modeling_options["collection"]["solver_options"])
S, G = solver.get_solution()
self.S_previous = S

# extract the outputs
terse_links = np.zeros((T,), dtype=np.int_)
Expand Down Expand Up @@ -178,14 +208,14 @@ def compute(
# pack and ship
self.graph = G
discrete_outputs["graph"] = G # TODO: remove for terse links, below!
discrete_outputs["terse_links"] = terse_links
discrete_outputs["length_cables"] = length_cables
discrete_outputs["load_cables"] = load_cables
discrete_outputs["max_load_cables"] = S.graph["max_load"]
# TODO: remove this assert after enough testing
assert (
abs(length_cables.sum() - G.size(weight="length")) < 1e-7
), f"difference: {length_cables.sum() - G.size(weight='length')}"
outputs["terse_links"] = terse_links
outputs["total_length_cables"] = length_cables.sum()

def compute_partials(self, inputs, J, discrete_inputs=None):
Expand Down
2 changes: 1 addition & 1 deletion ard/collection/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ def setup(self):

# set up outputs for the collection system
self.add_output("total_length_cables", 0.0, units="m")
self.add_output("terse_links", np.full((self.N_turbines,), -1))
self.add_discrete_output("length_cables", np.zeros((self.N_turbines,)))
self.add_discrete_output("terse_links", np.full((self.N_turbines,), -1))
self.add_discrete_output("load_cables", np.zeros((self.N_turbines,)))
self.add_discrete_output("max_load_cables", 0.0)
self.add_discrete_output("graph", None)
Expand Down
Loading
Loading