Skip to content

Reduce Compilation Time

Methods that accept symbolic expressions first differentiate them and then use Numba to compile vectorized value, gradient, and Hessian functions. For a large expression graph, this setup can take longer than the numerical solve. Changing only a boundary constant or mesh does not necessarily require recompiling every function.

Keep expressions compilation-friendly

  • Leave simplify=False unless testing shows that SymPy simplification reduces the specific expression. Simplification itself can be expensive.
  • Prefer ordinary algebra such as x * x or x ** 2 to indirect calls such as pow(x, 2.0).
  • Factor repeated symbolic subexpressions in the model design when that also keeps the equations readable; avoid expanding compact expressions without a numerical reason.

Reuse configured functions

The set_* methods are decoupled. For example, changing a boundary condition does not require calling set_dynamics again. If a phase is changed after System.set_phase, call System.update() once to refresh system-level indices and derivative data. That update is much cheaper than recompiling unrelated symbolic functions.

Cache generated functions

  1. Create a dedicated cache directory for one exact model configuration.
  2. Pass that path through the relevant cache argument:
phase.set_dynamics(..., cache="./cache/my_model")

Caching is supported by Phase.set_dynamics, Phase.set_integral, Phase.set_phase_constraint, Phase.set_boundary_condition, System.set_objective, and System.set_system_constraint.

Treat a cache as model-specific

Do not reuse a cache after changing an expression, symbol order, derivative option, or other input that affects the generated function. Use a separate directory or regenerate the cache. A stale compiled function can produce a numerically plausible result for the wrong model.

For custom generated functions and the required sparse derivative layout, see Skip Symbolic Differentiation.