10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-12-23 04:43:32 +01:00
QCaml/perturbation/lib/mp2.ml

84 lines
2.1 KiB
OCaml
Raw Normal View History

2024-02-28 11:07:24 +01:00
(** Type *)
2021-01-01 16:39:33 +01:00
type t = {
energy : float ;
mo_basis : Mo.Basis.t ;
frozen_core : Mo.Frozen_core.t ;
}
2024-02-28 11:07:24 +01:00
(** Creation *)
2021-01-01 16:39:33 +01:00
2020-12-07 13:52:56 +01:00
open Linear_algebra
2021-01-01 16:39:33 +01:00
let make_rmp2 mo_basis mo_class =
let epsilon = Mo.Basis.mo_energies mo_basis in
let eri = Mo.Basis.ee_ints mo_basis in
2020-12-07 13:52:56 +01:00
let inactives =
List.filter (fun i ->
match i with Mo.Class.Inactive _ -> true | _ -> false) mo_class
and virtuals =
List.filter (fun i ->
match i with Mo.Class.Virtual _ -> true | _ -> false) mo_class
in
2021-01-01 16:39:33 +01:00
List.fold_left (fun accu b ->
match b with Mo.Class.Virtual b ->
let eps = -. (epsilon%.(b)) in
2024-02-28 11:07:24 +01:00
accu +.
2021-01-01 16:39:33 +01:00
List.fold_left (fun accu a ->
match a with Mo.Class.Virtual a ->
let eps = eps -. (epsilon%.(a)) in
2024-02-28 11:07:24 +01:00
accu +.
2021-01-01 16:39:33 +01:00
List.fold_left (fun accu j ->
match j with Mo.Class.Inactive j ->
let eps = eps +. epsilon%.(j) in
2024-02-28 11:07:24 +01:00
accu +.
2021-01-01 16:39:33 +01:00
List.fold_left (fun accu i ->
match i with Mo.Class.Inactive i ->
let eps = eps +. epsilon%.(i) in
let ijab = Four_idx_storage.get_phys eri i j a b
and abji = Four_idx_storage.get_phys eri a b j i in
let abij = ijab in
2024-02-28 11:07:24 +01:00
accu +. ijab *. ( abij +. abij -. abji) /. eps
2021-01-01 16:39:33 +01:00
| _ -> accu
) 0. inactives
| _ -> accu
) 0. inactives
| _ -> accu
2020-12-07 13:52:56 +01:00
) 0. virtuals
2021-01-01 16:39:33 +01:00
| _ -> accu
) 0. virtuals
let make ~frozen_core mo_basis =
let mo_class =
Mo.Class.cas_sd mo_basis ~frozen_core 0 0
|> Mo.Class.to_list
in
2024-02-28 11:07:24 +01:00
let energy =
2021-01-01 16:39:33 +01:00
match Mo.Basis.mo_type mo_basis with
| RHF -> make_rmp2 mo_basis mo_class
| ROHF -> Common.Util.not_implemented "ROHF MP2"
| UHF -> Common.Util.not_implemented "UHF MP2"
| _ -> invalid_arg "MP2 needs RHF or ROHF MOs"
2020-12-07 13:52:56 +01:00
in
2021-01-01 16:39:33 +01:00
{ energy ; mo_basis ; frozen_core }
2020-12-07 13:52:56 +01:00
2024-02-28 11:07:24 +01:00
(** Access *)
2020-12-07 13:52:56 +01:00
2021-01-01 16:39:33 +01:00
let energy t = t.energy
let mo_basis t = t.mo_basis
let frozen_core t = t.frozen_core
2020-12-07 13:52:56 +01:00
2024-02-28 11:07:24 +01:00
(** Printers *)
2021-01-01 16:39:33 +01:00
let pp ppf t =
Format.fprintf ppf "@[E(MP2)=%f@]" t.energy
2024-02-28 11:07:24 +01:00