Source code for opentidalfarm.functionals.time_integrator
import numpy
from dolfin import *
from dolfin_adjoint import *
from ..problems import MultiSteadySWProblem
[docs]
class TimeIntegrator(object):
def __init__(self, problem, functional, final_only):
self.problem = problem
self.functional = functional
self.final_only = final_only
self.vals = []
self.times = []
[docs]
def add(self, time, state, tf, is_final):
if not self.final_only or (self.final_only and is_final):
val = assemble(self.functional.Jt(state, tf))
self.vals.append(val)
self.times.append(time)
[docs]
def integrate(self):
""" Integrats the functional with a second order scheme. """
if len(self.vals) == 0:
raise ValueError("Cannot integrate empty set.")
if self.final_only:
return self.vals[-1]
# FIXME: Don't assume constant timesteps
dt = self.times[1]-self.times[0]
# Compute quadrature weights
w = numpy.ones(len(self.times))
# The multi-steady state case is special in that we want to integrate
# over time, but without the initial guess.
w[-1] = 0.0
if type(self.problem) == MultiSteadySWProblem:
w[0] = 0.
w[1] = 0.5
else:
w[0] = 0.5
w[-1] += 0.5
return sum(w * dt * self.vals)
[docs]
def dolfin_adjoint_functional(self, state):
""" Constructs the dolfin-adjoint.Functional """
# The functional depends on the turbine_function which is not in scope.
# But dolfin-adjoint only cares about the name, hence it is sufficient
# to create a dummy function with the appropriate name.
R = FunctionSpace(self.problem.parameters.domain.mesh, "R", 0)
tf = Function(R, name="turbine_friction")
if self.final_only:
return Functional(self.functional.Jt(state, tf) * dt[FINISH_TIME])
if type(self.problem) == MultiSteadySWProblem:
return Functional(self.functional.Jt(state, tf) *
dt[float(self.times[1]):])
else:
return Functional(self.functional.Jt(state, tf) * dt)