32  integer, 
parameter ::       &
 
   33    LIBVDWXC_MODE_AUTO = 1,   &
 
   51    integer, 
pointer               :: libvdwxc_ptr
 
   54    type(mesh_cube_parallel_map_t) :: mesh_cube_map
 
   57    real(real64), 
public                  :: energy
 
   58    real(real64)                   :: vdw_factor
 
   62  include 
"vdwxcfort.f90" 
   68    type(libvdwxc_t),          
intent(out) :: libvdwxc
 
   69    type(namespace_t),         
intent(in)  :: namespace
 
   70    integer,                   
intent(in)  :: functional
 
   74    call vdwxc_new(functional, libvdwxc%libvdwxc_ptr)
 
   76    message(1) = 
"Octopus not compiled with libvdwxc" 
   79    assert(
associated(libvdwxc%libvdwxc_ptr))
 
   80    libvdwxc%functional = functional
 
   88    call parse_variable(namespace, 
'libvdwxcDebug', .false., libvdwxc%debug)
 
  103    type(libvdwxc_t), 
intent(in) :: this
 
  107    call vdwxc_print(this%libvdwxc_ptr)
 
  114    type(libvdwxc_t),            
intent(in) :: this
 
  115    integer,           
optional, 
intent(in) :: iunit
 
  116    type(namespace_t), 
optional, 
intent(in) :: namespace
 
  120    write(
message(1), 
'(2x,a)') 
'Correlation' 
  121    if (this%functional == 1) 
then 
  122      write(
message(2), 
'(4x,a)') 
'vdW-DF from libvdwxc' 
  123    else if (this%functional == 2) 
then 
  124      write(
message(2), 
'(4x,a)') 
'vdW-DF2 from libvdwxc' 
  125    else if (this%functional == 3) 
then 
  126      write(
message(2), 
'(4x,a)') 
'vdW-DF-cx from libvdwxc' 
  128      write(
message(2), 
'(4x,a)') 
'unknown libvdwxc functional' 
  138    class(
space_t),    
intent(in)    :: space
 
  139    class(
mesh_t),     
intent(in)    :: mesh
 
  142    integer :: libvdwxc_mode
 
  143    type(space_t) :: cube_space
 
  155    libvdwxc_mode = libvdwxc_mode_auto
 
  171    call parse_variable(namespace, 
'libvdwxcMode', libvdwxc_mode_auto, libvdwxc_mode)
 
  173    if (libvdwxc_mode == libvdwxc_mode_auto) 
then 
  174      if (mesh%mpi_grp%size == 1) 
then 
  183    blocksize = mesh%idx%ll(3) / mesh%mpi_grp%size
 
  184    if (mod(mesh%idx%ll(3), mesh%mpi_grp%size) /= 0) 
