  We consider checkpointing strategies that minimize the number of
recomputations needed when performing discrete adjoint computations using
multistage time-stepping schemes, which requires computing several substeps
within one complete time step. In this case we propose two algorithms that can
generate optimal checkpointing schedules under weak assumptions. The first is
an extension of the seminal Revolve algorithm adapted to multistage schemes.
The second algorithm, named CAMS, is developed based on dynamic programming,
and it requires the least number of recomputations when compared with other
algorithms. The CAMS algorithm is made publicly available in a library with
bindings to C and Python. Numerical results illustrate that the proposed
algorithms can deliver up to two times the speedup compared with that of
classical Revolve. Moreover, we discuss a tailored implementation of an adjoint
computation that is arguably better suited for mature scientific computing
libraries by avoiding the central control assumed by the original checkpointing
strategy. The proposed algorithms have been adopted by the PETSc TSAdjoint
library. Their performance has been demonstrated with a large-scale
PDE-constrained optimization problem on a leadership-class supercomputer.
