"""
Common joint model structure are predefined in this module.
"""
import numpy as np
from virocon import (
WeibullDistribution,
LogNormalDistribution,
ExponentiatedWeibullDistribution,
DependenceFunction,
WidthOfIntervalSlicer,
variable_transform,
)
__all__ = [
"get_DNVGL_Hs_Tz",
"get_DNVGL_Hs_U",
"get_OMAE2020_Hs_Tz",
"get_OMAE2020_V_Hs",
"get_Windmeier_EW_Hs_S",
"get_Nonzero_EW_Hs_S",
]
[docs]def get_DNVGL_Hs_Tz():
"""
Get DNVGL significant wave height and wave period model.
Get the descriptions necessary to create th significant wave height
and wave period model as defined in DNVGL [1]_ in section 3.6.3.
Returns
-------
dist_descriptions : list of dict
List of dictionaries containing the dist descriptions for each dimension.
Can be used to create a GlobalHierarchicalModel.
fit_descriptions : None
Default fit is used so None is returned.
Can be passed to fit function of GlobalHierarchicalModel.
semantics : dict
Dictionary with a semantic description of the model.
Can be passed to plot functions.
References
----------
.. [1] DNV GL (2017). Recommended practice DNVGL-RP-C205: Environmental
conditions and environmental loads.
"""
# TODO docstrings with links to literature
# DNVGL 3.6.3
def _power3(x, a, b, c):
return a + b * x**c
def _exp3(x, a, b, c):
return a + b * np.exp(c * x)
bounds = [(0, None), (0, None), (None, None)]
power3 = DependenceFunction(_power3, bounds, latex="$a + b * x^c$")
exp3 = DependenceFunction(_exp3, bounds, latex="$a + b * \exp(c * x)$")
dist_description_hs = {
"distribution": WeibullDistribution(),
"intervals": WidthOfIntervalSlicer(width=0.5),
}
dist_description_tz = {
"distribution": LogNormalDistribution(),
"conditional_on": 0,
"parameters": {"mu": power3, "sigma": exp3},
}
dist_descriptions = [dist_description_hs, dist_description_tz]
fit_descriptions = None
semantics = {
"names": ["Significant wave height", "Zero-up-crossing period"],
"symbols": ["H_s", "T_z"],
"units": ["m", "s"],
}
return dist_descriptions, fit_descriptions, semantics
[docs]def get_DNVGL_Hs_U():
"""
Get DNVGL significant wave height and wind speed model.
Get the descriptions necessary to create the significant wave height
and wind speed model as defined in DNVGL [2]_ in section 3.6.4.
Returns
-------
dist_descriptions : list of dict
List of dictionaries containing the dist descriptions for each dimension.
Can be used to create a GlobalHierarchicalModel.
fit_descriptions : None
Default fit is used so None is returned.
Can be passed to fit function of GlobalHierarchicalModel.
semantics : dict
Dictionary with a semantic description of the model.
Can be passed to plot functions.
References
----------
.. [2] DNV GL (2017). Recommended practice DNVGL-RP-C205: Environmental
conditions and environmental loads.
"""
def _power3(x, a, b, c):
return a + b * x**c
bounds = [(0, None), (0, None), (None, None)]
alpha_dep = DependenceFunction(_power3, bounds=bounds, latex="$a + b * x^c$")
beta_dep = DependenceFunction(_power3, bounds=bounds, latex="$a + b * x^c$")
dist_description_hs = {
"distribution": WeibullDistribution(),
"intervals": WidthOfIntervalSlicer(width=0.5, min_n_points=20),
}
dist_description_u = {
"distribution": WeibullDistribution(f_gamma=0),
"conditional_on": 0,
"parameters": {
"alpha": alpha_dep,
"beta": beta_dep,
},
}
dist_descriptions = [dist_description_hs, dist_description_u]
fit_descriptions = None
semantics = {
"names": ["Significant wave height", "Wind speed"],
"symbols": ["H_s", "U"],
"units": ["m", "m s$^{-1}$"],
}
return dist_descriptions, fit_descriptions, semantics
[docs]def get_OMAE2020_Hs_Tz():
"""
Get OMAE2020 significant wave height and wave period model.
Get the descriptions necessary to create the significant wave height
and wave period model as described by Haselsteiner et al. [3]_.
Returns
-------
dist_descriptions : list of dict
List of dictionaries containing the dist descriptions for each dimension.
Can be used to create a GlobalHierarchicalModel.
fit_descriptions : list of dict
List of dictionaries containing the fit description for each dimension.
Can be passed to fit function of GlobalHierarchicalModel.
semantics : dict
Dictionary with a semantic description of the model.
Can be passed to plot functions.
References
----------
.. [3] Haselsteiner, A.F.; Sander, A.; Ohlendorf, J.H.; Thoben, K.D. (2020)
Global hierarchical models for wind and wave contours: Physical
interpretations of the dependence functions. OMAE 2020, Fort Lauderdale,
USA. Proceedings of the 39th International Conference on Ocean,
Offshore and Arctic Engineering.
"""
def _asymdecrease3(x, a, b, c):
return a + b / (1 + c * x)
def _lnsquare2(x, a, b, c):
return np.log(a + b * np.sqrt(np.divide(x, 9.81)))
bounds = [(0, None), (0, None), (None, None)]
sigma_dep = DependenceFunction(
_asymdecrease3, bounds=bounds, latex="$a + b / (1 + c * x)$"
)
mu_dep = DependenceFunction(
_lnsquare2, bounds=bounds, latex="$\ln(a + b \sqrt{x / 9.81})$"
)
dist_description_hs = {
"distribution": ExponentiatedWeibullDistribution(),
"intervals": WidthOfIntervalSlicer(width=0.5, min_n_points=50),
}
dist_description_tz = {
"distribution": LogNormalDistribution(),
"conditional_on": 0,
"parameters": {
"sigma": sigma_dep,
"mu": mu_dep,
},
}
dist_descriptions = [dist_description_hs, dist_description_tz]
fit_description_hs = {"method": "wlsq", "weights": "quadratic"}
fit_descriptions = [fit_description_hs, None]
semantics = {
"names": ["Significant wave height", "Zero-up-crossing period"],
"symbols": ["H_s", "T_z"],
"units": ["m", "s"],
}
return dist_descriptions, fit_descriptions, semantics
[docs]def get_OMAE2020_V_Hs():
"""
Get OMAE2020 wind speed and significant wave height model.
Get the descriptions necessary to create the wind speed and
significant wave height model as described by Haselsteiner et al. [4]_.
Returns
-------
dist_descriptions : list of dict
List of dictionaries containing the dist descriptions for each dimension.
Can be used to create a GlobalHierarchicalModel.
fit_descriptions : list of dict
List of dictionaries containing the fit description for each dimension.
Can be passed to fit function of GlobalHierarchicalModel.
semantics : dict
Dictionary with a semantic description of the model.
Can be passed to plot functions.
References
----------
.. [4] Haselsteiner, A.F.; Sander, A.; Ohlendorf, J.H.; Thoben, K.D. (2020)
Global hierarchical models for wind and wave contours: Physical
interpretations of the dependence functions. OMAE 2020, Fort Lauderdale,
USA. Proceedings of the 39th International Conference on Ocean,
Offshore and Arctic Engineering.
"""
def _logistics4(x, a=1, b=1, c=-1, d=1):
return a + b / (1 + np.exp(c * (x - d)))
def _alpha3(x, a, b, c, d_of_x):
return (a + b * x**c) / 2.0445 ** (1 / d_of_x(x))
logistics_bounds = [(0, None), (0, None), (None, 0), (0, None)]
alpha_bounds = [(0, None), (0, None), (None, None)]
beta_dep = DependenceFunction(
_logistics4,
logistics_bounds,
weights=lambda x, y: y,
latex="$a + b / (1 + \exp[c * (x -d)])$",
)
alpha_dep = DependenceFunction(
_alpha3,
alpha_bounds,
d_of_x=beta_dep,
weights=lambda x, y: y,
latex="$(a + b * x^c) / 2.0445^{1 / F()}$",
)
dist_description_v = {
"distribution": ExponentiatedWeibullDistribution(),
"intervals": WidthOfIntervalSlicer(2, min_n_points=50),
}
dist_description_hs = {
"distribution": ExponentiatedWeibullDistribution(f_delta=5),
"conditional_on": 0,
"parameters": {
"alpha": alpha_dep,
"beta": beta_dep,
},
}
dist_descriptions = [dist_description_v, dist_description_hs]
fit_description_v = {"method": "wlsq", "weights": "quadratic"}
fit_description_hs = {"method": "wlsq", "weights": "quadratic"}
fit_descriptions = [fit_description_v, fit_description_hs]
semantics = {
"names": ["Wind speed", "Significant wave height"],
"symbols": ["V", "H_s"],
"units": [
"m s$^{-1}$",
"m",
],
}
return dist_descriptions, fit_descriptions, semantics
[docs]def get_Windmeier_EW_Hs_S():
"""
Get Windmeier's EW sea state model.
Get the descriptions necessary to create the significant wave height - steepness
model that was proposed by Windmeier [5]_. Both, Hs and Steepness follow
an exponentiated Weibull distribution.
Because the model is defined in Hs-steepness space it must be transformed to
Hs-Tz for contour calculation.
Returns
-------
dist_descriptions : list of dict
List of dictionaries containing the dist descriptions for each dimension.
Can be used to create a GlobalHierarchicalModel.
fit_descriptions : None
Default fit is used so None is returned.
Can be passed to fit function of GlobalHierarchicalModel.
semantics : dict
Dictionary with a semantic description of the model.
Can be passed to plot functions.
transformations : dict
References
----------
.. [5] Windmeier, K.-L. (2022). Modeling the statistical distribution of sea state
parameters [Master Thesis, University of Bremen]. https://doi.org/10.26092/elib/2181
"""
def _linear2(x, a=0, b=1):
return a + b * x
def _limited_growth2(x, a=0.08, b=1):
# Some people call this equatoin "negative exponential equation"
# https://www.statforbiology.com/nonlinearregression/usefulequations#negative_exponential_equation
return a * (1 - np.exp(-b * x))
def _transform(hs_tz):
hs = hs_tz[:, 0]
tz = hs_tz[:, 1]
s, _ = variable_transform.hs_tz_to_s_d(hs, tz)
return np.c_[hs, s]
def _inv_transform(hs_s):
hs = hs_s[:, 0]
s = hs_s[:, 1]
hs, tz = variable_transform.hs_s_to_hs_tz(hs, s)
return np.c_[hs, tz]
def _jacobian(hs_s):
hs = hs_s[:, 0]
s = hs_s[:, 1]
return 2 * variable_transform.factor * hs / s**3
linear_2_bounds = [(0, None), (0, None)]
limited_growth2_bounds = [(0, 1), (0, None)]
linear2 = DependenceFunction(_linear2, bounds=linear_2_bounds)
limited_growth2 = DependenceFunction(
_limited_growth2, bounds=limited_growth2_bounds
)
dist_description_hs = {
"distribution": ExponentiatedWeibullDistribution(),
"intervals": WidthOfIntervalSlicer(width=0.5, min_n_points=50),
}
dist_description_s = {
"distribution": ExponentiatedWeibullDistribution(f_delta=2.35),
"conditional_on": 0,
"parameters": {"alpha": limited_growth2, "beta": linear2},
}
dist_descriptions = [dist_description_hs, dist_description_s]
fit_description_hs = {"method": "wlsq", "weights": "quadratic"}
fit_descriptions = [fit_description_hs, None]
transformations = transformations = {
"transform": _transform,
"inverse": _inv_transform,
"jacobian": _jacobian,
}
semantics = {
"names": ["Significant wave height", "Zero-up-crossing period"],
"symbols": ["H_s", "T_z"],
"units": ["m", "s"],
}
return dist_descriptions, fit_descriptions, semantics, transformations
[docs]def get_Nonzero_EW_Hs_S():
"""
Get the non-zero EW sea state model.
Get the descriptions necessary to create the significant wave height - steepness
model that is an adaptation of Windmeier's EW model [5]_. Both, Hs and Steepness follow
an exponentiated Weibull distribution.
Compared to Windmeier's EW model, this model has a dependence function for scale
that evaluates to scale > 0 at hs = 0 m .
The dependence function reads: shift + a * (1 - np.exp(-b * hs))
Because the model is defined in Hs-steepness space it must be transformed to
Hs-Tz for contour calculation.
This model was introduced in the virocon software, there is research paper
describing it.
Returns
-------
dist_descriptions : list of dict
List of dictionaries containing the dist descriptions for each dimension.
Can be used to create a GlobalHierarchicalModel.
fit_descriptions : None
Default fit is used so None is returned.
Can be passed to fit function of GlobalHierarchicalModel.
semantics : dict
Dictionary with a semantic description of the model.
Can be passed to plot functions.
transformations : dict
References
----------
.. [5] Windmeier, K.-L. (2022). Modeling the statistical distribution of sea state
parameters [Master Thesis, University of Bremen]. https://doi.org/10.26092/elib/2181
"""
def _linear2(x, a=0, b=1):
return a + b * x
def _limited_growth_with_shift2(x, a=0.08, b=1):
# Compared to Windmeier's EW model the idea here is to have f(0) > 0.
# The idea is based on on the Figure 4.10 in Windmeier's thesis.
# DOI: 10.26092/elib/2181 .
# The value of 0.006 is chosen by extrapolating the median scale value line in
# Figure 4.10 to hs = 0.
shift = 0.006
# Some people call this equation "negative exponential equation" when the
# shift is zero, https://www.statforbiology.com/nonlinearregression/usefulequations#negative_exponential_equation
return shift + a * (1 - np.exp(-b * x))
def _transform(hs_tz):
hs = hs_tz[:, 0]
tz = hs_tz[:, 1]
s, _ = variable_transform.hs_tz_to_s_d(hs, tz)
return np.c_[hs, s]
def _inv_transform(hs_s):
hs = hs_s[:, 0]
s = hs_s[:, 1]
hs, tz = variable_transform.hs_s_to_hs_tz(hs, s)
return np.c_[hs, tz]
def _jacobian(hs_s):
hs = hs_s[:, 0]
s = hs_s[:, 1]
return 2 * variable_transform.factor * hs / s**3
linear_2_bounds = [(0, None), (0, None)]
limited_growth_with_shift2_bounds = [(0, 1), (0, None)]
linear2 = DependenceFunction(_linear2, bounds=linear_2_bounds)
limited_growth_with_shift2 = DependenceFunction(
_limited_growth_with_shift2, bounds=limited_growth_with_shift2_bounds
)
dist_description_hs = {
"distribution": ExponentiatedWeibullDistribution(),
"intervals": WidthOfIntervalSlicer(width=0.5, min_n_points=50),
}
dist_description_s = {
"distribution": ExponentiatedWeibullDistribution(f_delta=2.35),
"conditional_on": 0,
"parameters": {"alpha": limited_growth_with_shift2, "beta": linear2},
}
dist_descriptions = [dist_description_hs, dist_description_s]
fit_description_hs = {"method": "wlsq", "weights": "quadratic"}
fit_descriptions = [fit_description_hs, None]
transformations = transformations = {
"transform": _transform,
"inverse": _inv_transform,
"jacobian": _jacobian,
}
semantics = {
"names": ["Significant wave height", "Zero-up-crossing period"],
"symbols": ["H_s", "T_z"],
"units": ["m", "s"],
}
return dist_descriptions, fit_descriptions, semantics, transformations