Hi John,

One of the problems is that F is a functional rather than an ordinary
function.  So the derivatives with respect to u are functional
derivatives, and I dont think diff() can compute these without any
help.  Let's focus on one of the terms for instance: put f = u_x and
consider

  <lambda, f> = <lambda, u_x>
                      = \int lambda u_x dx
                      = - \int lambda_x u dx,

doing partial integration and assuming that u falls off sufficiently
fast so that the boundary term vanishes.  Then D[u] <lambda, u_x> = -
lambda_x in the sense of functional derivatives.

One way to "simulate" this in Sage is to define your own D operator
which satisfies

  D f = d f/ du - d/dx ( df/d u_x)

on functions f(u, u_x), where d/du, d/dx denote ordinary
differentiation wrt. u, x, etc.  Note how this operator correctly
simulates the effect of doing partial integration.  This operator is
sometimes also referred to as the "Euler-Lagrange operator".  We can
check that

  D <lambda, u_x> = d/du ( <lambda, u_x> ) - d/dx ( d/du_x <lambda,
u_x> )
                              = 0 - d/dx (lambda)
                              = - lambda_x

Hope this helps,
Joris


On 3 nov, 03:01, John Wiseman <[email protected]> wrote:
> Hi,
>
> I'm trying to use sage to automatically derive the adjoint PDE
> associated with the one-dimensional Burgers' equation. Suppose you
> have an equation F(u) = 0, where u is the function you're trying to
> solve for. Suppose you are interested in the value of some functional
> J(u). The associated adjoint equation is formed by constructing the
> Lagrangian:
>
> L(u, lambda) = J(u) - <lambda, F(u)>
>
> where <.> means the inner product.
>
> The adjoint PDE is defined by diff(L, u) = 0. This is what I'm trying
> to get sage to compute.
> Unfortunately, I can't quite figure out the right construction:
>
> # I am attempting to derive the adjoint PDE for the one-dimensional
> Burgers
> equation
> # posed as the following:
>
> # diff(u, t) + u * diff(u, x) - diff(u, x, 2)) = 0           on  [a,
> b] x [0, T]
> # u(x, t=0) = u0                                             on  [a,
> b]
> # u(a, t)   = 0                                              on  [0,
> T]
> # u(b, t)   = 0                                              on  [0,
> T]
>
> # To do this, I am attempting to form the Lagrangian
> # L(u, rho) = J(u) - <rho, diff(u, t) + u * diff(u, x) - diff(u, x,
> 2))>_ST - <eta, u(x=a, t)>_T - <zeta, u(x=b), t)>_T - <chi, u(x,
> t=0)>_S
> # where _SP means inner product over spacetime, _S over space, and _T
> over time.
>
> # The adjoint equation is defined as
> # diff(L, u) = 0
> # which is what I would like to compute.
>
> x = var('x')                   # space
> t = var('t')                   # time
>
> u = function('u', x, t)        # velocity, to be solved for in the
> Burgers equation
>
> a = var('a')                   # the left-hand space limit
> b = var('b')                   # the right-hand space limit
> assume(a < b)
> T = var('T')                   # the upper time limit
> assume(T > 0)
>
> def ip_st(u, v):
>   # inner product over spacetime
>   return integral(integral(u*v, x, a, b), t, 0, T)
>
> def ip_t(u, v):
>   # inner product over time
>   return integral(u*v, t, 0, T)
>
> def ip_s(u, v):
>   # inner product over space
>   return integral(u*v, x, a, b)
>
> rho = function('rho', x, t)    # the main adjoint variable
> eta = function('eta', t)       # the lagrange multiplier enforcing the
> left boundary condition
> zeta = function('zeta', t)     # the lagrange multiplier enforcing the
> right boundary condition
> chi = function('chi', x)       # the lagrange multiplier enforcing the
> initial condition
>
> # In the Lagrangian, we'll leave out the J(u), as I know what to do
> with it
> # Here is where it starts to go wrong.
> L = -ip_st(rho, diff(u, t) + u * diff(u, x) - diff(u, x, 2)) -
> ip_t(eta, u.subs(x=a)) - ip_t(zeta, u.subs(x=b)) - ip_s(chi,
> u.subs(t=0))
>
> # I am confused as to what to do now. L isn't a function of u, sage
> says:
> # sage: u in L.variables()
> # False
>
> # sage: print diff(L, u)
> # ...
> # TypeError: argument symb must be a symbol
>
> eps = var('epsilon')           # a small number
> assume(eps > 0)
> du = function('du', x, t)      # a perturbation
>
> # sage: print L.substitute_function(u, u + eps*du) - L
> # 0
>
> So I can't diff(L, u); it gives a TypeError. And when I try to
> substitute_function(), it gives the same thing back again.
>
> I tried many variants of this, making everything vars instead of
> functions, but I couldn't hit upon the right trick.
>
> Any ideas?
>
> Thanks,
>
> John

-- 
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/sage-support
URL: http://www.sagemath.org

Reply via email to