diff --git a/configure.ac b/configure.ac index da52c58a9d175a0e2dd9593669d4b845ed6aee56..4221d9202cd3312f8ece81422c6306683075360c 100644 --- a/configure.ac +++ b/configure.ac @@ -268,6 +268,7 @@ dnl =================================================================== dnl now we search for libraries ACX_LIBXC +ACX_LIBVDWXC dnl check for BLAS ACX_BLAS([], AC_MSG_ERROR([could not find required BLAS library])) diff --git a/m4/libvdwxc.m4 b/m4/libvdwxc.m4 new file mode 100644 index 0000000000000000000000000000000000000000..38959aded88a6bebb9b611d78511ae2494b18a46 --- /dev/null +++ b/m4/libvdwxc.m4 @@ -0,0 +1,87 @@ +AC_DEFUN([ACX_LIBVDWXC], +[ + + acx_libvdwxc_ok=no + acx_libvdwxc_mpi_ok=no + + dnl BACKUP LIBS AND FCFLAGS + acx_libvdwxc_save_LIBS="$LIBS" + acx_libvdwxc_save_FCFLAGS="$FCFLAGS" + + dnl Check if the library was given in the command line + AC_ARG_WITH(libvdwxc-prefix, [AS_HELP_STRING([--with-libvdwxc-prefix=DIR], [Directory where libvdwxc is installed.])]) + + if test x"$FCFLAGS_LIBVDWXC" = x; then + case $with_libvdwxc_prefix in + "") FCFLAGS_LIBVDWXC="-I/usr/include" ;; + *) FCFLAGS_LIBVDWXC="-I$with_libvdwxc_prefix/include" ;; + esac + fi + + AC_MSG_CHECKING([for libvdwxc]) + + libvdwxc_program_serial="AC_LANG_PROGRAM([],[ + implicit none + + include 'vdwxcfort.f90' + + integer, pointer :: vdw + + call vdwxc_new(1, vdw) + call vdwxc_print(vdw) + call vdwxc_init_serial(vdw) + call vdwxc_finalize(vdw) + ])" + + libvdwxc_program_mpi="AC_LANG_PROGRAM([],[ + implicit none + + include 'vdwxcfort.f90' + + integer, pointer :: vdw + integer :: has_mpi + + call vdwxc_new(1, vdw) + ! We are supposed to pass a communicator like MPI_COMM_WORLD below, + ! but I do not know how to get that here. We pass 42 instead. + ! The build system is happy as long as it compiles. + call vdwxc_init_mpi(vdw, 42) + call vdwxc_finalize(vdw) + ])" + + FCFLAGS="$FCFLAGS_LIBVDWXC $acx_libvdwxc_save_FCFLAGS" + + if test ! -z "$with_libvdwxc_prefix"; then + LIBS_LIBVDWXC="-L$with_libvdwxc_prefix/lib -lvdwxcfort" + else + LIBS_LIBVDWXC="-lvdwxcfort" + fi + + LIBS="$LIBS_LIBVDWXC $acx_libvdwxc_save_LIBS" + AC_LINK_IFELSE($libvdwxc_program_serial, [acx_libvdwxc_ok=yes], [acx_libvdwxc_ok=no]) + AC_LINK_IFELSE($libvdwxc_program_mpi, [acx_libvdwxc_mpi_ok=yes], [acx_libvdwxc_mpi_ok=no]) + + + if test x"$acx_libvdwxc_ok" = xyes; then + AC_DEFINE(HAVE_LIBVDWXC, 1, [Define if libvdwxc is available]) + AC_MSG_RESULT([$acx_libvdwxc_ok ($FCFLAGS_LIBVDWXC $LIBS_LIBVDWXC)]) + if test x"$acx_libvdwxc_mpi_ok" = xyes; then + AC_DEFINE(HAVE_LIBVDWXC_MPI, 1, [Define if libvdwxc has MPI support]) + AC_MSG_RESULT([$acx_libvdwxc_mpi_ok]) + else + AC_MSG_WARN([libvdwxc not compiled with MPI, cannot be used with domain decomposition]) + fi + else + LIBS_LIBVDWXC="" + FCFLAGS_LIBVDWXC="" + AC_MSG_RESULT([$acx_libvdwxc_ok]) + AC_MSG_WARN([Could not find libvdwxc library. + *** Will compile without libvdwxc support]) + fi + + AC_SUBST(FCFLAGS_LIBVDWXC) + AC_SUBST(LIBS_LIBVDWXC) + + FCFLAGS="$acx_libvdwxc_save_FCFLAGS" + LIBS="$acx_libvdwxc_save_LIBS" +]) diff --git a/src/basic/utils.F90 b/src/basic/utils.F90 index 0e90117f49fd5c062889b0e50b726877e19ddcd0..0cdec6c7d5182ab800bba2dc6a9693c10132975b 100644 --- a/src/basic/utils.F90 +++ b/src/basic/utils.F90 @@ -312,6 +312,9 @@ contains #ifdef HAVE_LIBISF get_optional_libraries = trim(get_optional_libraries)//' libisf' #endif +#ifdef HAVE_LIBVDWXC + get_optional_libraries = trim(get_optional_libraries)//' libvdwxc' +#endif #ifdef HAVE_METIS get_optional_libraries = trim(get_optional_libraries)//' metis' #endif diff --git a/src/common-rules.make b/src/common-rules.make index d9ee34199e406dc2851c141fe5c5575142eda0d7..e53386c936fe1a3ecf65d70bddad0efcce19193f 100644 --- a/src/common-rules.make +++ b/src/common-rules.make @@ -60,7 +60,7 @@ external_LIBS = \ $(top_builddir)/external_libs/yaml-0.1.4/src/libyaml.a # we should not have libyaml here if we used an external one... -FCFLAGS_MODS += @FCFLAGS_LIBXC@ @FCFLAGS_PSPIO@ @FCFLAGS_ISF@ @FCFLAGS_FFTW@ @FCFLAGS_PFFT@ @FCFLAGS_PNFFT@ @FCFLAGS_NETCDF@ @FCFLAGS_ETSF_IO@ @FCFLAGS_BERKELEYGW@ @FCFLAGS_NLOPT@ @FCFLAGS_LIBFM@ @FCFLAGS_ELPA@ @FCFLAGS_POKE@ @FCFLAGS_LIKWID@ +FCFLAGS_MODS += @FCFLAGS_LIBXC@ @FCFLAGS_PSPIO@ @FCFLAGS_ISF@ @FCFLAGS_FFTW@ @FCFLAGS_PFFT@ @FCFLAGS_PNFFT@ @FCFLAGS_NETCDF@ @FCFLAGS_ETSF_IO@ @FCFLAGS_LIBVDWXC@ @FCFLAGS_BERKELEYGW@ @FCFLAGS_NLOPT@ @FCFLAGS_LIBFM@ @FCFLAGS_ELPA@ @FCFLAGS_POKE@ @FCFLAGS_LIKWID@ if COMPILE_OPENCL external_LIBS += $(top_builddir)/external_libs/fortrancl/libfortrancl.a @LIBS_CLBLAS@ @LIBS_CLFFT@ @CL_LIBS@ @@ -77,7 +77,7 @@ endif # e.g. ETSF_IO depends on netCDF, ISF depends on LAPACK outside_LIBS = @LIBS_PSPIO@ @LIBS_POKE@ @LIBS_ISF@ @LIBS_NFFT@ @LIBS_PNFFT@ @LIBS_PFFT@ \ @LIBS_SPARSKIT@ @LIBS_ETSF_IO@ @LIBS_NETCDF@ @LIBS_LIBFM@ \ - @LIBS_BERKELEYGW@ @LIBS_NLOPT@ @GD_LIBS@ \ + @LIBS_LIBVDWXC@ @LIBS_BERKELEYGW@ @LIBS_NLOPT@ @GD_LIBS@ \ @LIBS_PARMETIS@ @LIBS_METIS@ @LIBS_LIKWID@ @LIBS_CUDA@ @LIBS_MPI@ other_LIBS = $(external_LIBS) $(scalapack_LIBS) $(outside_LIBS) $(core_LIBS) @CXXLIBS@ diff --git a/src/hamiltonian/libvdwxc.F90 b/src/hamiltonian/libvdwxc.F90 index 05d59ef03784a1f1bbca5158e40d0dce19d15422..c55f077957365ee15449456637351fb7dee3c3b6 100644 --- a/src/hamiltonian/libvdwxc.F90 +++ b/src/hamiltonian/libvdwxc.F90 @@ -5,6 +5,7 @@ ! * Functions that start with libvdwxc_ are public, to be called from other parts of Octopus. ! * Interfaces that start with vdwxc_ are actual functions of libvdwxc. + module libvdwxc_oct_m use cube_oct_m use cube_function_oct_m @@ -20,6 +21,7 @@ module libvdwxc_oct_m use parser_oct_m use pfft_oct_m use profiling_oct_m + use simul_box_oct_m use unit_system_oct_m implicit none @@ -53,69 +55,7 @@ module libvdwxc_oct_m end type libvdwxc_t #ifdef HAVE_LIBVDWXC - ! These interfaces correspond to functions in libvdwxc - interface - subroutine vdwxc_new(functional, vdw) - integer, intent(in) :: functional - integer, pointer, intent(out) :: vdw - end subroutine vdwxc_new - end interface - - interface - subroutine vdwxc_print(vdw) - integer, pointer, intent(in) :: vdw - end subroutine vdwxc_print - end interface - - interface - subroutine vdwxc_calculate(vdw, rho, sigma, dedn, dedsigma, energy) - integer, pointer, intent(inout) :: vdw - real(8), intent(in) :: rho(:,:,:) - real(8), intent(in) :: sigma(:,:,:) - real(8), intent(inout) :: dedn(:,:,:) - real(8), intent(inout) :: dedsigma(:,:,:) - real(8), intent(inout) :: energy - end subroutine vdwxc_calculate - end interface - - interface - subroutine vdwxc_set_unit_cell(vdw, nx, ny, nz, C00, C01, C02, & - C10, C11, C12, C20, C21, C22) - integer, pointer, intent(inout) :: vdw - integer, intent(in) :: nx, ny, nz - real(8), intent(in) :: C00, C01, C02, C10, C11, C12, C20, C21, C22 - end subroutine vdwxc_set_unit_cell - end interface - - interface - subroutine vdwxc_init_serial(vdw) - integer, pointer, intent(inout) :: vdw - end subroutine vdwxc_init_serial - end interface - -#ifdef HAVE_MPI - interface - subroutine vdwxc_init_mpi(vdw, comm) - integer, pointer, intent(inout) :: vdw - integer, intent(in) :: comm - end subroutine vdwxc_init_mpi - end interface - - interface - subroutine vdwxc_init_pfft(vdw, comm, ncpu1, ncpu2) - integer, pointer, intent(inout) :: vdw - integer, intent(in) :: comm - integer, intent(in) :: ncpu1 - integer, intent(in) :: ncpu2 - end subroutine vdwxc_init_pfft - end interface -#endif - - interface - subroutine vdwxc_finalize(vdw) - integer, pointer, intent(inout) :: vdw - end subroutine vdwxc_finalize - end interface + include "vdwxcfort.f90" #endif contains @@ -172,7 +112,7 @@ contains else if(this%functional == 2) then write(message(2), '(4x,a)') 'vdW-DF2 from libvdwxc' else if(this%functional == 3) then - write(message(2), '(4x,a)') 'vdW-DF-CX from libvdwxc' + write(message(2), '(4x,a)') 'vdW-DF-cx from libvdwxc' else write(message(2), '(4x,a)') 'unknown libvdwxc functional' end if @@ -245,17 +185,29 @@ contains ! Therefore we cannot use the PFFT stuff without a frightful mess. #ifdef HAVE_LIBVDWXC - call vdwxc_set_unit_cell(this%libvdwxc_ptr, & - this%cube%rs_n_global(3), this%cube%rs_n_global(2), this%cube%rs_n_global(1), & - mesh%spacing(3) * this%cube%rs_n_global(3), 0.0_8, 0.0_8, & - 0.0_8, mesh%spacing(2) * this%cube%rs_n_global(2), 0.0_8, & - 0.0_8, 0.0_8, mesh%spacing(1) * this%cube%rs_n_global(1)) + if(mesh%sb%box_shape == PARALLELEPIPED) then + call vdwxc_set_unit_cell(this%libvdwxc_ptr, & + this%cube%rs_n_global(3), this%cube%rs_n_global(2), this%cube%rs_n_global(1), & + mesh%sb%rlattice(3, 3), mesh%sb%rlattice(2, 3), mesh%sb%rlattice(1, 3), & + mesh%sb%rlattice(3, 2), mesh%sb%rlattice(2, 2), mesh%sb%rlattice(1, 2), & + mesh%sb%rlattice(3, 1), mesh%sb%rlattice(2, 1), mesh%sb%rlattice(1, 1)) + else + call vdwxc_set_unit_cell(this%libvdwxc_ptr, & + this%cube%rs_n_global(3), this%cube%rs_n_global(2), this%cube%rs_n_global(1), & + mesh%spacing(3) * this%cube%rs_n_global(3), 0.0_8, 0.0_8, & + 0.0_8, mesh%spacing(2) * this%cube%rs_n_global(2), 0.0_8, & + 0.0_8, 0.0_8, mesh%spacing(1) * this%cube%rs_n_global(1)) + end if if(libvdwxc_mode == LIBVDWXC_MODE_SERIAL) then call vdwxc_init_serial(this%libvdwxc_ptr) else -#ifdef HAVE_MPI +#ifdef HAVE_LIBVDWXC_MPI call vdwxc_init_mpi(this%libvdwxc_ptr, mesh%mpi_grp%comm) +#else + message(1) = "libvdwxc was not compiled with MPI" + message(2) = "Recompile libvdwxc with MPI for vdW with domain decomposition" + call messages_fatal(2) #endif end if call vdwxc_print(this%libvdwxc_ptr) @@ -279,7 +231,7 @@ contains #ifdef HAVE_MPI integer :: ierr #endif - + PUSH_SUB(libvdwxc_calculate) ASSERT(size(rho, 2) == 1) diff --git a/testsuite/functionals/13-vdw_df_cx_h2o.inp b/testsuite/functionals/13-vdw_df_cx_h2o.inp new file mode 100644 index 0000000000000000000000000000000000000000..6bead9a5b794507373d3b4664fb28db864e75836 --- /dev/null +++ b/testsuite/functionals/13-vdw_df_cx_h2o.inp @@ -0,0 +1,8 @@ +XCFunctional = vdw_c_vdwdfcx + gga_x_lv_rpw86 +ExperimentalFeatures = yes + +%Coordinates + 'O' | 0.0 | 0.0 | 0.119 * angstrom + 'H' | 0.0 | 0.763 * angstrom | -0.477 * angstrom + 'H' | 0.0 | -0.763 * angstrom | -0.477 * angstrom +% diff --git a/testsuite/functionals/13-vdw_df_cx_h2o.test b/testsuite/functionals/13-vdw_df_cx_h2o.test new file mode 100644 index 0000000000000000000000000000000000000000..1544131b9f7de1f894a184544d0e828ba2a77ba9 --- /dev/null +++ b/testsuite/functionals/13-vdw_df_cx_h2o.test @@ -0,0 +1,11 @@ +Test : vdW-DF-cx with libvdwxc - H2O +Program : octopus +Options : libvdwxc +TestGroups : short-run, functionals, libvdwxc +Enabled : Yes + +Input : 13-vdw_df_cx_h2o.inp + +match ; Total energy ; GREPFIELD(static/info, 'Total =', 3) ; -17.11611752 +match ; Exchange energy ; GREPFIELD(static/info, 'Exchange =', 3) ; -3.80140067 +match ; Correlation energy ; GREPFIELD(static/info, 'Correlation =', 3) ; -0.38368351 diff --git a/testsuite/functionals/14-vdw_df_cx_be_hcp.inp b/testsuite/functionals/14-vdw_df_cx_be_hcp.inp new file mode 100644 index 0000000000000000000000000000000000000000..beab871319596817e42646f42629288d352920cc --- /dev/null +++ b/testsuite/functionals/14-vdw_df_cx_be_hcp.inp @@ -0,0 +1,22 @@ +%LatticeVectors + 4.327472828166566 | 0.0 | 0.0 + -2.163736414083283 | 3.747701403379137 | 0.0 + 0.0 | 0.0 | 6.781149921737009 +% + +PeriodicDimensions = 3 +ParKPoints = False +ExperimentalFeatures = True +Spacing = 0.15 * angstrom +XCFunctional = vdw_c_vdwdfcx + gga_x_lv_rpw86 +PseudopotentialSet = sg15 + +%KPointsGrid + 2 | 2 | 2 +% + + +%Coordinates + 'Be' | -1.0818682070416414 | -1.8738507016895685 | -3.3905749608685043 + 'Be' | -1.0818682070416414 | 0.6246169005631896 | 0.0 +% diff --git a/testsuite/functionals/14-vdw_df_cx_be_hcp.test b/testsuite/functionals/14-vdw_df_cx_be_hcp.test new file mode 100644 index 0000000000000000000000000000000000000000..9375be93e14ce85ab3986154dc39171283120f4f --- /dev/null +++ b/testsuite/functionals/14-vdw_df_cx_be_hcp.test @@ -0,0 +1,11 @@ +Test : vdW-DF-cx with libvdwxc - H2O +Program : octopus +Options : libvdwxc +TestGroups : short-run, functionals, libvdwxc +Enabled : Yes + +Input : 14-vdw_df_cx_be_hcp.inp + +match ; Total energy ; GREPFIELD(static/info, 'Total =', 3) ; -26.58900976 +match ; Exchange energy ; GREPFIELD(static/info, 'Exchange =', 3) ; -3.76910154 +match ; Correlation energy ; GREPFIELD(static/info, 'Correlation =', 3) ; -0.41403236 diff --git a/testsuite/functionals/Makefile.am b/testsuite/functionals/Makefile.am index 0f55d13a0bc459a7585b858cae717f3acbbeec96..877af99a140e5fbacdae702e6b64690e1283d506 100644 --- a/testsuite/functionals/Makefile.am +++ b/testsuite/functionals/Makefile.am @@ -134,7 +134,10 @@ dist_share_DATA = \ 11-vdw_d3.01-gs.inp \ 12-vdw_solid_c6.test \ 12-vdw_solid_c6.01-gs_diamond.inp \ - 12-vdw_solid_c6.02-gs_graphene.inp - + 12-vdw_solid_c6.02-gs_graphene.inp \ + 13-vdw_df_cx_h2o.test \ + 13-vdw_df_cx_h2o.inp \ + 14-vdw_df_cx_be_hcp.test \ + 14-vdw_df_cx_be_hcp.inp CLEANFILES = *~ *.bak