Objective
Consolidate CTDirect following the control-toolbox Handbook philosophy to build a better base for future extensions.
Context
CTDirect (v1.0.12) transcribes a continuous OCP (from CTModels) into an NLP solved through CTSolvers (ADNLPModels / ExaModels backends). The current code is a flat module with symbol-based dispatch, raw field access, duplicated scheme code, and an ExaModels transcription that lives in CTParser instead of CTDirect. A detailed roadmap has been written, following the spirit of what was done for CTFlows.
Central theme
Abstract the founding ingredients of a transcription so that discretization methods become recipes — generic on abstract types (e.g. driven by an arbitrary Butcher tableau), yet overridable with optimized specializations (e.g. midpoint avoiding duplicate evaluations). Everything else follows from getting this abstraction right.
- Architecture overhaul — Move from flat
src/*.jl to one submodule per responsibility (Schemes, Layouts, Transcriptions, Sparsity, Grids, Discretizers, Solutions), with a strict dependency DAG.
- Types, traits, interfaces — Replace Symbol dispatch with scheme types, use traits for scheme properties (control parametrization, explicit/implicit, stage count, order), define accessor interfaces instead of raw field access, and typed extractors for post-processing (eliminating
occursin string matching).
- Transcription recipe (the heart) — Reify the ingredients of a direct transcription (unknowns, layout, reconstruction, defects, cost quadrature, constraints, initial guess, work arrays) so that building a DOCP is a generic recipe over abstract types. Two NLP emission backends (ADNLP callables and ExaModels generators) must be an explicit axis from day one.
- Butcher tableau as user input — Users can pass any Butcher tableau directly; named schemes become constructors returning tableaux. Control parametrization becomes an orthogonal option (
:stepwise | :stagewise).
- Own the ExaModels transcription — Move the ExaModels transcription from CTParser into CTDirect, eliminating duplicated logic that can silently drift, enabling the full scheme catalogue on Exa, and making Exa available for non-
@def problems.
- Sparsity & AD separation — Split "pattern provision" from "backend choice" — two orthogonal axes currently conflated in a single
backend == :manual knob.
- 1-D = scalar — Pass scalars for 1-D state/control/variable to user OCP functions, consistent with CTFlows.
- Initial guess — Pluggable and comparable strategies, with problem-informed defaults at the CTModels level (median of boxes, interpolation between boundary conditions) and proper NLP-level injection (including internal unknowns like stage slopes).
- Solution building & outputs — Typed extractors, duals consolidation, costate/multiplier handling and rescaling.
- Direct multiple shooting — Control/state parametrization decoupled from the ODE scheme; control parametrization as an ingredient independent of the integration scheme.
- Free node times, grid rebalancing, mesh refinement — Free interior nodes as NLP unknowns (switching-time optimization), outer-loop refinement with warm restart.
- Impulsive case — State jumps at selected nodes as a recipe extension — a first step toward non-conventional problems.
- Documentation — Vitepress migration + a "Transcription" guide explaining the exact NLP produced for each scheme family.
- Test suite restructuring — Adopt the Handbook testing template, organize by functionality, add contract tests with fakes.
Why
A cleaner architectural base will make CTDirect easier to extend and maintain. This consolidation will enable:
- Direct shooting extensions (control/state parametrization decoupled from ODE scheme)
- Multi-phase problems (via the recipe abstraction)
- Grid refinement (via first-class Grids with free nodes)
- Non-conventional problems (impulsive, hybrid — via recipe extensions)
- Moving the ExaModels transcription here (from CTParser) separates concerns: CTParser handles parsing, CTDirect handles discretization
References
Objective
Consolidate CTDirect following the control-toolbox Handbook philosophy to build a better base for future extensions.
Context
CTDirect (v1.0.12) transcribes a continuous OCP (from CTModels) into an NLP solved through CTSolvers (ADNLPModels / ExaModels backends). The current code is a flat module with symbol-based dispatch, raw field access, duplicated scheme code, and an ExaModels transcription that lives in CTParser instead of CTDirect. A detailed roadmap has been written, following the spirit of what was done for CTFlows.
Central theme
Abstract the founding ingredients of a transcription so that discretization methods become recipes — generic on abstract types (e.g. driven by an arbitrary Butcher tableau), yet overridable with optimized specializations (e.g. midpoint avoiding duplicate evaluations). Everything else follows from getting this abstraction right.
Key points (from the detailed roadmap)
src/*.jlto one submodule per responsibility (Schemes, Layouts, Transcriptions, Sparsity, Grids, Discretizers, Solutions), with a strict dependency DAG.occursinstring matching).:stepwise | :stagewise).@defproblems.backend == :manualknob.Why
A cleaner architectural base will make CTDirect easier to extend and maintain. This consolidation will enable:
References