mirror of
https://github.com/cp2k/cp2k.git
synced 2026-07-25 04:25:15 -04:00
912 lines
40 KiB
Fortran
912 lines
40 KiB
Fortran
!--------------------------------------------------------------------------------------------------!
|
|
! CP2K: A general program to perform molecular dynamics simulations !
|
|
! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
|
|
! !
|
|
! SPDX-License-Identifier: GPL-2.0-or-later !
|
|
!--------------------------------------------------------------------------------------------------!
|
|
|
|
! **************************************************************************************************
|
|
!> \brief Interface for Voronoi Integration and output of BQB files
|
|
!> \par History
|
|
!> 11/2020 created [mbrehm]
|
|
!> \author Martin Brehm
|
|
! **************************************************************************************************
|
|
MODULE voronoi_interface
|
|
USE input_section_types, ONLY: section_vals_type, &
|
|
section_vals_val_get
|
|
USE cp_log_handling, ONLY: cp_get_default_logger, &
|
|
cp_logger_get_default_io_unit, &
|
|
cp_logger_type
|
|
USE bibliography, ONLY: Rycroft2009, Thomas2015, Brehm2018, Brehm2020, &
|
|
Brehm2021, cite_reference
|
|
USE kinds, ONLY: dp, default_path_length
|
|
USE cell_types, ONLY: cell_type, pbc
|
|
USE pw_types, ONLY: pw_r3d_rs_type
|
|
USE physcon, ONLY: bohr, debye
|
|
USE mathconstants, ONLY: fourpi
|
|
USE orbital_pointers, ONLY: indco
|
|
USE qs_environment_types, ONLY: get_qs_env, &
|
|
qs_environment_type
|
|
USE molecule_kind_types, ONLY: molecule_kind_type, &
|
|
write_molecule_kind_set
|
|
USE molecule_types, ONLY: molecule_type
|
|
USE qs_rho_types, ONLY: qs_rho_get, &
|
|
qs_rho_type
|
|
USE atomic_kind_types, ONLY: atomic_kind_type, &
|
|
get_atomic_kind
|
|
USE particle_list_types, ONLY: particle_list_type
|
|
USE particle_types, ONLY: particle_type
|
|
USE cp_files, ONLY: file_exists, close_file, open_file
|
|
USE qs_kind_types, ONLY: get_qs_kind, &
|
|
qs_kind_type
|
|
USE message_passing, ONLY: mp_para_env_type
|
|
USE qs_subsys_types, ONLY: qs_subsys_get, &
|
|
qs_subsys_type
|
|
USE cp_control_types, ONLY: dft_control_type
|
|
USE pw_grid_types, ONLY: PW_MODE_LOCAL
|
|
USE physcon, ONLY: angstrom, femtoseconds
|
|
USE message_passing, ONLY: mp_comm_type
|
|
USE input_constants, ONLY: &
|
|
voro_radii_unity, voro_radii_vdw, voro_radii_cov, voro_radii_user, &
|
|
bqb_opt_off, bqb_opt_quick, bqb_opt_normal, bqb_opt_patient, bqb_opt_exhaustive, do_method_gapw
|
|
USE qs_rho0_types, ONLY: rho0_atom_type, &
|
|
rho0_mpole_type
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE, C_CHAR
|
|
|
|
#if defined(__HAS_IEEE_EXCEPTIONS)
|
|
USE ieee_exceptions, ONLY: ieee_get_halting_mode, &
|
|
ieee_set_halting_mode, &
|
|
ieee_all
|
|
#endif
|
|
|
|
#include "./base/base_uses.f90"
|
|
|
|
IMPLICIT NONE
|
|
PRIVATE
|
|
|
|
! Global parameters
|
|
CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'voronoi_interface'
|
|
PUBLIC :: entry_voronoi_or_bqb, finalize_libvori
|
|
INTEGER :: step_count = 0
|
|
|
|
#if defined(__LIBVORI)
|
|
|
|
! The C interface to libvori
|
|
|
|
INTERFACE
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setBQBSkipFirst(i) BIND(C, NAME='libvori_setBQBSkipFirst')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setBQBSkipFirst
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setBQBStoreStep(i) BIND(C, NAME='libvori_setBQBStoreStep')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setBQBStoreStep
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setVoronoiSkipFirst(i) BIND(C, NAME='libvori_setVoronoiSkipFirst')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setVoronoiSkipFirst
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setBQBCheck(i) BIND(C, NAME='libvori_setBQBCheck')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setBQBCheck
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setBQBFilename(len, s) BIND(C, NAME='libvori_setBQBFilename')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_CHAR
|
|
INTEGER(C_INT), VALUE :: len
|
|
CHARACTER(C_CHAR) :: s(*)
|
|
|
|
END FUNCTION libvori_setBQBFilename
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setBQBParmString(len, s) BIND(C, NAME='libvori_setBQBParmString')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_CHAR
|
|
INTEGER(C_INT), VALUE :: len
|
|
CHARACTER(C_CHAR) :: s(*)
|
|
|
|
END FUNCTION libvori_setBQBParmString
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setBQBHistory(i) BIND(C, NAME='libvori_setBQBHistory')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setBQBHistory
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setBQBOptimization(i) BIND(C, NAME='libvori_setBQBOptimization')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setBQBOptimization
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_processBQBFrame(step, t) BIND(C, NAME='libvori_processBQBFrame')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: step
|
|
REAL(C_DOUBLE), VALUE :: t
|
|
|
|
END FUNCTION libvori_processBQBFrame
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setPrefix_Voronoi() BIND(C, NAME='libvori_setPrefix_Voronoi')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
END FUNCTION libvori_setPrefix_Voronoi
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setPrefix_BQB() BIND(C, NAME='libvori_setPrefix_BQB')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
END FUNCTION libvori_setPrefix_BQB
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setRefinementFactor(i) BIND(C, NAME='libvori_setRefinementFactor')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setRefinementFactor
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setJitter(i) BIND(C, NAME='libvori_setJitter')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setJitter
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setJitterAmplitude(amp) BIND(C, NAME='libvori_setJitterAmplitude')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
REAL(C_DOUBLE), VALUE :: amp
|
|
|
|
END FUNCTION libvori_setJitterAmplitude
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setJitterSeed(seed) BIND(C, NAME='libvori_setJitterSeed')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: seed
|
|
|
|
END FUNCTION libvori_setJitterSeed
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setEMPOutput(i) BIND(C, NAME='libvori_setEMPOutput')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setEMPOutput
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setPrintLevel_Verbose() BIND(C, NAME='libvori_setPrintLevel_Verbose')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
END FUNCTION libvori_setPrintLevel_Verbose
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setRadii_Unity() BIND(C, NAME='libvori_setRadii_Unity')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
END FUNCTION libvori_setRadii_Unity
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setRadii_Covalent() BIND(C, NAME='libvori_setRadii_Covalent')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
END FUNCTION libvori_setRadii_Covalent
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setRadii_User(factor, rad) BIND(C, NAME='libvori_setRadii_User')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
REAL(C_DOUBLE), VALUE :: factor
|
|
REAL(C_DOUBLE) :: rad(*)
|
|
|
|
END FUNCTION libvori_setRadii_User
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_step(step, t) BIND(C, NAME='libvori_step')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: step
|
|
REAL(C_DOUBLE), VALUE :: t
|
|
|
|
END FUNCTION libvori_step
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_sanitycheck(step, t) BIND(C, NAME='libvori_sanitycheck')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: step
|
|
REAL(C_DOUBLE), VALUE :: t
|
|
|
|
END FUNCTION libvori_sanitycheck
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setGrid(rx, ry, rz, ax, ay, az, bx, by, bz, cx, cy, cz, tax, tay, taz, tbx, tby, tbz, &
|
|
tcx, tcy, tcz) BIND(C, NAME='libvori_setGrid')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: rx, ry, rz
|
|
REAL(C_DOUBLE), VALUE :: ax, ay, az, bx, by, bz, cx, cy, cz, tax, &
|
|
tay, taz, tbx, tby, tbz, tcx, tcy, tcz
|
|
|
|
END FUNCTION libvori_setGrid
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_pushAtoms(n, pord, pchg, posx, posy, posz) BIND(C, NAME='libvori_pushAtoms')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: n
|
|
INTEGER(C_INT) :: pord(*)
|
|
REAL(C_DOUBLE) :: pchg(*), posx(*), posy(*), posz(*)
|
|
|
|
END FUNCTION libvori_pushAtoms
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_push_rho_zrow(ix, iy, length, buf) BIND(C, NAME='libvori_push_rho_zrow')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: ix, iy, length
|
|
REAL(C_DOUBLE) :: buf(*)
|
|
|
|
END FUNCTION libvori_push_rho_zrow
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setBQBOverwrite(i) BIND(C, NAME='libvori_setBQBOverwrite')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setBQBOverwrite
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_setVoriOverwrite(i) BIND(C, NAME='libvori_setVoriOverwrite')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
INTEGER(C_INT), VALUE :: i
|
|
|
|
END FUNCTION libvori_setVoriOverwrite
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_get_radius(length, buf) BIND(C, NAME='libvori_get_radius')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: length
|
|
REAL(C_DOUBLE) :: buf(*)
|
|
|
|
END FUNCTION libvori_get_radius
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_get_volume(length, buf) BIND(C, NAME='libvori_get_volume')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: length
|
|
REAL(C_DOUBLE) :: buf(*)
|
|
|
|
END FUNCTION libvori_get_volume
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_get_charge(length, buf) BIND(C, NAME='libvori_get_charge')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: length
|
|
REAL(C_DOUBLE) :: buf(*)
|
|
|
|
END FUNCTION libvori_get_charge
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_get_dipole(component, length, buf) BIND(C, NAME='libvori_get_dipole')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: component, length
|
|
REAL(C_DOUBLE) :: buf(*)
|
|
|
|
END FUNCTION libvori_get_dipole
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_get_quadrupole(component, length, buf) BIND(C, NAME='libvori_get_quadrupole')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: component, length
|
|
REAL(C_DOUBLE) :: buf(*)
|
|
|
|
END FUNCTION libvori_get_quadrupole
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_get_wrapped_pos(component, length, buf) BIND(C, NAME='libvori_get_wrapped_pos')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: component, length
|
|
REAL(C_DOUBLE) :: buf(*)
|
|
|
|
END FUNCTION libvori_get_wrapped_pos
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_get_charge_center(component, length, buf) BIND(C, NAME='libvori_get_charge_center')
|
|
USE ISO_C_BINDING, ONLY: C_INT, C_DOUBLE
|
|
INTEGER(C_INT), VALUE :: component, length
|
|
REAL(C_DOUBLE) :: buf(*)
|
|
|
|
END FUNCTION libvori_get_charge_center
|
|
|
|
INTEGER(C_INT) FUNCTION libvori_finalize() BIND(C, NAME='libvori_finalize')
|
|
USE ISO_C_BINDING, ONLY: C_INT
|
|
END FUNCTION libvori_finalize
|
|
|
|
END INTERFACE
|
|
|
|
#endif
|
|
|
|
! **************************************************************************************************
|
|
|
|
CONTAINS
|
|
|
|
! **************************************************************************************************
|
|
!> \brief Does a Voronoi integration of density or stores the density to compressed BQB format
|
|
!> \param do_voro whether a Voronoi integration shall be performed
|
|
!> \param do_bqb whether the density shall be written to compressed BQB format
|
|
!> \param input_voro the input section for Voronoi integration
|
|
!> \param input_bqb the input section for the BQB compression
|
|
!> \param unit_voro the output unit number for the Voronoi integration results
|
|
!> \param qs_env the qs_env where to calculate the charges
|
|
!> \param rspace_pw the grid with the real-space electron density to integrate/compress
|
|
!> \author Martin Brehm
|
|
! **************************************************************************************************
|
|
SUBROUTINE entry_voronoi_or_bqb(do_voro, do_bqb, input_voro, input_bqb, unit_voro, qs_env, rspace_pw)
|
|
INTEGER :: do_voro, do_bqb
|
|
TYPE(section_vals_type), POINTER :: input_voro, input_bqb
|
|
INTEGER, INTENT(IN) :: unit_voro
|
|
TYPE(qs_environment_type), POINTER :: qs_env
|
|
TYPE(pw_r3d_rs_type) :: rspace_pw
|
|
|
|
#if defined(__LIBVORI)
|
|
|
|
CHARACTER(len=*), PARAMETER :: routineN = 'entry_voronoi_or_bqb'
|
|
INTEGER :: handle, iounit, &
|
|
ret, i, tag, &
|
|
nkind, natom, ikind, iat, ord, source, dest, &
|
|
ip, i1, i2, reffac, radius_type, bqb_optimize, &
|
|
bqb_history, nspins, jitter_seed
|
|
LOGICAL :: outemp, bqb_skip_first, voro_skip_first, &
|
|
bqb_store_step, bqb_check, voro_sanity, &
|
|
bqb_overwrite, vori_overwrite, molprop, &
|
|
gapw, jitter
|
|
REAL(KIND=dp) :: zeff, qa, fn0, fn1, jitter_amplitude
|
|
TYPE(qs_rho_type), POINTER :: rho
|
|
TYPE(cp_logger_type), POINTER :: logger
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: buf
|
|
INTEGER, ALLOCATABLE, DIMENSION(:) :: particles_z
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: particles_r
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: particles_c
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: particles_radius
|
|
TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
|
|
TYPE(atomic_kind_type), POINTER :: atomic_kind
|
|
TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
|
|
TYPE(mp_para_env_type), POINTER :: para_env
|
|
TYPE(particle_list_type), POINTER :: particles
|
|
REAL(KIND=dp) :: r
|
|
TYPE(qs_subsys_type), POINTER :: subsys
|
|
INTEGER, DIMENSION(:), POINTER :: atom_list
|
|
TYPE(dft_control_type), POINTER :: dft_control
|
|
TYPE(cell_type), POINTER :: cell
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: voro_radii
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: voro_charge
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: voro_volume
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: voro_dipole
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: voro_quadrupole
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: voro_buffer
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: voro_wrapped_pos
|
|
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: voro_charge_center
|
|
REAL(KIND=dp), DIMENSION(:), POINTER :: user_radii
|
|
CHARACTER(len=default_path_length) :: bqb_file_name, mp_file_name
|
|
CHARACTER(len=128) :: bqb_parm_string
|
|
TYPE(rho0_mpole_type), POINTER :: rho0_mpole
|
|
#if defined(__HAS_IEEE_EXCEPTIONS)
|
|
LOGICAL, DIMENSION(5) :: halt
|
|
#endif
|
|
|
|
CALL timeset(routineN, handle)
|
|
NULLIFY (logger)
|
|
logger => cp_get_default_logger()
|
|
iounit = cp_logger_get_default_io_unit(logger)
|
|
|
|
CALL get_qs_env(qs_env=qs_env, rho=rho, qs_kind_set=qs_kind_set, &
|
|
atomic_kind_set=atomic_kind_set, para_env=para_env, &
|
|
nkind=nkind, natom=natom, subsys=subsys, dft_control=dft_control, &
|
|
cell=cell)
|
|
|
|
tag = 1
|
|
|
|
IF (do_voro /= 0) THEN
|
|
CALL section_vals_val_get(input_voro, "REFINEMENT_FACTOR", i_val=reffac)
|
|
CALL section_vals_val_get(input_voro, "OUTPUT_EMP", l_val=outemp)
|
|
CALL section_vals_val_get(input_voro, "JITTER", l_val=jitter)
|
|
CALL section_vals_val_get(input_voro, "JITTER_AMPLITUDE", r_val=jitter_amplitude)
|
|
CALL section_vals_val_get(input_voro, "JITTER_SEED", i_val=jitter_seed)
|
|
CALL section_vals_val_get(input_voro, "VORONOI_RADII", i_val=radius_type)
|
|
CALL section_vals_val_get(input_voro, "SKIP_FIRST", l_val=voro_skip_first)
|
|
CALL section_vals_val_get(input_voro, "SANITY_CHECK", l_val=voro_sanity)
|
|
CALL section_vals_val_get(input_voro, "OVERWRITE", l_val=vori_overwrite)
|
|
IF (radius_type == voro_radii_user) THEN
|
|
CALL section_vals_val_get(input_voro, "USER_RADII", r_vals=user_radii)
|
|
END IF
|
|
IF (qs_env%single_point_run) THEN
|
|
voro_skip_first = .FALSE.
|
|
END IF
|
|
CALL cite_reference(Rycroft2009)
|
|
CALL cite_reference(Thomas2015)
|
|
CALL cite_reference(Brehm2018)
|
|
CALL cite_reference(Brehm2020)
|
|
CALL cite_reference(Brehm2021)
|
|
!
|
|
CALL section_vals_val_get(input_voro, "MOLECULAR_PROPERTIES", l_val=molprop)
|
|
CALL section_vals_val_get(input_voro, "MOLPROP_FILE_NAME", c_val=mp_file_name)
|
|
END IF
|
|
|
|
IF (do_bqb /= 0) THEN
|
|
CALL section_vals_val_get(input_bqb, "HISTORY", i_val=bqb_history)
|
|
CALL section_vals_val_get(input_bqb, "OPTIMIZE", i_val=bqb_optimize)
|
|
CALL section_vals_val_get(input_bqb, "FILENAME", c_val=bqb_file_name)
|
|
CALL section_vals_val_get(input_bqb, "SKIP_FIRST", l_val=bqb_skip_first)
|
|
CALL section_vals_val_get(input_bqb, "STORE_STEP_NUMBER", l_val=bqb_store_step)
|
|
CALL section_vals_val_get(input_bqb, "CHECK", l_val=bqb_check)
|
|
CALL section_vals_val_get(input_bqb, "OVERWRITE", l_val=bqb_overwrite)
|
|
CALL section_vals_val_get(input_bqb, "PARAMETER_KEY", c_val=bqb_parm_string)
|
|
IF (qs_env%single_point_run) THEN
|
|
bqb_skip_first = .FALSE.
|
|
bqb_history = 1
|
|
END IF
|
|
IF (bqb_history < 1) THEN
|
|
bqb_history = 1
|
|
END IF
|
|
CALL cite_reference(Brehm2018)
|
|
END IF
|
|
|
|
CALL qs_subsys_get(subsys, particles=particles)
|
|
|
|
! Temporarily disable floating point traps because libvori raise IEEE754 exceptions.
|
|
#if defined(__HAS_IEEE_EXCEPTIONS)
|
|
CALL ieee_get_halting_mode(IEEE_ALL, halt)
|
|
CALL ieee_set_halting_mode(IEEE_ALL, .FALSE.)
|
|
#endif
|
|
|
|
ASSOCIATE (ionode => para_env%is_source(), my_rank => para_env%mepos, &
|
|
num_pe => para_env%num_pe, &
|
|
sim_step => qs_env%sim_step, sim_time => qs_env%sim_time, &
|
|
L1 => rspace_pw%pw_grid%bounds(1, 1), L2 => rspace_pw%pw_grid%bounds(1, 2), &
|
|
L3 => rspace_pw%pw_grid%bounds(1, 3), U1 => rspace_pw%pw_grid%bounds(2, 1), &
|
|
U2 => rspace_pw%pw_grid%bounds(2, 2), U3 => rspace_pw%pw_grid%bounds(2, 3))
|
|
IF (ionode) THEN
|
|
|
|
IF (iounit > 0) THEN
|
|
WRITE (iounit, *) ""
|
|
END IF
|
|
|
|
IF (do_voro /= 0) THEN
|
|
ret = libvori_setPrefix_Voronoi()
|
|
ret = libvori_setRefinementFactor(reffac)
|
|
ret = libvori_setJitter(MERGE(1, 0, jitter))
|
|
ret = libvori_setJitterAmplitude(jitter_amplitude*angstrom)
|
|
ret = libvori_setJitterSeed(jitter_seed)
|
|
ret = libvori_setVoronoiSkipFirst(MERGE(1, 0, voro_skip_first))
|
|
ret = libvori_setVoriOverwrite(MERGE(1, 0, vori_overwrite))
|
|
ret = libvori_setEMPOutput(MERGE(1, 0, outemp))
|
|
ELSE
|
|
ret = libvori_setPrefix_BQB()
|
|
END IF
|
|
|
|
IF (do_bqb /= 0) THEN
|
|
ret = libvori_setBQBFilename(default_path_length, bqb_file_name)
|
|
ret = libvori_setBQBParmString(128, bqb_parm_string)
|
|
SELECT CASE (bqb_optimize)
|
|
CASE (bqb_opt_off)
|
|
bqb_optimize = 0
|
|
CASE (bqb_opt_quick)
|
|
bqb_optimize = 1
|
|
CASE (bqb_opt_normal)
|
|
bqb_optimize = 2
|
|
CASE (bqb_opt_patient)
|
|
bqb_optimize = 3
|
|
CASE (bqb_opt_exhaustive)
|
|
bqb_optimize = 4
|
|
END SELECT
|
|
ret = libvori_setBQBOptimization(bqb_optimize)
|
|
ret = libvori_setBQBHistory(bqb_history)
|
|
ret = libvori_setBQBSkipFirst(MERGE(1, 0, bqb_skip_first))
|
|
ret = libvori_setBQBCheck(MERGE(1, 0, bqb_check))
|
|
ret = libvori_setBQBOverwrite(MERGE(1, 0, bqb_overwrite))
|
|
ret = libvori_setBQBStoreStep(MERGE(1, 0, bqb_store_step))
|
|
END IF
|
|
|
|
ret = libvori_setgrid( &
|
|
U1 - L1 + 1, &
|
|
U2 - L2 + 1, &
|
|
U3 - L3 + 1, &
|
|
rspace_pw%pw_grid%dh(1, 1)*(U1 - L1 + 1), &
|
|
rspace_pw%pw_grid%dh(2, 1)*(U1 - L1 + 1), &
|
|
rspace_pw%pw_grid%dh(3, 1)*(U1 - L1 + 1), &
|
|
rspace_pw%pw_grid%dh(1, 2)*(U2 - L2 + 1), &
|
|
rspace_pw%pw_grid%dh(2, 2)*(U2 - L2 + 1), &
|
|
rspace_pw%pw_grid%dh(3, 2)*(U2 - L2 + 1), &
|
|
rspace_pw%pw_grid%dh(1, 3)*(U3 - L3 + 1), &
|
|
rspace_pw%pw_grid%dh(2, 3)*(U3 - L3 + 1), &
|
|
rspace_pw%pw_grid%dh(3, 3)*(U3 - L3 + 1), &
|
|
cell%hmat(1, 1), &
|
|
cell%hmat(2, 1), &
|
|
cell%hmat(3, 1), &
|
|
cell%hmat(1, 2), &
|
|
cell%hmat(2, 2), &
|
|
cell%hmat(3, 2), &
|
|
cell%hmat(1, 3), &
|
|
cell%hmat(2, 3), &
|
|
cell%hmat(3, 3) &
|
|
)
|
|
|
|
IF (ret /= 0) THEN
|
|
CPABORT("The library returned an error. Aborting.")
|
|
END IF
|
|
|
|
ALLOCATE (particles_z(natom))
|
|
ALLOCATE (particles_c(natom))
|
|
ALLOCATE (particles_r(3, natom))
|
|
ALLOCATE (particles_radius(natom))
|
|
|
|
DO ikind = 1, nkind
|
|
CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff, vdw_radius=r)
|
|
r = r*angstrom
|
|
atomic_kind => atomic_kind_set(ikind)
|
|
CALL get_atomic_kind(atomic_kind, atom_list=atom_list, z=ord)
|
|
DO iat = 1, SIZE(atom_list)
|
|
i = atom_list(iat)
|
|
particles_c(i) = zeff
|
|
particles_z(i) = ord
|
|
particles_r(:, i) = particles%els(i)%r(:)
|
|
particles_radius(i) = r
|
|
END DO
|
|
END DO
|
|
|
|
ret = libvori_pushatoms(natom, particles_z, particles_c, particles_r(1, :), particles_r(2, :), particles_r(3, :))
|
|
|
|
IF (ret /= 0) THEN
|
|
CPABORT("The library returned an error. Aborting.")
|
|
END IF
|
|
|
|
END IF
|
|
|
|
IF (iounit > 0) THEN
|
|
IF (do_voro /= 0) THEN
|
|
WRITE (iounit, *) "VORONOI| Collecting electron density from MPI ranks and sending to library..."
|
|
ELSE
|
|
WRITE (iounit, *) "BQB| Collecting electron density from MPI ranks and sending to library..."
|
|
END IF
|
|
END IF
|
|
|
|
ALLOCATE (buf(L3:U3))
|
|
|
|
dest = 0
|
|
|
|
DO I1 = L1, U1
|
|
DO I2 = L2, U2
|
|
|
|
! cycling through the CPUs, check if the current ray (I1,I2) is local to that CPU
|
|
IF (rspace_pw%pw_grid%para%mode .NE. PW_MODE_LOCAL) THEN
|
|
DO ip = 0, num_pe - 1
|
|
IF (rspace_pw%pw_grid%para%bo(1, 1, ip, 1) <= I1 - L1 + 1 &
|
|
.AND. rspace_pw%pw_grid%para%bo(2, 1, ip, 1) >= I1 - L1 + 1 .AND. &
|
|
rspace_pw%pw_grid%para%bo(1, 2, ip, 1) <= I2 - L2 + 1 &
|
|
.AND. rspace_pw%pw_grid%para%bo(2, 2, ip, 1) >= I2 - L2 + 1) THEN
|
|
source = ip
|
|
END IF
|
|
END DO
|
|
ELSE
|
|
source = dest
|
|
END IF
|
|
|
|
IF (source == dest) THEN
|
|
IF (my_rank == source) THEN
|
|
buf(:) = rspace_pw%array(I1, I2, :)
|
|
END IF
|
|
ELSE
|
|
IF (my_rank == source) THEN
|
|
buf(:) = rspace_pw%array(I1, I2, :)
|
|
CALL para_env%send(buf, dest, tag)
|
|
END IF
|
|
IF (my_rank == dest) THEN
|
|
CALL para_env%recv(buf, source, tag)
|
|
END IF
|
|
END IF
|
|
|
|
IF (my_rank == dest) THEN
|
|
ret = libvori_push_rho_zrow(I1 - L1, I2 - L2, U3 - L3 + 1, buf)
|
|
IF (ret /= 0) THEN
|
|
CPABORT("The library returned an error. Aborting.")
|
|
END IF
|
|
END IF
|
|
|
|
! this double loop generates so many messages that it can overload
|
|
! the message passing system, e.g. on XT3
|
|
! we therefore put a barrier here that limits the amount of message
|
|
! that flies around at any given time.
|
|
! if ever this routine becomes a bottleneck, we should go for a
|
|
! more complicated rewrite
|
|
CALL para_env%sync()
|
|
|
|
END DO
|
|
END DO
|
|
|
|
DEALLOCATE (buf)
|
|
|
|
IF (ionode) THEN
|
|
|
|
gapw = .FALSE.
|
|
IF (dft_control%qs_control%method_id == do_method_gapw) gapw = .TRUE.
|
|
|
|
IF (do_voro /= 0) THEN
|
|
|
|
IF (radius_type == voro_radii_unity) THEN
|
|
ret = libvori_setRadii_Unity()
|
|
ELSE IF (radius_type == voro_radii_cov) THEN
|
|
! Use the covalent radii from LIBVORI
|
|
ret = libvori_setRadii_Covalent()
|
|
ELSE IF (radius_type == voro_radii_vdw) THEN
|
|
! Use the van der Waals radii from CP2K
|
|
ret = libvori_setRadii_User(100.0_dp, particles_radius)
|
|
ELSE IF (radius_type == voro_radii_user) THEN
|
|
! Use the user defined atomic radii
|
|
IF (natom /= SIZE(user_radii)) THEN
|
|
CALL cp_abort(__LOCATION__, &
|
|
"Length of keyword VORONOI\USER_RADII does not "// &
|
|
"match number of atoms in the input coordinate file.")
|
|
END IF
|
|
ret = libvori_setRadii_User(100.0_dp, user_radii)
|
|
ELSE
|
|
CPABORT("No valid radius type was specified for VORONOI")
|
|
END IF
|
|
|
|
IF (voro_sanity) THEN
|
|
|
|
ret = libvori_sanitycheck(sim_step, sim_time)
|
|
|
|
IF (ret /= 0) THEN
|
|
CPABORT("The library returned an error. Aborting.")
|
|
END IF
|
|
|
|
END IF
|
|
|
|
ret = libvori_step(sim_step, sim_time)
|
|
|
|
step_count = step_count + 1
|
|
|
|
IF (ret /= 0) THEN
|
|
CPABORT("The library returned an error. Aborting.")
|
|
END IF
|
|
|
|
IF ((step_count > 1) .OR. (.NOT. voro_skip_first)) THEN
|
|
|
|
ALLOCATE (voro_radii(natom))
|
|
ALLOCATE (voro_charge(natom))
|
|
ALLOCATE (voro_volume(natom))
|
|
ALLOCATE (voro_dipole(natom, 3))
|
|
ALLOCATE (voro_quadrupole(natom, 9))
|
|
ALLOCATE (voro_buffer(natom))
|
|
ALLOCATE (voro_wrapped_pos(natom, 3))
|
|
ALLOCATE (voro_charge_center(natom, 3))
|
|
|
|
ret = libvori_get_radius(natom, voro_radii)
|
|
|
|
ret = libvori_get_charge(natom, voro_charge)
|
|
|
|
ret = libvori_get_volume(natom, voro_volume)
|
|
|
|
DO i1 = 1, 3
|
|
ret = libvori_get_dipole(i1, natom, voro_buffer)
|
|
voro_dipole(:, i1) = voro_buffer(:)
|
|
END DO
|
|
|
|
DO i1 = 1, 9
|
|
ret = libvori_get_quadrupole(i1, natom, voro_buffer)
|
|
voro_quadrupole(:, i1) = voro_buffer(:)
|
|
END DO
|
|
|
|
DO i1 = 1, 3
|
|
ret = libvori_get_wrapped_pos(i1, natom, voro_buffer)
|
|
voro_wrapped_pos(:, i1) = voro_buffer(:)
|
|
END DO
|
|
|
|
DO i1 = 1, 3
|
|
ret = libvori_get_charge_center(i1, natom, voro_buffer)
|
|
voro_charge_center(:, i1) = voro_buffer(:)
|
|
END DO
|
|
|
|
IF (gapw) THEN
|
|
CALL get_qs_env(qs_env=qs_env, rho0_mpole=rho0_mpole)
|
|
nspins = dft_control%nspins
|
|
DO i1 = 1, natom
|
|
voro_charge(i1) = voro_charge(i1) - SUM(rho0_mpole%mp_rho(i1)%Q0(1:nspins))
|
|
fn0 = rho0_mpole%norm_g0l_h(1)/bohr*100._dp
|
|
voro_dipole(i1, 1:3) = voro_dipole(i1, 1:3) + rho0_mpole%mp_rho(i1)%Qlm_car(2:4)/fn0
|
|
qa = voro_charge(i1) - particles_c(i1)
|
|
voro_charge_center(i1, 1:3) = voro_dipole(i1, 1:3)/qa
|
|
fn1 = rho0_mpole%norm_g0l_h(2)/bohr/bohr*10000._dp
|
|
voro_quadrupole(i1, 1) = voro_quadrupole(i1, 1) + rho0_mpole%mp_rho(i1)%Qlm_car(5)/fn1
|
|
voro_quadrupole(i1, 2) = voro_quadrupole(i1, 2) + rho0_mpole%mp_rho(i1)%Qlm_car(6)/fn1
|
|
voro_quadrupole(i1, 3) = voro_quadrupole(i1, 3) + rho0_mpole%mp_rho(i1)%Qlm_car(7)/fn1
|
|
voro_quadrupole(i1, 4) = voro_quadrupole(i1, 4) + rho0_mpole%mp_rho(i1)%Qlm_car(6)/fn1
|
|
voro_quadrupole(i1, 5) = voro_quadrupole(i1, 5) + rho0_mpole%mp_rho(i1)%Qlm_car(8)/fn1
|
|
voro_quadrupole(i1, 6) = voro_quadrupole(i1, 6) + rho0_mpole%mp_rho(i1)%Qlm_car(9)/fn1
|
|
voro_quadrupole(i1, 7) = voro_quadrupole(i1, 7) + rho0_mpole%mp_rho(i1)%Qlm_car(7)/fn1
|
|
voro_quadrupole(i1, 8) = voro_quadrupole(i1, 8) + rho0_mpole%mp_rho(i1)%Qlm_car(9)/fn1
|
|
voro_quadrupole(i1, 9) = voro_quadrupole(i1, 9) + rho0_mpole%mp_rho(i1)%Qlm_car(10)/fn1
|
|
END DO
|
|
END IF
|
|
|
|
IF (unit_voro > 0) THEN
|
|
WRITE (unit_voro, FMT="(T2,I0)") natom
|
|
WRITE (unit_voro, FMT="(A,I8,A,F12.4,A)") "# Step ", sim_step, ", Time ", &
|
|
sim_time*femtoseconds, " fs"
|
|
WRITE (unit_voro, FMT="(A,9F20.10)") "# Cell ", &
|
|
cell%hmat(1, 1)*angstrom, cell%hmat(2, 1)*angstrom, cell%hmat(3, 1)*angstrom, &
|
|
cell%hmat(1, 2)*angstrom, cell%hmat(2, 2)*angstrom, cell%hmat(3, 2)*angstrom, &
|
|
cell%hmat(1, 3)*angstrom, cell%hmat(2, 3)*angstrom, cell%hmat(3, 3)*angstrom
|
|
WRITE (unit_voro, FMT="(A,22A20)") "# Atom Z", &
|
|
"Radius", "Position(X)", "Position(Y)", "Position(Z)", &
|
|
"Voronoi_Volume", "Z(eff)", "Charge", "Dipole(X)", "Dipole(Y)", "Dipole(Z)", &
|
|
"ChargeCenter(X)", "ChargeCenter(Y)", "ChargeCenter(Z)", &
|
|
"Quadrupole(XX)", "Quadrupole(XY)", "Quadrupole(XZ)", &
|
|
"Quadrupole(YX)", "Quadrupole(YY)", "Quadrupole(YZ)", &
|
|
"Quadrupole(ZX)", "Quadrupole(ZY)", "Quadrupole(ZZ)"
|
|
DO i1 = 1, natom
|
|
WRITE (unit_voro, FMT="(2I6,22F20.10)") &
|
|
i1, &
|
|
particles_z(i1), &
|
|
voro_radii(i1)/100.0_dp, &
|
|
particles_r(1:3, i1)*angstrom, &
|
|
voro_volume(i1)/1000000.0_dp, &
|
|
particles_c(i1), &
|
|
voro_charge(i1), &
|
|
voro_dipole(i1, 1:3), &
|
|
voro_charge_center(i1, 1:3)/100.0_dp, &
|
|
voro_quadrupole(i1, 1:9)
|
|
END DO
|
|
END IF
|
|
|
|
IF (molprop) THEN
|
|
CALL molecular_properties(subsys, cell, sim_step, sim_time, iounit, &
|
|
particles_r, particles_c, &
|
|
voro_charge, voro_charge_center, mp_file_name)
|
|
END IF
|
|
|
|
DEALLOCATE (voro_radii)
|
|
DEALLOCATE (voro_charge)
|
|
DEALLOCATE (voro_volume)
|
|
DEALLOCATE (voro_dipole)
|
|
DEALLOCATE (voro_quadrupole)
|
|
DEALLOCATE (voro_buffer)
|
|
DEALLOCATE (voro_wrapped_pos)
|
|
DEALLOCATE (voro_charge_center)
|
|
|
|
END IF ! not skip_first
|
|
|
|
IF (iounit > 0) THEN
|
|
WRITE (iounit, *) "VORONOI| Voronoi integration finished."
|
|
END IF
|
|
|
|
END IF ! do_voro
|
|
|
|
IF (do_bqb /= 0) THEN
|
|
|
|
ret = libvori_processBQBFrame(sim_step, sim_time*femtoseconds)
|
|
|
|
IF (ret /= 0) THEN
|
|
CPABORT("The library returned an error. Aborting.")
|
|
END IF
|
|
|
|
IF (do_voro /= 0) THEN
|
|
IF (iounit > 0) THEN
|
|
WRITE (iounit, *) "VORONOI| BQB compression finished."
|
|
END IF
|
|
ELSE
|
|
IF (iounit > 0) THEN
|
|
WRITE (iounit, *) "BQB| BQB compression finished."
|
|
END IF
|
|
END IF
|
|
|
|
END IF ! do_bqb
|
|
|
|
END IF
|
|
|
|
IF (ionode) THEN
|
|
DEALLOCATE (particles_z)
|
|
DEALLOCATE (particles_c)
|
|
DEALLOCATE (particles_r)
|
|
DEALLOCATE (particles_radius)
|
|
END IF
|
|
END ASSOCIATE
|
|
|
|
#if defined(__HAS_IEEE_EXCEPTIONS)
|
|
CALL ieee_set_halting_mode(IEEE_ALL, halt)
|
|
#endif
|
|
|
|
CALL timestop(handle)
|
|
|
|
#else
|
|
|
|
MARK_USED(do_voro)
|
|
MARK_USED(do_bqb)
|
|
MARK_USED(input_voro)
|
|
MARK_USED(input_bqb)
|
|
MARK_USED(unit_voro)
|
|
MARK_USED(qs_env)
|
|
MARK_USED(rspace_pw)
|
|
|
|
CALL cp_warn(__LOCATION__, &
|
|
"Voronoi integration and BQB output require CP2k to be compiled"// &
|
|
" with the -D__LIBVORI preprocessor option.")
|
|
|
|
#endif
|
|
|
|
END SUBROUTINE entry_voronoi_or_bqb
|
|
|
|
! **************************************************************************************************
|
|
!> \brief Call libvori's finalize if support is compiled in
|
|
! **************************************************************************************************
|
|
SUBROUTINE finalize_libvori()
|
|
#if defined(__LIBVORI)
|
|
INTEGER(KIND=C_INT) :: ret
|
|
ret = libvori_finalize()
|
|
#endif
|
|
END SUBROUTINE
|
|
|
|
! **************************************************************************************************
|
|
!> \brief ...
|
|
!> \param subsys ...
|
|
!> \param cell ...
|
|
!> \param sim_step ...
|
|
!> \param sim_time ...
|
|
!> \param iounit ...
|
|
!> \param particles_r ...
|
|
!> \param particles_c ...
|
|
!> \param voro_charge ...
|
|
!> \param voro_charge_center ...
|
|
!> \param mp_file_name ...
|
|
! **************************************************************************************************
|
|
SUBROUTINE molecular_properties(subsys, cell, sim_step, sim_time, iounit, &
|
|
particles_r, particles_c, voro_charge, &
|
|
voro_charge_center, mp_file_name)
|
|
TYPE(qs_subsys_type), POINTER :: subsys
|
|
TYPE(cell_type), POINTER :: cell
|
|
INTEGER, INTENT(IN) :: sim_step
|
|
REAL(KIND=dp), INTENT(IN) :: sim_time
|
|
INTEGER, INTENT(IN) :: iounit
|
|
REAL(KIND=dp), DIMENSION(:, :) :: particles_r
|
|
REAL(KIND=dp), DIMENSION(:) :: particles_c, voro_charge
|
|
REAL(KIND=dp), DIMENSION(:, :) :: voro_charge_center
|
|
CHARACTER(len=default_path_length) :: mp_file_name
|
|
|
|
CHARACTER(len=3) :: fstatus
|
|
CHARACTER(len=default_path_length) :: fname
|
|
INTEGER :: ia, imol, mk, mpunit, na, na1, na2, &
|
|
nmolecule
|
|
REAL(KIND=dp) :: cm, ddip
|
|
REAL(KIND=dp), DIMENSION(3) :: dipm, posa, posc, ref
|
|
TYPE(molecule_kind_type), POINTER :: molecule_kind
|
|
TYPE(molecule_type), DIMENSION(:), POINTER :: molecule_set
|
|
|
|
IF (iounit > 0) THEN
|
|
WRITE (iounit, *) "VORONOI| Start Calculation of Molecular Properties from Voronoi Integration"
|
|
END IF
|
|
CALL qs_subsys_get(subsys, molecule_set=molecule_set)
|
|
|
|
IF (INDEX(mp_file_name, "__STD_OUT__") /= 0) THEN
|
|
mpunit = iounit
|
|
ELSE
|
|
fname = ADJUSTL(mp_file_name)
|
|
IF (fname(1:2) /= "./") THEN
|
|
fname = TRIM(fname)//".molprop"
|
|
END IF
|
|
IF (file_exists(fname)) THEN
|
|
fstatus = "old"
|
|
ELSE
|
|
fstatus = "new"
|
|
END IF
|
|
CALL open_file(file_name=fname, file_status=fstatus, file_action="write", &
|
|
file_position="append", unit_number=mpunit)
|
|
END IF
|
|
nmolecule = SIZE(molecule_set)
|
|
WRITE (mpunit, FMT="(T2,I0)") nmolecule
|
|
WRITE (mpunit, FMT="(A,I8,A,F12.4,A)") " # Step ", sim_step, ", Time ", &
|
|
sim_time*femtoseconds, " fs"
|
|
WRITE (mpunit, FMT="(A,T25,A)") " # Mol Type Charge", &
|
|
" Dipole[Debye] Total Dipole[Debye]"
|
|
DO imol = 1, nmolecule
|
|
molecule_kind => molecule_set(imol)%molecule_kind
|
|
mk = molecule_kind%kind_number
|
|
na1 = molecule_set(imol)%first_atom
|
|
na2 = molecule_set(imol)%last_atom
|
|
na = na2 - na1 + 1
|
|
ref(1:3) = 0.0_dp
|
|
DO ia = na1, na2
|
|
ref(1:3) = ref(1:3) + pbc(particles_r(1:3, ia), cell)
|
|
END DO
|
|
ref(1:3) = ref(1:3)/REAL(na, KIND=dp)
|
|
dipm = 0.0_dp
|
|
DO ia = na1, na2
|
|
posa(1:3) = particles_r(1:3, ia) - ref(1:3)
|
|
posa(1:3) = pbc(posa, cell)
|
|
posc(1:3) = posa(1:3) + bohr*voro_charge_center(ia, 1:3)/100.0_dp
|
|
posc(1:3) = pbc(posc, cell)
|
|
cm = -particles_c(ia) + voro_charge(ia)
|
|
dipm(1:3) = dipm(1:3) + posa(1:3)*particles_c(ia) + posc(1:3)*cm
|
|
END DO
|
|
dipm(1:3) = dipm(1:3)*debye
|
|
ddip = SQRT(SUM(dipm**2))
|
|
cm = SUM(voro_charge(na1:na2))
|
|
WRITE (mpunit, FMT="(I8,I6,F12.4,T25,3F12.4,8X,F12.4)") imol, mk, cm, dipm(1:3), ddip
|
|
END DO
|
|
IF (mpunit /= iounit) THEN
|
|
CALL close_file(mpunit)
|
|
END IF
|
|
|
|
END SUBROUTINE molecular_properties
|
|
|
|
END MODULE voronoi_interface
|
|
|