then 
  185      blocksize = blocksize + 1
 
  190    cube_space%dim = space%dim
 
  191    cube_space%periodic_dim = space%dim
 
  194      call cube_init(this%cube, mesh%idx%ll, namespace, cube_space, mesh%spacing, &
 
  198      call cube_init(this%cube, mesh%idx%ll, namespace, cube_space, mesh%spacing, &
 
  199        mesh%coord_system, mpi_grp = mesh%mpi_grp, &
 
  200        need_partition = .
true., blocksize = blocksize)
 
  210    call vdwxc_set_unit_cell(this%libvdwxc_ptr, &
 
  211      this%cube%rs_n_global(3), this%cube%rs_n_global(2), this%cube%rs_n_global(1), &
 
  212      this%cube%latt%rlattice(3, 3), this%cube%latt%rlattice(2, 3), this%cube%latt%rlattice(1, 3), &
 
  213      this%cube%latt%rlattice(3, 2), this%cube%latt%rlattice(2, 2), this%cube%latt%rlattice(1, 2), &
 
  214      this%cube%latt%rlattice(3, 1), this%cube%latt%rlattice(2, 1), this%cube%latt%rlattice(1, 1))
 
  217      call vdwxc_init_serial(this%libvdwxc_ptr)
 
  219#ifdef HAVE_LIBVDWXC_MPI 
  220      call vdwxc_init_mpi(this%libvdwxc_ptr, mesh%mpi_grp%comm%MPI_VAL)
 
  222      message(1) = 
"libvdwxc was not compiled with MPI" 
  223      message(2) = 
"Recompile libvdwxc with MPI for vdW with domain decomposition" 
  227    call vdwxc_print(this%libvdwxc_ptr)
 
  236    class(
space_t),                       
intent(in)    :: space
 
  237    real(real64), 
dimension(:,:),   
contiguous,  
intent(inout) :: rho 
 
  238    real(real64), 
dimension(:,:,:), 
contiguous,  
intent(in)    :: gradrho
 
  239    real(real64), 
dimension(:,:),   
contiguous,  
intent(inout) :: dedd
 
  240    real(real64), 
dimension(:,:,:), 
contiguous,  
intent(inout) :: dedgd
 
  244    real(real64), 
allocatable :: workbuffer(:)
 
  245    real(real64), 
allocatable :: cube_rho(:,:,:), cube_sigma(:,:,:), cube_dedrho(:,:,:), cube_dedsigma(:,:,:)
 
  246    real(real64), 
dimension(3) :: energy_and_integrals_buffer
 
  251    assert(
size(rho, 2) == 1)
 
  252    assert(
size(gradrho, 3) == 1)
 
  253    assert(
size(dedd, 2) == 1)
 
  254    assert(
size(dedgd, 3) == 1)
 
  280    safe_allocate(workbuffer(1:this%mesh%np))
 
  281    safe_allocate(cube_rho(1:this%cube%rs_n(1), 1:this%cube%rs_n(2), 1:this%cube%rs_n(3)))
 
  282    safe_allocate(cube_sigma(1:this%cube%rs_n(1), 1:this%cube%rs_n(2), 1:this%cube%rs_n(3)))
 
  283    safe_allocate(cube_dedrho(1:this%cube%rs_n(1), 1:this%cube%rs_n(2), 1:this%cube%rs_n(3)))
 
  284    safe_allocate(cube_dedsigma(1:this%cube%rs_n(1), 1:this%cube%rs_n(2), 1:this%cube%rs_n(3)))
 
  286    workbuffer(:) = sum(gradrho(:, :, 1)**2, 2)
 
  300    call tocube(rho(:, 1), cube_rho)
 
  301    call tocube(workbuffer, cube_sigma)
 
  305    call vdwxc_calculate(this%libvdwxc_ptr, cube_rho, cube_sigma, cube_dedrho, cube_dedsigma, this%energy)
 
  307    this%energy = this%energy * this%vdw_factor
 
  308    cube_dedrho = cube_dedrho * this%vdw_factor
 
  309    cube_dedsigma = cube_dedsigma * this%vdw_factor
 
  311    call fromcube(cube_dedrho, workbuffer)
 
  316    dedd(1:this%mesh%np, 1) = dedd(1:this%mesh%np, 1) + workbuffer
 
  317    call fromcube(cube_dedsigma, workbuffer)
 
  321    do ii = 1, this%mesh%np
 
  322      dedgd(ii, :, 1) = dedgd(ii, :, 1) + 
m_two * workbuffer(ii) * gradrho(ii, :, 1)
 
  325    energy_and_integrals_buffer(1) = this%energy
 
  326    energy_and_integrals_buffer(2) = sum(rho(1:this%mesh%np,:) * dedd(1:this%mesh%np,:)) * this%mesh%volume_element
 
  327    energy_and_integrals_buffer(3) = sum(gradrho(1:this%mesh%np,:,:) * dedgd(1:this%mesh%np,:,:)) * this%mesh%volume_element
 
  329    call this%mesh%mpi_grp%allreduce_inplace(energy_and_integrals_buffer(1), 3, mpi_double_precision, mpi_sum)
 
  330    this%energy = energy_and_integrals_buffer(1)
 
  331    write(
message(1), 
'(a,f18.10,a)') 
'libvdwxc non-local correlation energy: ', energy_and_integrals_buffer(1), 
' Ha' 
  332    write(
message(2), 
'(a,f18.10)')   
'                      n-dedn integral: ', energy_and_integrals_buffer(2)
 
  333    write(
message(3), 
'(a,f18.10)')   
'              gradn-dedgradn integral: ', energy_and_integrals_buffer(3)
 
  336    safe_deallocate_a(workbuffer)
 
  337    safe_deallocate_a(cube_rho)
 
  338    safe_deallocate_a(cube_sigma)
 
  339    safe_deallocate_a(cube_dedrho)
 
  340    safe_deallocate_a(cube_dedsigma)
 
  347    subroutine tocube(array, cubearray)
 
  348      real(real64), 
contiguous,     
intent(in)    :: array(:)
 
  349      real(real64),          
intent(out)   :: cubearray(:,:,:)
 
  353      if (this%cube%parallel_in_domains) 
then 
  358      cubearray(:,:,:) = cf%dRS
 
  362    subroutine fromcube(cubearray, array)
 
  363      real(real64),          
intent(in)  :: cubearray(:,:,:)
 
  364      real(real64), 
contiguous,     
intent(out) :: array(:)
 
  368      if (this%cube%parallel_in_domains) 
then 
  377      real(real64),     
intent(in) :: arr(:)
 
  378      character(len=*), 
intent(in) :: fname
 
  382        fname, namespace, space, this%mesh, arr, 
unit_one, ierr)
 
  392    call vdwxc_finalize(this%libvdwxc_ptr)
 
