mirror of
https://github.com/QuantumPackage/qp2.git
synced 2024-12-24 13:23:39 +01:00
380 lines
9.2 KiB
OCaml
380 lines
9.2 KiB
OCaml
(*
|
|
vim::syntax=ocaml
|
|
*)
|
|
|
|
open Qputils
|
|
open Qptypes
|
|
open Sexplib.Std
|
|
|
|
(** Interactive editing of the input.
|
|
|
|
WARNING
|
|
This file is automatically generated by
|
|
`${{QP_ROOT}}/scripts/ezfio_interface/ei_handler.py`
|
|
*)
|
|
|
|
|
|
(** Keywords used to define input sections *)
|
|
type keyword =
|
|
| Ao_basis
|
|
| Determinants_by_hand
|
|
| Electrons
|
|
| Mo_basis
|
|
| Nuclei_by_hand
|
|
{keywords}
|
|
|
|
|
|
|
|
let keyword_to_string = function
|
|
| Ao_basis -> "AO basis"
|
|
| Determinants_by_hand -> "Determinants_by_hand"
|
|
| Electrons -> "Electrons"
|
|
| Mo_basis -> "MO basis"
|
|
| Nuclei_by_hand -> "Molecule"
|
|
{keywords_to_string}
|
|
|
|
|
|
|
|
|
|
(** Create the header of the temporary file *)
|
|
let file_header filename =
|
|
Printf.sprintf "
|
|
==================================================================
|
|
Quantum Package
|
|
==================================================================
|
|
|
|
Editing file `%s`
|
|
|
|
" filename
|
|
|
|
|
|
|
|
(** Creates the header of a section *)
|
|
let make_header kw =
|
|
let s = keyword_to_string kw in
|
|
let l = String.length s in
|
|
"\n\n"^s^"\n"^(String.init l (fun _ -> '='))^"\n\n"
|
|
|
|
|
|
|
|
(** Returns the rst string of section [s] *)
|
|
let get s =
|
|
let header = (make_header s) in
|
|
let f (read,to_rst) =
|
|
match read () with
|
|
| Some text -> header ^ (Rst_string.to_string (to_rst text))
|
|
| None -> ""
|
|
in
|
|
let rst =
|
|
try
|
|
begin
|
|
let open Input in
|
|
match s with
|
|
| Mo_basis ->
|
|
f Mo_basis.(read, to_rst)
|
|
| Electrons ->
|
|
f Electrons.(read, to_rst)
|
|
| Nuclei_by_hand ->
|
|
f Nuclei_by_hand.(read, to_rst)
|
|
| Ao_basis ->
|
|
f Ao_basis.(read, to_rst)
|
|
| Determinants_by_hand ->
|
|
f Determinants_by_hand.(read ~full:false, to_rst)
|
|
{section_to_rst}
|
|
end
|
|
with
|
|
| Sys_error msg -> (Printf.eprintf "Info: %s\n%!" msg ; "")
|
|
in
|
|
rst
|
|
|
|
|
|
|
|
(** Applies the changes from the string [str] corresponding to section [s] *)
|
|
let set str s =
|
|
let header = (make_header s) in
|
|
match String_ext.substr_index ~pos:0 ~pattern:header str with
|
|
| None -> ()
|
|
| Some idx ->
|
|
begin
|
|
let index_begin = idx + (String.length header) in
|
|
let index_end =
|
|
match ( String_ext.substr_index ~pos:(index_begin+(String.length header)+1)
|
|
~pattern:"==" str) with
|
|
| Some i -> i
|
|
| None -> String.length str
|
|
in
|
|
let l = index_end - index_begin in
|
|
let str = String.sub str index_begin l
|
|
|> Rst_string.of_string
|
|
in
|
|
let write (of_rst,w) s =
|
|
try
|
|
match of_rst str with
|
|
| Some data -> w data
|
|
| None -> ()
|
|
with
|
|
| _ -> (Printf.eprintf "Info: Read error in %s\n%!"
|
|
(keyword_to_string s); ignore (of_rst str) )
|
|
in
|
|
let open Input in
|
|
match s with
|
|
{write}
|
|
| Electrons -> write Electrons.(of_rst, write) s
|
|
| Determinants_by_hand -> write Determinants_by_hand.(of_rst, write ~force:false) s
|
|
| Nuclei_by_hand -> write Nuclei_by_hand.(of_rst, write) s
|
|
| Ao_basis -> () (* TODO *)
|
|
| Mo_basis -> () (* TODO *)
|
|
end
|
|
|
|
|
|
|
|
(** Creates the temporary file for interactive editing *)
|
|
let create_temp_file ezfio_filename fields =
|
|
let temp_filename = Filename.temp_file "qp_edit_" ".rst" in
|
|
begin
|
|
let oc = open_out temp_filename in
|
|
(file_header ezfio_filename) :: (List.map get fields)
|
|
|> String.concat "\n"
|
|
|> Printf.fprintf oc "%s";
|
|
close_out oc;
|
|
at_exit (fun () -> Sys.remove temp_filename);
|
|
temp_filename
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
let run check_only ?ndet ?state ezfio_filename =
|
|
|
|
(* Set check_only if the arguments are not empty *)
|
|
let check_only =
|
|
match ndet, state with
|
|
| None, None -> check_only
|
|
| _ -> true
|
|
in
|
|
|
|
(* Open EZFIO *)
|
|
if (not (Sys.file_exists ezfio_filename)) then
|
|
failwith (ezfio_filename^" does not exists");
|
|
|
|
Ezfio.set_file ezfio_filename;
|
|
|
|
(* Clean qp_stop status *)
|
|
[ "qpstop" ; "qpkill" ]
|
|
|> List.iter (fun f ->
|
|
let stopfile =
|
|
Filename.concat (Qpackage.ezfio_work ezfio_filename) f
|
|
in
|
|
if Sys.file_exists stopfile then
|
|
Sys.remove stopfile
|
|
);
|
|
|
|
(* Reorder basis set *)
|
|
begin
|
|
let aos =
|
|
match Input.Ao_basis.read() with
|
|
| Some x -> x
|
|
| _ -> assert false
|
|
in
|
|
let ordering = Input.Ao_basis.ordering aos in
|
|
let test = Array.copy ordering in
|
|
Array.sort compare test ;
|
|
if test <> ordering then
|
|
begin
|
|
Printf.eprintf "Warning: Basis set is not properly ordered. Redordering.\n";
|
|
let new_aos = Input.Ao_basis.reorder aos in
|
|
Input.Ao_basis.write new_aos;
|
|
match Input.Mo_basis.read() with
|
|
| None -> ()
|
|
| Some mos ->
|
|
let new_mos = Input.Mo_basis.reorder mos ordering in
|
|
Input.Mo_basis.write new_mos
|
|
end
|
|
end;
|
|
|
|
begin
|
|
match ndet with
|
|
| None -> ()
|
|
| Some n -> Input.Determinants_by_hand.update_ndet (Det_number.of_int n)
|
|
end;
|
|
|
|
begin
|
|
match state with
|
|
| None -> ()
|
|
| Some range ->
|
|
begin
|
|
Input.Determinants_by_hand.extract_states range
|
|
end
|
|
end;
|
|
|
|
|
|
(*
|
|
let output = (file_header ezfio_filename) :: (
|
|
List.map get [
|
|
Ao_basis ;
|
|
Mo_basis ;
|
|
])
|
|
in
|
|
String.concat output
|
|
|> print_string
|
|
*)
|
|
|
|
let tasks = [
|
|
Nuclei_by_hand ;
|
|
Ao_basis;
|
|
Electrons ;
|
|
{tasks}
|
|
Mo_basis;
|
|
Determinants_by_hand ;
|
|
]
|
|
in
|
|
|
|
(* Create the temp file *)
|
|
let temp_filename =
|
|
create_temp_file ezfio_filename tasks
|
|
in
|
|
|
|
(* Open the temp file with external editor *)
|
|
let editor =
|
|
try Sys.getenv "EDITOR"
|
|
with Not_found -> "vi"
|
|
in
|
|
|
|
match check_only with
|
|
| true -> ()
|
|
| false ->
|
|
Printf.sprintf "%s %s" editor temp_filename
|
|
|> Sys.command |> ignore
|
|
;
|
|
|
|
(* Re-read the temp file *)
|
|
let temp_string =
|
|
let ic = open_in temp_filename in
|
|
let result =
|
|
input_lines ic
|
|
|> String.concat "\n"
|
|
in
|
|
close_in ic;
|
|
result
|
|
in
|
|
List.iter (fun x -> set temp_string x) tasks
|
|
|
|
|
|
|
|
|
|
|
|
(** Remove the backup file *)
|
|
let remove_backup ezfio_filename =
|
|
let backup_filename =
|
|
Printf.sprintf "%s/work/backup.tar" ezfio_filename
|
|
in
|
|
try Sys.remove backup_filename
|
|
with _ -> ()
|
|
|
|
(** Create a backup file in case of an exception *)
|
|
let create_backup ezfio_filename =
|
|
remove_backup ezfio_filename;
|
|
let backup_filename =
|
|
Printf.sprintf "%s/work/backup.tar" ezfio_filename
|
|
in
|
|
try
|
|
Printf.sprintf "
|
|
mkdir -p %s/work ;
|
|
tar -cf .backup.tar --exclude=\"work/*\" %s && (mv .backup.tar %s || rm .backup.tar)
|
|
"
|
|
ezfio_filename ezfio_filename backup_filename
|
|
|> Sys.command
|
|
|> ignore
|
|
with _ -> ()
|
|
|
|
|
|
(** Restore the backup file when an exception occuprs *)
|
|
let restore_backup ezfio_filename =
|
|
let filename =
|
|
Printf.sprintf "%s/work/backup.tar" ezfio_filename
|
|
in
|
|
if Sys.file_exists filename then
|
|
begin
|
|
Printf.sprintf "tar -xf %s" filename
|
|
|> Sys.command |> ignore;
|
|
remove_backup ezfio_filename
|
|
end
|
|
|
|
|
|
|
|
let () =
|
|
let open Command_line in
|
|
begin
|
|
set_header_doc (Sys.argv.(0) ^ " - quantum_package command");
|
|
set_description_doc
|
|
"Opens a text editor to edit the parameters of an EZFIO directory.";
|
|
|
|
[ {{ short='c'; long="check"; opt=Optional;
|
|
doc="Checks the input data";
|
|
arg=Without_arg; }};
|
|
|
|
{{ short='n'; long="ndet"; opt=Optional;
|
|
doc="Truncates the wavefunction to the target number of determinants";
|
|
arg=With_arg "<int>"; }};
|
|
|
|
{{
|
|
short='s'; long="state"; opt=Optional;
|
|
doc="Extracts selected states, for example \"[1,3-5]\"";
|
|
arg=With_arg "<range>"; }};
|
|
|
|
anonymous "EZFIO_DIR" Mandatory "EZFIO directory";
|
|
]
|
|
|> set_specs ;
|
|
|
|
end;
|
|
|
|
(* Handle options *)
|
|
let ndet =
|
|
match Command_line.get "ndet" with
|
|
| None -> None
|
|
| Some s -> (try Some (int_of_string s)
|
|
with _ -> failwith "[-n|--ndet] expects an integer")
|
|
in
|
|
let state =
|
|
match Command_line.get "state" with
|
|
| None -> None
|
|
| Some s -> (try Some (Range.of_string s)
|
|
with _ -> failwith "[-s|--state] expects a range")
|
|
in
|
|
|
|
let c = Command_line.get_bool "check" in
|
|
|
|
let ezfio_filename =
|
|
match Command_line.anon_args () with
|
|
| [x] -> x
|
|
| _ -> (Command_line.help () ; failwith "EZFIO_DIR is missing")
|
|
in
|
|
|
|
at_exit (fun () -> remove_backup ezfio_filename);
|
|
(* Run the program *)
|
|
try
|
|
if (not c) then create_backup ezfio_filename;
|
|
run c ?ndet ?state ezfio_filename
|
|
with
|
|
| Failure exc
|
|
| Invalid_argument exc ->
|
|
begin
|
|
Printf.eprintf "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n";
|
|
Printf.eprintf "%s\n\n" exc;
|
|
Printf.eprintf "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n";
|
|
restore_backup ezfio_filename;
|
|
ignore @@ exit 1
|
|
end
|
|
| Assert_failure (file, line, ch) ->
|
|
begin
|
|
Printf.eprintf "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n";
|
|
Printf.eprintf "Assert error in file $QP_ROOT/ocaml/%s, line %d, character %d\n\n" file line ch;
|
|
Printf.eprintf "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n";
|
|
restore_backup ezfio_filename;
|
|
ignore @@ exit 2
|
|
end;
|
|
|
|
exit 0
|
|
|