10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-11-18 20:12:26 +01:00
QCaml/gaussian_integrals/lib/kinetic.ml

190 lines
5.5 KiB
OCaml
Raw Normal View History

2020-09-26 12:02:53 +02:00
open Qcaml_common
open Qcaml_linear_algebra
open Qcaml_gaussian_basis
open Util
open Constants
2018-02-23 15:49:27 +01:00
2020-09-26 12:02:53 +02:00
module Am = Angular_momentum
2018-02-23 15:49:27 +01:00
module Bs = Basis
module Co = Coordinate
2020-09-26 12:02:53 +02:00
module Cs = Contracted_shell
module Csp = Contracted_shell_pair
2018-02-25 01:40:12 +01:00
module Po = Powers
2020-09-26 12:02:53 +02:00
module Psp = Primitive_shell_pair
2020-09-27 23:55:42 +02:00
module Ps = Primitive_shell
2018-02-09 00:37:25 +01:00
2020-10-02 18:55:19 +02:00
type t = (Basis.t, Basis.t) Matrix.t
external matrix : t -> (Basis.t, Basis.t) Matrix.t = "%identity"
external of_matrix : (Basis.t, Basis.t) Matrix.t -> t = "%identity"
2018-02-09 00:37:25 +01:00
2018-02-24 23:57:38 +01:00
let cutoff = integrals_cutoff
2020-09-27 23:55:42 +02:00
let to_powers x =
2018-02-25 01:40:12 +01:00
let open Zkey in
match to_powers x with
| Six x -> x
| _ -> assert false
(** Computes all the kinetic integrals of the contracted shell pair *)
2020-09-27 23:55:42 +02:00
let contracted_class shell_a shell_b : float Zmap.t =
2018-03-20 15:16:24 +01:00
match Csp.make shell_a shell_b with
2020-09-27 23:55:42 +02:00
| None -> Zmap.create 0
2018-03-15 19:35:10 +01:00
| Some shell_p ->
begin
2020-09-27 23:55:42 +02:00
2018-03-15 19:35:10 +01:00
(* Pre-computation of integral class indices *)
2020-09-27 23:55:42 +02:00
let class_indices = Csp.zkey_array shell_p in
2020-09-27 23:55:42 +02:00
let contracted_class =
2018-03-15 19:35:10 +01:00
Array.make (Array.length class_indices) 0.
in
2020-09-27 23:55:42 +02:00
let a_minus_b =
2018-03-21 15:01:39 +01:00
Csp.a_minus_b shell_p
2018-03-15 19:35:10 +01:00
in
2018-03-20 15:16:24 +01:00
let norm_coef_scales =
Csp.norm_scales shell_p
2018-03-15 19:35:10 +01:00
in
2020-09-27 23:55:42 +02:00
(* Compute all integrals in the shell for each pair of significant shell pairs *)
let sp = Csp.shell_pairs shell_p in
2018-03-15 19:35:10 +01:00
for ab=0 to (Array.length sp - 1)
do
let coef_prod =
2020-09-27 23:55:42 +02:00
(Csp.coefficients shell_p).(ab)
2018-02-25 01:40:12 +01:00
in
2020-09-26 12:02:53 +02:00
(* Screening on thr product of coefficients *)
2018-03-15 19:35:10 +01:00
if (abs_float coef_prod) > 1.e-4*.cutoff then
begin
2020-09-27 23:55:42 +02:00
let center_pa =
2018-03-15 19:35:10 +01:00
Psp.center_minus_a sp.(ab)
in
2020-09-27 23:55:42 +02:00
let expo_inv =
2018-03-20 15:16:24 +01:00
(Csp.exponents_inv shell_p).(ab)
in
2020-09-27 23:55:42 +02:00
let expo_a =
2018-03-20 15:16:24 +01:00
Ps.exponent (Psp.shell_a sp.(ab))
2020-09-27 23:55:42 +02:00
and expo_b =
2018-03-20 15:16:24 +01:00
Ps.exponent (Psp.shell_b sp.(ab))
in
2018-03-15 19:35:10 +01:00
let xyz_of_int k =
match k with
| 0 -> Co.X
| 1 -> Co.Y
| _ -> Co.Z
in
Array.iteri (fun i key ->
let (angMomA,angMomB) = to_powers key in
2020-09-27 23:55:42 +02:00
let ov a b k =
2018-03-15 19:35:10 +01:00
let xyz = xyz_of_int k in
Overlap_primitives.hvrr (a, b)
expo_inv
2018-03-21 15:01:39 +01:00
(Co.get xyz a_minus_b,
2020-09-27 23:55:42 +02:00
Co.get xyz center_pa)
2018-03-15 19:35:10 +01:00
in
2020-09-27 23:55:42 +02:00
let f k =
let xyz = xyz_of_int k in
2018-03-15 19:35:10 +01:00
ov (Po.get xyz angMomA) (Po.get xyz angMomB) k
and g k =
2020-09-27 23:55:42 +02:00
let xyz = xyz_of_int k in
2018-03-15 19:35:10 +01:00
let s1 = ov (Po.get xyz angMomA - 1) (Po.get xyz angMomB - 1) k
and s2 = ov (Po.get xyz angMomA + 1) (Po.get xyz angMomB - 1) k
and s3 = ov (Po.get xyz angMomA - 1) (Po.get xyz angMomB + 1) k
and s4 = ov (Po.get xyz angMomA + 1) (Po.get xyz angMomB + 1) k
2020-02-17 19:45:53 +01:00
and a = float_of_int_fast (Po.get xyz angMomA)
2020-09-27 23:55:42 +02:00
and b = float_of_int_fast (Po.get xyz angMomB)
2018-03-15 19:35:10 +01:00
in
2020-09-27 23:55:42 +02:00
0.5 *. a *. b *. s1 -. expo_a *. b *. s2 -. expo_b *. a *. s3 +.
2018-03-15 19:35:10 +01:00
2.0 *. expo_a *. expo_b *. s4
in
let s = Array.init 3 f
and k = Array.init 3 g
in
2018-03-20 15:16:24 +01:00
let norm = norm_coef_scales.(i) in
2018-03-15 19:35:10 +01:00
let integral = chop norm (fun () ->
k.(0)*.s.(1)*.s.(2) +.
s.(0)*.k.(1)*.s.(2) +.
2020-09-27 23:55:42 +02:00
s.(0)*.s.(1)*.k.(2)
) in
2018-03-15 19:35:10 +01:00
contracted_class.(i) <- contracted_class.(i) +. coef_prod *. integral
) class_indices
end
done;
2020-09-27 23:55:42 +02:00
let result =
2018-03-15 19:35:10 +01:00
Zmap.create (Array.length contracted_class)
in
Array.iteri (fun i key -> Zmap.add result key contracted_class.(i)) class_indices;
result
end
2018-02-09 00:37:25 +01:00
(** Create kinetic energy matrix *)
let of_basis basis =
2018-02-19 16:01:13 +01:00
let to_powers x =
let open Zkey in
2018-02-25 01:40:12 +01:00
match to_powers x with
| Three x -> x
| _ -> assert false
in
2018-03-20 14:11:31 +01:00
let n = Bs.size basis
and shell = Bs.contracted_shells basis
2018-02-09 00:37:25 +01:00
in
2020-09-26 12:02:53 +02:00
let result = Matrix.create n n in
let result_x = Matrix.to_bigarray_inplace result in
2018-02-09 00:37:25 +01:00
for j=0 to (Array.length shell) - 1 do
for i=0 to j do
(* Compute all the integrals of the class *)
let cls =
2018-02-09 00:37:25 +01:00
contracted_class shell.(i) shell.(j)
in
2018-02-09 00:37:25 +01:00
Array.iteri (fun j_c powers_j ->
2018-03-13 18:56:28 +01:00
let j_c = Cs.index shell.(j) + j_c + 1 in
2018-02-19 16:01:13 +01:00
let xj = to_powers powers_j in
2018-02-09 00:37:25 +01:00
Array.iteri (fun i_c powers_i ->
2018-03-13 18:56:28 +01:00
let i_c = Cs.index shell.(i) + i_c + 1 in
2018-02-19 16:01:13 +01:00
let xi = to_powers powers_i in
2018-02-09 00:37:25 +01:00
let key =
2018-02-25 00:53:09 +01:00
Zkey.of_powers_six xi xj
in
2018-02-09 00:37:25 +01:00
let value =
try Zmap.find cls key
2018-03-15 19:35:10 +01:00
with Not_found -> 0.
in
2020-09-26 12:02:53 +02:00
result_x.{i_c,j_c} <- value;
result_x.{j_c,i_c} <- value;
2018-03-21 15:01:39 +01:00
) (Am.zkey_array (Singlet (Cs.ang_mom shell.(i))))
2020-09-27 23:55:42 +02:00
) (Am.zkey_array (Singlet (Cs.ang_mom shell.(j))))
2018-02-09 00:37:25 +01:00
done;
done;
2020-09-26 12:02:53 +02:00
Matrix.detri_inplace result;
2018-02-09 00:37:25 +01:00
result
2020-09-26 12:02:53 +02:00
let of_basis_pair _first_basis _second_basis =
failwith "Not implemented"
2018-02-09 00:37:25 +01:00
(** Write all kinetic integrals to a file *)
let to_file ~filename kinetic =
let oc = open_out filename in
let n =
2020-09-26 12:02:53 +02:00
Matrix.dim1 kinetic
2018-02-09 00:37:25 +01:00
in
2020-09-26 12:02:53 +02:00
let kinetic_x = Matrix.to_bigarray kinetic in
2018-02-09 00:37:25 +01:00
for j=1 to n do
for i=1 to j do
2020-09-26 12:02:53 +02:00
if (abs_float kinetic_x.{i,j} > cutoff) then
Printf.fprintf oc "%4d %4d %20.12e\n" i j kinetic_x.{i,j}
done;
done;
close_out oc
2018-02-09 00:37:25 +01:00