sig
  type ('d, 'k) bsession = ('d, 'k) Ida_impl.AdjointTypes.bsession
  type 'a serial_bsession = (Sundials.RealArray.t, 'a) Idas.Adjoint.bsession
    constraint 'a = [> Nvector_serial.kind ]
  type interpolation = IPolynomial | IHermite
  val init :
    ('d, 'k) Ida.session -> int -> Idas.Adjoint.interpolation -> unit
  val forward_normal :
    ('d, 'k) Ida.session ->
    float ->
    ('d, 'k) Nvector.t ->
    ('d, 'k) Nvector.t -> float * int * Ida.solver_result
  val forward_one_step :
    ('d, 'k) Ida.session ->
    float ->
    ('d, 'k) Nvector.t ->
    ('d, 'k) Nvector.t -> float * int * Ida.solver_result
  type ('data, 'kind) linear_solver =
      ('data, 'kind) Ida_impl.AdjointTypes.linear_solver
  type 'a serial_linear_solver =
      (Sundials.RealArray.t, 'a) Idas.Adjoint.linear_solver
    constraint 'a = [> Nvector_serial.kind ]
  type 'd triple = 'd * 'd * 'd
  type ('t, 'd) jacobian_arg =
    ('t, 'd) Ida_impl.AdjointTypes.jacobian_arg = {
    jac_t : float;
    jac_y : 'd;
    jac_y' : 'd;
    jac_yb : 'd;
    jac_yb' : 'd;
    jac_resb : 'd;
    jac_coef : float;
    jac_tmp : 't;
  }
  module Dls :
    sig
      val dense :
        ?context:Sundials.Context.t ->
        ([> Nvector_serial.kind ] as 'a) Nvector.serial ->
        'Sundials.Matrix.dense ->
        (Sundials.Matrix.Dense.t, 'a, [ `Dls ])
        Sundials_LinearSolver.serial_t
      val lapack_dense :
        ?context:Sundials.Context.t ->
        ([> Nvector_serial.kind ] as 'a) Nvector.serial ->
        'Sundials.Matrix.dense ->
        (Sundials.Matrix.Dense.t, 'a, [ `Dls ])
        Sundials_LinearSolver.serial_t
      val band :
        ?context:Sundials.Context.t ->
        ([> Nvector_serial.kind ] as 'a) Nvector.serial ->
        'Sundials.Matrix.band ->
        (Sundials.Matrix.Band.t, 'a, [ `Dls ]) Sundials_LinearSolver.serial_t
      val lapack_band :
        ?context:Sundials.Context.t ->
        ([> Nvector_serial.kind ] as 'a) Nvector.serial ->
        'Sundials.Matrix.band ->
        (Sundials.Matrix.Band.t, 'a, [ `Dls ]) Sundials_LinearSolver.serial_t
      module Klu :
        sig
          type ordering =
            Sundials_LinearSolver_impl.Klu.ordering =
              Amd
            | ColAmd
            | Natural
          val make :
            ?context:Sundials.Context.t ->
            ?ordering:ordering ->
            ([> Nvector_serial.kind ] as 'a) Nvector.serial ->
            ('s, 'a) Sundials.Matrix.sparse ->
            ('Sundials.Matrix.Sparse.t, 'a, [ `Dls | `Klu ])
            Sundials_LinearSolver.serial_t
          val reinit :
            ('Sundials.Matrix.Sparse.t, [> Nvector_serial.kind ] as 'a,
             [> `Klu ])
            Sundials_LinearSolver.serial_t ->
            ('s, 'a) Sundials.Matrix.sparse -> ?nnz:int -> unit -> unit
          val set_ordering :
            ('Sundials.Matrix.Sparse.t, [> Nvector_serial.kind ],
             [> `Klu ])
            Sundials_LinearSolver.serial_t -> ordering -> unit
        end
      val klu :
        ?context:Sundials.Context.t ->
        ?ordering:Klu.ordering ->
        ([> Nvector_serial.kind ] as 'a) Nvector.serial ->
        ('s, 'a) Sundials.Matrix.sparse ->
        ('Sundials.Matrix.Sparse.t, 'a, [ `Dls | `Klu ])
        Sundials_LinearSolver.serial_t
      module Superlumt :
        sig
          type ordering =
            Sundials_LinearSolver_impl.Superlumt.ordering =
              Natural
            | MinDegreeProd
            | MinDegreeSum
            | ColAmd
          val make :
            ?context:Sundials.Context.t ->
            ?ordering:ordering ->
            nthreads:int ->
            ([> Nvector_serial.kind ] as 'a) Nvector.serial ->
            ('s, 'a) Sundials.Matrix.sparse ->
            ('Sundials.Matrix.Sparse.t, 'a, [ `Dls | `Slu ])
            Sundials_LinearSolver.serial_t
          val set_ordering :
            ('Sundials.Matrix.Sparse.t, [> Nvector_serial.kind ],
             [> `Slu ])
            Sundials_LinearSolver.serial_t -> ordering -> unit
        end
      val superlumt :
        ?context:Sundials.Context.t ->
        ?ordering:Superlumt.ordering ->
        nthreads:int ->
        ([> Nvector_serial.kind ] as 'a) Nvector.serial ->
        ('s, 'a) Sundials.Matrix.sparse ->
        ('Sundials.Matrix.Sparse.t, 'a, [> `Dls | `Slu ])
        Sundials_LinearSolver.serial_t
      type 'm jac_fn_no_sens =
          (Sundials.RealArray.t Idas.Adjoint.triple, Sundials.RealArray.t)
          Idas.Adjoint.jacobian_arg -> '-> unit
      type 'm jac_fn_with_sens =
          (Sundials.RealArray.t Idas.Adjoint.triple, Sundials.RealArray.t)
          Idas.Adjoint.jacobian_arg ->
          Sundials.RealArray.t array ->
          Sundials.RealArray.t array -> '-> unit
      type 'm jac_fn =
          NoSens of 'Idas.Adjoint.Dls.jac_fn_no_sens
        | WithSens of 'Idas.Adjoint.Dls.jac_fn_with_sens
      val solver :
        ?jac:'Idas.Adjoint.Dls.jac_fn ->
        ('m, Sundials.RealArray.t, [> Nvector_serial.kind ] as 'a, 't)
        Sundials.LinearSolver.t -> 'Idas.Adjoint.serial_linear_solver
      val get_work_space :
        [> Nvector_serial.kind ] Idas.Adjoint.serial_bsession -> int * int
      val get_num_jac_evals :
        [> Nvector_serial.kind ] Idas.Adjoint.serial_bsession -> int
      val get_num_lin_res_evals :
        [> Nvector_serial.kind ] Idas.Adjoint.serial_bsession -> int
    end
  module Spils :
    sig
      type gramschmidt_type =
        Sundials_LinearSolver_impl.Iterative.gramschmidt_type =
          ModifiedGS
        | ClassicalGS
      val spbcgs :
        ?context:Sundials.Context.t ->
        ?maxl:int ->
        ('d, 'k) Nvector.t ->
        ('m, 'd, 'k, [ `Iter | `Spbcgs ]) Sundials_LinearSolver.t
      val spfgmr :
        ?context:Sundials.Context.t ->
        ?maxl:int ->
        ?max_restarts:int ->
        ?gs_type:gramschmidt_type ->
        ('d, 'k) Nvector.t ->
        ('m, 'd, 'k, [ `Iter | `Spfgmr ]) Sundials_LinearSolver.t
      val spgmr :
        ?context:Sundials.Context.t ->
        ?maxl:int ->
        ?max_restarts:int ->
        ?gs_type:gramschmidt_type ->
        ('d, 'k) Nvector.t ->
        ('m, 'd, 'k, [ `Iter | `Spgmr ]) Sundials_LinearSolver.t
      val sptfqmr :
        ?context:Sundials.Context.t ->
        ?maxl:int ->
        ('d, 'k) Nvector.t ->
        ('m, 'd, 'k, [ `Iter | `Sptfqmr ]) Sundials_LinearSolver.t
      val pcg :
        ?context:Sundials.Context.t ->
        ?maxl:int ->
        ('d, 'k) Nvector.t ->
        ('m, 'd, 'k, [ `Iter | `Pcg ]) Sundials_LinearSolver.t
      module Algorithms :
        sig
          val qr_fact :
            int ->
            Sundials.RealArray2.t -> Sundials.RealArray.t -> bool -> unit
          val qr_sol :
            int ->
            Sundials.RealArray2.t ->
            Sundials.RealArray.t -> Sundials.RealArray.t -> unit
          val modified_gs :
            ('d, 'k) Nvector.t array ->
            Sundials.RealArray2.t -> int -> int -> float
          val classical_gs :
            ('d, 'k) Nvector.t array ->
            Sundials.RealArray2.t ->
            int ->
            int -> Sundials.RealArray.t -> ('d, 'k) Nvector.t array -> float
        end
      val set_maxl :
        ('m, 'd, 'k, [< `Iter | `Pcg | `Spbcgs | `Sptfqmr ])
        Sundials_LinearSolver.t -> int -> unit
      val set_gs_type :
        ('m, 'd, 'k, [< `Iter | `Spfgmr | `Spgmr ]) Sundials_LinearSolver.t ->
        gramschmidt_type -> unit
      val set_max_restarts :
        ('m, 'd, 'k, [< `Iter | `Spfgmr | `Spgmr ]) Sundials_LinearSolver.t ->
        int -> unit
      type preconditioning_type =
        Sundials_LinearSolver_impl.Iterative.preconditioning_type =
          PrecNone
        | PrecLeft
        | PrecRight
        | PrecBoth
      val set_prec_type :
        ('m, 'd, 'k, [> `Iter ]) Sundials_LinearSolver.t ->
        preconditioning_type -> unit
      val set_info_file :
        ('m, 'd, 'k, [> `Iter ]) Sundials_LinearSolver.t ->
        ?print_level:bool -> Sundials.Logfile.t -> unit
      val set_print_level :
        ('m, 'd, 'k, [> `Iter ]) Sundials_LinearSolver.t -> bool -> unit
      type 'd prec_solve_fn =
          (unit, 'd) Idas.Adjoint.jacobian_arg -> '-> '-> float -> unit
      type 'd prec_solve_fn_with_sens =
          (unit, 'd) Idas.Adjoint.jacobian_arg ->
          'd array -> 'd array -> '-> '-> float -> unit
      type 'd prec_setup_fn = (unit, 'd) Idas.Adjoint.jacobian_arg -> unit
      type 'd prec_setup_fn_with_sens =
          (unit, 'd) Idas.Adjoint.jacobian_arg ->
          'd array -> 'd array -> unit
      type ('d, 'k) preconditioner =
          ('d, 'k) Ida_impl.AdjointTypes.SpilsTypes.preconditioner
      val prec_none : ('d, 'k) Idas.Adjoint.Spils.preconditioner
      val prec_left :
        ?setup:'Idas.Adjoint.Spils.prec_setup_fn ->
        'Idas.Adjoint.Spils.prec_solve_fn ->
        ('d, 'k) Idas.Adjoint.Spils.preconditioner
      val prec_left_with_sens :
        ?setup:'Idas.Adjoint.Spils.prec_setup_fn_with_sens ->
        'Idas.Adjoint.Spils.prec_solve_fn_with_sens ->
        ('d, 'k) Idas.Adjoint.Spils.preconditioner
      type 'd jac_times_setup_fn_no_sens =
          (unit, 'd) Idas.Adjoint.jacobian_arg -> unit
      type 'd jac_times_setup_fn_with_sens =
          (unit, 'd) Idas.Adjoint.jacobian_arg -> 'd array -> unit
      type 'd jac_times_vec_fn_no_sens =
          ('d, 'd) Idas.Adjoint.jacobian_arg -> '-> '-> unit
      type 'd jac_times_vec_fn_with_sens =
          ('d, 'd) Idas.Adjoint.jacobian_arg ->
          'd array -> 'd array -> '-> '-> unit
      type 'd jac_times_vec_fn =
          NoSens of 'Idas.Adjoint.Spils.jac_times_setup_fn_no_sens option *
            'Idas.Adjoint.Spils.jac_times_vec_fn_no_sens
        | WithSens of
            'Idas.Adjoint.Spils.jac_times_setup_fn_with_sens option *
            'Idas.Adjoint.Spils.jac_times_vec_fn_with_sens
      val solver :
        ('m, 'd, 'k, 'f) Sundials.LinearSolver.t ->
        ?jac_times_vec:'Idas.Adjoint.Spils.jac_times_vec_fn ->
        ?jac_times_res:'Ida.resfn ->
        ('d, 'k) Idas.Adjoint.Spils.preconditioner ->
        ('d, 'k) Idas.Adjoint.linear_solver
      val set_eps_lin : ('d, 'k) Idas.Adjoint.bsession -> float -> unit
      val set_ls_norm_factor :
        ('d, 'k) Idas.Adjoint.bsession -> float -> unit
      val set_linear_solution_scaling :
        ('d, 'k) Idas.Adjoint.bsession -> bool -> unit
      val set_increment_factor :
        ('d, 'k) Idas.Adjoint.bsession -> float -> unit
      val get_work_space : ('d, 'k) Idas.Adjoint.bsession -> int * int
      val get_num_lin_iters : ('d, 'k) Idas.Adjoint.bsession -> int
      val get_num_lin_conv_fails : ('d, 'k) Idas.Adjoint.bsession -> int
      val get_num_prec_evals : ('d, 'k) Idas.Adjoint.bsession -> int
      val get_num_prec_solves : ('d, 'k) Idas.Adjoint.bsession -> int
      val get_num_jtsetup_evals : ('d, 'k) Idas.Adjoint.bsession -> int
      val get_num_jtimes_evals : ('d, 'k) Idas.Adjoint.bsession -> int
      val get_num_lin_res_evals : ('d, 'k) Idas.Adjoint.bsession -> int
      val set_preconditioner :
        ('d, 'k) Idas.Adjoint.bsession ->
        ?setup:'Idas.Adjoint.Spils.prec_setup_fn ->
        'Idas.Adjoint.Spils.prec_solve_fn -> unit
      val set_preconditioner_with_sens :
        ('d, 'k) Idas.Adjoint.bsession ->
        ?setup:'Idas.Adjoint.Spils.prec_setup_fn_with_sens ->
        'Idas.Adjoint.Spils.prec_solve_fn_with_sens -> unit
      val set_jac_times :
        ('d, 'k) Idas.Adjoint.bsession ->
        'Idas.Adjoint.Spils.jac_times_vec_fn -> unit
      val clear_jac_times : ('d, 'k) Idas.Adjoint.bsession -> unit
    end
  val matrix_embedded_solver :
    (unit, 'data, 'kind, [> `MatE ]) Sundials.LinearSolver.t ->
    ('data, 'kind) Idas.Adjoint.linear_solver
  type 'd bresfn_args =
    'Ida_impl.AdjointTypes.bresfn_args = {
    t : float;
    y : 'd;
    y' : 'd;
    yb : 'd;
    yb' : 'd;
  }
  type 'd bresfn_no_sens = 'Idas.Adjoint.bresfn_args -> '-> unit
  type 'd bresfn_with_sens =
      'Idas.Adjoint.bresfn_args -> 'd array -> 'd array -> '-> unit
  type 'd bresfn =
      NoSens of 'Idas.Adjoint.bresfn_no_sens
    | WithSens of 'Idas.Adjoint.bresfn_with_sens
  type ('d, 'k) tolerance =
      SStolerances of float * float
    | SVtolerances of float * ('d, 'k) Nvector.t
  val init_backward :
    ('d, 'k) Ida.session ->
    ('d, 'k) Idas.Adjoint.tolerance ->
    ?nlsolver:('d, 'k, ('d, 'k) Idas.session, [ `Nvec ])
              Sundials.NonlinearSolver.t ->
    lsolver:('d, 'k) Idas.Adjoint.linear_solver ->
    'Idas.Adjoint.bresfn ->
    ?varid:('d, 'k) Nvector.t ->
    float ->
    ('d, 'k) Nvector.t ->
    ('d, 'k) Nvector.t -> ('d, 'k) Idas.Adjoint.bsession
  module Quadrature :
    sig
      type 'd bquadrhsfn_args = {
        t : float;
        y : 'd;
        y' : 'd;
        yb : 'd;
        yb' : 'd;
      }
      type 'd bquadrhsfn_no_sens =
          'Idas.Adjoint.Quadrature.bquadrhsfn_args -> '-> unit
      type 'd bquadrhsfn_with_sens =
          'Idas.Adjoint.Quadrature.bquadrhsfn_args ->
          'd array -> 'd array -> '-> unit
      type 'd bquadrhsfn =
          NoSens of 'Idas.Adjoint.Quadrature.bquadrhsfn_no_sens
        | WithSens of 'Idas.Adjoint.Quadrature.bquadrhsfn_with_sens
      val init :
        ('d, 'k) Idas.Adjoint.bsession ->
        'Idas.Adjoint.Quadrature.bquadrhsfn -> ('d, 'k) Nvector.t -> unit
      val reinit :
        ('d, 'k) Idas.Adjoint.bsession -> ('d, 'k) Nvector.t -> unit
      type ('d, 'k) tolerance =
          NoStepSizeControl
        | SStolerances of float * float
        | SVtolerances of float * ('d, 'k) Nvector.t
      val set_tolerances :
        ('d, 'k) Idas.Adjoint.bsession ->
        ('d, 'k) Idas.Adjoint.Quadrature.tolerance -> unit
      val get : ('d, 'k) Idas.Adjoint.bsession -> ('d, 'k) Nvector.t -> float
      val get_num_rhs_evals : ('d, 'k) Idas.Adjoint.bsession -> int
      val get_num_err_test_fails : ('d, 'k) Idas.Adjoint.bsession -> int
      val get_err_weights :
        ('d, 'k) Idas.Adjoint.bsession -> ('d, 'k) Nvector.t -> unit
      val get_stats : ('d, 'k) Idas.Adjoint.bsession -> int * int
    end
  val backward_normal : ('d, 'k) Ida.session -> float -> unit
  val backward_one_step : ('d, 'k) Ida.session -> float -> unit
  val get :
    ('d, 'k) Idas.Adjoint.bsession ->
    ('d, 'k) Nvector.t -> ('d, 'k) Nvector.t -> float
  val get_dky :
    ('d, 'k) Idas.Adjoint.bsession ->
    ('d, 'k) Nvector.t -> float -> int -> unit
  val get_y :
    ('d, 'k) Ida.session ->
    ('d, 'k) Nvector.t -> ('d, 'k) Nvector.t -> float -> unit
  val reinit :
    ('d, 'k) Idas.Adjoint.bsession ->
    ?nlsolver:('d, 'k, ('d, 'k) Idas.session, [ `Nvec ])
              Sundials.NonlinearSolver.t ->
    ?lsolver:('d, 'k) Idas.Adjoint.linear_solver ->
    float -> ('d, 'k) Nvector.t -> ('d, 'k) Nvector.t -> unit
  val set_id : ('d, 'k) Idas.Adjoint.bsession -> ('d, 'k) Nvector.t -> unit
  val set_suppress_alg :
    ('d, 'k) Idas.Adjoint.bsession ->
    ?varid:('d, 'k) Nvector.t -> bool -> unit
  val calc_ic :
    ('d, 'k) Idas.Adjoint.bsession ->
    ?yb:('d, 'k) Nvector.t ->
    ?yb':('d, 'k) Nvector.t ->
    float -> ('d, 'k) Nvector.t -> ('d, 'k) Nvector.t -> unit
  val calc_ic_sens :
    ('d, 'k) Idas.Adjoint.bsession ->
    ?yb:('d, 'k) Nvector.t ->
    ?yb':('d, 'k) Nvector.t ->
    ?varid:('d, 'k) Nvector.t ->
    float ->
    ('d, 'k) Nvector.t ->
    ('d, 'k) Nvector.t ->
    ('d, 'k) Nvector.t array -> ('d, 'k) Nvector.t array -> unit
  val set_no_sensitivity : ('d, 'k) Ida.session -> unit
  val set_max_ord : ('d, 'k) Idas.Adjoint.bsession -> int -> unit
  val set_max_num_steps : ('d, 'k) Idas.Adjoint.bsession -> int -> unit
  val set_init_step : ('d, 'k) Idas.Adjoint.bsession -> float -> unit
  val set_max_step : ('d, 'k) Idas.Adjoint.bsession -> float -> unit
  val set_constraints :
    ('d, 'k) Idas.Adjoint.bsession -> ('d, 'k) Nvector.t -> unit
  val clear_constraints : ('d, 'k) Idas.Adjoint.bsession -> unit
  val get_work_space : ('d, 'k) Idas.Adjoint.bsession -> int * int
  val get_num_steps : ('d, 'k) Idas.Adjoint.bsession -> int
  val get_num_res_evals : ('d, 'k) Idas.Adjoint.bsession -> int
  val get_num_lin_solv_setups : ('d, 'k) Idas.Adjoint.bsession -> int
  val get_num_err_test_fails : ('d, 'k) Idas.Adjoint.bsession -> int
  val get_last_order : ('d, 'k) Idas.Adjoint.bsession -> int
  val get_current_order : ('d, 'k) Idas.Adjoint.bsession -> int
  val get_last_step : ('d, 'k) Idas.Adjoint.bsession -> float
  val get_current_step : ('d, 'k) Idas.Adjoint.bsession -> float
  val get_actual_init_step : ('d, 'k) Idas.Adjoint.bsession -> float
  val get_current_time : ('d, 'k) Idas.Adjoint.bsession -> float
  val get_tol_scale_factor : ('d, 'k) Idas.Adjoint.bsession -> float
  val get_err_weights :
    ('d, 'k) Idas.Adjoint.bsession -> ('d, 'k) Nvector.t -> unit
  val get_est_local_errors :
    ('d, 'k) Idas.Adjoint.bsession -> ('d, 'k) Nvector.t -> unit
  val get_integrator_stats :
    ('d, 'k) Idas.Adjoint.bsession -> Ida.integrator_stats
  val print_integrator_stats :
    ('d, 'k) Idas.Adjoint.bsession -> Stdlib.out_channel -> unit
  val get_num_nonlin_solv_iters : ('d, 'k) Idas.Adjoint.bsession -> int
  val get_num_nonlin_solv_conv_fails : ('d, 'k) Idas.Adjoint.bsession -> int
  val get_nonlin_solv_stats : ('d, 'k) Idas.Adjoint.bsession -> int * int
  exception AdjointNotInitialized
  exception NoForwardCall
  exception ForwardReinitFailure
  exception ForwardFailure
  exception NoBackwardProblem
  exception BadFinalTime
end