2018-02-23 18:44:31 +01:00
|
|
|
|
|
|
|
|
2020-12-26 01:47:55 +01:00
|
|
|
(* An exception is raised when the ~Angular_momentum.t~ element can't
|
|
|
|
* be created.
|
|
|
|
*
|
|
|
|
* The ~kind~ is used to build shells, shell doublets, triplets or
|
|
|
|
* quartets, use in the two-electron operators. *)
|
|
|
|
|
|
|
|
|
2020-12-28 01:55:03 +01:00
|
|
|
(* [[file:~/QCaml/common/angular_momentum.org::*Type][Type:2]] *)
|
2018-03-15 15:25:49 +01:00
|
|
|
type t =
|
2020-12-26 01:47:55 +01:00
|
|
|
| S | P | D | F | G | H | I | J | K | L | M | N | O
|
|
|
|
| Int of int
|
|
|
|
|
|
|
|
exception Angular_momentum_error of string
|
2018-02-23 18:44:31 +01:00
|
|
|
|
2020-12-26 01:47:55 +01:00
|
|
|
type kind =
|
|
|
|
Singlet of t
|
|
|
|
| Doublet of (t * t)
|
|
|
|
| Triplet of (t * t * t)
|
|
|
|
| Quartet of (t * t * t * t)
|
|
|
|
|
|
|
|
open Powers
|
|
|
|
(* Type:2 ends here *)
|
|
|
|
|
2020-12-27 17:38:04 +01:00
|
|
|
|
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
(* | ~of_char~ | Returns an ~Angular_momentum.t~ when a shell is given as a character (case insensitive) |
|
|
|
|
* | ~to_char~ | Converts the angular momentum into a char |
|
|
|
|
* | ~of_int~ | Returns a shell given an $l$ value. |
|
|
|
|
* | ~to_int~ | Returns the $l_{max}$ value of the shell |
|
|
|
|
* | ~to_string~ | Converts the angular momentum into a string |
|
2020-12-27 17:38:04 +01:00
|
|
|
*
|
2020-12-27 23:08:12 +01:00
|
|
|
* #+begin_example
|
|
|
|
* Angular_momentum.of_char 'p';;
|
2020-12-29 01:08:37 +01:00
|
|
|
* - : Angular_momentum.t = P
|
2020-12-27 23:08:12 +01:00
|
|
|
*
|
|
|
|
* Angular_momentum.(to_char P);;
|
|
|
|
* - : char = 'P'
|
|
|
|
*
|
|
|
|
* Angular_momentum.of_int 2;;
|
2020-12-29 01:08:37 +01:00
|
|
|
* - : Angular_momentum.t = D
|
2020-12-27 23:08:12 +01:00
|
|
|
*
|
|
|
|
* Angular_momentum.(to_int D);;
|
|
|
|
* - : int = 2
|
|
|
|
*
|
|
|
|
* Angular_momentum.(to_string D);;
|
|
|
|
* - : string = "D"
|
|
|
|
* #+end_example *)
|
2020-12-27 17:38:04 +01:00
|
|
|
|
|
|
|
|
2020-12-28 01:55:03 +01:00
|
|
|
(* [[file:~/QCaml/common/angular_momentum.org::*Conversions][Conversions:2]] *)
|
2018-02-23 18:44:31 +01:00
|
|
|
let of_char = function
|
|
|
|
| 's' | 'S' -> S | 'p' | 'P' -> P
|
|
|
|
| 'd' | 'D' -> D | 'f' | 'F' -> F
|
|
|
|
| 'g' | 'G' -> G | 'h' | 'H' -> H
|
|
|
|
| 'i' | 'I' -> I | 'j' | 'J' -> J
|
|
|
|
| 'k' | 'K' -> K | 'l' | 'L' -> L
|
|
|
|
| 'm' | 'M' -> M | 'n' | 'N' -> N
|
|
|
|
| 'o' | 'O' -> O
|
2020-09-26 12:02:53 +02:00
|
|
|
| c -> raise (Angular_momentum_error (String.make 1 c))
|
2020-12-27 17:38:04 +01:00
|
|
|
|
2018-02-23 18:44:31 +01:00
|
|
|
let to_string = function
|
|
|
|
| S -> "S" | P -> "P"
|
|
|
|
| D -> "D" | F -> "F"
|
|
|
|
| G -> "G" | H -> "H"
|
|
|
|
| I -> "I" | J -> "J"
|
|
|
|
| K -> "K" | L -> "L"
|
|
|
|
| M -> "M" | N -> "N"
|
2018-03-15 15:25:49 +01:00
|
|
|
| O -> "O" | Int i -> string_of_int i
|
2020-12-27 17:38:04 +01:00
|
|
|
|
|
|
|
|
2018-02-23 18:44:31 +01:00
|
|
|
let to_char = function
|
|
|
|
| S -> 'S' | P -> 'P'
|
|
|
|
| D -> 'D' | F -> 'F'
|
|
|
|
| G -> 'G' | H -> 'H'
|
|
|
|
| I -> 'I' | J -> 'J'
|
|
|
|
| K -> 'K' | L -> 'L'
|
|
|
|
| M -> 'M' | N -> 'N'
|
2020-09-26 12:02:53 +02:00
|
|
|
| O -> 'O' | Int _ -> '_'
|
2020-12-27 17:38:04 +01:00
|
|
|
|
|
|
|
|
2018-02-23 18:44:31 +01:00
|
|
|
let to_int = function
|
|
|
|
| S -> 0 | P -> 1
|
|
|
|
| D -> 2 | F -> 3
|
|
|
|
| G -> 4 | H -> 5
|
|
|
|
| I -> 6 | J -> 7
|
|
|
|
| K -> 8 | L -> 9
|
|
|
|
| M -> 10 | N -> 11
|
2018-03-15 15:25:49 +01:00
|
|
|
| O -> 12 | Int i -> i
|
2020-12-27 17:38:04 +01:00
|
|
|
|
|
|
|
|
2018-02-23 18:44:31 +01:00
|
|
|
let of_int = function
|
|
|
|
| 0 -> S | 1 -> P
|
|
|
|
| 2 -> D | 3 -> F
|
|
|
|
| 4 -> G | 5 -> H
|
|
|
|
| 6 -> I | 7 -> J
|
|
|
|
| 8 -> K | 9 -> L
|
|
|
|
| 10 -> M | 11 -> N
|
2018-03-15 15:25:49 +01:00
|
|
|
| 12 -> O | i -> Int i
|
2020-12-27 23:08:12 +01:00
|
|
|
(* Conversions:2 ends here *)
|
2018-02-23 18:44:31 +01:00
|
|
|
|
2020-12-27 17:38:04 +01:00
|
|
|
|
|
|
|
|
2020-12-27 23:08:12 +01:00
|
|
|
(* | ~n_functions~ | Returns the number of cartesian functions in a shell. |
|
|
|
|
* | ~zkey_array~ | Array of ~Zkey.t~, where each element is a a key associated with the the powers of $x,y,z$. |
|
|
|
|
*
|
|
|
|
* #+begin_example
|
|
|
|
* Angular_momentum.(n_functions D) ;;
|
|
|
|
* - : int = 6
|
2020-12-27 17:38:04 +01:00
|
|
|
*
|
2020-12-27 23:08:12 +01:00
|
|
|
* Angular_momentum.( zkey_array (Doublet (P,S)) );;
|
2020-12-29 01:08:37 +01:00
|
|
|
* - : Zkey.t array =
|
|
|
|
* [|< 01125899906842624 | 1, 0, 0, 0, 0, 0 >;
|
|
|
|
* < 01099511627776 | 0, 1, 0, 0, 0, 0 >;
|
|
|
|
* < 01073741824 | 0, 0, 1, 0, 0, 0 >|]
|
2020-12-27 23:08:12 +01:00
|
|
|
* #+end_example *)
|
2020-12-27 17:38:04 +01:00
|
|
|
|
|
|
|
|
2020-12-28 01:55:03 +01:00
|
|
|
(* [[file:~/QCaml/common/angular_momentum.org::*Shell functions][Shell functions:2]] *)
|
2018-02-23 18:44:31 +01:00
|
|
|
let n_functions a =
|
2020-12-26 01:47:55 +01:00
|
|
|
let a =
|
2018-02-23 18:44:31 +01:00
|
|
|
to_int a
|
|
|
|
in
|
|
|
|
(a*a + 3*a + 2)/2
|
2020-12-27 17:38:04 +01:00
|
|
|
|
|
|
|
|
2018-03-13 18:24:00 +01:00
|
|
|
let zkey_array_memo : (kind, Zkey.t array) Hashtbl.t =
|
2020-12-26 01:47:55 +01:00
|
|
|
Hashtbl.create 13
|
2018-03-13 18:24:00 +01:00
|
|
|
|
2020-12-26 01:47:55 +01:00
|
|
|
let zkey_array a =
|
2018-03-13 18:24:00 +01:00
|
|
|
|
2018-02-23 18:44:31 +01:00
|
|
|
let keys_1d l =
|
|
|
|
let create_z { x ; y ; _ } =
|
|
|
|
Powers.of_int_tuple (x,y,l-(x+y))
|
|
|
|
in
|
|
|
|
let rec create_y accu xyz =
|
2020-09-26 12:02:53 +02:00
|
|
|
let { x ; y ; z ;_ } = xyz in
|
2018-02-23 18:44:31 +01:00
|
|
|
match y with
|
|
|
|
| 0 -> (create_z xyz)::accu
|
2020-09-26 12:02:53 +02:00
|
|
|
| _ -> let ynew = y-1 in
|
2020-12-26 01:47:55 +01:00
|
|
|
(create_y [@tailcall]) ( (create_z xyz)::accu) (Powers.of_int_tuple (x,ynew,z))
|
2018-02-23 18:44:31 +01:00
|
|
|
in
|
|
|
|
let rec create_x accu xyz =
|
2020-09-26 12:02:53 +02:00
|
|
|
let { x ; z ;_ } = xyz in
|
2018-02-23 18:44:31 +01:00
|
|
|
match x with
|
|
|
|
| 0 -> (create_y [] xyz)@accu
|
2020-09-26 12:02:53 +02:00
|
|
|
| _ -> let xnew = x-1 in
|
2020-12-26 01:47:55 +01:00
|
|
|
let ynew = l-xnew in
|
|
|
|
(create_x [@tailcall]) ((create_y [] xyz)@accu) (Powers.of_int_tuple (xnew, ynew, z))
|
2018-02-23 18:44:31 +01:00
|
|
|
in
|
|
|
|
create_x [] (Powers.of_int_tuple (l,0,0))
|
|
|
|
|> List.rev
|
|
|
|
in
|
|
|
|
|
2018-03-13 18:24:00 +01:00
|
|
|
try
|
|
|
|
Hashtbl.find zkey_array_memo a
|
2018-02-23 18:44:31 +01:00
|
|
|
|
2018-03-13 18:24:00 +01:00
|
|
|
with Not_found ->
|
2018-02-23 18:44:31 +01:00
|
|
|
|
2020-12-26 01:47:55 +01:00
|
|
|
let result =
|
2018-03-13 18:24:00 +01:00
|
|
|
begin
|
|
|
|
match a with
|
2020-12-26 01:47:55 +01:00
|
|
|
| Singlet l1 ->
|
|
|
|
List.rev_map (fun x -> Zkey.of_powers_three x) (keys_1d @@ to_int l1)
|
2018-02-23 18:44:31 +01:00
|
|
|
|
2020-12-26 01:47:55 +01:00
|
|
|
| Doublet (l1, l2) ->
|
|
|
|
List.rev_map (fun a ->
|
2020-03-26 17:43:11 +01:00
|
|
|
List.rev_map (fun b -> Zkey.of_powers_six a b) (keys_1d @@ to_int l2)
|
2018-03-13 18:24:00 +01:00
|
|
|
) (keys_1d @@ to_int l1)
|
2020-12-26 01:47:55 +01:00
|
|
|
|> List.concat
|
2018-02-23 18:44:31 +01:00
|
|
|
|
2018-03-13 18:24:00 +01:00
|
|
|
| Triplet (l1, l2, l3) ->
|
2018-02-23 18:44:31 +01:00
|
|
|
|
2020-12-26 01:47:55 +01:00
|
|
|
List.rev_map (fun a ->
|
2020-03-26 17:43:11 +01:00
|
|
|
List.rev_map (fun b ->
|
2020-12-26 01:47:55 +01:00
|
|
|
List.rev_map (fun c ->
|
|
|
|
Zkey.of_powers_nine a b c) (keys_1d @@ to_int l3)
|
|
|
|
) (keys_1d @@ to_int l2)
|
2018-02-23 18:44:31 +01:00
|
|
|
|> List.concat
|
2018-03-13 18:24:00 +01:00
|
|
|
) (keys_1d @@ to_int l1)
|
2020-12-26 01:47:55 +01:00
|
|
|
|> List.concat
|
2018-03-13 18:24:00 +01:00
|
|
|
|
|
|
|
| Quartet (l1, l2, l3, l4) ->
|
|
|
|
|
2020-12-26 01:47:55 +01:00
|
|
|
List.rev_map (fun a ->
|
2020-03-26 17:43:11 +01:00
|
|
|
List.rev_map (fun b ->
|
2020-12-26 01:47:55 +01:00
|
|
|
List.rev_map (fun c ->
|
|
|
|
List.rev_map (fun d ->
|
|
|
|
Zkey.of_powers_twelve a b c d) (keys_1d @@ to_int l4)
|
|
|
|
) (keys_1d @@ to_int l3)
|
|
|
|
|> List.concat
|
|
|
|
) (keys_1d @@ to_int l2)
|
2018-03-13 18:24:00 +01:00
|
|
|
|> List.concat
|
|
|
|
) (keys_1d @@ to_int l1)
|
2020-12-26 01:47:55 +01:00
|
|
|
|> List.concat
|
2018-03-13 18:24:00 +01:00
|
|
|
end
|
2020-03-26 17:43:11 +01:00
|
|
|
|> List.rev
|
2018-03-13 18:24:00 +01:00
|
|
|
|> Array.of_list
|
|
|
|
in
|
|
|
|
Hashtbl.add zkey_array_memo a result;
|
|
|
|
result
|
2020-12-27 23:08:12 +01:00
|
|
|
(* Shell functions:2 ends here *)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(* #+begin_example
|
|
|
|
* Angular_momentum.(D + P);;
|
2020-12-29 01:08:37 +01:00
|
|
|
* - : Angular_momentum.t = F
|
2020-12-27 23:08:12 +01:00
|
|
|
*
|
|
|
|
* Angular_momentum.(F - P);;
|
2020-12-29 01:08:37 +01:00
|
|
|
* - : Angular_momentum.t = D
|
2020-12-27 23:08:12 +01:00
|
|
|
* #+end_example *)
|
|
|
|
|
2018-02-23 18:44:31 +01:00
|
|
|
|
2020-12-28 01:55:03 +01:00
|
|
|
(* [[file:~/QCaml/common/angular_momentum.org::*Arithmetic][Arithmetic:2]] *)
|
2018-03-14 21:58:55 +01:00
|
|
|
let ( + ) a b =
|
|
|
|
of_int ( (to_int a) + (to_int b) )
|
|
|
|
|
|
|
|
let ( - ) a b =
|
|
|
|
of_int ( (to_int a) - (to_int b) )
|
2020-12-26 01:47:55 +01:00
|
|
|
(* Arithmetic:2 ends here *)
|
2018-03-14 21:58:55 +01:00
|
|
|
|
2020-12-28 01:55:03 +01:00
|
|
|
(* [[file:~/QCaml/common/angular_momentum.org::*Printers][Printers:2]] *)
|
2018-03-15 15:25:49 +01:00
|
|
|
let pp_string ppf x =
|
|
|
|
Format.fprintf ppf "@[%s@]" (to_string x)
|
|
|
|
|
|
|
|
let pp_int ppf x =
|
|
|
|
Format.fprintf ppf "@[%d@]" (to_int x)
|
2020-12-27 23:08:12 +01:00
|
|
|
|
|
|
|
let pp = pp_string
|
2020-12-26 01:47:55 +01:00
|
|
|
(* Printers:2 ends here *)
|