diff --git a/CMakeLists.txt b/CMakeLists.txt index b6400873f4..a27699b7dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1023,6 +1023,18 @@ if(NOT QMC_NO_SLOW_CUSTOM_TESTING_COMMANDS) endif() endif() +#------------------------------------------------------------------- +# Check if GPAW is available +#------------------------------------------------------------------- +if(NOT QMC_NO_SLOW_CUSTOM_TESTING_COMMANDS) + check_python_reqs(gpaw "" HAVE_GPAW) + if(NOT ${HAVE_GPAW}) + message(STATUS "Unable to import GPAW python module. GPAW converter tests will not be run.") + else() + message(STATUS "Successfully imported GPAW python modules.") + endif() +endif() + #------------------------------------------------------------------- # Check if QE executables available at QE_BIN or on the PATH #------------------------------------------------------------------- diff --git a/src/QMCTools/CMakeLists.txt b/src/QMCTools/CMakeLists.txt index f4915d8ef2..1d791b5ffb 100644 --- a/src/QMCTools/CMakeLists.txt +++ b/src/QMCTools/CMakeLists.txt @@ -53,6 +53,9 @@ if(USE_OBJECT_TARGET) target_link_libraries(qmcfinitesize qmcparticle qmcutil) endif() +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/gpaw4qmcpack.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gpaw4qmcpack.py SYMBOLIC) +install(FILES gpaw4qmcpack.py DESTINATION bin) + foreach(EXE_TARGET convert4qmc qmc-extract-eshdf-kvectors qmc-get-supercell qmc-check-affinity convertpw4qmc qmcfinitesize) add_test_target_in_output_location(${EXE_TARGET} bin) install(TARGETS ${EXE_TARGET} RUNTIME DESTINATION bin) diff --git a/src/QMCTools/Eshdf.py b/src/QMCTools/Eshdf.py new file mode 100644 index 0000000000..ffffaa6195 --- /dev/null +++ b/src/QMCTools/Eshdf.py @@ -0,0 +1,245 @@ +###################################################################################### +## This file is distributed under the University of Illinois/NCSA Open Source License. +## See LICENSE file in top directory for details. +## +## Copyright (c) 2021 QMCPACK developers. +## +## File developed by: Juha Tiihonen, tiihonen@iki.fi, University of Jyvaskyla +## +## File created by: Juha Tiihonen, tiihonen@iki.fi, University of Jyvaskyla +####################################################################################### + +from numpy import array + +# This file defines python classes to load/write data needed by the ESHDF file format. +# +# The main logic of the class structure is to inherit from Base -> Representation -> Application +# +# currently implemented: +# +# Base: +# EshdfFileBase +# Representation: +# EshdfFilePw +# Application: +# EshdfFilePwGpaw <- found in Eshdf_gpaw.py + + +# define dtypes for the HDF5 +int_dtype = ' Representation -> Application.` +The Base class ´EshdfFileBase´ contains virtual implementation of the core +methods. The Representation classes add methods and variables for managing +specific choices of the representation. The Application class implements +bindings to a specific application. + + +## Currently implemented classes + +Base: +- EshdfFileBase +Representation: +- EshdfFilePw (plane-wave) +Application: +- EshdfFilePwGpaw (´Eshdf_gpaw.py´) + +This is work-in-progress, and other features are coming up. + + +# GPAW4QMCPACK + +Converter of electronic orbitals from GPAW (https://wiki.fysik.dtu.dk/gpaw/) +is implemented in ´gpaw4qmcpack.py´, using the ESHDF Python class. + +The converter is run on the command line. It requires a GPAW restart file +(.gpw) with orbitals included with ´mode=all´, and produces an ESHDF file (.h5) +that can be used in QMCPACK. + +If the MPC correction will be needed, the charge density information can be +added with `-d`, but it must be computed on the runtime. Therefore, the +density is not included by default. + +This is work-in-progress, and other features and documentation are coming up. diff --git a/src/QMCTools/gpaw4qmcpack.py b/src/QMCTools/gpaw4qmcpack.py new file mode 100755 index 0000000000..936d03d6a7 --- /dev/null +++ b/src/QMCTools/gpaw4qmcpack.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +###################################################################################### +## This file is distributed under the University of Illinois/NCSA Open Source License. +## See LICENSE file in top directory for details. +## +## Copyright (c) 2021 QMCPACK developers. +## +## File developed by: Juha Tiihonen, tiihonen@iki.fi, University of Jyvaskyla +## +## File created by: Juha Tiihonen, tiihonen@iki.fi, University of Jyvaskyla +####################################################################################### + +# This file converts GPAW orbitals for QMCPACK using ESHDF Python classes + +import argparse + +from Eshdf_gpaw import EshdfFilePwGpaw + +parser = argparse.ArgumentParser(description='GPAW4QMCPACK') +parser.add_argument('infile',help='input .gpw restart file') +parser.add_argument('outfile',default='eshdf.h5',help='output .h5 orbital file') +parser.add_argument('-d','--density',action='store_true',help='whether or not to convert density') + +if __name__=='__main__': + args = vars(parser.parse_args()) + eshdf = EshdfFilePwGpaw(**args) + eshdf.write() + print('Converted GPAW orbitals for QMCPACK!') +#end if diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 20f58437bf..8cfbfbea88 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -66,6 +66,7 @@ if(HAVE_PYSCF) endif() endif() endif() + # # if(NOT ${QMCAPP_ERR} STREQUAL "") diff --git a/tests/converter/CMakeLists.txt b/tests/converter/CMakeLists.txt index 1d563ab41a..357032222f 100644 --- a/tests/converter/CMakeLists.txt +++ b/tests/converter/CMakeLists.txt @@ -63,3 +63,12 @@ add_converter_test(test_LiH_qp) add_converter_test(test_C4_MSD_excited) add_converter_test(test_diamond2_rmg) add_converter_test(test_O_rmg) + +if(HAVE_GPAW) + include("${qmcpack_SOURCE_DIR}/CMake/python.cmake") + check_python_reqs("numpy;h5py;ase;gpaw" gpaw4qmcpack_test add_tests) + if(add_tests) + message("Python dependencies met. Adding GPAW4QMCPACK tests") + add_subdirectory("gpaw") + endif() +endif() diff --git a/tests/converter/gpaw/CMakeLists.txt b/tests/converter/gpaw/CMakeLists.txt new file mode 100644 index 0000000000..eb8fcf1ff6 --- /dev/null +++ b/tests/converter/gpaw/CMakeLists.txt @@ -0,0 +1,18 @@ +# add tests for GPAW4QMCPACK converter +file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/gpaw4qmcpack_test.py ${CMAKE_CURRENT_BINARY_DIR}/gpaw4qmcpack_test.py SYMBOLIC) +function(ADD_GPAW4QMCPACK_TEST test_name) + set(EXE_NAME "${PROJECT_SOURCE_DIR}/src/QMCTools/gpaw4qmcpack.py") + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${test_name}") + file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/${test_name}/restart.gpw" + "${CMAKE_CURRENT_BINARY_DIR}/${test_name}/restart.gpw" SYMBOLIC) + file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/${test_name}/gold.orbs.h5" + "${CMAKE_CURRENT_BINARY_DIR}/${test_name}/gold.orbs.h5" SYMBOLIC) + add_test(NAME gpaw4qmcpack_test COMMAND "${CMAKE_CURRENT_BINARY_DIR}/gpaw4qmcpack_test.py" + "${CMAKE_CURRENT_BINARY_DIR}/${test_name}" + --exe "${EXE_NAME}" --h5diff "${HDF5_DIFF_EXECUTABLE}") + set_tests_properties(gpaw4qmcpack_test PROPERTIES + FAIL_REGULAR_EXPRESSION " FAIL" + PASS_REGULAR_EXPRESSION " pass" + TIMEOUT 120 LABELS "converter;deterministic") +endfunction() +add_gpaw4qmcpack_test(test_Si_diamond) diff --git a/tests/converter/gpaw/gpaw4qmcpack_test.py b/tests/converter/gpaw/gpaw4qmcpack_test.py new file mode 100755 index 0000000000..8be1f5813c --- /dev/null +++ b/tests/converter/gpaw/gpaw4qmcpack_test.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 + +import argparse +import os +import subprocess +import sys + +# unit test GPAW4QMCPACK + +# TODO: implement and test converter generated QMCPACK input + +def run_gpaw4qmcpack_test(test_name, g4q_exe, h5diff_exe): + okay = True + + # Example invocation of converter + #gpaw4qmcpack infile.gpw outfile.h5 --density + + infile = 'restart.gpw' + outfile = 'test.orbs.h5' + cmd = [g4q_exe,infile,outfile] + + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + stdout, stderr = p.communicate() + + file_out = open('stdout.txt', 'w') + file_out.write(stdout) + file_out.close() + if len(stderr) > 0 : + file_err = open('stderr.txt', 'w') + file_err.write(stderr) + file_err.close() + + ret = p.returncode + + if ret != 0: + print("Return code nonzero: ", ret) + okay = False + + if len(stderr.strip()) != 0: + # some MPI output on stderr is okay + # TODO - more general way of checking acceptable stderr strings + if not stderr.startswith('Rank'): + print("Stderr not empty") + print(stderr) + okay = False + + ret = os.system(h5diff_exe + ' -d 0.000001 gold.orbs.h5 test.orbs.h5') + # if it's okay up to this point + if ret==0 and okay: + print(" pass") + return True + else: + print("h5diff reported a difference") + print(" FAIL") + return False + + return okay + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Test gpaw4qmcpck') + parser.add_argument('test_name', + default='test_Si_diamond', + help='Name of test to run (name of directory)') + parser.add_argument('--exe', + default='gpaw4qmcpack', + help='Location of gpaw4qmcpack executable') + parser.add_argument('--h5diff', + default='h5diff', + help='Location of h5diff executable') + args = parser.parse_args() + + test_dir = args.test_name + if not os.path.exists(test_dir): + print("Test not found: ", test_dir) + sys.exit(1) + + curr_dir = os.getcwd() + os.chdir(test_dir) + + ret = run_gpaw4qmcpack_test(test_dir, args.exe, args.h5diff) + + os.chdir(curr_dir) + + if ret: + sys.exit(0) + sys.exit(1) + diff --git a/tests/converter/gpaw/test_Si_diamond/gold.orbs.h5 b/tests/converter/gpaw/test_Si_diamond/gold.orbs.h5 new file mode 100644 index 0000000000..f58a60b043 Binary files /dev/null and b/tests/converter/gpaw/test_Si_diamond/gold.orbs.h5 differ diff --git a/tests/converter/gpaw/test_Si_diamond/restart.gpw b/tests/converter/gpaw/test_Si_diamond/restart.gpw new file mode 100644 index 0000000000..228266c850 Binary files /dev/null and b/tests/converter/gpaw/test_Si_diamond/restart.gpw differ diff --git a/tests/converter/gpaw/test_Si_diamond/run_si.py b/tests/converter/gpaw/test_Si_diamond/run_si.py new file mode 100755 index 0000000000..92c2049409 --- /dev/null +++ b/tests/converter/gpaw/test_Si_diamond/run_si.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 + +# This file provided just for reference, not executed in the test + +from ase.build import bulk +from ase.units import Ry +from gpaw import GPAW,PW,FermiDirac,setup_paths + +silicon = bulk('Si', 'diamond', a=5.459) + +econv = 1e-9*2*Ry +ecut = 30*Ry +silicon.calc = GPAW(xc='PBE', + setups = {'default':'sg15'}, # Based on standard library of soft SG15 ecps + mode = PW(ecut,force_complex_dtype=True), # give all modes explicitly + txt = 'silicon.txt', + kpts = (2,2,2), + occupations = FermiDirac(0.1), + convergence = {'energy':econv}, + symmetry = 'off' + ) +silicon.get_potential_energy() +silicon.calc.write('restart.gpw',mode='all') # important to request mode='all'