10
0
mirror of https://github.com/LCPQ/quantum_package synced 2024-09-27 12:00:56 +02:00
quantum_package/scripts/ezfio_interface/qp_edit_template

337 lines
8.2 KiB
Plaintext
Raw Normal View History

(*
vim::syntax=ocaml
*)
open Qputils
open Qptypes
2017-08-18 19:43:52 +02:00
open Core
2014-10-26 12:46:17 +01:00
(** Interactive editing of the input.
2014-10-29 00:12:45 +01:00
2015-04-20 10:12:08 +02:00
WARNING
This file is autogenerad by
`${{QP_ROOT}}/scripts/ezfio_interface/ei_handler.py`
*)
2014-10-29 00:12:45 +01:00
(** Keywords used to define input sections *)
2014-10-26 12:46:17 +01:00
type keyword =
| Ao_basis
2015-04-20 10:12:08 +02:00
| Determinants_by_hand
2014-10-28 17:16:51 +01:00
| Electrons
| Mo_basis
| Nuclei_by_hand
2015-04-02 11:30:03 +02:00
{keywords}
2014-10-26 12:46:17 +01:00
2014-10-26 12:46:17 +01:00
let keyword_to_string = function
2015-04-20 10:12:08 +02:00
| Ao_basis -> "AO basis"
| Determinants_by_hand -> "Determinants_by_hand"
| Electrons -> "Electrons"
| Mo_basis -> "MO basis"
| Nuclei_by_hand -> "Molecule"
2015-04-02 11:30:03 +02:00
{keywords_to_string}
2014-10-26 12:46:17 +01:00
(** 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 *)
2014-10-26 12:46:17 +01:00
let make_header kw =
let s = keyword_to_string kw in
let l = String.length s in
2014-10-29 00:12:45 +01:00
"\n\n"^s^"\n"^(String.init l ~f:(fun _ -> '='))^"\n\n"
2014-10-26 12:46:17 +01:00
(** Returns the rst string of section [s] *)
2014-10-28 17:16:51 +01:00
let get s =
2014-11-27 23:05:26 +01:00
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)
2014-11-27 23:05:26 +01:00
| Ao_basis ->
f Ao_basis.(read, to_rst)
2015-04-20 10:12:08 +02:00
| Determinants_by_hand ->
2016-03-07 19:21:11 +01:00
f Determinants_by_hand.(read_maybe, to_rst)
2015-04-02 11:30:03 +02:00
{section_to_rst}
2014-11-27 23:05:26 +01:00
end
with
| Sys_error msg -> (Printf.eprintf "Info: %s\n%!" msg ; "")
in
rst
2014-10-26 12:46:17 +01:00
(** Applies the changes from the string [str] corresponding to section [s] *)
2014-11-03 19:33:06 +01:00
let set str s =
let header = (make_header s) in
2014-11-27 23:05:26 +01:00
match String.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.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 ~pos:index_begin ~len:l str
|> 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) )
2014-11-27 23:05:26 +01:00
in
let open Input in
match s with
2015-04-02 11:30:03 +02:00
{write}
2014-11-27 23:05:26 +01:00
| Electrons -> write Electrons.(of_rst, write) s
2015-04-20 10:12:08 +02:00
| Determinants_by_hand -> write Determinants_by_hand.(of_rst, write) s
| Nuclei_by_hand -> write Nuclei_by_hand.(of_rst, write) s
2014-11-27 23:05:26 +01:00
| Ao_basis -> () (* TODO *)
| Mo_basis -> () (* TODO *)
end
2014-11-03 19:33:06 +01:00
(** Creates the temporary file for interactive editing *)
2014-10-28 17:16:51 +01:00
let create_temp_file ezfio_filename fields =
2014-11-03 19:33:06 +01:00
let temp_filename = Filename.temp_file "qp_edit_" ".rst" in
2014-11-27 23:05:26 +01:00
begin
2019-01-11 19:10:12 +01:00
Out_channel.with_file temp_filename ~f:(fun out_channel ->
2014-11-27 23:05:26 +01:00
(file_header ezfio_filename) :: (List.map ~f:get fields)
|> String.concat ~sep:"\n"
|> Out_channel.output_string out_channel
2019-01-11 19:10:12 +01:00
);
at_exit (fun () -> Sys.remove temp_filename);
temp_filename
2014-11-27 23:05:26 +01:00
end
2014-10-26 12:46:17 +01:00
2017-04-12 14:46:12 +02:00
let run check_only ?ndet ?state ezfio_filename =
(* Set check_only if the arguments are not empty *)
let check_only =
2017-04-12 14:46:12 +02:00
match ndet, state with
| None, None -> check_only
| _ -> true
in
2014-10-26 12:46:17 +01:00
(* Open EZFIO *)
if (not (Sys.file_exists_exn ezfio_filename)) then
failwith (ezfio_filename^" does not exists");
Ezfio.set_file ezfio_filename;
begin
match ndet with
| None -> ()
| Some n -> Input.Determinants_by_hand.update_ndet (Det_number.of_int n)
end;
2017-04-12 14:46:12 +02:00
begin
match state with
| None -> ()
2018-12-13 16:53:47 +01:00
| Some n ->
begin
Input.Determinants_by_hand.extract_state (States_number.of_int n)
end
2017-04-12 14:46:12 +02:00
end;
2014-11-03 19:33:06 +01:00
(*
let output = (file_header ezfio_filename) :: (
2014-10-28 17:16:51 +01:00
List.map ~f:get [
Ao_basis ;
Mo_basis ;
])
in
2014-10-26 12:46:17 +01:00
String.concat output
|> print_string
2014-11-03 19:33:06 +01:00
*)
let tasks = [
Nuclei_by_hand ;
2014-11-28 19:50:48 +01:00
Ao_basis;
2014-11-04 00:39:10 +01:00
Electrons ;
2015-04-02 11:30:03 +02:00
{tasks}
2014-12-25 23:53:29 +01:00
Mo_basis;
2015-04-20 10:12:08 +02:00
Determinants_by_hand ;
2014-11-03 19:33:06 +01:00
]
in
(* Create the temp file *)
let temp_filename =
create_temp_file ezfio_filename tasks
in
2014-11-03 19:33:06 +01:00
(* Open the temp file with external editor *)
let editor =
match Sys.getenv "EDITOR" with
| Some editor -> editor
| None -> "vi"
in
match check_only with
| true -> ()
| false ->
Printf.sprintf "%s %s" editor temp_filename
|> Sys.command_exn
;
2014-11-03 19:33:06 +01:00
(* Re-read the temp file *)
let temp_string =
In_channel.with_file temp_filename ~f:(fun in_channel ->
In_channel.input_all in_channel)
in
2019-01-11 19:10:12 +01:00
List.iter ~f:(fun x -> set temp_string x) tasks
2014-11-03 19:33:06 +01:00
2014-10-26 12:46:17 +01:00
2019-01-11 19:10:12 +01:00
(** 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 =
2019-01-11 19:10:12 +01:00
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_exn
with _ -> ()
(** Restore the backup file when an exception occuprs *)
let restore_backup ezfio_filename =
2019-01-11 19:10:12 +01:00
let filename =
Printf.sprintf "%s/work/backup.tar" ezfio_filename
in
if Sys.file_exists_exn filename then
begin
Printf.sprintf "tar -xf %s" filename
|> Sys.command_exn;
remove_backup ezfio_filename
end
2014-10-26 12:46:17 +01:00
let () =
2019-01-11 19:10:12 +01:00
(* Command-line specs *)
Command_line.set_header_doc "Opens a text editor to edit the parameters of a EZFIO directory.";
[ ( 'c', "check", "Checks the input data", Command_line.Without_arg);
( 'n', "ndet", "<int> Truncate the wavefunction to the target number of determinants",
Command_line.With_arg);
( 's', "state", "<int> Pick the state as a new wavefunction", Command_line.With_arg);
Command_line.anonymous "<EZFIO_FILE>" "EZFIO directory";
]
|> Command_line.set_specs ;
2014-10-26 12:46:17 +01:00
2019-01-11 19:10:12 +01:00
(* Handle options *)
if Command_line.show_help () then
exit 0;
2014-10-26 12:46:17 +01:00
2019-01-11 19:10:12 +01:00
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 (int_of_string s)
with _ -> failwith "[-s|--state] expects an integer")
in
let c =
match Command_line.get "check" with
| None -> false
| _ -> true
in
let ezfio_filename =
match Command_line.anon_args () with
| [x] -> x
| _ -> (Command_line.help () ; failwith "EZFIO_FILE 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
2014-10-26 12:46:17 +01:00