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

163 lines
4.2 KiB
OCaml
Raw Normal View History

2018-01-17 18:19:38 +01:00
open Util
2018-02-02 01:25:10 +01:00
open Constants
2018-01-17 18:19:38 +01:00
2018-02-08 01:00:54 +01:00
exception Null_contribution
2018-02-09 19:41:22 +01:00
type t =
{
2018-03-20 15:16:24 +01:00
shell_a : ContractedShell.t;
shell_b : ContractedShell.t;
shell_pairs : PrimitiveShellPair.t array;
coefficients : float array;
exponents_inv : float array;
center_ab : Coordinate.t; (* A-B *)
norm_sq : float; (* |A-B|^2 *)
norm_scales : float array; (* norm_coef.(i) / norm_coef.(0) *)
totAngMom : AngularMomentum.t; (* Total angular Momentum *)
2018-02-09 19:41:22 +01:00
}
2018-01-17 18:19:38 +01:00
2018-03-15 15:25:49 +01:00
module Am = AngularMomentum
module Co = Coordinate
module Cs = ContractedShell
module Ps = PrimitiveShell
module Psp = PrimitiveShellPair
2018-02-23 15:49:27 +01:00
2018-02-07 17:07:05 +01:00
(** Creates an contracted shell pair : an array of pairs of primitive shells.
A contracted shell with N functions combined with a contracted
shell with M functions generates a NxM array of shell pairs.
*)
2018-03-20 15:16:24 +01:00
let make ?(cutoff=1.e-32) s_a s_b =
2018-03-15 15:25:49 +01:00
2018-03-20 14:11:31 +01:00
let make = Psp.create_make_of (Cs.primitives s_a).(0) (Cs.primitives s_b).(0) in
2018-03-15 15:25:49 +01:00
2018-02-09 19:41:22 +01:00
let shell_pairs =
2018-03-15 16:03:43 +01:00
Array.mapi (fun i p_a ->
2018-03-20 14:11:31 +01:00
let c_a = (Cs.coefficients s_a).(i) in
2018-03-15 19:11:59 +01:00
let make = make p_a in
2018-03-15 16:03:43 +01:00
Array.mapi (fun j p_b ->
2018-03-20 14:11:31 +01:00
let c_b = (Cs.coefficients s_b).(j) in
2018-03-15 16:03:43 +01:00
let coef = c_a *. c_b in
assert (coef <> 0.);
let cutoff = cutoff /. abs_float coef in
2018-03-20 14:11:31 +01:00
coef, make p_b cutoff) (Cs.primitives s_b)) (Cs.primitives s_a)
2018-02-09 19:41:22 +01:00
|> Array.to_list
|> Array.concat
|> Array.to_list
2018-03-15 16:03:43 +01:00
|> List.filter (function (_, Some _) -> true | _ -> false)
|> List.map (function (c, Some x) -> (c,x) | _ -> assert false)
2018-02-09 19:41:22 +01:00
|> Array.of_list
in
2018-03-15 16:03:43 +01:00
2018-03-20 15:16:24 +01:00
let coefficients = Array.map (fun (c,y) -> c *. Psp.normalization y) shell_pairs
and exponents_inv = Array.map (fun (_,y) -> Psp.exponent_inv y) shell_pairs
2018-02-09 19:41:22 +01:00
in
2018-03-15 15:25:49 +01:00
let shell_pairs = Array.map snd shell_pairs in
2018-03-15 19:35:10 +01:00
if Array.length shell_pairs = 0 then
None
else
let root = shell_pairs.(0) in
Some {
2018-03-20 15:16:24 +01:00
shell_a = s_a ; shell_b = s_b ; coefficients ; exponents_inv ; shell_pairs ;
2018-03-15 19:35:10 +01:00
center_ab = Psp.a_minus_b root;
2018-03-20 15:16:24 +01:00
norm_scales = Psp.norm_scales root;
2018-03-15 19:35:10 +01:00
norm_sq=Psp.a_minus_b_sq root;
2018-03-20 15:16:24 +01:00
totAngMom = Psp.totAngMom root;
2018-03-15 19:35:10 +01:00
}
2018-01-17 18:19:38 +01:00
2018-02-07 13:33:25 +01:00
2018-03-14 14:39:22 +01:00
let shell_a x = x.shell_a
let shell_b x = x.shell_b
let shell_pairs x = x.shell_pairs
2018-03-20 15:16:24 +01:00
let coefficients x = x.coefficients
let exponents_inv x = x.exponents_inv
2018-03-14 14:39:22 +01:00
let center_ab x = x.center_ab
let norm_sq x = x.norm_sq
2018-03-20 15:16:24 +01:00
let totAngMom x = x.totAngMom
let norm_scales x = x.norm_scales
2018-03-14 14:39:22 +01:00
2018-03-15 16:03:43 +01:00
let monocentric x = Psp.monocentric x.shell_pairs.(0)
2018-03-14 14:39:22 +01:00
2018-02-07 17:07:05 +01:00
(** Returns an integer characteristic of a contracted shell pair *)
2018-02-07 13:33:25 +01:00
let hash a =
2018-02-08 01:00:54 +01:00
Array.map Hashtbl.hash a
2018-02-07 13:33:25 +01:00
2018-02-07 17:07:05 +01:00
(** Comparison function, used for sorting *)
2018-02-07 13:33:25 +01:00
let cmp a b =
2018-02-08 01:00:54 +01:00
if a = b then 0
else if (Array.length a < Array.length b) then -1
else if (Array.length a > Array.length b) then 1
else
let out = ref 0 in
begin
try
for k=0 to (Array.length a - 1) do
if a.(k) < b.(k) then
(out := (-1); raise Not_found)
else if a.(k) > b.(k) then
(out := 1; raise Not_found);
done
with Not_found -> ();
end;
!out
(** The array of all shell pairs with their correspondance in the list
of contracted shells.
*)
2018-03-20 14:11:31 +01:00
let of_contracted_shell_array basis =
2018-02-08 01:00:54 +01:00
Array.mapi (fun i shell_a ->
Array.mapi (fun j shell_b ->
2018-03-20 15:16:24 +01:00
make shell_a shell_b)
2018-02-08 01:00:54 +01:00
(Array.sub basis 0 (i+1))
) basis
2018-02-07 13:33:25 +01:00
2018-02-08 01:00:54 +01:00
let equivalent x y =
(Array.length x = Array.length y) &&
2018-03-15 16:03:43 +01:00
let rec eqv = function
| 0 -> true
| k -> if Psp.equivalent x.(k) y.(k) then
eqv (k-1)
else false
in eqv (Array.length x - 1)
2018-02-07 17:07:05 +01:00
(** A list of unique shell pairs *)
2018-02-08 01:00:54 +01:00
let unique sp =
let sp =
Array.to_list sp
|> Array.concat
|> Array.to_list
in
let rec aux accu = function
| [] -> accu
| x::rest ->
try ignore @@ List.find (fun y -> equivalent x y) accu; aux accu rest
with Not_found -> aux (x::accu) rest
in
aux [] sp
2018-02-07 13:33:25 +01:00
2018-02-08 01:00:54 +01:00
(** A map from a shell pair hash to the list of indices in the array
of shell pairs.
*)
let indices sp =
2018-02-07 17:07:05 +01:00
let map =
2018-02-07 13:33:25 +01:00
Hashtbl.create 129
in
2018-02-07 17:07:05 +01:00
Array.iteri (fun i s ->
Array.iteri (fun j shell_p ->
let key =
hash shell_p
in
2018-02-08 01:00:54 +01:00
Hashtbl.add map key (i,j); ) s
) sp;
2018-02-07 13:33:25 +01:00
map
2018-02-07 17:07:05 +01:00
2018-01-22 23:19:24 +01:00