10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-11-06 22:23:42 +01:00

Introduced AOBasis

This commit is contained in:
Anthony Scemama 2018-06-13 17:49:58 +02:00
parent d954d5ecdb
commit 9e5933f0d0
12 changed files with 165 additions and 63 deletions

View File

@ -1,7 +1,9 @@
PKG str unix bigarray lacaml PKG str unix bigarray lacaml
S . S .
S Nuclei S Nuclei
S CI
S Utils S Utils
S Basis S Basis
S SCF S SCF
S MOBasis
B _build/** B _build/**

43
Basis/AOBasis.ml Normal file
View File

@ -0,0 +1,43 @@
open Lacaml.D
type t =
{
basis : Basis.t ;
overlap : Overlap.t lazy_t;
ortho : Orthonormalization.t lazy_t;
eN_ints : NucInt.t lazy_t;
ee_ints : ERI.t lazy_t;
kin_ints : KinInt.t lazy_t;
cartesian : bool;
}
let make ~cartesian ~basis nuclei =
let overlap = lazy (
Overlap.of_basis basis
) in
let ortho = lazy (
Orthonormalization.make ~cartesian ~basis (Lazy.force overlap)
) in
let eN_ints = lazy (
NucInt.of_basis_nuclei ~basis nuclei
) in
let kin_ints = lazy (
KinInt.of_basis basis
) in
let ee_ints = lazy (
ERI.of_basis basis
) in
{ basis ; overlap ; ortho ; eN_ints ; kin_ints ; ee_ints ;
cartesian ;
}

19
Basis/AOBasis.mli Normal file
View File

@ -0,0 +1,19 @@
(** Data structure for Atomic Orbitals. *)
type t =
{
basis : Basis.t ; (* One-electron basis set *)
overlap : Overlap.t lazy_t; (* Overlap matrix *)
ortho : Orthonormalization.t lazy_t; (* Orthonormalization matrix of the overlap *)
eN_ints : NucInt.t lazy_t; (* Electron-nucleus potential integrals *)
ee_ints : ERI.t lazy_t; (* Electron-electron potential integrals *)
kin_ints : KinInt.t lazy_t; (* Kinetic energy integrals *)
cartesian : bool ; (* If true, use cartesian Gaussians (6d, 10f, ...) *)
}
val make : cartesian:bool -> basis:Basis.t -> Nuclei.t -> t
(** Creates the data structure for atomic orbitals from a {Basis.t} and the
molecular geometry {Nuclei.t} *)

17
Basis/KinInt.mli Normal file
View File

@ -0,0 +1,17 @@
(** Electronic kinetic energy integrals, expressed as a matrix in a {Basis.t}.
{%
$$
T_{ij} = \left \langle \chi_i \left| -\frac{1}{2} \Delta \right| \chi_j \right \rangle
$$
%}
*)
type t = Lacaml.D.Mat.t
val of_basis : Basis.t -> t
(** Build from a {Basis.t}. *)
val to_file : filename:string -> t -> unit
(** Write the integrals in a file. *)

View File

@ -41,7 +41,7 @@ let cutoff2 = cutoff *. cutoff
exception NullIntegral exception NullIntegral
let of_basis_nuclei basis nuclei = let of_basis_nuclei ~basis nuclei =
let to_powers x = let to_powers x =
let open Zkey in let open Zkey in
match to_powers x with match to_powers x with

15
Basis/NucInt.mli Normal file
View File

@ -0,0 +1,15 @@
(** Electron-Nucleus attractive potential integrals, expressed as a matrix in a {Basis.t}.
{% $$
V_{ij} = \left \langle \chi_i \left| \sum_A \frac{-Z_A}{ | \mathbf{r} - \mathbf{R}_A |} \right| \chi_j \right \rangle
$$ %}
*)
type t = Lacaml.D.Mat.t
val of_basis_nuclei : basis:Basis.t -> Nuclei.t -> t
(** Build from a {Basis.t} and the nuclei (coordinates and charges). *)
val to_file : filename:string -> t -> unit
(** Write the integrals in a file. *)

View File

@ -3,7 +3,6 @@ open Simulation
open Constants open Constants
type t = type t =
{ {
fock : Mat.t ; fock : Mat.t ;
@ -12,11 +11,13 @@ type t =
exchange : Mat.t ; exchange : Mat.t ;
} }
let make ~density simulation = module Ao = AOBasis
let make ~density ao_basis =
let m_P = density let m_P = density
and m_T = Lazy.force simulation.kin_ints and m_T = Lazy.force ao_basis.Ao.kin_ints
and m_V = Lazy.force simulation.eN_ints and m_V = Lazy.force ao_basis.Ao.eN_ints
and m_G = Lazy.force simulation.ee_ints and m_G = Lazy.force ao_basis.Ao.ee_ints
in in
let nBas = Mat.dim1 m_T let nBas = Mat.dim1 m_T
in in

View File

@ -7,43 +7,44 @@ type guess =
type t = guess type t = guess
module Si = Simulation module Ao = AOBasis
module El = Electrons module El = Electrons
let hcore_guess simulation = let hcore_guess ao_basis =
let eN_ints = Lazy.force simulation.Si.eN_ints let eN_ints = Lazy.force ao_basis.Ao.eN_ints
and kin_ints = Lazy.force simulation.Si.kin_ints and kin_ints = Lazy.force ao_basis.Ao.kin_ints
in in
Mat.add eN_ints kin_ints Mat.add eN_ints kin_ints
let huckel_guess simulation = let huckel_guess ao_basis =
let c = 0.5 *. 1.75 in let c = 0.5 *. 1.75 in
let ao_num = Basis.size simulation.Si.basis in let ao_num = Basis.size ao_basis.Ao.basis in
let eN_ints = Lazy.force simulation.Si.eN_ints let eN_ints = Lazy.force ao_basis.Ao.eN_ints
and kin_ints = Lazy.force simulation.Si.kin_ints and kin_ints = Lazy.force ao_basis.Ao.kin_ints
and overlap = Lazy.force simulation.Si.overlap and overlap = Lazy.force ao_basis.Ao.overlap
and m_X = Lazy.force simulation.Si.overlap_ortho and m_X = Lazy.force ao_basis.Ao.ortho
in in
let diag = Array.init (ao_num+1) (fun i -> if i=0 then 0. else let diag = Array.init (ao_num+1) (fun i -> if i=0 then 0. else
eN_ints.{i,i} +. kin_ints.{i,i}) eN_ints.{i,i} +. kin_ints.{i,i})
in in
let nocc = function
simulation.Si.electrons.El.n_alpha | 0 -> invalid_arg "Huckel guess needs a non-zero number of occupied MOs."
in | nocc ->
let m_F = (Fock.make ~density:(gemm ~alpha:2. ~transb:`T ~k:nocc m_X m_X) simulation).Fock.fock in let m_F = (Fock.make ~density:(gemm ~alpha:2. ~transb:`T ~k:nocc m_X m_X) ao_basis).Fock.fock in
for j=1 to ao_num do for j=1 to ao_num do
for i=1 to ao_num do for i=1 to ao_num do
if (i <> j) then if (i <> j) then
m_F.{i,j} <- c *. overlap.{i,j} *. (diag.(i) +. diag.(j)) (*TODO Pseudo *) m_F.{i,j} <- c *. overlap.{i,j} *. (diag.(i) +. diag.(j)) (*TODO Pseudo *)
done;
done; done;
done; m_F
m_F
let make ~guess simulation =
let make ?(nocc=0) ~guess ao_basis =
match guess with match guess with
| `Hcore -> Hcore (hcore_guess simulation) | `Hcore -> Hcore (hcore_guess ao_basis)
| `Huckel -> Huckel (huckel_guess simulation) | `Huckel -> Huckel (huckel_guess ao_basis nocc)

View File

@ -7,7 +7,7 @@ type guess =
type t = guess type t = guess
val make : guess:[ `Hcore | `Huckel ] -> Simulation.t -> t val make : ?nocc:int -> guess:[ `Hcore | `Huckel ] -> AOBasis.t -> t

View File

@ -1,37 +1,44 @@
open Util open Util
open Lacaml.D open Lacaml.D
open Simulation
module Si = Simulation
module El = Electrons
module Ao = AOBasis
let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=0.1) let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=0.1)
?threshold_SCF:(threshold_SCF=1.e-5) simulation = ?threshold_SCF:(threshold_SCF=1.e-5) simulation =
(* Number of occupied MOs *) (* Number of occupied MOs *)
let nocc = let nocc =
simulation.electrons.Electrons.n_alpha simulation.Si.electrons.El.n_alpha
in in
let nuclear_repulsion = let nuclear_repulsion =
simulation.nuclear_repulsion simulation.Si.nuclear_repulsion
in
let ao_basis =
simulation.Si.ao_basis
in in
(* Initial guess *) (* Initial guess *)
let guess = let guess =
Guess.make ~guess simulation Guess.make ~nocc ~guess ao_basis
in in
(* Orthogonalization matrix *) (* Orthogonalization matrix *)
let m_X = let m_X =
Lazy.force simulation.overlap_ortho Lazy.force ao_basis.Ao.ortho
in in
(* Overlap matrix *) (* Overlap matrix *)
let m_S = let m_S =
Lazy.force simulation.overlap Lazy.force ao_basis.Ao.overlap
in in
let m_T = Lazy.force simulation.kin_ints let m_T = Lazy.force ao_basis.Ao.kin_ints
and m_V = Lazy.force simulation.eN_ints and m_V = Lazy.force ao_basis.Ao.eN_ints
in in
(* Level shift in MO basis *) (* Level shift in MO basis *)
@ -53,7 +60,7 @@ let make ?guess:(guess=`Huckel) ?max_scf:(max_scf=64) ?level_shift:(level_shift=
(* Fock matrix in AO basis *) (* Fock matrix in AO basis *)
let m_F, m_Hc, m_J, m_K = let m_F, m_Hc, m_J, m_K =
let x = let x =
Fock.make ~density:m_P simulation Fock.make ~density:m_P ao_basis
in in
x.Fock.fock, x.Fock.core, x.Fock.coulomb, x.Fock.exchange x.Fock.fock, x.Fock.core, x.Fock.coulomb, x.Fock.exchange
in in

View File

@ -1,15 +1,10 @@
type t = { type t = {
charge : Charge.t; charge : Charge.t;
electrons : Electrons.t ; electrons : Electrons.t ;
basis : Basis.t; nuclei : Nuclei.t;
nuclei : Nuclei.t; basis : Basis.t;
overlap : Overlap.t lazy_t; ao_basis : AOBasis.t;
overlap_ortho : Orthonormalization.t lazy_t;
eN_ints : NucInt.t lazy_t;
kin_ints : KinInt.t lazy_t;
ee_ints : ERI.t lazy_t;
nuclear_repulsion : float; nuclear_repulsion : float;
cartesian : bool;
} }
let make ?cartesian:(cartesian=false) let make ?cartesian:(cartesian=false)
@ -26,21 +21,22 @@ let make ?cartesian:(cartesian=false)
let electrons = let electrons =
Electrons.make ~multiplicity ~charge nuclei Electrons.make ~multiplicity ~charge nuclei
in in
let charge = let charge =
Charge.(Nuclei.charge nuclei + Electrons.charge electrons) Charge.(Nuclei.charge nuclei + Electrons.charge electrons)
in in
let overlap =
lazy (Overlap.of_basis basis) let ao_basis =
AOBasis.make ~basis ~cartesian nuclei
in in
let nuclear_repulsion =
Nuclei.repulsion nuclei
in
{ {
charge ; charge ; basis ; nuclei ; electrons ; ao_basis ;
basis ; nuclei ; electrons ; overlap ; nuclear_repulsion ;
overlap_ortho = lazy (Orthonormalization.make ~cartesian ~basis (Lazy.force overlap));
eN_ints = lazy (NucInt.of_basis_nuclei basis nuclei);
kin_ints = lazy (KinInt.of_basis basis);
ee_ints = lazy (ERI.of_basis basis);
nuclear_repulsion = Nuclei.repulsion nuclei;
cartesian ;
} }

View File

@ -36,10 +36,11 @@ let run ~out =
print_float s.Simulation.nuclear_repulsion; print_newline (); print_float s.Simulation.nuclear_repulsion; print_newline ();
print_endline @@ Basis.to_string s.Simulation.basis; print_endline @@ Basis.to_string s.Simulation.basis;
let overlap = Lazy.force s.Simulation.overlap in let ao_basis = s.Simulation.ao_basis in
let eN_ints = Lazy.force s.Simulation.eN_ints in let overlap = Lazy.force ao_basis.AOBasis.overlap in
let kin_ints = Lazy.force s.Simulation.kin_ints in let eN_ints = Lazy.force ao_basis.AOBasis.eN_ints in
let ee_ints = Lazy.force s.Simulation.ee_ints in let kin_ints = Lazy.force ao_basis.AOBasis.kin_ints in
let ee_ints = Lazy.force ao_basis.AOBasis.ee_ints in
Overlap.to_file ~filename:(out_file^".overlap") overlap; Overlap.to_file ~filename:(out_file^".overlap") overlap;
NucInt.to_file ~filename:(out_file^".nuc") eN_ints; NucInt.to_file ~filename:(out_file^".nuc") eN_ints;
KinInt.to_file ~filename:(out_file^".kin") kin_ints; KinInt.to_file ~filename:(out_file^".kin") kin_ints;