10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-06-20 04:02:07 +02:00
QCaml/Basis/ContractedShellPair.ml

135 lines
3.8 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-07 17:07:05 +01:00
type t = ShellPair.t array
2018-01-17 18:19:38 +01:00
exception Null_contribution
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.
*)
let create ?cutoff p_a p_b =
let cutoff, log_cutoff =
match cutoff with
| None -> -1., max_float
| Some cutoff -> cutoff, -. (log cutoff)
2018-01-17 18:19:38 +01:00
in
2018-01-18 00:21:05 +01:00
let center_ab = Coordinate.(
Contracted_shell.center p_a |- Contracted_shell.center p_b )
2018-01-17 18:19:38 +01:00
in
2018-01-17 19:09:57 +01:00
let norm_sq =
Coordinate.dot center_ab center_ab
in
2018-02-01 16:09:04 +01:00
let norm_coef_scale_a =
Contracted_shell.norm_coef_scale p_a
and norm_coef_scale_b =
Contracted_shell.norm_coef_scale p_b
in
2018-02-01 17:13:47 +01:00
let norm_coef_scale =
Array.map (fun v1 ->
Array.map (fun v2 -> v1 *. v2) norm_coef_scale_b
) norm_coef_scale_a
|> Array.to_list
|> Array.concat
2018-02-01 16:09:04 +01:00
in
2018-01-17 19:09:57 +01:00
Array.init (Contracted_shell.size p_a) (fun i ->
2018-01-18 00:21:05 +01:00
let p_a_expo_center = Coordinate.(
Contracted_shell.expo p_a i |. Contracted_shell.center p_a )
2018-01-17 19:09:57 +01:00
in
2018-02-01 16:09:04 +01:00
let norm_coef_a =
2018-01-17 19:09:57 +01:00
Contracted_shell.norm_coef p_a i
in
2018-01-17 18:19:38 +01:00
2018-01-17 19:09:57 +01:00
Array.init (Contracted_shell.size p_b) (fun j ->
try
2018-02-01 16:09:04 +01:00
let norm_coef_b =
2018-01-17 19:09:57 +01:00
Contracted_shell.norm_coef p_b j
in
2018-02-01 16:09:04 +01:00
let norm_coef =
norm_coef_a *. norm_coef_b
2018-01-17 19:09:57 +01:00
in
2018-02-01 16:09:04 +01:00
if (norm_coef < cutoff) then
2018-01-17 19:09:57 +01:00
raise Null_contribution;
2018-01-18 00:21:05 +01:00
let p_b_expo_center = Coordinate.(
Contracted_shell.expo p_b j |. Contracted_shell.center p_b )
2018-01-17 19:09:57 +01:00
in
let expo = Contracted_shell.(expo p_a i +. expo p_b j) in
let expo_inv = 1. /. expo in
2018-01-18 00:21:05 +01:00
let center = Coordinate.(
expo_inv |. (p_a_expo_center |+ p_b_expo_center ) )
2018-01-17 19:09:57 +01:00
in
let argexpo =
Contracted_shell.(expo p_a i *. expo p_b j) *. norm_sq *. expo_inv
in
if (argexpo > log_cutoff) then
raise Null_contribution;
let g =
(pi *. expo_inv)**(1.5) *. exp(-. argexpo)
in
let coef =
2018-02-01 16:09:04 +01:00
norm_coef *. Contracted_shell.(coef p_a i *. coef p_b j) *. g
2018-01-17 19:09:57 +01:00
in
if (abs_float coef < cutoff) then
raise Null_contribution;
2018-01-22 23:19:24 +01:00
let center_a =
Coordinate.(center |- Contracted_shell.center p_a)
in
2018-02-03 16:41:29 +01:00
let monocentric =
Contracted_shell.center p_a = Contracted_shell.center p_b
in
2018-02-07 17:07:05 +01:00
Some ShellPair.{ i ; j ; shell_a=p_a ; shell_b=p_b ; norm_coef ; coef ; expo ; expo_inv ; center ; center_a ; center_ab ; norm_sq ; norm_coef_scale ; monocentric }
2018-01-17 19:09:57 +01:00
with
| Null_contribution -> None
)
)
|> Array.to_list
|> Array.concat
|> Array.to_list
|> List.filter (function Some _ -> true | None -> false)
|> List.map (function Some x -> x | None -> assert false)
|> Array.of_list
2018-01-17 18:19:38 +01:00
2018-02-07 13:33:25 +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-07 17:07:05 +01:00
1 (*TODO*)
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 =
hash a - hash b
2018-02-07 17:07:05 +01:00
(** The array of all shell pairs *)
2018-02-07 13:33:25 +01:00
let shell_pairs basis =
Array.mapi (fun i shell_a -> Array.map (fun shell_b ->
2018-02-07 17:07:05 +01:00
create shell_a shell_b) (Array.sub basis 0 (i+1)) ) basis
(** A list of unique shell pairs *)
let unique_of_shell_pairs sp =
Array.to_list sp
|> Array.concat
|> Array.to_list
|> List.sort_uniq cmp
2018-02-07 13:33:25 +01:00
2018-02-07 17:07:05 +01:00
(** A map from a shell pair hash to the list of indices in the array of shell pairs. *)
let indices_of_shell_pairs sp =
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
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