sig
  type ('d, 'k) session = ('d, 'k) Cvode_impl.session
  type 'a serial_session = (Nvector_serial.data, 'a) Cvode.session
    constraint 'a = [> Nvector_serial.kind ]
  type ('data, 'kind) linear_solver = ('data, 'kind) Cvode_impl.linear_solver
  type 'a serial_linear_solver =
      (Nvector_serial.data, 'a) Cvode.linear_solver
    constraint 'a = [> Nvector_serial.kind ]
  type 'd double = 'd * 'd
  type 'd triple = 'd * 'd * 'd
  type ('t, 'd) jacobian_arg =
    ('t, 'd) Cvode_impl.jacobian_arg = {
    jac_t : float;
    jac_y : 'd;
    jac_fy : 'd;
    jac_tmp : 't;
  }
  type 'd rhsfn = float -> '-> '-> unit
  module Diag :
    sig
      val solver : ('data, 'kind) Cvode.linear_solver
      val get_work_space : ('d, 'k) Cvode.session -> int * int
      val get_num_rhs_evals : ('d, 'k) Cvode.session -> int
    end
  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 =
          (Sundials.RealArray.t Cvode.triple, Sundials.RealArray.t)
          Cvode.jacobian_arg -> '-> unit
      type 'm linsys_fn =
          (Sundials.RealArray.t Cvode.triple, Sundials.RealArray.t)
          Cvode.jacobian_arg -> '-> bool -> float -> bool
      val solver :
        ?jac:'Cvode.Dls.jac_fn ->
        ?linsys:'Cvode.Dls.linsys_fn ->
        ('m, Sundials.RealArray.t, [> Nvector_serial.kind ] as 'a, [> `Dls ])
        Sundials.LinearSolver.t -> 'Cvode.serial_linear_solver
      val get_work_space :
        [> Nvector_serial.kind ] Cvode.serial_session -> int * int
      val get_num_jac_evals :
        [> Nvector_serial.kind ] Cvode.serial_session -> int
      val get_num_lin_rhs_evals :
        [> Nvector_serial.kind ] Cvode.serial_session -> 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_arg = {
        rhs : 'd;
        gamma : float;
        delta : float;
        left : bool;
      }
      type 'd prec_solve_fn =
          (unit, 'd) Cvode.jacobian_arg ->
          'Cvode.Spils.prec_solve_arg -> '-> unit
      type 'd prec_setup_fn =
          (unit, 'd) Cvode.jacobian_arg -> bool -> float -> bool
      type ('d, 'k) preconditioner =
          ('d, 'k) Cvode_impl.SpilsTypes.preconditioner
      val prec_none : ('d, 'k) Cvode.Spils.preconditioner
      val prec_left :
        ?setup:'Cvode.Spils.prec_setup_fn ->
        'Cvode.Spils.prec_solve_fn -> ('d, 'k) Cvode.Spils.preconditioner
      val prec_right :
        ?setup:'Cvode.Spils.prec_setup_fn ->
        'Cvode.Spils.prec_solve_fn -> ('d, 'k) Cvode.Spils.preconditioner
      val prec_both :
        ?setup:'Cvode.Spils.prec_setup_fn ->
        'Cvode.Spils.prec_solve_fn -> ('d, 'k) Cvode.Spils.preconditioner
      module Banded :
        sig
          type bandrange = { mupper : int; mlower : int; }
          val prec_left :
            Cvode.Spils.Banded.bandrange ->
            (Nvector_serial.data, [> Nvector_serial.kind ])
            Cvode.Spils.preconditioner
          val prec_right :
            Cvode.Spils.Banded.bandrange ->
            (Nvector_serial.data, [> Nvector_serial.kind ])
            Cvode.Spils.preconditioner
          val prec_both :
            Cvode.Spils.Banded.bandrange ->
            (Nvector_serial.data, [> Nvector_serial.kind ])
            Cvode.Spils.preconditioner
          val get_work_space :
            [> Nvector_serial.kind ] Cvode.serial_session -> int * int
          val get_num_rhs_evals :
            [> Nvector_serial.kind ] Cvode.serial_session -> int
        end
      type 'd jac_times_setup_fn = (unit, 'd) Cvode.jacobian_arg -> unit
      type 'd jac_times_vec_fn =
          ('d, 'd) Cvode.jacobian_arg -> '-> '-> unit
      val solver :
        ('m, 'd, 'k, [> `Iter ]) Sundials.LinearSolver.t ->
        ?jac_times_vec:'Cvode.Spils.jac_times_setup_fn option *
                       'Cvode.Spils.jac_times_vec_fn ->
        ?jac_times_rhs:'Cvode.rhsfn ->
        ('d, 'k) Cvode.Spils.preconditioner -> ('d, 'k) Cvode.linear_solver
      val set_jac_eval_frequency : ('d, 'k) Cvode.session -> int -> unit
      val set_lsetup_frequency : ('d, 'k) Cvode.session -> int -> unit
      val set_linear_solution_scaling :
        ('d, 'k) Cvode.session -> bool -> unit
      val set_eps_lin : ('d, 'k) Cvode.session -> float -> unit
      val set_ls_norm_factor : ('d, 'k) Cvode.session -> float -> unit
      val get_work_space : ('d, 'k) Cvode.session -> int * int
      val get_num_lin_iters : ('d, 'k) Cvode.session -> int
      val get_num_lin_conv_fails : ('d, 'k) Cvode.session -> int
      val get_num_prec_evals : ('d, 'k) Cvode.session -> int
      val get_num_prec_solves : ('d, 'k) Cvode.session -> int
      val get_num_jtsetup_evals : ('d, 'k) Cvode.session -> int
      val get_num_jtimes_evals : ('d, 'k) Cvode.session -> int
      val get_num_lin_rhs_evals : ('d, 'k) Cvode.session -> int
      val set_preconditioner :
        ('d, 'k) Cvode.session ->
        ?setup:'Cvode.Spils.prec_setup_fn ->
        'Cvode.Spils.prec_solve_fn -> unit
      val set_jac_times :
        ('d, 'k) Cvode.session ->
        ?jac_times_setup:'Cvode.Spils.jac_times_setup_fn ->
        'Cvode.Spils.jac_times_vec_fn -> unit
      val clear_jac_times : ('d, 'k) Cvode.session -> unit
    end
  val matrix_embedded_solver :
    (unit, 'data, 'kind, [> `MatE ]) Sundials.LinearSolver.t ->
    ('data, 'kind) Cvode.linear_solver
  type 'data error_weight_fun = 'data -> 'data -> unit
  type ('data, 'kind) tolerance =
      SStolerances of float * float
    | SVtolerances of float * ('data, 'kind) Nvector.t
    | WFtolerances of 'data Cvode.error_weight_fun
  val default_tolerances : ('data, 'kind) Cvode.tolerance
  type lmm = Adams | BDF
  type 'd rootsfn = float -> '-> Sundials.RealArray.t -> unit
  type 'd proj_fn = float -> '-> '-> float -> 'd option -> unit
  val init :
    ?context:Sundials.Context.t ->
    Cvode.lmm ->
    ('data, 'kind) Cvode.tolerance ->
    ?nlsolver:('data, 'kind, ('data, 'kind) Cvode.session, [ `Nvec ])
              Sundials_NonlinearSolver.t ->
    ?nlsrhsfn:'data Cvode.rhsfn ->
    ?lsolver:('data, 'kind) Cvode.linear_solver ->
    'data Cvode.rhsfn ->
    ?roots:int * 'data Cvode.rootsfn ->
    ?projfn:'data Cvode.proj_fn ->
    float -> ('data, 'kind) Nvector.t -> ('data, 'kind) Cvode.session
  val no_roots : int * 'Cvode.rootsfn
  type solver_result = Success | RootsFound | StopTimeReached
  val solve_normal :
    ('d, 'k) Cvode.session ->
    float -> ('d, 'k) Nvector.t -> float * Cvode.solver_result
  val solve_one_step :
    ('d, 'k) Cvode.session ->
    float -> ('d, 'k) Nvector.t -> float * Cvode.solver_result
  val get_dky :
    ('d, 'k) Cvode.session -> ('d, 'k) Nvector.t -> float -> int -> unit
  val reinit :
    ('d, 'k) Cvode.session ->
    ?nlsolver:('d, 'k, ('d, 'k) Cvode.session, [ `Nvec ])
              Sundials_NonlinearSolver.t ->
    ?nlsrhsfn:'Cvode.rhsfn ->
    ?lsolver:('d, 'k) Cvode.linear_solver ->
    ?roots:int * 'Cvode.rootsfn ->
    ?rhsfn:'Cvode.rhsfn -> float -> ('d, 'k) Nvector.t -> unit
  val set_tolerances :
    ('d, 'k) Cvode.session -> ('d, 'k) Cvode.tolerance -> unit
  val set_error_file : ('d, 'k) Cvode.session -> Sundials.Logfile.t -> unit
  val set_err_handler_fn :
    ('d, 'k) Cvode.session -> (Sundials.Util.error_details -> unit) -> unit
  val clear_err_handler_fn : ('d, 'k) Cvode.session -> unit
  val set_monitor_fn :
    ('d, 'k) Cvode.session -> int -> (('d, 'k) Cvode.session -> unit) -> unit
  val set_monitor_frequency : ('d, 'k) Cvode.session -> int -> unit
  val clear_monitor_fn : ('d, 'k) Cvode.session -> unit
  val set_max_ord : ('d, 'k) Cvode.session -> int -> unit
  val set_max_num_steps : ('d, 'k) Cvode.session -> int -> unit
  val set_max_hnil_warns : ('d, 'k) Cvode.session -> int -> unit
  val set_stab_lim_det : ('d, 'k) Cvode.session -> bool -> unit
  val set_init_step : ('d, 'k) Cvode.session -> float -> unit
  val set_min_step : ('d, 'k) Cvode.session -> float -> unit
  val set_max_step : ('d, 'k) Cvode.session -> float -> unit
  val set_stop_time : ('d, 'k) Cvode.session -> float -> unit
  val set_max_err_test_fails : ('d, 'k) Cvode.session -> int -> unit
  val set_max_nonlin_iters : ('d, 'k) Cvode.session -> int -> unit
  val set_max_conv_fails : ('d, 'k) Cvode.session -> int -> unit
  val set_nonlin_conv_coef : ('d, 'k) Cvode.session -> float -> unit
  val set_constraints : ('d, 'k) Cvode.session -> ('d, 'k) Nvector.t -> unit
  val clear_constraints : ('d, 'k) Cvode.session -> unit
  val set_proj_err_est : ('d, 'k) Cvode.session -> bool -> unit
  val set_proj_frequency : ('d, 'k) Cvode.session -> int -> unit
  val set_max_num_proj_fails : ('d, 'k) Cvode.session -> int -> unit
  val set_eps_proj : ('d, 'k) Cvode.session -> float -> unit
  val set_proj_fail_eta : ('d, 'k) Cvode.session -> float -> unit
  val get_work_space : ('d, 'k) Cvode.session -> int * int
  val get_num_steps : ('d, 'k) Cvode.session -> int
  val get_num_rhs_evals : ('d, 'k) Cvode.session -> int
  val get_num_lin_solv_setups : ('d, 'k) Cvode.session -> int
  val get_num_err_test_fails : ('d, 'k) Cvode.session -> int
  val get_last_order : ('d, 'k) Cvode.session -> int
  val get_current_order : ('d, 'k) Cvode.session -> int
  val get_current_state : ('d, 'k) Cvode.session -> 'd
  type 'd nonlin_system_data = {
    tn : float;
    ypred : 'd;
    yn : 'd;
    fn : 'd;
    gamma : float;
    rl1 : float;
    zn1 : 'd;
  }
  val get_nonlin_system_data :
    ('d, 'k) Cvode.session -> 'Cvode.nonlin_system_data
  val compute_state :
    ('d, 'k) Cvode.session ->
    ('d, 'k) Nvector.t -> ('d, 'k) Nvector.t -> unit
  external get_current_gamma : ('d, 'k) Cvode.session -> (float [@unboxed])
    = "sunml_cvode_get_current_gamma" "sunml_cvode_get_current_gamma_unboxed"
  val get_last_step : ('d, 'k) Cvode.session -> float
  val get_current_step : ('d, 'k) Cvode.session -> float
  val get_actual_init_step : ('d, 'k) Cvode.session -> float
  val get_current_time : ('d, 'k) Cvode.session -> float
  val get_num_stab_lim_order_reds : ('d, 'k) Cvode.session -> int
  val get_tol_scale_factor : ('d, 'k) Cvode.session -> float
  val get_err_weights : ('d, 'k) Cvode.session -> ('d, 'k) Nvector.t -> unit
  val get_est_local_errors :
    ('d, 'k) Cvode.session -> ('d, 'k) Nvector.t -> unit
  type integrator_stats = {
    num_steps : int;
    num_rhs_evals : int;
    num_lin_solv_setups : int;
    num_err_test_fails : int;
    last_order : int;
    current_order : int;
    actual_init_step : float;
    last_step : float;
    current_step : float;
    current_time : float;
  }
  val get_integrator_stats : ('d, 'k) Cvode.session -> Cvode.integrator_stats
  val print_integrator_stats :
    ('d, 'k) Cvode.session -> Stdlib.out_channel -> unit
  type linear_solver_stats = {
    jac_evals : int;
    lin_rhs_evals : int;
    lin_iters : int;
    lin_conv_fails : int;
    prec_evals : int;
    prec_solves : int;
    jtsetup_evals : int;
    jtimes_evals : int;
  }
  val get_linear_solver_stats :
    ('d, 'k) Cvode.session -> Cvode.linear_solver_stats
  val get_num_nonlin_solv_iters : ('d, 'k) Cvode.session -> int
  val get_num_nonlin_solv_conv_fails : ('d, 'k) Cvode.session -> int
  val get_nonlin_solv_stats : ('d, 'k) Cvode.session -> int * int
  val set_root_direction :
    ('d, 'k) Cvode.session -> Sundials.RootDirs.d array -> unit
  val set_all_root_directions :
    ('d, 'k) Cvode.session -> Sundials.RootDirs.d -> unit
  val set_no_inactive_root_warn : ('d, 'k) Cvode.session -> unit
  val get_num_roots : ('d, 'k) Cvode.session -> int
  val get_root_info : ('d, 'k) Cvode.session -> Sundials.Roots.t -> unit
  val get_num_g_evals : ('d, 'k) Cvode.session -> int
  val get_num_proj_evals : ('d, 'k) Cvode.session -> int
  val get_num_proj_fails : ('d, 'k) Cvode.session -> int
  exception IllInput
  exception TooClose
  exception TooMuchWork
  exception TooMuchAccuracy
  exception ErrFailure
  exception ConvergenceFailure
  exception LinearInitFailure
  exception LinearSetupFailure of exn option
  exception LinearSolveFailure of exn option
  exception NonlinearSolverFailure
  exception NonlinearInitFailure
  exception NonlinearSetupFailure
  exception RhsFuncFailure
  exception FirstRhsFuncFailure
  exception RepeatedRhsFuncFailure
  exception UnrecoverableRhsFuncFailure
  exception RootFuncFailure
  exception ConstraintFailure
  exception BadK
  exception BadT
  exception VectorOpErr
  exception ProjFuncFailure
  exception RepeatedProjFuncError
  exception ProjectionNotEnabled
end