This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Adding a Taylor test to time-dependent-wave.py

0 votes

I was trying to add a taylor test to this example, but before I am running into problems trying to understand some dolfin-adjoint concepts.

For instance, I cannot use the output of the function objective() in this example for the taylor test:

Jform = objective(times, u, refs)

because Jform is a TimeForm. Why is it a TimeForm when it is performing the sum over the sum over time steps and how can I transform it into something taylor_test() can process?

Also, in the same example, the forward() function returns the function "u1" and the simulation times. Given that objective() iterates over all time steps and u_obs, how does "u" (which is "u_1" from forward()) know the time steps? I imagine it must be because the expression is evaluated at time step "t" with dt[t], is this correct? What I do not understand is how "u" contains the entire simulation history. Is it just because of this expression?:

u1.assign(u, annotate = annotate)

Does the annotate make u1 to save the new "u" next to the previous one and therefore save the entire history instead of just one time step?

I am attaching a working code that shows the TimeForm problem

Thanks
Miguel

from dolfin import *
from dolfin_adjoint import *
import numpy as np
import os, sys

# Set log level
set_log_level(WARNING)

# Prepare a mesh
mesh = UnitIntervalMesh(50)

# Choose a time step size
k = Constant(1e-3)

# Compile sub domains for boundaries
left  = CompiledSubDomain("near(x[0], 0.)")
right = CompiledSubDomain("near(x[0], 1.)")

# Label boundaries, required for the objective
boundary_parts = MeshFunction("size_t", mesh, mesh.topology().dim()-1)
left.mark(boundary_parts, 0)
right.mark(boundary_parts, 1)
ds = Measure("ds")[boundary_parts]

class Source(Expression):
    def __init__(self, t, omega=Constant(2e2)):
        """ Construct the source function """
        self.t = t
        self.omega = omega

    def eval(self, value, x):
        """ Evaluate the expression """
        if x[0] < 1e-15:
            value[0] = np.sin(float(self.omega)*self.t)
        else:
            value[0] = 0.

    def deval(self, value, x, coeff):
        """ Evaluate the derivative of the expression """
        assert coeff == self.omega, "Given coeff must be the start time"
        if x[0] < 1e-15:
            value[0] = self.t*np.cos(float(self.omega)*self.t)
        else:
            value[0] = 0.

    def dependencies(self):
        """ List the dependencies of which derivatives are taken """
        return [self.omega]

    def copy(self):
        """ Return a copy of itself """
        return Source(self.t, self.omega)

def forward(excitation, c=Constant(1.), record=False, annotate=False):
    # Define function space
    U = FunctionSpace(mesh, "Lagrange", 1)

    # Set up initial values
    u0 = interpolate(Expression("0."), U, name = "u0", annotate = annotate)
    u1 = interpolate(Expression("0."), U, name = "u1", annotate = annotate)

    # Define test and trial functions
    v = TestFunction(U)
    u = TrialFunction(U)

    # Define variational formulation
    udot = (u - 2.*u1 + u0)
    uold = (0.25*u + 0.5*u1 +0.25*u0)
    F = (udot*v+k*k*c*c*uold.dx(0)*v.dx(0))*dx - u*v*ds(0) + excitation*v*ds(0)
    a = lhs(F)
    L = rhs(F)

    # Prepare solution
    u = Function(U, name = "u", annotate = annotate)

    # The actual timestepping
    if record: rec = [u1(1.),]
    i = 1
    t = 0.0        # Initial time
    T = 3.e-1      # Final time
    times = [t,]
    if annotate: adj_start_timestep()
    while t < T - .5*float(k):
        print t
        excitation.t = t + float(k)
        solve(a == L, u, annotate = annotate)
        u0.assign(u1, annotate = annotate)
        u1.assign(u, annotate = annotate)

        t = i*float(k)
        times.append(t)
        if record:
            rec.append(u1(1.0))
            plot(u)
        if annotate: adj_inc_timestep(t, t > T - .5*float(k))
        i += 1

    if record:
        np.savetxt("recorded.txt", rec)

    return u1, times

# Callback function for the optimizer
# Writes intermediate results to a logfile
def eval_cb(j, m):
    print("omega = %15.10e " % float(m[0]))
    print("objective = %15.10e " % j)

# Prepare the objective function
def objective(times, u, observations):
    combined = zip(times, observations)
    area = times[-1] - times[0]
    M = len(times)
    I = area/M*sum(inner(u - u_obs, u - u_obs)*ds(1)*dt[t]
                   for (t, u_obs) in combined)
    return I

# Load refs
def loadrefs():

    # Load references
    refs = np.loadtxt("recorded.txt")

    # create noise to references
    gamma = 1.e-5
    if gamma > 0:
        noise = np.random.normal(0, gamma, refs.shape)

        # add noise to the refs
        refs += noise

    # map refs to be constant
    refs = map(Constant, refs)

    return refs

def Jhat(omega):
    # Define the control
    source = Source(0.0, omega )

    # Execute first time to annotate and record the tape
    u, times = forward(source, 2*DOLFIN_PI, False, False)

    observations = loadrefs()

    # Evaluate functional
    return objective(times,u, observations)


def optimize(dbg=False):
    # Define the control
    source = Source(t = 0.0, omega = Constant(190))

    # Execute first time to annotate and record the tape
    u, times = forward(source, 2*DOLFIN_PI, False, True)

    if dbg:
        # Check the recorded tape
        success = replay_dolfin(tol = 0.0, stop = True)
        print "replay: ", success

        # for the equations recorded on the forward run
        adj_html("forward.html", "forward")
        # for the equations to be assembled on the adjoint run
        adj_html("adjoint.html", "adjoint")

    refs = loadrefs()

    # Define the controls
    controls = [Control(c) for c in source.dependencies()]

    Jform = objective(times, u, refs)
    J = Functional(Jform)

    # compute the gradient
    dJd0 = compute_gradient(J, controls)
    print float(dJd0[0])

    # Check the gradient
    conv_rate = taylor_test(Jhat,controls,Jform,dJd0)


    # Prepare the reduced functional
    reduced_functional = ReducedFunctional(J, controls, eval_cb_post = eval_cb)

    # Run the optimisation
    omega_opt = minimize(reduced_functional, method = "L-BFGS-B",\
                     tol=1.0e-12, options = {"disp": True,"gtol":1.0e-12})

    # Print the obtained optimal value for the controls
    print "omega = %f" %float(omega_opt)

if __name__ == "__main__":
    if '-r' in sys.argv:
        print "compute reference solution"
        os.popen('rm -rf recorded.txt')
        source = Source(t = 0.0, omega = Constant(2e2))
        forward(source, 2*DOLFIN_PI, True)
    print "start automatic characterization"
    if '-dbg' in sys.argv:
        optimize(True)
    else:
        optimize()
asked Mar 11, 2016 by miguelito FEniCS Novice (760 points)
...