10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-12-22 20:33:36 +01:00
QCaml/gaussian/lib/general_basis.ml

180 lines
4.6 KiB
OCaml
Raw Permalink Normal View History

2018-02-23 18:44:31 +01:00
(** General basis set read from a file *)
2018-03-08 23:29:08 +01:00
2020-10-09 09:47:57 +02:00
open Common
open Particles
2023-04-24 13:05:01 +02:00
2018-03-08 23:29:08 +01:00
type primitive =
{
exponent : float ;
coefficient: float ;
}
2018-02-23 18:44:31 +01:00
2020-09-26 12:02:53 +02:00
type general_contracted_shell = Angular_momentum.t * (primitive array)
2018-02-23 18:44:31 +01:00
2018-03-08 23:29:08 +01:00
type element_basis = Element.t * (general_contracted_shell array)
type t = element_basis list
exception No_shell
exception Malformed_shell of string
2022-11-07 11:24:20 +01:00
let read_shell ?element line_stream =
2018-03-08 23:29:08 +01:00
try
let shell, n =
try
2020-04-16 19:49:23 +02:00
let line = Stream.next line_stream in
2020-02-05 12:15:47 +01:00
if String.trim line = "$END" then raise End_of_file;
2020-02-06 11:10:18 +01:00
Scanf.sscanf line " %c %d " (fun shell n -> shell, n)
2018-03-08 23:29:08 +01:00
with
| End_of_file -> raise No_shell
2020-04-16 19:49:23 +02:00
| Stream.Failure -> raise No_shell
2018-03-08 23:29:08 +01:00
| Scanf.Scan_failure m -> raise (Malformed_shell m)
in
let rec loop = function
| 0 -> []
2023-04-24 13:05:01 +02:00
| i -> let contraction =
2020-04-16 19:49:23 +02:00
let line = Stream.next line_stream in
2020-02-06 11:10:18 +01:00
try Scanf.sscanf line " %_d %f %f "
2018-03-08 23:29:08 +01:00
(fun exponent coefficient -> { exponent ; coefficient })
2023-04-24 13:05:01 +02:00
with _ -> raise (Malformed_shell
2022-11-07 11:24:20 +01:00
(match element with
| Some element -> Printf.sprintf
"In %s: Expected %d %c contractions.\nError at contraction %d:\n%s"
(Element.to_string element) n shell (n-i+1) line
| None -> Printf.sprintf
"Expected %d %c contractions.\nError at contraction %d:\n%s"
n shell (n-i+1) line
))
2018-03-08 23:29:08 +01:00
in
contraction :: loop (pred i)
in
2020-09-26 12:02:53 +02:00
Some (Angular_momentum.of_char shell, Array.of_list (loop n))
2018-03-08 23:29:08 +01:00
with
| No_shell -> None
2018-02-23 18:44:31 +01:00
2018-03-08 23:29:08 +01:00
2022-11-07 11:24:20 +01:00
let rec read_element line_stream =
2018-03-08 23:29:08 +01:00
try
2020-04-16 19:49:23 +02:00
let line = Stream.next line_stream in
2022-11-07 11:24:20 +01:00
if String.length line = 0 || line.[0] = '!' then
read_element line_stream
else
let element =
try
Scanf.sscanf line " %s " Element.of_string
with
| Element.ElementError _ -> Element.X
in
let rec loop () =
match read_shell line_stream ~element with
| Some shell -> shell :: loop ()
| None -> []
in
Some (element, Array.of_list (loop ()) )
2018-03-08 23:29:08 +01:00
with
2020-04-16 19:49:23 +02:00
| Stream.Failure -> None
2018-03-08 23:29:08 +01:00
2023-04-24 13:05:01 +02:00
let read_stream line_stream =
2020-02-05 12:15:47 +01:00
let rec loop accu =
try
2020-04-16 19:49:23 +02:00
match read_element line_stream with
2020-02-05 12:15:47 +01:00
| Some e -> loop (e :: accu)
| None -> accu
with
Element.ElementError _ -> loop accu
2018-03-08 23:29:08 +01:00
in
2023-04-24 13:05:01 +02:00
loop []
2020-04-16 19:49:23 +02:00
let read filename =
let ic = open_in filename in
let line_stream =
2023-04-24 13:05:01 +02:00
Stream.from (fun _ ->
2020-04-16 19:49:23 +02:00
try Some (input_line ic)
with End_of_file -> None )
in
let result = read_stream line_stream in
close_in ic;
result
2018-03-08 23:29:08 +01:00
2019-03-21 00:44:10 +01:00
let combine basis_list =
let h = Hashtbl.create 63 in
2019-03-21 00:44:10 +01:00
List.concat basis_list
|> List.iter (fun (k,v) ->
let l = Hashtbl.find_all h k in
2019-11-20 16:42:28 +01:00
Hashtbl.replace h k (Array.concat (l@[v]) )
2019-03-21 00:44:10 +01:00
) ;
Hashtbl.fold (fun k v accu -> (k, v)::accu) h []
2019-03-21 00:44:10 +01:00
let read_many filenames =
List.map read filenames
|> combine
2023-04-24 13:05:01 +02:00
2018-02-23 18:44:31 +01:00
let string_of_primitive ?id prim =
match id with
| None -> (string_of_float prim.exponent)^" "^(string_of_float prim.coefficient)
| Some i -> (string_of_int i)^" "^(string_of_float prim.exponent)^" "^(string_of_float prim.coefficient)
let string_of_contracted_shell (angular_momentum, prim_array) =
2023-04-24 13:05:01 +02:00
let n =
2018-02-23 18:44:31 +01:00
Array.length prim_array
in
Printf.sprintf "%s %d\n%s"
2020-09-26 12:02:53 +02:00
(Angular_momentum.to_string angular_momentum) n
2018-02-23 18:44:31 +01:00
(Array.init n (fun i -> string_of_primitive ~id:(i+1) prim_array.(i))
|> Array.to_list
|> String.concat "\n")
let string_of_contracted_shell_array a =
Array.map string_of_contracted_shell a
|> Array.to_list
|> String.concat "\n"
let to_string (name, contracted_shell_array) =
Printf.sprintf "%s\n%s" name (string_of_contracted_shell_array contracted_shell_array)
2023-04-24 13:05:01 +02:00
let of_string input_string =
2020-04-16 19:49:23 +02:00
String.split_on_char '\n' input_string
|> Stream.of_list
|> read_stream
2020-10-08 11:42:33 +02:00
let pp_primitive ppf prim =
Format.fprintf ppf "@[%17.10e %17.10e@]" prim.exponent prim.coefficient
2023-04-24 13:05:01 +02:00
2020-10-08 11:42:33 +02:00
let pp_gcs ppf gcs =
let (angular_momentum, prim_array) = gcs in
Format.fprintf ppf "@[%a %d@]@."
Angular_momentum.pp_string angular_momentum
(Array.length prim_array);
Array.iteri (fun i prim -> Format.fprintf ppf "@[%3d %a@]@."
(i+1) pp_primitive prim) prim_array
2023-04-24 13:05:01 +02:00
2020-10-08 11:42:33 +02:00
let pp_element_basis ppf eb =
let (element, basis) = eb in
Format.fprintf ppf "@[%s@]@." (String.uppercase_ascii @@ Element.to_long_string element);
Array.iter (fun b -> Format.fprintf ppf "@[%a@]" pp_gcs b) basis
let pp ppf t =
List.iter (fun x -> Format.fprintf ppf "@[%a@]@." pp_element_basis x) t