@@ -222,6 +222,58 @@ is the vector of sensitivities. Since this ODE is dependent on the values of the
222222independent variables themselves, this ODE is computed simultaneously with the
223223actual ODE system.
224224
225+ Note that the Jacobian-vector product:
226+
227+ ``` math
228+ \frac{\partial f}{\partial u}\frac{\partial u}{\partial p_{j}}
229+ ```
230+
231+ can be computed without forming the Jacobian. With finite differences, this through using the following
232+ formula for the directional derivative:
233+
234+ ``` math
235+ Jv \approx \frac{f(x+v \epsilon) - f(x)}{\epsilon}
236+ ```
237+
238+ or by using a dual number with a single partial dimension, `` d = x + v \epsilon `` we get that
239+
240+ ``` math
241+ f(d) = f(x) + Jv \epsilon
242+ ```
243+
244+ as a fast way to calcuate `` Jv `` . Thus, except when a sufficiently good function for ` J ` is given
245+ by the user, the Jacobian is never formed. For more details, consult the
246+ [ MIT 18.337 lecture notes on forward mode AD] ( https://mitmath.github.io/18337/lecture9/autodiff_dimensions ) .
247+
248+ #### Syntax
249+
250+ ` ODELocalSensitivityProblem ` is similar to an ` ODEProblem ` :
251+
252+ ``` julia
253+ function ODELocalSensitivityProblem (f:: DiffEqBase.AbstractODEFunction ,u0,
254+ tspan,p= nothing ,
255+ SensitivityAlg ();
256+ kwargs... )
257+ ```
258+
259+ The ` SensitivityAlg ` is used to mirror the definition of the derivative options seen generally
260+ throughout OrdinaryDiffEq.jl. The keyword options on the ` SensitivityAlg ` are as follows:
261+
262+ * ` autojacvec ` : Calculate Jacobian-vector (local sensitivity analysis) product
263+ via automatic differentiation with special seeding to avoid building the Jacobian.
264+ Default is ` true ` . If ` autodiff=false ` , it will use the Jacobian-free forward
265+ differencing approximation. If ` false ` , the Jacobian will prefer to use any
266+ ` f.jac ` function provided by the user. If none is provided by the user, then it
267+ will fall back to automatic or finite differentiation, though this choice is
268+ not recommended.
269+ * ` autodiff ` : Use automatic differentiation in the internal sensitivity algorithm
270+ computations. Default is ` true ` .
271+ * ` chunk_size ` : Chunk size for forward mode differentiation. Default is ` 0 ` for
272+ automatic chunk size choice. Only used when ` autojacvec=false ` .
273+ * ` diff_type ` : Choice of differencing used to build the Jacobian when ` autojacvec=false `
274+ and ` autodiff=false ` . Defaults to ` Val{:central} ` for central differencing with
275+ DiffEqDiffTools.jl.
276+
225277#### Example solving an ODELocalSensitivityProblem
226278
227279To define a sensitivity problem, simply use the ` ODELocalSensitivityProblem ` type
@@ -384,6 +436,17 @@ g_{y}(t_{i})=2\left(\tilde{u}(t_{i})-u(t_{i},p)\right)
384436Thus the adjoint solution is given by integrating between the integrals and
385437applying the jump function `` g_y `` at every data point.
386438
439+ We note that
440+
441+ ``` math
442+ \lambda^{\star}(t)f_{u}(t)
443+ ```
444+
445+ is a vector-transpose Jacobian product, also known as a ` vjp ` , which can be efficiently computed
446+ using the pullback of backpropogation on the user function ` f ` with a forward pass at ` u ` with a
447+ pullback vector `` \lambda^{\star} `` . For more information, consult the
448+ [ MIT 18.337 lecture notes on reverse mode AD] ( https://mitmath.github.io/18337/lecture10/estimation_identification )
449+
387450#### Syntax
388451
389452There are two forms. For discrete adjoints, the form is:
@@ -428,10 +491,10 @@ s = adjoint_sensitivities(sol,alg,g,nothing;kwargs...)
428491
429492then it will be computed automatically using ForwardDiff or finite
430493differencing, depending on the ` autodiff ` setting in the ` SensitivityAlg ` .
431- Note that the keyword arguments are passed
432- to the internal ODE solver for solving the adjoint problem. Two special keyword
433- arguments are ` iabstol ` and ` ireltol ` which are the tolerances for the internal
434- quadrature via QuadGK for the resulting functional.
494+ Note that the keyword arguments are passed to the internal ODE solver for
495+ solving the adjoint problem. Two special keyword arguments are ` iabstol ` and
496+ ` ireltol ` which are the tolerances for the internal quadrature via QuadGK for
497+ the resulting functional.
435498
436499#### Options
437500
@@ -453,19 +516,49 @@ res = adjoint_sensitivities(sol,Vern9(),dg,t,reltol=1e-8,
453516 its higher order interpolation then this is by default disabled.
454517* ` quad ` : Use Gauss-Kronrod quadrature to integrate the adjoint sensitivity
455518 integral. Disabling it can decrease memory usage but increase computation
456- time. Default is ` true ` .
519+ time, since post-solution quadrature can be more accurate with less points
520+ using the continuous function. Default is ` true ` .
457521* ` backsolve ` : Solve the differential equation backward to get the past values.
458- Note that for chaotic or non-reversible systems, enabling this option can
459- lead to wildly incorrect results. Enabling it can decrease memory usage but
460- increase computation time. When it is set to ` true ` , ` quad ` will be
461- automatically set to ` false ` . Default is ` false ` .
522+ Note that for chaotic or non-reversible systems, such as though that solve to
523+ a steady state, enabling this option can lead to wildly incorrect results.
524+ Enabling it can decrease memory usage but increase computation time. When it
525+ is set to ` true ` , ` quad ` will be automatically set to ` false ` . Default is ` false ` .
462526* ` autodiff ` : Use automatic differentiation in the internal sensitivity algorithm
463- computations. Default is ` true ` .
464- * ` chunk_size ` : Chunk size for forward mode differentiation. Default is ` 0 ` for
465- automatic.
466- * ` autojacvec ` : Calculate Jacobian-vector (local sensitivity analysis) or
467- vector-Jacobian (adjoint sensitivity analysis) product via automatic
468- differentiation with special seeding. Default is ` true ` if ` autodiff ` is true.
527+ computations. This is the only option that is passed, this will flip ` autojacvec `
528+ to false, since that requires reverse-mode AD, and thus finite differencing for the
529+ full Jacobian will be used. Default is ` true ` .
530+ * ` chunk_size ` : Chunk size for forward mode differentiation if full Jacobians are
531+ built (` autojacvec=false ` and ` autodiff=true ` ). Default is ` 0 ` for automatic
532+ choice of chunk size.
533+ * ` autojacvec ` : Calculate the vector-Jacobian (adjoint sensitivity analysis) product
534+ via automatic differentiation with special seeding. Due to being a ` vjp ` function,
535+ this option requires using automatic differentiation, currently implemented with
536+ Tracker.jl. Default is ` true ` if ` autodiff ` is true, and otherwise is false. If
537+ ` autojacvec=false ` , then a full Jacobian has to be computed, and this will default
538+ to using a ` f.jac ` function provided by the user from the problem of the forward pass.
539+ Otherwise, if ` autodiff=true ` then it will use forward-mode AD for the Jacobian, otherwise
540+ it will fall back to using a numerical approximation to the Jacobian.
541+
542+ A way to understand these options at a higher level is as follows:
543+
544+ * For the choice of the overall sensitivity calculation algorithm, using interpolation is
545+ preferred if the ` sol ` is continuous. Otherwise it will use checkpointed adjoints by default
546+ if the user passes in a ` sol ` without a good interpolation. Using ` backsolve ` is unstable
547+ except in specific conditions, and thus is only used when chosen by the user.
548+ * In any of these cases ` quad=false ` is the default, which enlarges the ODE system to calculate
549+ the integral simultaniously to the ODE solution. This reduces the memory cost, though in some
550+ cases solving the reverse problem with a continuous solution and then using QuadGK.jl to
551+ perform the quadrature can use less reverse-pass points and thus decrease the computation
552+ time, though this is rare when the number of parameters is large.
553+ * Using automatic differentiation everywhere is the preferred default. This means the ` vjp `
554+ will be performed using reverse-mode AD with Tracker.jl and no Jacobian will be formed.
555+ If ` autodiff=false ` , then ` autojacvec=false ` is set since it assumes that user function
556+ is not compatible with any automatic differentiation. In this case, if a user-defined
557+ Jacobian function exists, this will be used. Otherwise this means that the
558+ ` vjp ` will be computed by forming the Jacobian with finite differences and then doing
559+ the matrix-vector product. As an intermediate option, one can set ` autodiff=true ` with
560+ ` autojacvec=false ` to compute the Jacobian with forward-mode AD and then perform the
561+ vector-Jacobian product using that matrix.
469562
470563#### Example discrete adjoints on a cost function
471564
0 commit comments