10
1
mirror of https://gitlab.com/scemama/QCaml.git synced 2024-06-02 11:25:19 +02:00
QCaml/Nuclei/Nuclei.ml

126 lines
3.3 KiB
OCaml
Raw Normal View History

2018-02-20 23:54:48 +01:00
open Util
2018-02-13 17:36:25 +01:00
open Xyz_ast
2018-01-19 03:14:06 +01:00
type t = (Element.t * Coordinate.t) array
2018-01-17 15:56:57 +01:00
2018-03-03 22:13:14 +01:00
let of_xyz_file filename =
2018-01-17 15:56:57 +01:00
let lexbuf =
let ic = open_in filename in
Lexing.from_channel ic
in
2018-02-13 17:36:25 +01:00
let data =
Xyz_parser.input Nuclei_lexer.read_all lexbuf
in
let len = List.length data.nuclei in
if len <> data.number_of_atoms then
Printf.sprintf "Error: expected %d atoms but %d read"
data.number_of_atoms len
|> failwith;
List.map (fun nucleus ->
nucleus.element, Coordinate.angstrom_to_bohr nucleus.coord
) data.nuclei
|> Array.of_list
2018-01-17 15:56:57 +01:00
2018-06-29 16:04:40 +02:00
let of_zmt_string buffer =
Zmatrix.of_string buffer
|> Zmatrix.to_xyz
|> Array.map (fun (e,x,y,z) -> (e, Coordinate.angstrom_to_bohr (Angstrom.make {Point.x ; y ; z} )))
2018-03-03 22:13:14 +01:00
let of_zmt_file filename =
2018-01-17 15:56:57 +01:00
let ic = open_in filename in
let rec aux accu =
try
let line = input_line ic in
aux (line::accu)
with End_of_file ->
close_in ic;
List.rev accu
|> String.concat "\n"
in aux []
2018-06-29 16:04:40 +02:00
|> of_zmt_string
2018-01-17 15:56:57 +01:00
2018-02-09 00:37:25 +01:00
2018-01-18 17:39:10 +01:00
let to_string atoms =
"
Nuclear Coordinates (Angstrom)
------------------------------
-----------------------------------------------------------------------
Center Atomic Element Coordinates (Angstroms)
Number X Y Z
-----------------------------------------------------------------------
" ^
(Array.mapi (fun i (e, coord) ->
let coord =
2018-02-13 17:36:25 +01:00
Coordinate.bohr_to_angstrom coord
2018-01-18 17:39:10 +01:00
in
Printf.sprintf " %5d %5d %5s %12.6f %12.6f %12.6f"
(i+1) (Element.to_int e) (Element.to_string e)
2018-02-13 17:36:25 +01:00
coord.Angstrom.x coord.Angstrom.y coord.Angstrom.z
2018-01-18 17:39:10 +01:00
) atoms
|> Array.to_list
|> String.concat "\n" ) ^
"
-----------------------------------------------------------------------
"
2018-03-03 22:13:14 +01:00
let of_filename filename =
2018-02-09 00:37:25 +01:00
of_xyz_file filename
2018-01-22 23:19:24 +01:00
2018-03-03 22:13:14 +01:00
let repulsion nuclei =
2018-02-20 23:54:48 +01:00
let get_charge e =
Element.to_charge e
|> Charge.to_float
in
Array.fold_left ( fun accu (e1, coord1) ->
accu +.
Array.fold_left (fun accu (e2, coord2) ->
let r = Coordinate.(norm (coord1 |- coord2)) in
if r > 0. then
accu +. 0.5 *. (get_charge e2) *. (get_charge e1) /. r
else accu
) 0. nuclei
) 0. nuclei
2018-03-03 22:13:14 +01:00
let charge nuclei =
Array.fold_left (fun accu (e, _) -> accu + Charge.to_int (Element.to_charge e) )
0 nuclei
|> Charge.of_int
2018-06-29 16:04:40 +02:00
let to_xyz_string t =
[ string_of_int (Array.length t) ; "" ] @
( Array.mapi (fun i (e, coord) ->
let coord =
Coordinate.bohr_to_angstrom coord
in
Printf.sprintf " %5s %12.6f %12.6f %12.6f"
(Element.to_string e) coord.Angstrom.x coord.Angstrom.y coord.Angstrom.z
) t
|> Array.to_list )
|> String.concat "\n"
let to_t2_string t =
[ "# nAt nEl nCore nRyd" ;
Printf.sprintf " %d %d %d 0" (Array.length t)
(Array.fold_left (+) 0 (Array.map (fun (e,_) -> Element.to_int e) t) )
(2 * Array.length t);
"# Znuc x y z" ]
@ (Array.mapi (fun i (e, coord) ->
Printf.sprintf " %5f %12.6f %12.6f %12.6f"
(Element.to_int e |> float_of_int) coord.Bohr.x coord.Bohr.y coord.Bohr.z
) t
|> Array.to_list )
|> String.concat "\n"