RAO#

The RAO class provides an interface for handling response amplitude operators (RAOs). RAO extends Grid, and contains RAO values on a two-dimentional frequency/(wave)direction grid.

\[H(\omega, \theta)\]

The RAO class is initialized with a frequency list (1-D array), a direction list (1-D array) and corresponding RAO transfer function values as complex numbers (2-D array).

import numpy as np
import waveresponse as wr


freq = np.linspace(0.0, 1.0, 50)
dirs = np.linspace(0.0, 360.0, 10, endpoint=False)
vals_real = np.random.random((len(freq), len(dirs)))
vals_imag = np.random.random((len(freq), len(dirs)))
vals_complex = vals_real + 1j * vals_imag

rao = wr.RAO(
    freq,
    dirs,
    vals_complex,
    freq_hz=True,
    degrees=True,
)

Alternatively, you can construct an RAO object using amplitudes (2-D array) and phase (2-D array):

import numpy as np
import waveresponse as wr


freq = np.linspace(0.0, 1.0, 50)
dirs = np.linspace(0.0, 360.0, endpoint=False)
amp = np.random.random((len(freq), len(dirs)))
phase = np.random.random((len(freq), len(dirs)))

rao = wr.RAO.from_amp_phase(
    freq,
    dirs,
    amp,
    phase,
    phase_degrees=False,
    phase_leading=True,
    freq_hz=True,
    degrees=True,
)

The RAO class extends the Grid class with the following:

Retrieve the RAO’s frequency/direction coordinates and amplitude/phase values using to_amp_phase().

freq, dirs, amp, phase = rao.to_amp_phase(freq_hz=True, degrees=True)

Get the complex conjugate version of the RAO using conjugate().

rao_conj = rao.conjugate()

Differentiate the RAO’s transfer function to obtain an RAO object that represents the nth derivative of the original degree-of-freedom:

n = 1   # order of differentiation
rao_diff = rao.differentiate(n)

Note

If \(H_x(j\omega)\) is a transfer function for variable, \(x\), then the corresponding transfer function for the differentiated variable, \(\dot{x}\), is given by:

\[H_{\dot{x}}(\omega) = j\omega H_x(\omega)\]

Convert units#

You can convert an RAO object between different units simply by scaling the RAO’s values with an appropriate factor:

import numpy as np


# Convert RAO from 'deg/m' to 'rad/m'
deg2rad = np.pi / 180.0
rao = deg2rad * rao

# Convert RAO from 'rad/m' to 'deg/m'
rad2deg = 180.0 / np.pi
rao = rad2deg * rao

Tip

Rigid body transformation of RAOs require that the rotational degree-of-freedom RAOs represent angles in radians. Then, it can be useful to be able to convert an RAO from e.g. \([deg/m]\) units to \([rad/m]\) units. This is done by a scaling of the RAO values with a factor of \(\pi/180\):

\[H(\omega) \left[\frac{rad}{m}\right] = \frac{\pi}{180} \left[\frac{rad}{deg}\right] \cdot H(\omega) \left[\frac{deg}{m}\right]\]

Mirror an RAO about a symmetry plane#

If you have an RAO object defined only over half the directional domain (e.g., [0, 180) degrees), you may want to mirror this RAO about a symmetry plane to obtain an extended version of the RAO which is defined over the full directional domain (i.e., [0, 360) degrees). Symmetry mirroring is proveded by the mirror() function; the function takes an RAO object, a degree-of-freedom and a symmetry plane as input, and outputs a new, extended RAO object:

import waveresponse as wr

# Mirror heave rao about the xz-plane
rao_full = wr.mirror(rao, 'heave', sym_plane="xz")

Similarly, if you have an RAO object defined only in one quadrant (e.g., [0, 90] degrees), you can mirror this RAO twise to obtain the ‘full’ RAO:

import waveresponse as wr

# Mirror heave rao twise, first about the xz-plane and then about the yz-plane
rao_full = wr.mirror(wr.mirror(rao, "heave", sym_plane="xz"), "heave", sym_plane="yz")

Note

When using an RAO object in response estimation, it is important that the RAO is defined over the full directional domain.