Skip to content

Commit

Permalink
Adding NOTICE.txt and paper link to readthedocs:
Browse files Browse the repository at this point in the history
- Added NOTICE.txt for copyright/license statement.
- Tweaked documentation pages to give link to Torque paper
  and hide rough-draft theory scraps.
- Added a plotting option for showing/hiding the airfoil cords.
  • Loading branch information
mattEhall committed Aug 22, 2022
1 parent 274124e commit 5af4b7f
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 104 deletions.
15 changes: 15 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Copyright (c) 2022 Alliance for Sustainable Energy, LLC

RAFT (Response Amplitudes of Floating Turbines)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this software except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Binary file added docs/images/illustrations.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 33 additions & 25 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,41 +1,49 @@

.. toctree::
:maxdepth: 2
:hidden:

Home <self>
starting
structure
usage
theory

RAFT
====

Welcome to RAFT's online documentation!
RAFT Documentation
==================

RAFT (**R**\ esponse **A**\ mplitudes of **F**\ loating **T**\ urbines) is a
Python code for frequency-domain analysis of floating wind turbines. RAFT works in
the frequency domain to provide efficient computations of a floating wind
system's response spectra accounting for platform hydrodynamics, quasi-static
mooring reactions, rotor aerodynamics, and linearized control.
Python code for frequency-domain analysis of floating wind turbines. RAFT uses
quasi-static and frequency-domain models to provide efficient computations of
a floating wind system's response spectra accounting for platform hydrodynamics,
mooring reactions, rotor aerodynamics, and turbine control.
It can be used to calculate response amplitude
operators (RAO's), power spectral densities, mean/static properties, and
response metrics based on mean and root-mean-square values of each output.

RAFT serves as the lowest fidelity "Level 1" model in the WEIS
.. figure:: /images/illustrations.png
:align: center

Three reference designs represented in RAFT

RAFT serves as the lowest fidelity "Level 1" dynamics model in the WEIS
(Wind Energy with Integrated Servo-control)
toolset for multifidelity co-design of wind turbines. WEIS is a framework that
toolset for control co-design of floating wind turbines. WEIS is a framework that
combines multiple NREL-developed tools to enable design optimization of floating
offshore wind turbines. See the `WEIS documentation <https://weis.readthedocs.io>`_
and `GitHub repository <https://github.com/WISDEM/WEIS>`_ for more information.

Following a modular philosophy, RAFT can be used independently for various
frequency-domain modeling needs. Or, it can be used as an integrated part of
WEIS through its OpenMDAO wrapper.

.. toctree::
:maxdepth: 2
:hidden:

Home <self>
starting
structure
usage
theory


The pages available in the menu on the left provide more information about RAFT, and
the RAFT source code is available on GitHub `here <https://github.com/WISDEM/RAFT>`_.

WEIS through its OpenMDAO wrapper. The pages in this documentation site provide
some guidance on setting up and using RAFT, as well as understanding how RAFT
works.
RAFT is available from the `RAFT GitHub Repository <https://github.com/WISDEM/RAFT>`_
and is released under the Apache 2.0 open-source license.

The following paper provides an overview of RAFT's theory:

`M. Hall, S. Housner, D. Zalkind, P. Bortolotti, D. Ogden, and G. Barter,
“An Open-Source Frequency-Domain Model for Floating Wind Turbine Design Optimization,”
Journal of Physics: Conference Series, vol. 2265, no. 4, p. 042020, May 2022, DOI: 10.1088/1742-6596/2265/4/042020. <https://iopscience.iop.org/article/10.1088/1742-6596/2265/4/042020>`_
1 change: 1 addition & 0 deletions docs/structure.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ RAFT represents a floating wind turbine system as a collection of different obje

.. image:: /images/objects.JPG
:align: center
:width: 240px

Each of these objects corresponds to a class in python. The Model class contains
the full RAFT representation of a floating wind system. Within it, the FOWT class
Expand Down
151 changes: 79 additions & 72 deletions docs/theory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,75 +2,82 @@ Theory
=====================

The theory behind RAFT is in the process of being documented. This page will be incrementally updated.


Frequency Domain Equations of Motion
------------------------------------

The overall process of RAFT is to use the input design data of a FOWT to fill out the 6x6 matrices of the equations of motion.

.. math::
[M+A]\ddot{X}(t) + [B+B_{visc}]\dot{X}(t) + [C_{struc}+C_{hydro}+C_{moor}]X(t) = F_{env}(t)
F(t) = Re\{\tilde{F}e^{iwt}\}
\tilde{F} = \|F\|e^{i\phi}
X = Xe^{iwt}
\dot{X} = iwXe^{iwt}
\ddot{X} = -w^2Xe^{iwt}
X(\omega) = [-\omega^2A(\omega) + i \omega B(\omega) + C]^{-1} F(\omega)
A(\omega) = M + A_{BEM}(\omega) + A_{morison}(\omega) + A_{aero}(\omega)
B(\omega) = B_{BEM}(\omega) + B_{aero}(\omega) + B_{nonlinear-hydro-drag}(X)
C = C_{struc} + C_{hydro} + C_{moor}
F = F_{BEM}(\omega) + F_{hydro}(\omega) + F_{aero}(\omega) + F_{nonlinear-hydro-drag}(X)
Notice that the nonlinear-hydro-drag damping and forcing terms are a function of the platform positions, so these are iterated
until the positions (X) converge.


Member Theory
-------------

.. image:: /images/members1.JPG
:align: center

.. image:: /images/members2.JPG
:align: center
:width: 350px
:height: 350px

Mass & Inertia
^^^^^^^^^^^^^^
The 6x6 mass matrix is calculated for each member using the properties given in the input design yaml.
Members can be cylindrical or rectangular

Hydrostatics
^^^^^^^^^^^^
The 6x6 hydrostatic stiffness matrix is calculated for each member using the properties given in the input design yaml.

Hydrodynamics
^^^^^^^^^^^^^
The 6x6 hydrodynamic matrices for each member are calculated in one of two ways: a BEM solver, pyHAMS, or a Morison equation approximation



Rotor Theory
------------

The Rotor uses aerodynamic theory from WISDEM's CCBlade. Check out the `CCBlade documentation <https://wisdem.readthedocs.io/en/latest/wisdem/ccblade/index.html>`_
for more infomation.

Mooring Theory
--------------

RAFT uses the quasi-static mooring system modeler, MoorPy. Check out `the MoorPy documentation <https://moorpy.readthedocs.io/en/latest/>`_
for more information.
The following paper provides an overview:

`M. Hall, S. Housner, D. Zalkind, P. Bortolotti, D. Ogden, and G. Barter,
“An Open-Source Frequency-Domain Model for Floating Wind Turbine Design Optimization,”
Journal of Physics: Conference Series, vol. 2265, no. 4, p. 042020, May 2022, DOI: 10.1088/1742-6596/2265/4/042020. <https://iopscience.iop.org/article/10.1088/1742-6596/2265/4/042020>`_


..
COMMENTING OUT TILL IT'S UP TO DATE
Frequency Domain Equations of Motion
------------------------------------
The overall process of RAFT is to use the input design data of a FOWT to fill out the 6x6 matrices of the equations of motion.
.. math::
[M+A]\ddot{X}(t) + [B+B_{visc}]\dot{X}(t) + [C_{struc}+C_{hydro}+C_{moor}]X(t) = F_{env}(t)
F(t) = Re\{\tilde{F}e^{iwt}\}
\tilde{F} = \|F\|e^{i\phi}
X = Xe^{iwt}
\dot{X} = iwXe^{iwt}
\ddot{X} = -w^2Xe^{iwt}
X(\omega) = [-\omega^2A(\omega) + i \omega B(\omega) + C]^{-1} F(\omega)
A(\omega) = M + A_{BEM}(\omega) + A_{morison}(\omega) + A_{aero}(\omega)
B(\omega) = B_{BEM}(\omega) + B_{aero}(\omega) + B_{nonlinear-hydro-drag}(X)
C = C_{struc} + C_{hydro} + C_{moor}
F = F_{BEM}(\omega) + F_{hydro}(\omega) + F_{aero}(\omega) + F_{nonlinear-hydro-drag}(X)
Notice that the nonlinear-hydro-drag damping and forcing terms are a function of the platform positions, so these are iterated
until the positions (X) converge.
Member Theory
-------------
.. image:: /images/members1.JPG
:align: center
.. image:: /images/members2.JPG
:align: center
:width: 350px
:height: 350px
Mass & Inertia
^^^^^^^^^^^^^^
The 6x6 mass matrix is calculated for each member using the properties given in the input design yaml.
Members can be cylindrical or rectangular
Hydrostatics
^^^^^^^^^^^^
The 6x6 hydrostatic stiffness matrix is calculated for each member using the properties given in the input design yaml.
Hydrodynamics
^^^^^^^^^^^^^
The 6x6 hydrodynamic matrices for each member are calculated in one of two ways: a BEM solver, pyHAMS, or a Morison equation approximation
Rotor Theory
------------
The Rotor uses aerodynamic theory from WISDEM's CCBlade. Check out the `CCBlade documentation <https://wisdem.readthedocs.io/en/latest/wisdem/ccblade/index.html>`_
for more infomation.
Mooring Theory
--------------
RAFT uses the quasi-static mooring system modeler, MoorPy. Check out `the MoorPy documentation <https://moorpy.readthedocs.io/en/latest/>`_
for more information.
4 changes: 2 additions & 2 deletions raft/raft_fowt.py
Original file line number Diff line number Diff line change
Expand Up @@ -893,11 +893,11 @@ def saveTurbineOutputs(self, results, case, iCase, Xi0, Xi):
self.add_output('tower_maxMy_Mz', val=np.zeros(n_full_tow-1), units='kN*m', desc='distributed moment around tower-aligned x-axis corresponding to maximum fore-aft moment at tower base')
'''

def plot(self, ax, color='k', nodes=0, plot_rotor=True, station_plot=[]):
def plot(self, ax, color='k', nodes=0, plot_rotor=True, station_plot=[], airfoils=False):
'''plots the FOWT...'''

if plot_rotor:
self.rotor.plot(ax, r_ptfm=self.body.r6[:3], R_ptfm=self.body.R, color=color)
self.rotor.plot(ax, r_ptfm=self.body.r6[:3], R_ptfm=self.body.R, color=color, airfoils=airfoils)

# loop through each member and plot it
for mem in self.memberList:
Expand Down
5 changes: 3 additions & 2 deletions raft/raft_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,8 @@ def preprocess_HAMS(self, dw=0, wMax=0, dz=0, da=0):
self.fowtList[0].calcBEM(dw=dw, wMax=wMax, dz=dz, da=da)


def plot(self, ax=None, hideGrid=False, draw_body=True, color='k', nodes=0, xbounds=None, ybounds=None, zbounds=None, plot_rotor=True, station_plot=[]):
def plot(self, ax=None, hideGrid=False, draw_body=True, color='k', nodes=0,
xbounds=None, ybounds=None, zbounds=None, plot_rotor=True, airfoils=False, station_plot=[]):
'''plots the whole model, including FOWTs and mooring system...'''

# for now, start the plot via the mooring system, since MoorPy doesn't yet know how to draw on other codes' plots
Expand All @@ -808,7 +809,7 @@ def plot(self, ax=None, hideGrid=False, draw_body=True, color='k', nodes=0, xbou

# plot each FOWT
for fowt in self.fowtList:
fowt.plot(ax, color=color, nodes=nodes, plot_rotor=plot_rotor, station_plot=station_plot)
fowt.plot(ax, color=color, nodes=nodes, plot_rotor=plot_rotor, station_plot=station_plot, airfoils=airfoils)

if hideGrid:
ax.set_xticks([]) # Hide axes ticks
Expand Down
7 changes: 4 additions & 3 deletions raft/raft_rotor.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ def calcAeroServoContributions(self, case, ptfm_pitch=0, display=0):
return F_aero0, f_aero, a_aero, b_aero # B_aero, C_aero, F_aero0, F_aero


def plot(self, ax, r_ptfm=[0,0,0], R_ptfm=np.eye(3), azimuth=0, color='k'):
def plot(self, ax, r_ptfm=[0,0,0], R_ptfm=np.eye(3), azimuth=0, color='k', airfoils=False):
'''Draws the rotor on the passed axes, considering optional platform offset and rotation matrix, and rotor azimuth angle'''

# ----- blade geometry ----------
Expand Down Expand Up @@ -538,8 +538,9 @@ def plot(self, ax, r_ptfm=[0,0,0], R_ptfm=np.eye(3), azimuth=0, color='k'):
P2 = np.matmul(R_ptfm, P2) + np.array(r_ptfm)[:,None]

# drawing airfoils
#for ii in range(m-1):
# ax.plot(P2[0, npts*ii:npts*(ii+1)], P2[1, npts*ii:npts*(ii+1)], P2[2, npts*ii:npts*(ii+1)])
if airfoils:
for ii in range(m-1):
ax.plot(P2[0, npts*ii:npts*(ii+1)], P2[1, npts*ii:npts*(ii+1)], P2[2, npts*ii:npts*(ii+1)], color=color, lw=0.4)
# draw outline
ax.plot(P2[0, 0:-1:npts], P2[1, 0:-1:npts], P2[2, 0:-1:npts], color=color, lw=0.4, zorder=2) # leading edge
ax.plot(P2[0, 2:-1:npts], P2[1, 2:-1:npts], P2[2, 2:-1:npts], color=color, lw=0.4, zorder=2) # trailing edge
Expand Down

0 comments on commit 5af4b7f

Please sign in to comment.