Skip to content

Commit

Permalink
Merge branch 'develop' into weis
Browse files Browse the repository at this point in the history
  • Loading branch information
dzalkind committed Mar 10, 2021
2 parents 7d28a6f + b813a22 commit 15976f5
Show file tree
Hide file tree
Showing 28 changed files with 1,263 additions and 820 deletions.
7 changes: 3 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ _build
*.out
*.outb
*.dbg
*.vtp

# ROSCO files
*.85
Expand All @@ -48,13 +49,11 @@ examples/cp_ct_cq_lut.p
Examples/DISCON.IN
Examples/*.p

# Matlab Stuff
Matlab_Toolbox/*.slxc
*.mat

# Exclude testing results
ROSCO_testing/results/

# Simulink/Matlab temp files
*.slxc
*.autosave
*.mat

2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "ROSCO"]
path = ROSCO
url = https://github.com/NREL/ROSCO
branch = develop
branch = main
86 changes: 43 additions & 43 deletions Examples/DISCON.IN

Large diffs are not rendered by default.

203 changes: 96 additions & 107 deletions Matlab_Toolbox/Simulink/ROSCO.mdl

Large diffs are not rendered by default.

85 changes: 6 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ NREL's Reference OpenSource Controller (ROSCO) toolbox for wind turbine applicat
* Simple 1-DOF turbine simulations for quick controller capability verifications
* Parsing of OpenFAST input and output files

Block diagrams of these capabilities can be seen in [architecture.png](architecture.png).

## Introduction
The NREL Reference OpenSource Controller (ROSCO) provides an open, modular and fully adaptable baseline wind turbine controller to the scientific community. The ROSCO toolbox leverages this architecture and implementation to provide a generic tuning process for the controller. Because of the open character and modular set-up, scientists are able to collaborate and contribute in making continuous improvements to the code for the controller and the toolbox. The ROSCO toolbox is a mostly-python code base with a number of functionalities.
Expand All @@ -16,95 +15,23 @@ The NREL Reference OpenSource Controller (ROSCO) provides an open, modular and f
* [Matlab_Toolbox](https://github.com/NREL/ROSCO_toolbox/tree/master/Matlab_Toolbox) - MATLAB scripts to parse and plot simulation output data.
* [ofTools](https://github.com/NREL/ROSCO_toolbox/tree/master/ofTools) - A number of scripts to facilitate usage of OpenFAST and manage OpenFAST input and output files.

## Using the ROSCO Toolbox
Here is a short (but _hopefully_ sweet) installation and run process for basic controller tuning...

### Installing the complete ROSCO Toolbox
Installation of the complete ROSCO toolbox is made easy through [Anaconda](https://www.anaconda.com/). If you do not already have Anaconda installed on your machine, please install it. If you cannot install Anaconda, you can install the ROSCO toolbox without first initiating a conda environment (step 1), but will need to follow the detailed installatino instructions of [WISDEM](https://github.com/WISDEM/WISDEM) and [ROSCO](https://github.com/NREL/ROSCO.git) from their respective github pages.

For users who have access to anaconda, please follow steps 1-3/4 below.

1. #### Create a conda environment for ROSCO
```
conda config --add channels conda-forge
conda create -y --name rosco-env python=3.8
conda activate rosco-env
```

2. #### Install WISDEM
```
conda install -y wisdem
```

You should then do step three _OR_ four. If you do not want to compile the ROSCO controller within the installation of the ROSCO toolbox, please follow the instruction on the controller's [github page]((https://github.com/NREL/ROSCO.git)).

3. #### Clone and Install the ROSCO toolbox with ROSCO
```
git clone https://github.com/NREL/ROSCO_toolbox.git
cd ROSCO_toolbox
git submodule init
git submodule update
conda install compilers # (Mac/Linux only)
conda install m2w64-toolchain libpython # (Windows only)
python setup.py install --compile-rosco
```

4. #### Clone and Install the ROSCO toolbox _without_ ROSCO
```
git clone https://github.com/NREL/ROSCO_toolbox.git
cd ROSCO_toolbox
python setup.py install
```

### Alternatively...
If you wish to write your own scripts to leverage the ROSCO toolbox tools, but do not necessarily need the source code or to run any of the examples, the ROSCO toolbox is available via PyPi:
```
pip install rosco_toolbox
```
Note that if you do choose to install the ROSCO Toolbox this way, you will not have the source code. Additionally, you will need to download WISDEM and the ROSCO controller separately if you wish to use any of the ROSCO toolbox functionalities that need those software packages.

#### Compiling ROSCO
The controller itself is installed as a submodule in the ROSCO toolbox. For further information on compiling and running ROSCO itself, or to download the release binaries directly, we point you to the [ROSCO github page](https://github.com/NREL/ROSCO_toolbox.git). If you wish to re-compile the ROSOCO toolbox, cmake provides easy to compiling on Unix based systems. In order to compile the controller, you should run the following commands from the ROSCO_toolbox folder.
```
cd ROSCO
mkdir build
cd build
cmake ..
make
```
Those familiar with mingw on windows can also compile ROSCO similarly.

These commands will compile a binary titled `libdiscon.*` in the build folder, which is the binary necessary run the controller. This should only need to be compiled once. The extension should be `.dll`, `.so`, or `.dylib`, depending on the user operating system.

### Running ROSCO with Generic Tuning
The [Tune_Cases](Tune_Cases) folder hosts examples on what needs to happen to write the input file to the ROSCO controller. See below on some details for compiling ROSCO:

#### ROSCO Toolbox Generic Tuning
IF you would like to run the generic tuning process for ROSCO, examples are shown in the [Tune_Cases](Tune_Cases) folder. When you run your own version of [tune_ROSCO.py](Tune_Cases/tune_ROSCO.py), you will have two files that are necessary to run the controller.
1. `DISCON.IN` (or similar) - the input file to `libdiscon.*`. When running the controller in OpenFAST, `DISCON.IN` must be appropriately pointed to by the `DLL_FileName` parameter in ServoDyn.
2. `Cp_Cq_Ct.txt` (or similar) - This file contains rotor performance tables that are necessary to run the wind speed estimators in ROSCO. This can live wherever you desire, just be sure to point to it properly with the `PerfFileName` parameter in `DISCON.IN`.

### Updating ROSCO Toolbox
Simple git commands should update the toolbox and controller as development continues:
```
git pull
git submodule update
```
and then recompile and reinstall as necessary...
## Documentation
All relevant documentation about the ROSCO toolbox and ROSCO controller can be found at through [ROSCO's readthedocs webpage](https://rosco-toolbox.readthedocs.io/en/latest/). Here, users can find the information on [installing the ROSCO toolbox](https://rosco-toolbox.readthedocs.io/en/latest/source/install.html#installing-the-rosco-toolbox) and [compiling ROSCO](https://rosco-toolbox.readthedocs.io/en/latest/source/install.html#compiling-rosco) for control purposes. Additionally, there is information on the standard workflow and uses cases for the ROSCO toolchain, and more.

## Referencing
If the ROSCO Toolbox played a role in your research, please cite it. This software can be
cited as:

ROSCO. Version 1.0.0 (2020). Available at https://github.com/nrel/rosco_toolbox.
NREL: ROSCO Toolbox. Version 2.2.0, https://github.com/NREL/rosco_toolbox, 2021.

For LaTeX users:

```
@misc{ROSCO_toolbox_2019,
@misc{ROSCO_toolbox_2021,
author = {NREL},
title = {{ROSCO Toolbox. Version 0.1.0}},
year = {2019},
title = {{ROSCO Toolbox. Version 2.2.0}},
year = {2021},
publisher = {GitHub},
journal = {GitHub repository},
url = {https://github.com/NREL/rosco_toolbox}
Expand Down
2 changes: 1 addition & 1 deletion ROSCO
48 changes: 48 additions & 0 deletions ROSCO_testing/ROSCO_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
from ROSCO_toolbox.ofTools.fast_io.FAST_reader import InputReader_OpenFAST
from ROSCO_toolbox.ofTools.case_gen.CaseGen_IEC import CaseGen_IEC
from ROSCO_toolbox.ofTools.case_gen.runFAST_pywrapper import runFAST_pywrapper_batch
from matplotlib.backends.backend_pdf import FigureCanvasPdf, PdfPages
from ROSCO_toolbox.ofTools.fast_io import output_processing
import matplotlib.pyplot as plt



Expand Down Expand Up @@ -238,6 +241,8 @@ def ROSCO_Test_lite(self, more_case_inputs={}, U=[]):
else:
fastBatch.run_serial()

self.print_results(outFileNames)


def ROSCO_Test_heavy(self, more_case_inputs={}, U=[]):
'''
Expand Down Expand Up @@ -401,6 +406,8 @@ def ROSCO_Test_heavy(self, more_case_inputs={}, U=[]):
else:
fastBatch.run_serial()

self.print_results(outFileNames)

def ROSCO_Controller_Comp(self, controller_paths, testtype='light', more_case_inputs={}, U=[]):
'''
Heavy or light testing for n controllers, n = len(controller_paths)
Expand Down Expand Up @@ -468,6 +475,47 @@ def ROSCO_DISCON_Comp(self, DISCON_filenames, testtype='light', more_case_inputs
self.runDir = run_dir_init
self.windDir = wind_dir_init

def print_results(self,outfiles):

op = output_processing.output_processing()
FAST_Output = op.load_fast_out(outfiles, tmin=0)

figs_fname = 'test_outputs.pdf'
with PdfPages(os.path.join(self.runDir,figs_fname)) as pdf:
for fast_out in FAST_Output:
if self.FAST_InputFile == 'NREL-5MW.fst':
plots2make = {'Baseline': ['Wind1VelX', 'GenPwr', 'RotSpeed', 'BldPitch1', 'GenTq']}
else:
plots2make = {'Baseline': ['Wind1VelX', 'GenPwr', 'RotSpeed', 'BldPitch1', 'GenTq','PtfmPitch']}

numplots = len(plots2make)
maxchannels = np.max([len(plots2make[key]) for key in plots2make.keys()])
fig = plt.figure(figsize=(8,6), constrained_layout=True)
gs_all = fig.add_gridspec(1, numplots)
for pnum, (gs, pname) in enumerate(zip(gs_all, plots2make.keys())):
gs0 = gs.subgridspec(len(plots2make[pname]),1)
for cid, channel in enumerate(plots2make[pname]):
subplt = fig.add_subplot(gs0[cid])
try:
subplt.plot(fast_out['Time'], fast_out[channel])
unit_idx = fast_out['meta']['channels'].index(channel)
subplt.set_ylabel('{:^} \n ({:^})'.format(
channel,
fast_out['meta']['attribute_units'][unit_idx]))
subplt.grid(True)
subplt.set_xlabel('Time (s)')
except:
print('Cannot plot {}'.format(channel))
if cid == 0:
subplt.set_title(pname)
if cid != len(plots2make[pname])-1:
subplt.axes.get_xaxis().set_visible(False)

plt.suptitle(fast_out['meta']['name'])
pdf.savefig(fig)
plt.close()


if __name__=='__main__':
rt = ROSCO_testing()

Expand Down
11 changes: 5 additions & 6 deletions ROSCO_testing/run_Testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ def run_testing(turbine2test, testtype, rosco_binaries=[], discon_files=[], **kw
if turbine2test == 'NREL-5MW':
rt.Turbine_Class = 'I'
rt.Turbulence_Class = 'A'
rt.FAST_directory = os.path.join(os.path.dirname(__file__), '../Test_Cases/NREL-5MW')
rt.FAST_directory = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../Test_Cases/NREL-5MW')
rt.FAST_InputFile = 'NREL-5MW.fst'
elif turbine2test == 'IEA-15MW':
rt.Turbine_Class = 'I'
rt.Turbulence_Class = 'B'
rt.FAST_directory = os.path.join(os.path.dirname(__file__), '../Test_Cases/IEA-15-240-RWT-UMaineSemi')
rt.FAST_directory = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../Test_Cases/IEA-15-240-RWT-UMaineSemi')
rt.FAST_InputFile = 'IEA-15-240-RWT-UMaineSemi.fst'
else:
raise ValueError('{} is not an available turbine to test!'.format(turbine2test))
Expand All @@ -79,11 +79,11 @@ def run_testing(turbine2test, testtype, rosco_binaries=[], discon_files=[], **kw
if __name__ == "__main__":

# WEIS directory, for running openfast, etc.
this_dir = os.path.dirname(__file__)
this_dir = os.path.dirname(os.path.realpath(__file__))

# Setup ROSCO testing parameters
rt_kwargs = {}
rt_kwargs['runDir'] = os.path.join(this_dir,'results/') # directory for FAST simulations
rt_kwargs['runDir'] = os.path.join(this_dir,'results/IEA-15MW') # directory for FAST simulations
rt_kwargs['namebase'] = 'lite_test' # Base name for FAST files
rt_kwargs['FAST_exe'] = 'openfast' # OpenFAST executable path
rt_kwargs['Turbsim_exe']= 'turbsim' # Turbsim executable path
Expand All @@ -97,13 +97,12 @@ def run_testing(turbine2test, testtype, rosco_binaries=[], discon_files=[], **kw
rt_kwargs['outfile_fmt'] = 2 # 1 = .txt, 2 = binary, 3 = both

# ---- Define test type ----
turbine2test = 'NREL-5MW' # IEA-15MW or NREL-5MW
turbine2test = 'IEA-15MW' # IEA-15MW or NREL-5MW
testtype = 'lite' # lite, heavy, binary-comp, discon-comp

# Only fill one of these if comparing controllers
rosco_binaries = [glob.glob(os.path.join(this_dir,'../ROSCO/build/libdiscon.*'))[0]] # Differently named libdiscons to compare
discon_files = [] # Differently named DISCON.IN files to compare


# Run testing
run_testing(turbine2test, testtype, rosco_binaries=rosco_binaries, discon_files=discon_files, **rt_kwargs)
26 changes: 26 additions & 0 deletions ROSCO_testing/submit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
#SBATCH --account=ssc
#SBATCH --time=1:00:00
#SBATCH --job-name=rosco_test
#SBATCH --nodes=1 # This should be nC/36 (36 cores on eagle)
#SBATCH --ntasks-per-node=36
#SBATCH --mail-user [email protected]
#SBATCH --mail-type BEGIN,END,FAIL
#SBATCH --output=output.%j.out
#SBATCH --partition=debug

nDV=1 # Number of design variables (x2 for central difference)
nOF=60 # Number of openfast runs per finite-difference evaluation
nC=$((nDV + nDV * nOF)) # Number of cores needed. Make sure to request an appropriate number of nodes = N / 36
## nC=72

source activate /home/dzalkind/.conda-envs/weis-env4
which python

# module purge
# module load conda
# module load comp-intel intel-mpi mkl


python run_Testing.py
# python weis_driver.py
4 changes: 2 additions & 2 deletions ROSCO_toolbox/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Top-level package for ROSCO_toolbox Repo."""

__author__ = """Nikhar J. Abbas and Paul Fleming"""
__author__ = """Nikhar J. Abbas and Daniel S. Zalkind"""
__email__ = '[email protected]'
__version__ = '2.1.1'
__version__ = '2.2.0'
2 changes: 1 addition & 1 deletion Test_Cases/BAR_10/BAR_10_ServoDyn.dat
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ False CompNTMD - Compute nacelle tuned mass damper {true/fal
False CompTTMD - Compute tower tuned mass damper {true/false} (flag)
"b.dat" TTMDfile - Name of the file for tower tuned mass damper (quoted string) [unused when CompTTMD is false]
---------------------- BLADED INTERFACE ---------------------------------------- [used only with Bladed Interface]
"../../ROSCO/build/libdiscon.dylib" DLL_FileName - Name/location of the dynamic library {.dll [Windows] or .so [Linux]} in the Bladed-DLL format (-) [used only with Bladed Interface]
"../../ROSCO/install/lib/libdiscon.dylib" DLL_FileName - Name/location of the dynamic library {.dll [Windows] or .so [Linux]} in the Bladed-DLL format (-) [used only with Bladed Interface]
"BAR_10_DISCON.IN" DLL_InFile - Name of input file sent to the DLL (-) [used only with Bladed Interface]
"DISCON" DLL_ProcName - Name of procedure in DLL to be called (-) [case sensitive; used only with DLL Interface]
"default" DLL_DT - Communication interval for dynamic library (s) (or "default") [used only with Bladed Interface]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ False CompNTMD - Compute nacelle tuned mass damper {true/fal
False CompTTMD - Compute tower tuned mass damper {true/false} (flag)
"unused" TTMDfile - Name of the file for tower tuned mass damper (quoted string) [unused when CompTTMD is false]
---------------------- BLADED INTERFACE ---------------------------------------- [used only with Bladed Interface]
"../../ROSCO/build/libdiscon.dylib" DLL_FileName - Name/location of the dynamic library {.dll [Windows] or .so [Linux]} in the Bladed-DLL format (-) [used only with Bladed Interface]
"../../ROSCO/install/lib/libdiscon.dylib" DLL_FileName - Name/location of the dynamic library {.dll [Windows] or .so [Linux]} in the Bladed-DLL format (-) [used only with Bladed Interface]
"ServoData/DISCON-UMaineSemi.IN" DLL_InFile - Name of input file sent to the DLL (-) [used only with Bladed Interface]
"DISCON" DLL_ProcName - Name of procedure in DLL to be called (-) [case sensitive; used only with DLL Interface]
"default" DLL_DT - Communication interval for dynamic library (s) (or "default") [used only with Bladed Interface]
Expand Down
Loading

0 comments on commit 15976f5

Please sign in to comment.