subroutine libvdwxc_write_array(arr, fname)
 
subroutine fromcube(cubearray, array)
 
subroutine tocube(array, cubearray)
 
subroutine, public dmesh_to_cube(mesh, mf, cube, cf)
The next two subroutines convert a function between the normal mesh and the cube.
 
subroutine, public dcube_to_mesh(cube, cf, mesh, mf)
 
subroutine, public dcube_function_alloc_rs(cube, cf, in_device, force_alloc)
Allocates locally the real space grid, if PFFT library is not used. Otherwise, it assigns the PFFT re...
 
subroutine, public dcube_function_free_rs(cube, cf)
Deallocates the real space grid.
 
subroutine, public dmesh_to_cube_parallel(mesh, mf, cube, cf, map)
The next two subroutines convert a function between the normal mesh and the cube in parallel.
 
subroutine, public dcube_to_mesh_parallel(cube, cf, mesh, mf, map)
 
subroutine, public cube_init(cube, nn, namespace, space, spacing, coord_system, fft_type, fft_library, dont_optimize, nn_out, mpi_grp, need_partition, tp_enlarge, blocksize)
 
subroutine, public cube_end(cube)
 
subroutine, public cube_init_cube_map(cube, mesh)
 
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
 
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
 
real(real64), parameter, public m_two
 
real(real64), parameter, public m_zero
 
real(real64), parameter, public m_one
 
This module implements the underlying real-space grid.
 
subroutine, public dio_function_output(how, dir, fname, namespace, space, mesh, ff, unit, ierr, pos, atoms, grp, root)
 
subroutine, public libvdwxc_end(this)
 
subroutine, public libvdwxc_init(libvdwxc, namespace, functional)
 
subroutine, public libvdwxc_write_info(this, iunit, namespace)
 
integer, parameter libvdwxc_mode_serial
 
integer, parameter libvdwxc_mode_mpi
 
subroutine, public libvdwxc_print(this)
 
subroutine, public libvdwxc_set_geometry(this, namespace, space, mesh)
 
subroutine, public libvdwxc_calculate(this, namespace, space, rho, gradrho, dedd, dedgd)
 
subroutine, public mesh_cube_parallel_map_end(this)
 
subroutine, public mesh_cube_parallel_map_init(this, mesh, cube)
 
This module defines the meshes, which are used in Octopus.
 
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
 
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
 
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
 
The low level module to work with the PFFT library. http:
 
This module defines the unit system, used for input and output.
 
type(unit_t), public unit_one
some special units required for particular quantities
 
Describes mesh distribution to nodes.