TABLE OF CONTENTS
- ABINIT/m_dvdb
- m_dvdb/calc_eiqr
- m_dvdb/dvdb_check_fform
- m_dvdb/dvdb_close
- m_dvdb/dvdb_find_qpts
- m_dvdb/dvdb_findq
- m_dvdb/dvdb_free
- m_dvdb/dvdb_ftinterp_qpt
- m_dvdb/dvdb_ftinterp_setup
- m_dvdb/dvdb_ftqcache_build
- m_dvdb/dvdb_ftqcache_update_from_ft
- m_dvdb/dvdb_get_ftqbz
- m_dvdb/dvdb_get_maxw
- m_dvdb/dvdb_get_pinfo
- m_dvdb/dvdb_get_v1r_long_range
- m_dvdb/dvdb_get_v1scf_qpt
- m_dvdb/dvdb_get_v1scf_rpt
- m_dvdb/dvdb_interpolate_and_write
- m_dvdb/dvdb_interpolate_v1scf
- m_dvdb/dvdb_list_perts
- m_dvdb/dvdb_load_ddb
- m_dvdb/dvdb_load_efield
- m_dvdb/dvdb_merge_files
- m_dvdb/dvdb_new
- m_dvdb/dvdb_open_read
- m_dvdb/dvdb_print
- m_dvdb/dvdb_qcache_read
- m_dvdb/dvdb_qcache_update_from_file
- m_dvdb/dvdb_qdownsample
- m_dvdb/dvdb_read_onev1
- m_dvdb/dvdb_readsym_allv1
- m_dvdb/dvdb_readsym_qbz
- m_dvdb/dvdb_rewind
- m_dvdb/dvdb_seek
- m_dvdb/dvdb_set_pert_distrib
- m_dvdb/dvdb_t
- m_dvdb/dvdb_test_ftinterp
- m_dvdb/dvdb_test_v1complete
- m_dvdb/dvdb_test_v1rsym
- m_dvdb/dvdb_write_v1qavg
- m_dvdb/find_symeq
- m_dvdb/my_hdr_skip
- m_dvdb/prepare_ftinterp
- m_dvdb/qcache_free
- m_dvdb/qcache_get_mbsize
- m_dvdb/qcache_new
- m_dvdb/qcache_qcache_make_room
- m_dvdb/qcache_report_stats
- m_dvdb/qcache_t
- m_dvdb/rotate_fqg
- m_dvdb/v1phq_complete
- m_dvdb/v1phq_rotate
- m_dvdb/v1phq_rotate_myperts
- m_dvdb/v1phq_symmetrize
ABINIT/m_dvdb [ Modules ]
NAME
m_dvdb
FUNCTION
Objects and methods to extract data from the DVDB file. The DVDB file is Fortran binary file with a collection of DFPT potentials associated to the different phonon perturbations (idir, ipert, qpt). DVDB files are produced with the `mrgdv` utility and used in the EPH code to compute the matrix elements: <k+q| dvscf_{idir, ipert, qpt} |k>.
COPYRIGHT
Copyright (C) 2009-2024 ABINIT group (MG, GA) This file is distributed under the terms of the GNU General Public License, see ~abinit/COPYING or http://www.gnu.org/copyleft/gpl.txt . For the initials of contributors, see ~abinit/doc/developers/contributors.txt.
TODO
- Do we still need to support the case in which the potentials are read from file without interpolation? We know that IO is gonna be terrible. - Check spin and MPI-parallelism. Can we distributed nsppol? - Rewrite qcache from scratch, keep only the IBZ of the present iteration
SOURCE
27 #if defined HAVE_CONFIG_H 28 #include "config.h" 29 #endif 30 31 #include "abi_common.h" 32 33 module m_dvdb 34 35 use defs_basis 36 use m_abicore 37 use m_errors 38 use m_xmpi 39 use m_distribfft 40 use m_nctk 41 use m_sort 42 use netcdf 43 use m_hdr 44 use m_ddb 45 use m_ddb_hdr 46 use m_dtset 47 use m_krank 48 49 use defs_abitypes, only : mpi_type 50 use m_fstrings, only : strcat, sjoin, itoa, ktoa, ltoa, ftoa, yesno, endswith 51 use m_time, only : cwtime, cwtime_report, sec2str, timab 52 use m_io_tools, only : open_file, file_exists, delete_file 53 use m_numeric_tools, only : wrap2_pmhalf, vdiff_t, vdiff_eval, vdiff_print, l2int 54 use m_symtk, only : mati3inv, matr3inv, littlegroup_q 55 use m_geometry, only : littlegroup_pert, irreducible_set_pert, mkradim, xcart2xred 56 use m_dynmat, only : canat9, get_bigbox_and_weights 57 use m_copy, only : alloc_copy 58 use m_mpinfo, only : destroy_mpi_enreg, initmpi_seq 59 use m_ioarr, only : read_rhor 60 use m_fftcore, only : ngfft_seq 61 use m_fft_mesh, only : rotate_fft_mesh, times_eigr, times_eikr, ig2gfft, get_gftt, calc_ceikr, calc_eigr 62 use m_fft, only : fourdp, zerosym 63 use m_crystal, only : crystal_t 64 use m_kpts, only : kpts_ibz_from_kptrlatt, listkk, kpts_map, kpts_timrev_from_kptopt 65 use m_spacepar, only : symrhg, setsym 66 use m_fourier_interpol,only : fourier_interpol 67 use m_pawrhoij, only : pawrhoij_type 68 69 implicit none 70 71 private
m_dvdb/calc_eiqr [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
calc_eiqr
FUNCTION
Compute e^{iq.r} for nrpt R-points.
INPUTS
OUTPUT
SOURCE
5206 pure subroutine calc_eiqr(qpt, nrpt, rpt, eiqr) 5207 5208 !Arguments ------------------------------- 5209 !scalars 5210 integer,intent(in) :: nrpt 5211 !arrays 5212 real(dp),intent(in) :: qpt(3), rpt(3, nrpt) 5213 real(dp),intent(out) :: eiqr(2, nrpt) 5214 5215 !Local variables ------------------------- 5216 !scalars 5217 integer :: ir 5218 real(dp) :: qr 5219 5220 ! ********************************************************************* 5221 5222 do ir=1,nrpt 5223 qr = two_pi * dot_product(qpt, rpt(:,ir)) 5224 eiqr(1, ir) = cos(qr); eiqr(2, ir) = sin(qr) 5225 end do 5226 5227 end subroutine calc_eiqr
m_dvdb/dvdb_check_fform [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_check_fform
FUNCTION
Check the value of fform. Return exit status and error message.
INPUTS
fform=Value read from the header mode="merge_dvdb" to check the value of fform when we are merging POT1 files "read_dvdb" when we are reading POT1 files from a DVDB file.
OUTPUT
errmsg=String with error message if ierr /= 0
SOURCE
5249 integer function dvdb_check_fform(fform, mode, errmsg) result(ierr) 5250 5251 !Arguments ------------------------------------ 5252 integer,intent(in) :: fform 5253 character(len=*),intent(in) :: mode 5254 character(len=*),intent(out) :: errmsg 5255 5256 ! ************************************************************************* 5257 ierr = 0 5258 5259 ! Here I made a mistake because 102 corresponds to GS potentials 5260 ! as a consequence DVDB files generated with version <= 8.1.6 5261 ! contain list of potentials with fform = 102. 5262 !integer :: fform_pot=102 5263 !integer :: fform_pot=109 5264 !integer :: fform_pot=111 5265 5266 if (fform == 0) then 5267 errmsg = "fform == 0! Either corrupted/nonexistent file or IO error" 5268 ierr = 42; return 5269 end if 5270 5271 select case (mode) 5272 case ("merge_dvdb") 5273 if (all(fform /= [109, 111])) then 5274 errmsg = sjoin("fform:", itoa(fform), "is not supported in `merge_dvdb` mode") 5275 ierr = 1; return 5276 end if 5277 5278 case ("read_dvdb") 5279 if (all(fform /= [102, 109, 111])) then 5280 errmsg = sjoin("fform:", itoa(fform), "is not supported in `read_dvdb` mode") 5281 ierr = 1; return 5282 end if 5283 5284 case default 5285 errmsg = sjoin("Invalid mode:", mode) 5286 ierr = -1; return 5287 end select 5288 5289 end function dvdb_check_fform
m_dvdb/dvdb_close [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_close
FUNCTION
Close the file
SOURCE
883 subroutine dvdb_close(db) 884 885 !Arguments ------------------------------------ 886 !scalars 887 class(dvdb_t),intent(inout) :: db 888 889 !************************************************************************ 890 891 select case (db%iomode) 892 case (IO_MODE_FORTRAN) 893 close(db%fh) 894 case default 895 ABI_ERROR(sjoin("Unsupported iomode:", itoa(db%iomode))) 896 end select 897 898 db%rw_mode = DVDB_NOMODE 899 900 end subroutine dvdb_close
m_dvdb/dvdb_find_qpts [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_find_qpts
FUNCTION
Find the index of the q-point in db%qpts. Non zero umklapp vectors are not allowed. Returns -1 if not found.
INPUTS
nqpt: Number of q-points qpt(3,nqpt): q-point in reduced coordinates. comm: MPI communicator
OUTPUT
iq2dvdb(nqpt): index of q-points in dvdb%qpts. Set to -1 if not found ierr= Number of points **not** found
SOURCE
4585 integer function dvdb_find_qpts(db, nqpt, qpts, iq2dvdb, comm) result(notfound) 4586 4587 !Arguments ------------------------------------ 4588 !scalars 4589 class(dvdb_t),intent(in) :: db 4590 integer,intent(in) :: nqpt, comm 4591 !arrays 4592 real(dp),intent(in) :: qpts(3, nqpt) 4593 integer,intent(out) :: iq2dvdb(nqpt) 4594 4595 !Local variables------------------------------- 4596 !scalars 4597 integer :: iq, my_rank, nprocs, ierr 4598 4599 ! ************************************************************************* 4600 4601 my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm) 4602 4603 iq2dvdb = 0 4604 do iq=1,nqpt 4605 if (mod(iq, nprocs) /= my_rank) cycle ! MPI parallelism 4606 iq2dvdb(iq) = db%findq(qpts(:, iq)) 4607 end do 4608 4609 call xmpi_sum(iq2dvdb, comm, ierr) 4610 notfound = count(iq2dvdb == -1) 4611 4612 end function dvdb_find_qpts
m_dvdb/dvdb_findq [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_findq
FUNCTION
Find the index of the q-point in db%qpts. Non zero umklapp vectors are not allowed. Returns -1 if not found.
INPUTS
qpt(3)=q-point in reduced coordinates. [qtol]=Optional tolerance for q-point comparison. For each reduced direction the absolute difference between the coordinates must be less that qtol
SOURCE
4537 integer pure function dvdb_findq(db, qpt, qtol) result(iqpt) 4538 4539 !Arguments ------------------------------------ 4540 !scalars 4541 real(dp),optional,intent(in) :: qtol 4542 class(dvdb_t),intent(in) :: db 4543 !arrays 4544 real(dp),intent(in) :: qpt(3) 4545 4546 !Local variables------------------------------- 4547 !scalars 4548 integer :: iq 4549 real(dp) :: my_qtol 4550 4551 ! ************************************************************************* 4552 4553 my_qtol = tol6; if (present(qtol)) my_qtol = qtol 4554 iqpt = -1 4555 do iq=1,db%nqpt 4556 if (all(abs(db%qpts(:, iq) - qpt) < my_qtol)) then 4557 iqpt = iq; exit 4558 end if 4559 end do 4560 4561 end function dvdb_findq
m_dvdb/dvdb_free [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_free
FUNCTION
Close the file and release the memory allocated.
SOURCE
914 subroutine dvdb_free(db) 915 916 !Arguments ------------------------------------ 917 !scalars 918 class(dvdb_t),intent(inout) :: db 919 920 !************************************************************************ 921 922 ! integer arrays 923 ABI_SFREE(db%my_pinfo) 924 ABI_SFREE(db%pert_table) 925 ABI_SFREE(db%pos_dpq) 926 ABI_SFREE(db%cplex_v1) 927 ABI_SFREE(db%symq_table) 928 ABI_SFREE(db%iv_pinfoq) 929 ABI_SFREE(db%ngfft3_v1) 930 ABI_SFREE(db%my_irpt2tot) 931 932 ! real arrays 933 ABI_SFREE(db%qpts) 934 ABI_SFREE(db%my_rpt) 935 ABI_SFREE(db%wsr) 936 ABI_SFREE(db%my_wratm) 937 ABI_SFREE(db%rhog1_g0) 938 ABI_SFREE(db%zeff) 939 ABI_SFREE(db%zeff_raw) 940 ABI_SFREE(db%qstar) 941 ABI_SFREE(db%v1r_efield) 942 943 ! types 944 call db%hdr_ref%free() 945 call db%cryst%free() 946 call destroy_mpi_enreg(db%mpi_enreg) 947 948 ! Clean cache(s) 949 call db%qcache%free() 950 call db%ft_qcache%free() 951 952 ! Close the file but only if we have performed IO. 953 if (db%rw_mode == DVDB_NOMODE) return 954 call db%close() 955 956 end subroutine dvdb_free
m_dvdb/dvdb_ftinterp_qpt [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_ftinterp_qpt
FUNCTION
Fourier interpolation of potentials for a given q-point Internal tables must be prepared in advance by calling `dvdb_ftinterp_setup`. \begin{equation} \partial v^{scf}_{\tilde\qq\kappa\alpha}(\rr) \approx \sum_\RR e^{+i\tilde{\qq}\cdot(\RR - \rr)} W_{\kappa\alpha}(\rr,\RR). \end{equation
INPUTS
qpt(3)=q-point in reduced coordinates (arbitrary point in the BZ). nfft=Number of FFT-points treated by this processors. ngfft(18)=contain all needed information about 3D FFT. comm=MPI communicator for R-points. [add_lr]= If present, use this value for the LR treatment instead of dv%add_lr
OUTPUT
ov1r(2*nfft, nspden, my_npert)=Interpolated DFPT potentials at the given q-point (periodic part)
SOURCE
3424 subroutine dvdb_ftinterp_qpt(db, qpt, nfft, ngfft, ov1r, comm_rpt, add_lr) 3425 3426 !Arguments ------------------------------------ 3427 !scalars 3428 integer,intent(in) :: nfft, comm_rpt 3429 integer,optional,intent(in) :: add_lr 3430 class(dvdb_t),intent(inout) :: db 3431 !arrays 3432 integer,intent(in) :: ngfft(18) 3433 real(dp),intent(in) :: qpt(3) 3434 real(dp),intent(out) :: ov1r(2, nfft, db%nspden, db%my_npert) 3435 3436 !Local variables------------------------------- 3437 !scalars 3438 integer,parameter :: cplex2 = 2 3439 integer :: ispden, imyp, idir, ipert, timerev_q, ierr, my_add_lr !, ifft, ir 3440 !real(dp) :: qmod 3441 !real(sp) :: beta_sp !, wr !,wi 3442 logical :: prev_has_zeff, prev_has_quadrupoles, prev_has_efield 3443 !arrays 3444 integer :: symq(4,2,db%cryst%nsym), rfdir(3) 3445 integer,allocatable :: pertsy(:,:), rfpert(:), pflag(:,:) 3446 !real(dp) :: qcart(3) 3447 real(dp),allocatable :: eiqr(:,:), v1r_lr(:,:,:) 3448 real(sp),allocatable :: weiqr_sp(:,:), ov1r_sp(:, :), eiqr_sp(:,:) 3449 3450 ! ************************************************************************* 3451 3452 my_add_lr = db%add_lr; if (present(add_lr)) my_add_lr = add_lr 3453 3454 !qcart = two_pi * matmul(db%cryst%gprimd, qpt) 3455 !qmod = sqrt(dot_product(qcart, qcart)) 3456 3457 if (my_add_lr >= 4) then 3458 ! Use LR part only and return immediately. 3459 3460 if (my_add_lr > 4) then 3461 prev_has_zeff = db%has_zeff 3462 prev_has_quadrupoles = db%has_quadrupoles 3463 prev_has_efield = db%has_efield 3464 db%has_zeff = .False. 3465 db%has_quadrupoles = .False. 3466 db%has_efield = .False. 3467 if (my_add_lr == 5 .and. prev_has_zeff) db%has_zeff = .True. 3468 if (my_add_lr == 6 .and. prev_has_quadrupoles) db%has_quadrupoles = .True. 3469 if (my_add_lr == 7 .and. prev_has_efield) db%has_efield = .True. 3470 end if 3471 3472 ov1r = zero 3473 do imyp=1,db%my_npert 3474 idir = db%my_pinfo(1, imyp); ipert = db%my_pinfo(2, imyp) 3475 call db%get_v1r_long_range(qpt, idir, ipert, nfft, ngfft, ov1r(:, :, 1, imyp)) 3476 ! Remove the phase to get the lattice-periodic part. 3477 call times_eikr(-qpt, ngfft, nfft, 1, ov1r(:, :, 1, imyp)) 3478 if (db%nspden /= 1) ov1r(:, :, 2, imyp) = ov1r(:, :, 1, imyp) 3479 end do 3480 3481 if (my_add_lr > 4) then 3482 ! Restore input flags. 3483 db%has_zeff = prev_has_zeff 3484 db%has_quadrupoles = prev_has_quadrupoles 3485 db%has_efield = prev_has_efield 3486 end if 3487 3488 return 3489 end if 3490 3491 ABI_CHECK(allocated(db%wsr), "wsr is not allocated (call dvdb_ftinterp_setup)") 3492 3493 ! Examine the symmetries of the q-wavevector 3494 call littlegroup_q(db%cryst%nsym, qpt, symq, db%cryst%symrec, db%cryst%symafm, timerev_q, prtvol=db%prtvol) 3495 3496 ! Compute long-range part of the coupling potential. 3497 if (my_add_lr > 0) then 3498 !call wrtout(std_out, "dvdb_ftinterp_qpt: Computing long-range part of the coupling potential.") 3499 ABI_MALLOC(v1r_lr, (2, nfft, db%my_npert)) 3500 do imyp=1,db%my_npert 3501 idir = db%my_pinfo(1, imyp); ipert = db%my_pinfo(2, imyp) 3502 call db%get_v1r_long_range(qpt, idir, ipert, nfft, ngfft, v1r_lr(:,:,imyp)) 3503 end do 3504 end if 3505 3506 ! Compute e^{iq.R} FT phases for this q-point. 3507 ABI_MALLOC(eiqr, (2, db%my_nrpt)) 3508 call calc_eiqr(qpt, db%my_nrpt, db%my_rpt, eiqr) 3509 3510 ! Interpolate potentials (results in ov1r) 3511 if (db%nprocs_rpt > 1) ov1r = zero 3512 ABI_MALLOC(ov1r_sp, (2, nfft)) 3513 3514 ABI_MALLOC(weiqr_sp, (db%my_nrpt, 2)) 3515 ABI_MALLOC(eiqr_sp, (db%my_nrpt, 2)) 3516 eiqr_sp = transpose(eiqr) 3517 3518 do imyp=1,db%my_npert 3519 idir = db%my_pinfo(1, imyp); ipert = db%my_pinfo(2, imyp) 3520 3521 weiqr_sp(:, 1) = db%my_wratm(:, ipert) * eiqr_sp(:, 1) 3522 weiqr_sp(:, 2) = db%my_wratm(:, ipert) * eiqr_sp(:, 2) 3523 3524 do ispden=1,db%nspden 3525 3526 ! We need to compute: sum_R W(R, r) e^{iq.R} with W real matrix. 3527 ! Use BLAS2 to compute ov1r = W (x + iy) but need to handle kind conversion as ov1r is double-precision 3528 ! NB: Can use MKL BLAS-like extensions to perform 2 matrix-vector operations: 3529 ! call dgem2vu(m, n, alpha, a, lda, x1, incx1, x2, incx2, beta, y1, incy1, y2, incy2) 3530 ! unfortunately the API does not support transa so one has to transport db%wsr. 3531 ! Alternatively, compute all my_npert with ZGEMM (more memory but it should be more efficient). 3532 3533 call SGEMV("T", db%my_nrpt, nfft, one_sp, db%wsr(1,1,1,ispden,imyp), db%my_nrpt, weiqr_sp(1,1), 1, & 3534 zero_sp, ov1r_sp(1,1), 2) 3535 call SGEMV("T", db%my_nrpt, nfft, one_sp, db%wsr(1,1,1,ispden,imyp), db%my_nrpt, weiqr_sp(1,2), 1, & 3536 zero_sp, ov1r_sp(2,1), 2) 3537 3538 ov1r(:, :, ispden, imyp) = ov1r_sp(:, :) 3539 3540 ! Add the long-range part of the potential 3541 if (my_add_lr > 0) then 3542 !call wrtout(std_out, "Adding the long-range part of the potential") 3543 ov1r(:, :, ispden, imyp) = ov1r(:, :, ispden, imyp) + v1r_lr(:, :, imyp) 3544 end if 3545 3546 ! Remove the phase to get the lattice-periodic part. 3547 call times_eikr(-qpt, ngfft, nfft, 1, ov1r(:, :, ispden, imyp)) 3548 3549 ! Need to collect results if R-points are distributed (TODO Non-blocking API?) 3550 if (db%nprocs_rpt > 1) call xmpi_sum(ov1r(:,:,ispden,imyp), comm_rpt, ierr) 3551 end do ! ispden 3552 3553 ! Be careful with Gamma-point and cplex! 3554 if (db%symv1 == 1) then !(.and. reveiver == -1 .or. receiver == db%comm_rpt%my_rank) 3555 call v1phq_symmetrize(db%cryst, idir, ipert, symq, ngfft, cplex2, nfft, db%nspden, db%nsppol, & 3556 db%mpi_enreg, ov1r(:,:,:,imyp)) 3557 end if 3558 end do ! imyp 3559 3560 ABI_FREE(ov1r_sp) 3561 3562 if (db%symv1 == 2) then 3563 ! Symmetrize potentials (this part is seldom executed) 3564 ! Initialize the list of perturbations rfpert and rdfir 3565 ! WARNING: Only phonon perturbations are considered for the time being. 3566 ABI_MALLOC(rfpert, (db%mpert)) 3567 rfpert = 0; rfpert(1:db%cryst%natom) = 1; rfdir = 1 3568 ABI_MALLOC(pertsy, (3, db%mpert)) 3569 ABI_MALLOC(pflag, (3, db%natom)) 3570 3571 ! Determine the symmetrical perturbations. Meaning of pertsy: 3572 ! 0 for non-target perturbations 3573 ! 1 for basis perturbations 3574 ! -1 for perturbations that can be found from basis perturbations 3575 call irreducible_set_pert(db%cryst%indsym,db%mpert,db%cryst%natom,db%cryst%nsym,& 3576 pertsy,rfdir,rfpert,symq,db%cryst%symrec,db%cryst%symrel) 3577 3578 pflag = 0 3579 do imyp=1,3*db%cryst%natom 3580 idir = mod(imyp-1, 3) + 1; ipert = (imyp - idir) / 3 + 1 3581 if (pertsy(idir, ipert) == 1) pflag(idir,ipert) = 1 3582 end do 3583 3584 ! Complete potentials 3585 call v1phq_complete(db%cryst,qpt,ngfft,cplex2,nfft,db%nspden,db%nsppol,db%mpi_enreg,db%symv1,pflag,ov1r) 3586 3587 ABI_FREE(pertsy) 3588 ABI_FREE(rfpert) 3589 ABI_FREE(pflag) 3590 endif 3591 3592 ! Set imaginary part to zero if gamma point. 3593 if (sum(qpt**2) < tol14) ov1r(2, :, :, :) = zero 3594 3595 ABI_FREE(eiqr) 3596 ABI_FREE(weiqr_sp) 3597 ABI_SFREE(v1r_lr) 3598 ABI_SFREE(eiqr_sp) 3599 3600 end subroutine dvdb_ftinterp_qpt
m_dvdb/dvdb_ftinterp_setup [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_ftinterp_setup
FUNCTION
Precompute the wsr array with with the DFPT potential in the supercell required for the Fourier interpolation This is a collective routine that should be called by all procs inside db%comm. \begin{equation} \label{eq:dfpt_pot_realspace} W_{\kappa\alpha}(\rr,\RR) = \dfrac{1}{N_\qq} \sum_\qq e^{-i\qq\cdot(\RR - \rr)}\, \partial_{\kappa\alpha\qq}{v^{\text{scf}}}(\rr) \end{equation}
INPUTS
ngqpt(3)=Divisions of the ab-initio q-mesh. qptopt=option for the generation of q points (defines whether spatial symmetries and/or time-reversal can be used) nqshift=Number of shifts used to generated the ab-initio q-mesh. qshift(3,nqshift)=The shifts of the ab-initio q-mesh. nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT comm_rpt = MPI communicator used to distribute R-lattice points.
SOURCE
2890 subroutine dvdb_ftinterp_setup(db, ngqpt, qptopt, nqshift, qshift, nfft, ngfft, comm_rpt) 2891 2892 !Arguments ------------------------------------ 2893 !scalars 2894 integer,intent(in) :: qptopt,nqshift,nfft,comm_rpt 2895 class(dvdb_t),target,intent(inout) :: db 2896 !arrays 2897 integer,intent(in) :: ngqpt(3), ngfft(18) 2898 real(dp),intent(in) :: qshift(3,nqshift) 2899 2900 !Local variables------------------------------- 2901 !scalars 2902 integer,parameter :: master=0 2903 integer :: iq_ibz,nqibz,iq_bz,nqbz !, timerev_q 2904 integer :: ii,jj,cplex_qibz,ispden,imyp,irpt,idir,ipert,ipc 2905 integer :: iqst, itimrev, isym 2906 integer :: ifft, ierr, my_rstart, my_rstop, iatom 2907 real(dp) :: cpu, wall, gflops, cpu_all, wall_all, gflops_all 2908 logical :: isirr_q 2909 character(len=500) :: msg 2910 !arrays 2911 integer :: g0q(3) 2912 !integer :: symq(4,2,db%cryst%nsym) 2913 integer,allocatable :: indqq(:,:), iperm(:), nqsts(:), iqs_dvdb(:), all_cell(:,:) 2914 real(dp) :: qpt_bz(3) 2915 real(dp),allocatable :: qibz(:,:), qbz(:,:), emiqr(:,:), all_rpt(:,:), all_wghatm(:,:,:) 2916 real(dp),allocatable :: v1r_qibz(:,:,:,:), v1r_qbz(:,:,:,:), v1r_lr(:,:,:) 2917 2918 ! ************************************************************************* 2919 2920 ! Set communicator for R-point parallelism. 2921 ! Note that client code is responsible for calling the interpolation routine dvdb_get_ftqbz (R -> q) 2922 ! with all procs inside comm_rpt to avoid MPI deadlocks. 2923 db%comm_rpt = comm_rpt; db%nprocs_rpt = xmpi_comm_size(db%comm_rpt); db%me_rpt = xmpi_comm_rank(db%comm_rpt) 2924 2925 if (db%add_lr >= 4) then 2926 call wrtout(std_out, " Skipping construction of W(R,r) because add_lr >= 4. Wll use LR part only!") 2927 return 2928 end if 2929 2930 call cwtime(cpu_all, wall_all, gflops_all, "start") 2931 2932 call wrtout(std_out, sjoin(ch10, "Building W(R,r) using q-mesh ngqpt: ", ltoa(ngqpt), & 2933 ", with nprocs_rpt:", itoa(db%nprocs_rpt)), do_flush=.True.) 2934 call wrtout(std_out, sjoin(" Using Gaussian filter with qdamp: ", ftoa(db%qdamp, fmt="(f6.1)"))) 2935 !call wrtout(std_out, " Q-mesh shifts:") 2936 !do ii=1,nqshift 2937 ! call wrtout(std_out, ltoa(qshift(:, ii))) 2938 !end do 2939 call wrtout(std_out, "") 2940 call wrtout(std_out, " Note: this part may take some time depending on the number of MPI procs, ngqpt and nfft points.") 2941 call wrtout(std_out, " Use boxcutmin < 2.0 (> 1.1) to decrease nfft, reduce memory requirements and speedup the calculation.") 2942 2943 call prepare_ftinterp(db, ngqpt, qptopt, nqshift, qshift, & 2944 qibz, qbz, indqq, iperm, nqsts, iqs_dvdb, all_rpt, all_wghatm, db%comm) 2945 2946 nqibz = size(qibz, dim=2); nqbz = size(qbz, dim=2); db%nrtot = size(all_rpt, dim=2) 2947 2948 ! Distribute R-points inside comm_rpt. 2949 call xmpi_split_work(db%nrtot, db%comm_rpt, my_rstart, my_rstop) 2950 2951 ! Select my_rpoints. 2952 ! Use REMALLOC so that we can call this routine multiple times i.e. for changing add_lr 2953 db%my_nrpt = my_rstop - my_rstart + 1 2954 ABI_CHECK(db%my_nrpt /= 0, "my_nrpt == 0!") 2955 2956 ABI_REMALLOC(db%my_rpt, (3, db%my_nrpt)) 2957 db%my_rpt = all_rpt(:, my_rstart:my_rstop) 2958 ABI_REMALLOC(db%my_irpt2tot, (db%my_nrpt)) 2959 do irpt=1,db%my_nrpt 2960 db%my_irpt2tot(irpt) = my_rstart + (irpt - 1) 2961 end do 2962 2963 ! Copy weights for the atoms treated by this proc. 2964 ii = minval(db%my_pinfo(2,:)); jj = maxval(db%my_pinfo(2,:)) 2965 ABI_REMALLOC(db%my_wratm, (db%my_nrpt, ii:jj)) 2966 db%my_wratm = one 2967 if (db%rspace_cell == 1) then 2968 do iatom=1,db%cryst%natom 2969 if (iatom >= ii .and. iatom <= jj) db%my_wratm(:, iatom) = all_wghatm(iatom, iatom, my_rstart:my_rstop) 2970 end do 2971 end if 2972 2973 write(std_out, "(a, i0)")" Using rspace_cell method for integration weights: ", db%rspace_cell 2974 write(std_out, "(a, i0)")" Total number of R-points in real-space big box: ", db%nrtot 2975 write(std_out, "(a, i0)")" Number of R-points treated by this MPI rank: ", db%my_nrpt 2976 write(std_out, "(a, 3(i0, 1x))")" ngfft: ", ngfft(1:3) 2977 write(std_out, "(a, i0)")" dvdb_add_lr: ", db%add_lr 2978 2979 ! Allocate potential in the supercell. Memory is MPI-distributed over my_nrpt and my_npert 2980 call wrtout(std_out, sjoin(" Memory required for W(R,r): ", & 2981 ftoa(two * db%my_nrpt * nfft * db%nspden * db%my_npert * sp * b2Mb, fmt="f8.1"), "[Mb] <<< MEM")) 2982 2983 ABI_SFREE(all_cell) 2984 ABI_SFREE(all_wghatm) 2985 ABI_FREE(all_rpt) 2986 2987 ABI_MALLOC(emiqr, (2, db%my_nrpt)) 2988 ABI_MALLOC(v1r_qbz, (2, nfft, db%nspden, db%natom3)) 2989 ABI_CALLOC(v1r_lr, (2, nfft, db%my_npert)) 2990 2991 ABI_SFREE(db%wsr) 2992 ABI_MALLOC_OR_DIE(db%wsr, (1, db%my_nrpt, nfft, db%nspden, db%my_npert), ierr) 2993 db%wsr = zero 2994 2995 ! TODO: Parallelize this part over q-points using comm_rpt. For the time being only pert parallelism. 2996 iqst = 0 2997 do iq_ibz=1,nqibz 2998 call cwtime(cpu, wall, gflops, "start") 2999 ! 3000 ! Here all procs get all potentials for this IBZ q-point on the real-space FFT mesh. 3001 ! This call allocates v1r_qibz(cplex_qibz, nfft, nspden, 3*natom) 3002 ! Note that here we need all 3*natom perturbations because of v1phq_rotate 3003 call db%readsym_allv1(iqs_dvdb(iq_ibz), cplex_qibz, nfft, ngfft, v1r_qibz, db%comm) 3004 3005 ! Reconstruct by symmetry the potentials for the star of this q-point, 3006 ! perform slow FT and accumulate in wsr. Be careful with the gamma point. 3007 do ii=1,nqsts(iq_ibz) 3008 iqst = iqst + 1 3009 !if (mod(ii, nproc) /= my_rank) cycle ! MPI parallelism. 3010 iq_bz = iperm(iqst) 3011 ABI_CHECK(iq_ibz == indqq(1, iq_bz), "iq_ibz !/ indqq(1)") 3012 qpt_bz = qbz(:, iq_bz) 3013 !if (all(abs(qpt_bz) < tol12)) cycle 3014 ! IS(q_ibz) + g0q = q_bz 3015 isym = indqq(2, iq_bz); itimrev = indqq(6, iq_bz) + 1; g0q = indqq(3:5, iq_bz) 3016 isirr_q = (isym == 1 .and. itimrev == 1 .and. all(g0q == 0)) 3017 !write(std_out, *)"qbz", trim(ktoa(qpt_bz)), " --> qibz ", trim(ktoa(qibz(:,iq_ibz))) 3018 !write(std_out, *)"via isym, itimrev, g0q:", isym, itimrev, g0q 3019 3020 ! Compute long-range part of the coupling potential at qpt_bz. 3021 if (db%add_lr /= 0) then 3022 do imyp=1,db%my_npert 3023 idir = db%my_pinfo(1, imyp); ipert = db%my_pinfo(2, imyp) 3024 call db%get_v1r_long_range(qpt_bz, idir, ipert, nfft, ngfft, v1r_lr(:,:,imyp)) 3025 end do 3026 end if 3027 3028 if (cplex_qibz == 1) then 3029 ! Gamma point. 3030 ABI_CHECK(nqsts(iq_ibz) == 1, "cplex_qibz == 1 and nq nqst /= 1 (should be gamma)") 3031 ABI_CHECK(all(g0q == 0), "gamma point with g0q /= 0") 3032 3033 if (db%add_lr /= 0) then 3034 ! Substract the long-range part of the potential. 3035 do imyp=1,db%my_npert 3036 ipc = db%my_pinfo(3, imyp) 3037 do ispden=1,db%nspden 3038 v1r_qibz(1, :, ispden, ipc) = v1r_qibz(1, :, ispden, ipc) - v1r_lr(1, :, imyp) 3039 end do 3040 end do 3041 end if 3042 3043 ! Slow FT. 3044 do imyp=1,db%my_npert 3045 ipc = db%my_pinfo(3, imyp) 3046 do ispden=1,db%nspden 3047 do ifft=1,nfft 3048 do irpt=1,db%my_nrpt 3049 db%wsr(1, irpt, ifft, ispden, imyp) = db%wsr(1, irpt, ifft, ispden, imyp) + & 3050 v1r_qibz(1, ifft, ispden, ipc) 3051 end do 3052 end do 3053 end do 3054 end do 3055 3056 else 3057 ! q /= Gamma. Get the periodic part of the potential in BZ (v1r_qbz) 3058 if (isirr_q) then 3059 v1r_qbz = v1r_qibz 3060 else 3061 call v1phq_rotate(db%cryst, qibz(:,iq_ibz), isym, itimrev, g0q, & 3062 ngfft, cplex_qibz, nfft, db%nspden, db%mpi_enreg, v1r_qibz, v1r_qbz, xmpi_comm_self) 3063 end if 3064 3065 ! Multiply by e^{iqpt_bz.r} 3066 call times_eikr(qpt_bz, ngfft, nfft, db%nspden * db%natom3, v1r_qbz) 3067 3068 if (db%add_lr /= 0) then 3069 ! Substract the long-range part of the potential. 3070 do imyp=1,db%my_npert 3071 ipc = db%my_pinfo(3, imyp) 3072 do ispden=1,db%nspden 3073 v1r_qbz(:, :, ispden, ipc) = v1r_qbz(:, :, ispden, ipc) - v1r_lr(:, :, imyp) 3074 end do 3075 end do 3076 end if 3077 3078 ! Compute FT phases for this qpt_bz. 3079 call calc_eiqr(-qpt_bz, db%my_nrpt, db%my_rpt, emiqr) 3080 3081 ! Slow FT. 3082 do imyp=1,db%my_npert 3083 ipc = db%my_pinfo(3, imyp) 3084 do ispden=1,db%nspden 3085 do ifft=1,nfft 3086 db%wsr(1, :, ifft, ispden, imyp) = db%wsr(1, :, ifft, ispden, imyp) & 3087 + emiqr(1, :) * v1r_qbz(1, ifft, ispden, ipc) & 3088 - emiqr(2, :) * v1r_qbz(2, ifft, ispden, ipc) 3089 3090 !db%wsr(2, :, ifft, ispden, imyp) = db%wsr(2, :, ifft, ispden, imyp) & 3091 ! + emiqr(1, :) * v1r_qbz(2, ifft, ispden, ipc) & 3092 ! + emiqr(2, :) * v1r_qbz(1, ifft, ispden, ipc) 3093 end do 3094 3095 !call zgerc(db%my_nrpt, nfft, cone, emiqr, 1, v1r_qbz(:,:,ispden,ipc), 1, & 3096 ! db%wsr(:,:,:,ispden,imyp), db%my_nrpt) 3097 3098 end do ! ispden 3099 end do ! imyp 3100 end if 3101 3102 end do ! iqst 3103 3104 write(msg,'(2(a,i0),a)') " IBZ q-point [", iq_ibz, "/", nqibz, "]" 3105 call cwtime_report(msg, cpu, wall, gflops) 3106 ABI_FREE(v1r_qibz) 3107 end do ! iq_ibz 3108 3109 ABI_CHECK(iqst == nqbz, "iqst /= nqbz") 3110 call wrtout(std_out, ch10//ch10) 3111 3112 ABI_FREE(iperm) 3113 ABI_FREE(emiqr) 3114 ABI_FREE(qibz) 3115 ABI_FREE(qbz) 3116 ABI_FREE(indqq) 3117 ABI_FREE(iqs_dvdb) 3118 ABI_FREE(nqsts) 3119 ABI_FREE(v1r_qbz) 3120 ABI_FREE(v1r_lr) 3121 3122 !call xmpi_sum(db%wsr, db%comm, ierr) 3123 db%wsr = db%wsr / nqbz 3124 3125 call cwtime_report(" Construction of W(R,r)", cpu_all, wall_all, gflops_all) 3126 3127 end subroutine dvdb_ftinterp_setup
m_dvdb/dvdb_ftqcache_build [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_ftqcache_build
FUNCTION
This function initializes the internal q-cache from W(R,r). This is a collective routine that must be called by all procs inside comm.
INPUTS
nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT. nqibz=Number of points in the IBZ. qibz(3, nqibz)=q-points in the IBZ. mbsize: Cache size in megabytes. < 0 to allocate all q-points. 0 has not effect. > 0 for cache with automatically computed nqpt points. qselect_ibz(nqibz)=0 to ignore this q-point (global array) itreatq(nqibz) = 0 if this q-point won't be treated by this CPU else > 0. Each CPU calls this routine with its own array. comm=MPI communicator
OUTPUT
SOURCE
3825 subroutine dvdb_ftqcache_build(db, nfft, ngfft, nqibz, qibz, mbsize, qselect_ibz, itreatq, comm) 3826 3827 !Arguments ------------------------------------ 3828 !scalars 3829 integer,intent(in) :: nfft, nqibz, comm 3830 real(dp),intent(in) :: mbsize 3831 class(dvdb_t),intent(inout) :: db 3832 !arrays 3833 integer,intent(in) :: ngfft(18), qselect_ibz(nqibz) 3834 integer(i1b),intent(in) :: itreatq(nqibz) 3835 real(dp),intent(in) :: qibz(3, nqibz) 3836 3837 !Local variables------------------------------- 3838 !scalars 3839 integer :: iq_ibz, cplex, ierr 3840 real(dp) :: cpu, wall, gflops, cpu_all, wall_all, gflops_all, my_mbsize, max_mbsize 3841 character(len=500) :: msg 3842 !arrays 3843 real(dp) :: tsec(2) 3844 real(dp),allocatable :: v1scf(:,:,:,:) 3845 3846 ! ************************************************************************* 3847 3848 call timab(1808, 1, tsec) 3849 call cwtime(cpu_all, wall_all, gflops_all, "start") 3850 3851 !call db%ft_qcache%free() 3852 db%ft_qcache = qcache_new(nqibz, nfft, ngfft, mbsize, db%natom3, db%my_npert, db%nspden) 3853 db%ft_qcache%itreatq(:) = itreatq 3854 3855 ! All procs skip this part if qcache is not used. 3856 if (db%ft_qcache%maxnq /= 0) then 3857 3858 call wrtout(std_out, ch10//" Precomputing Vscf(q) from W(R,r) and building qcache...", do_flush=.True.) 3859 3860 ! Note that cplex is always set to 2 here 3861 cplex = 2 3862 ABI_MALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert)) 3863 3864 do iq_ibz=1,nqibz 3865 ! Ignore points reported by the oracle. We can still recompute them on the fly if needed. 3866 if (qselect_ibz(iq_ibz) == 0) cycle 3867 if (itreatq(iq_ibz) == 0) cycle 3868 3869 call cwtime(cpu, wall, gflops, "start") 3870 3871 ! Interpolate my_npert potentials inside comm_rpt 3872 call db%ftinterp_qpt(qibz(:, iq_ibz), nfft, ngfft, v1scf, db%comm_rpt) 3873 3874 ! Points in the IBZ may be distributed to reduce memory. 3875 if (db%ft_qcache%itreatq(iq_ibz) /= 0) then 3876 ABI_MALLOC_OR_DIE(db%ft_qcache%key(iq_ibz)%v1scf, (cplex, nfft, db%nspden, db%my_npert), ierr) 3877 db%ft_qcache%key(iq_ibz)%v1scf = real(v1scf, kind=QCACHE_KIND) 3878 end if 3879 3880 ! Print progress. 3881 if (iq_ibz <= 50 .or. mod(iq_ibz, 100) == 0) then 3882 write(msg,'(2(a,i0),a)') " Interpolating q-point [", iq_ibz, "/", nqibz, "]" 3883 call cwtime_report(msg, cpu, wall, gflops) 3884 end if 3885 end do 3886 3887 ABI_FREE(v1scf) 3888 end if 3889 3890 ! Compute final cache size. 3891 my_mbsize = db%ft_qcache%get_mbsize() 3892 call wrtout(std_out, sjoin(" Memory allocated for Q-cache: ", ftoa(my_mbsize, fmt="f8.1"), " [Mb] <<< MEM")) 3893 call xmpi_max(my_mbsize, max_mbsize, comm, ierr) 3894 call wrtout(std_out, sjoin(" Max memory inside MPI comm: ", ftoa(max_mbsize, fmt="f8.1"), " [Mb] <<< MEM")) 3895 call cwtime_report(" Qcache from W(R, r) + symmetrization", cpu_all, wall_all, gflops_all, end_str=ch10) 3896 call timab(1808, 2, tsec) 3897 3898 ! This barrier seems to be needed on lemaitre3. DO NOT REMOVE! 3899 call xmpi_barrier(comm) 3900 3901 end subroutine dvdb_ftqcache_build
m_dvdb/dvdb_ftqcache_update_from_ft [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_ftqcache_update_from_ft
FUNCTION
Interpolate selected potentials and update the internal q-cache. This is a collective routine that must be called by all procs in comm.
INPUTS
nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT. nqibz=Number of q-points in the IBZ. qibz(3, nqibz)= q-points in the IBZ. ineed_qpt(%nqpt)=1 if this MPI rank requires this q-point. comm=MPI communicator
OUTPUT
SOURCE
3924 subroutine dvdb_ftqcache_update_from_ft(db, nfft, ngfft, nqibz, qibz, ineed_qpt, comm) 3925 3926 !Arguments ------------------------------------ 3927 !scalars 3928 integer,intent(in) :: nfft,comm, nqibz 3929 class(dvdb_t),intent(inout) :: db 3930 !arrays 3931 integer,intent(in) :: ngfft(18), ineed_qpt(nqibz) 3932 real(dp),intent(in) :: qibz(3, nqibz) 3933 3934 !Local variables------------------------------- 3935 !scalars 3936 integer :: iq_ibz, cplex, ierr, qcnt 3937 real(dp) :: cpu_all, wall_all, gflops_all, mbsize, max_mbsize 3938 character(len=500) :: msg 3939 !arrays 3940 real(dp),allocatable :: v1scf(:,:,:,:) 3941 !real(dp) :: tsec(2) 3942 3943 ! ************************************************************************* 3944 3945 if (db%ft_qcache%maxnq == 0) return 3946 qcnt = count(ineed_qpt /= 0) 3947 3948 !ABI_ERROR("Legacy code!") 3949 3950 call cwtime(cpu_all, wall_all, gflops_all, "start") 3951 3952 if (qcnt /= 0) then 3953 !call timab(1807, 1, tsec) 3954 call wrtout(std_out, sjoin(" Need to update Vscf(q) cache with: ", itoa(qcnt), "q-points from FT..."), do_flush=.True.) 3955 if (db%ft_qcache%make_room(ineed_qpt, msg) /= 0) then 3956 ABI_WARNING(msg) 3957 end if 3958 3959 cplex = 2 3960 ABI_MALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert)) 3961 do iq_ibz=1,nqibz 3962 if (ineed_qpt(iq_ibz) == 0) cycle 3963 ! Interpolate my_npert potentials inside comm_rpt. 3964 call db%ftinterp_qpt(qibz(:, iq_ibz), nfft, ngfft, v1scf, db%comm_rpt) 3965 ! Transfer to cache. 3966 if (ineed_qpt(iq_ibz) /= 0) then 3967 ABI_MALLOC_OR_DIE(db%ft_qcache%key(iq_ibz)%v1scf, (cplex, nfft, db%nspden, db%my_npert), ierr) 3968 db%ft_qcache%key(iq_ibz)%v1scf = real(v1scf, kind=QCACHE_KIND) 3969 end if 3970 end do 3971 3972 ABI_FREE(v1scf) 3973 end if 3974 3975 mbsize = db%ft_qcache%get_mbsize() 3976 call wrtout(std_out, sjoin(" Memory allocated for cache: ", ftoa(mbsize, fmt="f8.1"), " [Mb] <<< MEM")) 3977 call xmpi_max(mbsize, max_mbsize, comm, ierr) 3978 call wrtout(std_out, sjoin(" Max memory inside MPI comm: ", ftoa(max_mbsize, fmt="f8.1"), " [Mb] <<< MEM")) 3979 call cwtime_report(" dvdb_ftqcache_update_from_ft", cpu_all, wall_all, gflops_all) 3980 !call timab(1807, 2, tsec) 3981 3982 end subroutine dvdb_ftqcache_update_from_ft
m_dvdb/dvdb_get_ftqbz [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_get_ftqbz
FUNCTION
Fourier interpolation of potentials for a given q-point in the BZ (qbz). Internal tables must be prepared in advance by calling `dvdb_ftinterp_setup`. Interpolation is avoided if potential is in ft_qcache
INPUTS
cryst<crystal_t>=crystal structure parameters qbz(3)= q-point in the BZ in reduced coordinates. qibz(3) = Image of qbz in the IBZ. Needed to apply symmetries IBZ --> qbz indq2ibz(6)=Symmetry mapping qbz --> IBZ qpoint produced by listkk. nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT
OUTPUT
ov1r(2*nfft, nspden, my_npert)=Interpolated DFPT potentials at the given q-point.
SOURCE
3627 subroutine dvdb_get_ftqbz(db, cryst, qbz, qibz, indq2ibz, cplex, nfft, ngfft, v1scf, comm) 3628 3629 !Arguments ------------------------------------ 3630 !scalars 3631 integer,intent(in) :: nfft, comm 3632 integer,intent(out) :: cplex 3633 type(crystal_t),intent(in) :: cryst 3634 class(dvdb_t),intent(inout) :: db 3635 !arrays 3636 integer,intent(in) :: ngfft(18), indq2ibz(6) 3637 real(dp),intent(in) :: qbz(3), qibz(3) 3638 real(dp),allocatable,intent(out) :: v1scf(:,:,:,:) 3639 3640 !Local variables------------------------------- 3641 !scalars 3642 integer :: iq_ibz, itimrev, isym, ierr, imyp, mu, root 3643 logical :: isirr_q, incache 3644 !!arrays 3645 integer :: g0q(3), requests(db%natom3) 3646 real(dp) :: tsec(2) 3647 real(dp) ABI_ASYNC, allocatable :: work(:,:,:,:), work2(:,:,:,:) 3648 3649 ! ************************************************************************* 3650 3651 ABI_UNUSED(comm) 3652 3653 ! Keep track of total time spent. 3654 call timab(1809, 1, tsec) 3655 3656 iq_ibz = indq2ibz(1) 3657 db%ft_qcache%count_qused(iq_ibz) = db%ft_qcache%count_qused(iq_ibz) + 1 3658 db%ft_qcache%stats(1) = db%ft_qcache%stats(1) + 1 3659 3660 ! IS(q_ibz) + g0q = q_bz 3661 isym = indq2ibz(2); itimrev = indq2ibz(6) + 1; g0q = indq2ibz(3:5) 3662 isirr_q = (isym == 1 .and. itimrev == 1 .and. all(g0q == 0)) 3663 3664 if (db%ft_qcache%use_3natom_cache .and. db%ft_qcache%v1scf_3natom_request /= xmpi_request_null) then 3665 ! Wait for completion of iallgather. 3666 call xmpi_wait(db%ft_qcache%v1scf_3natom_request, ierr) 3667 end if 3668 3669 !print *, "Have_ibz, need_iq_ibz, isirr_q", db%ft_qcache%stored_iqibz_cplex(1), iq_ibz, isirr_q 3670 3671 if (db%ft_qcache%use_3natom_cache .and. db%ft_qcache%stored_iqibz_cplex(1) == iq_ibz .and. .not. isirr_q) then 3672 !print *, "hello cache" 3673 3674 ! All 3 natom potentials for qibz are in cache. Symmetrize to get Sq for my_npert perturbations 3675 db%ft_qcache%stats(2) = db%ft_qcache%stats(2) + 1 3676 cplex = db%ft_qcache%stored_iqibz_cplex(2) 3677 3678 ABI_MALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert)) 3679 call v1phq_rotate_myperts(cryst, qibz, isym, itimrev, g0q, ngfft, cplex, nfft, & 3680 db%nspden, db%mpi_enreg, db%my_npert, db%my_pinfo, & 3681 db%ft_qcache%v1scf_3natom_qibz, v1scf) 3682 call timab(1809, 2, tsec); return 3683 end if 3684 3685 ! Note that cplex is always set to 2 here 3686 cplex = 2 3687 3688 ! Check whether iq_ibz is in cache. 3689 incache = .False. 3690 3691 if (db%ft_qcache%maxnq > 0) then 3692 ! Get number of perturbations computed for this iq_ibz as well as cplex. 3693 ! Remember that the size of v1scf in qcache depends on db%my_npert 3694 if (allocated(db%ft_qcache%key(iq_ibz)%v1scf)) then 3695 if (size(db%ft_qcache%key(iq_ibz)%v1scf, dim=1) == cplex .and. & 3696 size(db%ft_qcache%key(iq_ibz)%v1scf, dim=2) == nfft) then 3697 ! Potential in cache --> copy it in output v1scf. 3698 ABI_MALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert)) 3699 v1scf = real(db%ft_qcache%key(iq_ibz)%v1scf, kind=QCACHE_KIND) 3700 incache = .True. 3701 db%ft_qcache%stats(3) = db%ft_qcache%stats(3) + 1 3702 else 3703 ABI_ERROR("Found different cplex/nfft in cache.") 3704 end if 3705 else 3706 !call wrtout(std_out, sjoin("Cache miss for iq_ibz. Will try to interpolate it...", itoa(iq_ibz))) 3707 db%ft_qcache%stats(4) = db%ft_qcache%stats(4) + 1 3708 end if 3709 end if 3710 3711 if (.not. incache) then 3712 ! Interpolate the dvscf potentials directly in the **BZ** for my_npert perturbations. 3713 ! This is possible only if all procs inside comm_rpt call this routine else deadlock 3714 ABI_MALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert)) 3715 call db%ftinterp_qpt(qbz, nfft, ngfft, v1scf, db%comm_rpt) 3716 3717 if (db%ft_qcache%use_3natom_cache .and. isirr_q) then 3718 !call wrtout(std_out, " Collecting in cache all 3*natom DFPT potentials for q in the IBZ") 3719 if (cplex /= db%ft_qcache%stored_iqibz_cplex(2)) then 3720 ABI_REMALLOC(db%ft_qcache%v1scf_3natom_qibz, (cplex, nfft, db%nspden, db%natom3)) 3721 end if 3722 db%ft_qcache%stored_iqibz_cplex = [iq_ibz, cplex] 3723 ! Gather 3 * natom potentials on each pert proc. Note non-blocking version with request handle. 3724 call xmpi_iallgather(v1scf, cplex*nfft*db%nspden*db%my_npert, & 3725 db%ft_qcache%v1scf_3natom_qibz, db%comm_pert, db%ft_qcache%v1scf_3natom_request) 3726 end if 3727 3728 call timab(1809, 2, tsec); return 3729 end if 3730 3731 if (.not. isirr_q) then 3732 ! Must rotate iq_ibz to get potential for qpoint in the BZ. 3733 ! Be careful with the shape of output v1scf because the routine returns db%my_npert potentials. 3734 3735 if (db%my_npert == db%natom3) then 3736 ABI_MALLOC(work, (cplex, nfft, db%nspden, db%natom3)) 3737 work = v1scf 3738 call v1phq_rotate(cryst, qibz, isym, itimrev, g0q, ngfft, cplex, nfft, & 3739 db%nspden, db%mpi_enreg, work, v1scf, db%comm_pert) 3740 ABI_FREE(work) 3741 3742 else 3743 ! Parallelism over perturbations. 3744 ABI_MALLOC(work2, (cplex, nfft, db%nspden, db%natom3)) 3745 3746 if (incache) then 3747 ! Cache is distributed --> have to collect all 3 natom perts inside db%comm_pert. 3748 ABI_MALLOC(work, (cplex, nfft, db%nspden, db%natom3)) 3749 3750 ! IBCAST is much faster than a naive xmpi_sum. 3751 call timab(1806, 1, tsec) 3752 do mu=1,db%natom3 3753 root = db%pert_table(1, mu) 3754 if (root == db%me_pert) then 3755 imyp = db%pert_table(2, mu) 3756 work(:,:,:,mu) = v1scf(:,:,:,imyp) 3757 end if 3758 call xmpi_ibcast(work(:,:,:,mu), root, db%comm_pert, requests(mu), ierr) 3759 end do 3760 call xmpi_waitall(requests, ierr) 3761 call timab(1806, 2, tsec) 3762 3763 call v1phq_rotate(cryst, qibz, isym, itimrev, g0q, ngfft, cplex, nfft, & 3764 db%nspden, db%mpi_enreg, work, work2, db%comm_pert) 3765 3766 ! Now Store all 3 natom potentials for q in IBZ in cache. 3767 if (db%ft_qcache%use_3natom_cache .and. db%ft_qcache%stored_iqibz_cplex(1) /= iq_ibz) then 3768 if (cplex /= db%ft_qcache%stored_iqibz_cplex(2)) then 3769 ABI_REMALLOC(db%ft_qcache%v1scf_3natom_qibz, (cplex, nfft, db%nspden, db%natom3)) 3770 end if 3771 db%ft_qcache%stored_iqibz_cplex = [iq_ibz, cplex] 3772 db%ft_qcache%v1scf_3natom_qibz = work 3773 end if 3774 ABI_FREE(work) 3775 3776 else 3777 NOT_IMPLEMENTED_ERROR() 3778 ! All 3 natom have been read in v1scf by dvdb_readsym_allv1 3779 !call v1phq_rotate(cryst, qibz, isym, itimrev, g0q, ngfft, cplex, nfft, & 3780 ! db%nspden, db%mpi_enreg, v1scf, work2, db%comm_pert) 3781 end if 3782 3783 ! Reallocate v1scf with my_npert and extract data from work2. 3784 ABI_REMALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert)) 3785 do imyp=1,db%my_npert 3786 v1scf(:,:,:,imyp) = work2(:,:,:,db%my_pinfo(3, imyp)) 3787 end do 3788 ABI_FREE(work2) 3789 end if 3790 end if ! not isirr_q 3791 3792 call timab(1809, 2, tsec) 3793 3794 end subroutine dvdb_get_ftqbz
m_dvdb/dvdb_get_maxw [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_get_maxw
FUNCTION
Compute max_r |W(R,r)|
INPUTS
FUNCTION
m_dvdb/dvdb_get_pinfo [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_get_pinfo
FUNCTION
Return information on the perturbations available for a given q-point index.
INPUTS
iqpt=Index of the q-point
OUTPUT
nperts=Number of perturbations found. cplex=2 if potentials are complex, 1 for real pinfo(3,3*db%mpert)=Array with info on the perturbations present on file pinfo(1, ip) gives the `idir` index of the ip-th perturbation. pinfo(2, ip) gives the `ipert` index of the ip-th perturbation. pinfo(3, ip) gives `pertcase`=idir + (ipert-1)*3
SOURCE
1128 integer function dvdb_get_pinfo(db, iqpt, cplex, pinfo) result(nperts) 1129 1130 !Arguments ------------------------------------ 1131 !scalars 1132 type(dvdb_t),intent(in) :: db 1133 integer,intent(in) :: iqpt 1134 integer,intent(out) :: cplex 1135 !arrays 1136 integer,intent(out) :: pinfo(3,3*db%mpert) 1137 1138 !Local variables------------------------------- 1139 !scalars 1140 integer :: idir,ipert,iv1 1141 1142 ! ************************************************************************* 1143 1144 ! Get the number of perturbations computed for this iqpt 1145 pinfo = 0; cplex = 0; nperts = 0 1146 do ipert=1,db%natom ! selects atomic perturbations only. 1147 do idir=1,3 1148 iv1 = db%pos_dpq(idir,ipert,iqpt) 1149 if (iv1 /= 0) then 1150 nperts = nperts + 1 1151 pinfo(:, nperts) = [idir, ipert, idir + (ipert-1)*3] 1152 if (cplex == 0) cplex = db%cplex_v1(iv1) 1153 ABI_CHECK(cplex == db%cplex_v1(iv1), "cplex should be constant for given q!") 1154 end if 1155 end do 1156 end do 1157 1158 end function dvdb_get_pinfo
m_dvdb/dvdb_get_v1r_long_range [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_get_v1r_long_range
FUNCTION
Compute the long-range part of the phonon potential due to the Born effective charges, PRL 115, 176401 (2015) [[cite:Verdi2015]]. V^L_{iatom,idir}(r) = i (4pi/vol) sum_G (q+G) . Zeff_{iatom,idir} e^{i (q+G).(r - tau_{iatom})} / ((q+G) . dielt . (q+G)) where Zeff and dielt are the Born effective charge tensor and the dielectric tensor in cart coords, tau is the atom position, and vol is the volume of the unit cell. Note that internally the tensors are stored in Cartesian coordinates while in output we need the contribution due to the displacement of the iatom-sublattice along the reduced direction idir hence we need to perform some tensor gymnastics to go from Cart to reduced.
INPUTS
db = the DVDB object. qpt = the q-point in reduced coordinates. idir = direction index. iatom = atom index. nfft = number of fft points. ngfft(18) = FFT mesh. [add_qphase]=By default, the routine returns the LR potential with the e^{iqr} phase. Use add_qphase = 0 to get the lattice-periodic part.
OUTPUT
v1r_lr = dipole potential
SOURCE
6269 subroutine dvdb_get_v1r_long_range(db, qpt, idir, iatom, nfft, ngfft, v1r_lr, add_qphase) 6270 6271 !Arguments ------------------------------------ 6272 !scalars 6273 class(dvdb_t),intent(in) :: db 6274 integer,intent(in) :: idir, iatom, nfft 6275 integer,optional,intent(in) :: add_qphase 6276 !arrays 6277 integer,intent(in) :: ngfft(18) 6278 real(dp),intent(in) :: qpt(3) 6279 real(dp),intent(out) :: v1r_lr(2,nfft) 6280 6281 !Local variables------------------------------- 6282 !scalars 6283 integer :: n1, n2, n3, nfftot, ig, iphase, ii, jj, kk, ll, mm, ifft, ispden 6284 real(dp) :: fac, qGZ, qGS, denom, denom_inv, qtau, re, im, phre, phim, qg_mod, gsq_max 6285 real(dp),parameter :: tol_denom = tol8 6286 !arrays 6287 integer, allocatable :: gfft(:,:) 6288 real(dp) :: gprimd(3,3), rprimd(3,3), dielt_red(3,3) 6289 real(dp) :: qG_red(3), qG_cart(3), Zstar(3), Sstar(3,3), tau_red(3) 6290 real(dp), allocatable :: v1G_lr(:,:), v1G_lr33(:,:,:,:), workr(:,:) 6291 6292 ! ************************************************************************* 6293 6294 ! Return immediately if metals by 6295 !if (db%has_zeff .or. db%has_quadrupoles) then 6296 6297 iphase = 1; if (present(add_qphase)) iphase = add_qphase 6298 6299 ! Make sure FFT parallelism is not used 6300 n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3); nfftot = product(ngfft(1:3)) 6301 ABI_CHECK(nfftot == nfft, "FFT parallelism not supported") 6302 6303 ! Allocate memory 6304 ABI_MALLOC(gfft, (3, nfft)) 6305 ABI_MALLOC(v1G_lr, (2, nfft)) 6306 6307 ! Reciprocal and real space primitive vectors 6308 gprimd = db%cryst%gprimd; rprimd = db%cryst%rprimd 6309 6310 ! Prefactor 6311 fac = four_pi / db%cryst%ucvol 6312 6313 ! Transform the Born effective charge tensor from Cartesian to reduced coordinates 6314 ! and select the relevant direction. 6315 Zstar = matmul(transpose(gprimd), matmul(db%zeff(:,:,iatom), rprimd(:,idir))) * two_pi 6316 6317 if (db%has_quadrupoles) then 6318 ! Transform Qstar from Cartesian to reduced coordinates and select the relevant direction. 6319 Sstar = zero 6320 do ii=1,3 6321 do jj=1,3 6322 do kk=1,3 6323 do ll=1,3 6324 do mm=1,3 6325 Sstar(ii,jj) = Sstar(ii,jj) + & 6326 gprimd(mm,jj) * gprimd(ll,ii) * db%qstar(mm,ll,kk,iatom) * rprimd(kk,idir) * two_pi ** 2 6327 end do 6328 end do 6329 end do 6330 end do 6331 end do 6332 end if 6333 6334 ! Transform the dielectric tensor from Cartesian to reduced coordinates. 6335 ! q_cart e_cart q_cart = q_red (G^t e_cart G) q_red 6336 dielt_red = matmul(transpose(gprimd), matmul(db%dielt, gprimd)) * two_pi ** 2 6337 6338 ! Atom position 6339 tau_red = db%cryst%xred(:,iatom) 6340 6341 ! Get the set of G vectors 6342 ! TODO: May use zero-padded FFT with small G-sphere 6343 call get_gftt(ngfft, qpt, db%cryst%gmet, gsq_max, gfft) 6344 6345 ! Compute the long-range potential in G-space due to Z* and Q* (if present) 6346 v1G_lr = zero 6347 if (db%has_zeff .or. db%has_quadrupoles) then 6348 6349 do ig=1,nfft 6350 ! (q + G) 6351 qG_red = qpt + gfft(:,ig) 6352 qG_cart = two_pi * matmul(db%cryst%gprimd, qG_red) 6353 qG_mod = sqrt(sum(qG_cart ** 2)) 6354 ! (q + G) . Zeff(:,idir,iatom) 6355 qGZ = dot_product(qG_red, Zstar) 6356 ! (q + G) . dielt . (q + G) 6357 denom = dot_product(qG_red, matmul(dielt_red, qG_red)) 6358 ! Avoid (q + G) = 0 6359 if (denom < tol_denom) cycle 6360 denom_inv = one / denom 6361 ! HM hard cutoff, in this case qdamp takes the meaning of an energy cutoff in Hartree (hardcoded to 1 for the moment) 6362 !if (half*qG_mod**2 > 1) cycle 6363 if (db%qdamp > zero) denom_inv = denom_inv * exp(-qG_mod ** 2 / (four * db%qdamp)) 6364 qGS = zero 6365 if (db%has_quadrupoles) then 6366 do ii=1,3 6367 do jj=1,3 6368 qGS = qGS + qG_red(ii) * qG_red(jj) * Sstar(ii,jj) / two 6369 end do 6370 end do 6371 end if 6372 6373 ! Phase factor exp(-i (q+G) . tau) 6374 qtau = - two_pi * dot_product(qG_red, tau_red) 6375 phre = cos(qtau); phim = sin(qtau) 6376 !phre = one; phim = zero 6377 6378 re = +fac * qGS * denom_inv !re = zero 6379 im = fac * qGZ * denom_inv 6380 v1G_lr(1,ig) = phre * re - phim * im 6381 v1G_lr(2,ig) = phim * re + phre * im 6382 end do 6383 end if 6384 6385 ! FFT to get the long-range potential in r-space 6386 call fourdp(2, v1G_lr, v1r_lr, 1, db%mpi_enreg, nfft, 1, ngfft, 0) 6387 6388 if (db%has_efield) then 6389 ! Add term due to Electric field. 6390 ! TODO: Change API to account for ispden/isppol. return nspden LR part 6391 ! although only the electric field part depends on nsppden. 6392 !v1r_lr = zero ! Comment this line to have only efield contribution 6393 ABI_CHECK(db%nspden == 1, "nspden != 1 not coded") 6394 ispden = 1 6395 ABI_CALLOC(v1G_lr33, (3, 3, 2, nfft)) 6396 do ig=1,nfft 6397 !if (ig > 1) cycle 6398 ! (q + G) 6399 qG_red = qpt + gfft(:,ig) 6400 qG_cart = two_pi * matmul(db%cryst%gprimd, qG_red) 6401 qG_mod = sqrt(sum(qG_cart ** 2)) 6402 ! (q + G) . Zeff(:,idir,iatom) 6403 !qGZ = dot_product(qG_red, Zstar) 6404 ! (q + G) . dielt . (q + G) 6405 denom = dot_product(qG_red, matmul(dielt_red, qG_red)) 6406 ! Avoid (q + G) = 0 6407 if (denom < tol_denom) cycle 6408 denom_inv = one / denom 6409 if (db%qdamp > zero) denom_inv = denom_inv * exp(-qG_mod ** 2 / (four * db%qdamp)) 6410 fac = (four_pi / db%cryst%ucvol) * denom_inv !* qGZ 6411 ! Phase factor exp(-i (q+G) . tau) 6412 qtau = - two_pi * dot_product(qG_red, tau_red) 6413 phre = cos(qtau); phim = sin(qtau) 6414 !phre = one; phim = zero 6415 6416 do ii=1,3 6417 do jj=1,3 6418 v1G_lr33(ii, jj, 1, ig) = fac * phre * qG_red(ii) * qG_red(jj) 6419 v1G_lr33(ii, jj, 2, ig) = fac * phim * qG_red(ii) * qG_red(jj) 6420 end do 6421 end do 6422 end do ! ig 6423 6424 ABI_MALLOC(workr, (2, nfft)) 6425 do ii=1,3 6426 do jj=1,3 6427 v1G_lr = v1G_lr33(ii, jj, :, :) 6428 call fourdp(2, v1G_lr, workr, 1, db%mpi_enreg, nfft, 1, ngfft, 0) 6429 ! Two pi comes for qpt but we should check whether the gradient wrt E-field is in gprimd or 2pi gprimd coordinates. 6430 ! MG: Remove two_pi factor because jump discontinuity in the real part for G != 0 are overestimated. 6431 do ifft=1,nfft 6432 !v1r_lr(:, ifft) = v1r_lr(:, ifft) - Zstar(ii) * db%v1r_efield(ifft, jj, ispden) * workr(:, ifft) * two_pi 6433 v1r_lr(:, ifft) = v1r_lr(:, ifft) - Zstar(ii) * db%v1r_efield(ifft, jj, ispden) * workr(:, ifft) ! * two_pi 6434 end do 6435 end do 6436 end do 6437 6438 ABI_FREE(workr) 6439 ABI_FREE(v1G_lr33) 6440 end if 6441 6442 ! Multiply by exp(i q.r) 6443 if (iphase == 1) call times_eikr(qpt, ngfft, nfft, 1, v1r_lr) 6444 6445 ABI_FREE(gfft) 6446 ABI_FREE(v1G_lr) 6447 6448 end subroutine dvdb_get_v1r_long_range
m_dvdb/dvdb_get_v1scf_qpt [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_get_v1scf_qpt
FUNCTION
Fourier interpolation of potentials for a given q-point This routine is meant to replace dvdb_ftinterp_qpt by performing the interpolation one perturbation at a time.
INPUTS
qpt(3)=q-point in reduced coordinates. nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT nrpt=Number of R-points = number of q-points in the full BZ nspden=Number of spin densities. ipert=index of the perturbation to be treated [1,natom3] v1scf_rpt(2,nrpt,nfft,nspden)=phonon perturbation potential in real space lattice representation. comm=MPI communicator
OUTPUT
v1scf_qpt(2*nfft, nspden)=Interpolated DFPT potentials at the given q-point.
SOURCE
4354 subroutine dvdb_get_v1scf_qpt(db, cryst, qpt, nfft, ngfft, nrpt, nspden, & 4355 ipert, v1scf_rpt, v1scf_qpt, comm) 4356 4357 !Arguments ------------------------------------ 4358 !scalars 4359 integer,intent(in) :: nfft,nrpt,nspden,ipert,comm 4360 class(dvdb_t),intent(in) :: db 4361 type(crystal_t),intent(in) :: cryst 4362 !arrays 4363 integer,intent(in) :: ngfft(18) 4364 real(dp),intent(in) :: qpt(3) 4365 real(dp),intent(in) :: v1scf_rpt(2,nrpt,nfft,db%nspden) 4366 real(dp),intent(out) :: v1scf_qpt(2,nfft,db%nspden) 4367 4368 !Local variables------------------------------- 4369 !scalars 4370 integer,parameter :: cplex2=2 4371 integer :: ir,ispden,ifft,idir,iat,timerev_q,nproc,my_rank,cnt,ierr 4372 real(dp) :: wr,wi 4373 !arrays 4374 integer :: symq(4,2,db%cryst%nsym) 4375 real(dp),allocatable :: eiqr(:,:), v1r_lr(:,:) 4376 4377 ! ************************************************************************* 4378 4379 !ABI_ERROR("Legacy code!") 4380 4381 ABI_UNUSED(cryst%natom) 4382 ABI_UNUSED(nspden) 4383 4384 my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm) 4385 4386 ABI_MALLOC(v1r_lr, (2,nfft)) 4387 4388 ! Examine the symmetries of the q wavevector 4389 call littlegroup_q(db%cryst%nsym, qpt, symq, db%cryst%symrec, db%cryst%symafm, timerev_q, prtvol=db%prtvol) 4390 4391 ! Compute FT phases for this q-point. 4392 ABI_MALLOC(eiqr, (2, db%my_nrpt)) 4393 call calc_eiqr(qpt, db%my_nrpt, db%my_rpt, eiqr) 4394 4395 idir = mod(ipert-1, 3) + 1; iat = (ipert - idir) / 3 + 1 4396 4397 ! Compute long-range part of the coupling potential 4398 v1r_lr = zero; cnt = 0 4399 if (db%add_lr > 0) call db%get_v1r_long_range(qpt, idir, iat, nfft, ngfft, v1r_lr) 4400 4401 ! TODO: If high-symmetry q-points, one could save flops by FFT interpolating the independent 4402 ! TODO: Use ZGEMM with MPI 4403 ! perturbations and then rotate ... 4404 v1scf_qpt = zero; cnt = 0 4405 do ispden=1,db%nspden 4406 do ifft=1,nfft 4407 cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI-parallelism 4408 4409 do ir=1,db%my_nrpt 4410 wr = v1scf_rpt(1, ir,ifft,ispden) 4411 wi = v1scf_rpt(2, ir,ifft,ispden) 4412 v1scf_qpt(1,ifft,ispden) = v1scf_qpt(1,ifft,ispden) + wr*eiqr(1,ir) - wi * eiqr(2,ir) 4413 v1scf_qpt(2,ifft,ispden) = v1scf_qpt(2,ifft,ispden) + wr*eiqr(2,ir) + wi * eiqr(1,ir) 4414 end do 4415 4416 ! Add the long-range part of the potential 4417 if (db%add_lr > 0) then 4418 v1scf_qpt(1,ifft,ispden) = v1scf_qpt(1,ifft,ispden) + v1r_lr(1,ifft) 4419 v1scf_qpt(2,ifft,ispden) = v1scf_qpt(2,ifft,ispden) + v1r_lr(2,ifft) 4420 end if 4421 if (db%add_lr == 4) then 4422 v1scf_qpt(1,ifft,ispden) = v1r_lr(1,ifft) 4423 v1scf_qpt(2,ifft,ispden) = v1r_lr(2,ifft) 4424 end if 4425 end do ! ifft 4426 4427 call xmpi_sum(v1scf_qpt(:,:,ispden), comm, ierr) 4428 4429 ! Remove the phase. 4430 call times_eikr(-qpt, ngfft, nfft, 1, v1scf_qpt(:,:,ispden)) 4431 end do 4432 4433 ! Be careful with gamma and cplex! 4434 if (db%symv1 == 1) then 4435 call v1phq_symmetrize(db%cryst, idir, iat, symq, ngfft, cplex2, nfft, db%nspden, db%nsppol, db%mpi_enreg, v1scf_qpt) 4436 end if 4437 4438 ABI_FREE(eiqr) 4439 ABI_FREE(v1r_lr) 4440 4441 end subroutine dvdb_get_v1scf_qpt
m_dvdb/dvdb_get_v1scf_rpt [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_get_v1scf_rpt
FUNCTION
Compute the phonon perturbation potential in real space lattice representation. This routine is meant to replace dvdb_ftinterp_setup and performs the potential interpolation one perturbation at a time.
INPUTS
ngqpt(3)=Divisions of the ab-initio q-mesh. nqshift=Number of shifts used to generated the ab-initio q-mesh. qshift(3,nqshift)=The shifts of the ab-initio q-mesh. nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT nrpt=Number of R-points = number of q-points in the full BZ nspden=Number of spin densities. ipert=index of the perturbation to be treated [1,natom3] comm=MPI communicator
OUTPUT
v1scf_rpt(2,nrpt,nfft,nspden)
SOURCE
4012 subroutine dvdb_get_v1scf_rpt(db, cryst, ngqpt, nqshift, qshift, nfft, ngfft, & 4013 nrpt, nspden, ipert, v1scf_rpt, comm) 4014 4015 !Arguments ------------------------------------ 4016 !scalars 4017 integer,intent(in) :: nqshift,nfft,nrpt,nspden,ipert,comm 4018 class(dvdb_t),target,intent(inout) :: db 4019 !arrays 4020 integer,intent(in) :: ngqpt(3),ngfft(18) 4021 real(dp),intent(in) :: qshift(3,nqshift) 4022 real(dp),intent(out) :: v1scf_rpt(2,nrpt,nfft,nspden) 4023 type(crystal_t),intent(in) :: cryst 4024 4025 !Local variables------------------------------- 4026 !scalars 4027 integer,parameter :: sppoldbl1=1, timrev1=1 4028 integer :: my_qptopt,iq_ibz,nqibz,iq_bz,nqbz 4029 integer :: ii,iq_dvdb,cplex_qibz,ispden,irpt,idir,iat 4030 integer :: iqst,nqst,itimrev,tsign,isym,ix,iy,iz,nq1,nq2,nq3,r1,r2,r3 4031 integer :: nproc,my_rank,ifft,cnt,ierr 4032 character(len=500) :: msg 4033 real(dp) :: dksqmax 4034 logical :: isirr_q, found 4035 !arrays 4036 integer :: qptrlatt(3,3),g0q(3) 4037 integer,allocatable :: indqq(:,:),iperm(:),bz2ibz_sort(:),nqsts(:),iqs_dvdb(:) 4038 real(dp) :: qpt_bz(3),shift(3) 4039 real(dp) :: cpu, wall, gflops 4040 real(dp),allocatable :: qibz(:,:),qbz(:,:),wtq(:),emiqr(:,:) 4041 real(dp),allocatable :: v1r_qibz(:,:,:,:),v1r_qbz(:,:,:,:), v1r_lr(:,:) 4042 4043 ! ************************************************************************* 4044 4045 !ABI_ERROR("Legacy code!") 4046 4047 nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm) 4048 4049 nq1 = ngqpt(1); nq2 = ngqpt(2); nq3 = ngqpt(3); my_qptopt = 1 !; if (present(qptopt)) my_qptopt = qptopt 4050 4051 ! Generate the q-mesh by finding the IBZ and the corresponding weights. 4052 qptrlatt = 0 4053 do ii=1,3 4054 qptrlatt(ii,ii) = ngqpt(ii) 4055 end do 4056 4057 ! Get IBZ and BZ. 4058 call kpts_ibz_from_kptrlatt(cryst, qptrlatt, my_qptopt, nqshift, qshift, & 4059 nqibz, qibz, wtq, nqbz, qbz) ! new_kptrlatt, new_shiftk) 4060 4061 !write(std_out,*)"Irreducible q-points:" 4062 !do iq_ibz=1,nqibz; write(std_out,*)trim(ktoa(qibz(:,iq_ibz))),wtq(iq_ibz)*nqbz; end do 4063 ABI_CHECK(nqbz == product(ngqpt) * nqshift, "nqbz /= product(ngqpt) * nqshift") 4064 ABI_CHECK(nqbz == nrpt, "nqbz /= nrpt") 4065 4066 db%my_nrpt = nqbz 4067 4068 ABI_CHECK(nspden == db%nspden, "nspden /= db%nspden") 4069 4070 ! We want a gamma centered q-mesh for FFT. 4071 ABI_CHECK(nqshift == 1, "nshift > 1 not supported") 4072 ABI_CHECK(all(qshift(:,1) == zero), "qshift != 0 not supported") 4073 4074 ABI_FREE(qbz) 4075 ABI_MALLOC(qbz, (3, nqbz)) 4076 ii = 0 4077 do iz=0,nq3-1 4078 do iy=0,nq2-1 4079 do ix=0,nq1-1 4080 ii = ii + 1 4081 qbz(:, ii) = [ix/dble(nq1), iy/dble(nq2), iz/dble(nq3)] 4082 call wrap2_pmhalf([ix/dble(nq1), iy/dble(nq2), iz/dble(nq3)], qbz(:,ii), shift) 4083 end do 4084 end do 4085 end do 4086 4087 ! Compute real-space points. 4088 ! Use the following indexing (N means ngfft of the adequate direction) 4089 ! 0 1 2 3 ... N/2 -(N-1)/2 ... -1 <= gc 4090 ! 1 2 3 4 ....N/2+1 N/2+2 ... N <= index ig 4091 ABI_MALLOC(db%my_rpt, (3, db%my_nrpt)) 4092 ii = 0 4093 do iz=1,nq3 4094 r3 = ig2gfft(iz,nq3) 4095 do iy=1,nq2 4096 r2 = ig2gfft(iy,nq2) 4097 do ix=1,nq1 4098 r1 = ig2gfft(ix,nq1) 4099 ii = ii + 1 4100 db%my_rpt(:,ii) = [r1, r2, r3] 4101 end do 4102 end do 4103 end do 4104 4105 ! Find correspondence BZ --> IBZ. Note: 4106 ! q --> -q symmetry is always used for phonons. 4107 ! we use symrec instead of symrel 4108 ABI_MALLOC(indqq, (nqbz*sppoldbl1,6)) 4109 call listkk(dksqmax,cryst%gmet,indqq,qibz,qbz,nqibz,nqbz,cryst%nsym,& 4110 sppoldbl1,cryst%symafm,cryst%symrec,timrev1,comm,use_symrec=.True.) 4111 4112 !qrank = krank_from_kptrlatt(new%nqibz, new%qibz, qptrlatt, compute_invrank=.False.) 4113 !call qrank%get_mapping(new%nqbz, new%qbz, dksqmax, cryst%gmet, temp, & 4114 ! cryst%nsym, cryst%symafm, cryst%symrec, 1, use_symrec=.True.) 4115 !call qrank%free() 4116 4117 if (dksqmax > tol12) then 4118 ABI_BUG("Something wrong in the generation of the q-points in the BZ! Cannot map BZ --> IBZ") 4119 end if 4120 4121 ! Construct sorted mapping BZ --> IBZ to speedup qbz search below. 4122 ABI_MALLOC(iperm, (nqbz)) 4123 ABI_MALLOC(bz2ibz_sort, (nqbz)) 4124 iperm = [(ii, ii=1,nqbz)] 4125 bz2ibz_sort = indqq(:,1) 4126 call sort_int(nqbz, bz2ibz_sort, iperm) 4127 4128 ! Reconstruct the IBZ according to what is present in the DVDB. 4129 ABI_MALLOC(nqsts, (nqibz)) 4130 ABI_MALLOC(iqs_dvdb, (nqibz)) 4131 ABI_MALLOC(v1r_lr, (2,nfft)) 4132 4133 iqst = 0 4134 do iq_ibz=1,nqibz 4135 ! In each q-point star, count the number of q-points and find the one present in DVDB. 4136 nqst = 0 4137 found = .false. 4138 do ii=iqst+1,nqbz 4139 if (bz2ibz_sort(ii) /= iq_ibz) exit 4140 nqst = nqst + 1 4141 4142 iq_bz = iperm(ii) 4143 if (.not. found) then 4144 iq_dvdb = db%findq(qbz(:,iq_bz)) 4145 if (iq_dvdb /= -1) then 4146 qibz(:,iq_ibz) = qbz(:,iq_bz) 4147 iqs_dvdb(iq_ibz) = iq_dvdb 4148 found = .true. 4149 end if 4150 end if 4151 end do 4152 4153 ! Check that nqst has been counted properly. 4154 ABI_CHECK(nqst > 0 .and. bz2ibz_sort(iqst+1) == iq_ibz, "Wrong iqst") 4155 if (abs(nqst - wtq(iq_ibz) * nqbz) > tol12) then 4156 write(std_out,*)nqst, wtq(iq_ibz) * nqbz 4157 ABI_ERROR("Error in counting q-point star or in the weights.") 4158 end if 4159 4160 ! Check that the q-point has been found in DVDB. 4161 if (.not. found) then 4162 ABI_ERROR(sjoin("Cannot find symmetric q-point of:", ktoa(qibz(:,iq_ibz)), "in DVDB file")) 4163 end if 4164 !write(std_out,*)sjoin("qpt irred:",ktoa(qibz(:,iq_ibz))) 4165 4166 iqst = iqst + nqst 4167 nqsts(iq_ibz) = nqst 4168 end do 4169 4170 ! Redo the mapping with the new IBZ 4171 call listkk(dksqmax,cryst%gmet,indqq,qibz,qbz,nqibz,nqbz,cryst%nsym,& 4172 sppoldbl1,cryst%symafm,cryst%symrec,timrev1,comm,use_symrec=.True.) 4173 4174 !qrank = krank_from_kptrlatt(new%nqibz, new%qibz, qptrlatt, compute_invrank=.False.) 4175 !call qrank%get_mapping(new%nqbz, new%qbz, dksqmax, cryst%gmet, temp, & 4176 ! cryst%nsym, cryst%symafm, cryst%symrec, 1, use_symrec=.True.) 4177 !call qrank%free() 4178 4179 if (dksqmax > tol12) then 4180 ABI_BUG("Something wrong in the generation of the q-points in the BZ! Cannot map BZ --> IBZ") 4181 end if 4182 4183 ABI_MALLOC(emiqr, (2, db%my_nrpt)) 4184 v1scf_rpt = zero 4185 4186 ABI_MALLOC_OR_DIE(v1r_qbz, (2, nfft, db%nspden, db%natom3), ierr) 4187 !v1r_qbz = huge(one) 4188 4189 iqst = 0 4190 call cwtime(cpu, wall, gflops, "start") 4191 do iq_ibz=1,nqibz 4192 4193 ! Get potentials for this IBZ q-point on the real-space FFT mesh. 4194 ! This call allocates v1r_qibz(cplex_qibz, nfft, nspden, 3*natom) 4195 ! TODO: Interface with qcache 4196 call db%readsym_allv1(iqs_dvdb(iq_ibz), cplex_qibz, nfft, ngfft, v1r_qibz, comm) 4197 4198 ! Reconstruct by symmetry the potentials for the star of this q-point, perform FT and accumulate 4199 ! Be careful with the gamma point. 4200 do ii=1,nqsts(iq_ibz) 4201 iqst = iqst + 1 4202 iq_bz = iperm(iqst) 4203 ABI_CHECK(iq_ibz == indqq(iq_bz,1), "iq_ibz !/ ind qq(1)") 4204 isym = indqq(iq_bz,2); itimrev = indqq(iq_bz,6) + 1; g0q = indqq(iq_bz,3:5) ! IS(q_ibz) + g0q = q_bz 4205 tsign = 3-2*itimrev 4206 4207 qpt_bz = qbz(:, iq_bz) 4208 !write(std_out,*)" treating:",trim(ktoa(qpt_bz)) 4209 isirr_q = (isym == 1 .and. itimrev == 1 .and. all(g0q == 0)) 4210 !ABI_CHECK(all(g0q == 0), "g0q /= 0") 4211 4212 ! Compute long-range part of the coupling potential 4213 !call cwtime(cpu, wall, gflops, "start") 4214 v1r_lr = zero; cnt = 0 4215 if (db%add_lr /= 0) then 4216 idir = mod(ipert-1, 3) + 1; iat = (ipert - idir) / 3 + 1 4217 call db%get_v1r_long_range(qpt_bz, idir, iat, nfft, ngfft, v1r_lr) 4218 end if 4219 !call cwtime_report(" dvdb_get_v1r_long_range", cpu, wall, gflops) 4220 4221 if (cplex_qibz == 1) then 4222 ! Gamma point. 4223 ABI_CHECK(nqsts(iq_ibz) == 1, "cplex_qibz == 1 and nq nqst /= 1 (should be gamma)") 4224 ABI_CHECK(all(g0q == 0), "gamma point with g0q /= 0") 4225 4226 ! Substract the long-range part of the potential 4227 if (db%add_lr /= 0) then 4228 do ispden=1,db%nspden 4229 v1r_qibz(1,:,ispden,ipert) = v1r_qibz(1,:,ispden,ipert) - v1r_lr(1,:) 4230 end do 4231 end if 4232 4233 ! SLOW FT. 4234 !call cwtime(cpu, wall, gflops, "start") 4235 cnt = 0 4236 do ispden=1,db%nspden 4237 do irpt=1,db%my_nrpt 4238 ! MPI-parallelism 4239 cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle 4240 do ifft=1,nfft 4241 v1scf_rpt(1,irpt,ifft,ispden) = v1scf_rpt(1,irpt,ifft,ispden) + & 4242 v1r_qibz(1, ifft, ispden, ipert) 4243 end do 4244 end do 4245 end do 4246 !call cwtime_report(" slow fft", cpu, wall, gflops) 4247 4248 else 4249 ! q /= Gamma 4250 ! Get the periodic part of the potential in BZ (v1r_qbz) 4251 if (isirr_q) then 4252 !write(std_out,*)sjoin("qpt irred:",ktoa(qpt_bz)) 4253 v1r_qbz = v1r_qibz 4254 else 4255 !call cwtime(cpu, wall, gflops, "start") 4256 call v1phq_rotate(cryst, qibz(:,iq_ibz), isym, itimrev, g0q, & 4257 ngfft, cplex_qibz, nfft, db%nspden, db%mpi_enreg, v1r_qibz, v1r_qbz, xmpi_comm_self) 4258 !call cwtime_report(" rotate", cpu, wall, gflops) 4259 !v1r_qbz = zero; v1r_qbz = v1r_qibz 4260 4261 !call times_eigr(-tsign * g0q, ngfft, nfft, db%nspden*db%natom3, v1r_qbz) 4262 !call times_eigr(+tsign * g0q, ngfft, nfft, db%nspden*db%natom3, v1r_qbz) 4263 !if (itimrev == 2) v1r_qbz(2,:,:,:) = -v1r_qbz(2,:,:,:) 4264 !call times_eigr(-tsign * g0q, ngfft, nfft, db%nspden*db%natom3, v1r_qbz) 4265 !call times_eigr(+tsign * g0q, ngfft, nfft, db%nspden*db%natom3, v1r_qbz) 4266 end if 4267 4268 ! Multiply by e^{iqpt_bz.r} 4269 call times_eikr(qpt_bz, ngfft, nfft, db%nspden*db%natom3, v1r_qbz) 4270 4271 ! Substract the long-range part of the potential 4272 if (db%add_lr /= 0) then 4273 do ispden=1,db%nspden 4274 v1r_qbz(1,:,ispden,ipert) = v1r_qbz(1,:,ispden,ipert) - v1r_lr(1,:) 4275 v1r_qbz(2,:,ispden,ipert) = v1r_qbz(2,:,ispden,ipert) - v1r_lr(2,:) 4276 end do 4277 end if 4278 4279 ! Compute FT phases for this qpt_bz. 4280 call calc_eiqr(-qpt_bz, db%my_nrpt, db%my_rpt, emiqr) 4281 !call cwtime_report(" phases", cpu, wall, gflops) 4282 4283 ! SLOW FT. 4284 cnt = 0 4285 do ispden=1,db%nspden 4286 do ifft=1,nfft 4287 cnt = cnt + 1; if (mod(cnt, nproc) /= my_rank) cycle ! MPI parallelism. 4288 4289 v1scf_rpt(1,:,ifft,ispden) = v1scf_rpt(1,:,ifft,ispden) & 4290 + emiqr(1,:) * v1r_qbz(1, ifft, ispden, ipert) & 4291 - emiqr(2,:) * v1r_qbz(2, ifft, ispden, ipert) 4292 4293 v1scf_rpt(2,:,ifft,ispden) = v1scf_rpt(2,:,ifft,ispden) & 4294 + emiqr(1,:) * v1r_qbz(2, ifft, ispden, ipert) & 4295 + emiqr(2,:) * v1r_qbz(1, ifft, ispden, ipert) 4296 end do 4297 end do 4298 !call cwtime_report(" slow fft", cpu, wall, gflops) 4299 end if 4300 4301 end do ! iqst 4302 4303 write(msg,'(2(a,i0),a)') " q-point [",iq_ibz,"/",nqibz,"]" 4304 call cwtime_report(msg, cpu, wall, gflops) 4305 4306 ABI_FREE(v1r_qibz) 4307 end do ! iq_ibz 4308 ABI_CHECK(iqst == nqbz, "iqst /= nqbz") 4309 4310 v1scf_rpt = v1scf_rpt / nqbz 4311 call xmpi_sum(v1scf_rpt, comm, ierr) 4312 4313 ABI_FREE(emiqr) 4314 ABI_FREE(qibz) 4315 ABI_FREE(wtq) 4316 ABI_FREE(qbz) 4317 ABI_FREE(indqq) 4318 ABI_FREE(iperm) 4319 ABI_FREE(bz2ibz_sort) 4320 ABI_FREE(iqs_dvdb) 4321 ABI_FREE(nqsts) 4322 ABI_FREE(v1r_qbz) 4323 ABI_FREE(v1r_lr) 4324 4325 end subroutine dvdb_get_v1scf_rpt
m_dvdb/dvdb_interpolate_and_write [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_interpolate_and_write
FUNCTION
Interpolate the phonon potential onto a fine q-point grid and write the data in a new DVDB file.
INPUTS
OUTPUT
SOURCE
6627 subroutine dvdb_interpolate_and_write(dvdb, dtset, new_dvdb_fname, ngfft, ngfftf, cryst, & 6628 ngqpt_coarse, nqshift_coarse, qshift_coarse, comm, custom_qpt) 6629 6630 !Arguments ------------------------------------ 6631 !scalars 6632 integer,intent(in) :: nqshift_coarse, comm 6633 character(len=*),intent(in) :: new_dvdb_fname 6634 type(crystal_t),intent(in) :: cryst 6635 class(dvdb_t),intent(inout) :: dvdb 6636 type(dataset_type),intent(in) :: dtset 6637 !arrays 6638 integer,intent(in) :: ngfft(18), ngfftf(18) 6639 integer,intent(in) :: ngqpt_coarse(3) 6640 real(dp),intent(in) :: qshift_coarse(3,nqshift_coarse) 6641 real(dp),optional,intent(in) :: custom_qpt(:,:) 6642 6643 !Local variables ------------------------------ 6644 !scalars 6645 integer,parameter :: master=0 6646 integer :: fform_pot=111 6647 integer :: my_rank,nproc,idir,ipert,iat,ipc,ispden, ierr 6648 integer :: cplex,db_iqpt,natom,natom3,npc,trev_q,nspden 6649 integer :: nqbz, nqibz, iq, ifft, nqbz_coarse 6650 integer :: nperts_read, nperts_interpolate, nperts 6651 integer :: nqpt_read, nqpt_interpolate, qptopt, qtimrev 6652 integer :: nfft,nfftf, dimv1 6653 integer :: ount, unt, fform 6654 integer :: ncid, ncerr 6655 logical :: use_netcdf 6656 real(dp) :: cpu, wall, gflops, cpu_all, wall_all, gflops_all 6657 character(len=500) :: msg 6658 character(len=fnlen) :: tmp_fname 6659 type(hdr_type) :: hdr_ref 6660 !arrays 6661 integer :: qptrlatt(3,3), rfdir(3) 6662 integer :: symq(4,2,cryst%nsym) 6663 integer,allocatable :: pinfo(:,:),rfpert(:),pertsy(:,:,:),iq_read(:),this_pertsy(:,:) 6664 real(dp) :: qpt(3), rhog1_g0(2) 6665 real(dp),allocatable :: v1scf(:,:,:), v1scf_rpt(:,:,:,:),v1(:) 6666 real(dp),allocatable :: wtq(:),qibz(:,:),qbz(:,:),q_interp(:,:),q_read(:,:) 6667 6668 !************************************************************************ 6669 6670 my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm) 6671 6672 write(msg, '(2a)') " Interpolation of the electron-phonon coupling potential", ch10 6673 call wrtout(ab_out, msg, do_flush=.True.); call wrtout(std_out, msg, do_flush=.True.) 6674 6675 call cwtime(cpu_all, wall_all, gflops_all, "start") 6676 6677 if (dtset%eph_task == 5 .or. present(custom_qpt)) then 6678 msg = sjoin(" From coarse q-mesh:", ltoa(ngqpt_coarse), "to:", ltoa(dtset%eph_ngqpt_fine)) 6679 call wrtout([std_out, ab_out], msg) 6680 ! Setup fine q-point grid in the IBZ 6681 ! Generate the list of irreducible q-points in the grid 6682 qptrlatt = 0 6683 qptrlatt(1,1) = dtset%eph_ngqpt_fine(1); qptrlatt(2,2) = dtset%eph_ngqpt_fine(2); qptrlatt(3,3) = dtset%eph_ngqpt_fine(3) 6684 qptopt = 1; if (dtset%qptopt /= 0) qptopt = dtset%qptopt 6685 qtimrev = kpts_timrev_from_kptopt(qptopt) 6686 call wrtout(std_out, sjoin(" Generating q-IBZ for DVDB with qptopt:", itoa(qptopt))) 6687 call kpts_ibz_from_kptrlatt(cryst, qptrlatt, qptopt, 1, [zero, zero, zero], nqibz, qibz, wtq, nqbz, qbz) 6688 6689 else if (dtset%eph_task == -5) then 6690 msg = sjoin(" Using list of q-points specified by ph_qpath with ", itoa(dtset%ph_nqpath), "qpoints") 6691 call wrtout([std_out, ab_out], msg) 6692 ABI_CHECK(dtset%ph_nqpath > 0, "ph_nqpath must be specified when eph_task == -5") 6693 nqibz = dtset%ph_nqpath 6694 ABI_MALLOC(qibz, (3, nqibz)) 6695 qibz = dtset%ph_qpath(:, 1:nqibz) 6696 ABI_CALLOC(wtq, (nqibz)) 6697 nqbz = nqibz 6698 ABI_MALLOC(qbz, (3, nqbz)) 6699 qbz = qibz 6700 6701 else 6702 ABI_ERROR(sjoin("Invalid eph_task", itoa(dtset%eph_task))) 6703 end if 6704 6705 if (present(custom_qpt)) then 6706 ABI_SFREE(qibz) 6707 ABI_SFREE(wtq) 6708 ABI_SFREE(qbz) 6709 nqibz = size(custom_qpt,dim=2) 6710 ABI_MALLOC(qibz, (3, nqibz)) 6711 qibz = custom_qpt 6712 ABI_CALLOC(wtq, (nqibz)) 6713 nqbz = nqibz 6714 ABI_MALLOC(qbz, (3, nqbz)) 6715 qbz = qibz 6716 end if 6717 6718 nfft = product(ngfft(1:3)); nfftf = product(ngfftf(1:3)) 6719 6720 ! check that ngqpt_coarse is in DVDB. 6721 nqbz_coarse = product(ngqpt_coarse) * nqshift_coarse 6722 6723 ! ========================================== 6724 ! Prepare the header to write the potentials 6725 ! ========================================== 6726 6727 ! Read the first header 6728 if (my_rank == master) then 6729 if (open_file(dvdb%path, msg, newunit=unt, form="unformatted", status="old", action="read") /= 0) then 6730 ABI_ERROR(msg) 6731 end if 6732 read(unt, err=10, iomsg=msg) dvdb%version 6733 read(unt, err=10, iomsg=msg) dvdb%numv1 6734 6735 call hdr_fort_read(hdr_ref, unt, fform) 6736 if (dvdb_check_fform(fform, "read_dvdb", msg) /= 0) then 6737 ABI_ERROR(sjoin("While reading:", dvdb%path, ch10, msg)) 6738 end if 6739 close(unt) 6740 end if 6741 6742 ! Reset the symmetries of the header 6743 ! One might have disable the symmetries in the response function calculation 6744 ! that produced the initial set of potentials present in the DVDB. 6745 ! This is because the symmetry features are not used in all parts 6746 ! of the response function driver. 6747 !write(std_out,*)hdr_ref%nsym, cryst%nsym 6748 !ABI_CHECK(hdr_ref%nsym == cryst%nsym, "Diff nsym") 6749 ABI_SFREE(hdr_ref%symrel) 6750 ABI_SFREE(hdr_ref%tnons) 6751 ABI_SFREE(hdr_ref%symafm) 6752 hdr_ref%nsym = cryst%nsym 6753 ABI_MALLOC(hdr_ref%symrel, (3,3,hdr_ref%nsym)) 6754 ABI_MALLOC(hdr_ref%tnons, (3,hdr_ref%nsym)) 6755 ABI_MALLOC(hdr_ref%symafm, (hdr_ref%nsym)) 6756 6757 hdr_ref%symrel(:,:,:) = cryst%symrel(:,:,:) 6758 hdr_ref%tnons(:,:) = cryst%tnons(:,:) 6759 hdr_ref%symafm(:) = cryst%symafm(:) 6760 hdr_ref%ngfft = ngfftf(1:3) 6761 6762 ! ======================================= 6763 ! Open DVDB and copy important dimensions 6764 ! ======================================= 6765 6766 call dvdb%open_read(ngfftf, xmpi_comm_self) 6767 6768 ! Besides perturbations with same q-points won't be contiguous on file --> IO is gonna be inefficient. 6769 call dvdb%print(prtvol=dtset%prtvol) 6770 6771 natom = cryst%natom 6772 natom3 = 3 * natom 6773 nspden = dvdb%nspden 6774 6775 ! ================================================== 6776 ! Sort the q-points to read and those to interpolate 6777 ! and find the irreducible perturbations 6778 ! ================================================== 6779 ABI_MALLOC(iq_read, (nqibz)) 6780 ABI_MALLOC(q_read, (3,nqibz)) 6781 ABI_MALLOC(q_interp, (3,nqibz)) 6782 ABI_MALLOC(pertsy, (nqibz,3,dvdb%mpert)) 6783 ABI_MALLOC(this_pertsy, (3,dvdb%mpert)) 6784 ABI_MALLOC(rfpert, (dvdb%mpert)) 6785 ABI_MALLOC(pinfo, (3,3*dvdb%mpert)) 6786 rfpert = 0; rfpert(1:cryst%natom) = 1; rfdir = 1 6787 6788 pertsy = 0 6789 nqpt_read = 0 6790 nperts_read = 0 6791 nqpt_interpolate = 0 6792 nperts_interpolate = 0 6793 6794 do iq=1,nqibz 6795 qpt = qibz(:,iq) 6796 6797 ! Find the index of the q-point in the DVDB. 6798 db_iqpt = dvdb%findq(qpt) 6799 !if (db_iqpt /= 1) db_iqpt = -1 6800 6801 if (db_iqpt /= -1) then 6802 if (dvdb%prtvol > 0) call wrtout(std_out, sjoin("Q-point: ",ktoa(qpt)," found in DVDB with index ",itoa(db_iqpt))) 6803 nqpt_read = nqpt_read + 1 6804 q_read(:,nqpt_read) = qpt(:) 6805 iq_read(nqpt_read) = db_iqpt 6806 6807 ! Count the perturbations 6808 npc = dvdb_get_pinfo(dvdb, db_iqpt, cplex, pinfo) 6809 do ipc=1,npc 6810 idir = pinfo(1,ipc); iat = pinfo(2,ipc); ipert = pinfo(3, ipc) 6811 if (iat .le. natom) nperts_read = nperts_read + 1 6812 end do 6813 6814 else 6815 if (dvdb%prtvol > 0) call wrtout(std_out, sjoin("Q-point: ",ktoa(qpt), "not found in DVDB. Will interpolate.")) 6816 nqpt_interpolate = nqpt_interpolate + 1 6817 q_interp(:,nqpt_interpolate) = qpt(:) 6818 6819 ! Examine the symmetries of the q wavevector 6820 call littlegroup_q(cryst%nsym,qpt,symq,cryst%symrec,cryst%symafm,trev_q,prtvol=0) 6821 6822 ! Find the list of irreducible perturbations for this q-point. 6823 call irreducible_set_pert(cryst%indsym,dvdb%mpert,cryst%natom,cryst%nsym,& 6824 this_pertsy,rfdir,rfpert,symq,cryst%symrec,cryst%symrel) 6825 pertsy(nqpt_interpolate,:,:) = this_pertsy 6826 !pertsy = 1 6827 6828 do iat=1,natom 6829 do idir=1,3 6830 ipert = (iat-1) * 3 + idir 6831 if (pertsy(nqpt_interpolate,idir,iat) == 1) nperts_interpolate = nperts_interpolate + 1 6832 end do 6833 end do 6834 6835 end if 6836 end do 6837 6838 call wrtout([std_out, ab_out], sjoin(" Number of q-points found in input DVDB:", itoa(nqpt_read))) 6839 call wrtout([std_out, ab_out], sjoin(" Number of q-points requiring Fourier interpolation", itoa(nqpt_interpolate))) 6840 6841 ! ================================================= 6842 ! Open the new DVDB file and write preliminary info 6843 ! ================================================= 6844 nperts = nperts_read + nperts_interpolate 6845 6846 if (my_rank == master) then 6847 if (open_file(new_dvdb_fname, msg, newunit=ount, form="unformatted", action="write", status="unknown") /= 0) then 6848 ABI_ERROR(msg) 6849 end if 6850 write(ount, err=10, iomsg=msg) dvdb_last_version 6851 write(ount, err=10, iomsg=msg) nperts 6852 end if 6853 6854 ! ================================================================= 6855 ! Master reads all available perturbations and copy in the new DVDB 6856 ! ================================================================= 6857 6858 rhog1_g0 = zero 6859 6860 if (my_rank == master) then 6861 do iq=1,nqpt_read 6862 qpt = q_read(:,iq) 6863 db_iqpt = iq_read(iq) 6864 6865 ! Read each irreducible perturbation potentials 6866 npc = dvdb_get_pinfo(dvdb, db_iqpt, cplex, pinfo) 6867 ABI_CHECK(npc /= 0, "npc == 0!") 6868 6869 ! These arrays depend on cplex. 6870 ABI_MALLOC(v1scf, (cplex, nfftf, nspden)) 6871 ABI_MALLOC(v1, (cplex*nfftf)) 6872 6873 do ipc=1,npc 6874 idir = pinfo(1,ipc); iat = pinfo(2,ipc); ipert = pinfo(3, ipc) 6875 if (dvdb%read_onev1(idir, iat, db_iqpt, cplex, nfftf, ngfftf, v1scf, msg) /= 0) then 6876 ABI_ERROR(msg) 6877 end if 6878 6879 ! Write header 6880 hdr_ref%qptn = qpt 6881 hdr_ref%pertcase = ipert 6882 call hdr_ref%fort_write(ount, fform_pot, ierr) 6883 ABI_CHECK(ierr == 0, "hdr_fort_write returned ierr = 0") 6884 6885 do ispden=1,nspden 6886 v1 = reshape(v1scf(:,:,ispden), (/cplex*nfftf/)) 6887 write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfftf) 6888 end do 6889 if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0 6890 end do 6891 6892 ABI_FREE(v1scf) 6893 ABI_FREE(v1) 6894 end do 6895 end if ! master 6896 6897 call xmpi_barrier(comm) 6898 6899 ! ================================================================ 6900 ! Interpolate the potential for q-points not in the original DVDB 6901 ! ================================================================ 6902 6903 dvdb%my_nrpt = nqbz_coarse 6904 ABI_MALLOC_OR_DIE(v1scf_rpt, (2, dvdb%my_nrpt, nfftf, dvdb%nspden), ierr) 6905 6906 cplex = 2 6907 ABI_MALLOC(v1scf, (cplex,nfftf,nspden)) 6908 ABI_MALLOC(v1, (cplex*nfftf)) 6909 6910 use_netcdf = .False. 6911 ! Create temporary netcdf file used to write Fortran file with contiguous perturbations. 6912 use_netcdf = .True. 6913 if (my_rank == master) then 6914 tmp_fname = strcat(new_dvdb_fname, "_TEMPORARY_TRANSFER_FILE.nc") 6915 dimv1 = cplex * nfftf 6916 NCF_CHECK(nctk_open_create(ncid, tmp_fname, xmpi_comm_self)) 6917 ncerr = nctk_def_dims(ncid, [& 6918 nctkdim_t("dimv1", dimv1), nctkdim_t("nspden", nspden), & 6919 nctkdim_t("natom", natom), nctkdim_t("nqpt_intp", nqpt_interpolate), & 6920 nctkdim_t("nrpt", dvdb%my_nrpt), nctkdim_t("nfft", nfftf), nctkdim_t("natom3", natom * 3) & 6921 ]) 6922 NCF_CHECK(ncerr) 6923 NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("v1", "dp", "dimv1, nspden, three, natom, nqpt_intp"))) 6924 !NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("v1scf_rpt", "dp", "two, nrpt, nfft, nspden, natom3"))) 6925 NCF_CHECK(nctk_set_datamode(ncid)) 6926 end if 6927 6928 do iat=1,natom 6929 do idir=1,3 6930 ipert = (iat-1) * 3 + idir 6931 6932 ! Entry set to -1 for perturbations that can be found from basis perturbations. 6933 if (sum(pertsy(:,idir,iat)) == -nqpt_interpolate) cycle 6934 6935 call wrtout(std_out, sjoin(" Interpolating perturbation iat, idir = ",itoa(iat), itoa(idir)), do_flush=.True.) 6936 call cwtime(cpu, wall, gflops, "start") 6937 6938 ! TODO: This part is slow. 6939 ! Compute phonon potential in real space lattice representation. 6940 call dvdb_get_v1scf_rpt(dvdb, cryst, ngqpt_coarse, nqshift_coarse, & 6941 qshift_coarse, nfftf, ngfftf, & 6942 dvdb%my_nrpt, dvdb%nspden, ipert, v1scf_rpt, comm) 6943 6944 !NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "v1scf_rpt"), v1scf_rpt, start=[1,1,1,1,ipert])) 6945 call cwtime_report(" v1scf_rpt built", cpu, wall, gflops) 6946 6947 do iq=1,nqpt_interpolate 6948 if (pertsy(iq,idir,iat) == -1) cycle 6949 qpt = q_interp(:,iq) 6950 6951 ! Interpolate the phonon potential 6952 call dvdb_get_v1scf_qpt(dvdb, cryst, qpt, nfftf, ngfftf, dvdb%my_nrpt, & 6953 dvdb%nspden, ipert, v1scf_rpt, v1scf, comm) 6954 6955 !call wrtout(std_out, sjoin("Writing q-point", itoa(iq))) 6956 if (my_rank == master) then 6957 if (use_netcdf) then 6958 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1"), v1scf, & 6959 start=[1,1,idir,iat,iq], count=[dimv1,nspden,1,1,1]) 6960 NCF_CHECK(ncerr) 6961 else 6962 ! Master writes the file (change also qpt and ipert in hdr%) 6963 hdr_ref%qptn = qpt 6964 hdr_ref%pertcase = ipert 6965 call hdr_ref%fort_write(ount, fform_pot, ierr) 6966 ABI_CHECK(ierr == 0, "hdr_fort_write returned ierr = 0") 6967 6968 do ispden=1,nspden 6969 v1 = reshape(v1scf(:,:,ispden), [cplex*nfftf]) 6970 write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfftf) 6971 end do 6972 if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0 6973 end if 6974 end if 6975 end do 6976 6977 call cwtime_report(" q-points interpolated and written to new DVDB file.", cpu, wall, gflops) 6978 ABI_FREE(dvdb%my_rpt) 6979 end do 6980 end do 6981 6982 if (use_netcdf .and. my_rank == master) then 6983 do iq=1,nqpt_interpolate 6984 qpt = q_interp(:,iq) 6985 do iat=1,natom 6986 do idir=1,3 6987 if (pertsy(iq,idir,iat) == -1) cycle 6988 ipert = (iat-1) * 3 + idir 6989 hdr_ref%qptn = qpt 6990 hdr_ref%pertcase = ipert 6991 call hdr_ref%fort_write(ount, fform_pot, ierr) 6992 ncerr = nf90_get_var(ncid, nctk_idname(ncid, "v1"), v1scf, & 6993 start=[1,1,idir,iat,iq], count=[dimv1,nspden,1,1,1]) 6994 NCF_CHECK(ncerr) 6995 do ispden=1,nspden 6996 v1 = reshape(v1scf(:,:,ispden), [cplex*nfftf]) 6997 write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfftf) 6998 end do 6999 if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0 7000 end do 7001 end do 7002 end do 7003 NCF_CHECK(nf90_close(ncid)) 7004 call delete_file(tmp_fname, ierr) 7005 end if 7006 7007 if (my_rank == master) close(ount) 7008 7009 ! Free memory 7010 ABI_FREE(v1scf) 7011 ABI_FREE(v1) 7012 ABI_FREE(v1scf_rpt) 7013 ABI_FREE(qbz) 7014 ABI_FREE(qibz) 7015 ABI_FREE(q_interp) 7016 ABI_FREE(q_read) 7017 ABI_FREE(wtq) 7018 ABI_FREE(iq_read) 7019 ABI_FREE(pertsy) 7020 ABI_FREE(this_pertsy) 7021 ABI_FREE(rfpert) 7022 ABI_FREE(pinfo) 7023 7024 call hdr_ref%free() 7025 7026 write(msg, '(2a)') "Interpolation of the electron-phonon coupling potential completed", ch10 7027 call wrtout([std_out, ab_out], msg, do_flush=.True.) 7028 7029 call cwtime_report(" Overall time:", cpu_all, wall_all, gflops_all) 7030 7031 return 7032 7033 ! Handle Fortran IO error 7034 10 continue 7035 ABI_ERROR(msg) 7036 7037 end subroutine dvdb_interpolate_and_write
m_dvdb/dvdb_interpolate_v1scf [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_interpolate_v1scf
FUNCTION
Interpolate the phonon perturbation potential. This routine is meant to replace dvdb_ftinterp_setup and dvdb_ftinterp_qpt. It performs the interpolation one perturbation at a time.
INPUTS
ngqpt(3)=Divisions of the ab-initio q-mesh. nqshift=Number of shifts used to generated the ab-initio q-mesh. qshift(3,nqshift)=The shifts of the ab-initio q-mesh. nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT nfftf=Number of fft-points on the fine grid for interpolated potential ngfftf(18)=information on 3D FFT for interpolated potential comm=MPI communicator
OUTPUT
v1scf(2, nfft, nspden, 3*natom)= v1scf potentials on the real-space FFT mesh for the 3*natom perturbations.
SOURCE
4470 subroutine dvdb_interpolate_v1scf(db, cryst, qpt, ngqpt, nqshift, qshift, & 4471 nfft, ngfft, nfftf, ngfftf, v1scf, comm) 4472 4473 !Arguments ------------------------------------ 4474 !scalars 4475 integer,intent(in) :: nqshift,nfft,nfftf,comm 4476 class(dvdb_t),target,intent(inout) :: db 4477 !arrays 4478 real(dp),intent(in) :: qpt(3) 4479 integer,intent(in) :: ngqpt(3),ngfft(18),ngfftf(18) 4480 real(dp),intent(in) :: qshift(3,nqshift) 4481 real(dp),allocatable,intent(out) :: v1scf(:,:,:,:) 4482 type(crystal_t),intent(in) :: cryst 4483 4484 !Local variables------------------------------- 4485 !scalars 4486 integer :: ipert, nqbz, ierr, nproc, my_rank 4487 !real(dp) :: work_size 4488 !arrays 4489 real(dp),allocatable :: v1scf_rpt(:,:,:,:) 4490 4491 ! ************************************************************************* 4492 4493 nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm) 4494 4495 nqbz = product(ngqpt) * nqshift 4496 db%my_nrpt = nqbz 4497 4498 ABI_MALLOC_OR_DIE(v1scf, (2,nfftf,db%nspden,db%natom3), ierr) 4499 ABI_MALLOC_OR_DIE(v1scf_rpt, (2,db%my_nrpt,nfft,db%nspden), ierr) 4500 4501 do ipert=1,db%natom3 4502 write(std_out, "(a,i4,a,i4,a)") " Interpolating potential for perturbation ", ipert, " / ", db%natom3, ch10 4503 4504 ! FIXME I think this should be ngfftf and not ngfft 4505 ! Also, other calls to dvdb_ftinterp_setup should use ngfftf. 4506 call dvdb_get_v1scf_rpt(db, cryst, ngqpt, nqshift, qshift, nfft, ngfft, & 4507 db%my_nrpt, db%nspden, ipert, v1scf_rpt, comm) 4508 4509 call dvdb_get_v1scf_qpt(db, cryst, qpt, nfftf, ngfftf, db%my_nrpt, db%nspden, & 4510 ipert, v1scf_rpt, v1scf(:,:,:,ipert), comm) 4511 4512 ABI_FREE(db%my_rpt) 4513 end do 4514 4515 ABI_FREE(v1scf_rpt) 4516 4517 end subroutine dvdb_interpolate_v1scf
m_dvdb/dvdb_list_perts [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_list_perts
FUNCTION
Given a q-point mesh, this routine checks if all the (phonon) perturbations are available taking into account symmetries.
INPUTS
ngqpt(3)=Q-mesh divisions. If all(ngqpt == -1), the list of q-points in the DVDB (i.e. db%qpts) is analyzed instead of the q-points generated from ngqpt. [unit]=Unit number for output. Default `std_out`.
OUTPUT
npert_miss = Number of missing perturbations.
SOURCE
4867 subroutine dvdb_list_perts(db, ngqpt, npert_miss, unit) 4868 4869 !Arguments ------------------------------------ 4870 class(dvdb_t),target,intent(in) :: db 4871 integer,intent(out) :: npert_miss 4872 integer,optional,intent(in) :: unit 4873 !arrays 4874 integer,intent(in) :: ngqpt(3) 4875 4876 !Local variables------------------------------- 4877 !scalars 4878 integer :: npert_redund,miss_q,idir,ipert,iv1,psy,weird_q,enough 4879 integer :: iq_ibz,nqibz,iq_file,qptopt,nshiftq,ii,timerev_q,unt,nqbz 4880 character(len=500) :: msg,ptype,found 4881 type(crystal_t),pointer :: cryst 4882 !arrays 4883 integer :: rfdir(3),qptrlatt(3,3) 4884 integer,allocatable :: pertsy(:,:),symq(:,:,:),rfpert(:) 4885 real(dp) :: qq(3),shiftq(3,1) 4886 real(dp),allocatable :: qibz(:,:),wtq(:),qbz(:,:) 4887 4888 ! ************************************************************************* 4889 4890 unt = std_out; if (present(unit)) unt = unit 4891 cryst => db%cryst 4892 4893 if (all(ngqpt == -1)) then 4894 ! Will test the q-points in db 4895 call alloc_copy(db%qpts, qibz) 4896 nqibz = db%nqpt 4897 else 4898 ! Will test the q-points in the IBZ associated to ngqpt hence build IBZ and BZ from ngqpt. 4899 qptopt = 1; shiftq = zero; nshiftq = 1; qptrlatt = 0 4900 do ii=1,3 4901 qptrlatt(ii, ii) = ngqpt(ii) 4902 end do 4903 4904 call kpts_ibz_from_kptrlatt(cryst, qptrlatt, qptopt, nshiftq, shiftq, nqibz, qibz, wtq, nqbz, qbz) 4905 4906 ABI_FREE(qbz) 4907 ABI_FREE(wtq) 4908 end if 4909 4910 ! Initialize the list of perturbations rfpert and rdfir 4911 ! WARNING: Only phonon perturbations are considered for the time being. 4912 ABI_MALLOC(rfpert,(db%mpert)) 4913 rfpert = 0; rfpert(1:cryst%natom) = 1; rfdir = 1 4914 4915 ABI_MALLOC(symq, (4,2,cryst%nsym)) 4916 ABI_MALLOC(pertsy, (3,db%mpert)) 4917 4918 ! Loop over the q-points in the IBZ and test whether the q-point is present 4919 ! and if all the independent perturbations are available. 4920 ! `npert_miss` is the number of irreducible perturbations not found in the DVDB (critical) 4921 ! `npert_redund` is the number of redundant perturbations found in the DVDB (not critical) 4922 ! 4923 enough = 5; if (db%prtvol > 0) enough = nqibz + 1 4924 npert_miss = 0; npert_redund = 0 4925 do iq_ibz=1,nqibz 4926 if (iq_ibz == enough) then 4927 call wrtout(unt,' More than 20 q-points with prtvol == 0. Only important messages will be printed...') 4928 end if 4929 qq = qibz(:,iq_ibz) 4930 iq_file = db%findq(qq) 4931 4932 ! Examine the symmetries of the q wavevector 4933 call littlegroup_q(cryst%nsym,qq,symq,cryst%symrec,cryst%symafm,timerev_q,prtvol=db%prtvol) 4934 4935 ! Determine the symmetrical perturbations. Meaning of pertsy: 4936 ! 0 for non-target perturbations 4937 ! 1 for basis perturbations 4938 ! -1 for perturbations that can be found from basis perturbations 4939 call irreducible_set_pert(cryst%indsym,db%mpert,cryst%natom,cryst%nsym,& 4940 pertsy,rfdir,rfpert,symq,cryst%symrec,cryst%symrel) 4941 4942 if (iq_file /= -1) then 4943 ! This q-point is in the DVDB. Test if all the independent perturbations are available. 4944 if (iq_ibz <= enough) then 4945 call wrtout(unt, sjoin(" qpoint:", ktoa(qq), "is present in the DVDB file")) 4946 call wrtout(unt,' The list of irreducible perturbations for this q vector is:') 4947 end if 4948 ii = 0; weird_q = 0; miss_q = 0 4949 do ipert=1,db%mpert 4950 do idir=1,3 4951 psy = pertsy(idir,ipert) 4952 if (psy == 0) cycle 4953 iv1 = db%pos_dpq(idir,ipert,iq_file) 4954 ptype = "independent"; if (psy == -1) ptype = "symmetric" 4955 found = "Yes"; if (iv1 == 0) found = "No" 4956 4957 if (psy == 1 .and. iv1 == 0) miss_q = miss_q + 1 4958 if (psy == -1 .and. iv1 /= 0) weird_q = weird_q + 1 4959 4960 ii=ii+1 4961 if (iq_ibz <= enough) then 4962 write(msg,'(i5,a,i2,a,i4,4a)')ii,') idir=',idir,', ipert=',ipert,", type=",trim(ptype),", found=",trim(found) 4963 call wrtout(unt, msg) 4964 end if 4965 end do 4966 end do 4967 4968 if (weird_q /= 0) then 4969 write(msg,"(a,i0,a)")" DVDB is overcomplete. ",weird_q, " perturbation(s) can be reconstructed by symmetry." 4970 call wrtout(unt, msg) 4971 end if 4972 4973 npert_redund = npert_redund + weird_q 4974 npert_miss = npert_miss + miss_q 4975 if (miss_q /=0) then 4976 call wrtout(unt, sjoin(" WARNING:", itoa(miss_q), "independent perturbation(s) are missing!.")) 4977 end if 4978 4979 else 4980 ! This q-point is not present in dvdb. Print the list of independent perturbations. 4981 call wrtout(unt, sjoin(" qpoint:", ktoa(qq), "is NOT present in the DVDB file")) 4982 call wrtout(unt,' The list of irreducible perturbations for this q vector is:') 4983 ii = 0 4984 do ipert=1,db%mpert 4985 do idir=1,3 4986 if (pertsy(idir,ipert) == 1) then 4987 ii=ii+1 4988 write(msg,'(i5,a,i2,a,i4,a)')ii,') idir=',idir,', ipert=',ipert,", type=independent, found=No" 4989 call wrtout(unt, msg) 4990 npert_miss = npert_miss + 1 4991 end if 4992 end do 4993 end do 4994 end if 4995 4996 if (iq_ibz <= enough) call wrtout(unt," ") 4997 end do ! iq_ibz 4998 4999 if (npert_miss /= 0) then 5000 call wrtout(unt, sjoin(ch10, " There are ",itoa(npert_miss), "independent perturbations missing!")) 5001 else 5002 call wrtout(unt, " All the independent perturbations are available") 5003 if (npert_redund /= 0) then 5004 call wrtout(unt, " Note however that the DVDB is overcomplete as symmetric perturbations are present.") 5005 end if 5006 end if 5007 5008 ABI_FREE(qibz) 5009 ABI_FREE(rfpert) 5010 ABI_FREE(symq) 5011 ABI_FREE(pertsy) 5012 5013 end subroutine dvdb_list_perts
m_dvdb/dvdb_load_ddb [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_load_ddb
FUNCTION
Load information about the Born effective charges and dielectric tensor from a DDB file
TODO
Use this function in eph driver
m_dvdb/dvdb_load_efield [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_load_efield
FUNCTION
Load first oder derivatives wrt the electric file from files
INPUTS
pot_paths=List of strings with paths to POT1 files. comm=MPI communicator.
m_dvdb/dvdb_merge_files [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_merge_files
FUNCTION
Merge a list of POT1 files. INPUT nfiles=Number of files to be merged. dvdb_filepath=Name of output DVDB file. prtvol=Verbosity level.
SIDE EFFECTS
v1files=List of file names to merge. This list could be changed if POT1 files in netcdf format are found.
SOURCE
5035 subroutine dvdb_merge_files(nfiles, v1files, dvdb_filepath, prtvol) 5036 5037 !Arguments ------------------------------------ 5038 !scalars 5039 integer,intent(in) :: nfiles,prtvol 5040 character(len=*),intent(in) :: dvdb_filepath 5041 character(len=*),intent(inout) :: v1files(nfiles) 5042 5043 !Local variables------------------------------- 5044 !scalars 5045 ! Here I made a mistake because 102 corresponds to GS potentials 5046 ! as a consequence DVDB files generated with version <= 8.1.6 5047 ! contain list of potentials with fform = 102. 5048 !integer :: fform_pot=102 5049 integer :: fform_pot=111 5050 integer :: ii,jj,fform,ount,cplex,nfft,ifft,ispden,nperts 5051 integer :: n1,n2,n3,v1_varid,ierr, npert_miss 5052 logical :: qeq0 5053 character(len=500) :: msg 5054 type(hdr_type),pointer :: hdr1 5055 type(dvdb_t) :: dvdb 5056 !arrays 5057 integer :: units(nfiles) 5058 real(dp) :: rhog1_g0(2) 5059 real(dp),allocatable :: v1(:) 5060 logical :: has_rhog1_g0(nfiles) 5061 type(hdr_type),target,allocatable :: hdr1_list(:) 5062 5063 !************************************************************************ 5064 5065 if (file_exists(dvdb_filepath)) then 5066 ABI_ERROR(sjoin("Cannot overwrite existing file:", dvdb_filepath)) 5067 end if 5068 5069 ! If a file is not found, try the netcdf version and change v1files accordingly. 5070 do ii=1,nfiles 5071 if (nctk_try_fort_or_ncfile(v1files(ii), msg) /= 0) then 5072 ABI_ERROR(msg) 5073 end if 5074 end do 5075 5076 ! Read the headers 5077 ABI_MALLOC(hdr1_list, (nfiles)) 5078 nperts = size(hdr1_list) 5079 5080 ! Write dvdb file (we only support fortran binary format) 5081 if (open_file(dvdb_filepath, msg, newunit=ount, form="unformatted", action="write", status="unknown") /= 0) then 5082 ABI_ERROR(msg) 5083 end if 5084 write(ount, err=10, iomsg=msg) dvdb_last_version 5085 write(ount, err=10, iomsg=msg) nperts 5086 5087 ! Validate headers. 5088 ! TODO: Should perform consistency check on the headers 5089 ! rearrange them in blocks of q-points for efficiency reason. 5090 ! ignore POT1 files that do not correspond to atomic perturbations. 5091 ! Add POT file from GS run to support Sternheimer in eph_task = 4 5092 5093 do ii=1,nfiles 5094 write(std_out,"(a,i0,2a)")"- Reading header of file [",ii,"]: ",trim(v1files(ii)) 5095 5096 if (endswith(v1files(ii), ".nc")) then 5097 NCF_CHECK(nctk_open_read(units(ii), v1files(ii), xmpi_comm_self)) 5098 call hdr_ncread(hdr1_list(ii),units(ii),fform) 5099 else 5100 if (open_file(v1files(ii), msg, newunit=units(ii), form="unformatted", action="read", status="old") /= 0) then 5101 ABI_ERROR(msg) 5102 end if 5103 call hdr_fort_read(hdr1_list(ii), units(ii), fform) 5104 end if 5105 5106 if (dvdb_check_fform(fform, "merge_dvdb", msg) /= 0) then 5107 ABI_ERROR(sjoin("While reading:", v1files(ii), msg)) 5108 end if 5109 if (prtvol > 0) call hdr1_list(ii)%echo(fform, 3, unit=std_out) 5110 if (hdr1_list(ii)%pertcase == 0) then 5111 ABI_ERROR(sjoin("Found GS potential:", v1files(ii))) 5112 end if 5113 !write(std_out,*)"done", trim(v1files(ii)) 5114 5115 ! Supported fform: 5116 ! 109 POT1 files without vh1(G=0) 5117 ! 111 POT1 files with extra record with vh1(G=0) after FFT data. 5118 has_rhog1_g0(ii) = .True. 5119 if (fform == 109) has_rhog1_g0(ii) = .False. 5120 5121 write(std_out,"(a,i0,2a)")"- Merging file [",ii,"]: ",trim(v1files(ii)) 5122 jj = ii 5123 hdr1 => hdr1_list(jj) 5124 call hdr1%fort_write(ount, fform_pot, ierr) 5125 ABI_CHECK(ierr == 0, "hdr_fort_write returned ierr = 0") 5126 5127 qeq0 = (hdr1%qptn(1)**2+hdr1%qptn(2)**2+hdr1%qptn(3)**2<1.d-14) 5128 cplex = 2; if (qeq0) cplex = 1 5129 nfft = product(hdr1%ngfft(1:3)) 5130 n1 = hdr1%ngfft(1); n2 = hdr1%ngfft(2); n3 = hdr1%ngfft(3) 5131 5132 ABI_MALLOC(v1, (cplex*nfft)) 5133 5134 if (.not. endswith(v1files(ii), ".nc")) then 5135 ! Fortran IO 5136 do ispden=1,hdr1%nspden 5137 read(units(jj), err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfft) 5138 write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfft) 5139 end do 5140 ! Add rhog1(G=0) 5141 rhog1_g0 = zero 5142 if (has_rhog1_g0(jj)) read(units(jj), err=10, iomsg=msg) rhog1_g0 5143 if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0 5144 else 5145 ! Netcdf IO 5146 ! netcdf array has shape [cplex, n1, n2, n3, nspden] 5147 NCF_CHECK(nf90_inq_varid(units(ii), "first_order_potential", v1_varid)) 5148 do ispden=1,hdr1%nspden 5149 NCF_CHECK(nf90_get_var(units(ii), v1_varid, v1, start=[1,1,1,1,ispden], count=[cplex, n1, n2, n3, 1])) 5150 write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfft) 5151 end do 5152 ! Add rhog1(G=0) 5153 rhog1_g0 = zero 5154 if (has_rhog1_g0(jj)) then 5155 NCF_CHECK(nf90_get_var(units(ii), nctk_idname(units(ii), "rhog1_g0"), rhog1_g0)) 5156 end if 5157 if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0 5158 end if 5159 5160 if (.not. endswith(v1files(ii), ".nc")) then 5161 close(units(ii)) 5162 else 5163 NCF_CHECK(nf90_close(units(ii))) 5164 end if 5165 5166 ABI_FREE(v1) 5167 end do ! nperts 5168 5169 close(ount) 5170 5171 do ii=1,size(hdr1_list) 5172 call hdr1_list(ii)%free() 5173 end do 5174 ABI_FREE(hdr1_list) 5175 5176 write(std_out,"(a,i0,a)")" Merged successfully ", nfiles, " files" 5177 5178 ! List available perturbations. 5179 dvdb = dvdb_new(dvdb_filepath, xmpi_comm_self) 5180 call dvdb%print() 5181 call dvdb%list_perts([-1, -1, -1], npert_miss) 5182 call dvdb%free() 5183 5184 return 5185 5186 ! Handle Fortran IO error 5187 10 continue 5188 ABI_ERROR(sjoin("Error while merging files", ch10, msg)) 5189 5190 end subroutine dvdb_merge_files
m_dvdb/dvdb_new [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_new
FUNCTION
Initialize the object from file. This is a COLLECTIVE procedure that must be called by each process in the MPI communicator comm.
INPUTS
path=DVDB Filename. comm=MPI communicator.
SOURCE
577 type(dvdb_t) function dvdb_new(path, comm) result(new) 578 579 !Arguments ------------------------------------ 580 !scalars 581 character(len=*),intent(in) :: path 582 integer,intent(in) :: comm 583 584 !Local variables------------------------------- 585 !scalars 586 integer,parameter :: master = 0 587 integer :: iv1,ii,ierr,unt,fform,nqpt,iq,iq_found,cplex,trev_q 588 integer :: idir,ipert,my_rank, nprocs, iatom, pertcase 589 real(dp) :: cpu, wall, gflops 590 character(len=500) :: msg 591 type(hdr_type) :: hdr1 592 !arrays 593 integer,allocatable :: tmp_pos(:,:,:) 594 real(dp),allocatable :: tmp_qpts(:,:) 595 real(dp) :: tsec(2) 596 597 !************************************************************************ 598 599 ! Keep track of total time spent. 600 call timab(1800, 1, tsec) 601 602 my_rank = xmpi_comm_rank(comm); nprocs = xmpi_comm_size(comm) 603 new%path = path; new%comm = comm; new%iomode = IO_MODE_FORTRAN 604 605 call wrtout(std_out, sjoin("- Analyzing DVDB file: ", path, "...")) 606 call cwtime(cpu, wall, gflops, "start") 607 608 ! Master reads the header and builds useful tables 609 if (my_rank == master) then 610 611 if (open_file(path, msg, newunit=unt, form="unformatted", status="old", action="read") /= 0) then 612 ABI_ERROR(msg) 613 end if 614 read(unt, err=10, iomsg=msg) new%version 615 read(unt, err=10, iomsg=msg) new%numv1 616 617 ! Get important dimensions from the first header and rewind the file. 618 call hdr_fort_read(new%hdr_ref, unt, fform) 619 if (dvdb_check_fform(fform, "read_dvdb", msg) /= 0) then 620 ABI_ERROR(sjoin("While reading:", path, ch10, msg)) 621 end if 622 if (new%debug) call new%hdr_ref%echo(fform, 4, unit=std_out) 623 624 rewind(unt) 625 read(unt, err=10, iomsg=msg) 626 read(unt, err=10, iomsg=msg) 627 628 ! The code below must be executed by the other procs if MPI. 629 new%natom = new%hdr_ref%natom 630 new%natom3 = 3 * new%hdr_ref%natom 631 new%nspden = new%hdr_ref%nspden 632 new%nsppol = new%hdr_ref%nsppol 633 new%nspinor = new%hdr_ref%nspinor 634 new%usepaw = new%hdr_ref%usepaw 635 ABI_CHECK(new%usepaw == 0, "PAW not yet supported") 636 637 ! TODO: Write function to return mpert from natom! 638 new%mpert = new%natom + 6 639 640 ABI_MALLOC(tmp_qpts, (3, new%numv1)) 641 ABI_MALLOC(tmp_pos, (3, new%mpert, new%numv1)) 642 tmp_pos = 0 643 644 ABI_MALLOC(new%cplex_v1, (new%numv1)) 645 ABI_MALLOC(new%ngfft3_v1, (3, new%numv1)) 646 ABI_MALLOC(new%iv_pinfoq, (4, new%numv1)) 647 ABI_MALLOC(new%rhog1_g0, (2, new%numv1)) 648 649 nqpt = 0 650 do iv1=1,new%numv1 651 call hdr_fort_read(hdr1, unt, fform) 652 if (dvdb_check_fform(fform, "read_dvdb", msg) /= 0) then 653 ABI_ERROR(sjoin("While reading hdr of v1 potential of index:", itoa(iv1), ch10, msg)) 654 end if 655 656 ! Save cplex and FFT mesh associated to this perturbation. 657 cplex = 2; if (hdr1%qptn(1)**2+hdr1%qptn(2)**2+hdr1%qptn(3)**2<1.d-14) cplex = 1 658 new%cplex_v1(iv1) = cplex 659 new%ngfft3_v1(:, iv1) = hdr1%ngfft(:3) 660 661 ! Skip the records with v1. 662 do ii=1,hdr1%nspden 663 read(unt, err=10, iomsg=msg) 664 end do 665 ! Read rhog1_g0 (if available) 666 new%rhog1_g0(:, iv1) = zero 667 if (new%version > 1) read(unt, err=10, iomsg=msg) new%rhog1_g0(:, iv1) 668 669 ! Check whether this q-point is already in the list. 670 ! Assume qpoints are grouped so invert the iq loop for better performace. 671 ! This is gonna be slow if lots of q-points and perturbations are not grouped. 672 iq_found = 0 673 do iq=nqpt,1,-1 674 if (all(abs(hdr1%qptn - tmp_qpts(:,iq)) < tol14)) then 675 iq_found = iq; exit 676 end if 677 end do 678 679 ! pertcase = idir + (ipert-1)*3 where ipert=iatom in the interesting cases 680 idir = mod(hdr1%pertcase-1, 3) + 1 681 ipert = (hdr1%pertcase - idir) / 3 + 1 682 683 ! Increment nqpt is new q-points and update tmp_pos 684 if (iq_found == 0) then 685 nqpt = nqpt + 1 686 tmp_qpts(:, nqpt) = hdr1%qptn 687 iq_found = nqpt 688 end if 689 tmp_pos(idir, ipert, iq_found) = iv1 690 new%iv_pinfoq(:,iv1) = [idir, ipert, hdr1%pertcase, iq_found] 691 692 call hdr1%free() 693 end do 694 695 ! Allocate arrays with correct nqpt dimension 696 new%nqpt = nqpt 697 ABI_MALLOC(new%qpts, (3, nqpt)) 698 new%qpts = tmp_qpts(:,1:nqpt) 699 ABI_FREE(tmp_qpts) 700 701 ABI_MALLOC(new%pos_dpq, (3, new%mpert, nqpt)) 702 new%pos_dpq = tmp_pos(:, :, 1:nqpt) 703 ABI_FREE(tmp_pos) 704 705 close(unt) 706 end if 707 708 ! Master broadcasts data. 709 if (xmpi_comm_size(comm) > 1) then 710 call xmpi_bcast(new%version, master, comm, ierr) 711 call xmpi_bcast(new%numv1, master, comm, ierr) 712 call xmpi_bcast(new%nqpt, master, comm, ierr) 713 call new%hdr_ref%bcast(master, my_rank, comm) 714 715 new%natom = new%hdr_ref%natom 716 new%natom3 = 3 * new%hdr_ref%natom 717 new%nspden = new%hdr_ref%nspden 718 new%nsppol = new%hdr_ref%nsppol 719 new%nspinor = new%hdr_ref%nspinor 720 new%usepaw = new%hdr_ref%usepaw 721 new%mpert = new%natom + 6 722 723 if (my_rank /= master) then 724 ABI_MALLOC(new%cplex_v1, (new%numv1)) 725 ABI_MALLOC(new%ngfft3_v1, (3, new%numv1)) 726 ABI_MALLOC(new%iv_pinfoq, (4, new%numv1)) 727 ABI_MALLOC(new%qpts, (3, new%nqpt)) 728 ABI_MALLOC(new%pos_dpq, (3, new%mpert, new%nqpt)) 729 ABI_MALLOC(new%rhog1_g0, (2, new%numv1)) 730 end if 731 732 call xmpi_bcast(new%cplex_v1, master, comm, ierr) 733 call xmpi_bcast(new%ngfft3_v1, master, comm, ierr) 734 call xmpi_bcast(new%iv_pinfoq, master, comm, ierr) 735 call xmpi_bcast(new%qpts, master, comm, ierr) 736 call xmpi_bcast(new%pos_dpq, master, comm, ierr) 737 call xmpi_bcast(new%rhog1_g0, master, comm, ierr) 738 end if 739 740 ! Init crystal_t from the hdr read from file. 741 new%cryst = new%hdr_ref%get_crystal() 742 new%my_npert = new%natom3 743 744 ! Init tables assuming no MPI distribution of perturbations. 745 ABI_MALLOC(new%my_pinfo, (3, new%natom3)) 746 ABI_MALLOC(new%pert_table, (2, new%natom3)) 747 do iatom=1,new%natom 748 do idir=1,3 749 pertcase = idir + (iatom-1) * 3 750 new%my_pinfo(:, pertcase) = [idir, iatom, pertcase] 751 new%pert_table(:, pertcase) = [xmpi_comm_self, pertcase] 752 end do 753 end do 754 755 ! Init Born effective charges 756 ABI_CALLOC(new%zeff, (3, 3, new%natom)) 757 ABI_CALLOC(new%zeff_raw, (3, 3, new%natom)) 758 ABI_CALLOC(new%qstar, (3, 3, 3, new%natom)) 759 760 ! Internal MPI_type needed for calling fourdp! 761 call initmpi_seq(new%mpi_enreg) 762 763 ! Precompute symq_table for all q-points in the DVDB. 764 ABI_ICALLOC(new%symq_table, (4, 2, new%cryst%nsym, new%nqpt)) 765 do iq=1,new%nqpt 766 if (mod(iq, nprocs) /= my_rank) cycle ! MPI parallelism 767 call littlegroup_q(new%cryst%nsym, new%qpts(:,iq), new%symq_table(:,:,:,iq), & 768 new%cryst%symrec, new%cryst%symafm, trev_q, prtvol=0) 769 end do 770 call xmpi_sum(new%symq_table, comm, ierr) 771 772 call cwtime_report("- dvdb_new", cpu, wall, gflops) 773 call timab(1800, 2, tsec) 774 775 return 776 777 ! Handle Fortran IO error 778 10 continue 779 ABI_ERROR(sjoin("Error while reading:", path, ch10, msg)) 780 781 end function dvdb_new
m_dvdb/dvdb_open_read [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_open_read
FUNCTION
Open the file in read-only mode.
INPUTS
ngfft(18)=Info on the FFT mesh used for the DFPT potentials. Note that ngfft is the mesh used by the parent. In principle, it can differ from the one found in the file. In this case a Fourier interpolation is required. comm=MPI communicator
SOURCE
801 subroutine dvdb_open_read(db, ngfft, comm) 802 803 !Arguments ------------------------------------ 804 !scalars 805 integer,intent(in) :: comm 806 class(dvdb_t),intent(inout) :: db 807 !arrays 808 integer,intent(in) :: ngfft(18) 809 810 !Local variables------------------------------- 811 !scalars 812 integer :: nprocs, unt, ii 813 character(len=500) :: msg 814 !arrays 815 character(len=fnlen) :: pot_paths(3) 816 817 !************************************************************************ 818 819 if (db%rw_mode /= DVDB_NOMODE) then 820 ABI_ERROR("DVDB should be in DVDB_NOMODE when open_read is called.") 821 end if 822 db%rw_mode = DVDB_READMODE 823 824 nprocs = xmpi_comm_size(comm) 825 826 ! Initialize tables to call fourdp in sequential 827 db%ngfft = ngfft 828 call init_distribfft_seq(db%mpi_enreg%distribfft, 'c', ngfft(2), ngfft(3), 'all') 829 call init_distribfft_seq(db%mpi_enreg%distribfft, 'f', ngfft(2), ngfft(3), 'all') 830 831 ! Open the file. 832 select case (db%iomode) 833 case (IO_MODE_FORTRAN) 834 if (open_file(db%path, msg, newunit=db%fh, form="unformatted", status="old", action="read") /= 0) then 835 ABI_ERROR(msg) 836 end if 837 read(db%fh, err=10, iomsg=msg) 838 read(db%fh, err=10, iomsg=msg) 839 db%current_fpos = 1 840 841 case (IO_MODE_MPI) 842 ABI_ERROR("MPI not coded") 843 844 case default 845 ABI_ERROR(sjoin("Unsupported iomode:", itoa(db%iomode))) 846 end select 847 848 ! Read potentials induced by electric fields 849 ! This requires ngfft so for the time being we call it here. 850 ! I should try to add efield perturbations to DVDB but then I also have to handle symmetrization wrt idir! 851 if (file_exists("__EFIELD_POTS__")) then 852 call wrtout(std_out, " Reading Efield potentials from EFIELD_POTS") 853 if (open_file("__EFIELD_POTS__", msg, newunit=unt, form="formatted") /= 0) then 854 ABI_ERROR(msg) 855 end if 856 do ii=1,3 857 read(unt, "(a)") pot_paths(ii) 858 end do 859 close(unt) 860 call db%load_efield(pot_paths, comm) 861 end if 862 863 return 864 865 ! Handle Fortran IO error 866 10 continue 867 ABI_ERROR(sjoin("Error while reading", db%path, ch10, msg)) 868 869 end subroutine dvdb_open_read
m_dvdb/dvdb_print [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_print
FUNCTION
Print info on the object.
INPUTS
[unit]=the unit number for output [prtvol]=verbosity level [mode_paral]=either "COLL" or "PERS"
OUTPUT
Only printing.
SOURCE
978 subroutine dvdb_print(db, header, unit, prtvol, mode_paral) 979 980 !Arguments ------------------------------------ 981 !scalars 982 integer,optional,intent(in) :: prtvol,unit 983 character(len=4),optional,intent(in) :: mode_paral 984 character(len=*),optional,intent(in) :: header 985 class(dvdb_t),intent(in) :: db 986 987 !Local variables------------------------------- 988 !scalars 989 integer :: my_unt,my_prtvol,iv1,iq,idir,ipert,iatom 990 character(len=4) :: my_mode 991 character(len=500) :: msg 992 993 ! ************************************************************************* 994 995 my_unt = std_out; if (present(unit)) my_unt = unit 996 my_prtvol = 0 ; if (present(prtvol)) my_prtvol = prtvol 997 my_mode = 'COLL'; if (present(mode_paral)) my_mode = mode_paral 998 999 msg=' ==== Info on the dvdb% object ==== ' 1000 if (present(header)) msg=' ==== '//trim(adjustl(header))//' ==== ' 1001 call wrtout(my_unt,msg,my_mode) 1002 1003 write(my_unt,"(a)")sjoin(" DVDB version:", itoa(db%version)) 1004 write(my_unt,"(a)")sjoin(" File path:", db%path) 1005 write(my_unt,"(a)")sjoin(" Number of v1scf potentials:", itoa(db%numv1)) 1006 write(my_unt,"(a)")sjoin(" Number of q-points in DVDB: ", itoa(db%nqpt)) 1007 ! TODO 1008 !if (with_mpi) then 1009 write(my_unt,"(a)")sjoin("-P Number of CPUs for parallelism over perturbations:", itoa(db%nprocs_pert)) 1010 write(my_unt,"(a)")sjoin("-P Number of perturbations treated by this CPU:", itoa(db%my_npert)) 1011 !end if 1012 write(my_unt,"(a)")sjoin(" Option for symmetrization of v1scf(r):", itoa(db%symv1)) 1013 write(my_unt,"(a)")" List of q-points: min(10, nqpt)" 1014 do iq=1,min(db%nqpt, 10) 1015 write(my_unt,"(a)")sjoin("[", itoa(iq),"]", ktoa(db%qpts(:,iq))) 1016 end do 1017 if (db%nqpt > 10) write(my_unt,"(a)")"..." 1018 1019 write(my_unt,"(a)")sjoin(" Have dielectric tensor:", yesno(db%has_dielt)) 1020 write(my_unt,"(a)")sjoin(" Have Born effective charges:", yesno(db%has_zeff)) 1021 write(my_unt,"(a)")sjoin(" Have quadrupoles:", yesno(db%has_quadrupoles)) 1022 write(my_unt,"(a)")sjoin(" Have electric field:", yesno(db%has_efield)) 1023 write(my_unt,"(a)")sjoin(" Treatment of long-range part in V1scf (add_lr):", itoa(db%add_lr)) 1024 write(my_unt,"(a, f6.1)")" Damping factor for Gaussian filter (qdamp):", db%qdamp 1025 1026 if (db%has_dielt) then 1027 write(my_unt, '(a,3(/,3es16.6))') ' Dielectric tensor in Cart coords:', & 1028 db%dielt(1,1), db%dielt(1,2), db%dielt(1,3), & 1029 db%dielt(2,1), db%dielt(2,2), db%dielt(2,3), & 1030 db%dielt(3,1), db%dielt(3,2), db%dielt(3,3) 1031 end if 1032 if (db%has_zeff) then 1033 call print_zeff(my_unt, db%zeff, db%cryst, title=' Born effectives charges in Cart coords:') 1034 !call print_zeff(my_unt, db%zeff_raw, db%cryst, title=' Born effectives charges before chneut: ') 1035 end if 1036 if (db%has_quadrupoles) then 1037 write(my_unt, '(a)') ' Dynamical Quadrupoles in Cartesian Coordinates: ' 1038 do iatom=1,db%natom 1039 do idir=1,3 1040 write(my_unt,'(2(a,i0),3(/,3es16.6))')' Q* for iatom: ', iatom, ' idir: ', idir, & 1041 db%qstar(1,1,idir,iatom), db%qstar(1,2,idir,iatom), db%qstar(1,3,idir,iatom), & 1042 db%qstar(2,1,idir,iatom), db%qstar(2,2,idir,iatom), db%qstar(2,3,idir,iatom), & 1043 db%qstar(3,1,idir,iatom), db%qstar(3,2,idir,iatom), db%qstar(3,3,idir,iatom) 1044 end do 1045 end do 1046 1047 write(my_unt,"(a)")" Dynamical quadrupoles sum rule: \sum_\iatom Q_{beta,gamma}{iatom,idir} = 0 for nonpolar materials" 1048 do idir=1,3 1049 write(my_unt,'(a,i0,/,3(/,3es16.6))')" Sum rule for idir: ", idir, & 1050 sum(db%qstar(1,1,idir,:)), sum(db%qstar(1,2,idir,:)), sum(db%qstar(1,3,idir,:)), & 1051 sum(db%qstar(2,1,idir,:)), sum(db%qstar(2,2,idir,:)), sum(db%qstar(2,3,idir,:)), & 1052 sum(db%qstar(3,1,idir,:)), sum(db%qstar(3,2,idir,:)), sum(db%qstar(3,3,idir,:)) 1053 end do 1054 end if 1055 1056 if (my_prtvol > 0) then 1057 call db%cryst%print(header="Crystal structure in DVDB file") 1058 write(my_unt,"(a)")"FFT mesh for potentials on file:" 1059 write(my_unt,"(a)")"q-point, idir, ipert, ngfft(:3)" 1060 do iv1=1,db%numv1 1061 idir = db%iv_pinfoq(1, iv1); ipert = db%iv_pinfoq(2, iv1); iq = db%iv_pinfoq(4, iv1) 1062 write(my_unt,"(a)")sjoin(ktoa(db%qpts(:,iq)), itoa(idir), itoa(ipert), ltoa(db%ngfft3_v1(:,iv1))) 1063 end do 1064 end if 1065 1066 contains 1067 1068 subroutine print_zeff(unt, zeff, cryst, title) 1069 1070 !Arguments ------------------------------------ 1071 !scalars 1072 integer,intent(in) :: unt 1073 character(len=*),optional,intent(in) :: title 1074 type(crystal_t),intent(in) :: cryst 1075 real(dp),intent(in) :: zeff(3,3,cryst%natom) 1076 1077 !Local variables------------------------------- 1078 !scalars 1079 integer :: iatom 1080 1081 ! ************************************************************************* 1082 1083 if (present(title)) then 1084 write(unt, "(a)")trim(title) 1085 else 1086 write(unt, '(a)') ' Born effectives charges in Cartesian coordinates: ' 1087 end if 1088 1089 do iatom=1,cryst%natom 1090 write(unt,'(a,i0,1x,2a,3(/,3es16.6),a)')' iatom: ', iatom, ", type: ", cryst%symbol_iatom(iatom), & 1091 zeff(1,1,iatom), zeff(1,2,iatom), zeff(1,3,iatom), & 1092 zeff(2,1,iatom), zeff(2,2,iatom), zeff(2,3,iatom), & 1093 zeff(3,1,iatom), zeff(3,2,iatom), zeff(3,3,iatom), ch10 1094 end do 1095 1096 write(unt,'(2a,3(/,3es16.6),a)')ch10,' Fulfillment of charge neutrality, \sum_{atom} Z^*_{ij,atom} = 0', & 1097 sum(zeff(1,1,:)), sum(zeff(1,2,:)), sum(zeff(1,3,:)), & 1098 sum(zeff(2,1,:)), sum(zeff(2,2,:)), sum(zeff(2,3,:)), & 1099 sum(zeff(3,1,:)), sum(zeff(3,2,:)), sum(zeff(3,3,:)), ch10 1100 1101 end subroutine print_zeff 1102 1103 end subroutine dvdb_print
m_dvdb/dvdb_qcache_read [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_qcache_read
FUNCTION
This function initializes the internal q-cache from file. This is a collective routine that must be called by all procs in comm.
INPUTS
nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT mbsize: Cache size in megabytes. < 0 to allocate all q-points. 0 has not effect. > 0 for cache with automatically computed nqpt points. qselect_dvdb(%nqpt)=0 to ignore this q-point when reading (global array) itreatq(%nqpt) = 0 if this q-point won't be treated by this CPU else > 0. Each CPU calls this routine with its own array. comm=MPI communicator
OUTPUT
SOURCE
1709 subroutine dvdb_qcache_read(db, nfft, ngfft, mbsize, qselect_dvdb, itreatq, comm) 1710 1711 !Arguments ------------------------------------ 1712 !scalars 1713 integer,intent(in) :: nfft,comm 1714 class(dvdb_t),intent(inout) :: db 1715 real(dp),intent(in) :: mbsize 1716 !arrays 1717 integer,intent(in) :: ngfft(18), qselect_dvdb(db%nqpt) 1718 integer(i1b),intent(in) :: itreatq(db%nqpt) 1719 1720 !Local variables------------------------------- 1721 !scalars 1722 integer :: db_iqpt, cplex, imyp, ipc, ierr !, ii 1723 real(dp) :: cpu, wall, gflops, cpu_all, wall_all, gflops_all 1724 character(len=500) :: msg 1725 !arrays 1726 real(dp),allocatable :: v1scf(:,:,:,:) 1727 real(dp) :: tsec(2) 1728 1729 ! ************************************************************************* 1730 1731 call timab(1801, 1, tsec) 1732 call wrtout(std_out, " Loading Vscf(q) from DVDB into qcache...", do_flush=.True.) 1733 call cwtime(cpu_all, wall_all, gflops_all, "start") 1734 1735 db%qcache = qcache_new(db%nqpt, nfft, ngfft, mbsize, db%natom3, db%my_npert, db%nspden) 1736 db%qcache%itreatq(:) = itreatq 1737 1738 do db_iqpt=1,db%nqpt 1739 ! Ignore points reported by the oracle 1740 if (qselect_dvdb(db_iqpt) == 0) cycle 1741 1742 ! All procs are getting the same q-point. Exit when we reach maxnq 1743 ! TODO: Rewrite this part. 1744 !qcnt = 0 1745 !do ii=1,db%nqpt 1746 ! if (allocated(db%qcache%key(ii)%v1scf)) qcnt = qcnt + 1 1747 !end do 1748 !if (qcnt >= db%qcache%maxnq) exit 1749 1750 call cwtime(cpu, wall, gflops, "start") 1751 1752 ! Read all 3*natom potentials inside comm 1753 call db%readsym_allv1(db_iqpt, cplex, nfft, ngfft, v1scf, comm) 1754 1755 ! Print progress. 1756 if (db_iqpt <= 10 .or. mod(db_iqpt, 50) == 0) then 1757 write(msg,'(2(a,i0),a)') " Reading q-point [",db_iqpt,"/",db%nqpt, "]" 1758 call cwtime_report(msg, cpu, wall, gflops) 1759 end if 1760 1761 ! Transfer to cache taking into account my_npert. Note that IBZ may be distributed. 1762 if (db%qcache%itreatq(db_iqpt) /= 0) then 1763 ABI_MALLOC_OR_DIE(db%qcache%key(db_iqpt)%v1scf, (cplex, nfft, db%nspden, db%my_npert), ierr) 1764 do imyp=1,db%my_npert 1765 ipc = db%my_pinfo(3, imyp) 1766 db%qcache%key(db_iqpt)%v1scf(:,:,:,imyp) = real(v1scf(:,:,:,ipc), kind=QCACHE_KIND) 1767 end do 1768 end if 1769 1770 ABI_FREE(v1scf) 1771 end do 1772 1773 call wrtout(std_out, sjoin(" Memory allocated for cache:", ftoa(db%qcache%get_mbsize(), fmt="f8.1"), " [Mb] <<< MEM"), & 1774 pre_newlines=2) 1775 call cwtime_report(" DVDB qcache IO + symmetrization", cpu_all, wall_all, gflops_all) 1776 call timab(1801, 2, tsec) 1777 1778 end subroutine dvdb_qcache_read
m_dvdb/dvdb_qcache_update_from_file [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_qcache_update_from_file
FUNCTION
Read selected potentials and update the internal q-cache. This is a collective routine that must be called by all procs in comm.
INPUTS
nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT. ineed_qpt(%nqpt)=1 if this MPI rank requires this q-point. comm=MPI communicator
OUTPUT
SOURCE
1801 subroutine dvdb_qcache_update_from_file(db, nfft, ngfft, ineed_qpt, comm) 1802 1803 !Arguments ------------------------------------ 1804 !scalars 1805 integer,intent(in) :: nfft,comm 1806 class(dvdb_t),intent(inout) :: db 1807 !arrays 1808 integer,intent(in) :: ngfft(18), ineed_qpt(db%nqpt) 1809 1810 !Local variables------------------------------- 1811 !scalars 1812 integer,parameter :: master = 0 1813 integer :: db_iqpt, cplex, ierr, imyp, ipc, qcnt 1814 real(dp) :: cpu_all, wall_all, gflops_all, mbsize, max_mbsize 1815 character(len=500) :: msg 1816 !arrays 1817 integer :: qselect(db%nqpt) 1818 real(dp),allocatable :: v1scf(:,:,:,:) 1819 real(dp) :: tsec(2) 1820 1821 ! ************************************************************************* 1822 1823 if (db%qcache%maxnq == 0) return 1824 1825 ! Take the union of the q-points inside comm because we need to perform IO inside comm 1826 qselect = ineed_qpt 1827 call xmpi_sum(qselect, comm, ierr) 1828 qcnt = count(qselect > 0) 1829 if (qcnt == 0) then 1830 call wrtout(std_out, " All qpts in Vscf(q) already in cache. No need to perform IO. Hurrah!", do_flush=.True.) 1831 return 1832 end if 1833 1834 call wrtout(std_out, sjoin(" Need to update cache. Master node will read ", itoa(qcnt), "q-points. It may be slow..."), & 1835 do_flush=.True.) 1836 call timab(1807, 1, tsec) 1837 call cwtime(cpu_all, wall_all, gflops_all, "start") 1838 1839 if (db%qcache%make_room(ineed_qpt, msg) /= 0) then 1840 ABI_WARNING(msg) 1841 end if 1842 1843 do db_iqpt=1,db%nqpt 1844 if (qselect(db_iqpt) == 0) cycle 1845 1846 ! Read all 3*natom potentials inside comm. 1847 call db%readsym_allv1(db_iqpt, cplex, nfft, ngfft, v1scf, comm) 1848 1849 ! Transfer to cache taking into account my_npert. 1850 if (ineed_qpt(db_iqpt) /= 0) then 1851 ABI_MALLOC_OR_DIE(db%qcache%key(db_iqpt)%v1scf, (cplex, nfft, db%nspden, db%my_npert), ierr) 1852 do imyp=1,db%my_npert 1853 ipc = db%my_pinfo(3, imyp) 1854 db%qcache%key(db_iqpt)%v1scf(:,:,:,imyp) = real(v1scf(:,:,:,ipc), kind=QCACHE_KIND) 1855 end do 1856 end if 1857 1858 ABI_FREE(v1scf) 1859 end do 1860 1861 mbsize = db%ft_qcache%get_mbsize() 1862 call wrtout(std_out, sjoin(" Memory allocated for cache: ", ftoa(mbsize, fmt="f8.1"), " [Mb] <<< MEM")) 1863 call xmpi_max(mbsize, max_mbsize, comm, ierr) 1864 call wrtout(std_out, sjoin(" Max memory inside MPI comm: ", ftoa(max_mbsize, fmt="f8.1"), " [Mb] <<< MEM")) 1865 call cwtime_report(" dvdb_qcache_update_from_file", cpu_all, wall_all, gflops_all) 1866 call timab(1807, 2, tsec) 1867 1868 end subroutine dvdb_qcache_update_from_file
m_dvdb/dvdb_qdownsample [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_qdownsample
FUNCTION
Downsample the q-mesh. Produce new DVDB file
INPUTS
new_dvdb_fname=Path of output DVDB qptopt=option for the generation of q points (defines whether spatial symmetries and/or time-reversal can be used) ngqpt(3)=Division of coarse Q-mesh comm=MPI communicator.
OUTPUT
Only writing
SOURCE
7060 subroutine dvdb_qdownsample(dvdb, new_dvdb_fname, qptopt, ngqpt, comm) 7061 7062 !Arguments ------------------------------------ 7063 !scalars 7064 integer,intent(in) :: comm 7065 class(dvdb_t),intent(inout) :: dvdb 7066 character(len=*),intent(in) :: new_dvdb_fname 7067 !arrays 7068 integer,intent(in) :: qptopt, ngqpt(3) 7069 7070 !Local variables ------------------------------ 7071 !scalars 7072 integer,parameter :: master=0 7073 integer :: fform_pot=111 7074 integer :: ierr,my_rank,nproc,idir,ipert,iat,ipc,ispden 7075 integer :: cplex, db_iqpt, npc, nqbz, nqibz, iq, ifft, nperts_read, nfft, ount 7076 character(len=500) :: msg 7077 !arrays 7078 integer :: qptrlatt(3,3) 7079 integer,allocatable :: iq_read(:), pinfo(:,:) 7080 real(dp) :: rhog1_g0(2) 7081 real(dp),allocatable :: v1scf(:,:,:), v1(:), wtq(:), qibz(:,:), qbz(:,:) 7082 7083 !************************************************************************ 7084 7085 my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm) 7086 if (my_rank /= master) goto 20 7087 7088 nfft = product(dvdb%ngfft(1:3)) 7089 7090 ! ======================= 7091 ! Setup fine q-point grid 7092 ! ======================= 7093 ! Generate the list of irreducible q-points in the coarse grid 7094 qptrlatt = 0; qptrlatt(1,1) = ngqpt(1); qptrlatt(2,2) = ngqpt(2); qptrlatt(3,3) = ngqpt(3) 7095 call kpts_ibz_from_kptrlatt(dvdb%cryst, qptrlatt, qptopt, 1, [zero, zero, zero], nqibz, qibz, wtq, nqbz, qbz) 7096 7097 ! ======================================= 7098 ! Open DVDB and copy important dimensions 7099 ! ======================================= 7100 7101 ABI_MALLOC(iq_read, (nqibz)) 7102 ABI_MALLOC(pinfo, (3, 3*dvdb%mpert)) 7103 nperts_read = 0 7104 7105 do iq=1,nqibz 7106 ! Find the index of the q-point in the DVDB. 7107 db_iqpt = dvdb%findq(qibz(:, iq)) 7108 ABI_CHECK(db_iqpt /= -1, sjoin("Q-point:", ktoa(qibz(:, iq)), "not found in DVDB!")) 7109 iq_read(iq) = db_iqpt 7110 7111 ! Count the number of perturbations. 7112 npc = dvdb_get_pinfo(dvdb, db_iqpt, cplex, pinfo) 7113 do ipc=1,npc 7114 idir = pinfo(1,ipc); iat = pinfo(2,ipc); ipert = pinfo(3, ipc) 7115 if (iat <= dvdb%cryst%natom) nperts_read = nperts_read + 1 7116 end do 7117 end do 7118 7119 ! ================================================= 7120 ! Open the new DVDB file and write preliminary info 7121 ! ================================================= 7122 !nperts = nperts_read + nperts_interpolate 7123 if (open_file(new_dvdb_fname, msg, newunit=ount, form="unformatted", action="write", status="unknown") /= 0) then 7124 ABI_ERROR(msg) 7125 end if 7126 write(ount, err=10, iomsg=msg) dvdb_last_version 7127 write(ount, err=10, iomsg=msg) nperts_read 7128 7129 ! Read all perturbations on the coarse Q-mesh and write them to the new DVDB 7130 rhog1_g0 = zero 7131 7132 do iq=1,nqibz 7133 db_iqpt = iq_read(iq) 7134 7135 ! Read each irreducible perturbation potentials 7136 npc = dvdb_get_pinfo(dvdb, db_iqpt, cplex, pinfo) 7137 ABI_CHECK(npc /= 0, "npc == 0!") 7138 7139 ABI_MALLOC(v1scf, (cplex, nfft, dvdb%nspden)) 7140 ABI_MALLOC(v1, (cplex*nfft)) 7141 7142 do ipc=1,npc 7143 idir = pinfo(1,ipc); iat = pinfo(2,ipc); ipert = pinfo(3, ipc) 7144 if (dvdb%read_onev1(idir, iat, db_iqpt, cplex, nfft, dvdb%ngfft, v1scf, msg) /= 0) then 7145 ABI_ERROR(msg) 7146 end if 7147 7148 ! Change the header. 7149 dvdb%hdr_ref%qptn = qibz(:, iq) 7150 dvdb%hdr_ref%pertcase = ipert 7151 7152 ! Write header 7153 call dvdb%hdr_ref%fort_write(ount, fform_pot, ierr) 7154 ABI_CHECK(ierr == 0, "hdr_fort_write returned ierr = 0") 7155 7156 do ispden=1,dvdb%nspden 7157 v1 = reshape(v1scf(:,:,ispden), [cplex*nfft]) 7158 write(ount, err=10, iomsg=msg) (v1(ifft), ifft=1,cplex*nfft) 7159 end do 7160 if (dvdb_last_version > 1) write(ount, err=10, iomsg=msg) rhog1_g0 7161 end do 7162 7163 ABI_FREE(v1scf) 7164 ABI_FREE(v1) 7165 end do 7166 7167 close(ount) 7168 7169 ! Free memory 7170 ABI_FREE(qbz) 7171 ABI_FREE(qibz) 7172 ABI_FREE(wtq) 7173 ABI_FREE(iq_read) 7174 ABI_FREE(pinfo) 7175 7176 write(msg, '(2a)') " Downsampling of the e-ph coupling potential completed", ch10 7177 call wrtout(std_out, msg, do_flush=.True.) 7178 7179 20 continue 7180 call xmpi_barrier(comm) 7181 7182 return 7183 7184 ! Handle Fortran IO error 7185 10 continue 7186 ABI_ERROR(msg) 7187 7188 end subroutine dvdb_qdownsample
m_dvdb/dvdb_read_onev1 [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_read_onev1
FUNCTION
Read the DFPT potential for the specified (idir, ipert, iqpt). Note that iqpt is the index in dvdb%qpts. Use dvdb_findq to get the index from the q-point in reduced coordinates.
INPUTS
idir=Direction of the perturbation ipert=Perturbation type. iqpt=Index of the q-point in dvdb%qpts cplex=1 if real, 2 if complex potentials. nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT.
OUTPUT
ierr=Non-zero if error. v1scf(cplex*nfft, nspden)=DFT potential associated to (idir, ipert, iqpt). msg=String with error message if ierr /= 0.
SOURCE
1187 integer function dvdb_read_onev1(db, idir, ipert, iqpt, cplex, nfft, ngfft, v1scf, msg) result(ierr) 1188 1189 !Arguments ------------------------------------ 1190 !scalars 1191 integer,intent(in) :: idir,ipert,iqpt,cplex,nfft 1192 character(len=*),intent(out) :: msg 1193 class(dvdb_t),intent(inout) :: db 1194 !arrays 1195 integer,intent(in) :: ngfft(18) 1196 real(dp),intent(out) :: v1scf(cplex*nfft,db%nspden) 1197 1198 !Local variables------------------------------- 1199 !scalars 1200 integer,save :: enough = 0 1201 integer :: iv1,ispden,nfftot_file,nfftot_out,ifft 1202 type(MPI_type) :: MPI_enreg_seq 1203 !arrays 1204 integer :: ngfft_in(18),ngfft_out(18) 1205 real(dp),allocatable :: v1r_file(:,:),v1g_in(:,:),v1g_out(:,:) 1206 1207 ! ************************************************************************* 1208 1209 ! Consistency checks 1210 ierr = 1 1211 iv1 = db%pos_dpq(idir,ipert,iqpt) 1212 1213 if (iv1 == 0) then 1214 write(msg,"(3(a,i0))")"Cannot find idir: ",idir,", ipert: ",ipert,", iqpt:",iqpt 1215 return 1216 end if 1217 1218 if (cplex /= db%cplex_v1(iv1)) then 1219 write(msg,"(2(a,i0))")"Wrong cplex. Expecting: ",db%cplex_v1(iv1),", received: ",cplex 1220 return 1221 end if 1222 1223 ! Find (idir, ipert, iqpt) and skip the header. 1224 call dvdb_seek(db, idir, ipert, iqpt) 1225 ierr = my_hdr_skip(db%fh, idir, ipert, db%qpts(:,iqpt), msg) 1226 if (ierr /= 0) then 1227 msg = sjoin("In my_hdr_skip:", msg) 1228 return 1229 end if 1230 1231 ! Read v1 from file. 1232 nfftot_out = product(ngfft(:3)); nfftot_file = product(db%ngfft3_v1(:3, iv1)) 1233 1234 if (all(ngfft(:3) == db%ngfft3_v1(:3, iv1))) then 1235 do ispden=1,db%nspden 1236 read(db%fh, err=10, iomsg=msg) (v1scf(ifft, ispden), ifft=1,cplex*nfftot_file) 1237 end do 1238 else 1239 ! The FFT mesh used in the caller differ from the one found in the DVDB --> Fourier interpolation 1240 ! TODO: Add linear interpolation as well. 1241 if (enough == 0) ABI_COMMENT("Performing FFT interpolation of DFPT potentials as input ngfft differs from ngfft_file.") 1242 enough = enough + 1 1243 ABI_MALLOC(v1r_file, (cplex*nfftot_file, db%nspden)) 1244 do ispden=1,db%nspden 1245 read(db%fh, err=10, iomsg=msg) (v1r_file(ifft, ispden), ifft=1,cplex*nfftot_file) 1246 end do 1247 1248 ! Call fourier_interpol to get v1scf on ngfft mesh. 1249 ngfft_in = ngfft; ngfft_out = ngfft 1250 ngfft_in(1:3) = db%ngfft3_v1(1:3, iv1); ngfft_out(1:3) = ngfft(1:3) 1251 ngfft_in(4:6) = ngfft_in(1:3); ngfft_out(4:6) = ngfft_out(1:3) 1252 ngfft_in(9:18) = 0; ngfft_out(9:18) = 0 1253 ngfft_in(10) = 1; ngfft_out(10) = 1 1254 1255 call initmpi_seq(MPI_enreg_seq) 1256 ! Which one is coarse? Note that this part is not very robust and can fail! 1257 if (ngfft_in(2) * ngfft_in(3) < ngfft_out(2) * ngfft_out(3)) then 1258 call init_distribfft_seq(MPI_enreg_seq%distribfft,'c',ngfft_in(2),ngfft_in(3),'all') 1259 call init_distribfft_seq(MPI_enreg_seq%distribfft,'f',ngfft_out(2),ngfft_out(3),'all') 1260 else 1261 call init_distribfft_seq(MPI_enreg_seq%distribfft,'f',ngfft_in(2),ngfft_in(3),'all') 1262 call init_distribfft_seq(MPI_enreg_seq%distribfft,'c',ngfft_out(2),ngfft_out(3),'all') 1263 end if 1264 1265 ABI_MALLOC(v1g_in, (2, nfftot_file)) 1266 ABI_MALLOC(v1g_out, (2, nfftot_out)) 1267 1268 call fourier_interpol(cplex,db%nspden,0,0,nfftot_file,ngfft_in,nfftot_out,ngfft_out,& 1269 MPI_enreg_seq,v1r_file,v1scf,v1g_in,v1g_out) 1270 1271 ABI_FREE(v1g_in) 1272 ABI_FREE(v1g_out) 1273 ABI_FREE(v1r_file) 1274 call destroy_mpi_enreg(MPI_enreg_seq) 1275 end if 1276 1277 ! Skip record with rhog1_g0 (if present) 1278 if (db%version > 1) read(db%fh, err=10, iomsg=msg) 1279 1280 db%current_fpos = db%current_fpos + 1 1281 !write(std_out, *)"incr current_fpos", db%current_fpos 1282 1283 return 1284 1285 ! Handle Fortran IO error 1286 10 continue 1287 ierr = 1 1288 msg = sjoin("Error while reading", db%path, ch10, msg) 1289 1290 end function dvdb_read_onev1
m_dvdb/dvdb_readsym_allv1 [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_readsym_allv1
FUNCTION
Read all 3*natom DFPT potentials for the given iqpt (only atomic perturbations). The routine will: 1) Reconstruct the potentials by symmetry if the DVDB contains less than 3*natom potentials. 2) interpolate the data if the input FFT mesh defined by `ngfft` differs from the one used to store data in the file. Note that iqpt is the index in dvdb%qpts. Use dvdb_findq to get the index from the q-point in reduced coordinates.
INPUTS
iqpt=Index of the q-point in dvdb%qpts nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT comm=MPI communicator
OUTPUT
cplex=1 if real, 2 if complex. v1scf(cplex, nfft, nspden, 3*natom)= v1scf potentials on the real-space FFT mesh for the 3*natom perturbations.
SOURCE
1323 subroutine dvdb_readsym_allv1(db, iqpt, cplex, nfft, ngfft, v1scf, comm) 1324 1325 !Arguments ------------------------------------ 1326 !scalars 1327 integer,intent(in) :: iqpt,nfft,comm 1328 integer,intent(out) :: cplex 1329 class(dvdb_t),intent(inout) :: db 1330 !arrays 1331 integer,intent(in) :: ngfft(18) 1332 real(dp) ABI_ASYNC ,allocatable,intent(out) :: v1scf(:,:,:,:) 1333 1334 !Local variables------------------------------- 1335 !scalars 1336 integer,parameter :: master=0 1337 integer :: ipc,npc,idir,ipert,pcase,my_rank,nproc,ierr,mu 1338 character(len=500) :: msg 1339 !arrays 1340 integer :: pinfo(3,3*db%mpert),pflag(3, db%natom) 1341 real(dp) :: tsec(2) 1342 integer,allocatable :: requests(:) 1343 1344 ! ************************************************************************* 1345 1346 ! Keep track of total time spent. 1347 call timab(1805, 1, tsec) 1348 1349 my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm) 1350 1351 ! Get number of perturbations computed for this iqpt as well as cplex. 1352 npc = dvdb_get_pinfo(db, iqpt, cplex, pinfo) 1353 ABI_CHECK(npc /= 0, "npc == 0!") 1354 1355 ABI_MALLOC_OR_DIE(v1scf, (cplex, nfft, db%nspden, 3*db%natom), ierr) 1356 1357 ! Master read all available perturbations and broadcasts data (non-blocking to overlap IO and MPI) 1358 ABI_MALLOC(requests, (npc)) 1359 1360 do ipc=1,npc 1361 idir = pinfo(1,ipc); ipert = pinfo(2,ipc); pcase = pinfo(3, ipc) 1362 if (my_rank == master) then 1363 if (db%read_onev1(idir, ipert, iqpt, cplex, nfft, ngfft, v1scf(:,:,:,pcase), msg) /= 0) then 1364 ABI_ERROR(msg) 1365 end if 1366 end if 1367 if (nproc > 1) call xmpi_ibcast(v1scf(:,:,:,pcase), master, comm, requests(ipc), ierr) 1368 end do 1369 1370 if (nproc > 1) call xmpi_waitall(requests, ierr) 1371 ABI_FREE(requests) 1372 1373 ! Return if all perts are available. 1374 if (npc == 3*db%natom) then 1375 if (db%symv1==1) then 1376 if (db%debug) write(std_out,*)"Potentials are available but will call v1phq_symmetrize because of symv1" 1377 do mu=1,db%natom3 1378 !if (mod(mu, nproc) /= my_rank) cycle ! MPI parallelism. 1379 idir = mod(mu-1, 3) + 1; ipert = (mu - idir) / 3 + 1 1380 call v1phq_symmetrize(db%cryst,idir,ipert,db%symq_table(:,:,:,iqpt),ngfft,cplex,nfft,& 1381 db%nspden,db%nsppol,db%mpi_enreg,v1scf(:,:,:,mu)) 1382 !call MPI_Ibcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, MPI_Request *request) 1383 end do 1384 end if 1385 if (db%debug) write(std_out,*)"All perts available. Returning" 1386 return 1387 end if 1388 1389 ! Perturbation are missing and we have to reconstruct them by symmetry. 1390 ! This is the common case when DFPT calculations are done for independent perturbations only. 1391 if (db%debug) then 1392 write(std_out,*)sjoin("Will use symmetries to recostruct:", itoa(3*db%natom - npc), "perturbations") 1393 end if 1394 1395 ! 0 if pert is not available. 1396 ! 1 if pert is on file. 1397 ! 2 if pert has been reconstructed by symmetry. 1398 pflag = 0 1399 do ipc=1,npc 1400 pflag(pinfo(1,ipc), pinfo(2,ipc)) = 1 1401 end do 1402 1403 call v1phq_complete(db%cryst,db%qpts(:,iqpt),ngfft,cplex,nfft,db%nspden,db%nsppol,db%mpi_enreg,db%symv1,pflag,v1scf) 1404 1405 call timab(1805, 2, tsec) 1406 1407 end subroutine dvdb_readsym_allv1
m_dvdb/dvdb_readsym_qbz [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_readsym_qbz
FUNCTION
This is the MAIN ENTRY POINT for client code. Reconstruct the DFPT potential for a q-point in the BZ starting from its symmetrical image in the IBZ. Implements caching mechanism to reduce IO.
INPUTS
cryst<crystal_t>=crystal structure parameters qbz(3)=Q-point in BZ. indq2db(6)=Symmetry mapping qbz --> DVDB qpoint produced by listkk. nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT comm=MPI communicator (either xmpi_comm_self or comm for perturbations.
OUTPUT
cplex=1 if real, 2 if complex. v1scf(cplex, nfft, nspden, db%my_npert)= v1scf potentials on the real-space FFT mesh for the db%my_npert perturbations treated by this MPI rank.
SOURCE
1436 subroutine dvdb_readsym_qbz(db, cryst, qbz, indq2db, cplex, nfft, ngfft, v1scf, comm) 1437 1438 !Arguments ------------------------------------ 1439 !scalars 1440 integer,intent(in) :: nfft,comm 1441 integer,intent(out) :: cplex 1442 type(crystal_t),intent(in) :: cryst 1443 class(dvdb_t),intent(inout) :: db 1444 !arrays 1445 integer,intent(in) :: ngfft(18) 1446 integer,intent(in) :: indq2db(6) 1447 real(dp),intent(in) :: qbz(3) 1448 real(dp),allocatable,intent(out) :: v1scf(:,:,:,:) 1449 1450 !Local variables------------------------------- 1451 !scalars 1452 integer :: db_iqpt, itimrev, isym, npc, ierr, imyp, mu, root 1453 logical :: isirr_q, incache 1454 !arrays 1455 integer :: pinfo(3,3*db%mpert), g0q(3), requests(db%natom3) 1456 real(dp) :: tsec(2) 1457 real(dp) ABI_ASYNC, allocatable :: work(:,:,:,:), work2(:,:,:,:) 1458 1459 ! ************************************************************************* 1460 ABI_UNUSED(qbz(1)) 1461 1462 ! Keep track of total time spent. 1463 call timab(1802, 1, tsec) 1464 1465 db_iqpt = indq2db(1) 1466 db%qcache%count_qused(db_iqpt) = db%qcache%count_qused(db_iqpt) + 1 1467 db%qcache%stats(1) = db%qcache%stats(1) + 1 1468 1469 ! IS(q_dvdb) + g0q = q_bz 1470 isym = indq2db(2); itimrev = indq2db(6) + 1; g0q = indq2db(3:5) 1471 isirr_q = (isym == 1 .and. itimrev == 1 .and. all(g0q == 0)) 1472 1473 if (db%qcache%use_3natom_cache .and. db%qcache%stored_iqibz_cplex(1) == db_iqpt .and. .not. isirr_q) then 1474 ! All 3 natom potentials for qibz are in cache. Symmetrize to get Sq without MPI communication. 1475 db%qcache%stats(2) = db%qcache%stats(2) + 1 1476 cplex = db%qcache%stored_iqibz_cplex(2) 1477 ABI_MALLOC(work2, (cplex, nfft, db%nspden, db%natom3)) 1478 call v1phq_rotate(cryst, db%qpts(:, db_iqpt), isym, itimrev, g0q, ngfft, cplex, nfft, & 1479 db%nspden, db%mpi_enreg, db%qcache%v1scf_3natom_qibz, work2, db%comm_pert) 1480 ! Extract my data from work2 1481 ABI_MALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert)) 1482 do imyp=1,db%my_npert 1483 v1scf(:,:,:,imyp) = work2(:,:,:,db%my_pinfo(3, imyp)) 1484 end do 1485 ABI_FREE(work2) 1486 call timab(1802, 2, tsec); return 1487 end if 1488 1489 ! Check whether db_iqpt is in cache. 1490 incache = .False. 1491 if (db%qcache%maxnq > 0) then 1492 ! Get number of perturbations computed for this iqpt as well as cplex. 1493 npc = dvdb_get_pinfo(db, db_iqpt, cplex, pinfo) 1494 ABI_CHECK(npc /= 0, "npc == 0!") 1495 1496 ! Size of v1scf in qcache depends on db%my_npert 1497 if (allocated(db%qcache%key(db_iqpt)%v1scf)) then 1498 if (size(db%qcache%key(db_iqpt)%v1scf, dim=1) == cplex .and. size(db%qcache%key(db_iqpt)%v1scf, dim=2) == nfft) then 1499 ! Potential in cache --> copy it in output v1scf. 1500 ABI_MALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert)) 1501 v1scf = real(db%qcache%key(db_iqpt)%v1scf, kind=QCACHE_KIND) 1502 incache = .True. 1503 db%qcache%stats(3) = db%qcache%stats(3) + 1 1504 else 1505 ! This to handle the unlikely event in which the caller changes ngfft! 1506 ABI_WARNING("different cplex or nfft!") 1507 end if 1508 else 1509 !call wrtout(std_out, sjoin("Cache miss for db_iqpt. Will read it from file...", itoa(db_iqpt))) 1510 db%qcache%stats(4) = db%qcache%stats(4) + 1 1511 end if 1512 end if 1513 1514 if (.not. incache) then 1515 ! Read the dvscf potentials in the IBZ for all 3*natom perturbations. 1516 ! This call allocates v1scf(cplex, nfftf, nspden, 3*natom) 1517 call db%readsym_allv1(db_iqpt, cplex, nfft, ngfft, v1scf, comm) 1518 1519 ! Store all 3 natom potentials for q in IBZ in cache. 1520 if (db%qcache%use_3natom_cache .and. db%qcache%stored_iqibz_cplex(1) /= db_iqpt .and. isirr_q) then 1521 if (cplex /= db%qcache%stored_iqibz_cplex(2)) then 1522 ABI_REMALLOC(db%qcache%v1scf_3natom_qibz, (cplex, nfft, db%nspden, db%natom3)) 1523 end if 1524 db%qcache%v1scf_3natom_qibz = v1scf 1525 db%qcache%stored_iqibz_cplex = [db_iqpt, cplex] 1526 end if 1527 end if 1528 1529 if (.not. isirr_q) then 1530 ! Must rotate db_iqpt to get potential for qpoint in the BZ. 1531 ! Be careful with the shape of output v1scf because the routine returns db%my_npert potentials. 1532 1533 if (db%my_npert == db%natom3) then 1534 ABI_MALLOC(work, (cplex, nfft, db%nspden, db%natom3)) 1535 work = v1scf 1536 call v1phq_rotate(cryst, db%qpts(:, db_iqpt), isym, itimrev, g0q, ngfft, cplex, nfft, & 1537 db%nspden, db%mpi_enreg, work, v1scf, db%comm_pert) 1538 ABI_FREE(work) 1539 1540 else 1541 ! Parallelism over perturbations. 1542 ABI_MALLOC(work2, (cplex, nfft, db%nspden, db%natom3)) 1543 1544 if (incache) then 1545 ! Cache is distributed --> have to collect all 3*natom perts inside db%comm_pert. 1546 ABI_MALLOC(work, (cplex, nfft, db%nspden, db%natom3)) 1547 1548 ! IBCAST is much faster than a naive xmpi_sum. 1549 call timab(1806, 1, tsec) 1550 do mu=1,db%natom3 1551 root = db%pert_table(1, mu) 1552 if (root == db%me_pert) then 1553 work(:,:,:,mu) = v1scf(:,:,:,db%pert_table(2, mu)) 1554 end if 1555 call xmpi_ibcast(work(:,:,:,mu), root, db%comm_pert, requests(mu), ierr) 1556 end do 1557 call xmpi_waitall(requests, ierr) 1558 call timab(1806, 2, tsec) 1559 1560 ! Store all 3 natom potentials for q in IBZ in cache. 1561 if (db%qcache%use_3natom_cache .and. db%qcache%stored_iqibz_cplex(1) /= db_iqpt) then 1562 if (cplex /= db%qcache%stored_iqibz_cplex(2)) then 1563 ABI_REMALLOC(db%qcache%v1scf_3natom_qibz, (cplex, nfft, db%nspden, db%natom3)) 1564 end if 1565 db%qcache%v1scf_3natom_qibz = work 1566 db%qcache%stored_iqibz_cplex = [db_iqpt, cplex] 1567 end if 1568 1569 ! Now rotate. 1570 call v1phq_rotate(cryst, db%qpts(:, db_iqpt), isym, itimrev, g0q, ngfft, cplex, nfft, & 1571 db%nspden, db%mpi_enreg, work, work2, db%comm_pert) 1572 ABI_FREE(work) 1573 1574 else 1575 ! All 3 natom have been read in v1scf by dvdb_readsym_allv1 1576 call v1phq_rotate(cryst, db%qpts(:, db_iqpt), isym, itimrev, g0q, ngfft, cplex, nfft, & 1577 db%nspden, db%mpi_enreg, v1scf, work2, db%comm_pert) 1578 end if 1579 1580 ! Reallocate v1scf with my_npert and extract data from work2. 1581 ABI_REMALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert)) 1582 do imyp=1,db%my_npert 1583 v1scf(:,:,:,imyp) = work2(:,:,:,db%my_pinfo(3, imyp)) 1584 end do 1585 ABI_FREE(work2) 1586 end if 1587 1588 else 1589 ! Handle potentials read from file in case of parallelism over perturbations. 1590 if (.not. incache .and. db%my_npert /= db%natom3) then 1591 ABI_MALLOC(work, (cplex, nfft, db%nspden, db%my_npert)) 1592 do imyp=1,db%my_npert 1593 work(:,:,:,imyp) = v1scf(:,:,:,db%my_pinfo(3, imyp)) 1594 end do 1595 1596 ABI_REMALLOC(v1scf, (cplex, nfft, db%nspden, db%my_npert)) 1597 v1scf = work 1598 ABI_FREE(work) 1599 end if 1600 end if ! not isirr_q 1601 1602 call timab(1802, 2, tsec) 1603 1604 end subroutine dvdb_readsym_qbz
m_dvdb/dvdb_rewind [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_rewind
FUNCTION
Rewind the file and move to the first header. Needed only if dvdb%iomode==IO_MODE_FORTRAN Return exit code and error message in msg if ierr != 0
SOURCE
4771 integer function dvdb_rewind(db, msg) result(ierr) 4772 4773 !Arguments ------------------------------------ 4774 type(dvdb_t),intent(inout) :: db 4775 character(len=*),intent(out) :: msg 4776 4777 ! ************************************************************************* 4778 4779 ierr = 0 4780 if (db%iomode == IO_MODE_FORTRAN) then 4781 rewind(db%fh, err=10, iomsg=msg) 4782 read(db%fh, err=10, iomsg=msg) ! version 4783 read(db%fh, err=10, iomsg=msg) ! numv1 4784 db%current_fpos = 1 4785 4786 else 4787 ierr = -1 4788 msg = "should not be called when iomode /= IO_MODE_FORTRAN" 4789 end if 4790 4791 return 4792 4793 ! Handle Fortran IO error 4794 10 continue 4795 ierr = 1 4796 msg = sjoin("Error while reading", db%path, ch10, msg) 4797 4798 end function dvdb_rewind
m_dvdb/dvdb_seek [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_seek
FUNCTION
Move the internal file pointer so that it points to the block with (idir, ipert, iqpt). Needed only if dvdb%iomode==IO_MODE_FORTRAN
INPUTS
idir,ipert,iqpt = (direction, perturbation, q-point) indices
SIDE EFFECTS
db<type(dvdb_t)>: modifies db%current_fpos.
SOURCE
4683 subroutine dvdb_seek(db, idir, ipert, iqpt) 4684 4685 !Arguments ------------------------------------ 4686 integer,intent(in) :: idir, ipert, iqpt 4687 type(dvdb_t),intent(inout) :: db 4688 4689 !Local variables------------------------------- 4690 integer :: pos_now,pos_wanted,ii,ispden,nn,ierr 4691 real(dp),parameter :: fake_qpt(3)=zero 4692 character(len=500) :: msg 4693 4694 ! ************************************************************************* 4695 4696 if (db%iomode == IO_MODE_FORTRAN) then 4697 pos_now = db%current_fpos 4698 pos_wanted = db%pos_dpq(idir,ipert,iqpt) 4699 ABI_CHECK(pos_wanted /= 0, "pos_wanted cannot be zero!") 4700 4701 ! Optimal access. 4702 if (pos_now == pos_wanted) return 4703 4704 if (pos_wanted < pos_now) then 4705 ! Backspace previous records and header 4706 ! but only if nn <= pos_wanted else rewind file and skip pos_wanted potentials (should be faster) 4707 nn = pos_now - pos_wanted 4708 if (nn <= pos_wanted) then 4709 do ii=1,nn 4710 !write(std_out, *)"backspacing" 4711 if (db%version > 1) backspace(unit=db%fh, err=10, iomsg=msg) 4712 do ispden=1,db%nspden 4713 backspace(unit=db%fh, err=10, iomsg=msg) 4714 end do 4715 ierr = db%hdr_ref%backspace(db%fh, msg) 4716 if (ierr /= 0) goto 10 4717 end do 4718 db%current_fpos = pos_wanted; return 4719 else 4720 ! rewind the file and read it from the beginning 4721 if (dvdb_rewind(db, msg) /= 0) then 4722 ABI_ERROR(msg) 4723 end if 4724 nn = pos_wanted 4725 end if 4726 4727 else 4728 nn = pos_wanted - pos_now + 1 4729 end if 4730 4731 do ii=1,nn-1 4732 !write(std_out,*)"in seek with ii: ",ii,"pos_wanted: ",pos_wanted 4733 if (my_hdr_skip(db%fh, -1, -1, fake_qpt, msg) /= 0) then 4734 ABI_ERROR(msg) 4735 end if 4736 ! Skip the records with v1. 4737 do ispden=1,db%nspden 4738 read(db%fh, err=10, iomsg=msg) 4739 end do 4740 ! Skip record with rhog1_g0 (if present) 4741 if (db%version > 1) read(db%fh, err=10, iomsg=msg) 4742 end do 4743 4744 db%current_fpos = pos_wanted 4745 4746 else 4747 ABI_ERROR("Should not be called when iomode /= IO_MODE_FORTRAN") 4748 end if 4749 4750 return 4751 4752 ! Handle Fortran IO error 4753 10 continue 4754 msg = sjoin("Error while reading", db%path, ch10, msg) 4755 4756 end subroutine dvdb_seek
m_dvdb/dvdb_set_pert_distrib [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_set_pert_distrib
FUNCTION
Activate MPI distribution of the 3*natom perturbations.
INPUTS
my_npert=Number of perturbations treated by this rank natom3= 3 * natom my_pinfo(3, my_npert) my_pinfo(1, ip) gives the `idir` index of the ip-th perturbation. my_pinfo(2, ip) gives the `ipert` index of the ip-th perturbation. my_pinfo(3, ip) gives `pertcase`=idir + (ipert-1)*3 pert_table(2, natom3) pert_table(1, npert): rank of the processor treating this atomic perturbation. pert_table(2, npert): imyp index in my_pinfo table, -1 if this rank is not treating ipert. comm_pert=MPI communicator used to distribute the 3*natom perturbations
SOURCE
4636 subroutine dvdb_set_pert_distrib(self, my_npert, natom3, my_pinfo, pert_table, comm_pert) 4637 4638 !Arguments ------------------------------------ 4639 !scalars 4640 class(dvdb_t),intent(inout) :: self 4641 integer,intent(in) :: my_npert, natom3, comm_pert 4642 !arrays 4643 integer,intent(in) :: my_pinfo(3,my_npert), pert_table(2,natom3) 4644 4645 ! ************************************************************************* 4646 4647 self%comm_pert = comm_pert 4648 self%nprocs_pert = xmpi_comm_size(comm_pert) 4649 self%me_pert = xmpi_comm_rank(comm_pert) 4650 self%my_npert = my_npert 4651 4652 ABI_SFREE(self%my_pinfo) 4653 ABI_SFREE(self%pert_table) 4654 call alloc_copy(my_pinfo, self%my_pinfo) 4655 call alloc_copy(pert_table, self%pert_table) 4656 4657 if (self%debug) then 4658 write(std_out, *)"Activating perturbation over perturbations:" 4659 write(std_out, *)"nprocs_pert: ", self%nprocs_pert 4660 write(std_out, *)"my_pinfo: ",self%my_pinfo 4661 write(std_out, *)"pert_table: ",self%pert_table 4662 end if 4663 4664 end subroutine dvdb_set_pert_distrib
m_dvdb/dvdb_t [ Types ]
NAME
dvdb_t
FUNCTION
Database of DFPT results. The database contains `numv1` perturbations and the corresponding first order local potentials in real space on the FFT mesh. Note that one can have different FFT meshes for the different perturbations. Provides methods to Fourier interpolate the potentials including the treatment of long-range behaviour in the FT interpolation in polar semiconductors.
NOTES
natom, nspden, nspinor, and usepaw are global variables in the sense that it's not possible to add new entries to the database if these dimensions differ from the global ones.
SOURCE
198 type,public :: dvdb_t 199 200 integer :: fh 201 ! file handle 202 ! Fortran unit number if iomode==IO_MODE_FORTRAN 203 ! MPI file handler if iomode==IO_MODE_MPI 204 205 integer :: comm 206 ! Global MPI communicator used for IO. 207 208 integer :: comm_rpt = xmpi_comm_self 209 ! MPI communicator used to distributed R-points. 210 211 integer :: nprocs_rpt = 1 212 ! Number of cpus for parallelism over R-points. 213 214 integer :: me_rpt = 0 215 ! My rank in comm_rpt. 216 217 integer :: comm_pert = xmpi_comm_self 218 ! MPI communicator for parallelism over atomic perturbations. 219 220 integer :: nprocs_pert = 1 221 ! Number of cpus for parallelism over atomic perturbations. 222 223 integer :: me_pert = 0 224 ! My rank in comm over atomic perturbations. 225 226 integer :: my_npert 227 ! Number of atomic perturbations or phonon modes treated by this MPI rank 228 229 integer,allocatable :: my_pinfo(:,:) 230 ! my_pinfo(3, my_npert) 231 ! my_pinfo(1, ip) gives the `idir` index of the ip-th perturbation. 232 ! my_pinfo(2, ip) gives the `ipert` index of the ip-th perturbation. 233 ! my_pinfo(3, ip) gives `pertcase`=idir + (ipert-1)*3 234 235 integer,allocatable :: pert_table(:,:) 236 ! pert_table(2, natom3) 237 ! pert_table(1, npert): rank of the processor treating this atomic perturbation. 238 ! pert_table(2, npert): imyp index in my_pinfo table, -1 if this rank is not treating ipert. 239 240 integer :: version 241 ! File format version read from file. 242 243 integer :: iomode = IO_MODE_FORTRAN 244 ! Method used to access the DVDB file: 245 ! IO_MODE_FORTRAN for usual Fortran IO routines 246 ! IO_MODE_MPI if MPI/IO routines. 247 248 integer :: rw_mode = DVDB_NOMODE 249 ! (Read|Write) mode 250 251 integer :: current_fpos 252 ! The current position of the file pointer used for sequential access with Fortran-IO 253 254 integer :: numv1 255 ! Number of v1 potentials present in file. 256 257 integer :: nqpt 258 ! Number of q-points 259 260 integer :: natom 261 ! Number of atoms 262 263 integer :: natom3 264 ! 3 * natom 265 266 integer :: nspden 267 ! Number of spin density components 268 269 integer :: nsppol 270 ! Number of spin polarizations. 271 272 integer :: nspinor 273 ! Number of spinor components. 274 275 integer :: usepaw 276 ! 1 if PAW calculation, 0 otherwise 277 278 integer :: mpert 279 ! Maximum number of perturbations 280 281 integer :: my_nrpt = 0 282 ! Number of real space points used for Fourier interpolation treated by this MPI rank. 283 284 integer :: nrtot = 0 285 ! Total Number of real space points used for Fourier interpolation. 286 287 integer :: prtvol = 0 288 ! Verbosity level 289 290 integer :: brav = 1 291 ! Option for the sampling of the BZ (input variable, the same option is stored in ifc_t) 292 293 real(dp) :: qdamp = 0.1_dp 294 ! Exponential damping used in the Fourier transform of the long-range potentials 295 ! Use negative value to deactivate damping. 296 297 logical :: debug = .False. 298 ! Debug flag 299 300 logical :: has_dielt = .False. 301 ! True if the dielectric tensor is available. 302 303 logical :: has_zeff = .False. 304 ! True if Born effective charges are available. 305 306 logical :: has_quadrupoles = .False. 307 ! True if quadrupoles are available. 308 309 logical :: has_efield = .False. 310 ! True if electric field perturbations are available. 311 312 integer :: add_lr = 1 313 ! Flag defining the treatment of the long range component in the interpolation of the DFPT potentials. 314 ! 315 ! 0 --> No treatment 316 ! 1 --> Remove LR model when building W(R,r). Add it back after W(R,r) --> v(q) Fourier interpolation 317 ! This is the standard approach for polar materials. 318 ! -1 --> Remove LR model when building W(R,r). DO NOT reintroduce it after Fourier interpolation. 319 ! This procedure should be used for homopolar materials with (spurious) non-zero BECS 320 ! in order to remove the long range component from the DFPT potentials. 321 ! 2 --> Similar to 1 but include only the dipole part. Q* are set to zero even if the DDB file contains them. 322 ! 4,5,6,7 --> Use model for the LR part only. 323 ! 4: Use dipole + quadrupole part (if available) 324 ! 5: Use dipole part only. 325 ! 6: Use quadrupole part only. 326 ! 7: Use electric field only. 327 328 integer :: symv1 = 0 329 ! Flag for the symmetrization of v1 potentials. 330 ! 0 --> No symmetrization 331 ! 1 --> Symmetrization in real space 332 ! 2 --> Call v1phq_complete after interpolation of the potentials in ftinterp_qpt 333 334 integer :: rspace_cell = 0 335 ! Flag defining the algorithm for generating the list of R-points and the weigths used to go from W(r,R) to v1scf(r,q) 336 ! 0 --> Use unit supercell for R space. All weights set to 1. 337 ! 1 --> Use Wigner-Seitz super cell and atom dependent weights (same algo as for dynmat) 338 339 type(qcache_t) :: qcache 340 ! Cache used to store potentials if Fourier interpolation is not used 341 ! (see dvdb_readsym_qbz for the implementation) 342 343 type(qcache_t) :: ft_qcache 344 ! Cache used to store potentials if Fourier interpolation is used 345 ! (see dvdb_get_ftqbz for the implementation) 346 347 character(len=fnlen) :: path = ABI_NOFILE 348 ! File name of the DVDB file. 349 350 real(dp) :: dielt(3, 3) = zero 351 ! Dielectric tensor in Cartesian coordinates. 352 ! Used to deal with the long-range component in the Fourier interpolation. 353 354 integer,allocatable :: pos_dpq(:,:,:) 355 ! pos_dpq(3, mpert, nqpt) 356 ! The position of the (idir, ipert, iqpt) potential in the file (in units of POT1 blocks) 357 ! 0 if the corresponding entry is not available. 358 359 integer,allocatable :: cplex_v1(:) 360 ! cplex_v1(numv1) 361 ! The value of cplex for each v1(cplex*nfft, nspden) potential 362 ! 2 if the potential is complex, 1 if real (q==Gamma) 363 364 integer,allocatable :: symq_table(:,:,:,:) 365 ! symq(4,2,nsym,nqpt) 366 ! Table computed by littlegroup_q for all q-points found in the DVDB. 367 ! three first numbers define the G vector; 368 ! fourth number is zero if the q-vector is not preserved, is 1 otherwise 369 ! second index is one without time-reversal symmetry, two with time-reversal symmetry 370 371 integer :: ngfft(18) = -1 372 ! Info on the FFT to be used for the potentials. 373 374 integer,allocatable :: iv_pinfoq(:,:) 375 !iv_pinfoq(4, numv1) 376 ! iv_pinfoq(1, iv1) gives the `idir` index of the iv1 potential 377 ! iv_pinfoq(2, iv1) gives the `ipert` index of the iv1 potential 378 ! iv_pinfoq(3, iv1) gives `pertcase`=idir + (ipert-1)*3 379 ! iv_pinfoq(4, iv1) gives the `iqpt` index of the iv1 potential 380 381 integer,allocatable :: ngfft3_v1(:,:) 382 ! ngfft3_v1(3, numv1) 383 ! The FFT mesh used for each v1 potential (the one used to store data in the file). 384 385 integer,allocatable :: my_irpt2tot(:) 386 ! Mapping my_irpt index to full list of R-points. 387 388 real(dp),allocatable :: qpts(:,:) 389 ! qpts(3,nqpt) 390 ! List of q-points in reduced coordinates. 391 392 real(dp),allocatable :: my_rpt(:,:) 393 ! my_rpt(3, my_nrpt) 394 ! Real space points for Fourier interpolation (MPI distributed if nprocs_rpt > 1) 395 396 real(kind=sp),allocatable :: wsr(:,:,:,:,:) 397 ! DFPT potential in the real space supercell representation. 398 ! wsr(1, my_nrpt, nfft, nspden, my_npert) 399 ! NOTE kind=sp to save memory as much as possible. 400 401 real(dp),allocatable :: my_wratm(:,:) 402 ! my_wratm(my_nrpt, minatom:maxatom) 403 ! Weight for the FT associated to the atom and the R vector. 404 405 real(dp),allocatable :: rhog1_g0(:,:) 406 ! rhog1_g0(2, numv1) 407 ! G=0 component of rhog1. Used to treat the long range component in (polar) semiconductors. 408 ! NB: For the time being, this quantity is not used. Long range term is treated with Verdi's model. 409 410 real(dp),allocatable :: zeff(:,:,:) 411 ! zeff(3, 3, natom) 412 ! Effective charges on each atom, versus electric field and atomic displacement in Cartesian coordinates. 413 ! Used to deal with the long-range componenent in the Fourier interpolation. 414 415 real(dp),allocatable :: zeff_raw(:,:,:) 416 ! Raw Effective charges i.e. values before enforcing the charge-neutrality condition. 417 418 real(dp),allocatable :: qstar(:,:,:,:) 419 ! qstar(3, 3, 3, natom) 420 ! dynamical quadrupole in Cartesian coordinates. 421 ! First two dimension are associated to the q-point, then atomic perturbation in Cart coords. 422 423 real(dp),allocatable :: v1r_efield(:,:,:) 424 ! v1r_efield(nfft, 3, nspden) 425 ! First order potentials due to the three different directions of the electric field perturbation. 426 ! Potentials are in r-space 427 428 type(crystal_t) :: cryst 429 ! Crystalline structure read from the the DVDB file. 430 431 type(hdr_type) :: hdr_ref 432 ! Header associated to the first potential in the DVDB. Used to backspace. 433 ! Gives the number of Fortran records required to backspace the header 434 ! Assume headers with same headform and same basic dimensions e.g. npsp 435 436 type(mpi_type) :: mpi_enreg 437 ! Internal object used to call fourdp 438 439 contains 440 441 procedure :: open_read => dvdb_open_read 442 ! Open the file in read-only mode. 443 444 procedure :: close => dvdb_close 445 ! Close the DVDB file. 446 447 procedure :: free => dvdb_free 448 ! Release the memory allocated and close the file. 449 450 procedure :: print => dvdb_print 451 ! Print info on object. 452 453 procedure :: findq => dvdb_findq 454 ! Returns the index of the q-point. 455 456 procedure :: find_qpts => dvdb_find_qpts 457 ! Returns the index of a list of q-points. 458 459 procedure :: set_pert_distrib => dvdb_set_pert_distrib 460 461 procedure :: read_onev1 => dvdb_read_onev1 462 ! Read and return the DFPT potential for given (idir, ipert, iqpt). 463 464 procedure :: readsym_allv1 => dvdb_readsym_allv1 465 ! Read and return all the 3*natom DFPT potentials (either from file or symmetrized) 466 467 procedure :: readsym_qbz => dvdb_readsym_qbz 468 ! Reconstruct the DFPT potential for a q-point in the BZ starting 469 ! from its symmetrical image in the IBZ. 470 471 procedure :: qcache_read => dvdb_qcache_read 472 ! Allocate internal cache for potentials. 473 ! Read potentials from DVDB file and store them in cache (COLLECTIVE routine) 474 475 procedure :: qcache_update_from_file => dvdb_qcache_update_from_file 476 ! Read selected potentials and update cache (COLLECTIVE routine) 477 478 procedure :: list_perts => dvdb_list_perts 479 ! Check if all the (phonon) perts are available taking into account symmetries. 480 481 procedure :: ftinterp_setup => dvdb_ftinterp_setup 482 ! Prepare the internal tables for Fourier interpolation. 483 484 procedure :: get_maxw => dvdb_get_maxw 485 ! Compute max_r |W(R,r)| 486 487 procedure :: ftinterp_qpt => dvdb_ftinterp_qpt 488 ! Fourier interpolation of potentials for given q-point 489 490 procedure :: get_ftqbz => dvdb_get_ftqbz 491 ! Retrieve Fourier interpolated potential for a given q-point in the BZ. 492 ! Use cache to reduce number of slow FTs. 493 494 procedure :: ftqcache_build => dvdb_ftqcache_build 495 ! This function initializes the internal q-cache from W(R,r) 496 497 procedure :: ftqcache_update_from_ft => dvdb_ftqcache_update_from_ft 498 ! This function initializes the internal q-cache from W(R,r) 499 500 procedure :: get_v1r_long_range => dvdb_get_v1r_long_range 501 ! Long-range part of the phonon potential 502 503 procedure :: load_ddb => dvdb_load_ddb 504 ! Load information about the Born effective charges and dielectric tensor from a DDB file 505 506 procedure :: interpolate_v1scf => dvdb_interpolate_v1scf 507 ! Fourier interpolation of the phonon potentials 508 509 procedure :: get_v1scf_rpt => dvdb_get_v1scf_rpt 510 ! Fourier transform of the phonon potential from qpt to R 511 512 procedure :: get_v1scf_qpt => dvdb_get_v1scf_qpt 513 ! Fourier transform of the phonon potential from R to qpt 514 515 procedure :: load_efield => dvdb_load_efield 516 517 procedure :: interpolate_and_write => dvdb_interpolate_and_write 518 ! Interpolate the phonon potentials and write a new DVDB file. 519 520 procedure :: qdownsample => dvdb_qdownsample 521 ! Downsample the q-mesh. Produce new DVDB file 522 523 procedure :: write_v1qavg => dvdb_write_v1qavg 524 ! Computes the average over the unit cell of the periodic part of the DFPT potentials 525 ! as a function of the q-point and the corresponding quantity obtained with the model for the LR part. 526 527 end type dvdb_t 528 529 public :: dvdb_new ! Create new object. 530 531 ! Utilities 532 public :: dvdb_merge_files ! Merge a list of POT1 files. 533 534 ! debugging tools. 535 public :: dvdb_test_v1rsym ! Check symmetries of the DFPT potentials. 536 public :: dvdb_test_v1complete ! Debugging tool used to test the symmetrization of the DFPT potentials. 537 538 public :: dvdb_test_ftinterp ! Test Fourier interpolation of DFPT potentials. 539 540 !---------------------------------------------------------------------- 541 542 !type, public star_t 543 ! integer :: npts 544 ! real(dp) :: weight 545 ! real(dp) :: ibz_point(3) 546 ! integer,allocatable :: pt2ibz_map(:,:) 547 ! ! (6, npts) 548 ! real(dp), allocatable :: points(:,:) 549 ! ! points(3, npts) 550 !end type kstars_t 551 552 !type, public stars_t 553 ! integer :: nstars 554 ! type(star_t),allocatable :: star(:) 555 ! ! star(nstars) 556 !end type stars_t 557 558 contains
m_dvdb/dvdb_test_ftinterp [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_test_ftinterp
FUNCTION
Debugging tool used to test the Fourier interpolation of the DFPT potentials.
INPUTS
dvdb_filepath=Filename dvdb_ngqpt(3)=Divisions of the Q-mesh reported in the DVDB file (usually equat to ddb_ngqpt) dvdb_add_lr=0 to disable treatment of long-range part in Fourier interpolation. qdamp=Defines exponential damping in LR potential ddb_filepath=Path to DDB file. Used to treat LR part. prtvol=Verbosity level. coarse_ngqpt(3)= Coarse q-mesh used to analyze the accuracy of the FT interpolation Must be divisor of dvdb_ngqpt. Use 0 to disable the test. comm=MPI communicator.
OUTPUT
Only writing.
SOURCE
6040 subroutine dvdb_test_ftinterp(dvdb_filepath, rspace_cell, symv1, dvdb_ngqpt, dvdb_add_lr, dvdb_qdamp, & 6041 ddb_filepath, prtvol, coarse_ngqpt, comm) 6042 6043 !Arguments ------------------------------------ 6044 character(len=*),intent(in) :: dvdb_filepath, ddb_filepath 6045 integer,intent(in) :: comm, prtvol, dvdb_add_lr, rspace_cell, symv1 6046 real(dp),intent(in) :: dvdb_qdamp 6047 integer,intent(in) :: dvdb_ngqpt(3), coarse_ngqpt(3) 6048 6049 !Local variables------------------------------- 6050 !scalars 6051 integer,parameter :: master = 0, chneut2 = 2, qptopt1 = 1 6052 integer :: nfft, iq, cplex, mu, ispden, comm_rpt, iblock_dielt, iblock_dielt_zeff, my_rank, ierr 6053 logical :: autotest 6054 type(dvdb_t) :: dvdb, coarse_dvdb 6055 type(vdiff_t) :: vd_max 6056 type(ddb_type) :: ddb 6057 character(len=fnlen) :: coarse_fname 6058 !arrays 6059 integer :: ngfft(18) 6060 real(dp),allocatable :: file_v1r(:,:,:,:),intp_v1r(:,:,:,:),tmp_v1r(:,:,:,:) 6061 6062 ! ************************************************************************* 6063 6064 my_rank = xmpi_comm_rank(comm) 6065 6066 write(std_out,"(a)")sjoin(" Testing Fourier interpolation of V1(r) with ngqpt:", ltoa(dvdb_ngqpt)) 6067 if (len_trim(ddb_filepath) > 0) then 6068 write(std_out,"(a)")sjoin(" Reading Zeff and eps_inf from DDB file:", ddb_filepath) 6069 write(std_out,"(a)")sjoin(" dvdb_add_lr set to:", itoa(dvdb_add_lr)) 6070 end if 6071 6072 dvdb = dvdb_new(dvdb_filepath, comm) 6073 dvdb%debug = .False. 6074 ABI_CHECK(any(symv1 == [0, 1, 2]), sjoin("invalid value of symv1:", itoa(symv1))) 6075 dvdb%symv1 = symv1 6076 dvdb%add_lr = dvdb_add_lr 6077 dvdb%qdamp = dvdb_qdamp 6078 dvdb%rspace_cell = rspace_cell 6079 6080 !call dvdb%set_pert_distrib(sigma%comm_pert, sigma%my_pinfo, sigma%pert_table) 6081 6082 iblock_dielt = 0; iblock_dielt_zeff = 0 6083 if (len_trim(ddb_filepath) > 0) then 6084 call dvdb%load_ddb(prtvol, chneut2, comm, ddb_filepath=ddb_filepath) 6085 else 6086 dvdb%add_lr = 0 6087 ABI_WARNING("ddb_filepath was not provided --> Setting dvdb_add_lr to zero") 6088 end if 6089 6090 call dvdb%print() 6091 6092 ! Define FFT mesh for real space representation. 6093 call ngfft_seq(ngfft, dvdb%ngfft3_v1(:,1)) 6094 nfft = product(ngfft(1:3)) 6095 call dvdb%open_read(ngfft, comm) 6096 6097 ABI_MALLOC(intp_v1r, (2, nfft, dvdb%nspden, dvdb%natom3)) 6098 ABI_MALLOC(file_v1r, (2, nfft, dvdb%nspden, dvdb%natom3)) 6099 6100 ! Prepare FT interpolation. 6101 comm_rpt = xmpi_comm_self 6102 6103 autotest = .True. 6104 if (autotest) then 6105 call dvdb%ftinterp_setup(dvdb_ngqpt, qptopt1, 1, [zero, zero, zero], nfft, ngfft, comm_rpt) 6106 6107 ! First step: Use FT interpolation to get q-points in the initial ab-initio mesh. 6108 ! We should get the same result... 6109 do iq=1,dvdb%nqpt 6110 ! Read data from DVDB file and store it in file_v1r 6111 call dvdb%readsym_allv1(dvdb%findq(dvdb%qpts(:,iq)), cplex, nfft, ngfft, tmp_v1r, comm) 6112 6113 if (cplex == 1) then 6114 file_v1r(1,:,:,:) = tmp_v1r(1,:,:,:) 6115 file_v1r(2,:,:,:) = zero 6116 else 6117 file_v1r = tmp_v1r 6118 end if 6119 ABI_FREE(tmp_v1r) 6120 6121 ! Interpolate data at the same q-point. 6122 call dvdb%ftinterp_qpt(dvdb%qpts(:,iq), nfft, ngfft, intp_v1r, dvdb%comm_rpt) 6123 6124 write(std_out,"(a)")sjoin("=== For q-point:", ktoa(dvdb%qpts(:,iq)), "===") 6125 do mu=1,dvdb%natom3 6126 do ispden=1,dvdb%nspden 6127 write(std_out, "(a)")"--- !DVDB_SELF_DIFF" 6128 write(std_out,"(3a)")" qpoint: ", trim(ktoa(dvdb%qpts(:,iq))), "," 6129 write(std_out,"(a,i0,a)")" iqpt: ", iq, "," 6130 write(std_out,"(a,i0,a)")" iatom3: ", mu, "," 6131 write(std_out,"(a,i0,a)")" ispden: ", ispden, "," 6132 call vdiff_print(vdiff_eval(2, nfft, file_v1r(:,:,ispden,mu), intp_v1r(:,:,ispden,mu), & 6133 dvdb%cryst%ucvol, vd_max=vd_max)) 6134 write(std_out,"(a)")"..." 6135 !do ifft=1,nfft 6136 ! write(std_out,*)file_v1r(1,ifft,ispden,mu),intp_v1r(1,ifft,ispden,mu),& 6137 ! file_v1r(2,ifft,ispden,mu),intp_v1r(2,ifft,ispden,mu) 6138 !end do 6139 end do 6140 end do 6141 write(std_out,*)" " 6142 end do ! iq 6143 6144 write(std_out, "(/, a)")" Max values over q-points and perturbations" 6145 call vdiff_print(vd_max) 6146 ABI_FREE(dvdb%wsr) 6147 end if 6148 6149 ! Now downsample the q-mesh, build real-space representation with coarse q-mesh and 6150 ! compare with ab-intio values in the initial dvdb. 6151 if (all(coarse_ngqpt /= 0)) then 6152 write(std_out, "(/, 2a)")" Downsampling Q-mesh using coarse_ngqpt:", trim(ltoa(coarse_ngqpt)) 6153 6154 !Flang compiler complains with empty constructors (this bug should be corrected in future versions) 6155 #if defined FC_LLVM || defined FC_ARM || defined FC_NVHPC 6156 vd_max = vdiff_t(zero,zero,zero,zero,zero,zero) 6157 #else 6158 vd_max = vdiff_t() 6159 #endif 6160 6161 coarse_fname = strcat(dvdb_filepath, "_COARSE") 6162 call dvdb%qdownsample(coarse_fname, qptopt1, coarse_ngqpt, comm) 6163 6164 coarse_dvdb = dvdb_new(coarse_fname, comm) 6165 call coarse_dvdb%open_read(ngfft, comm) 6166 !call coarse_dvdb%set_pert_distrib(sigma%comm_pert, sigma%my_pinfo, sigma%pert_table) 6167 6168 coarse_dvdb%debug = dvdb%debug 6169 coarse_dvdb%symv1 = dvdb%symv1 6170 coarse_dvdb%add_lr = dvdb%add_lr 6171 coarse_dvdb%has_dielt = dvdb%has_dielt 6172 coarse_dvdb%has_zeff = dvdb%has_zeff 6173 coarse_dvdb%has_quadrupoles = dvdb%has_quadrupoles 6174 coarse_dvdb%has_efield = dvdb%has_efield 6175 coarse_dvdb%dielt = dvdb%dielt 6176 coarse_dvdb%zeff = dvdb%zeff 6177 coarse_dvdb%zeff_raw = dvdb%zeff_raw 6178 coarse_dvdb%qstar = dvdb%qstar 6179 coarse_dvdb%qdamp = dvdb%qdamp 6180 !call coarse_dvdb%print() 6181 6182 ! Prepare FT interpolation using coarse q-mesh. 6183 call coarse_dvdb%ftinterp_setup(coarse_ngqpt, qptopt1, 1, [zero, zero, zero], nfft, ngfft, comm_rpt) 6184 6185 do iq=1,dvdb%nqpt 6186 ! Read data from DVDB file and store it in file_v1r 6187 call dvdb%readsym_allv1(dvdb%findq(dvdb%qpts(:,iq)), cplex, nfft, ngfft, tmp_v1r, comm) 6188 6189 if (cplex == 1) then 6190 file_v1r(1,:,:,:) = tmp_v1r(1,:,:,:) 6191 file_v1r(2,:,:,:) = zero 6192 else 6193 file_v1r = tmp_v1r 6194 end if 6195 ABI_FREE(tmp_v1r) 6196 6197 ! Interpolate data at the same q-point using the coarse Q-mesh 6198 call coarse_dvdb%ftinterp_qpt(dvdb%qpts(:,iq), nfft, ngfft, intp_v1r, dvdb%comm_rpt) 6199 6200 write(std_out,"(a)")sjoin("=== For COARSE q-point:", ktoa(dvdb%qpts(:,iq)), "===") 6201 do mu=1,dvdb%natom3 6202 do ispden=1,dvdb%nspden 6203 write(std_out, "(a)")"--- !DVDB_COARSE_DIFF" 6204 write(std_out,"(3a)")" qpoint: ", trim(ktoa(dvdb%qpts(:,iq))), "," 6205 write(std_out,"(a,i0,a)")" iqpt: ", iq, "," 6206 write(std_out,"(a,i0,a)")" iatom3: ", mu, "," 6207 write(std_out,"(a,i0,a)")" ispden: ", ispden, "," 6208 call vdiff_print(vdiff_eval(2, nfft, file_v1r(:,:,ispden,mu), intp_v1r(:,:,ispden,mu), & 6209 dvdb%cryst%ucvol, vd_max=vd_max)) 6210 write(std_out,"(a)")"..." 6211 !do ifft=1,nfft 6212 ! write(std_out,*)file_v1r(1,ifft,ispden,mu),intp_v1r(1,ifft,ispden,mu),& 6213 ! file_v1r(2,ifft,ispden,mu),intp_v1r(2,ifft,ispden,mu) 6214 !end do 6215 end do 6216 end do 6217 write(std_out,*)" " 6218 end do ! iq 6219 6220 write(std_out, "(/, a)")" COARSE DVDB: Max values over q-points and perturbations" 6221 call vdiff_print(vd_max) 6222 call coarse_dvdb%free() 6223 if (my_rank == master) call delete_file(coarse_fname, ierr) 6224 end if 6225 6226 ABI_FREE(intp_v1r) 6227 ABI_FREE(file_v1r) 6228 6229 call dvdb%free() 6230 call ddb%free() 6231 6232 end subroutine dvdb_test_ftinterp
m_dvdb/dvdb_test_v1complete [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_test_v1complete
FUNCTION
Debugging tool used to test the symmetrization of the DFPT potentials. Assumes DVDB file containing all 3*natom perturbations (generated with nsym == 1 or other specialized variables e.g. prepgkk)
INPUTS
db_path=Filename of the DVDB file. symv1scf=1 to activate symmetrization of DFPT potentials. 0 ti disable it. dump_path=File used to dump potentials (empty string to disable output) comm=MPI communicator.
OUTPUT
Only writing.
SOURCE
5445 subroutine dvdb_test_v1complete(dvdb_filepath, symv1scf, dump_path, comm) 5446 5447 !Arguments ------------------------------------ 5448 character(len=*),intent(in) :: dvdb_filepath,dump_path 5449 integer,intent(in) :: symv1scf, comm 5450 5451 !Local variables------------------------------- 5452 !scalars 5453 integer,parameter :: master = 0 5454 integer :: iqpt,pcase,idir,ipert,cplex,nfft,ispden,timerev_q,ifft,unt,my_rank, ncid 5455 integer :: i1,i2,i3,n1,n2,n3,id1,id2,id3,cnt, npert_miss 5456 integer :: ncerr 5457 character(len=500) :: msg 5458 type(crystal_t),pointer :: cryst 5459 type(dvdb_t),target :: dvdb 5460 !arrays 5461 integer :: ngfft(18), rfdir(3) 5462 integer,allocatable :: pflag(:,:) 5463 real(dp) :: qpt(3) 5464 integer,allocatable :: pertsy(:,:),rfpert(:),symq(:,:,:) 5465 real(dp),allocatable :: file_v1scf(:,:,:,:),symm_v1scf(:,:,:,:), work2(:,:,:,:) 5466 5467 ! ************************************************************************* 5468 5469 my_rank = xmpi_comm_rank(comm) 5470 5471 dvdb = dvdb_new(dvdb_filepath, comm) 5472 dvdb%debug = .false. 5473 dvdb%symv1 = symv1scf 5474 call dvdb%print() 5475 call dvdb%list_perts([-1,-1,-1], npert_miss) 5476 5477 call ngfft_seq(ngfft, dvdb%ngfft3_v1(:,1)) 5478 nfft = product(ngfft(1:3)) 5479 call dvdb%open_read(ngfft, comm) 5480 5481 cryst => dvdb%cryst 5482 call ngfft_seq(ngfft, dvdb%ngfft3_v1(:,1)) 5483 nfft = product(ngfft(:3)) 5484 5485 n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3) 5486 id1 = n1/2+2; id2 = n2/2+2; id3 = n3/2+2 5487 5488 ABI_MALLOC(pflag, (3, dvdb%natom)) 5489 5490 ! Initialize the list of perturbations rfpert and rdfir 5491 ! WARNING: Only phonon perturbations are considered for the time being. 5492 ABI_MALLOC(rfpert,(dvdb%mpert)) 5493 rfpert = 0; rfpert(1:cryst%natom) = 1; rfdir = 1 5494 ABI_MALLOC(symq, (4,2,cryst%nsym)) 5495 ABI_MALLOC(pertsy, (3,dvdb%mpert)) 5496 5497 unt = -1; ncid = nctk_noid 5498 if (len_trim(dump_path) /= 0 .and. my_rank == master) then 5499 write(std_out,"(a)")sjoin("Will write potentials to:", dump_path) 5500 if (endswith(dump_path, ".nc")) then 5501 NCF_CHECK(nctk_open_create(ncid, dump_path, xmpi_comm_self)) 5502 NCF_CHECK(dvdb%cryst%ncwrite(ncid)) 5503 ncerr = nctk_def_dims(ncid, [& 5504 nctkdim_t("two", 2), nctkdim_t("three", 3), nctkdim_t("nfft", nfft), nctkdim_t("nspden", dvdb%nspden), & 5505 nctkdim_t("natom3", cryst%natom * 3), nctkdim_t("mpert", dvdb%mpert), nctkdim_t("nqpt", dvdb%nqpt)], & 5506 defmode=.True.) 5507 NCF_CHECK(ncerr) 5508 NCF_CHECK(nctk_def_iscalars(ncid, [character(len=nctk_slen) :: "symv1scf"])) 5509 NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("qpts", "dp", "three, nqpt"))) 5510 NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("origin_v1scf", "dp", "two, nfft, nspden, natom3, nqpt"))) 5511 NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("recons_v1scf", "dp", "two, nfft, nspden, natom3, nqpt"))) 5512 NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("pertsy_qpt", "int", "three, mpert, nqpt"))) 5513 NCF_CHECK(nctk_def_arrays(ncid, nctkarr_t("ngfft", "int", "three"))) 5514 NCF_CHECK(nctk_set_datamode(ncid)) 5515 ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: & 5516 "symv1scf"], [symv1scf]) 5517 NCF_CHECK(ncerr) 5518 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qpts"), dvdb%qpts)) 5519 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ngfft"), ngfft(1:3))) 5520 else 5521 if (open_file(dump_path, msg, newunit=unt, action="write", status="unknown", form="formatted") /= 0) then 5522 ABI_ERROR(msg) 5523 end if 5524 end if 5525 end if 5526 5527 ABI_CALLOC(work2, (2, nfft, dvdb%nspden, dvdb%natom3)) 5528 5529 do iqpt=1,dvdb%nqpt 5530 qpt = dvdb%qpts(:,iqpt) 5531 ! Examine the symmetries of the q wavevector 5532 call littlegroup_q(cryst%nsym,qpt,symq,cryst%symrec,cryst%symafm,timerev_q,prtvol=dvdb%prtvol) 5533 5534 ! Determine the symmetrical perturbations. Meaning of pertsy: 5535 ! 0 for non-target perturbations 5536 ! 1 for basis perturbations 5537 ! -1 for perturbations that can be found from basis perturbations 5538 call irreducible_set_pert(cryst%indsym,dvdb%mpert,cryst%natom,cryst%nsym,& 5539 pertsy,rfdir,rfpert,symq,cryst%symrec,cryst%symrel) 5540 5541 ! Read all potentials (here I assume that all perturbations are available) 5542 call dvdb%readsym_allv1(iqpt, cplex, nfft, ngfft, file_v1scf, dvdb%comm) 5543 5544 ! Copy basis perturbations in symm_v1scf and set pflag 5545 ABI_MALLOC(symm_v1scf, (cplex, nfft, dvdb%nspden, dvdb%natom3)) 5546 symm_v1scf = huge(one); pflag = 0 5547 do pcase=1,3*dvdb%cryst%natom 5548 idir = mod(pcase-1, 3) + 1; ipert = (pcase - idir) / 3 + 1 5549 if (pertsy(idir, ipert) == 1) then 5550 symm_v1scf(:,:,:,pcase) = file_v1scf(:,:,:,pcase) 5551 pflag(idir,ipert) = 1 5552 end if 5553 end do 5554 5555 ! Complete potentials 5556 call v1phq_complete(cryst,qpt,ngfft,cplex,nfft,dvdb%nspden,dvdb%nsppol,dvdb%mpi_enreg,dvdb%symv1,pflag,symm_v1scf) 5557 5558 if (ncid /= nctk_noid) then 5559 work2 = zero 5560 if (cplex == 1) work2(1,:,:,:) = file_v1scf(1,:,:,:) 5561 if (cplex == 2) work2 = file_v1scf 5562 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "origin_v1scf"), work2, start=[1,1,1,1,iqpt]) 5563 NCF_CHECK(ncerr) 5564 if (cplex == 1) work2(1,:,:,:) = symm_v1scf(1,:,:,:) 5565 if (cplex == 2) work2 = symm_v1scf 5566 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "recons_v1scf"), work2, start=[1,1,1,1,iqpt]) 5567 NCF_CHECK(ncerr) 5568 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "pertsy_qpt"), pertsy, start=[1,1,iqpt])) 5569 end if 5570 5571 ! Compare values. 5572 do pcase=1,3*cryst%natom 5573 idir = mod(pcase-1, 3) + 1; ipert = (pcase - idir) / 3 + 1 5574 if (pflag(idir,ipert) /= 2) cycle 5575 cnt = cnt+1 5576 5577 do ispden=1,dvdb%nspden 5578 !write(std_out,"(5(a,i0),3a,es12.4)")"For cnt: ",cnt ,", iqpt: ", iqpt, ", idir: ", idir, & 5579 ! ", ipert: ", ipert, ", ispden: ", ispden, ", qpt: ", trim(ktoa(qpt)) ,", max_err: ", & 5580 ! maxval(abs(file_v1scf(:,:,ispden,pcase) - symm_v1scf(:,:,ispden,pcase))) 5581 !write(std_out,"(a,es10.3)")" max(abs(f1-f2))", maxval(abs(file_v1scf(:,:,ispden,pcase) - symm_v1scf(:,:,ispden,pcase))) 5582 call vdiff_print(vdiff_eval(cplex,nfft,file_v1scf(:,:,ispden,pcase),symm_v1scf(:,:,ispden,pcase),cryst%ucvol)) 5583 5584 ! Debug: write potentials to file. 5585 if (unt /= -1) then 5586 write(unt,*)"# count:", cnt 5587 write(unt,*)"# q-point:", trim(ktoa(qpt)), ", iqpt: ", trim(itoa(iqpt)) 5588 write(unt,*)"# idir: ",idir,", ipert: ",ipert,", ispden:", ispden 5589 write(unt,*)"# file_v1scf, symmetrized_v1scf, diff" 5590 if (cplex == 1) then 5591 do i3=1,n3 5592 do i2=1,n2 5593 do i1=1,n1 5594 ifft = i1+n1*((i2-1)+n2*(i3-1)) 5595 write(unt,"(3i3,3(es12.4,2x))") & 5596 i1,i2,i3, & 5597 file_v1scf(1,ifft,ispden,pcase), symm_v1scf(1,ifft,ispden,pcase), & 5598 file_v1scf(1,ifft,ispden,pcase) - symm_v1scf(1,ifft,ispden,pcase) 5599 end do 5600 end do 5601 end do 5602 else 5603 do i3=1,n3 5604 do i2=1,n2 5605 do i1=1,n1 5606 ifft = i1+n1*((i2-1)+n2*(i3-1)) 5607 write(unt, "(3i3,6(es12.4,2x))") & 5608 i1,i2,i3, & 5609 file_v1scf(1,ifft,ispden,pcase), symm_v1scf(1,ifft,ispden,pcase), & 5610 file_v1scf(1,ifft,ispden,pcase) - symm_v1scf(1,ifft,ispden,pcase), & 5611 file_v1scf(2,ifft,ispden,pcase), symm_v1scf(2,ifft,ispden,pcase), & 5612 file_v1scf(2,ifft,ispden,pcase) - symm_v1scf(2,ifft,ispden,pcase) 5613 end do 5614 end do 5615 end do 5616 end if 5617 write(unt,*) 5618 write(unt,*) 5619 end if 5620 5621 end do 5622 !write(std_out,*)"" 5623 end do 5624 5625 ABI_FREE(symm_v1scf) 5626 ABI_FREE(file_v1scf) 5627 end do 5628 5629 ABI_FREE(work2) 5630 ABI_FREE(pflag) 5631 ABI_FREE(rfpert) 5632 ABI_FREE(symq) 5633 ABI_FREE(pertsy) 5634 5635 call dvdb%free() 5636 5637 if (unt /= -1) close(unt) 5638 if (ncid /= nctk_noid) then 5639 NCF_CHECK(nf90_close(ncid)) 5640 end if 5641 5642 end subroutine dvdb_test_v1complete
m_dvdb/dvdb_test_v1rsym [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_test_v1rsym
FUNCTION
Debugging tool used to check whether the DFPT potentials in real space fulfill the correct symmetries on the real space FFT mesh.
INPUTS
db_path=Filename symv1scf=1 to activate symmetrization of DFPT potentials. 0 to disable it. comm=MPI communicator.
OUTPUT
Only writing.
SOURCE
5310 subroutine dvdb_test_v1rsym(db_path, symv1scf, comm) 5311 5312 !Arguments ------------------------------------ 5313 character(len=*),intent(in) :: db_path 5314 integer,intent(in) :: symv1scf, comm 5315 5316 !Local variables------------------------------- 5317 !scalars 5318 integer,parameter :: rfmeth2=2,syuse0=0 5319 integer :: iqpt,idir,ipert,nsym1,cplex,v1pos 5320 integer :: isym,nfft,ifft,ifft_rot,ispden 5321 real(dp) :: max_err,re,im,vre,vim !,pre,pim 5322 character(len=500) :: msg 5323 logical :: isok 5324 type(dvdb_t),target :: db 5325 type(crystal_t),pointer :: cryst 5326 !arrays 5327 integer :: ngfft(18) 5328 integer,allocatable :: symafm1(:),symrel1(:,:,:),irottb(:,:) 5329 real(dp) :: qpt(3) 5330 real(dp),allocatable :: tnons1(:,:),v1scf(:,:) 5331 5332 ! ************************************************************************* 5333 5334 db = dvdb_new(db_path, comm) 5335 db%debug = .True. 5336 db%symv1 = symv1scf 5337 call db%print() 5338 !call db%list_perts([-1,-1,-1], npert_miss) 5339 5340 call ngfft_seq(ngfft, db%ngfft3_v1(:,1)) 5341 nfft = product(ngfft(1:3)) 5342 call db%open_read(ngfft, comm) 5343 5344 ABI_CHECK(db%nspinor==1, "nspinor == 2 not coded") 5345 5346 cryst => db%cryst 5347 ABI_MALLOC(symafm1, (cryst%nsym)) 5348 ABI_MALLOC(symrel1, (3,3,cryst%nsym)) 5349 ABI_MALLOC(tnons1, (3,cryst%nsym)) 5350 5351 do iqpt=1,db%nqpt 5352 qpt = db%qpts(:, iqpt) 5353 do ipert=1,db%natom 5354 do idir=1,3 5355 v1pos = db%pos_dpq(idir, ipert, iqpt); if (v1pos == 0) cycle 5356 5357 ! Determines the set of symmetries that leaves the perturbation invariant. 5358 call littlegroup_pert(cryst%gprimd,idir,cryst%indsym,dev_null,ipert,cryst%natom,cryst%nsym,nsym1,rfmeth2,& 5359 cryst%symafm,symafm1,db%symq_table(:,:,:,iqpt),cryst%symrec,cryst%symrel,symrel1,syuse0,cryst%tnons,& 5360 tnons1,unit=dev_null) 5361 5362 cplex = db%cplex_v1(v1pos) 5363 ngfft(1:3) = db%ngfft3_v1(:, v1pos) 5364 nfft = product(ngfft(:3)) 5365 ABI_MALLOC(v1scf, (cplex*nfft, db%nspden)) 5366 5367 if (db%read_onev1(idir, ipert, iqpt, cplex, nfft, ngfft, v1scf, msg) /= 0) then 5368 ABI_ERROR(msg) 5369 end if 5370 5371 ABI_MALLOC(irottb, (nfft,nsym1)) 5372 call rotate_fft_mesh(nsym1,symrel1,tnons1,ngfft,irottb,isok) 5373 if (.not. isok) then 5374 ABI_WARNING("Real space FFT mesh is not compatible with symmetries!") 5375 end if 5376 5377 max_err = zero 5378 do isym=1,nsym1 5379 do ispden=1,db%nspden 5380 do ifft=1,nfft 5381 ifft_rot = irottb(ifft, isym) 5382 !pre = cos(two_pi * dot_product(qpt, tnons1(:,isym))) 5383 !pim = -sin(two_pi * dot_product(qpt, tnons1(:,isym))) 5384 if (cplex == 2) then 5385 re = v1scf(2*ifft_rot-1, ispden) 5386 im = v1scf(2*ifft_rot , ispden) 5387 !vre = re * pre - im * pim 5388 !vim = re * pim + im * pre 5389 vre = re; vim = im 5390 5391 re = v1scf(2*ifft-1, ispden) - vre 5392 im = v1scf(2*ifft , ispden) - vim 5393 else 5394 re = v1scf(ifft, ispden) - v1scf(ifft_rot, ispden) 5395 im = zero 5396 end if 5397 !if (sqrt(re**2 + im**2) > tol6) write(std_out,*)"ifft,isym,err: ",ifft,isym,sqrt(re**2 + im**2) 5398 max_err = max(max_err, sqrt(re**2 + im**2)) 5399 end do 5400 end do 5401 end do 5402 if (nsym1>1) then 5403 write(std_out,"(3(a,i2),a,i2,a,es16.8)")"For iqpt= ",iqpt,& 5404 ", idir= ",idir,", ipert= ",ipert,", nsym= ",nsym1,", max_err= ",max_err 5405 end if 5406 5407 ABI_FREE(irottb) 5408 ABI_FREE(v1scf) 5409 end do 5410 end do 5411 5412 end do ! iqpt 5413 5414 ABI_FREE(symafm1) 5415 ABI_FREE(symrel1) 5416 ABI_FREE(tnons1) 5417 5418 call db%free() 5419 5420 end subroutine dvdb_test_v1rsym
m_dvdb/dvdb_write_v1qavg [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
dvdb_write_v1qavg
FUNCTION
Computes the average over the unit cell of the periodic part of the DFPT potentials as a function of the q-point and the corresponding quantity obtained with the model for the LR part. Results are stored in the V1QAVG netcdf file. Two options are available: eph_task = -15 --> Use list of q-points found in the DVDB file. Mainly used to plot the average along a q-path. The procedure required to generate a DVDB with a q-path is rather lengthy as it requires several phonon calculations with WKQ followed by a merge of the POT files. eph_task = +15 --> Assume DVDB file with q-mesh (dvdb_ngqpt), use Fourier interpolation to interpolate potentials along the path specified by ph_qpath and ph_nqpath.
INPUTS
dtset<dataset_type>= Input variables. out_ncpath=Filename for output netcdf file.
OUTPUT
Only writing.
SOURCE
5672 subroutine dvdb_write_v1qavg(dvdb, dtset, out_ncpath) 5673 5674 !Arguments ------------------------------------ 5675 class(dvdb_t),target,intent(inout) :: dvdb 5676 type(dataset_type),target,intent(in) :: dtset 5677 character(len=*),intent(in) :: out_ncpath 5678 5679 !Local variables------------------------------- 5680 !scalars 5681 integer,parameter :: master = 0 5682 integer :: nfft, iq, cplex, ispden, comm_rpt, my_rank, idir, ipert, ipc, imyp 5683 integer :: n1, n2, n3, unt, this_nqpt, interpolated 5684 integer :: i1, i2, i3, ifft, ig, ngsmall, ii, qptopt 5685 integer :: ncid, ncerr 5686 real(dp) :: gsq_max, g2 5687 !type(vdiff_t) :: vd_max 5688 logical :: write_v1r 5689 character(len=500) :: msg 5690 character(len=fnlen) :: dump_path 5691 !arrays 5692 integer :: ngfft(18), units(2) 5693 integer, allocatable :: gfft(:,:),ig2ifft(:), gsmall(:,:) 5694 real(dp) :: dvdb_qdamp(1) 5695 real(dp) :: vals2(2) 5696 real(dp),pointer :: this_qpts(:,:) 5697 real(dp),allocatable :: file_v1r(:,:,:,:),long_v1r(:,:,:,:),tmp_v1r(:,:,:,:) 5698 real(dp),allocatable :: maxw(:,:), all_rpt(:,:), all_rmod(:), workg(:,:), work_gsmall(:,:) 5699 5700 ! ************************************************************************* 5701 5702 my_rank = xmpi_comm_rank(dvdb%comm) 5703 units = [std_out, ab_out] 5704 5705 call wrtout(units, " Computing average over the unit cell of the periodic part of the DFPT potentials", newlines=2) 5706 call dvdb%print(unit=std_out) 5707 !call dvdb%print(unit=ab_out) 5708 5709 ! Define FFT mesh 5710 ngfft = dvdb%ngfft 5711 nfft = product(ngfft(1:3)) 5712 n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3) 5713 5714 ! Get list of G-vectors in FFT mesh. 5715 ABI_MALLOC(gfft, (3, nfft)) 5716 call get_gftt(ngfft, [zero, zero, zero], dvdb%cryst%gmet, gsq_max, gfft) 5717 ABI_MALLOC(workg, (2, nfft)) 5718 5719 ! Select G-vectors in small sphere (ratio of gsq_max) 5720 do ii=1,2 5721 if (ii == 2) then 5722 ABI_MALLOC(ig2ifft, (ngsmall)) 5723 end if 5724 ngsmall = 0 5725 do ig=1,nfft 5726 ! Don't include (2pi)**2 to be consistent with get_gftt 5727 g2 = dot_product(gfft(:,ig), matmul(dvdb%cryst%gmet, gfft(:, ig))) 5728 if (g2 <= gsq_max * 0.01_dp) ngsmall = ngsmall + 1 5729 if (ii == 2) ig2ifft(ngsmall) = ig 5730 end do 5731 end do 5732 write(std_out, *)"Found ngsmall", ngsmall 5733 5734 !call ig2fft_sphere(dvdb%cryst%gmet, gfft, ig2ifft) 5735 ABI_MALLOC(gsmall, (3, ngsmall)) 5736 do ig=1,ngsmall 5737 gsmall(:, ig) = gfft(:, ig2ifft(ig)) 5738 end do 5739 ABI_MALLOC(work_gsmall, (2, ngsmall)) 5740 5741 ABI_MALLOC(long_v1r, (2, nfft, dvdb%nspden, dvdb%my_npert)) 5742 ABI_MALLOC(file_v1r, (2, nfft, dvdb%nspden, dvdb%my_npert)) 5743 5744 unt = -1; dump_path = "" 5745 !dump_path = "V1QAVG.dat" 5746 if (len_trim(dump_path) /= 0 .and. my_rank == master) then 5747 if (open_file(dump_path, msg, newunit=unt, action="write", status="unknown", form="formatted") /= 0) then 5748 ABI_ERROR(msg) 5749 end if 5750 write(std_out,"(a)")sjoin(" Will write potentials in text format to:", dump_path) 5751 end if 5752 5753 ! Select list of q-points depending on eph_task (either from DVDB file or interpolated) 5754 write_v1r = .False. 5755 if (dtset%eph_task == -15) then 5756 call wrtout(units, " Using list of q-points found in the DVDB file") 5757 this_nqpt = dvdb%nqpt 5758 this_qpts => dvdb%qpts 5759 interpolated = 0 5760 5761 else if (dtset%eph_task == +15) then 5762 msg = sjoin(" Using list of q-points specified by ph_qpath with ", itoa(dtset%ph_nqpath), "qpoints") 5763 call wrtout(units, msg) 5764 ABI_CHECK(dtset%ph_nqpath > 0, "When eph_task = +15, ph_qpath must be given in input.") 5765 this_nqpt = dtset%ph_nqpath 5766 this_qpts => dtset%ph_qpath(:, 1:this_nqpt) 5767 comm_rpt = xmpi_comm_self 5768 qptopt = dtset%kptopt; if (dtset%qptopt /= 0) qptopt = dtset%qptopt 5769 call dvdb%ftinterp_setup(dtset%ddb_ngqpt, qptopt, 1, dtset%ddb_shiftq, nfft, ngfft, comm_rpt) 5770 interpolated = 1 5771 write_v1r = dtset%prtpot > 0 5772 else 5773 ABI_ERROR(sjoin("Invalid value for eph_task:", itoa(dtset%eph_task))) 5774 end if 5775 5776 call wrtout(units, sjoin(ch10, "- Results stored in: ", out_ncpath)) 5777 call wrtout(units, " Use `abiopen.py out_V1QAVG.nc -e` to visualize results") 5778 5779 if (my_rank == master) then 5780 NCF_CHECK(nctk_open_create(ncid, out_ncpath, xmpi_comm_self)) 5781 NCF_CHECK(dvdb%cryst%ncwrite(ncid)) 5782 ncerr = nctk_def_dims(ncid, [ & 5783 nctkdim_t("nspden", dvdb%nspden), nctkdim_t("natom", dvdb%natom3 / 3), nctkdim_t("nqpt", this_nqpt), & 5784 nctkdim_t("natom3", dvdb%natom3), nctkdim_t("ngsmall", ngsmall)], defmode=.True.) 5785 NCF_CHECK(ncerr) 5786 5787 if (interpolated == 1) then 5788 ! Define arrays for Max_r |W(R, r)| 5789 NCF_CHECK(nctk_def_dims(ncid, [nctkdim_t("nrpt", dvdb%nrtot), nctkdim_t("nfft", nfft)])) 5790 ncerr = nctk_def_arrays(ncid, [ & 5791 nctkarr_t("ngqpt", "int", "three"), nctkarr_t("rpt", "dp", "three, nrpt"), nctkarr_t("rmod", "dp", "nrpt"), & 5792 nctkarr_t("ngfft", "int", "three"), & 5793 nctkarr_t("maxw", "dp", "nrpt, natom3") & 5794 ]) 5795 NCF_CHECK(ncerr) 5796 end if 5797 5798 ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: & 5799 "symdynmat", "symv1scf", "dvdb_add_lr", "interpolated"]) 5800 NCF_CHECK(ncerr) 5801 ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: & 5802 "has_dielt", "has_zeff", "has_quadrupoles", "has_efield", "dvdb_add_lr"]) 5803 NCF_CHECK(ncerr) 5804 NCF_CHECK(nctk_def_dpscalars(ncid, [character(len=nctk_slen) :: "qdamp"])) 5805 ncerr = nctk_def_arrays(ncid, [ & 5806 nctkarr_t("v1scf_avg", "dp", "two, nspden, three, natom, nqpt"), & 5807 nctkarr_t("v1lr_avg", "dp", "two, nspden, three, natom, nqpt"), & 5808 nctkarr_t("v1scfmlr_avg", "dp", "two, nspden, three, natom, nqpt"), & 5809 nctkarr_t("v1scfmlr_abs_avg", "dp", "two, nspden, three, natom, nqpt"), & 5810 nctkarr_t("v1scf_abs_avg", "dp", "two, nspden, three, natom, nqpt"), & 5811 nctkarr_t("v1lr_abs_avg", "dp", "two, nspden, three, natom, nqpt"), & 5812 nctkarr_t("gsmall", "int", "three, ngsmall"), & 5813 nctkarr_t("v1scf_gsmall", "dp", "two, ngsmall, nspden, three, natom, nqpt"), & 5814 nctkarr_t("v1lr_gsmall", "dp", "two, ngsmall, nspden, three, natom, nqpt"), & 5815 nctkarr_t("qpoints", "dp", "three, nqpt") & 5816 ]) 5817 NCF_CHECK(ncerr) 5818 5819 if (write_v1r) then 5820 ncerr = nctk_def_arrays(ncid, [ & 5821 nctkarr_t("v1r_interpolated", "dp", "two, nfft, nspden, natom3"), & 5822 nctkarr_t("v1r_lrmodel", "dp", "two, nfft, nspden, natom3") & 5823 ]) 5824 NCF_CHECK(ncerr) 5825 end if 5826 5827 NCF_CHECK(nctk_set_datamode(ncid)) 5828 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "qpoints"), this_qpts)) 5829 ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: & 5830 "symdynmat", "symv1scf", "dvdb_add_lr", "interpolated"], & 5831 [dtset%symdynmat, dvdb%symv1, dtset%dvdb_add_lr, interpolated]) 5832 NCF_CHECK(ncerr) 5833 ncerr = nctk_write_iscalars(ncid, [character(len=nctk_slen) :: & 5834 "has_dielt", "has_zeff", "has_quadrupoles", "has_efield"], & 5835 l2int([dvdb%has_dielt, dvdb%has_zeff, dvdb%has_quadrupoles, dvdb%has_efield])) 5836 NCF_CHECK(ncerr) 5837 dvdb_qdamp = dvdb%qdamp 5838 NCF_CHECK(nctk_write_dpscalars(ncid, [character(len=nctk_slen) :: "qdamp"], dvdb_qdamp)) 5839 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "gsmall"), gsmall)) 5840 end if 5841 5842 do iq=1,this_nqpt 5843 5844 if (interpolated == 0) then 5845 call wrtout(std_out, sjoin(" Treating qpt:", ktoa(this_qpts(:,iq)))) 5846 5847 ! Read data from DVDB file, reconstruct all 3*natom perturbations in tmp_v1r. 5848 call dvdb%readsym_allv1(dvdb%findq(this_qpts(:, iq)), cplex, nfft, ngfft, tmp_v1r, xmpi_comm_self) 5849 5850 ! Transfer data to file_v1r taking into account my_npert 5851 do imyp=1,dvdb%my_npert 5852 ipc = dvdb%my_pinfo(3, imyp) 5853 if (cplex == 1) then 5854 file_v1r(1,:,:,imyp) = tmp_v1r(1,:,:,ipc) 5855 file_v1r(2,:,:,imyp) = zero 5856 else 5857 file_v1r(:,:,:,imyp) = tmp_v1r(:,:,:,ipc) 5858 end if 5859 end do 5860 ABI_FREE(tmp_v1r) 5861 5862 else 5863 ! Interpolate my_npert potentials for this q-point. 5864 call wrtout(std_out, sjoin(" Interpolating qpt:", ktoa(this_qpts(:,iq)))) 5865 call dvdb%ftinterp_qpt(this_qpts(:, iq), nfft, ngfft, file_v1r, comm_rpt) !, add_lr=?) 5866 cplex = 2 5867 end if 5868 5869 ! Compute the periodic part of the LR term (note add_qphase = 0 because we want the periodic part) 5870 do imyp=1,dvdb%my_npert 5871 idir = dvdb%my_pinfo(1, imyp); ipert = dvdb%my_pinfo(2, imyp); ipc = dvdb%my_pinfo(3, imyp) 5872 do ispden=1,min(dvdb%nspden, 2) 5873 call dvdb%get_v1r_long_range(this_qpts(:,iq), idir, ipert, nfft, ngfft, long_v1r(:,:,ispden,imyp), add_qphase=0) 5874 end do 5875 end do 5876 5877 ! Compute average and write to file. 5878 if (my_rank /= master) cycle 5879 5880 if (write_v1r .and. iq == 1) then 5881 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "v1r_interpolated"), file_v1r)) 5882 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "v1r_lrmodel"), long_v1r)) 5883 end if 5884 5885 do imyp=1,dvdb%my_npert 5886 idir = dvdb%my_pinfo(1, imyp); ipert = dvdb%my_pinfo(2, imyp); ipc = dvdb%my_pinfo(3, imyp) 5887 do ispden=1,dvdb%nspden 5888 5889 vals2 = sum(file_v1r(:,:,ispden,imyp), dim=2) / nfft 5890 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1scf_avg"), vals2, & 5891 start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1]) 5892 NCF_CHECK(ncerr) 5893 5894 vals2 = sum(abs(file_v1r(:,:,ispden,imyp)), dim=2) / nfft 5895 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1scf_abs_avg"), vals2, & 5896 start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1]) 5897 NCF_CHECK(ncerr) 5898 5899 vals2 = sum(long_v1r(:,:,ispden,imyp), dim=2) / nfft 5900 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1lr_avg"), vals2, & 5901 start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1]) 5902 NCF_CHECK(ncerr) 5903 vals2 = sum(abs(long_v1r(:,:,ispden,imyp)), dim=2) / nfft 5904 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1lr_abs_avg"), vals2, & 5905 start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1]) 5906 NCF_CHECK(ncerr) 5907 vals2 = sum(file_v1r(:,:,ispden,imyp) - long_v1r(:,:,ispden,imyp), dim=2) / nfft 5908 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1scfmlr_avg"), vals2, & 5909 start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1]) 5910 NCF_CHECK(ncerr) 5911 vals2 = sum(abs(file_v1r(:,:,ispden,imyp) - long_v1r(:,:,ispden,imyp)), dim=2) / nfft 5912 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1scfmlr_abs_avg"), vals2, & 5913 start=[1,ispden,idir,ipert,iq], count=[2,1,1,1,1]) 5914 NCF_CHECK(ncerr) 5915 5916 ! Compute G-components of DFPT potentials and LR model for G in small-sphere and save results to disk 5917 call fourdp(2, workg, file_v1r(:,:,ispden,imyp), -1, dvdb%mpi_enreg, nfft, 1, ngfft, 0) 5918 do ig=1,ngsmall 5919 work_gsmall(:, ig) = workg(:, ig2ifft(ig)) 5920 end do 5921 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1scf_gsmall"), work_gsmall, & 5922 start=[1,1,ispden,idir,ipert,iq], count=[2,ngsmall,1,1,1,1]) 5923 NCF_CHECK(ncerr) 5924 5925 call fourdp(2, workg, long_v1r(:,:,ispden,imyp), -1, dvdb%mpi_enreg, nfft, 1, ngfft, 0) 5926 do ig=1,ngsmall 5927 work_gsmall(:, ig) = workg(:, ig2ifft(ig)) 5928 end do 5929 ncerr = nf90_put_var(ncid, nctk_idname(ncid, "v1lr_gsmall"), work_gsmall, & 5930 start=[1,1,ispden,idir,ipert,iq], count=[2,ngsmall,1,1,1,1]) 5931 NCF_CHECK(ncerr) 5932 5933 ! Debugging section. 5934 !write(std_out, "(a)")"--- !DVDB_LONGRANGE_DIFF" 5935 !write(std_out,"(3a)")" qpoint: ", trim(ktoa(this_qpts(:,iq))), "," 5936 !write(std_out,"(a,i0,a)")" iq: ", iq, "," 5937 !write(std_out,"(2(a,i0))")" idir: ", idir, ", ipert:", ipert 5938 !write(std_out,"(a,i0,a)")" ispden: ", ispden, "," 5939 !call vdiff_print(vdiff_eval(2, nfft, file_v1r(:,:,ispden,imyp), long_v1r(:,:,ispden,imyp), & 5940 ! dvdb%cryst%ucvol, vd_max=vd_max)) 5941 !write(std_out,"(a)")"..." 5942 5943 ! Debug: write potentials to file. 5944 if (unt /= -1) then 5945 write(unt,*)"# q-point:", trim(ktoa(this_qpts(:,iq))), ", iq: ", trim(itoa(iq)) 5946 write(unt,*)"# idir: ",idir,", ipert: ",ipert,", ispden:", ispden 5947 write(unt,*)"# file_v1r, long_v1r, diff" 5948 5949 if (cplex == 1) then 5950 do i3=1,n3 5951 do i2=1,n2 5952 do i1=1,n1 5953 ifft = i1+n1*((i2-1)+n2*(i3-1)) 5954 write(unt,"(3(i0,1x),3(es12.4,2x))") & 5955 i1,i2,i3, & 5956 file_v1r(1,ifft,ispden,imyp), long_v1r(1,ifft,ispden,imyp), & 5957 file_v1r(1,ifft,ispden,imyp) - long_v1r(1,ifft,ispden,imyp) 5958 end do 5959 end do 5960 end do 5961 else 5962 do i3=1,n3 5963 do i2=1,n2 5964 do i1=1,n1 5965 ifft = i1+n1*((i2-1)+n2*(i3-1)) 5966 write(unt, "(3(i0,1x),6(es12.4,2x))") & 5967 i1,i2,i3, & 5968 file_v1r(1,ifft,ispden,imyp), long_v1r(1,ifft,ispden,imyp), & 5969 file_v1r(1,ifft,ispden,imyp) - long_v1r(1,ifft,ispden,imyp), & 5970 file_v1r(2,ifft,ispden,imyp), long_v1r(2,ifft,ispden,imyp), & 5971 file_v1r(2,ifft,ispden,imyp) - long_v1r(2,ifft,ispden,imyp) 5972 end do 5973 end do 5974 end do 5975 end if 5976 write(unt,*) 5977 write(unt,*) 5978 end if 5979 5980 end do 5981 end do 5982 !write(std_out,*)" " 5983 end do ! iq 5984 5985 ABI_FREE(long_v1r) 5986 ABI_FREE(file_v1r) 5987 ABI_FREE(workg) 5988 ABI_FREE(gfft) 5989 ABI_FREE(ig2ifft) 5990 ABI_FREE(gsmall) 5991 ABI_FREE(work_gsmall) 5992 5993 if (interpolated == 1) then 5994 ! Compute max_r |W(R,r)| and write data to file. 5995 call dvdb%get_maxw(dtset%ddb_ngqpt, all_rpt, all_rmod, maxw) 5996 if (my_rank == master) then 5997 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ngqpt"), dtset%ddb_ngqpt)) 5998 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "rpt"), all_rpt)) 5999 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "rmod"), all_rmod)) 6000 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "ngfft"), ngfft(1:3))) 6001 NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "maxw"), maxw)) 6002 end if 6003 ABI_FREE(all_rpt) 6004 ABI_FREE(all_rmod) 6005 ABI_FREE(maxw) 6006 end if 6007 6008 if (my_rank == master) then 6009 NCF_CHECK(nf90_close(ncid)) 6010 end if 6011 6012 end subroutine dvdb_write_v1qavg
m_dvdb/find_symeq [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
find_symeq
FUNCTION
Find symmetry which links to the perturbation specified by (idir, ipert)
INPUTS
cryst<crystal_t>=crystal structure parameters idir=Direction of the perturbation ipert=Perturbation type. symq(4,2,nsym)=Table produced by littlegroup_q pflag(3,natom)= For each atomic perturbation: 0 if pert is not available. 1 if pert is available. 2 if pert can been reconstructed by symmetry.
OUTPUT
ipert_eq isym_eq itirev_eq g0_qpt(3)
SOURCE
2327 subroutine find_symeq(cryst, idir, ipert, symq, pflag, ipert_eq, isym_eq, itirev_eq, g0_qpt, allow_g0) 2328 2329 !Arguments ------------------------------------ 2330 !scalars 2331 integer,intent(in) :: idir,ipert 2332 integer,intent(out) :: ipert_eq,isym_eq,itirev_eq 2333 type(crystal_t),intent(in) :: cryst 2334 logical,optional :: allow_g0 2335 !arrays 2336 integer,intent(in) :: symq(4,2,cryst%nsym),pflag(3,cryst%natom) 2337 integer,intent(out) :: g0_qpt(3) 2338 2339 !Local variables------------------------------- 2340 !scalars 2341 logical :: do_allow_g0 2342 integer :: isym,idir_eq,ip,itirev 2343 2344 ! ************************************************************************* 2345 2346 isym_eq = -1; ipert_eq = -1 2347 do_allow_g0 = .true.; if (present(allow_g0)) do_allow_g0 = allow_g0 2348 2349 symloop: & 2350 do itirev=1,2 2351 itirev_eq = itirev 2352 do isym=1,cryst%nsym 2353 2354 ! Check that isym preserves the q-point 2355 !if (symq(4,itirev,isym) /= 1 .or. any(symq(1:3,itirev,isym) /= 0)) cycle 2356 if (symq(4,itirev,isym) /= 1) cycle ! .or. any(symq(1:3,itirev,isym) /= 0)) cycle 2357 if (any(symq(1:3,itirev,isym) /= 0) .and. .not.do_allow_g0) cycle 2358 g0_qpt = symq(1:3,itirev,isym) 2359 2360 do ip=1,cryst%natom 2361 !if (.not. cryst%indsym(4,isym,ip) == ipert) cycle 2362 if (.not. cryst%indsym(4,isym,ipert) == ip) cycle 2363 isym_eq = isym; ipert_eq = ip 2364 do idir_eq=1,3 2365 if (idir_eq == idir .and. ip == ipert .and. cryst%symrec(idir,idir_eq,isym) /= 0) isym_eq = -1 2366 if (cryst%symrec(idir,idir_eq,isym) /= 0 .and. pflag(idir_eq, ip) == 0) then 2367 !if (cryst%symrel(idir,idir_eq,isym) /= 0 .and. pflag(idir_eq, ip) == 0) then 2368 !if (idir_eq == idir .and. ip == ipert) cycle 2369 isym_eq = -1 2370 end if 2371 end do 2372 if (isym_eq /= -1) exit symloop 2373 end do 2374 end do 2375 end do symloop 2376 2377 if (isym_eq == -1) then 2378 ipert_eq = -1; itirev_eq = -1 2379 end if 2380 2381 end subroutine find_symeq
m_dvdb/my_hdr_skip [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
my_hdr_skip
FUNCTION
Skip the header without rewinding the file. Return exit code.
NOTES
Because hdr_skip rewinds the file and I'm not gonna change that ugly code.
SOURCE
4815 integer function my_hdr_skip(unit, idir, ipert, qpt, msg) result(ierr) 4816 4817 !Arguments ------------------------------------ 4818 !scalars 4819 integer,intent(in) :: unit,idir,ipert 4820 real(dp),intent(in) :: qpt(3) 4821 character(len=500),intent(out) :: msg 4822 4823 !Local variables------------------------------- 4824 integer :: fform 4825 type(hdr_type) :: tmp_hdr 4826 !************************************************************************ 4827 4828 ierr = 0; msg = "" 4829 call hdr_fort_read(tmp_hdr, unit, fform) 4830 ierr = dvdb_check_fform(fform, "read_dvdb", msg) 4831 if (ierr /= 0) return 4832 4833 if (idir /= -1 .and. ipert /= -1) then 4834 if (idir /= mod(tmp_hdr%pertcase-1, 3) + 1 .or. & 4835 ipert /= (tmp_hdr%pertcase - idir) / 3 + 1 .or. & 4836 any(abs(qpt - tmp_hdr%qptn) > tol14)) then 4837 msg = "Perturbation index on file does not match the one expected by the caller" 4838 ierr = -1 4839 end if 4840 end if 4841 4842 call tmp_hdr%free() 4843 4844 end function my_hdr_skip
m_dvdb/prepare_ftinterp [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
prepare_ftinterp
FUNCTION
Internal helper function used to prepare the Fourier interpolation of the DFPT potentials.
m_dvdb/qcache_free [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
qcache_free
FUNCTION
Free dynamic memory.
SOURCE
1882 subroutine qcache_free(qcache) 1883 1884 !Arguments ------------------------------------ 1885 !scalars 1886 class(qcache_t),intent(inout) :: qcache 1887 1888 !Local variables------------------------------- 1889 !scalars 1890 integer :: iq, ierr 1891 1892 ! ************************************************************************* 1893 1894 if (allocated(qcache%key)) then 1895 do iq=1,size(qcache%key) 1896 ABI_SFREE(qcache%key(iq)%v1scf) 1897 end do 1898 ABI_SFREE(qcache%key) 1899 end if 1900 ABI_SFREE(qcache%count_qused) 1901 ABI_SFREE(qcache%itreatq) 1902 1903 if (qcache%v1scf_3natom_request /= xmpi_request_null) call xmpi_wait(qcache%v1scf_3natom_request, ierr) 1904 ABI_SFREE(qcache%v1scf_3natom_qibz) 1905 1906 end subroutine qcache_free
m_dvdb/qcache_get_mbsize [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
qcache_get_mbsize
FUNCTION
Return the (allocated) size of the cache in Mb.
SOURCE
1966 pure real(dp) function qcache_get_mbsize(qcache) result(mbsize) 1967 1968 !Arguments ------------------------------------ 1969 !scalars 1970 class(qcache_t),intent(in) :: qcache 1971 1972 !Local variables------------------------------- 1973 !scalars 1974 integer :: qcnt, iq 1975 1976 ! ************************************************************************* 1977 1978 mbsize = zero; if (.not. allocated(qcache%key)) return 1979 ! Compute cache size. 1980 qcnt = 0 1981 do iq=1,size(qcache%key) 1982 if (allocated(qcache%key(iq)%v1scf)) qcnt = qcnt + 1 1983 end do 1984 mbsize = qcache%onepot_mb * qcnt 1985 1986 end function qcache_get_mbsize
m_dvdb/qcache_new [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
qcache_new
FUNCTION
Initialize qcache_t object from dimensions.
INPUTS
nqpt=Number of q-points (dvdb%nqpt or nqibz depending on cache type) nfft=Number of fft-points treated by this processors ngfft(18)=contain all needed information about 3D FFT mbsize: Cache size in megabytes. < 0 to allocate all q-points. 0 has not effect. > 0 for cache with automatically computed nqpt points. natom3, my_npert=Total number of perturbations and number of perturbations treated by this CPU. nspden=Number of spin density components.
OUTPUT
SOURCE
1631 type(qcache_t) function qcache_new(nqpt, nfft, ngfft, mbsize, natom3, my_npert, nspden) result(qcache) 1632 1633 !Arguments ------------------------------------ 1634 !scalars 1635 integer,intent(in) :: nqpt, nfft, natom3, nspden, my_npert 1636 real(dp),intent(in) :: mbsize 1637 !arrays 1638 integer,intent(in) :: ngfft(18) 1639 1640 ! ************************************************************************* 1641 1642 qcache%nqpt = nqpt 1643 ABI_ICALLOC(qcache%count_qused, (nqpt)) 1644 ABI_MALLOC(qcache%key, (nqpt)) 1645 ABI_MALLOC(qcache%itreatq, (nqpt)) 1646 qcache%itreatq = 1 1647 qcache%stats = 0 1648 qcache%max_mbsize = mbsize 1649 1650 qcache%onepot_mb = two * product(ngfft(1:3)) * nspden * QCACHE_KIND * b2Mb 1651 if (abs(mbsize) < tol3) then 1652 qcache%maxnq = 0 1653 else if (mbsize < zero) then 1654 qcache%maxnq = nqpt 1655 else 1656 qcache%maxnq = nint(mbsize / (qcache%onepot_mb * my_npert)) 1657 qcache%maxnq = max(min(qcache%maxnq, nqpt), 1) 1658 end if 1659 1660 ! TODO: Get rid of maxnq, keep use_3natom_cache only. 1661 1662 ! Allocate cache with all the 3*natom perturbations. 1663 ! Disable it if no parallelism over perturbations. 1664 ! Disabled as slow FT R --> q seems to be faster. 1665 qcache%use_3natom_cache = .False. 1666 !qcache%use_3natom_cache = .True. 1667 !if (my_npert == natom3) qcache%use_3natom_cache = .False. 1668 qcache%stored_iqibz_cplex = huge(1) 1669 if (qcache%use_3natom_cache) then 1670 ABI_MALLOC(qcache%v1scf_3natom_qibz, (2, nfft, nspden, natom3)) 1671 end if 1672 qcache%v1scf_3natom_request = xmpi_request_null 1673 1674 call wrtout(std_out, sjoin(" Using cache for Vscf(q) with MAX input size: ", ftoa(mbsize, fmt="f9.2"), " [Mb]")) 1675 call wrtout(std_out, sjoin(" Max number of q-points stored in memory: ", itoa(qcache%maxnq))) 1676 call wrtout(std_out, sjoin(" Use extra cache with 3 natom potentials: ", yesno(qcache%use_3natom_cache))) 1677 call wrtout(std_out, sjoin(" One DFPT potential requires: ", ftoa(qcache%onepot_mb, fmt="f9.2"), " [Mb]")) 1678 call wrtout(std_out, sjoin(" QCACHE_KIND: ", itoa(QCACHE_KIND))) 1679 1680 end function qcache_new
m_dvdb/qcache_qcache_make_room [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
qcache_qcache_make_room
FUNCTION
Deallocate entries in cache taking into account the list of q-points required in the next iteration. Deallocate entries only if the cache size required to treat all the points specified by ineed_qpt would become greater than %max_bsize Return ierr /= 0 and msg if max_bsize constraint cannot be respected.
INPUTS
ineed_qpt(%nqpt) = 0 if this q-points is not required. OUTPUTS msg=Warning message if ierr /= 0
SOURCE
2009 integer function qcache_make_room(qcache, ineed_qpt, msg) result(ierr) 2010 2011 !Arguments ------------------------------------ 2012 !scalars 2013 class(qcache_t),intent(inout) :: qcache 2014 character(len=*),intent(out) :: msg 2015 !arrays 2016 integer,intent(in) :: ineed_qpt(qcache%nqpt) 2017 2018 !Local variables------------------------------- 2019 !scalars 2020 integer :: iq, nq_remove, qcnt, count_qnew 2021 real(dp) :: mbsize_now, mbsize_extra 2022 2023 ! ************************************************************************* 2024 2025 ierr = 0; msg = "" 2026 if (qcache%max_mbsize < zero) return 2027 mbsize_now = qcache%get_mbsize() 2028 2029 ! Count the number of q-points that are not in cache and the extra memory required to allocate everything. 2030 count_qnew = 0 2031 do iq=1,qcache%nqpt 2032 if (ineed_qpt(iq) > 0 .and. .not. allocated(qcache%key(iq)%v1scf)) count_qnew = count_qnew + 1 2033 end do 2034 mbsize_extra = mbsize_now + count_qnew * qcache%onepot_mb 2035 2036 if (mbsize_extra > qcache%max_mbsize) then 2037 ! Try to deallocate nq_remove q-points provided they are not needed. 2038 nq_remove = nint((mbsize_extra - qcache%max_mbsize) / qcache%onepot_mb) 2039 qcnt = 0 2040 do iq=1,qcache%nqpt 2041 if (ineed_qpt(iq) == 0 .and. allocated(qcache%key(iq)%v1scf)) then 2042 ABI_FREE(qcache%key(iq)%v1scf) 2043 qcnt = qcnt + 1 2044 if (qcnt == nq_remove) exit 2045 end if 2046 end do 2047 if (iq == qcache%nqpt + 1) then 2048 ierr = 1 2049 msg = "Couldn't decrease cache size below input limit. Continuing anyway but we may go out of memory!" 2050 end if 2051 end if 2052 2053 end function qcache_make_room
m_dvdb/qcache_report_stats [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
qcache_report_stats
FUNCTION
Print info on q-cache states and reset counters.
SOURCE
1920 subroutine qcache_report_stats(qcache) 1921 1922 !Arguments ------------------------------------ 1923 !scalars 1924 class(qcache_t),intent(inout) :: qcache 1925 1926 ! ************************************************************************* 1927 1928 if (qcache%maxnq == 0) then 1929 !write(std_out, "(/,a)")" MPI-distributed q-cache deactivated as maxnq == 0" 1930 if (qcache%use_3natom_cache) then 1931 write(std_out, "(a,i0,2x,a,f5.1,a)") & 1932 " Cache hit in v1scf_3natom_qibz: ", qcache%stats(2), "(", (100.0_dp * qcache%stats(2)) / qcache%stats(1), "%)" 1933 end if 1934 1935 else if (qcache%maxnq > 0 .and. qcache%stats(1) /= 0) then 1936 write(std_out, "(2a)")ch10, " Qcache stats:" 1937 write(std_out, "(4x,a,i0)")" Total number of calls: ", qcache%stats(1) 1938 write(std_out, "(4x,a,i0,2x,a,f5.1,a)") & 1939 " Cache hit in v1scf_3natom_qibz: ", qcache%stats(2), "(", (100.0_dp * qcache%stats(2)) / qcache%stats(1), "%)" 1940 write(std_out, "(4x,a,i0,2x,a,f5.1,a)") & 1941 " Cache hit in MPI-distributed cache: ", qcache%stats(3), "(", (100.0_dp * qcache%stats(3)) / qcache%stats(1), "%)" 1942 write(std_out, "(4x,a,i0,2x,a,f5.1,a)") & 1943 " Cache miss: ", qcache%stats(4), "(", (100.0_dp * qcache%stats(4)) / qcache%stats(1), "%)" 1944 write(std_out, "(a)")sjoin(" Memory allocated for MPI cache: ", ftoa(qcache%get_mbsize(), fmt="f8.1"), " [Mb] <<< MEM") 1945 write(std_out, "(a)")sjoin(" max_mbsize:", ftoa(qcache%max_mbsize, fmt="f8.1"), & 1946 "(Decrease this value if calculation goes out of memory)") 1947 end if 1948 1949 write(std_out, "(a)") 1950 qcache%stats = 0 1951 1952 end subroutine qcache_report_stats
m_dvdb/qcache_t [ Types ]
NAME
qcache_t
FUNCTION
SOURCE
108 type, private :: qcache_t 109 110 integer :: maxnq = 0 111 ! Max number of q-points in Vscf(q) stored in the cache. 112 ! Note this is not the size of the key array that is dimensioned with 113 ! dvdb%nqpt or nqibz depending on the type of cache in use. 114 115 integer :: nqpt 116 ! Number of q-points in the key array 117 118 !integer :: nspden, my_npert, nfft 119 120 real(dp) :: max_mbsize = zero 121 ! Max cache size in megabytes. 122 ! < 0 to allocate all q-points. 123 ! 0 has not effect. 124 ! > 0 for cache with automatically computed nqpt points. 125 126 real(dp) :: onepot_mb = zero 127 ! Size of 1 DFPT potential in megabytes 128 129 logical :: use_3natom_cache = .False. 130 ! True if v1scf_3natom_qibz cache is used. 131 132 integer :: v1scf_3natom_request = xmpi_request_null 133 ! Reques for v1scf_3natom_qibz iallgather 134 135 integer :: stats(4) 136 ! Total number of calls, number of cache hit in v1scf_3natom_qibz cache, hit in key cache, cache misses. 137 138 integer,allocatable :: count_qused(:) 139 ! count_qused(nq) 140 ! Number of times this q-point has been used in dvdb_readsym_qbz 141 142 integer(i1b),allocatable :: itreatq(:) 143 ! itreatq(nq) 144 ! Table used to distribute q-points in the IBZ among procs. 145 ! 0 if this MPI rank should not store and treat this q-point. 146 ! 1 or 2-9 147 148 real(dp), allocatable :: v1scf_3natom_qibz(:,:,:,:) 149 ! v1scf_3natom(cplex, nfftf, nspden, 3*natom)) 150 ! Store all the 3*natom perturbations associated to `stored_iqibz_cplex` 151 ! Used to reduce the number of MPI communications required to collect all the potentials 152 ! on the MPI rank before computing V(Sq) from V(q). 153 ! IMPORTANT: This cache is beneficial provided client code loops over q-points grouped in stars/shells. 154 ! cplex value is stored in `stored_iqibz_cplex`. 155 156 integer :: stored_iqibz_cplex(2) = huge(1) 157 ! The index of the qpoint in the IBZ/DVDB file associated to v1scf_3natom_qibz. 158 159 type(qcache_entry_t), allocatable :: key(:) 160 ! key(nq) 161 ! array of v1scf potentials (ony a subset is usually allocated) 162 163 contains 164 165 procedure :: free => qcache_free 166 ! Release dynamic memory. 167 168 procedure :: report_stats => qcache_report_stats 169 ! Print info on q-cache stats and reset counters. 170 171 procedure :: get_mbsize => qcache_get_mbsize 172 ! Return the (allocated) size of the cache in Mb. 173 174 procedure :: make_room => qcache_make_room 175 176 end type qcache_t
m_dvdb/rotate_fqg [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
rotate_fqg
FUNCTION
INPUTS
SOURCE
2760 subroutine rotate_fqg(itirev, symm, qpt, tnon, ngfft, nfft, nspden, infg, outfg) 2761 2762 !Arguments ------------------------------------ 2763 !scalars 2764 integer,intent(in) :: itirev,nfft,nspden 2765 !arrays 2766 integer,intent(in) :: symm(3,3),ngfft(18) 2767 real(dp),intent(in) :: qpt(3),tnon(3) 2768 real(dp),intent(in) :: infg(2,nfft,nspden) 2769 real(dp),intent(out) :: outfg(2,nfft,nspden) 2770 2771 !Local variables------------------------------- 2772 !scalars 2773 integer :: i1,i2,i3,id1,id2,id3,n1,n2,n3,ind1,ind2,j1,j2,j3,l1,l2,l3,k1,k2,k3,nfftot,isp,tsign 2774 real(dp) :: arg 2775 logical :: has_phase 2776 !arrays 2777 integer :: tsg(3) 2778 real(dp) :: phnon1(2), tsec(2) 2779 2780 ! ************************************************************************* 2781 2782 ! Keep track of total time spent. 2783 call timab(1803, 1, tsec) 2784 2785 n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3); nfftot = product(ngfft(1:3)) 2786 ABI_CHECK(nfftot == nfft, "FFT parallelism not supported") 2787 id1 = n1/2+2; id2 = n2/2+2; id3=n3/2+2 2788 2789 ABI_CHECK(any(itirev == [1, 2]), "Wrong itirev") 2790 tsign = 3-2*itirev; has_phase = any(abs(tnon) > tol12) 2791 2792 !outfg = zero 2793 2794 do isp=1,nspden 2795 ind1 = 0 2796 do i3=1,n3 2797 ! Get location of G vector (grid point) centered at 0 0 0 2798 l3 = i3-(i3/id3)*n3-1 2799 do i2=1,n2 2800 l2 = i2-(i2/id2)*n2-1 2801 do i1=1,n1 2802 ind1 = ind1 + 1 2803 !ind1 = 1 + i1 + (i2-1)*n1 + (i3-1)*n1*n2 2804 !if (mod(ind1, nprocs) /= my_rank) cycle 2805 2806 l1 = i1-(i1/id1)*n1-1 2807 2808 ! Get rotated G vector. IS(G) 2809 j1 = tsign * (symm(1,1)*l1+symm(1,2)*l2+symm(1,3)*l3) 2810 j2 = tsign * (symm(2,1)*l1+symm(2,2)*l2+symm(2,3)*l3) 2811 j3 = tsign * (symm(3,1)*l1+symm(3,2)*l2+symm(3,3)*l3) 2812 2813 ! FIXME :TO BE CLARIFIED: 2814 ! We are not working on the G-sphere thus SG may be outside 2815 ! of the box. This check is not done in irrzg!!! 2816 if ( (j1 > n1/2 .or. j1 < -(n1-1)/2) .or. & 2817 (j2 > n2/2 .or. j1 < -(n2-1)/2) .or. & 2818 (j3 > n3/2 .or. j3 < -(n3-1)/2) ) then 2819 !write(std_out,*)"outsize box!" 2820 outfg(:,ind1,isp) = zero 2821 cycle 2822 end if 2823 2824 tsg = [j1,j2,j3] ! +- S^{-1} G 2825 2826 ! Map into [0,n-1] and then add 1 for array index in [1, n] 2827 k1=1+mod(n1+mod(j1,n1),n1) 2828 k2=1+mod(n2+mod(j2,n2),n2) 2829 k3=1+mod(n3+mod(j3,n3),n3) 2830 2831 ! Get linear index of rotated point Gj 2832 ind2 = k1+n1*((k2-1)+n2*(k3-1)) 2833 2834 ! TODO: Here I believe there are lots of cache misses, should perform low-level profiling 2835 ! OMP perhaps can accelerate this part but mind false sharing... 2836 if (has_phase) then 2837 ! compute exp(-2*Pi*I*G dot tau) using original G 2838 arg = two_pi * dot_product(qpt + tsg, tnon) 2839 phnon1(1) = cos(arg); phnon1(2) =-sin(arg) 2840 2841 ! rho(Strans*G)=exp(2*Pi*I*(G) dot tau_S) rho(G) 2842 outfg(1, ind1, isp) = phnon1(1) * infg(1, ind2, isp) - phnon1(2) * infg(2, ind2, isp) 2843 outfg(2, ind1, isp) = phnon1(1) * infg(2, ind2, isp) + phnon1(2) * infg(1, ind2, isp) 2844 else 2845 outfg(1, ind1, isp) = infg(1, ind2, isp) 2846 outfg(2, ind1, isp) = infg(2, ind2, isp) 2847 end if 2848 2849 ! Take complex conjugate if time-reversal is used. 2850 if (tsign == -1) outfg(2, ind1, isp) = -outfg(2, ind1, isp) 2851 end do 2852 end do 2853 end do 2854 end do ! isp 2855 2856 !call xmpi_sum(comm, outfg, ierr) 2857 call timab(1803, 2, tsec) 2858 2859 end subroutine rotate_fqg
m_dvdb/v1phq_complete [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
v1phq_complete
FUNCTION
Use the symmetries of the little group of the q-point to reconstruct the first order potentials starting from an initial irreducible set.
INPUTS
cryst<crystal_t>=crystal structure parameters qpt(3)=q-point in reduced coordinates. ngfft(18)=Info of FFT grid. cplex=1 if real potentials (qpt==gamma), 2 if complex nfft=(effective) number of FFT grid points (for this proc). nspden=number of spin-density components nsppol=Number of independent spin polarizations mpi_enreg=information about MPI parallelization symv1=If 1, the new potentials are symmetrized using the set of symmetries that leaves the perturbation invariant.
SIDE EFFECTS
pflag(3,natom)= For each atomic perturbation: 0 if pert is not available. 1 if pert is available. 2 if pert has been reconstructed by symmetry. Initialized by the caller. Changed in output. v1scf(cplex*nfft,nspden,3*cryst%natom)=Array with first order potentials. in input: filled with the irreducible potentials (corresponding pflag set to 1) output: Contains full set of perturbations.
SOURCE
2088 subroutine v1phq_complete(cryst,qpt,ngfft,cplex,nfft,nspden,nsppol,mpi_enreg,symv1,pflag,v1scf) 2089 2090 !Arguments ------------------------------------ 2091 !scalars 2092 integer,intent(in) :: cplex,nfft,nspden,nsppol 2093 integer,intent(in) :: symv1 2094 type(crystal_t),intent(in) :: cryst 2095 type(MPI_type),intent(in) :: mpi_enreg 2096 !arrays 2097 integer,intent(in) :: ngfft(18) 2098 integer,intent(inout) :: pflag(3, cryst%natom) 2099 real(dp),intent(in) :: qpt(3) 2100 real(dp),intent(inout) :: v1scf(cplex*nfft,nspden,3*cryst%natom) 2101 2102 !Local variables------------------------------- 2103 !scalars 2104 integer,parameter :: syuse0=0,rfmeth2=2,tim_fourdp0=0 2105 integer :: idir,ipert,tsign,isym_eq,itirev_eq,ipert_eq !,itirev 2106 integer :: pcase,trev_q,idir_eq,pcase_eq,ispden,cnt 2107 integer :: i1,i2,i3,id1,id2,id3,n1,n2,n3,ind1,ind2,j1,j2,j3,l1,l2,l3,k1,k2,k3,nfftot 2108 real(dp) :: arg 2109 logical :: has_phase 2110 logical,parameter :: debug=.False. 2111 character(len=500) :: msg 2112 !integer,save :: enough=0 2113 !arrays 2114 integer :: symrel_eq(3,3),symrec_eq(3,3),g0_qpt(3),l0(3),tsm1g(3) !symm(3,3), 2115 integer :: symq(4,2,cryst%nsym) 2116 real(dp) :: phnon1(2),tnon(3) 2117 real(dp),allocatable :: workg(:,:), workg_eq(:,:),v1g(:,:,:) 2118 2119 ! ************************************************************************* 2120 2121 n1 = ngfft(1); n2 = ngfft(2); n3 = ngfft(3); nfftot = product(ngfft(1:3)) 2122 ABI_CHECK(nfftot == nfft, "FFT parallelism not supported") 2123 id1 = n1/2+2; id2 = n2/2+2; id3 = n3/2+2 2124 2125 ABI_MALLOC(v1g, (2,nfft,nspden)) 2126 ABI_MALLOC(workg_eq, (2, nfft)) 2127 ABI_MALLOC(workg, (2, nfft)) 2128 2129 ! Examine the symmetries of the q wavevector 2130 call littlegroup_q(cryst%nsym,qpt,symq,cryst%symrec,cryst%symafm,trev_q,prtvol=0) 2131 2132 pcase_loop: & 2133 do pcase=1,3*cryst%natom 2134 idir = mod(pcase-1, 3) + 1; ipert = (pcase - idir) / 3 + 1 2135 if (pflag(idir, ipert) /= 0) cycle ! This pcase is available 2136 2137 ! Find symmetry which links to the perturbation requested (pcase) 2138 call find_symeq(cryst, idir, ipert, symq, pflag, ipert_eq, isym_eq, itirev_eq, g0_qpt, allow_g0=.true.) 2139 !if (isym_eq == -1) then 2140 ! call find_symeq(cryst, idir, ipert, symq, pflag, ipert_eq, isym_eq, itirev_eq, g0_qpt, allow_g0=.true.) 2141 !end if 2142 2143 if (isym_eq == -1) then 2144 if (debug) write(std_out,*)"Cannot find isym eq for idir, ipert:", idir,ipert 2145 cycle pcase_loop 2146 end if 2147 2148 ! set flag since we will reconstruct pcase from isym_eq. 2149 pflag(idir, ipert) = 2 2150 2151 symrel_eq = cryst%symrel(:,:,isym_eq) 2152 symrec_eq = cryst%symrec(:,:,isym_eq) 2153 tsign = 3-2*itirev_eq 2154 2155 ! Phase due to L0 + R^{-1}tau 2156 l0 = cryst%indsym(1:3,isym_eq,ipert) 2157 2158 tnon = l0 + matmul(transpose(symrec_eq), cryst%tnons(:,isym_eq)) 2159 has_phase = any(abs(tnon) > tol12) 2160 ! FIXME 2161 !ABI_CHECK(.not. has_phase, "has phase must be tested") 2162 !if (has_phase) then 2163 ! enough = enough + 1 2164 ! if (enough == 1) ABI_WARNING("has phase must be tested") 2165 !end if 2166 2167 workg = zero 2168 2169 ! Reconstruct DFPT potential. Final results stored in v1g. 2170 if (debug) write(std_out,*)"Reconstructing idir:", idir, ", ipert:", ipert 2171 v1g = zero; cnt = 0 2172 do idir_eq=1,3 2173 if (symrec_eq(idir, idir_eq) == 0) cycle 2174 cnt = cnt + 1 2175 pcase_eq = idir_eq + (ipert_eq-1)*3 2176 if (debug) write(std_out,*) "idir_eq: ", idir_eq, ", ipert_eq: ", ipert_eq, ", tsign: ", tsign 2177 2178 if (pflag(idir_eq, ipert_eq) == 0) then 2179 write(msg, *)"pflag for idir_eq, ipert_eq", idir_eq, ipert_eq, "cannot be zero" 2180 ABI_ERROR(msg) 2181 end if 2182 2183 !if (pflag(idir_eq, ipert_eq) == 0) then 2184 ! write(msg, *)"pflag for idir_eq, ipert_eq", idir_eq, ipert_eq, "cannot be zero" 2185 ! ABI_ERROR(msg) 2186 !end if 2187 2188 do ispden=1,nspden 2189 ! Get symmetric perturbation in G-space in workg_eq array. 2190 call fourdp(cplex,workg_eq,v1scf(:,ispden,pcase_eq),-1,mpi_enreg,nfft,1,ngfft,tim_fourdp0) 2191 !call zerosym(workg_eq,cplex,n1,n2,n3,comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft) 2192 2193 !call rotate_fqg(itirev_eq,symrec_eq,qpt,tnon,ngfft,nfft,nspden,workg_eq,workg) 2194 ind1=0 2195 do i3=1,n3 2196 ! Get location of G vector (grid point) centered at 0 0 0 2197 l3 = i3-(i3/id3)*n3-1 2198 do i2=1,n2 2199 l2 = i2-(i2/id2)*n2-1 2200 do i1=1,n1 2201 ind1=ind1+1 2202 2203 l1 = i1-(i1/id1)*n1-1 2204 2205 ! Get rotated G vector Gj for each symmetry element 2206 ! -- here we use the TRANSPOSE of symrel_eq; assuming symrel_eq expresses 2207 ! the rotation in real space, the transpose is then appropriate 2208 ! for G space symmetrization (p. 1172d,e of notes, 2 June 1995). 2209 j1 = tsign * (symrel_eq(1,1)*l1+symrel_eq(2,1)*l2+symrel_eq(3,1)*l3) 2210 j2 = tsign * (symrel_eq(1,2)*l1+symrel_eq(2,2)*l2+symrel_eq(3,2)*l3) 2211 j3 = tsign * (symrel_eq(1,3)*l1+symrel_eq(2,3)*l2+symrel_eq(3,3)*l3) 2212 2213 ! FIXME :TO BE CLARIFIED: 2214 ! We are not working on the G-sphere thus SG may be outside 2215 ! of the box. This check is not done in irrzg!!! 2216 if ( (j1 > n1/2 .or. j1 < -(n1-1)/2) .or. & 2217 (j2 > n2/2 .or. j1 < -(n2-1)/2) .or. & 2218 (j3 > n3/2 .or. j3 < -(n3-1)/2) ) then 2219 !write(std_out,*)"got it" 2220 workg(:, ind1) = zero; cycle 2221 end if 2222 2223 tsm1g = [j1,j2,j3] ! +- S^{-1} G 2224 2225 ! Map into [0,n-1] and then add 1 for array index in [1,n] 2226 k1=1+mod(n1+mod(j1,n1),n1) 2227 k2=1+mod(n2+mod(j2,n2),n2) 2228 k3=1+mod(n3+mod(j3,n3),n3) 2229 2230 ! Get linear index of rotated point Gj 2231 ind2 = k1+n1*((k2-1)+n2*(k3-1)) 2232 2233 if (has_phase) then 2234 ! compute exp(-2*Pi*I*G dot tau) using original G 2235 ! NB: this phase is same as that in irrzg and phnons1, and corresponds 2236 ! to complex conjugate of phase from G to Gj; 2237 ! we use it immediately below, to go _to_ workg_eq(ind1) 2238 arg = two_pi * dot_product(qpt + tsm1g, tnon) 2239 phnon1(1) = cos(arg); phnon1(2) = -sin(arg) 2240 2241 ! rho(Strans*G)=exp(2*Pi*I*(G) dot tau_S) rho(G) 2242 workg(1, ind1) = phnon1(1) * workg_eq(1, ind2) - phnon1(2) * workg_eq(2, ind2) 2243 workg(2, ind1) = phnon1(1) * workg_eq(2, ind2) + phnon1(2) * workg_eq(1, ind2) 2244 else 2245 workg(1, ind1) = workg_eq(1, ind2) 2246 workg(2, ind1) = workg_eq(2, ind2) 2247 end if 2248 2249 ! Take complex conjugate if time-reversal is used. 2250 if (tsign == -1) workg(2, ind1) = -workg(2, ind1) 2251 end do 2252 end do 2253 end do 2254 2255 v1g(:,:,ispden) = v1g(:,:,ispden) + workg * symrec_eq(idir, idir_eq) 2256 end do ! ispden 2257 end do ! idir_eq 2258 !if (debug) write(std_out,*)"Used ",cnt," equivalent perturbations" 2259 2260 ! Get potential in real space (results in v1scf) 2261 do ispden=1,nspden 2262 !call zerosym(v1g(:,:,ispden),cplex,n1,n2,n3,comm_fft=mpi_enreg%comm_fft,distribfft=mpi_enreg%distribfft) 2263 call fourdp(cplex,v1g(:,:,ispden),v1scf(:,ispden,pcase),+1,mpi_enreg,nfft,1,ngfft,tim_fourdp0) 2264 2265 ! IS(q) = q + G0 2266 ! we want q so we have to multiply by exp(iG0r) in real space. 2267 if (any(g0_qpt /= 0)) then 2268 ABI_CHECK(cplex==2, "cplex == 1") 2269 if (debug) write(std_out,*)"Found not zero g0_qpt", g0_qpt ! for idir: ", idir, ", ipert: ", ipert 2270 call times_eigr(g0_qpt, ngfft, nfft, 1, v1scf(:,ispden,pcase)) 2271 end if 2272 end do 2273 2274 if (symv1 == 1) then 2275 if (debug) write(std_out,*)" Calling v1phq_symmetrize" 2276 call v1phq_symmetrize(cryst,idir,ipert,symq,ngfft,cplex,nfft,nspden,nsppol,mpi_enreg,v1scf(:,:,pcase)) 2277 end if 2278 end do pcase_loop 2279 2280 ABI_FREE(v1g) 2281 ABI_FREE(workg) 2282 ABI_FREE(workg_eq) 2283 2284 ! Handle possible error. 2285 if (any(pflag == 0)) then 2286 write(std_out,"(2a)")"The following perturbations cannot be recostructed by symmetry for q-point: ",trim(ktoa(qpt)) 2287 do ipert=1,cryst%natom 2288 do idir=1,3 2289 if (pflag(idir, ipert) == 0) write(std_out,"(2(a,i0))")"idir= ",idir,", ipert= ",ipert 2290 end do 2291 end do 2292 write(msg,"(5a)")& 2293 "Cannot recostruct all 3*natom atomic perturbations from file",ch10,& 2294 "This usually happens when the DVDB does not contain all the independent perturbations for this q-point",ch10,& 2295 "See above message for further information." 2296 ABI_ERROR(msg) 2297 end if 2298 2299 end subroutine v1phq_complete
m_dvdb/v1phq_rotate [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
v1phq_rotate
FUNCTION
Reconstruct all the DFPT potential for a q-point in the BZ starting from its symmetrical image in the IBZ.
INPUTS
cryst<crystal_t>=crystal structure parameters qpt_ibz(3)=q-point in the IBZ in reduced coordinates. ngfft=array of dimensions for different FFT grids isym, itimrev, g0q: qpt_bz = I(itimrev) S(isym) q_ibz + g0q ngfft(18)=contain all needed information about 3D FFT. cplex: if 1, real space 1-order functions on FFT grid are REAL, if 2, COMPLEX nfft=(effective) number of FFT grid points (for this proc) for the "fine" grid (see NOTES in respfn.F90) nspden=number of spin-density components mpi_enreg=information about MPI parallelization v1r_qibz(cplex*nfft,nspden,3*cryst%natom)=Array with first order potentials in real space for the irreducible q-point `qpt_ibz` comm: MPI communicator to distribute natom3 * nspden FFT calls
OUTPUT
v1r_qbz(cplex*nfft,nspden,3*cryst%natom)=Array with first order potentials in real space for the q-point in the BZ
SOURCE
2413 subroutine v1phq_rotate(cryst, qpt_ibz, isym, itimrev, g0q, ngfft, cplex, nfft, nspden, & 2414 mpi_enreg, v1r_qibz, v1r_qbz, comm) 2415 2416 !Arguments ------------------------------------ 2417 !scalars 2418 integer,intent(in) :: isym, itimrev, cplex, nfft, nspden, comm 2419 type(crystal_t),intent(in) :: cryst 2420 type(MPI_type),intent(in) :: mpi_enreg 2421 !arrays 2422 integer,intent(in) :: g0q(3),ngfft(18) 2423 real(dp),intent(in) :: qpt_ibz(3) 2424 real(dp),intent(inout) :: v1r_qibz(cplex*nfft,nspden,3*cryst%natom) 2425 real(dp) ABI_ASYNC, intent(out) :: v1r_qbz(cplex*nfft,nspden,3*cryst%natom) 2426 2427 !Local variables------------------------------- 2428 !scalars 2429 integer,parameter :: tim_fourdp0 = 0 2430 !integer,save :: enough = 0 2431 integer :: natom3,mu,ispden,idir,ipert,idir_eq,ipert_eq,mu_eq,cnt,tsign,my_rank,nproc,ierr,root 2432 !arrays 2433 integer :: symrec_eq(3,3),sm1(3,3),l0(3) !g0_qpt(3), symrel_eq(3,3), 2434 real(dp) :: tnon(3), tsec(2) 2435 real(dp) ABI_ASYNC, allocatable :: v1g_qibz(:,:,:),workg(:,:),v1g_mu(:,:) 2436 integer :: requests(nspden, 3*cryst%natom), requests_v1r_qbz(3*cryst%natom) 2437 logical :: requests_v1g_qibz_done(nspden, 3*cryst%natom) 2438 2439 ! ************************************************************************* 2440 2441 ! Keep track of total time spent. 2442 call timab(1804, 1, tsec) 2443 2444 ABI_CHECK(cplex == 2, "cplex != 2") 2445 2446 nproc = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm) 2447 natom3 = 3 * cryst%natom; tsign = 3-2*itimrev 2448 2449 ! Compute IBZ potentials in G-space. Results stored in v1g_qibz(G) 2450 ABI_MALLOC(v1g_qibz, (2*nfft, nspden, natom3)) 2451 requests_v1g_qibz_done = .False. 2452 cnt = 0 2453 do mu=1,natom3 2454 do ispden=1,nspden 2455 cnt = cnt + 1; root = mod(cnt, nproc) 2456 if (root == my_rank) then ! Non-blocking 2457 call fourdp(cplex, v1g_qibz(:,ispden,mu), v1r_qibz(:,ispden,mu), -1, mpi_enreg, nfft, 1, ngfft, tim_fourdp0) 2458 end if 2459 call xmpi_ibcast(v1g_qibz(:,ispden,mu), root, comm, requests(ispden, mu), ierr) 2460 end do 2461 end do 2462 2463 ABI_MALLOC(workg, (2*nfft, nspden)) 2464 ABI_MALLOC(v1g_mu, (2*nfft, nspden)) 2465 2466 symrec_eq = cryst%symrec(:,:,isym) 2467 call mati3inv(symrec_eq, sm1); sm1 = transpose(sm1) 2468 2469 ! For each perturbation. 2470 do mu=1,natom3 2471 root = mod(mu, nproc) 2472 ! MPI parallelism. 2473 if (root == my_rank) then 2474 idir = mod(mu-1, 3) + 1; ipert = (mu - idir) / 3 + 1 2475 2476 ! Phase due to L0 + R^{-1}tau 2477 l0 = cryst%indsym(1:3,isym,ipert) 2478 tnon = l0 + matmul(transpose(symrec_eq), cryst%tnons(:,isym)) 2479 !if (.not. all(abs(tnon) < tol12)) then 2480 ! enough = enough + 1 2481 ! if (enough == 1) ABI_WARNING("tnon must be tested!") 2482 !end if 2483 2484 ipert_eq = cryst%indsym(4, isym, ipert) 2485 2486 v1g_mu = zero; cnt = 0 2487 do idir_eq=1,3 2488 if (symrec_eq(idir, idir_eq) == 0) cycle 2489 mu_eq = idir_eq + (ipert_eq - 1) * 3 2490 cnt = cnt + 1 2491 2492 ! Wait for request before operating on v1g_qibz 2493 if (.not. all(requests_v1g_qibz_done(:, mu_eq))) then 2494 do ispden=1,nspden 2495 call xmpi_wait(requests(ispden, mu_eq), ierr) 2496 requests_v1g_qibz_done(ispden, mu_eq) = .True. 2497 end do 2498 end if 2499 2500 ! Rotate in G-space and accumulate in workg 2501 call rotate_fqg(itimrev, sm1, qpt_ibz, tnon, ngfft, nfft, nspden, v1g_qibz(:,:,mu_eq), workg) 2502 v1g_mu = v1g_mu + workg * symrec_eq(idir, idir_eq) 2503 end do ! idir_eq 2504 2505 ABI_CHECK(cnt /= 0, "cnt should not be zero!") 2506 2507 ! Transform to real space and take into account a possible shift. Results are stored in v1r_qbz. 2508 do ispden=1,nspden 2509 call fourdp(cplex, v1g_mu(:, ispden), v1r_qbz(:, ispden, mu), +1, mpi_enreg, nfft, 1, ngfft, tim_fourdp0) 2510 call times_eigr(-g0q, ngfft, nfft, 1, v1r_qbz(:, ispden, mu)) 2511 !call times_eigr(tsign * g0q, ngfft, nfft, 1, v1r_qbz(:,ispden,mu)) 2512 end do 2513 2514 end if ! root == myrank 2515 2516 call xmpi_ibcast(v1r_qbz(:,:,mu), root, comm, requests_v1r_qbz(mu), ierr) 2517 end do ! mu 2518 2519 ! Relase all requests 2520 call xmpi_waitall(requests, ierr) 2521 call xmpi_waitall(requests_v1r_qbz, ierr) 2522 2523 ABI_FREE(workg) 2524 ABI_FREE(v1g_mu) 2525 ABI_FREE(v1g_qibz) 2526 2527 call timab(1804, 2, tsec) 2528 2529 end subroutine v1phq_rotate
m_dvdb/v1phq_rotate_myperts [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
v1phq_rotate_myperts
FUNCTION
Reconstruct all the DFPT potential for a q-point in the BZ starting from its symmetrical image in the IBZ.
INPUTS
cryst<crystal_t>=crystal structure parameters qpt_ibz(3)=q-point in the IBZ in reduced coordinates. ngfft=array of dimensions for different FFT grids isym, itimrev, g0q: qpt_bz = I(itimrev) S(isym) q_ibz + g0q ngfft(18)=contain all needed information about 3D FFT. cplex: if 1, real space 1-order functions on FFT grid are REAL, if 2, COMPLEX nfft=(effective) number of FFT grid points (for this proc) for the "fine" grid (see NOTES in respfn.F90) nspden=number of spin-density components mpi_enreg=information about MPI parallelization v1r_qibz(cplex*nfft,nspden,3*cryst%natom)=Array with first order potentials in real space for the irreducible q-point `qpt_ibz`
OUTPUT
v1r_qbz(cplex*nfft,nspden,3*cryst%natom)=Array with first order potentials in real space for the q-point in the BZ
SOURCE
2560 subroutine v1phq_rotate_myperts(cryst, qpt_ibz, isym, itimrev, g0q, ngfft, cplex, nfft, nspden, & 2561 mpi_enreg, my_npert, my_pinfo, v1r_qibz, v1r_qbz) 2562 2563 !Arguments ------------------------------------ 2564 !scalars 2565 integer,intent(in) :: isym, itimrev, cplex, nfft, nspden, my_npert 2566 type(crystal_t),intent(in) :: cryst 2567 type(MPI_type),intent(in) :: mpi_enreg 2568 !arrays 2569 integer,intent(in) :: g0q(3), ngfft(18), my_pinfo(3, my_npert) 2570 real(dp),intent(in) :: qpt_ibz(3) 2571 real(dp),intent(inout) :: v1r_qibz(cplex*nfft,nspden,3*cryst%natom) 2572 real(dp),intent(out) :: v1r_qbz(cplex*nfft,nspden,my_npert) 2573 2574 !Local variables------------------------------- 2575 !scalars 2576 integer,parameter :: tim_fourdp0 = 0 2577 !integer,save :: enough = 0 2578 integer :: natom3,mu,ispden,idir,ipert,idir_eq,ipert_eq,mu_eq,cnt,tsign,imyp !ierr, 2579 !arrays 2580 integer :: symrec_eq(3,3),sm1(3,3),l0(3) !g0_qpt(3), symrel_eq(3,3), 2581 logical :: fourdp_done(3*cryst%natom) 2582 real(dp) :: tnon(3), tsec(2) 2583 real(dp), allocatable :: v1g_qibz(:,:,:),workg(:,:),v1g_mu(:,:) 2584 2585 ! ************************************************************************* 2586 2587 ! Keep track of total time spent. 2588 call timab(1804, 1, tsec) 2589 2590 ABI_CHECK(cplex == 2, "cplex != 2") 2591 2592 natom3 = 3 * cryst%natom; tsign = 3-2*itimrev 2593 2594 ! Compute IBZ potentials in G-space. Results stored in v1g_qibz(G) 2595 fourdp_done = .False. 2596 ABI_MALLOC(v1g_qibz, (2*nfft, nspden, natom3)) 2597 !do mu=1,natom3 2598 ! do ispden=1,nspden 2599 ! call fourdp(cplex, v1g_qibz(:,ispden,mu), v1r_qibz(:,ispden,mu), -1, mpi_enreg, nfft, 1, ngfft, tim_fourdp0) 2600 ! end do 2601 !end do 2602 2603 ABI_MALLOC(workg, (2*nfft, nspden)) 2604 ABI_MALLOC(v1g_mu, (2*nfft, nspden)) 2605 2606 symrec_eq = cryst%symrec(:,:,isym) 2607 call mati3inv(symrec_eq, sm1); sm1 = transpose(sm1) 2608 2609 ! For each perturbation treated by this MPI proc 2610 do imyp=1,my_npert 2611 idir = my_pinfo(1, imyp); ipert = my_pinfo(2, imyp); mu = my_pinfo(3, imyp) 2612 2613 ! Phase due to L0 + R^{-1}tau 2614 l0 = cryst%indsym(1:3,isym,ipert) 2615 tnon = l0 + matmul(transpose(symrec_eq), cryst%tnons(:,isym)) 2616 !if (.not. all(abs(tnon) < tol12)) then 2617 ! enough = enough + 1 2618 ! if (enough == 1) ABI_WARNING("tnon must be tested!") 2619 !end if 2620 2621 ipert_eq = cryst%indsym(4, isym, ipert) 2622 2623 v1g_mu = zero; cnt = 0 2624 do idir_eq=1,3 2625 if (symrec_eq(idir, idir_eq) == 0) cycle 2626 mu_eq = idir_eq + (ipert_eq - 1) * 3 2627 cnt = cnt + 1 2628 2629 if (.not. fourdp_done(mu_eq)) then 2630 do ispden=1,nspden 2631 call fourdp(cplex, v1g_qibz(:,ispden,mu_eq), v1r_qibz(:,ispden,mu_eq), -1, mpi_enreg, nfft, 1, ngfft, tim_fourdp0) 2632 end do 2633 fourdp_done(mu_eq) = .True. 2634 end if 2635 2636 ! Rotate in G-space and accumulate in workg 2637 call rotate_fqg(itimrev, sm1, qpt_ibz, tnon, ngfft, nfft, nspden, v1g_qibz(:,:,mu_eq), workg) 2638 v1g_mu = v1g_mu + workg * symrec_eq(idir, idir_eq) 2639 end do ! idir_eq 2640 2641 ABI_CHECK(cnt /= 0, "cnt should not be zero!") 2642 2643 ! Transform to real space and take into account a possible shift. Results are stored in v1r_qbz. 2644 do ispden=1,nspden 2645 call fourdp(cplex, v1g_mu(:, ispden), v1r_qbz(:, ispden, imyp), +1, mpi_enreg, nfft, 1, ngfft, tim_fourdp0) 2646 call times_eigr(-g0q, ngfft, nfft, 1, v1r_qbz(:, ispden, imyp)) 2647 !call times_eigr(tsign * g0q, ngfft, nfft, 1, v1r_qbz(:,ispden,imyp)) 2648 end do 2649 2650 end do ! imyp 2651 2652 ABI_FREE(workg) 2653 ABI_FREE(v1g_mu) 2654 ABI_FREE(v1g_qibz) 2655 2656 call timab(1804, 2, tsec) 2657 2658 end subroutine v1phq_rotate_myperts
m_dvdb/v1phq_symmetrize [ Functions ]
[ Top ] [ m_dvdb ] [ Functions ]
NAME
v1phq_symmetrize
FUNCTION
Enforce spatial-symmetry on the DFPT potential.
INPUTS
cryst<crystal_t>=crystal structure parameters idir=Direction of the perturbation ipert=Perturbation type. symq(4,2,nsym)= Table computed by littlegroup_q. three first numbers define the G vector; fourth number is zero if the q-vector is not preserved, is 1 otherwise second index is one without time-reversal symmetry, two with time-reversal symmetry ngfft=array of dimensions for different FFT grids cplex: if 1, real space 1-order functions on FFT grid are REAL, if 2, COMPLEX nfft=(effective) number of FFT grid points (for this proc) for the "fine" grid (see NOTES in respfn.F90) nspden=number of spin-density components mpi_enreg=information about MPI parallelization
SIDE EFFECTS
v1r(cplex*nfft,nspden)=Array with first order potentials in real space. Symmetrized in output.
SOURCE
2687 subroutine v1phq_symmetrize(cryst, idir, ipert, symq, ngfft, cplex, nfft, nspden, nsppol ,mpi_enreg, v1r) 2688 2689 !Arguments ------------------------------------ 2690 !scalars 2691 integer,intent(in) :: idir, ipert, cplex, nfft, nspden, nsppol 2692 type(crystal_t),intent(in) :: cryst 2693 type(MPI_type),intent(in) :: mpi_enreg 2694 !arrays 2695 integer,intent(in) :: symq(4,2,cryst%nsym),ngfft(18) 2696 real(dp),intent(inout) :: v1r(cplex*nfft,nspden) 2697 2698 !Local variables------------------------------- 2699 integer,parameter :: syuse0 = 0, rfmeth2 = 2, iscf1 = 1 2700 integer :: nsym1, nfftot 2701 !arrays 2702 integer :: symafm1(cryst%nsym),symrel1(3,3,cryst%nsym),symrc1(3,3,cryst%nsym) 2703 integer,allocatable :: irrzon1(:,:,:),indsy1(:,:,:) 2704 real(dp) :: tnons1(3,cryst%nsym) 2705 real(dp),allocatable :: phnons1(:,:,:),v1g(:,:) 2706 2707 ! ************************************************************************* 2708 2709 if (cryst%nsym == 1) return 2710 2711 nfftot = product(ngfft(1:3)) 2712 ABI_CHECK(nfft == nfftot, "MPI-FFT not coded") 2713 2714 ! Symmetrize (copied from dfpt_looppert) 2715 ! Determines the set of symmetries that leaves the perturbation invariant. 2716 call littlegroup_pert(cryst%gprimd,idir,cryst%indsym,dev_null,ipert,cryst%natom,cryst%nsym,nsym1,rfmeth2,& 2717 cryst%symafm,symafm1,symq,cryst%symrec,cryst%symrel,symrel1,syuse0,cryst%tnons,tnons1,unit=dev_null) 2718 2719 ! Set up corresponding symmetry data 2720 ABI_MALLOC(irrzon1, (nfft**(1-1/nsym1),2,(nspden/nsppol)-3*(nspden/4))) 2721 ABI_MALLOC(phnons1, (2,nfft**(1-1/nsym1),(nspden/nsppol)-3*(nspden/4))) 2722 ABI_MALLOC(indsy1,(4,nsym1,cryst%natom)) 2723 2724 call setsym(indsy1,irrzon1,iscf1,cryst%natom,nfft,ngfft,nspden,nsppol,& 2725 nsym1,phnons1,symafm1,symrc1,symrel1,tnons1,cryst%typat,cryst%xred) 2726 2727 !if (psps%usepaw==1) then 2728 ! ! Allocate/initialize only zarot in pawang1 datastructure 2729 ! call pawang_init(pawang1,0,0,pawang%l_max-1,0,0,nsym1,0,0,0,0) 2730 ! call setsym_ylm(gprimd,pawang1%l_max-1,pawang1%nsym,0,rprimd,symrc1,pawang1%zarot) 2731 !end if 2732 2733 ! FIXME Be careful here because symrhg was written for densities! 2734 ABI_CHECK(nsppol == 1 .and. nspden == 1, "symrhg was written for densities, not for potentials") 2735 2736 ABI_MALLOC(v1g, (2,nfft)) 2737 call symrhg(cplex,cryst%gprimd,irrzon1,mpi_enreg,nfft,nfftot,ngfft,nspden,nsppol,nsym1,& 2738 phnons1,v1g,v1r,cryst%rprimd,symafm1,symrel1,tnons1) 2739 2740 ABI_FREE(irrzon1) 2741 ABI_FREE(phnons1) 2742 ABI_FREE(indsy1) 2743 ABI_FREE(v1g) 2744 2745 end subroutine v1phq_symmetrize