@@ -571,22 +571,21 @@ def _auto_dt0(dt0):
571571
572572
573573@citation_rules .append
574- def _clip_controller (terms , stepsize_controller ):
575- if type (stepsize_controller ) is ClipStepSizeController :
576- if stepsize_controller .store_rejected_steps is not None and is_sde (terms ):
577- return r"""
578- % You are adaptively solving an SDE whilst revisiting rejected time points. This is a
579- % subtle point required for the correctness of adaptive noncommutative SDE solves, as
580- % found in:
581- """ + _parse_reference (ClipStepSizeController )
574+ def _stepsize_controller (stepsize_controller , terms = None ):
575+ out = _stepsize_controller_impl (terms , stepsize_controller )
576+ if len (out ) == 0 :
577+ return None
578+ else :
579+ return "\n \n " .join (x .strip () for x in out )
582580
583581
584- @ citation_rules . append
585- def _pid_controller ( stepsize_controller , terms = None ):
582+ def _stepsize_controller_impl ( terms , stepsize_controller ) -> set [ str ]:
583+ out = set ()
586584 if type (stepsize_controller ) is PIDController :
587585 if is_sde (terms ):
588- return r"""
589- % The use of PI and PI controllers to adapt step sizes for SDEs are from:
586+ out .add (
587+ r"""
588+ % The use of adaptive step size controllers for SDEs are from:
590589@article{burrage2004adaptive,
591590 title={Adaptive stepsize based on control theory for stochastic
592591 differential equations},
@@ -612,14 +611,16 @@ def _pid_controller(stepsize_controller, terms=None):
612611 pages={791–-812},
613612}
614613"""
614+ )
615615 else :
616616 no_p = stepsize_controller .pcoeff == 0
617617 no_d = stepsize_controller .dcoeff == 0
618618 _no_tracer (no_p , "stepsize_controller.pcoeff" )
619619 _no_tracer (no_d , "stepsize_controller.dcoeff" )
620620 if no_d :
621621 if no_p :
622- return r"""
622+ out .add (
623+ r"""
623624% The use of an I-controller to adapt step sizes is from Section II.4 of:
624625@book{hairer2008solving-i,
625626 address={Berlin},
@@ -631,8 +632,10 @@ def _pid_controller(stepsize_controller, terms=None):
631632 year={2008}
632633}
633634"""
635+ )
634636 else :
635- return r"""
637+ out .add (
638+ r"""
636639% The use of a PI-controller to adapt step sizes is from Section IV.2 of:
637640@book{hairer2002solving-ii,
638641 address={Berlin},
@@ -653,9 +656,11 @@ def _pid_controller(stepsize_controller, terms=None):
653656 pages={281--310}
654657}
655658"""
659+ )
656660 else :
657- return r"""
658- % The use of a PID controller to adapt step sizes is from:
661+ out .add (
662+ r"""
663+ % The use of a PID-controller to adapt step sizes is from:
659664@article{soderlind2003digital,
660665 title={{D}igital {F}ilters in {A}daptive {T}ime-{S}tepping,
661666 author={Gustaf S{\"o}derlind},
@@ -666,3 +671,16 @@ def _pid_controller(stepsize_controller, terms=None):
666671 pages={1--26}
667672}
668673"""
674+ )
675+ elif type (stepsize_controller ) is ClipStepSizeController :
676+ out .update (_stepsize_controller_impl (terms , stepsize_controller .controller ))
677+ if stepsize_controller .store_rejected_steps is not None and is_sde (terms ):
678+ out .add (
679+ r"""
680+ % You are adaptively solving an SDE whilst revisiting rejected time points. This is a
681+ % subtle point required for the correctness of adaptive noncommutative SDE solves, as
682+ % found in:
683+ """
684+ + _parse_reference (ClipStepSizeController )
685+ )
686+ return out
0 commit comments