Multiple tangent linear evaluations

Asked by Gabriel Balaban

Dear Patrick, Simon or other dolfin-adjoint developer,
I have been trying to run the tangent linear model several times for different parameter values but have gotten a 0 vector on the second run. Between the tlm evals I would like to evaluate the forward model as I am doing an optimization and I need to check convergence.

Is there a way to adjust the script below so it computes the right value on the second tlm evaluation? It works if the second forward run is disabled, but it is unfortunatly necessary for my application (non linear least squares optimization of Cardiac mechanics).

Cheers,
    Gabriel

"""
Implementation of Burger's equation with nonlinear solve in each
timestep
"""

import sys

from dolfin import *
from dolfin_adjoint import *

n = 4
mesh = UnitIntervalMesh(n)
V = FunctionSpace(mesh, "CG", 2)

def Dt(u, u_, timestep):
    return (u - u_)/timestep

def main(ic, annotate=False):

    u_ = Function(ic, name="Velocity")
    u = Function(V, name="VelocityNext")
    v = TestFunction(V)

    nu = Constant(0.0001)

    timestep = Constant(1.0/n)

    F = (Dt(u, u_, timestep)*v
         + u*u.dx(0)*v + nu*u.dx(0)*v.dx(0))*dx
    bc = DirichletBC(V, 0.0, "on_boundary")

    t = 0.0
    end = 0.2
    while (t <= end):
        solve(F == 0, u, bc, annotate=annotate)
        u_.assign(u, annotate=annotate)

        t += float(timestep)
        adj_inc_timestep()

    return u_, nu

if __name__ == "__main__":

    ic = project(Expression("sin(2*pi*x[0])"), V)
    forward, nu = main(ic, annotate=True)

    print "First tlm run"
    for val, var in compute_tlm(ScalarParameter(nu), forget = None):
        if val: print val.vector().array()

    forward, nu = main(ic, annotate=False)

    print "Second tlm run"
    nu.assign(0.0003)
    for val, var in compute_tlm(ScalarParameter(nu)):
        if val: print val.vector().array()

Question information

Language:
English Edit question
Status:
Solved
For:
dolfin-adjoint Edit question
Assignee:
No assignee Edit question
Solved by:
Patrick Farrell
Solved:
Last query:
Last reply:
Revision history for this message
Best Patrick Farrell (pefarrell) said :
#1

The second call to main() creates a new nu, but you don't annotate its existence. So when you ask for the derivative of the old tape with respect to the new nu, it gives you zero.

Try this?

"""
Implementation of Burger's equation with nonlinear solve in each
timestep
"""

import sys

from dolfin import *
from dolfin_adjoint import *

n = 4
mesh = UnitIntervalMesh(n)
V = FunctionSpace(mesh, "CG", 2)

def Dt(u, u_, timestep):
    return (u - u_)/timestep

def main(ic, nu, annotate=False):

    u_ = Function(ic, name="Velocity")
    u = Function(V, name="VelocityNext")
    v = TestFunction(V)

    timestep = Constant(1.0/n)

    F = (Dt(u, u_, timestep)*v
         + u*u.dx(0)*v + nu*u.dx(0)*v.dx(0))*dx
    bc = DirichletBC(V, 0.0, "on_boundary")

    t = 0.0
    end = 0.2
    while (t <= end):
        solve(F == 0, u, bc, annotate=annotate)
        u_.assign(u, annotate=annotate)

        t += float(timestep)
        adj_inc_timestep()

    return u_, nu

if __name__ == "__main__":

    ic = project(Expression("sin(2*pi*x[0])"), V)
    nu = Constant(0.0001)
    forward = main(ic, nu, annotate=True)

    print "First tlm run"
    for val, var in compute_tlm(ScalarParameter(nu), forget = None):
        if val: print val.vector().array()

    adj_reset()
    nu = Constant(0.0003)
    forward = main(ic, nu, annotate=True)

    print "Second tlm run"
    for val, var in compute_tlm(ScalarParameter(nu)):
        if val: print val.vector().array()

Revision history for this message
Gabriel Balaban (gabrib) said :
#2

Thanks Patrick Farrell, that solved my question.

Revision history for this message
Gabriel Balaban (gabrib) said :
#3

Hey Patrick,
Thank you very much for the fix! That did it.
Cheers,
  Gabriel