(** Data structure to represent the molecular orbitals.

    The MO indices start from 1.

*)

open Lacaml.D

type mo_type =
  | RHF | ROHF | UHF | CASSCF | Projected
  | Natural of string
  | Localized of string


type t

(** {1 Accessors} *)

val simulation : t -> Simulation.t
(** Simulation which produced the MOs *)

val mo_type : t -> mo_type
(** Kind of MOs (RHF, CASSCF, Localized...) *)

val ao_basis : t -> AOBasis.t
(** Matrix of the MO coefficients in the AO basis *)

val mo_occupation : t -> Vec.t
(** Occupation numbers *)

val mo_coef : t -> Mat.t
(** Molecular orbitcal coefficients *)

val eN_ints : t -> NucInt.t
(** Electron-nucleus potential integrals *)

val ee_ints : t -> ERI.t
(** Electron-electron repulsion integrals *)

val kin_ints : t -> KinInt.t
(** Kinetic energy integrals *)

val one_e_ints : t -> Mat.t
(** One-electron integrals {% $\hat{T} + V$ %} *)

val two_e_ints : t -> ERI.t
(** Electron-electron repulsion integrals *)

val f12_ints : t -> F12.t
(** F12 integrals *)

val size : t -> int
(** Number of molecular orbitals in the basis *)

val mo_energies : t -> Vec.t
(** Fock MO energies *)

val values : t -> Coordinate.t -> Vec.t
(** Values of the MOs evaluated at a given coordinate. *)

(** {1 Creators} *)

val make : simulation:Simulation.t ->
  mo_type:mo_type ->
  mo_occupation:Vec.t ->
  mo_coef:Mat.t ->
  unit -> t
(** Function to build a data structure representing the molecular orbitals. *)

val of_hartree_fock : HartreeFock.t -> t
(** Build MOs from a Restricted Hartree-Fock calculation. *)

val of_mo_basis : Simulation.t -> t -> t
(** Project the MOs of the other basis on the current one. *)


val mo_matrix_of_ao_matrix : mo_coef:Mat.t -> Mat.t -> Mat.t
(** Build a matrix in MO basis from a matrix in AO basis. *)

val ao_matrix_of_mo_matrix : mo_coef:Mat.t ->  ao_overlap:Mat.t -> Mat.t -> Mat.t 
(** Build a matrix in AO basis from a matrix in MO basis. *)



(** {1 Printers} *)

val pp : ?start:int -> ?finish:int -> Format.formatter -> t -> unit


