10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-07-16 16:10:22 +02:00
QCaml/ao/lib/basis_gaussian.ml

160 lines
5.1 KiB
OCaml
Raw Normal View History

2021-01-04 23:15:27 +01:00
(* [[file:~/QCaml/ao/basis_gaussian.org::*Type][Type:2]] *)
2020-10-09 09:47:57 +02:00
open Linear_algebra
2020-10-10 10:59:09 +02:00
open Gaussian
2020-10-09 09:47:57 +02:00
open Gaussian_integrals
open Operators
2023-04-24 19:01:42 +02:00
2020-10-10 10:59:09 +02:00
module Basis = Gaussian.Basis
2020-10-09 09:38:52 +02:00
2020-10-02 23:35:56 +02:00
type t =
{
2020-10-03 00:54:17 +02:00
basis : Basis.t ;
overlap : Overlap.t lazy_t;
multipole : Multipole.t lazy_t;
ortho : Orthonormalization.t lazy_t;
eN_ints : Electron_nucleus.t lazy_t;
kin_ints : Kinetic.t lazy_t;
ee_ints : Eri.t lazy_t;
ee_lr_ints : Eri_long_range.t lazy_t;
f12_ints : F12.t lazy_t;
f12_over_r12_ints : Screened_eri.t lazy_t;
cartesian : bool ;
2020-10-02 23:35:56 +02:00
}
2021-01-04 23:15:27 +01:00
(* Type:2 ends here *)
2020-10-02 23:35:56 +02:00
2021-01-04 23:15:27 +01:00
2021-01-28 00:34:26 +01:00
(* |---------------------+--------------------------------------------------|
* | ~basis~ | One-electron basis set |
2021-01-04 23:15:27 +01:00
* | ~cartesian~ | If true, use cartesian Gaussians (6d, 10f, ...) |
* | ~ee_ints~ | Electron-electron potential integrals |
* | ~ee_lr_ints~ | Electron-electron long-range potential integrals |
* | ~eN_ints~ | Electron-nucleus potential integrals |
* | ~f12_ints~ | Electron-electron potential integrals |
* | ~f12_over_r12_ints~ | Electron-electron potential integrals |
* | ~kin_ints~ | Kinetic energy integrals |
* | ~multipole~ | Multipole matrices |
* | ~ortho~ | Orthonormalization matrix of the overlap |
* | ~overlap~ | Overlap matrix |
2021-01-28 00:34:26 +01:00
* | ~size~ | Number of atomic orbitals |
* |---------------------+--------------------------------------------------| *)
2021-01-04 23:15:27 +01:00
(* [[file:~/QCaml/ao/basis_gaussian.org::*Access][Access:2]] *)
2020-10-02 23:35:56 +02:00
let basis t = t.basis
2021-01-04 23:15:27 +01:00
let cartesian t = t.cartesian
2020-10-02 23:35:56 +02:00
let ee_ints t = Lazy.force t.ee_ints
let ee_lr_ints t = Lazy.force t.ee_lr_ints
2021-01-04 23:15:27 +01:00
let eN_ints t = Lazy.force t.eN_ints
2020-10-02 23:35:56 +02:00
let f12_ints t = Lazy.force t.f12_ints
let f12_over_r12_ints t = Lazy.force t.f12_over_r12_ints
2021-01-04 23:15:27 +01:00
let kin_ints t = Lazy.force t.kin_ints
let multipole t = Lazy.force t.multipole
let ortho t = Lazy.force t.ortho
let overlap t = Lazy.force t.overlap
let size t = Matrix.dim1 (Lazy.force t.overlap)
(* Access:2 ends here *)
2021-01-28 00:34:26 +01:00
(* |----------+--------------------------------------------------------------|
* | ~values~ | Returns the values of all the AOs evaluated at a given point |
* |----------+--------------------------------------------------------------| *)
2020-10-02 23:35:56 +02:00
2021-01-04 23:15:27 +01:00
(* [[file:~/QCaml/ao/basis_gaussian.org::*Computation][Computation:2]] *)
2020-10-03 00:54:17 +02:00
module Cs = Contracted_shell
2020-10-02 23:35:56 +02:00
let values t point =
2020-10-03 00:54:17 +02:00
let result = Vector.create (Basis.size t.basis) in
let resultx = Vector.to_bigarray_inplace result in
2020-10-02 23:35:56 +02:00
Array.iter (fun shell ->
Cs.values shell point
|> Array.iteri
(fun i_c value ->
let i = Cs.index shell + i_c + 1 in
2020-10-03 00:54:17 +02:00
resultx.{i} <- value)
2020-10-02 23:35:56 +02:00
) (Basis.contracted_shells t.basis);
result
2021-01-04 23:15:27 +01:00
(* Computation:2 ends here *)
2020-10-02 23:35:56 +02:00
2021-01-04 23:15:27 +01:00
2023-04-24 19:01:42 +02:00
2021-01-04 23:15:27 +01:00
(* Creates the data structure for atomic orbitals from a Gaussian basis and the
* molecular geometry ~Nuclei.t~.
*
* Defaults:
* - ~operators~ : ~[]~
* - ~cartesian~ : ~false~
*
2021-01-28 00:34:26 +01:00
* Example:
2021-01-04 23:15:27 +01:00
* #+begin_example
* let b = Ao.Basis_gaussian.make ~basis nuclei ;;
* val b : Ao.Basis_gaussian.t = Gaussian Basis, spherical, 15 AOs
* #+end_example *)
(* [[file:~/QCaml/ao/basis_gaussian.org::*Creation][Creation:2]] *)
2020-10-03 00:54:17 +02:00
let make ~basis ?(operators=[]) ?(cartesian=false) nuclei =
2023-04-24 19:01:42 +02:00
2020-10-03 00:54:17 +02:00
let overlap = lazy (
Overlap.of_basis basis
) in
2023-04-24 19:01:42 +02:00
2020-10-03 00:54:17 +02:00
let ortho = lazy (
Lazy.force overlap
2023-04-24 19:01:42 +02:00
|> Orthonormalization.make ~cartesian ~basis
2020-10-03 00:54:17 +02:00
) in
2023-04-24 19:01:42 +02:00
2020-10-03 00:54:17 +02:00
let eN_ints = lazy (
Electron_nucleus.of_basis_nuclei ~basis nuclei
) in
2023-04-24 19:01:42 +02:00
2020-10-03 00:54:17 +02:00
let kin_ints = lazy (
Kinetic.of_basis basis
) in
2023-04-24 19:01:42 +02:00
2020-10-03 00:54:17 +02:00
let ee_ints = lazy (
Eri.of_basis basis
) in
2023-04-24 19:01:42 +02:00
2020-10-03 00:54:17 +02:00
let rec get_f12 = function
| (Operator.F12 _ as f) :: _ -> f
| [] -> failwith "Missing F12 operator"
| _ :: rest -> get_f12 rest
in
2020-10-02 23:35:56 +02:00
2020-10-03 00:54:17 +02:00
let rec get_rs = function
| (Operator.Range_sep _ as r) :: _ -> r
| [] -> failwith "Missing range-separation operator"
| _ :: rest -> get_rs rest
in
2020-10-02 23:35:56 +02:00
2020-10-03 00:54:17 +02:00
let ee_lr_ints = lazy (
Eri_long_range.of_basis basis~operator:(get_rs operators)
) in
2023-04-24 19:01:42 +02:00
2020-10-03 00:54:17 +02:00
let f12_ints = lazy (
F12.of_basis basis ~operator:(get_f12 operators)
) in
2023-04-24 19:01:42 +02:00
2020-10-03 00:54:17 +02:00
let f12_over_r12_ints = lazy (
Screened_eri.of_basis basis ~operator:(get_f12 operators)
) in
2020-10-02 23:35:56 +02:00
2020-10-03 00:54:17 +02:00
let multipole = lazy (
2020-10-02 23:35:56 +02:00
Multipole.of_basis basis
) in
{ basis ; overlap ; multipole ; ortho ; eN_ints ; kin_ints ; ee_ints ;
2020-10-03 00:54:17 +02:00
ee_lr_ints ; f12_ints ; f12_over_r12_ints ; cartesian }
2021-01-04 23:15:27 +01:00
(* Creation:2 ends here *)
(* [[file:~/QCaml/ao/basis_gaussian.org::*Printers][Printers:2]] *)
let pp ppf t =
let cart = if t.cartesian then "cartesian" else "spherical" in
let nao = size t in
Format.fprintf ppf "@[@[Gaussian Basis@], @[%s@], @[%d AOs@]@]"
cart nao
(* Printers:2 ends here *)