From 299127f24122de032c4fc38066f22a78fe14cd3d Mon Sep 17 00:00:00 2001 From: the-hampel Date: Fri, 25 Oct 2024 09:38:32 +0200 Subject: [PATCH] [feat] add mpi_exe flag and update to latest vasp h5 interface --- python/solid_dmft/csc_flow.py | 14 +++++-- python/solid_dmft/dft_managers/mpi_helpers.py | 5 +++ python/solid_dmft/dft_managers/qe_manager.py | 5 ++- .../solid_dmft/dft_managers/vasp_manager.py | 41 +++++++++++++++---- python/solid_dmft/io_tools/default.toml | 1 + 5 files changed, 54 insertions(+), 12 deletions(-) diff --git a/python/solid_dmft/csc_flow.py b/python/solid_dmft/csc_flow.py index 10635da3..fd19b045 100644 --- a/python/solid_dmft/csc_flow.py +++ b/python/solid_dmft/csc_flow.py @@ -99,7 +99,7 @@ def _full_qe_run(seedname, dft_params, mode): # runs a full iteration of DFT qe_wrapper = lambda calc_type: qe.run(dft_params['n_cores'], calc_type, dft_params['dft_exec'], - dft_params['mpi_env'], seedname) + dft_params['mpi_env'], dft_params['mpi_exe'], seedname) # Initially run an scf calculation if mode == 'initial': @@ -180,15 +180,23 @@ def _full_vasp_run(general_params, dft_params, initial_run, n_iter_dft=1, sum_k= if initial_run: assert n_iter_dft == 1 else: + dft_iter_init = vasp.read_dft_iter() assert n_iter_dft == 1 or sum_k is not None, 'Sumk object needed to run multiple DFT iterations' for i in range(n_iter_dft): if initial_run: vasp_process_id = vasp.run_initial_scf(dft_params['n_cores'], dft_params['dft_exec'], - dft_params['mpi_env']) + dft_params['mpi_exe'], dft_params['mpi_env']) else: vasp_process_id = None vasp.run_charge_update() + dft_iter = vasp.read_dft_iter() + mpi.report(f'\nDFT SCF iteration {dft_iter} finished. Running converter:') + if not dft_iter == dft_iter_init+i+1: + mpi.report(f'DFT iteration number did not increase. Aborting.\n \ + DFT iteration {dft_iter} != {dft_iter_init+i+1}') + vasp.kill(vasp_process_id) + exit() if dft_params['projector_type'] == 'plo': _run_plo_converter(general_params, dft_params) @@ -222,7 +230,7 @@ def _full_vasp_run(general_params, dft_params, initial_run, n_iter_dft=1, sum_k= sum_k.calc_mu(precision=general_params['prec_mu']) # Writes out GAMMA file - deltaN, _, _ = sum_k.calc_density_correction(dm_type='vasp', kpts_to_write=irred_indices) + sum_k.calc_density_correction(dm_type='vasp', kpts_to_write=irred_indices) return vasp_process_id, irred_indices diff --git a/python/solid_dmft/dft_managers/mpi_helpers.py b/python/solid_dmft/dft_managers/mpi_helpers.py index 17fe58ca..a1376eb0 100644 --- a/python/solid_dmft/dft_managers/mpi_helpers.py +++ b/python/solid_dmft/dft_managers/mpi_helpers.py @@ -93,6 +93,11 @@ def find_path_to_mpi_command(env_vars, mpi_exe): string: absolute path to mpi command """ + # first check if mpi_exe is already full path to executable + if os.path.isfile(mpi_exe): + return mpi_exe + + # otherwise, check if mpi_exe is in PATH for path_directory in env_vars.get('PATH').split(os.pathsep): if path_directory: potential_path = os.path.join(path_directory, mpi_exe) diff --git a/python/solid_dmft/dft_managers/qe_manager.py b/python/solid_dmft/dft_managers/qe_manager.py index ebc883ba..beeedd7b 100644 --- a/python/solid_dmft/dft_managers/qe_manager.py +++ b/python/solid_dmft/dft_managers/qe_manager.py @@ -82,7 +82,7 @@ def _start_with_piping(mpi_exe, mpi_arguments, qe_file_ext, env_vars, seedname): subprocess.check_call(mpi_arguments + [seedname], env=env_vars, shell=False) -def run(number_cores, qe_file_ext, qe_exec, mpi_profile, seedname): +def run(number_cores, qe_file_ext, qe_exec, mpi_profile, mpi_exe_param, seedname): """ Starts the VASP child process. Takes care of initializing a clean environment for the child process. This is needed so that VASP does not @@ -111,7 +111,8 @@ def run(number_cores, qe_file_ext, qe_exec, mpi_profile, seedname): env_vars[var_name] = var # assuming that mpirun points to the correct mpi env - mpi_exe = mpi_helpers.find_path_to_mpi_command(env_vars, 'mpirun') + mpi_exe = mpi_helpers.find_path_to_mpi_command(env_vars, mpi_exe_param) + print('\nMPI executable for QE:', mpi_exe) if qe_file_ext in ['scf', 'nscf', 'mod_scf', 'bnd']: qe_exec += f'pw.x -nk {number_cores}' diff --git a/python/solid_dmft/dft_managers/vasp_manager.py b/python/solid_dmft/dft_managers/vasp_manager.py index 3e764b2f..0258f4a8 100644 --- a/python/solid_dmft/dft_managers/vasp_manager.py +++ b/python/solid_dmft/dft_managers/vasp_manager.py @@ -100,7 +100,7 @@ def remove_legacy_projections_suppressed(): mpi.barrier() -def run_initial_scf(number_cores, vasp_command, cluster_name): +def run_initial_scf(number_cores, vasp_command, mpi_exe_param, cluster_name): """ Starts the VASP child process. Takes care of initializing a clean environment for the child process. This is needed so that VASP does not @@ -134,7 +134,8 @@ def run_initial_scf(number_cores, vasp_command, cluster_name): env_vars[var_name] = var # assuming that mpirun points to the correct mpi env - mpi_exe = mpi_helpers.find_path_to_mpi_command(env_vars, 'mpirun') + mpi_exe = mpi_helpers.find_path_to_mpi_command(env_vars, mpi_exe_param) + print('\nMPI executable for Vasp:', mpi_exe) arguments = mpi_helpers.get_mpi_arguments(cluster_name, mpi_exe, number_cores, vasp_command, hostfile) vasp_process_id = _fork_and_start_vasp(mpi_exe, arguments, env_vars) @@ -172,12 +173,17 @@ def run_charge_update(): def read_dft_energy(): """ - Reads DFT energy from the last line of Vasp's vasptriqs.h5 or from OSZICAR. + Reads DFT energy from the last line of Vasp's OSZICAR or from vasptriqs.h5 """ - if os.path.isfile('vasptriqs.h5'): - with HDFArchive('vasptriqs.h5', 'r') as h5: - dft_energy = h5['triqs/etotal'] - else: + h5_energy = False + if os.path.isfile('vaspout.h5'): + with HDFArchive('vaspout.h5', 'r') as h5: + if 'oszicar' in h5['intermediate/ion_dynamics']: + dft_energy = h5['intermediate/ion_dynamics/oszicar'][-1,1] + h5_energy = True + + # as backup use OSZICAR file + if not h5_energy: with open('OSZICAR', 'r') as file: nextline = file.readline() while nextline.strip(): @@ -187,6 +193,27 @@ def read_dft_energy(): return dft_energy +def read_dft_iter(): + """ + Reads DFT iteration number from the last line of the OSZICAR or from Vasp's vasptriqs.h5 + """ + h5_iter = False + if os.path.isfile('vaspout.h5'): + with HDFArchive('vaspout.h5', 'r') as h5: + if 'oszicar' in h5['intermediate/ion_dynamics']: + dft_iter = int(h5['intermediate/ion_dynamics/oszicar'][-1,0]) + h5_iter = True + + # as backup use OSZICAR file + if not h5_iter: + with open('OSZICAR', 'r') as file: + nextline = file.readline() + while nextline.strip(): + line = nextline + nextline = file.readline() + dft_iter = int(line.split()[1]) + + return dft_iter def read_irred_kpoints(kpts): """ Reads the indices of the irreducible k-points from the OUTCAR. """ diff --git a/python/solid_dmft/io_tools/default.toml b/python/solid_dmft/io_tools/default.toml index 0757afdb..b85f6716 100644 --- a/python/solid_dmft/io_tools/default.toml +++ b/python/solid_dmft/io_tools/default.toml @@ -182,6 +182,7 @@ with_fock = false dft_code = "" dft_exec = "vasp_std" mpi_env = "default" +mpi_exe = "mpirun" n_cores = "" n_iter = 4 n_iter_first = ""