[petsc-users] 2nd order time-stepping in PETSc

Jed Brown jed at 59A2.org
Thu May 27 06:03:47 CDT 2010


On Wed, 26 May 2010 21:48:56 -0300, Lisandro Dalcin <dalcinl at gmail.com> wrote:
> On 26 May 2010 18:58, Matthew Knepley <knepley at gmail.com> wrote:
> > It sounds like you could formulate it to solve for timestep n+1, and
> > then the RHS would depend on timestep n (which PETSc would give
> > you), and timestep n-1.  You could save t^{n-1} yourself with a
> > custom Monitor and get it in your RHS function through the user
> > context.     Matt
> >
> 
> What about using TSSet{Pre|Post}Step() ?

The problem is that this sort of ad-hoc dependence on the last step
causes the application to assume things about the integrator in use.
You can of course reduce the second-order problem to a first-order
system, but at the expense of increasing the length of the Krylov
vectors and ruining potential symmetry.  This is currently the only
general method supported by TS, but I don't like it.  An alternative is
to have the method perform differencing in auxiliary variables, as I
proposed a few weeks ago in a different context:

  http://lists.mcs.anl.gov/pipermail/petsc-dev/2010-April/002671.html

Some integrators, like RADAU, recognize special orderings and a flag for
this, but I find this especially awkward in parallel and we don't live
in an F77 world, so I would prefer to write this capability into the
API.

Specifically in this case, we have

  x_tt + f(x) = 0

which with time step \Delta t ~ 1/a and mass matrix M, yields a Jacobian

  J(x) = a^2 M + f'(x)

(I am ignoring the details of the time discretization which involves
precise definition of  a  and the right hand side.)  We can transform
this as

  x_t - y    = 0
  y_t + f(x) = 0

but we now have a Jacobian

  J(x,y) = [aM, -M; f'(x), aM]

which is somewhat unfortunate.  The proposal in the message referenced
above is not sufficient to transform this into the system you want, but
consider

  /* Set by the user before TSSolve(), called by the integrator at each
   * stage (maybe lazily). */
  typedef PetscErrorCode (*TSAuxiliaryFunction)(TS,Vec X,Vec X_t,Vec Y,void *ctx);
  PetscErrorCode TSSetAuxiliaryFunction(TS,TSAuxiliaryFunction,void*);

  /* Called by the user in TSIFunction(), Y is provided directly be the
   * user's function, Y_t is determined by the integrator using some
   * differencing of the Y values at prior steps/stages.  (This is a
   * virtual function to be defined by supported implementations.) */
  PetscErrorCode TSGetAuxiliaryVector(TS,Vec *Y,Vec *Y_t);

The material energy in the referenced message would by Y = Y(X), for
Hamiltonian systems you might have Y = Y(X_t) = X_t.  I don't think it
is possible to avoid leaving the user responsible for differentiating
through their auxiliary function when computing a Jacobian, but this is
easy for the easy cases (like the wave equation) and when it is actually
difficult, I think (naively) it is true complexity and not API
awkwardness.  What do you think?

Jed


More information about the petsc-users mailing list