Skip to content
This repository was archived by the owner on Mar 17, 2026. It is now read-only.

Some ideas #68

@devmotion

Description

@devmotion

In my opinion, DelayDiffEq is a lot more complicated than it should be, which also makes analysis and fixes more difficult. Hence I started to think about how the current situation could be improved.

Status quo

Currently, when initializing a new DDEIntegrator an ODEIntegrator is created (but not initialized) whose function, however, can never be evaluated since it has the wrong number of arguments. Hence in a quite confusing way it is wrapped, together with its solution, in a HistoryFunction, which itself is wrapped in a new differential equation of the form needed for OrdinaryDiffEq. Based on this, a DDEIntegrator is defined that duplicates all fields of an ODEIntegrator and uses this closure for function evaluations; hence OrdinaryDiffEq can be used for integration; in a quite advanced way the initial ODEIntegrator is updated to ensure a correct history function. Moreover, to reduce memory the caches of this ODEIntegrator are transferred to the DDEIntegrator, and the solution of the integrator is shortened already during integration if possible.

Ideas

  • Create one fully functional ODEIntegrator: This is currently not possible since the DDE function depends on argument h as well which itself depends on the interpolation of the ODEIntegrator that does not exist yet; possible solution:
    • Wrap h in a HistoryFunction that can be called as (::HistoryFunction)(integrator, t, ::Val{deriv}; idxs = nothing) (and so on):
      1. does not require the non-existing integrator at creation time
      2. requires the possibility to pass integrator instead of parameters p during integration as it was discussed already when the breaking changes were introduced in January
      3. passing integrator to the wrapper would still allow to only pass integrator.p to the wrapped initial function h
    • Wrap f and this HistoryFunction (probably together with analytic solution, gradient, Jacobian etc.) in a DDEFunction <: AbstractDiffEqFunction
      1. allows to define (::DDEFunction)(du, u, integrator, t) (and so on), as required by OrdinaryDiffEq
      2. requires to pass integrator instead of parameters p
      3. would still allow to pass only integrator.p to f
      4. would group all different functions such as f and h that belong together (e.g. usually the analytic solution depends on both)
  • Wrap it inside a DDEIntegrator which contains no duplicate fields:
    • currently almost every update of ODEIntegrator breaks DDEIntegrator
  • Use ODEIntegrator for integration and DDEIntegrator mostly for its control, i.e. for resets and fixed-point iteration:
    • from previous experiences, the most difficult part would be to implement intra-/extrapolations and fixed-point iterations correctly
  • Add possibility to only save dense output of certain indices:
    • currently a very complicated algorithm exists to reduce the solution in special cases
    • based on the implementation of RADAR5, one could (alternatively) save dense output only for certain indices (but still save solution at all or given time points for all or given indices)
    • would be simpler probably, and would also work for state-dependent delays

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions