QCaml/Basis/Orthonormalization.ml

69 lines
1.8 KiB
OCaml
Raw Permalink Normal View History

2018-02-23 18:44:31 +01:00
open Util
open Lacaml.D
2018-05-30 09:19:49 +02:00
type t = Mat.t
2018-02-23 18:44:31 +01:00
2018-05-30 01:15:45 +02:00
module Am = AngularMomentum
module Bs = Basis
module Cs = ContractedShell
2018-06-13 19:03:42 +02:00
module Ov = Overlap
2018-05-30 01:15:45 +02:00
2018-02-23 18:44:31 +01:00
2018-05-30 09:19:49 +02:00
let make_canonical ~thresh ~basis ~cartesian ~overlap =
2018-06-13 19:03:42 +02:00
let overlap_matrix = Ov.matrix overlap in
2018-05-30 09:19:49 +02:00
let make_canonical_spherical basis =
let ao_num = Bs.size basis in
let cart_sphe = Mat.make ao_num ao_num 0.
and i = ref 0
and n = ref 0 in
Array.iter (fun shell ->
let submatrix =
SphericalToCartesian.matrix (Cs.ang_mom shell)
in
ignore @@ lacpy ~b:cart_sphe ~br:(!i+1) ~bc:(!n+1) submatrix;
i := !i + Mat.dim1 submatrix;
n := !n + Mat.dim2 submatrix;
) (Bs.contracted_shells basis);
2018-06-13 19:03:42 +02:00
let s = gemm ~transa:`T ~m:!n cart_sphe overlap_matrix in
let overlap_matrix = gemm s ~n:!n cart_sphe in
let s = canonical_ortho ~thresh ~overlap:overlap_matrix (Mat.identity !n) in
2018-05-30 09:19:49 +02:00
gemm cart_sphe ~k:!n s
in
2018-05-30 09:19:49 +02:00
if cartesian then
2018-06-13 19:03:42 +02:00
canonical_ortho ~thresh ~overlap:overlap_matrix (Mat.identity @@ Mat.dim1 overlap_matrix)
2018-05-30 09:19:49 +02:00
else
match basis with
| None -> invalid_arg
"Basis.t is required when cartesian=false in make_canonical"
| Some basis -> make_canonical_spherical basis
let make_lowdin ~thresh ~overlap =
2018-02-23 18:44:31 +01:00
2018-06-13 19:03:42 +02:00
let overlap_matrix = Ov.matrix overlap in
let u_vec, u_val = diagonalize_symm overlap_matrix in
2018-02-23 18:44:31 +01:00
Vec.iter (fun x -> if x < thresh then
2018-02-25 00:53:09 +01:00
invalid_arg (__FILE__^": make_lowdin") ) u_val;
2018-02-23 18:44:31 +01:00
let u_val = Vec.reci (Vec.sqrt u_val) in
let u_vec' =
Mat.init_cols (Mat.dim1 u_vec) (Mat.dim2 u_vec) (fun i j -> u_vec.{i,j} *. u_val.{j})
in
2018-05-30 09:19:49 +02:00
gemm u_vec' ~transb:`T u_vec
2018-02-23 18:44:31 +01:00
2018-05-30 09:19:49 +02:00
let make ?(thresh=1.e-12) ?basis ~cartesian overlap =
(*
make_lowdin ~thresh ~overlap
*)
2018-05-30 09:19:49 +02:00
make_canonical ~thresh ~basis ~cartesian ~overlap
2018-06-13 19:03:42 +02:00