Source code for opentidalfarm.functionals.power_functionals
#"""
#.. module:: Power Functionals
# :synopsis: This module contains the functional classes which compute the
# power extracted by an array.
#"""
from dolfin import dot, Constant, dx, assemble, conditional
from ..helpers import smooth_uflmin
from .prototype_functional import PrototypeFunctional
[docs]
class PowerFunctional(PrototypeFunctional):
r""" Implements a power functional of the form:
.. math:: J(u, m) = \int \rho c_t ||sq(u)||^{1.5}~ dx,
where :math:`c_t` is the friction due to the turbines, and
:math:`sq(u)` is the squared velocity that takes into account the
cut-in/out behaviour of the turbines, i.e.
.. math:: sq(u) =
\begin{cases}
eps \|u\|^2 & \text{if } \|u\| < {cut\_in\_speed} \\
(cut\_out\_speed)^2 & \text{if } \|u\| > {cut\_out\_speed} \\
\|u\|^2 & \text{else.}
\end{cases}
:param problem: The problem for which the functional is being computed.
:type problem: Instance of the problem class.
:param cut_in_speed: The turbine's cut in speed (Default: None).
:type cut_in_speed: float
:param cut_out_speed: The turbine's cut out speed (Default: None).
:type cut_out_speed: float
:param eps: The turbine's cut in speed slope (Default: 1e-10).
:type esp: float
"""
def __init__(self, problem, cut_in_speed=None, cut_out_speed=None, eps=1e-10):
self.farm = problem.parameters.tidal_farm
self.rho = problem.parameters.rho
self.farm.update()
self._cut_in_speed = cut_in_speed
self._cut_out_speed = cut_out_speed
self._eps = eps
[docs]
def Jt(self, state, turbine_field):
""" Computes the power output of the farm.
:param state: Current solution state
:type state: dolfin.Function
:param turbine_field: Turbine friction field
:type turbine_field: dolfin.Function
"""
return self.power(state, turbine_field)*self.farm.site_dx
[docs]
def power(self, state, turbine_field):
""" Computes the power field over the domain.
:param state: Current solution state.
:type state: dolfin.Function
:param turbine_field: Turbine friction field
:type turbine_field: dolfin.Function
"""
return self.rho * turbine_field * self._speed_squared(state) ** 1.5
[docs]
def Jt_individual(self, state, i):
""" Computes the power output of the i'th turbine.
:param state: Current solution state
:type state: dolfin.Function
:param i: refers to the i'th turbine
:type i: Integer
"""
turbine_field_individual = \
self.farm.turbine_cache['turbine_field_individual'][i]
return assemble(self.power(state, turbine_field_individual) *
self.farm.site_dx)
[docs]
def force(self, state, turbine_field):
""" Computes the force field over turbine field
:param state: Current solution state.
:type state: dolfin.Function
:param turbine_field: Turbine friction field
:type turbine_field: dolfin.Function
"""
return self.rho * turbine_field * self._speed_squared(state)
[docs]
def force_individual(self, state, i):
""" Computes the total force on the i'th turbine
:param state: Current solution state
:type state: dolfin.Function
:param i: refers to the i'th turbine
:type i: Integer
"""
turbine_field_individual = \
self.farm.turbine_cache['turbine_field_individual'][i]
return assemble(self.force(state, turbine_field_individual) * self.farm.site_dx)
def _speed_squared(self, state):
""" The velocity speed with turbine cut in and out speed limits """
speed_sq = dot(state[0], state[0]) + dot(state[1], state[1])
if self._cut_in_speed is not None:
speed_sq *= conditional(speed_sq < self._cut_in_speed**2, self._eps, 1)
if self._cut_out_speed is not None:
speed_sq = conditional(speed_sq > self._cut_out_speed**2,
self._cut_out_speed**2, speed_sq)
return speed_sq