10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-06-02 03:15:19 +02:00
QCaml/ao/lib/basis_gaussian.ml

160 lines
5.1 KiB
OCaml

(* [[file:~/QCaml/ao/basis_gaussian.org::*Type][Type:2]] *)
open Linear_algebra
open Gaussian
open Gaussian_integrals
open Operators
module Basis = Gaussian.Basis
type t =
{
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 ;
}
(* Type:2 ends here *)
(* |---------------------+--------------------------------------------------|
* | ~basis~ | One-electron basis set |
* | ~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 |
* | ~size~ | Number of atomic orbitals |
* |---------------------+--------------------------------------------------| *)
(* [[file:~/QCaml/ao/basis_gaussian.org::*Access][Access:2]] *)
let basis t = t.basis
let cartesian t = t.cartesian
let ee_ints t = Lazy.force t.ee_ints
let ee_lr_ints t = Lazy.force t.ee_lr_ints
let eN_ints t = Lazy.force t.eN_ints
let f12_ints t = Lazy.force t.f12_ints
let f12_over_r12_ints t = Lazy.force t.f12_over_r12_ints
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 *)
(* |----------+--------------------------------------------------------------|
* | ~values~ | Returns the values of all the AOs evaluated at a given point |
* |----------+--------------------------------------------------------------| *)
(* [[file:~/QCaml/ao/basis_gaussian.org::*Computation][Computation:2]] *)
module Cs = Contracted_shell
let values t point =
let result = Vector.create (Basis.size t.basis) in
let resultx = Vector.to_bigarray_inplace result in
Array.iter (fun shell ->
Cs.values shell point
|> Array.iteri
(fun i_c value ->
let i = Cs.index shell + i_c + 1 in
resultx.{i} <- value)
) (Basis.contracted_shells t.basis);
result
(* Computation:2 ends here *)
(* Creates the data structure for atomic orbitals from a Gaussian basis and the
* molecular geometry ~Nuclei.t~.
*
* Defaults:
* - ~operators~ : ~[]~
* - ~cartesian~ : ~false~
*
* Example:
* #+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]] *)
let make ~basis ?(operators=[]) ?(cartesian=false) nuclei =
let overlap = lazy (
Overlap.of_basis basis
) in
let ortho = lazy (
Lazy.force overlap
|> Orthonormalization.make ~cartesian ~basis
) in
let eN_ints = lazy (
Electron_nucleus.of_basis_nuclei ~basis nuclei
) in
let kin_ints = lazy (
Kinetic.of_basis basis
) in
let ee_ints = lazy (
Eri.of_basis basis
) in
let rec get_f12 = function
| (Operator.F12 _ as f) :: _ -> f
| [] -> failwith "Missing F12 operator"
| _ :: rest -> get_f12 rest
in
let rec get_rs = function
| (Operator.Range_sep _ as r) :: _ -> r
| [] -> failwith "Missing range-separation operator"
| _ :: rest -> get_rs rest
in
let ee_lr_ints = lazy (
Eri_long_range.of_basis basis~operator:(get_rs operators)
) in
let f12_ints = lazy (
F12.of_basis basis ~operator:(get_f12 operators)
) in
let f12_over_r12_ints = lazy (
Screened_eri.of_basis basis ~operator:(get_f12 operators)
) in
let multipole = lazy (
Multipole.of_basis basis
) in
{ basis ; overlap ; multipole ; ortho ; eN_ints ; kin_ints ; ee_ints ;
ee_lr_ints ; f12_ints ; f12_over_r12_ints ; cartesian }
(* 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 *)